diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 12:41:32 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-17 12:41:32 -0500 |
| commit | c103b21c20ee3d173ccccb7d5ca8f5b8bc02cac3 (patch) | |
| tree | 9fed771f32b878b5bd16f2251052c5177820fcd2 | |
| parent | 603ba7e41bf5d405aba22294af5d075d8898176d (diff) | |
| parent | 1c68271cf1bfe7f3664b6dbf4ffd5fe11130be5c (diff) | |
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()
| -rw-r--r-- | fs/fuse/cuse.c | 2 | ||||
| -rw-r--r-- | fs/fuse/dev.c | 29 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 538 | ||||
| -rw-r--r-- | fs/fuse/file.c | 230 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 45 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 39 |
6 files changed, 359 insertions, 524 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 966ace8b243f..28d0c7abba1c 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
| @@ -415,7 +415,7 @@ err_unlock: | |||
| 415 | err_region: | 415 | err_region: |
| 416 | unregister_chrdev_region(devt, 1); | 416 | unregister_chrdev_region(devt, 1); |
| 417 | err: | 417 | err: |
| 418 | fuse_conn_kill(fc); | 418 | fuse_abort_conn(fc); |
| 419 | goto out; | 419 | goto out; |
| 420 | } | 420 | } |
| 421 | 421 | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ca887314aba9..ba1107977f2e 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -511,6 +511,35 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | |||
| 511 | } | 511 | } |
| 512 | EXPORT_SYMBOL_GPL(fuse_request_send); | 512 | EXPORT_SYMBOL_GPL(fuse_request_send); |
| 513 | 513 | ||
| 514 | ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) | ||
| 515 | { | ||
| 516 | struct fuse_req *req; | ||
| 517 | ssize_t ret; | ||
| 518 | |||
| 519 | req = fuse_get_req(fc, 0); | ||
| 520 | if (IS_ERR(req)) | ||
| 521 | return PTR_ERR(req); | ||
| 522 | |||
| 523 | req->in.h.opcode = args->in.h.opcode; | ||
| 524 | req->in.h.nodeid = args->in.h.nodeid; | ||
| 525 | req->in.numargs = args->in.numargs; | ||
| 526 | memcpy(req->in.args, args->in.args, | ||
| 527 | args->in.numargs * sizeof(struct fuse_in_arg)); | ||
| 528 | req->out.argvar = args->out.argvar; | ||
| 529 | req->out.numargs = args->out.numargs; | ||
| 530 | memcpy(req->out.args, args->out.args, | ||
| 531 | args->out.numargs * sizeof(struct fuse_arg)); | ||
| 532 | fuse_request_send(fc, req); | ||
| 533 | ret = req->out.h.error; | ||
| 534 | if (!ret && args->out.argvar) { | ||
| 535 | BUG_ON(args->out.numargs != 1); | ||
| 536 | ret = req->out.args[0].size; | ||
| 537 | } | ||
| 538 | fuse_put_request(fc, req); | ||
| 539 | |||
| 540 | return ret; | ||
| 541 | } | ||
| 542 | |||
| 514 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | 543 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, |
| 515 | struct fuse_req *req) | 544 | struct fuse_req *req) |
| 516 | { | 545 | { |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index df562cc87763..252b8a5de8b5 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -145,22 +145,22 @@ static void fuse_invalidate_entry(struct dentry *entry) | |||
| 145 | fuse_invalidate_entry_cache(entry); | 145 | fuse_invalidate_entry_cache(entry); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_req *req, | 148 | static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, |
| 149 | u64 nodeid, struct qstr *name, | 149 | u64 nodeid, struct qstr *name, |
| 150 | struct fuse_entry_out *outarg) | 150 | struct fuse_entry_out *outarg) |
| 151 | { | 151 | { |
| 152 | memset(outarg, 0, sizeof(struct fuse_entry_out)); | 152 | memset(outarg, 0, sizeof(struct fuse_entry_out)); |
| 153 | req->in.h.opcode = FUSE_LOOKUP; | 153 | args->in.h.opcode = FUSE_LOOKUP; |
| 154 | req->in.h.nodeid = nodeid; | 154 | args->in.h.nodeid = nodeid; |
| 155 | req->in.numargs = 1; | 155 | args->in.numargs = 1; |
| 156 | req->in.args[0].size = name->len + 1; | 156 | args->in.args[0].size = name->len + 1; |
| 157 | req->in.args[0].value = name->name; | 157 | args->in.args[0].value = name->name; |
| 158 | req->out.numargs = 1; | 158 | args->out.numargs = 1; |
| 159 | if (fc->minor < 9) | 159 | if (fc->minor < 9) |
| 160 | req->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | 160 | args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; |
| 161 | else | 161 | else |
| 162 | req->out.args[0].size = sizeof(struct fuse_entry_out); | 162 | args->out.args[0].size = sizeof(struct fuse_entry_out); |
| 163 | req->out.args[0].value = outarg; | 163 | args->out.args[0].value = outarg; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | u64 fuse_get_attr_version(struct fuse_conn *fc) | 166 | u64 fuse_get_attr_version(struct fuse_conn *fc) |
| @@ -200,9 +200,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 200 | goto invalid; | 200 | goto invalid; |
| 201 | else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || | 201 | else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || |
| 202 | (flags & LOOKUP_REVAL)) { | 202 | (flags & LOOKUP_REVAL)) { |
| 203 | int err; | ||
| 204 | struct fuse_entry_out outarg; | 203 | struct fuse_entry_out outarg; |
| 205 | struct fuse_req *req; | 204 | FUSE_ARGS(args); |
| 206 | struct fuse_forget_link *forget; | 205 | struct fuse_forget_link *forget; |
| 207 | u64 attr_version; | 206 | u64 attr_version; |
| 208 | 207 | ||
| @@ -215,31 +214,23 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 215 | goto out; | 214 | goto out; |
| 216 | 215 | ||
| 217 | fc = get_fuse_conn(inode); | 216 | fc = get_fuse_conn(inode); |
| 218 | req = fuse_get_req_nopages(fc); | ||
| 219 | ret = PTR_ERR(req); | ||
| 220 | if (IS_ERR(req)) | ||
| 221 | goto out; | ||
| 222 | 217 | ||
| 223 | forget = fuse_alloc_forget(); | 218 | forget = fuse_alloc_forget(); |
| 224 | if (!forget) { | 219 | ret = -ENOMEM; |
| 225 | fuse_put_request(fc, req); | 220 | if (!forget) |
| 226 | ret = -ENOMEM; | ||
| 227 | goto out; | 221 | goto out; |
| 228 | } | ||
| 229 | 222 | ||
| 230 | attr_version = fuse_get_attr_version(fc); | 223 | attr_version = fuse_get_attr_version(fc); |
| 231 | 224 | ||
| 232 | parent = dget_parent(entry); | 225 | parent = dget_parent(entry); |
| 233 | fuse_lookup_init(fc, req, get_node_id(parent->d_inode), | 226 | fuse_lookup_init(fc, &args, get_node_id(parent->d_inode), |
| 234 | &entry->d_name, &outarg); | 227 | &entry->d_name, &outarg); |
| 235 | fuse_request_send(fc, req); | 228 | ret = fuse_simple_request(fc, &args); |
| 236 | dput(parent); | 229 | dput(parent); |
| 237 | err = req->out.h.error; | ||
| 238 | fuse_put_request(fc, req); | ||
| 239 | /* Zero nodeid is same as -ENOENT */ | 230 | /* Zero nodeid is same as -ENOENT */ |
| 240 | if (!err && !outarg.nodeid) | 231 | if (!ret && !outarg.nodeid) |
| 241 | err = -ENOENT; | 232 | ret = -ENOENT; |
| 242 | if (!err) { | 233 | if (!ret) { |
| 243 | fi = get_fuse_inode(inode); | 234 | fi = get_fuse_inode(inode); |
| 244 | if (outarg.nodeid != get_node_id(inode)) { | 235 | if (outarg.nodeid != get_node_id(inode)) { |
| 245 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); | 236 | fuse_queue_forget(fc, forget, outarg.nodeid, 1); |
| @@ -250,7 +241,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
| 250 | spin_unlock(&fc->lock); | 241 | spin_unlock(&fc->lock); |
| 251 | } | 242 | } |
| 252 | kfree(forget); | 243 | kfree(forget); |
| 253 | if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) | 244 | if (ret == -ENOMEM) |
| 245 | goto out; | ||
| 246 | if (ret || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) | ||
| 254 | goto invalid; | 247 | goto invalid; |
| 255 | 248 | ||
| 256 | fuse_change_attributes(inode, &outarg.attr, | 249 | fuse_change_attributes(inode, &outarg.attr, |
| @@ -296,7 +289,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
| 296 | struct fuse_entry_out *outarg, struct inode **inode) | 289 | struct fuse_entry_out *outarg, struct inode **inode) |
| 297 | { | 290 | { |
| 298 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 291 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
| 299 | struct fuse_req *req; | 292 | FUSE_ARGS(args); |
| 300 | struct fuse_forget_link *forget; | 293 | struct fuse_forget_link *forget; |
| 301 | u64 attr_version; | 294 | u64 attr_version; |
| 302 | int err; | 295 | int err; |
| @@ -306,24 +299,16 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
| 306 | if (name->len > FUSE_NAME_MAX) | 299 | if (name->len > FUSE_NAME_MAX) |
| 307 | goto out; | 300 | goto out; |
| 308 | 301 | ||
| 309 | req = fuse_get_req_nopages(fc); | ||
| 310 | err = PTR_ERR(req); | ||
| 311 | if (IS_ERR(req)) | ||
| 312 | goto out; | ||
| 313 | 302 | ||
| 314 | forget = fuse_alloc_forget(); | 303 | forget = fuse_alloc_forget(); |
| 315 | err = -ENOMEM; | 304 | err = -ENOMEM; |
| 316 | if (!forget) { | 305 | if (!forget) |
| 317 | |||
