Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Pull fuse bugfixes from Miklos Szeredi:
"This contains two more fixes by Maxim for writeback/truncate races and
fixes for RCU walk in fuse_dentry_revalidate()"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
fuse: no RCU mode in fuse_access()
fuse: readdirplus: fix RCU walk
fuse: don't check_submounts_and_drop() in RCU walk
fuse: fix fallocate vs. ftruncate race
fuse: wait for writeback in fuse_file_fallocate()

+32 -13
+13 -7
fs/fuse/dir.c
··· 182 182 struct inode *inode; 183 183 struct dentry *parent; 184 184 struct fuse_conn *fc; 185 + struct fuse_inode *fi; 185 186 int ret; 186 187 187 188 inode = ACCESS_ONCE(entry->d_inode); ··· 229 228 if (!err && !outarg.nodeid) 230 229 err = -ENOENT; 231 230 if (!err) { 232 - struct fuse_inode *fi = get_fuse_inode(inode); 231 + fi = get_fuse_inode(inode); 233 232 if (outarg.nodeid != get_node_id(inode)) { 234 233 fuse_queue_forget(fc, forget, outarg.nodeid, 1); 235 234 goto invalid; ··· 247 246 attr_version); 248 247 fuse_change_entry_timeout(entry, &outarg); 249 248 } else if (inode) { 250 - fc = get_fuse_conn(inode); 251 - if (fc->readdirplus_auto) { 249 + fi = get_fuse_inode(inode); 250 + if (flags & LOOKUP_RCU) { 251 + if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 252 + return -ECHILD; 253 + } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 252 254 parent = dget_parent(entry); 253 255 fuse_advise_use_readdirplus(parent->d_inode); 254 256 dput(parent); ··· 263 259 264 260 invalid: 265 261 ret = 0; 266 - if (check_submounts_and_drop(entry) != 0) 262 + 263 + if (!(flags & LOOKUP_RCU) && check_submounts_and_drop(entry) != 0) 267 264 ret = 1; 268 265 goto out; 269 266 } ··· 1068 1063 struct fuse_access_in inarg; 1069 1064 int err; 1070 1065 1066 + BUG_ON(mask & MAY_NOT_BLOCK); 1067 + 1071 1068 if (fc->no_access) 1072 1069 return 0; 1073 1070 ··· 1157 1150 noticed immediately, only after the attribute 1158 1151 timeout has expired */ 1159 1152 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1160 - if (mask & MAY_NOT_BLOCK) 1161 - return -ECHILD; 1162 - 1163 1153 err = fuse_access(inode, mask); 1164 1154 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1165 1155 if (!(inode->i_mode & S_IXUGO)) { ··· 1295 1291 } 1296 1292 1297 1293 found: 1294 + if (fc->readdirplus_auto) 1295 + set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state); 1298 1296 fuse_change_entry_timeout(dentry, o); 1299 1297 1300 1298 err = 0;
+17 -6
fs/fuse/file.c
··· 2467 2467 { 2468 2468 struct fuse_file *ff = file->private_data; 2469 2469 struct inode *inode = file->f_inode; 2470 + struct fuse_inode *fi = get_fuse_inode(inode); 2470 2471 struct fuse_conn *fc = ff->fc; 2471 2472 struct fuse_req *req; 2472 2473 struct fuse_fallocate_in inarg = { ··· 2485 2484 2486 2485 if (lock_inode) { 2487 2486 mutex_lock(&inode->i_mutex); 2488 - if (mode & FALLOC_FL_PUNCH_HOLE) 2489 - fuse_set_nowrite(inode); 2487 + if (mode & FALLOC_FL_PUNCH_HOLE) { 2488 + loff_t endbyte = offset + length - 1; 2489 + err = filemap_write_and_wait_range(inode->i_mapping, 2490 + offset, endbyte); 2491 + if (err) 2492 + goto out; 2493 + 2494 + fuse_sync_writes(inode); 2495 + } 2490 2496 } 2497 + 2498 + if (!(mode & FALLOC_FL_KEEP_SIZE)) 2499 + set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 2491 2500 2492 2501 req = fuse_get_req_nopages(fc); 2493 2502 if (IS_ERR(req)) { ··· 2531 2520 fuse_invalidate_attr(inode); 2532 2521 2533 2522 out: 2534 - if (lock_inode) { 2535 - if (mode & FALLOC_FL_PUNCH_HOLE) 2536 - fuse_release_nowrite(inode); 2523 + if (!(mode & FALLOC_FL_KEEP_SIZE)) 2524 + clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 2525 + 2526 + if (lock_inode) 2537 2527 mutex_unlock(&inode->i_mutex); 2538 - } 2539 2528 2540 2529 return err; 2541 2530 }
+2
fs/fuse/fuse_i.h
··· 115 115 enum { 116 116 /** Advise readdirplus */ 117 117 FUSE_I_ADVISE_RDPLUS, 118 + /** Initialized with readdirplus */ 119 + FUSE_I_INIT_RDPLUS, 118 120 /** An operation changing file size is in progress */ 119 121 FUSE_I_SIZE_UNSTABLE, 120 122 };