Skip to content

Commit 3e32715

Browse files
torvaldsbrauner
authored andcommitted
vfs: get rid of old '->iterate' directory operation
All users now just use '->iterate_shared()', which only takes the directory inode lock for reading. Filesystems that never got convered to shared mode now instead use a wrapper that drops the lock, re-takes it in write mode, calls the old function, and then downgrades the lock back to read mode. This way the VFS layer and other callers no longer need to care about filesystems that never got converted to the modern era. The filesystems that use the new wrapper are ceph, coda, exfat, jfs, ntfs, ocfs2, overlayfs, and vboxsf. Honestly, several of them look like they really could just iterate their directories in shared mode and skip the wrapper entirely, but the point of this change is to not change semantics or fix filesystems that haven't been fixed in the last 7+ years, but to finally get rid of the dual iterators. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 0a2c2ba commit 3e32715

File tree

13 files changed

+95
-58
lines changed

13 files changed

+95
-58
lines changed

Documentation/filesystems/locking.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,9 +551,8 @@ mutex or just to use i_size_read() instead.
551551
Note: this does not protect the file->f_pos against concurrent modifications
552552
since this is something the userspace has to take care about.
553553

554-
->iterate() is called with i_rwsem exclusive.
555-
556-
->iterate_shared() is called with i_rwsem at least shared.
554+
->iterate_shared() is called with i_rwsem held for reading, and with the
555+
file f_pos_lock held exclusively
557556

558557
->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
559558
Most instances call fasync_helper(), which does that maintenance, so it's

Documentation/filesystems/porting.rst

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ vfs_readdir() is gone; switch to iterate_dir() instead
537537

538538
**mandatory**
539539

540-
->readdir() is gone now; switch to ->iterate()
540+
->readdir() is gone now; switch to ->iterate_shared()
541541

542542
**mandatory**
543543

@@ -693,24 +693,19 @@ parallel now.
693693

694694
---
695695

696-
**recommended**
696+
**mandatory**
697697

698-
->iterate_shared() is added; it's a parallel variant of ->iterate().
698+
->iterate_shared() is added.
699699
Exclusion on struct file level is still provided (as well as that
700700
between it and lseek on the same struct file), but if your directory
701701
has been opened several times, you can get these called in parallel.
702702
Exclusion between that method and all directory-modifying ones is
703703
still provided, of course.
704704

705-
Often enough ->iterate() can serve as ->iterate_shared() without any
706-
changes - it is a read-only operation, after all. If you have any
707-
per-inode or per-dentry in-core data structures modified by ->iterate(),
708-
you might need something to serialize the access to them. If you
709-
do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for
710-
that; look for in-tree examples.
711-
712-
Old method is only used if the new one is absent; eventually it will
713-
be removed. Switch while you still can; the old one won't stay.
705+
If you have any per-inode or per-dentry in-core data structures modified
706+
by ->iterate_shared(), you might need something to serialize the access
707+
to them. If you do dcache pre-seeding, you'll need to switch to
708+
d_alloc_parallel() for that; look for in-tree examples.
714709

715710
---
716711

@@ -930,9 +925,9 @@ should be done by looking at FMODE_LSEEK in file->f_mode.
930925
filldir_t (readdir callbacks) calling conventions have changed. Instead of
931926
returning 0 or -E... it returns bool now. false means "no more" (as -E... used
932927
to) and true - "keep going" (as 0 in old calling conventions). Rationale:
933-
callers never looked at specific -E... values anyway. ->iterate() and
934-
->iterate_shared() instance require no changes at all, all filldir_t ones in
935-
the tree converted.
928+
callers never looked at specific -E... values anyway. -> iterate_shared()
929+
instances require no changes at all, all filldir_t ones in the tree
930+
converted.
936931

937932
---
938933

fs/ceph/dir.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,9 +2019,10 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
20192019
}
20202020
}
20212021

