Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Dec 2014 17:41:32 +0000 (09:41 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Dec 2014 17:41:32 +0000 (09:41 -0800)
Pull fuse update from Miklos Szeredi:
 "The first part makes sure we don't hold up umount with pending async
  requests.  In addition to being a cleanup, this is a small behavioral
  change (for the better) and unlikely to break anything.

  The second part prepares for a cleanup of the fuse device I/O code by
  adding a helper for simple request submission, with some savings in
  line numbers already realized"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
  fuse: use file_inode() in fuse_file_fallocate()
  fuse: introduce fuse_simple_request() helper
  fuse: reduce max out args
  fuse: hold inode instead of path after release
  fuse: flush requests on umount
  fuse: don't wake up reserved req in fuse_conn_kill()

fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index 966ace8b243fa39796fbdd788c4d83ebd6024217..28d0c7abba1c2fa7748d3b1c2874b855427b3897 100644 (file)
@@ -415,7 +415,7 @@ err_unlock:
 err_region:
        unregister_chrdev_region(devt, 1);
 err:
-       fuse_conn_kill(fc);
+       fuse_abort_conn(fc);
        goto out;
 }
 
index ca887314aba9deb6d59811f0d19b8c9b9a0381c3..ba1107977f2ecafa96cafc04f6498b3fb79a3145 100644 (file)
@@ -511,6 +511,35 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
 }
 EXPORT_SYMBOL_GPL(fuse_request_send);
 
+ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args)
+{
+       struct fuse_req *req;
+       ssize_t ret;
+
+       req = fuse_get_req(fc, 0);
+       if (IS_ERR(req))
+               return PTR_ERR(req);
+
+       req->in.h.opcode = args->in.h.opcode;
+       req->in.h.nodeid = args->in.h.nodeid;
+       req->in.numargs = args->in.numargs;
+       memcpy(req->in.args, args->in.args,
+              args->in.numargs * sizeof(struct fuse_in_arg));
+       req->out.argvar = args->out.argvar;
+       req->out.numargs = args->out.numargs;
+       memcpy(req->out.args, args->out.args,
+              args->out.numargs * sizeof(struct fuse_arg));
+       fuse_request_send(fc, req);
+       ret = req->out.h.error;
+       if (!ret && args->out.argvar) {
+               BUG_ON(args->out.numargs != 1);
+               ret = req->out.args[0].size;
+       }
+       fuse_put_request(fc, req);
+
+       return ret;
+}
+
 static void fuse_request_send_nowait_locked(struct fuse_conn *fc,
                                            struct fuse_req *req)
 {
index df562cc87763692fac081068fa40114d69cd8164..252b8a5de8b57f71b841d1fc64c9f48e78b641c2 100644 (file)
@@ -145,22 +145,22 @@ static void fuse_invalidate_entry(struct dentry *entry)
        fuse_invalidate_entry_cache(entry);
 }
 
-static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req,
+static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
                             u64 nodeid, struct qstr *name,
                             struct fuse_entry_out *outarg)
 {
        memset(outarg, 0, sizeof(struct fuse_entry_out));
-       req->in.h.opcode = FUSE_LOOKUP;
-       req->in.h.nodeid = nodeid;
-       req->in.numargs = 1;
-       req->in.args[0].size = name->len + 1;
-       req->in.args[0].value = name->name;
-       req->out.numargs = 1;
+       args->in.h.opcode = FUSE_LOOKUP;
+       args->in.h.nodeid = nodeid;
+       args->in.numargs = 1;
+       args->in.args[0].size = name->len + 1;
+       args->in.args[0].value = name->name;
+       args->out.numargs = 1;
        if (fc->minor < 9)
-               req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
+               args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
        else
-               req->out.args[0].size = sizeof(struct fuse_entry_out);
-       req->out.args[0].value = outarg;
+               args->out.args[0].size = sizeof(struct fuse_entry_out);
+       args->out.args[0].value = outarg;
 }
 
 u64 fuse_get_attr_version(struct fuse_conn *fc)
