Commit c103b21c authored by Linus Torvalds's avatar 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()
parents 603ba7e4 1c68271c
......@@ -415,7 +415,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
err_region:
unregister_chrdev_region(devt, 1);
err:
fuse_conn_kill(fc);
fuse_abort_conn(fc);
goto out;
}
......
......@@ -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)
{
......
This diff is collapsed.
This diff is collapsed.
......@@ -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 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
*/
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment