提交 c103b21c 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse

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()
...@@ -415,7 +415,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) ...@@ -415,7 +415,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
err_region: err_region:
unregister_chrdev_region(devt, 1); unregister_chrdev_region(devt, 1);
err: err:
fuse_conn_kill(fc); fuse_abort_conn(fc);
goto out; goto out;
} }
......
...@@ -511,6 +511,35 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) ...@@ -511,6 +511,35 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req)
} }
EXPORT_SYMBOL_GPL(fuse_request_send); 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, static void fuse_request_send_nowait_locked(struct fuse_conn *fc,
struct fuse_req *req) struct fuse_req *req)
{ {
......
此差异已折叠。
...@@ -24,30 +24,22 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *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) int opcode, struct fuse_open_out *outargp)
{ {
struct fuse_open_in inarg; struct fuse_open_in inarg;
struct fuse_req *req; FUSE_ARGS(args);
int err;
req = fuse_get_req_nopages(fc);
if (IS_ERR(req))
return PTR_ERR(req);
memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg));
inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
if (!fc->atomic_o_trunc) if (!fc->atomic_o_trunc)
inarg.flags &= ~O_TRUNC; inarg.flags &= ~O_TRUNC;
req->in.h.opcode = opcode; args.in.h.opcode = opcode;
req->in.h.nodeid = nodeid; args.in.h.nodeid = nodeid;
req->in.numargs = 1; args.in.numargs = 1;
req->in.args[0].size = sizeof(inarg); args.in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg; args.in.args[0].value = &inarg;
req->out.numargs = 1; args.out.numargs = 1;
req->out.args[0].size = sizeof(*outargp); args.out.args[0].size = sizeof(*outargp);
req->out.args[0].value = outargp; args.out.args[0].value = outargp;
fuse_request_send(fc, req);
err = req->out.h.error;
fuse_put_request(fc, req);
return err; return fuse_simple_request(fc, &args);
} }
struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
...@@ -89,37 +81,9 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff) ...@@ -89,37 +81,9 @@ struct fuse_file *fuse_file_get(struct fuse_file *ff)
return 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) static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
{ {
if (fc->destroy_req) { iput(req->misc.release.inode);
/*
* 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);
}
} }
static void fuse_file_put(struct fuse_file *ff, bool sync) 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) ...@@ -133,12 +97,12 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
* implement 'open' * implement 'open'
*/ */
req->background = 0; req->background = 0;
path_put(&req->misc.release.path); iput(req->misc.release.inode);
fuse_put_request(ff->fc, req); fuse_put_request(ff->fc, req);
} else if (sync) { } else if (sync) {
req->background = 0; req->background = 0;
fuse_request_send(ff->fc, req); fuse_request_send(ff->fc, req);
path_put(&req->misc.release.path); iput(req->misc.release.inode);
fuse_put_request(ff->fc, req); fuse_put_request(ff->fc, req);
} else { } else {
req->end = fuse_release_end; req->end = fuse_release_end;
...@@ -297,9 +261,8 @@ void fuse_release_common(struct file *file, int opcode) ...@@ -297,9 +261,8 @@ void fuse_release_common(struct file *file, int opcode)
inarg->lock_owner = fuse_lock_owner_id(ff->fc, inarg->lock_owner = fuse_lock_owner_id(ff->fc,
(fl_owner_t) file); (fl_owner_t) file);
} }
/* Hold vfsmount and dentry until release is finished */ /* Hold inode until release is finished */
path_get(&file->f_path); req->misc.release.inode = igrab(file_inode(file));
req->misc.release.path = file->f_path;
/* /*
* Normally this will send the RELEASE request, however if * 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, ...@@ -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 inode *inode = file->f_mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data; struct fuse_file *ff = file->private_data;
struct fuse_req *req; FUSE_ARGS(args);
struct fuse_fsync_in inarg; struct fuse_fsync_in inarg;
int err; int err;
...@@ -506,23 +469,15 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, ...@@ -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)) if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
goto out; goto out;
req = fuse_get_req_nopages(fc);
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto out;
}
memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh; inarg.fh = ff->fh;
inarg.fsync_flags = datasync ? 1 : 0; inarg.fsync_flags = datasync ? 1 : 0;
req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC; args.in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
req->in.h.nodeid = get_node_id(inode); args.in.h.nodeid = get_node_id(inode);
req->in.numargs = 1; args.in.numargs = 1;
req->in.args[0].size = sizeof(inarg); args.in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg; args.in.args[0].value = &inarg;
fuse_request_send(fc, req); err = fuse_simple_request(fc, &args);
err = req->out.h.error;
fuse_put_request(fc, req);
if (err == -ENOSYS) { if (err == -ENOSYS) {
if (isdir) if (isdir)
fc->no_fsyncdir = 1; fc->no_fsyncdir = 1;
...@@ -2156,49 +2111,44 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, ...@@ -2156,49 +2111,44 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
return 0; 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, 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 inode *inode = file_inode(file);
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data; struct fuse_file *ff = file->private_data;
struct fuse_lk_in *arg = &req->misc.lk_in;
memset(inarg, 0, sizeof(*inarg));
arg->fh = ff->fh; inarg->fh = ff->fh;
arg->owner = fuse_lock_owner_id(fc, fl->fl_owner); inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
arg->lk.start = fl->fl_start; inarg->lk.start = fl->fl_start;
arg->lk.end = fl->fl_end; inarg->lk.end = fl->fl_end;
arg->lk.type = fl->fl_type; inarg->lk.type = fl->fl_type;
arg->lk.pid = pid; inarg->lk.pid = pid;
if (flock) if (flock)
arg->lk_flags |= FUSE_LK_FLOCK; inarg->lk_flags |= FUSE_LK_FLOCK;
req->in.h.opcode = opcode; args->in.h.opcode = opcode;
req->in.h.nodeid = get_node_id(inode); args->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1; args->in.numargs = 1;
req->in.args[0].size = sizeof(*arg); args->in.args[0].size = sizeof(*inarg);
req->in.args[0].value = arg; args->in.args[0].value = inarg;
} }
static int fuse_getlk(struct file *file, struct file_lock *fl) static int fuse_getlk(struct file *file, struct file_lock *fl)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct fuse_conn *fc = get_fuse_conn(inode); 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; struct fuse_lk_out outarg;
int err; int err;
req = fuse_get_req_nopages(fc); fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg);
if (IS_ERR(req)) args.out.numargs = 1;
return PTR_ERR(req); args.out.args[0].size = sizeof(outarg);
args.out.args[0].value = &outarg;
fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0); err = fuse_simple_request(fc, &args);
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);
if (!err) if (!err)
err = convert_fuse_file_lock(&outarg.lk, fl); 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) ...@@ -2209,7 +2159,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
{ {
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct fuse_conn *fc = get_fuse_conn(inode); 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; int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
int err; int err;
...@@ -2223,17 +2174,13 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) ...@@ -2223,17 +2174,13 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
if (fl->fl_flags & FL_CLOSE) if (fl->fl_flags & FL_CLOSE)
return 0; return 0;
req = fuse_get_req_nopages(fc); fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg);
if (IS_ERR(req)) err = fuse_simple_request(fc, &args);
return PTR_ERR(req);
fuse_lk_fill(req, file, fl, opcode, pid, flock);
fuse_request_send(fc, req);
err = req->out.h.error;
/* locking is restartable */ /* locking is restartable */
if (err == -EINTR) if (err == -EINTR)
err = -ERESTARTSYS; err = -ERESTARTSYS;
fuse_put_request(fc, req);
return err; return err;
} }
...@@ -2283,7 +2230,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) ...@@ -2283,7 +2230,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
{ {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req; FUSE_ARGS(args);
struct fuse_bmap_in inarg; struct fuse_bmap_in inarg;
struct fuse_bmap_out outarg; struct fuse_bmap_out outarg;
int err; int err;
...@@ -2291,24 +2238,18 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) ...@@ -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) if (!inode->i_sb->s_bdev || fc->no_bmap)
return 0; return 0;
req = fuse_get_req_nopages(fc);
if (IS_ERR(req))
return 0;
memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg));
inarg.block = block; inarg.block = block;
inarg.blocksize = inode->i_sb->s_blocksize; inarg.blocksize = inode->i_sb->s_blocksize;
req->in.h.opcode = FUSE_BMAP; args.in.h.opcode = FUSE_BMAP;
req->in.h.nodeid = get_node_id(inode); args.in.h.nodeid = get_node_id(inode);
req->in.numargs = 1; args.in.numargs = 1;
req->in.args[0].size = sizeof(inarg); args.in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg; args.in.args[0].value = &inarg;
req->out.numargs = 1; args.out.numargs = 1;
req->out.args[0].size = sizeof(outarg); args.out.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg; args.out.args[0].value = &outarg;
fuse_request_send(fc, req); err = fuse_simple_request(fc, &args);
err = req->out.h.error;
fuse_put_request(fc, req);
if (err == -ENOSYS) if (err == -ENOSYS)
fc->no_bmap = 1; fc->no_bmap = 1;
...@@ -2776,7 +2717,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) ...@@ -2776,7 +2717,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait)
struct fuse_conn *fc = ff->fc; struct fuse_conn *fc = ff->fc;
struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
struct fuse_poll_out outarg; struct fuse_poll_out outarg;
struct fuse_req *req; FUSE_ARGS(args);
int err; int err;
if (fc->no_poll) if (fc->no_poll)
...@@ -2794,21 +2735,15 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) ...@@ -2794,21 +2735,15 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait)
fuse_register_polled_file(fc, ff); fuse_register_polled_file(fc, ff);
} }
req = fuse_get_req_nopages(fc); args.in.h.opcode = FUSE_POLL;
if (IS_ERR(req)) args.in.h.nodeid = ff->nodeid;
return POLLERR; args.in.numargs = 1;
args.in.args[0].size = sizeof(inarg);
req->in.h.opcode = FUSE_POLL; args.in.args[0].value = &inarg;
req->in.h.nodeid = ff->nodeid; args.out.numargs = 1;
req->in.numargs = 1; args.out.args[0].size = sizeof(outarg);
req->in.args[0].size = sizeof(inarg); args.out.args[0].value = &outarg;
req->in.args[0].value = &inarg; err = fuse_simple_request(fc, &args);
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);
if (!err) if (!err)
return outarg.revents; return outarg.revents;
...@@ -2949,10 +2884,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, ...@@ -2949,10 +2884,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
loff_t length) loff_t length)
{ {
struct fuse_file *ff = file->private_data; 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_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = ff->fc; struct fuse_conn *fc = ff->fc;
struct fuse_req *req; FUSE_ARGS(args);
struct fuse_fallocate_in inarg = { struct fuse_fallocate_in inarg = {
.fh = ff->fh, .fh = ff->fh,
.offset = offset, .offset = offset,
...@@ -2985,25 +2920,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, ...@@ -2985,25 +2920,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
if (!(mode & FALLOC_FL_KEEP_SIZE)) if (!(mode & FALLOC_FL_KEEP_SIZE))
set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
req = fuse_get_req_nopages(fc); args.in.h.opcode = FUSE_FALLOCATE;
if (IS_ERR(req)) { args.in.h.nodeid = ff->nodeid;
err = PTR_ERR(req); args.in.numargs = 1;
goto out; args.in.args[0].size = sizeof(inarg);
} args.in.args[0].value = &inarg;
err = fuse_simple_request(fc, &args);
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;
if (err == -ENOSYS) { if (err == -ENOSYS) {
fc->no_fallocate = 1; fc->no_fallocate = 1;
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
} }
fuse_put_request(fc, req);
if (err) if (err)
goto out; goto out;
......
...@@ -213,7 +213,7 @@ struct fuse_out { ...@@ -213,7 +213,7 @@ struct fuse_out {
unsigned numargs; unsigned numargs;
/** Array of arguments */ /** Array of arguments */
struct fuse_arg args[3]; struct fuse_arg args[2];
}; };
/** FUSE page descriptor */ /** FUSE page descriptor */
...@@ -222,6 +222,25 @@ struct fuse_page_desc { ...@@ -222,6 +222,25 @@ struct fuse_page_desc {
unsigned int offset; 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 */ /** The request state */
enum fuse_req_state { enum fuse_req_state {
FUSE_REQ_INIT = 0, FUSE_REQ_INIT = 0,
...@@ -305,11 +324,8 @@ struct fuse_req { ...@@ -305,11 +324,8 @@ struct fuse_req {
/** Data for asynchronous requests */ /** Data for asynchronous requests */
union { union {
struct { struct {
union { struct fuse_release_in in;
struct fuse_release_in in; struct inode *inode;
struct work_struct work;
};
struct path path;
} release; } release;
struct fuse_init_in init_in; struct fuse_init_in init_in;
struct fuse_init_out init_out; struct fuse_init_out init_out;
...@@ -324,7 +340,6 @@ struct fuse_req { ...@@ -324,7 +340,6 @@ struct fuse_req {
struct fuse_req *next; struct fuse_req *next;
} write; } write;
struct fuse_notify_retrieve_in retrieve_in; struct fuse_notify_retrieve_in retrieve_in;
struct fuse_lk_in lk_in;
} misc; } misc;
/** page vector */ /** page vector */
...@@ -753,15 +768,6 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, ...@@ -753,15 +768,6 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc,
*/ */
void __fuse_get_request(struct fuse_req *req); 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 * 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); ...@@ -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); 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 * Send a request in the background
*/ */
...@@ -804,8 +815,6 @@ void fuse_invalidate_atime(struct inode *inode); ...@@ -804,8 +815,6 @@ void fuse_invalidate_atime(struct inode *inode);
*/ */
struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); struct fuse_conn *fuse_conn_get(struct fuse_conn *fc);
void fuse_conn_kill(struct fuse_conn *fc);
/** /**
* Initialize fuse_conn * Initialize fuse_conn
*/ */
......
...@@ -376,28 +376,13 @@ static void fuse_bdi_destroy(struct fuse_conn *fc) ...@@ -376,28 +376,13 @@ static void fuse_bdi_destroy(struct fuse_conn *fc)
bdi_destroy(&fc->bdi); 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) static void fuse_put_super(struct super_block *sb)
{ {
struct fuse_conn *fc = get_fuse_conn_super(sb); struct fuse_conn *fc = get_fuse_conn_super(sb);
fuse_send_destroy(fc); fuse_send_destroy(fc);
fuse_conn_kill(fc); fuse_abort_conn(fc);
mutex_lock(&fuse_mutex); mutex_lock(&fuse_mutex);
list_del(&fc->entry); list_del(&fc->entry);
fuse_ctl_remove_conn(fc); fuse_ctl_remove_conn(fc);
...@@ -425,7 +410,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -425,7 +410,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
struct super_block *sb = dentry->d_sb; struct super_block *sb = dentry->d_sb;
struct fuse_conn *fc = get_fuse_conn_super(sb); struct fuse_conn *fc = get_fuse_conn_super(sb);
struct fuse_req *req; FUSE_ARGS(args);
struct fuse_statfs_out outarg; struct fuse_statfs_out outarg;
int err; int err;
...@@ -434,23 +419,17 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -434,23 +419,17 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
return 0; return 0;
} }
req = fuse_get_req_nopages(fc);
if (IS_ERR(req))
return PTR_ERR(req);
memset(&outarg, 0, sizeof(outarg)); memset(&outarg, 0, sizeof(outarg));
req->in.numargs = 0; args.in.numargs = 0;
req->in.h.opcode = FUSE_STATFS; args.in.h.opcode = FUSE_STATFS;
req->in.h.nodeid = get_node_id(dentry->d_inode); args.in.h.nodeid = get_node_id(dentry->d_inode);
req->out.numargs = 1; args.out.numargs = 1;
req->out.args[0].size = args.out.args[0].size =
fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
req->out.args[0].value = &outarg; args.out.args[0].value = &outarg;
fuse_request_send(fc, req); err = fuse_simple_request(fc, &args);
err = req->out.h.error;
if (!err) if (!err)
convert_fuse_statfs(buf, &outarg.st); convert_fuse_statfs(buf, &outarg.st);
fuse_put_request(fc, req);
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册