@@ -200,9 +200,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                goto invalid;
        else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
                 (flags & LOOKUP_REVAL)) {
-               int err;
                struct fuse_entry_out outarg;
-               struct fuse_req *req;
+               FUSE_ARGS(args);
                struct fuse_forget_link *forget;
                u64 attr_version;
 
@@ -215,31 +214,23 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                        goto out;
 
                fc = get_fuse_conn(inode);
-               req = fuse_get_req_nopages(fc);
-               ret = PTR_ERR(req);
-               if (IS_ERR(req))
-                       goto out;
 
                forget = fuse_alloc_forget();
-               if (!forget) {
-                       fuse_put_request(fc, req);
-                       ret = -ENOMEM;
+               ret = -ENOMEM;
+               if (!forget)
                        goto out;
-               }
 
                attr_version = fuse_get_attr_version(fc);
 
                parent = dget_parent(entry);
-               fuse_lookup_init(fc, req, get_node_id(parent->d_inode),
+               fuse_lookup_init(fc, &args, get_node_id(parent->d_inode),
                                 &entry->d_name, &outarg);
-               fuse_request_send(fc, req);
+               ret = fuse_simple_request(fc, &args);
                dput(parent);
-               err = req->out.h.error;
-               fuse_put_request(fc, req);
                /* Zero nodeid is same as -ENOENT */
-               if (!err && !outarg.nodeid)
-                       err = -ENOENT;
-               if (!err) {
+               if (!ret && !outarg.nodeid)
+                       ret = -ENOENT;
+               if (!ret) {
                        fi = get_fuse_inode(inode);
                        if (outarg.nodeid != get_node_id(inode)) {
                                fuse_queue_forget(fc, forget, outarg.nodeid, 1);
@@ -250,7 +241,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                        spin_unlock(&fc->lock);
                }
                kfree(forget);
-               if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
+               if (ret == -ENOMEM)
+                       goto out;
+               if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
                        goto invalid;
 
                fuse_change_attributes(inode, &outarg.attr,
@@ -296,7 +289,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
                     struct fuse_entry_out *outarg, struct inode **inode)
 {
        struct fuse_conn *fc = get_fuse_conn_super(sb);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_forget_link *forget;
        u64 attr_version;
        int err;
@@ -306,24 +299,16 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
        if (name->len > FUSE_NAME_MAX)
                goto out;
 
-       req = fuse_get_req_nopages(fc);
-       err = PTR_ERR(req);
-       if (IS_ERR(req))
-               goto out;
 
        forget = fuse_alloc_forget();
        err = -ENOMEM;
-       if (!forget) {
-               fuse_put_request(fc, req);
+       if (!forget)
                goto out;
-       }
 
        attr_version = fuse_get_attr_version(fc);
 
-       fuse_lookup_init(fc, req, nodeid, name, outarg);
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       fuse_lookup_init(fc, &args, nodeid, name, outarg);
+       err = fuse_simple_request(fc, &args);
        /* Zero nodeid is same as -ENOENT, but with valid timeout */
        if (err || !outarg->nodeid)
                goto out_put_forget;
@@ -405,7 +390,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        int err;
        struct inode *inode;
        struct fuse_conn *fc = get_fuse_conn(dir);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_forget_link *forget;
        struct fuse_create_in inarg;
        struct fuse_open_out outopen;
@@ -420,15 +405,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        if (!forget)
                goto out_err;
 
-       req = fuse_get_req_nopages(fc);
-       err = PTR_ERR(req);
-       if (IS_ERR(req))
-               goto out_put_forget_req;
-
        err = -ENOMEM;
        ff = fuse_file_alloc(fc);
        if (!ff)
-               goto out_put_request;
+               goto out_put_forget_req;
 
        if (!fc->dont_mask)
                mode &= ~current_umask();
@@ -439,24 +419,23 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        inarg.flags = flags;
        inarg.mode = mode;
        inarg.umask = current_umask();
-       req->in.h.opcode = FUSE_CREATE;
-       req->in.h.nodeid = get_node_id(dir);
-       req->in.numargs = 2;
-       req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
+       args.in.h.opcode = FUSE_CREATE;
+       args.in.h.nodeid = get_node_id(dir);
+       args.in.numargs = 2;
+       args.in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
                                                sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = entry->d_name.len + 1;
-       req->in.args[1].value = entry->d_name.name;
-       req->out.numargs = 2;
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = entry->d_name.len + 1;
+       args.in.args[1].value = entry->d_name.name;
+       args.out.numargs = 2;
        if (fc->minor < 9)
-               req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
+               args.out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
        else
-               req->out.args[0].size = sizeof(outentry);
-       req->out.args[0].value = &outentry;
-       req->out.args[1].size = sizeof(outopen);
-       req->out.args[1].value = &outopen;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
+               args.out.args[0].size = sizeof(outentry);
+       args.out.args[0].value = &outentry;
+       args.out.args[1].size = sizeof(outopen);
+       args.out.args[1].value = &outopen;
+       err = fuse_simple_request(fc, &args);
        if (err)
                goto out_free_ff;
 
@@ -464,7 +443,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
                goto out_free_ff;
 
-       fuse_put_request(fc, req);
        ff->fh = outopen.fh;
        ff->nodeid = outentry.nodeid;
        ff->open_flags = outopen.open_flags;
@@ -492,8 +470,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
 
 out_free_ff:
        fuse_file_free(ff);
-out_put_request:
-       fuse_put_request(fc, req);
 out_put_forget_req:
        kfree(forget);
 out_err:
@@ -547,7 +523,7 @@ no_open:
 /*
  * Code shared between mknod, mkdir, symlink and link
  */
-static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
+static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
                            struct inode *dir, struct dentry *entry,
                            umode_t mode)
 {
@@ -557,22 +533,18 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
        struct fuse_forget_link *forget;
 
        forget = fuse_alloc_forget();
-       if (!forget) {
-               fuse_put_request(fc, req);
+       if (!forget)
                return -ENOMEM;
-       }
 
        memset(&outarg, 0, sizeof(outarg));
-       req->in.h.nodeid = get_node_id(dir);
-       req->out.numargs = 1;
+       args->in.h.nodeid = get_node_id(dir);
+       args->out.numargs = 1;
        if (fc->minor < 9)
-               req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
+               args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
        else
-               req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+               args->out.args[0].size = sizeof(outarg);
+       args->out.args[0].value = &outarg;
+       err = fuse_simple_request(fc, args);
        if (err)
                goto out_put_forget_req;
 
@@ -609,9 +581,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
 {
        struct fuse_mknod_in inarg;
        struct fuse_conn *fc = get_fuse_conn(dir);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       FUSE_ARGS(args);
 
        if (!fc->dont_mask)
                mode &= ~current_umask();
@@ -620,14 +590,14 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
        inarg.mode = mode;
        inarg.rdev = new_encode_dev(rdev);
        inarg.umask = current_umask();
-       req->in.h.opcode = FUSE_MKNOD;
-       req->in.numargs = 2;
-       req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
+       args.in.h.opcode = FUSE_MKNOD;
+       args.in.numargs = 2;
+       args.in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
                                                sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = entry->d_name.len + 1;
-       req->in.args[1].value = entry->d_name.name;
-       return create_new_entry(fc, req, dir, entry, mode);
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = entry->d_name.len + 1;
+       args.in.args[1].value = entry->d_name.name;
+       return create_new_entry(fc, &args, dir, entry, mode);
 }
 
 static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
@@ -640,9 +610,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
 {
        struct fuse_mkdir_in inarg;
        struct fuse_conn *fc = get_fuse_conn(dir);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       FUSE_ARGS(args);
 
        if (!fc->dont_mask)
                mode &= ~current_umask();
@@ -650,13 +618,13 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
        memset(&inarg, 0, sizeof(inarg));
        inarg.mode = mode;
        inarg.umask = current_umask();
-       req->in.h.opcode = FUSE_MKDIR;
-       req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = entry->d_name.len + 1;
-       req->in.args[1].value = entry->d_name.name;
-       return create_new_entry(fc, req, dir, entry, S_IFDIR);
+       args.in.h.opcode = FUSE_MKDIR;
+       args.in.numargs = 2;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = entry->d_name.len + 1;
+       args.in.args[1].value = entry->d_name.name;
+       return create_new_entry(fc, &args, dir, entry, S_IFDIR);
 }
 
 static int fuse_symlink(struct inode *dir, struct dentry *entry,
@@ -664,17 +632,15 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
 {
        struct fuse_conn *fc = get_fuse_conn(dir);
        unsigned len = strlen(link) + 1;
-       struct fuse_req *req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       FUSE_ARGS(args);
 
-       req->in.h.opcode = FUSE_SYMLINK;
-       req->in.numargs = 2;
-       req->in.args[0].size = entry->d_name.len + 1;
-       req->in.args[0].value = entry->d_name.name;
-       req->in.args[1].size = len;
-       req->in.args[1].value = link;
-       return create_new_entry(fc, req, dir, entry, S_IFLNK);
+       args.in.h.opcode = FUSE_SYMLINK;
+       args.in.numargs = 2;
+       args.in.args[0].size = entry->d_name.len + 1;
+       args.in.args[0].value = entry->d_name.name;
+       args.in.args[1].size = len;
+       args.in.args[1].value = link;
+       return create_new_entry(fc, &args, dir, entry, S_IFLNK);
 }
 
 static inline void fuse_update_ctime(struct inode *inode)
@@ -689,18 +655,14 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
 {
        int err;
        struct fuse_conn *fc = get_fuse_conn(dir);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       req->in.h.opcode = FUSE_UNLINK;
-       req->in.h.nodeid = get_node_id(dir);
-       req->in.numargs = 1;
-       req->in.args[0].size = entry->d_name.len + 1;
-       req->in.args[0].value = entry->d_name.name;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       FUSE_ARGS(args);
+
+       args.in.h.opcode = FUSE_UNLINK;
+       args.in.h.nodeid = get_node_id(dir);
+       args.in.numargs = 1;
+       args.in.args[0].size = entry->d_name.len + 1;
+       args.in.args[0].value = entry->d_name.name;
+       err = fuse_simple_request(fc, &args);
        if (!err) {
                struct inode *inode = entry->d_inode;
                struct fuse_inode *fi = get_fuse_inode(inode);
@@ -729,18 +691,14 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
 {
        int err;
        struct fuse_conn *fc = get_fuse_conn(dir);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       req->in.h.opcode = FUSE_RMDIR;
-       req->in.h.nodeid = get_node_id(dir);
-       req->in.numargs = 1;
-       req->in.args[0].size = entry->d_name.len + 1;
-       req->in.args[0].value = entry->d_name.name;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       FUSE_ARGS(args);
+
+       args.in.h.opcode = FUSE_RMDIR;
+       args.in.h.nodeid = get_node_id(dir);
+       args.in.numargs = 1;
+       args.in.args[0].size = entry->d_name.len + 1;
+       args.in.args[0].value = entry->d_name.name;
+       err = fuse_simple_request(fc, &args);
        if (!err) {
                clear_nlink(entry->d_inode);
                fuse_invalidate_attr(dir);
@@ -757,27 +715,21 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
        int err;
        struct fuse_rename2_in inarg;
        struct fuse_conn *fc = get_fuse_conn(olddir);
-       struct fuse_req *req;
-
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       FUSE_ARGS(args);
 
        memset(&inarg, 0, argsize);
        inarg.newdir = get_node_id(newdir);
        inarg.flags = flags;
-       req->in.h.opcode = opcode;
-       req->in.h.nodeid = get_node_id(olddir);
-       req->in.numargs = 3;
-       req->in.args[0].size = argsize;
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = oldent->d_name.len + 1;
-       req->in.args[1].value = oldent->d_name.name;
-       req->in.args[2].size = newent->d_name.len + 1;
-       req->in.args[2].value = newent->d_name.name;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = opcode;
+       args.in.h.nodeid = get_node_id(olddir);
+       args.in.numargs = 3;
+       args.in.args[0].size = argsize;
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = oldent->d_name.len + 1;
+       args.in.args[1].value = oldent->d_name.name;
+       args.in.args[2].size = newent->d_name.len + 1;
+       args.in.args[2].value = newent->d_name.name;
+       err = fuse_simple_request(fc, &args);
        if (!err) {
                /* ctime changes */
                fuse_invalidate_attr(oldent->d_inode);
@@ -849,19 +801,17 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
        struct fuse_link_in inarg;
        struct inode *inode = entry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       FUSE_ARGS(args);
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.oldnodeid = get_node_id(inode);
-       req->in.h.opcode = FUSE_LINK;
-       req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = newent->d_name.len + 1;
-       req->in.args[1].value = newent->d_name.name;
-       err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
+       args.in.h.opcode = FUSE_LINK;
+       args.in.numargs = 2;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = newent->d_name.len + 1;
+       args.in.args[1].value = newent->d_name.name;
+       err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
        /* Contrary to "normal" filesystems it can happen that link
           makes two "logical" inodes point to the same "physical"
           inode.  We invalidate the attributes of the old one, so it
@@ -929,13 +879,9 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
        struct fuse_getattr_in inarg;
        struct fuse_attr_out outarg;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        u64 attr_version;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        attr_version = fuse_get_attr_version(fc);
 
        memset(&inarg, 0, sizeof(inarg));
@@ -947,20 +893,18 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
                inarg.getattr_flags |= FUSE_GETATTR_FH;
                inarg.fh = ff->fh;
        }
-       req->in.h.opcode = FUSE_GETATTR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->out.numargs = 1;
+       args.in.h.opcode = FUSE_GETATTR;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.out.numargs = 1;
        if (fc->minor < 9)
-               req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
+               args.out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
        else
-               req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+               args.out.args[0].size = sizeof(outarg);
+       args.out.args[0].value = &outarg;
+       err = fuse_simple_request(fc, &args);
        if (!err) {
                if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
                        make_bad_inode(inode);
@@ -1102,7 +1046,7 @@ int fuse_allow_current_process(struct fuse_conn *fc)
 static int fuse_access(struct inode *inode, int mask)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_access_in inarg;
        int err;
 
@@ -1111,20 +1055,14 @@ static int fuse_access(struct inode *inode, int mask)
        if (fc->no_access)
                return 0;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        memset(&inarg, 0, sizeof(inarg));
        inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
-       req->in.h.opcode = FUSE_ACCESS;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = FUSE_ACCESS;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       err = fuse_simple_request(fc, &args);
        if (err == -ENOSYS) {
                fc->no_access = 1;
                err = 0;
@@ -1445,31 +1383,27 @@ static char *read_link(struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req = fuse_get_req_nopages(fc);
+       FUSE_ARGS(args);
        char *link;
-
-       if (IS_ERR(req))
-               return ERR_CAST(req);
+       ssize_t ret;
 
        link = (char *) __get_free_page(GFP_KERNEL);
-       if (!link) {
-               link = ERR_PTR(-ENOMEM);
-               goto out;
-       }
-       req->in.h.opcode = FUSE_READLINK;
-       req->in.h.nodeid = get_node_id(inode);
-       req->out.argvar = 1;
-       req->out.numargs = 1;
-       req->out.args[0].size = PAGE_SIZE - 1;
-       req->out.args[0].value = link;
-       fuse_request_send(fc, req);
-       if (req->out.h.error) {
+       if (!link)
+               return ERR_PTR(-ENOMEM);
+
+       args.in.h.opcode = FUSE_READLINK;
+       args.in.h.nodeid = get_node_id(inode);
+       args.out.argvar = 1;
+       args.out.numargs = 1;
+       args.out.args[0].size = PAGE_SIZE - 1;
+       args.out.args[0].value = link;
+       ret = fuse_simple_request(fc, &args);
+       if (ret < 0) {
                free_page((unsigned long) link);
-               link = ERR_PTR(req->out.h.error);
-       } else
-               link[req->out.args[0].size] = '\0';
- out:
-       fuse_put_request(fc, req);
+               link = ERR_PTR(ret);
+       } else {
+               link[ret] = '\0';
+       }
        fuse_invalidate_atime(inode);
        return link;
 }
@@ -1629,22 +1563,22 @@ void fuse_release_nowrite(struct inode *inode)
        spin_unlock(&fc->lock);
 }
 
-static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
+static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
                              struct inode *inode,
                              struct fuse_setattr_in *inarg_p,
                              struct fuse_attr_out *outarg_p)
 {
-       req->in.h.opcode = FUSE_SETATTR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(*inarg_p);
-       req->in.args[0].value = inarg_p;
-       req->out.numargs = 1;
+       args->in.h.opcode = FUSE_SETATTR;
+       args->in.h.nodeid = get_node_id(inode);
+       args->in.numargs = 1;
+       args->in.args[0].size = sizeof(*inarg_p);
+       args->in.args[0].value = inarg_p;
+       args->out.numargs = 1;
        if (fc->minor < 9)
-               req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
+               args->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
        else
-               req->out.args[0].size = sizeof(*outarg_p);
-       req->out.args[0].value = outarg_p;
+               args->out.args[0].size = sizeof(*outarg_p);
+       args->out.args[0].value = outarg_p;
 }
 
 /*
@@ -1653,14 +1587,9 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
 int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_setattr_in inarg;
        struct fuse_attr_out outarg;
-       int err;
-
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
 
        memset(&inarg, 0, sizeof(inarg));
        memset(&outarg, 0, sizeof(outarg));
@@ -1677,12 +1606,9 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
                inarg.valid |= FATTR_FH;
                inarg.fh = ff->fh;
        }
-       fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
 
-       return err;
+       return fuse_simple_request(fc, &args);
 }
 
 /*
@@ -1698,7 +1624,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_setattr_in inarg;
        struct fuse_attr_out outarg;
        bool is_truncate = false;
@@ -1723,10 +1649,6 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
        if (attr->ia_valid & ATTR_SIZE)
                is_truncate = true;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        if (is_truncate) {
                fuse_set_nowrite(inode);
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
@@ -1747,10 +1669,8 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
                inarg.valid |= FATTR_LOCKOWNER;
                inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
        }
-       fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
+       err = fuse_simple_request(fc, &args);
        if (err) {
                if (err == -EINTR)
                        fuse_invalidate_attr(inode);
@@ -1837,32 +1757,26 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
 {
        struct inode *inode = entry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_setxattr_in inarg;
        int err;
 
        if (fc->no_setxattr)
                return -EOPNOTSUPP;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
        inarg.flags = flags;
-       req->in.h.opcode = FUSE_SETXATTR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 3;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = strlen(name) + 1;
-       req->in.args[1].value = name;
-       req->in.args[2].size = size;
-       req->in.args[2].value = value;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = FUSE_SETXATTR;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 3;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = strlen(name) + 1;
+       args.in.args[1].value = name;
+       args.in.args[2].size = size;
+       args.in.args[2].value = value;
+       err = fuse_simple_request(fc, &args);
        if (err == -ENOSYS) {
                fc->no_setxattr = 1;
                err = -EOPNOTSUPP;
@@ -1879,7 +1793,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
 {
        struct inode *inode = entry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_getxattr_in inarg;
        struct fuse_getxattr_out outarg;
        ssize_t ret;
@@ -1887,40 +1801,32 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
        if (fc->no_getxattr)
                return -EOPNOTSUPP;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
-       req->in.h.opcode = FUSE_GETXATTR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = strlen(name) + 1;
-       req->in.args[1].value = name;
+       args.in.h.opcode = FUSE_GETXATTR;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 2;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.in.args[1].size = strlen(name) + 1;
+       args.in.args[1].value = name;
        /* This is really two different operations rolled into one */
-       req->out.numargs = 1;
+       args.out.numargs = 1;
        if (size) {
-               req->out.argvar = 1;
-               req->out.args[0].size = size;
-               req->out.args[0].value = value;
+               args.out.argvar = 1;
+               args.out.args[0].size = size;
+               args.out.args[0].value = value;
        } else {
-               req->out.args[0].size = sizeof(outarg);
-               req->out.args[0].value = &outarg;
+               args.out.args[0].size = sizeof(outarg);
+               args.out.args[0].value = &outarg;
        }
-       fuse_request_send(fc, req);
-       ret = req->out.h.error;
-       if (!ret)
-               ret = size ? req->out.args[0].size : outarg.size;
-       else {
-               if (ret == -ENOSYS) {
-                       fc->no_getxattr = 1;
-                       ret = -EOPNOTSUPP;
-               }
+       ret = fuse_simple_request(fc, &args);
+       if (!ret && !size)
+               ret = outarg.size;
+       if (ret == -ENOSYS) {
+               fc->no_getxattr = 1;
+               ret = -EOPNOTSUPP;
        }
-       fuse_put_request(fc, req);
        return ret;
 }
 
@@ -1928,7 +1834,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 {
        struct inode *inode = entry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_getxattr_in inarg;
        struct fuse_getxattr_out outarg;
        ssize_t ret;
@@ -1939,38 +1845,30 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
        if (fc->no_listxattr)
                return -EOPNOTSUPP;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
-       req->in.h.opcode = FUSE_LISTXATTR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
+       args.in.h.opcode = FUSE_LISTXATTR;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
        /* This is really two different operations rolled into one */
-       req->out.numargs = 1;
+       args.out.numargs = 1;
        if (size) {
-               req->out.argvar = 1;
-               req->out.args[0].size = size;
-               req->out.args[0].value = list;
+               args.out.argvar = 1;
+               args.out.args[0].size = size;
+               args.out.args[0].value = list;
        } else {
-               req->out.args[0].size = sizeof(outarg);
-               req->out.args[0].value = &outarg;
+               args.out.args[0].size = sizeof(outarg);
+               args.out.args[0].value = &outarg;
        }
-       fuse_request_send(fc, req);
-       ret = req->out.h.error;
-       if (!ret)
-               ret = size ? req->out.args[0].size : outarg.size;
-       else {
-               if (ret == -ENOSYS) {
-                       fc->no_listxattr = 1;
-                       ret = -EOPNOTSUPP;
-               }
+       ret = fuse_simple_request(fc, &args);
+       if (!ret && !size)
+               ret = outarg.size;
+       if (ret == -ENOSYS) {
+               fc->no_listxattr = 1;
+               ret = -EOPNOTSUPP;
        }
-       fuse_put_request(fc, req);
        return ret;
 }
 
@@ -1978,24 +1876,18 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
 {
        struct inode *inode = entry->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        int err;
 
        if (fc->no_removexattr)
                return -EOPNOTSUPP;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       req->in.h.opcode = FUSE_REMOVEXATTR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = strlen(name) + 1;
-       req->in.args[0].value = name;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = FUSE_REMOVEXATTR;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = strlen(name) + 1;
+       args.in.args[0].value = name;
+       err = fuse_simple_request(fc, &args);
        if (err == -ENOSYS) {
                fc->no_removexattr = 1;
                err = -EOPNOTSUPP;
index bf50259012ab7921ecaa7033b9260a9405f577f5..760b2c55219741a48e0e444d482cb9e08535f938 100644 (file)
@@ -24,30 +24,22 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
                          int opcode, struct fuse_open_out *outargp)
 {
        struct fuse_open_in inarg;
-       struct fuse_req *req;
-       int err;
-
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       FUSE_ARGS(args);
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
        if (!fc->atomic_o_trunc)
                inarg.flags &= ~O_TRUNC;
-       req->in.h.opcode = opcode;
-       req->in.h.nodeid = nodeid;
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(*outargp);
-       req->out.args[0].value = outargp;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = opcode;
+       args.in.h.nodeid = nodeid;
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.out.numargs = 1;
+       args.out.args[0].size = sizeof(*outargp);
+       args.out.args[0].value = outargp;
 
-       return err;
+       return fuse_simple_request(fc, &args);
 }
 
 struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
@@ -89,37 +81,9 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff)
        return ff;
 }
 
-static void fuse_release_async(struct work_struct *work)
-{
-       struct fuse_req *req;
-       struct fuse_conn *fc;
-       struct path path;
-
-       req = container_of(work, struct fuse_req, misc.release.work);
-       path = req->misc.release.path;
-       fc = get_fuse_conn(path.dentry->d_inode);
-
-       fuse_put_request(fc, req);
-       path_put(&path);
-}
-
 static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
 {
-       if (fc->destroy_req) {
-               /*
-                * If this is a fuseblk mount, then it's possible that
-                * releasing the path will result in releasing the
-                * super block and sending the DESTROY request.  If
-                * the server is single threaded, this would hang.
-                * For this reason do the path_put() in a separate
-                * thread.
-                */
-               atomic_inc(&req->count);
-               INIT_WORK(&req->misc.release.work, fuse_release_async);
-               schedule_work(&req->misc.release.work);
-       } else {
-               path_put(&req->misc.release.path);
-       }
+       iput(req->misc.release.inode);
 }
 
 static void fuse_file_put(struct fuse_file *ff, bool sync)
@@ -133,12 +97,12 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
                         * implement 'open'
                         */
                        req->background = 0;
-                       path_put(&req->misc.release.path);
+                       iput(req->misc.release.inode);
                        fuse_put_request(ff->fc, req);
                } else if (sync) {
                        req->background = 0;
                        fuse_request_send(ff->fc, req);
-                       path_put(&req->misc.release.path);
+                       iput(req->misc.release.inode);
                        fuse_put_request(ff->fc, req);
                } else {
                        req->end = fuse_release_end;
@@ -297,9 +261,8 @@ void fuse_release_common(struct file *file, int opcode)
                inarg->lock_owner = fuse_lock_owner_id(ff->fc,
                                                       (fl_owner_t) file);
        }
-       /* Hold vfsmount and dentry until release is finished */
-       path_get(&file->f_path);
-       req->misc.release.path = file->f_path;
+       /* Hold inode until release is finished */
+       req->misc.release.inode = igrab(file_inode(file));
 
        /*
         * Normally this will send the RELEASE request, however if
@@ -480,7 +443,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
        struct inode *inode = file->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_fsync_in inarg;
        int err;
 
@@ -506,23 +469,15 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
        if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
                goto out;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req)) {
-               err = PTR_ERR(req);
-               goto out;
-       }
-
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
        inarg.fsync_flags = datasync ? 1 : 0;
-       req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       err = fuse_simple_request(fc, &args);
        if (err == -ENOSYS) {
                if (isdir)
                        fc->no_fsyncdir = 1;
@@ -2156,49 +2111,44 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
        return 0;
 }
 
-static void fuse_lk_fill(struct fuse_req *req, struct file *file,
+static void fuse_lk_fill(struct fuse_args *args, struct file *file,
                         const struct file_lock *fl, int opcode, pid_t pid,
-                        int flock)
+                        int flock, struct fuse_lk_in *inarg)
 {
        struct inode *inode = file_inode(file);
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
-       struct fuse_lk_in *arg = &req->misc.lk_in;
-
-       arg->fh = ff->fh;
-       arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
-       arg->lk.start = fl->fl_start;
-       arg->lk.end = fl->fl_end;
-       arg->lk.type = fl->fl_type;
-       arg->lk.pid = pid;
+
+       memset(inarg, 0, sizeof(*inarg));
+       inarg->fh = ff->fh;
+       inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
+       inarg->lk.start = fl->fl_start;
+       inarg->lk.end = fl->fl_end;
+       inarg->lk.type = fl->fl_type;
+       inarg->lk.pid = pid;
        if (flock)
-               arg->lk_flags |= FUSE_LK_FLOCK;
-       req->in.h.opcode = opcode;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(*arg);
-       req->in.args[0].value = arg;
+               inarg->lk_flags |= FUSE_LK_FLOCK;
+       args->in.h.opcode = opcode;
+       args->in.h.nodeid = get_node_id(inode);
+       args->in.numargs = 1;
+       args->in.args[0].size = sizeof(*inarg);
+       args->in.args[0].value = inarg;
 }
 
 static int fuse_getlk(struct file *file, struct file_lock *fl)
 {
        struct inode *inode = file_inode(file);
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
+       struct fuse_lk_in inarg;
        struct fuse_lk_out outarg;
        int err;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0);
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg);
+       args.out.numargs = 1;
+       args.out.args[0].size = sizeof(outarg);
+       args.out.args[0].value = &outarg;
+       err = fuse_simple_request(fc, &args);
        if (!err)
                err = convert_fuse_file_lock(&outarg.lk, fl);
 
@@ -2209,7 +2159,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
 {
        struct inode *inode = file_inode(file);
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
+       struct fuse_lk_in inarg;
        int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
        pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
        int err;
@@ -2223,17 +2174,13 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
        if (fl->fl_flags & FL_CLOSE)
                return 0;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
+       fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg);
+       err = fuse_simple_request(fc, &args);
 
-       fuse_lk_fill(req, file, fl, opcode, pid, flock);
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
        /* locking is restartable */
        if (err == -EINTR)
                err = -ERESTARTSYS;
-       fuse_put_request(fc, req);
+
        return err;
 }
 
@@ -2283,7 +2230,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
 {
        struct inode *inode = mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_bmap_in inarg;
        struct fuse_bmap_out outarg;
        int err;
@@ -2291,24 +2238,18 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
        if (!inode->i_sb->s_bdev || fc->no_bmap)
                return 0;
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return 0;
-
        memset(&inarg, 0, sizeof(inarg));
        inarg.block = block;
        inarg.blocksize = inode->i_sb->s_blocksize;
-       req->in.h.opcode = FUSE_BMAP;
-       req->in.h.nodeid = get_node_id(inode);
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = FUSE_BMAP;
+       args.in.h.nodeid = get_node_id(inode);
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.out.numargs = 1;
+       args.out.args[0].size = sizeof(outarg);
+       args.out.args[0].value = &outarg;
+       err = fuse_simple_request(fc, &args);
        if (err == -ENOSYS)
                fc->no_bmap = 1;
 
@@ -2776,7 +2717,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait)
        struct fuse_conn *fc = ff->fc;
        struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
        struct fuse_poll_out outarg;
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        int err;
 
        if (fc->no_poll)
@@ -2794,21 +2735,15 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait)
                fuse_register_polled_file(fc, ff);
        }
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return POLLERR;
-
-       req->in.h.opcode = FUSE_POLL;
-       req->in.h.nodeid = ff->nodeid;
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
-       fuse_put_request(fc, req);
+       args.in.h.opcode = FUSE_POLL;
+       args.in.h.nodeid = ff->nodeid;
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       args.out.numargs = 1;
+       args.out.args[0].size = sizeof(outarg);
+       args.out.args[0].value = &outarg;
+       err = fuse_simple_request(fc, &args);
 
        if (!err)
                return outarg.revents;
@@ -2949,10 +2884,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                                loff_t length)
 {
        struct fuse_file *ff = file->private_data;
-       struct inode *inode = file->f_inode;
+       struct inode *inode = file_inode(file);
        struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_conn *fc = ff->fc;
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_fallocate_in inarg = {
                .fh = ff->fh,
                .offset = offset,
@@ -2985,25 +2920,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        if (!(mode & FALLOC_FL_KEEP_SIZE))
                set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req)) {
-               err = PTR_ERR(req);
-               goto out;
-       }
-
-       req->in.h.opcode = FUSE_FALLOCATE;
-       req->in.h.nodeid = ff->nodeid;
-       req->in.numargs = 1;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
+       args.in.h.opcode = FUSE_FALLOCATE;
+       args.in.h.nodeid = ff->nodeid;
+       args.in.numargs = 1;
+       args.in.args[0].size = sizeof(inarg);
+       args.in.args[0].value = &inarg;
+       err = fuse_simple_request(fc, &args);
        if (err == -ENOSYS) {
                fc->no_fallocate = 1;
                err = -EOPNOTSUPP;
        }
-       fuse_put_request(fc, req);
-
        if (err)
                goto out;
 
index e8e47a6ab5186be8df5889d65df28bc92bf8c97d..e0fc6725d1d0d66a4c3c7dce595239631ba353b1 100644 (file)
@@ -213,7 +213,7 @@ struct fuse_out {
        unsigned numargs;
 
        /** Array of arguments */
-       struct fuse_arg args[3];
+       struct fuse_arg args[2];
 };
 
 /** FUSE page descriptor */
@@ -222,6 +222,25 @@ struct fuse_page_desc {
        unsigned int offset;
 };
 
+struct fuse_args {
+       struct {
+               struct {
+                       uint32_t opcode;
+                       uint64_t nodeid;
+               } h;
+               unsigned numargs;
+               struct fuse_in_arg args[3];
+
+       } in;
+       struct {
+               unsigned argvar:1;
+               unsigned numargs;
+               struct fuse_arg args[2];
+       } out;
+};
+
+#define FUSE_ARGS(args) struct fuse_args args = {}
+
 /** The request state */
 enum fuse_req_state {
        FUSE_REQ_INIT = 0,
@@ -305,11 +324,8 @@ struct fuse_req {
        /** Data for asynchronous requests */
        union {
                struct {
-                       union {
-                               struct fuse_release_in in;
-                               struct work_struct work;
-                       };
-                       struct path path;
+                       struct fuse_release_in in;
+                       struct inode *inode;
                } release;
                struct fuse_init_in init_in;
                struct fuse_init_out init_out;
@@ -324,7 +340,6 @@ struct fuse_req {
                        struct fuse_req *next;
                } write;
                struct fuse_notify_retrieve_in retrieve_in;
-               struct fuse_lk_in lk_in;
        } misc;
 
        /** page vector */
@@ -753,15 +768,6 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
  */
 void __fuse_get_request(struct fuse_req *req);
 
-/**
- * Get a request, may fail with -ENOMEM,
- * useful for callers who doesn't use req->pages[]
- */
-static inline struct fuse_req *fuse_get_req_nopages(struct fuse_conn *fc)
-{
-       return fuse_get_req(fc, 0);
-}
-
 /**
  * Gets a requests for a file operation, always succeeds
  */
@@ -779,6 +785,11 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
  */
 void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req);
 
+/**
+ * Simple request sending that does request allocation and freeing
+ */
+ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args);
+
 /**
  * Send a request in the background
  */
@@ -804,8 +815,6 @@ void fuse_invalidate_atime(struct inode *inode);
  */
 struct fuse_conn *fuse_conn_get(struct fuse_conn *fc);
 
-void fuse_conn_kill(struct fuse_conn *fc);
-
 /**
  * Initialize fuse_conn
  */
index 03246cd9d47a7b27d93ce0c2a122cae89d5fbd4f..6749109f255da69a5c24825aab1f2a25140fbb47 100644 (file)
@@ -376,28 +376,13 @@ static void fuse_bdi_destroy(struct fuse_conn *fc)
                bdi_destroy(&fc->bdi);
 }
 
-void fuse_conn_kill(struct fuse_conn *fc)
-{
-       spin_lock(&fc->lock);
-       fc->connected = 0;
-       fc->blocked = 0;
-       fc->initialized = 1;
-       spin_unlock(&fc->lock);
-       /* Flush all readers on this fs */
-       kill_fasync(&fc->fasync, SIGIO, POLL_IN);
-       wake_up_all(&fc->waitq);
-       wake_up_all(&fc->blocked_waitq);
-       wake_up_all(&fc->reserved_req_waitq);
-}
-EXPORT_SYMBOL_GPL(fuse_conn_kill);
-
 static void fuse_put_super(struct super_block *sb)
 {
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
        fuse_send_destroy(fc);
 
-       fuse_conn_kill(fc);
+       fuse_abort_conn(fc);
        mutex_lock(&fuse_mutex);
        list_del(&fc->entry);
        fuse_ctl_remove_conn(fc);
@@ -425,7 +410,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
        struct fuse_conn *fc = get_fuse_conn_super(sb);
-       struct fuse_req *req;
+       FUSE_ARGS(args);
        struct fuse_statfs_out outarg;
        int err;
 
@@ -434,23 +419,17 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
                return 0;
        }
 
-       req = fuse_get_req_nopages(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
        memset(&outarg, 0, sizeof(outarg));
-       req->in.numargs = 0;
-       req->in.h.opcode = FUSE_STATFS;
-       req->in.h.nodeid = get_node_id(dentry->d_inode);
-       req->out.numargs = 1;
-       req->out.args[0].size =
+       args.in.numargs = 0;
+       args.in.h.opcode = FUSE_STATFS;
+       args.in.h.nodeid = get_node_id(dentry->d_inode);
+       args.out.numargs = 1;
+       args.out.args[0].size =
                fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       fuse_request_send(fc, req);
-       err = req->out.h.error;
+       args.out.args[0].value = &outarg;
+       err = fuse_simple_request(fc, &args);
        if (!err)
                convert_fuse_statfs(buf, &outarg.st);
-       fuse_put_request(fc, req);
        return err;
 }