Commit f741a79e982cf56d7584435bad663553ffe6715f

Authored by Linus Torvalds

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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
  fuse: make fuse_dentry_revalidate() RCU aware
  fuse: make fuse_permission() RCU aware
  fuse: wakeup pollers on connection release/abort
  fuse: reduce size of struct fuse_request

Showing 5 changed files Side-by-side Diff

... ... @@ -305,7 +305,7 @@
305 305 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
306 306 {
307 307 struct cuse_conn *cc = fc_to_cc(fc);
308   - struct cuse_init_out *arg = &req->misc.cuse_init_out;
  308 + struct cuse_init_out *arg = req->out.args[0].value;
309 309 struct page *page = req->pages[0];
310 310 struct cuse_devinfo devinfo = { };
311 311 struct device *dev;
... ... @@ -384,6 +384,7 @@
384 384 dev_set_uevent_suppress(dev, 0);
385 385 kobject_uevent(&dev->kobj, KOBJ_ADD);
386 386 out:
  387 + kfree(arg);
387 388 __free_page(page);
388 389 return;
389 390  
... ... @@ -405,6 +406,7 @@
405 406 struct page *page;
406 407 struct fuse_conn *fc = &cc->fc;
407 408 struct cuse_init_in *arg;
  409 + void *outarg;
408 410  
409 411 BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
410 412  
... ... @@ -419,6 +421,10 @@
419 421 if (!page)
420 422 goto err_put_req;
421 423  
  424 + outarg = kzalloc(sizeof(struct cuse_init_out), GFP_KERNEL);
  425 + if (!outarg)
  426 + goto err_free_page;
  427 +
422 428 arg = &req->misc.cuse_init_in;
423 429 arg->major = FUSE_KERNEL_VERSION;
424 430 arg->minor = FUSE_KERNEL_MINOR_VERSION;
... ... @@ -429,7 +435,7 @@
429 435 req->in.args[0].value = arg;
430 436 req->out.numargs = 2;
431 437 req->out.args[0].size = sizeof(struct cuse_init_out);
432   - req->out.args[0].value = &req->misc.cuse_init_out;
  438 + req->out.args[0].value = outarg;
433 439 req->out.args[1].size = CUSE_INIT_INFO_MAX;
434 440 req->out.argvar = 1;
435 441 req->out.argpages = 1;
... ... @@ -440,6 +446,8 @@
440 446  
441 447 return 0;
442 448  
  449 +err_free_page:
  450 + __free_page(page);
443 451 err_put_req:
444 452 fuse_put_request(fc, req);
445 453 err:
... ... @@ -1910,6 +1910,21 @@
1910 1910 kfree(dequeue_forget(fc, 1, NULL));
1911 1911 }
1912 1912  
  1913 +static void end_polls(struct fuse_conn *fc)
  1914 +{
  1915 + struct rb_node *p;
  1916 +
  1917 + p = rb_first(&fc->polled_files);
  1918 +
  1919 + while (p) {
  1920 + struct fuse_file *ff;
  1921 + ff = rb_entry(p, struct fuse_file, polled_node);
  1922 + wake_up_interruptible_all(&ff->poll_wait);
  1923 +
  1924 + p = rb_next(p);
  1925 + }
  1926 +}
  1927 +
