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

introduce a parallel variant of ->iterate()

New method: ->iterate_shared(). Same arguments as in ->iterate(),
called with the directory locked only shared. Once all filesystems
switch, the old one will be gone.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 61922694 63b6df14

+48 -11
+18
Documentation/filesystems/porting
··· 557 557 will not happen in parallel ("same" in the sense of your ->d_compare()). 558 558 Lookups on different names in the same directory can and do happen in 559 559 parallel now. 560 + -- 561 + [recommended] 562 + ->iterate_shared() is added; it's a parallel variant of ->iterate(). 563 + Exclusion on struct file level is still provided (as well as that 564 + between it and lseek on the same struct file), but if your directory 565 + has been opened several times, you can get these called in parallel. 566 + Exclusion between that method and all directory-modifying ones is 567 + still provided, of course. 568 + 569 + Often enough ->iterate() can serve as ->iterate_shared() without any 570 + changes - it is a read-only operation, after all. If you have any 571 + per-inode or per-dentry in-core data structures modified by ->iterate(), 572 + you might need something to serialize the access to them. If you 573 + do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for 574 + that; look for in-tree examples. 575 + 576 + Old method is only used if the new one is absent; eventually it will 577 + be removed. Switch while you still can; the old one won't stay.
+12 -6
fs/coda/dir.c
··· 424 424 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); 425 425 host_file = cfi->cfi_container; 426 426 427 - if (host_file->f_op->iterate) { 427 + if (host_file->f_op->iterate || host_file->f_op->iterate_shared) { 428 428 struct inode *host_inode = file_inode(host_file); 429 - 430 - inode_lock(host_inode); 431 429 ret = -ENOENT; 432 430 if (!IS_DEADDIR(host_inode)) { 433 - ret = host_file->f_op->iterate(host_file, ctx); 434 - file_accessed(host_file); 431 + if (host_file->f_op->iterate_shared) { 432 + inode_lock_shared(host_inode); 433 + ret = host_file->f_op->iterate_shared(host_file, ctx); 434 + file_accessed(host_file); 435 + inode_unlock_shared(host_inode); 436 + } else { 437 + inode_lock(host_inode); 438 + ret = host_file->f_op->iterate(host_file, ctx); 439 + file_accessed(host_file); 440 + inode_unlock(host_inode); 441 + } 435 442 } 436 - inode_unlock(host_inode); 437 443 return ret; 438 444 } 439 445 /* Venus: we must read Venus dirents from a file */
+1 -1
fs/exportfs/expfs.c
··· 312 312 goto out; 313 313 314 314 error = -EINVAL; 315 - if (!file->f_op->iterate) 315 + if (!file->f_op->iterate && !file->f_op->iterate_shared) 316 316 goto out_close; 317 317 318 318 buffer.sequence = 0;
+16 -4
fs/readdir.c
··· 24 24 int iterate_dir(struct file *file, struct dir_context *ctx) 25 25 { 26 26 struct inode *inode = file_inode(file); 27 + bool shared = false; 27 28 int res = -ENOTDIR; 28 - if (!file->f_op->iterate) 29 + if (file->f_op->iterate_shared) 30 + shared = true; 31 + else if (!file->f_op->iterate) 29 32 goto out; 30 33 31 34 res = security_file_permission(file, MAY_READ); 32 35 if (res) 33 36 goto out; 34 37 35 - inode_lock(inode); 38 + if (shared) 39 + inode_lock_shared(inode); 40 + else 41 + inode_lock(inode); 36 42 // res = mutex_lock_killable(&inode->i_mutex); 37 43 // if (res) 38 44 // goto out; ··· 46 40 res = -ENOENT; 47 41 if (!IS_DEADDIR(inode)) { 48 42 ctx->pos = file->f_pos; 49 - res = file->f_op->iterate(file, ctx); 43 + if (shared) 44 + res = file->f_op->iterate_shared(file, ctx); 45 + else 46 + res = file->f_op->iterate(file, ctx); 50 47 file->f_pos = ctx->pos; 51 48 fsnotify_access(file); 52 49 file_accessed(file); 53 50 } 54 - inode_unlock(inode); 51 + if (shared) 52 + inode_unlock_shared(inode); 53 + else 54 + inode_unlock(inode); 55 55 out: 56 56 return res; 57 57 }
+1
include/linux/fs.h
··· 1674 1674 ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); 1675 1675 ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); 1676 1676 int (*iterate) (struct file *, struct dir_context *); 1677 + int (*iterate_shared) (struct file *, struct dir_context *); 1677 1678 unsigned int (*poll) (struct file *, struct poll_table_struct *); 1678 1679 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 1679 1680 long (*compat_ioctl) (struct file *, unsigned int, unsigned long);