2022+
WRAP_DIR_ITER(ceph_readdir) // FIXME!
20222023
const struct file_operations ceph_dir_fops = {
20232024
.read = ceph_read_dir,
2024-
.iterate = ceph_readdir,
2025+
.iterate_shared = shared_ceph_readdir,
20252026
.llseek = ceph_dir_llseek,
20262027
.open = ceph_open,
20272028
.release = ceph_release,
@@ -2033,7 +2034,7 @@ const struct file_operations ceph_dir_fops = {
20332034
};
20342035

20352036
const struct file_operations ceph_snapdir_fops = {
2036-
.iterate = ceph_readdir,
2037+
.iterate_shared = shared_ceph_readdir,
20372038
.llseek = ceph_dir_llseek,
20382039
.open = ceph_open,
20392040
.release = ceph_release,

fs/coda/dir.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -429,21 +429,14 @@ static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
429429
cfi = coda_ftoc(coda_file);
430430
host_file = cfi->cfi_container;
431431

432-
if (host_file->f_op->iterate || host_file->f_op->iterate_shared) {
432+
if (host_file->f_op->iterate_shared) {
433433
struct inode *host_inode = file_inode(host_file);
434434
ret = -ENOENT;
435435
if (!IS_DEADDIR(host_inode)) {
436-
if (host_file->f_op->iterate_shared) {
437-
inode_lock_shared(host_inode);
438-
ret = host_file->f_op->iterate_shared(host_file, ctx);
439-
file_accessed(host_file);
440-
inode_unlock_shared(host_inode);
441-
} else {
442-
inode_lock(host_inode);
443-
ret = host_file->f_op->iterate(host_file, ctx);
444-
file_accessed(host_file);
445-
inode_unlock(host_inode);
446-
}
436+
inode_lock_shared(host_inode);
437+
ret = host_file->f_op->iterate_shared(host_file, ctx);
438+
file_accessed(host_file);
439+
inode_unlock_shared(host_inode);
447440
}
448441
return ret;
449442
}
@@ -585,10 +578,11 @@ const struct inode_operations coda_dir_inode_operations = {
585578
.setattr = coda_setattr,
586579
};
587580

581+
WRAP_DIR_ITER(coda_readdir) // FIXME!
588582
const struct file_operations coda_dir_operations = {
589583
.llseek = generic_file_llseek,
590584
.read = generic_read_dir,
591-
.iterate = coda_readdir,
585+
.iterate_shared = shared_coda_readdir,
592586
.open = coda_open,
593587
.release = coda_release,
594588
.fsync = coda_fsync,

fs/exfat/dir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,11 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
306306
return err;
307307
}
308308

309+
WRAP_DIR_ITER(exfat_iterate) // FIXME!
309310
const struct file_operations exfat_dir_operations = {
310311
.llseek = generic_file_llseek,
311312
.read = generic_read_dir,
312-
.iterate = exfat_iterate,
313+
.iterate_shared = shared_exfat_iterate,
313314
.unlocked_ioctl = exfat_ioctl,
314315
#ifdef CONFIG_COMPAT
315316
.compat_ioctl = exfat_compat_ioctl,

fs/exportfs/expfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
315315
goto out;
316316

317317
error = -EINVAL;
318-
if (!file->f_op->iterate && !file->f_op->iterate_shared)
318+
if (!file->f_op->iterate_shared)
319319
goto out_close;
320320

321321
buffer.sequence = 0;

fs/jfs/namei.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,9 +1535,10 @@ const struct inode_operations jfs_dir_inode_operations = {
15351535
#endif
15361536
};
15371537

1538+
WRAP_DIR_ITER(jfs_readdir) // FIXME!
15381539
const struct file_operations jfs_dir_operations = {
15391540
.read = generic_read_dir,
1540-
.iterate = jfs_readdir,
1541+
.iterate_shared = shared_jfs_readdir,
15411542
.fsync = jfs_fsync,
15421543
.unlocked_ioctl = jfs_ioctl,
15431544
.compat_ioctl = compat_ptr_ioctl,

fs/ntfs/dir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1525,10 +1525,11 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
15251525

15261526
#endif /* NTFS_RW */
15271527

1528+
WRAP_DIR_ITER(ntfs_readdir) // FIXME!
15281529
const struct file_operations ntfs_dir_ops = {
15291530
.llseek = generic_file_llseek, /* Seek inside directory. */
15301531
.read = generic_read_dir, /* Return -EISDIR. */
1531-
.iterate = ntfs_readdir, /* Read directory contents. */
1532+
.iterate_shared = shared_ntfs_readdir, /* Read directory contents. */
15321533
#ifdef NTFS_RW
15331534
.fsync = ntfs_dir_fsync, /* Sync a directory to disk. */
15341535
#endif /* NTFS_RW */

fs/ocfs2/file.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,10 +2793,11 @@ const struct file_operations ocfs2_fops = {
27932793
.remap_file_range = ocfs2_remap_file_range,
27942794
};
27952795

2796+
WRAP_DIR_ITER(ocfs2_readdir) // FIXME!
27962797
const struct file_operations ocfs2_dops = {
27972798
.llseek = generic_file_llseek,
27982799
.read = generic_read_dir,
2799-
.iterate = ocfs2_readdir,
2800+
.iterate_shared = shared_ocfs2_readdir,
28002801
.fsync = ocfs2_sync_file,
28012802
.release = ocfs2_dir_release,
28022803
.open = ocfs2_dir_open,
@@ -2842,7 +2843,7 @@ const struct file_operations ocfs2_fops_no_plocks = {
28422843
const struct file_operations ocfs2_dops_no_plocks = {
28432844
.llseek = generic_file_llseek,
28442845
.read = generic_read_dir,
2845-
.iterate = ocfs2_readdir,
2846+
.iterate_shared = shared_ocfs2_readdir,
28462847
.fsync = ocfs2_sync_file,
28472848
.release = ocfs2_dir_release,
28482849
.open = ocfs2_dir_open,

fs/overlayfs/readdir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,10 +954,11 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
954954
return 0;
955955
}
956956

957+
WRAP_DIR_ITER(ovl_iterate) // FIXME!
957958
const struct file_operations ovl_dir_operations = {
958959
.read = generic_read_dir,
959960
.open = ovl_dir_open,
960-
.iterate = ovl_iterate,
961+
.iterate_shared = shared_ovl_iterate,
961962
.llseek = ovl_dir_llseek,
962963
.fsync = ovl_dir_fsync,
963964
.release = ovl_dir_release,

0 commit comments

Comments
 (0)