1913 1928 /*
1914 1929 * Abort all requests.
1915 1930 *
... ... @@ -1937,6 +1952,7 @@
1937 1952 fc->blocked = 0;
1938 1953 end_io_requests(fc);
1939 1954 end_queued_requests(fc);
  1955 + end_polls(fc);
1940 1956 wake_up_all(&fc->waitq);
1941 1957 wake_up_all(&fc->blocked_waitq);
1942 1958 kill_fasync(&fc->fasync, SIGIO, POLL_IN);
... ... @@ -1953,6 +1969,7 @@
1953 1969 fc->connected = 0;
1954 1970 fc->blocked = 0;
1955 1971 end_queued_requests(fc);
  1972 + end_polls(fc);
1956 1973 wake_up_all(&fc->blocked_waitq);
1957 1974 spin_unlock(&fc->lock);
1958 1975 fuse_conn_put(fc);
... ... @@ -158,10 +158,7 @@
158 158 {
159 159 struct inode *inode;
160 160  
161   - if (nd && nd->flags & LOOKUP_RCU)
162   - return -ECHILD;
163   -
164   - inode = entry->d_inode;
  161 + inode = ACCESS_ONCE(entry->d_inode);
165 162 if (inode && is_bad_inode(inode))
166 163 return 0;
167 164 else if (fuse_dentry_time(entry) < get_jiffies_64()) {
... ... @@ -177,6 +174,9 @@
177 174 if (!inode)
178 175 return 0;
179 176  
  177 + if (nd->flags & LOOKUP_RCU)
  178 + return -ECHILD;
  179 +
180 180 fc = get_fuse_conn(inode);
181 181 req = fuse_get_req(fc);
182 182 if (IS_ERR(req))
... ... @@ -970,6 +970,14 @@
970 970 return err;
971 971 }
972 972  
  973 +static int fuse_perm_getattr(struct inode *inode, int flags)
  974 +{
  975 + if (flags & IPERM_FLAG_RCU)
  976 + return -ECHILD;
  977 +
  978 + return fuse_do_getattr(inode, NULL, NULL);
  979 +}
  980 +
973 981 /*
974 982 * Check permission. The two basic access models of FUSE are:
975 983 *
... ... @@ -989,9 +997,6 @@
989 997 bool refreshed = false;
990 998 int err = 0;
991 999  
992   - if (flags & IPERM_FLAG_RCU)
993   - return -ECHILD;
994   -
995 1000 if (!fuse_allow_task(fc, current))
996 1001 return -EACCES;
997 1002  
... ... @@ -1000,9 +1005,15 @@
1000 1005 */
1001 1006 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
1002 1007 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
1003   - err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
1004   - if (err)
1005   - return err;
  1008 + struct fuse_inode *fi = get_fuse_inode(inode);
  1009 +
  1010 + if (fi->i_time < get_jiffies_64()) {
  1011 + refreshed = true;
  1012 +
  1013 + err = fuse_perm_getattr(inode, flags);
  1014 + if (err)
  1015 + return err;
  1016 + }
1006 1017 }
1007 1018  
1008 1019 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
... ... @@ -1012,7 +1023,7 @@
1012 1023 attributes. This is also needed, because the root
1013 1024 node will at first have no permissions */
1014 1025 if (err == -EACCES && !refreshed) {
1015   - err = fuse_do_getattr(inode, NULL, NULL);
  1026 + err = fuse_perm_getattr(inode, flags);
1016 1027 if (!err)
1017 1028 err = generic_permission(inode, mask,
1018 1029 flags, NULL);
1019 1030  
... ... @@ -1023,13 +1034,16 @@
1023 1034 noticed immediately, only after the attribute
1024 1035 timeout has expired */
1025 1036 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
  1037 + if (flags & IPERM_FLAG_RCU)
  1038 + return -ECHILD;
  1039 +
1026 1040 err = fuse_access(inode, mask);
1027 1041 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1028 1042 if (!(inode->i_mode & S_IXUGO)) {
1029 1043 if (refreshed)
1030 1044 return -EACCES;
1031 1045  
1032   - err = fuse_do_getattr(inode, NULL, NULL);
  1046 + err = fuse_perm_getattr(inode, flags);
1033 1047 if (!err && !(inode->i_mode & S_IXUGO))
1034 1048 return -EACCES;
1035 1049 }
... ... @@ -222,7 +222,7 @@
222 222 rb_erase(&ff->polled_node, &fc->polled_files);
223 223 spin_unlock(&fc->lock);
224 224  
225   - wake_up_interruptible_sync(&ff->poll_wait);
  225 + wake_up_interruptible_all(&ff->poll_wait);
226 226  
227 227 inarg->fh = ff->fh;
228 228 inarg->flags = flags;
... ... @@ -272,7 +272,6 @@
272 272 struct fuse_init_in init_in;
273 273 struct fuse_init_out init_out;
274 274 struct cuse_init_in cuse_init_in;
275   - struct cuse_init_out cuse_init_out;
276 275 struct {
277 276 struct fuse_read_in in;
278 277 u64 attr_ver;