]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/nilfs2/ioctl.c
nilfs2: avoid double error caused by nilfs_transaction_end
[linux-2.6-omap-h63xx.git] / fs / nilfs2 / ioctl.c
index 35ba60ea9617b651ade0f8968439ebf0ad2393df..5ce06a01c7ec6972ac2087ceba612e0a907169c0 100644 (file)
@@ -34,9 +34,6 @@
 #include "dat.h"
 
 
-#define KMALLOC_SIZE_MIN       4096    /* 4KB */
-#define KMALLOC_SIZE_MAX       131072  /* 128 KB */
-
 static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
                                 struct nilfs_argv *argv, int dir,
                                 ssize_t (*dofunc)(struct the_nilfs *,
@@ -44,21 +41,20 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
                                                   void *, size_t, size_t))
 {
        void *buf;
-       size_t ksize, maxmembs, total, n;
+       size_t maxmembs, total, n;
        ssize_t nr;
        int ret, i;
 
        if (argv->v_nmembs == 0)
                return 0;
 
-       for (ksize = KMALLOC_SIZE_MAX; ksize >= KMALLOC_SIZE_MIN; ksize /= 2) {
-               buf = kmalloc(ksize, GFP_NOFS);
-               if (buf != NULL)
-                       break;
-       }
-       if (ksize < KMALLOC_SIZE_MIN)
+       if (argv->v_size > PAGE_SIZE)
+               return -EINVAL;
+
+       buf = (void *)__get_free_pages(GFP_NOFS, 0);
+       if (unlikely(!buf))
                return -ENOMEM;
-       maxmembs = ksize / argv->v_size;
+       maxmembs = PAGE_SIZE / argv->v_size;
 
        ret = 0;
        total = 0;
@@ -89,7 +85,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
        }
        argv->v_nmembs = total;
 
-       kfree(buf);
+       free_pages((unsigned long)buf, 0);
        return ret;
 }
 
@@ -109,7 +105,11 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
        nilfs_transaction_begin(inode->i_sb, &ti, 0);
        ret = nilfs_cpfile_change_cpmode(
                cpfile, cpmode.cm_cno, cpmode.cm_mode);
-       nilfs_transaction_end(inode->i_sb, !ret);
+       if (unlikely(ret < 0)) {
+               nilfs_transaction_abort(inode->i_sb);
+               return ret;
+       }
+       nilfs_transaction_commit(inode->i_sb); /* never fails */
        return ret;
 }
 
@@ -129,7 +129,11 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
 
        nilfs_transaction_begin(inode->i_sb, &ti, 0);
        ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
-       nilfs_transaction_end(inode->i_sb, !ret);
+       if (unlikely(ret < 0)) {
+               nilfs_transaction_abort(inode->i_sb);
+               return ret;
+       }
+       nilfs_transaction_commit(inode->i_sb); /* never fails */
        return ret;
 }
 
@@ -146,16 +150,17 @@ static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp,
 {
        struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
        struct nilfs_argv argv;
-       struct nilfs_transaction_info ti;
        int ret;
 
        if (copy_from_user(&argv, argp, sizeof(argv)))
                return -EFAULT;
 
-       nilfs_transaction_begin(inode->i_sb, &ti, 0);
+       down_read(&nilfs->ns_segctor_sem);
        ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
                                    nilfs_ioctl_do_get_cpinfo);
-       nilfs_transaction_end(inode->i_sb, 0);
+       up_read(&nilfs->ns_segctor_sem);
+       if (ret < 0)
+               return ret;
 
        if (copy_to_user(argp, &argv, sizeof(argv)))
                ret = -EFAULT;
@@ -165,14 +170,13 @@ static int nilfs_ioctl_get_cpinfo(struct inode *inode, struct file *filp,
 static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
                                  unsigned int cmd, void __user *argp)
 {
-       struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
+       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
        struct nilfs_cpstat cpstat;
-       struct nilfs_transaction_info ti;
        int ret;
 
-       nilfs_transaction_begin(inode->i_sb, &ti, 0);
-       ret = nilfs_cpfile_get_stat(cpfile, &cpstat);
-       nilfs_transaction_end(inode->i_sb, 0);
+       down_read(&nilfs->ns_segctor_sem);
+       ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
+       up_read(&nilfs->ns_segctor_sem);
        if (ret < 0)
                return ret;
 
@@ -193,16 +197,17 @@ static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp,
 {
        struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
        struct nilfs_argv argv;
-       struct nilfs_transaction_info ti;
        int ret;
 
        if (copy_from_user(&argv, argp, sizeof(argv)))
                return -EFAULT;
 
-       nilfs_transaction_begin(inode->i_sb, &ti, 0);
+       down_read(&nilfs->ns_segctor_sem);
        ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
                                    nilfs_ioctl_do_get_suinfo);
-       nilfs_transaction_end(inode->i_sb, 0);
+       up_read(&nilfs->ns_segctor_sem);
+       if (ret < 0)
+               return ret;
 
        if (copy_to_user(argp, &argv, sizeof(argv)))
                ret = -EFAULT;
@@ -212,14 +217,13 @@ static int nilfs_ioctl_get_suinfo(struct inode *inode, struct file *filp,
 static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
                                  unsigned int cmd, void __user *argp)
 {
-       struct inode *sufile = NILFS_SB(inode->i_sb)->s_nilfs->ns_sufile;
+       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
        struct nilfs_sustat sustat;
-       struct nilfs_transaction_info ti;
        int ret;
 
-       nilfs_transaction_begin(inode->i_sb, &ti, 0);
-       ret = nilfs_sufile_get_stat(sufile, &sustat);
-       nilfs_transaction_end(inode->i_sb, 0);
+       down_read(&nilfs->ns_segctor_sem);
+       ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
+       up_read(&nilfs->ns_segctor_sem);
        if (ret < 0)
                return ret;
 
@@ -240,16 +244,17 @@ static int nilfs_ioctl_get_vinfo(struct inode *inode, struct file *filp,
 {
        struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
        struct nilfs_argv argv;
-       struct nilfs_transaction_info ti;
        int ret;
 
        if (copy_from_user(&argv, argp, sizeof(argv)))
                return -EFAULT;
 
-       nilfs_transaction_begin(inode->i_sb, &ti, 0);
+       down_read(&nilfs->ns_segctor_sem);
        ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
                                    nilfs_ioctl_do_get_vinfo);
-       nilfs_transaction_end(inode->i_sb, 0);
+       up_read(&nilfs->ns_segctor_sem);
+       if (ret < 0)
+               return ret;
 
        if (copy_to_user(argp, &argv, sizeof(argv)))
                ret = -EFAULT;
@@ -284,16 +289,17 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
 {
        struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
        struct nilfs_argv argv;
-       struct nilfs_transaction_info ti;
        int ret;
 
        if (copy_from_user(&argv, argp, sizeof(argv)))
                return -EFAULT;
 
-       nilfs_transaction_begin(inode->i_sb, &ti, 0);
+       down_read(&nilfs->ns_segctor_sem);
        ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
                                    nilfs_ioctl_do_get_bdescs);
-       nilfs_transaction_end(inode->i_sb, 0);
+       up_read(&nilfs->ns_segctor_sem);
+       if (ret < 0)
+               return ret;
 
        if (copy_to_user(argp, &argv, sizeof(argv)))
                ret = -EFAULT;