diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/dev.c | 51 | ||||
-rw-r--r-- | fs/fuse/dir.c | 31 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 2 | ||||
-rw-r--r-- | fs/fuse/inode.c | 5 |
4 files changed, 60 insertions, 29 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ba1107977f2e..ed19a7d622fa 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -131,6 +131,13 @@ static void fuse_req_init_context(struct fuse_req *req) | |||
131 | req->in.h.pid = current->pid; | 131 | req->in.h.pid = current->pid; |
132 | } | 132 | } |
133 | 133 | ||
134 | void fuse_set_initialized(struct fuse_conn *fc) | ||
135 | { | ||
136 | /* Make sure stores before this are seen on another CPU */ | ||
137 | smp_wmb(); | ||
138 | fc->initialized = 1; | ||
139 | } | ||
140 | |||
134 | static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) | 141 | static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) |
135 | { | 142 | { |
136 | return !fc->initialized || (for_background && fc->blocked); | 143 | return !fc->initialized || (for_background && fc->blocked); |
@@ -155,6 +162,8 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages, | |||
155 | if (intr) | 162 | if (intr) |
156 | goto out; | 163 | goto out; |
157 | } | 164 | } |
165 | /* Matches smp_wmb() in fuse_set_initialized() */ | ||
166 | smp_rmb(); | ||
158 | 167 | ||
159 | err = -ENOTCONN; | 168 | err = -ENOTCONN; |
160 | if (!fc->connected) | 169 | if (!fc->connected) |
@@ -253,6 +262,8 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, | |||
253 | 262 | ||
254 | atomic_inc(&fc->num_waiting); | 263 | atomic_inc(&fc->num_waiting); |
255 | wait_event(fc->blocked_waitq, fc->initialized); | 264 | wait_event(fc->blocked_waitq, fc->initialized); |
265 | /* Matches smp_wmb() in fuse_set_initialized() */ | ||
266 | smp_rmb(); | ||
256 | req = fuse_request_alloc(0); | 267 | req = fuse_request_alloc(0); |
257 | if (!req) | 268 | if (!req) |
258 | req = get_reserved_req(fc, file); | 269 | req = get_reserved_req(fc, file); |
@@ -511,6 +522,39 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | |||
511 | } | 522 | } |
512 | EXPORT_SYMBOL_GPL(fuse_request_send); | 523 | EXPORT_SYMBOL_GPL(fuse_request_send); |
513 | 524 | ||
525 | static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args) | ||
526 | { | ||
527 | if (fc->minor < 4 && args->in.h.opcode == FUSE_STATFS) | ||
528 | args->out.args[0].size = FUSE_COMPAT_STATFS_SIZE; | ||
529 | |||
530 | if (fc->minor < 9) { | ||
531 | switch (args->in.h.opcode) { | ||
532 | case FUSE_LOOKUP: | ||
533 | case FUSE_CREATE: | ||
534 | case FUSE_MKNOD: | ||
535 | case FUSE_MKDIR: | ||
536 | case FUSE_SYMLINK: | ||
537 | case FUSE_LINK: | ||
538 | args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | ||
539 | break; | ||
540 | case FUSE_GETATTR: | ||
541 | case FUSE_SETATTR: | ||
542 | args->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | if (fc->minor < 12) { | ||
547 | switch (args->in.h.opcode) { | ||
548 | case FUSE_CREATE: | ||
549 | args->in.args[0].size = sizeof(struct fuse_open_in); | ||
550 | break; | ||
551 | case FUSE_MKNOD: | ||
552 | args->in.args[0].size = FUSE_COMPAT_MKNOD_IN_SIZE; | ||
553 | break; | ||
554 | } | ||
555 | } | ||
556 | } | ||
557 | |||
514 | ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) | 558 | ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) |
515 | { | 559 | { |
516 | struct fuse_req *req; | 560 | struct fuse_req *req; |
@@ -520,6 +564,9 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) | |||
520 | if (IS_ERR(req)) | 564 | if (IS_ERR(req)) |
521 | return PTR_ERR(req); | 565 | return PTR_ERR(req); |
522 | 566 | ||
567 | /* Needs to be done after fuse_get_req() so that fc->minor is valid */ | ||
568 | fuse_adjust_compat(fc, args); | ||
569 | |||
523 | req->in.h.opcode = args->in.h.opcode; | 570 | req->in.h.opcode = args->in.h.opcode; |
524 | req->in.h.nodeid = args->in.h.nodeid; | 571 | req->in.h.nodeid = args->in.h.nodeid; |
525 | req->in.numargs = args->in.numargs; | 572 | req->in.numargs = args->in.numargs; |
@@ -2127,7 +2174,7 @@ void fuse_abort_conn(struct fuse_conn *fc) | |||
2127 | if (fc->connected) { | 2174 | if (fc->connected) { |
2128 | fc->connected = 0; | 2175 | fc->connected = 0; |
2129 | fc->blocked = 0; | 2176 | fc->blocked = 0; |
2130 | fc->initialized = 1; | 2177 | fuse_set_initialized(fc); |
2131 | end_io_requests(fc); | 2178 | end_io_requests(fc); |
2132 | end_queued_requests(fc); | 2179 | end_queued_requests(fc); |
2133 | end_polls(fc); | 2180 | end_polls(fc); |
@@ -2146,7 +2193,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) | |||
2146 | spin_lock(&fc->lock); | 2193 | spin_lock(&fc->lock); |
2147 | fc->connected = 0; | 2194 | fc->connected = 0; |
2148 | fc->blocked = 0; | 2195 | fc->blocked = 0; |
2149 | fc->initialized = 1; | 2196 | fuse_set_initialized(fc); |
2150 | end_queued_requests(fc); | 2197 | end_queued_requests(fc); |
2151 | end_polls(fc); | 2198 | end_polls(fc); |
2152 | wake_up_all(&fc->blocked_waitq); | 2199 | wake_up_all(&fc->blocked_waitq); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 252b8a5de8b5..08e7b1a9d5d0 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -156,10 +156,7 @@ static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, | |||
156 | args->in.args[0].size = name->len + 1; | 156 | args->in.args[0].size = name->len + 1; |
157 | args->in.args[0].value = name->name; | 157 | args->in.args[0].value = name->name; |
158 | args->out.numargs = 1; | 158 | args->out.numargs = 1; |
159 | if (fc->minor < 9) | 159 | args->out.args[0].size = sizeof(struct fuse_entry_out); |
160 | args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | ||
161 | else | ||
162 | args->out.args[0].size = sizeof(struct fuse_entry_out); | ||
163 | args->out.args[0].value = outarg; | 160 | args->out.args[0].value = outarg; |
164 | } | 161 | } |
165 | 162 | ||
@@ -422,16 +419,12 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
422 | args.in.h.opcode = FUSE_CREATE; | 419 | args.in.h.opcode = FUSE_CREATE; |
423 | args.in.h.nodeid = get_node_id(dir); | 420 | args.in.h.nodeid = get_node_id(dir); |
424 | args.in.numargs = 2; | 421 | args.in.numargs = 2; |
425 | args.in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : | 422 | args.in.args[0].size = sizeof(inarg); |
426 | sizeof(inarg); | ||
427 | args.in.args[0].value = &inarg; | 423 | args.in.args[0].value = &inarg; |
428 | args.in.args[1].size = entry->d_name.len + 1; | 424 | args.in.args[1].size = entry->d_name.len + 1; |
429 | args.in.args[1].value = entry->d_name.name; | 425 | args.in.args[1].value = entry->d_name.name; |
430 | args.out.numargs = 2; | 426 | args.out.numargs = 2; |
431 | if (fc->minor < 9) | 427 | args.out.args[0].size = sizeof(outentry); |
432 | args.out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | ||
433 | else | ||
434 | args.out.args[0].size = sizeof(outentry); | ||
435 | args.out.args[0].value = &outentry; | 428 | args.out.args[0].value = &outentry; |
436 | args.out.args[1].size = sizeof(outopen); | 429 | args.out.args[1].size = sizeof(outopen); |
437 | args.out.args[1].value = &outopen; | 430 | args.out.args[1].value = &outopen; |
@@ -539,10 +532,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args, | |||
539 | memset(&outarg, 0, sizeof(outarg)); | 532 | memset(&outarg, 0, sizeof(outarg)); |
540 | args->in.h.nodeid = get_node_id(dir); | 533 | args->in.h.nodeid = get_node_id(dir); |
541 | args->out.numargs = 1; | 534 | args->out.numargs = 1; |
542 | if (fc->minor < 9) | 535 | args->out.args[0].size = sizeof(outarg); |
543 | args->out.args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE; | ||
544 | else | ||
545 | args->out.args[0].size = sizeof(outarg); | ||
546 | args->out.args[0].value = &outarg; | 536 | args->out.args[0].value = &outarg; |
547 | err = fuse_simple_request(fc, args); | 537 | err = fuse_simple_request(fc, args); |
548 | if (err) | 538 | if (err) |
@@ -592,8 +582,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, | |||
592 | inarg.umask = current_umask(); | 582 | inarg.umask = current_umask(); |
593 | args.in.h.opcode = FUSE_MKNOD; | 583 | args.in.h.opcode = FUSE_MKNOD; |
594 | args.in.numargs = 2; | 584 | args.in.numargs = 2; |
595 | args.in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : | 585 | args.in.args[0].size = sizeof(inarg); |
596 | sizeof(inarg); | ||
597 | args.in.args[0].value = &inarg; | 586 | args.in.args[0].value = &inarg; |
598 | args.in.args[1].size = entry->d_name.len + 1; | 587 | args.in.args[1].size = entry->d_name.len + 1; |
599 | args.in.args[1].value = entry->d_name.name; | 588 | args.in.args[1].value = entry->d_name.name; |
@@ -899,10 +888,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
899 | args.in.args[0].size = sizeof(inarg); | 888 | args.in.args[0].size = sizeof(inarg); |
900 | args.in.args[0].value = &inarg; | 889 | args.in.args[0].value = &inarg; |
901 | args.out.numargs = 1; | 890 | args.out.numargs = 1; |
902 | if (fc->minor < 9) | 891 | args.out.args[0].size = sizeof(outarg); |
903 | args.out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | ||
904 | else | ||
905 | args.out.args[0].size = sizeof(outarg); | ||
906 | args.out.args[0].value = &outarg; | 892 | args.out.args[0].value = &outarg; |
907 | err = fuse_simple_request(fc, &args); | 893 | err = fuse_simple_request(fc, &args); |
908 | if (!err) { | 894 | if (!err) { |
@@ -1574,10 +1560,7 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, | |||
1574 | args->in.args[0].size = sizeof(*inarg_p); | 1560 | args->in.args[0].size = sizeof(*inarg_p); |
1575 | args->in.args[0].value = inarg_p; | 1561 | args->in.args[0].value = inarg_p; |
1576 | args->out.numargs = 1; | 1562 | args->out.numargs = 1; |
1577 | if (fc->minor < 9) | 1563 | args->out.args[0].size = sizeof(*outarg_p); |
1578 | args->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | ||
1579 | else | ||
1580 | args->out.args[0].size = sizeof(*outarg_p); | ||
1581 | args->out.args[0].value = outarg_p; | 1564 | args->out.args[0].value = outarg_p; |
1582 | } | 1565 | } |
1583 | 1566 | ||
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e0fc6725d1d0..1cdfb07c1376 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -906,4 +906,6 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc); | |||
906 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | 906 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, |
907 | struct file *file); | 907 | struct file *file); |
908 | 908 | ||
909 | void fuse_set_initialized(struct fuse_conn *fc); | ||
910 | |||
909 | #endif /* _FS_FUSE_I_H */ | 911 | #endif /* _FS_FUSE_I_H */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 6749109f255d..f38256e4476e 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -424,8 +424,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
424 | args.in.h.opcode = FUSE_STATFS; | 424 | args.in.h.opcode = FUSE_STATFS; |
425 | args.in.h.nodeid = get_node_id(dentry->d_inode); | 425 | args.in.h.nodeid = get_node_id(dentry->d_inode); |
426 | args.out.numargs = 1; | 426 | args.out.numargs = 1; |
427 | args.out.args[0].size = | 427 | args.out.args[0].size = sizeof(outarg); |
428 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); | ||
429 | args.out.args[0].value = &outarg; | 428 | args.out.args[0].value = &outarg; |
430 | err = fuse_simple_request(fc, &args); | 429 | err = fuse_simple_request(fc, &args); |
431 | if (!err) | 430 | if (!err) |
@@ -898,7 +897,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
898 | fc->max_write = max_t(unsigned, 4096, fc->max_write); | 897 | fc->max_write = max_t(unsigned, 4096, fc->max_write); |
899 | fc->conn_init = 1; | 898 | fc->conn_init = 1; |
900 | } | 899 | } |
901 | fc->initialized = 1; | 900 | fuse_set_initialized(fc); |
902 | wake_up_all(&fc->blocked_waitq); | 901 | wake_up_all(&fc->blocked_waitq); |
903 | } | 902 | } |
904 | 903 | ||