Skip to content

Commit 0108963

Browse files
committed
Merge tag 'v6.5-rc5.vfs.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Fix a wrong check for O_TMPFILE during RESOLVE_CACHED lookup - Clean up directory iterators and clarify file_needs_f_pos_lock() * tag 'v6.5-rc5.vfs.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: fs: rely on ->iterate_shared to determine f_pos locking vfs: get rid of old '->iterate' directory operation proc: fix missing conversion to 'iterate_shared' open: make RESOLVE_CACHED correctly test for O_TMPFILE
2 parents f0ab9f3 + 7d84d1b commit 0108963

File tree

16 files changed

+98
-61
lines changed

16 files changed

+98
-61
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/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ unsigned long __fdget_raw(unsigned int fd)
10491049
static inline bool file_needs_f_pos_lock(struct file *file)
10501050
{
10511051
return (file->f_mode & FMODE_ATOMIC_POS) &&
1052-
(file_count(file) > 1 || S_ISDIR(file_inode(file)->i_mode));
1052+
(file_count(file) > 1 || file->f_op->iterate_shared);
10531053
}
10541054

10551055
unsigned long __fdget_pos(unsigned int fd)

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/open.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
13221322
lookup_flags |= LOOKUP_IN_ROOT;
13231323
if (how->resolve & RESOLVE_CACHED) {
13241324
/* Don't bother even trying for create/truncate/tmpfile open */
1325-
if (flags & (O_TRUNC | O_CREAT | O_TMPFILE))
1325+
if (flags & (O_TRUNC | O_CREAT | __O_TMPFILE))
13261326
return -EAGAIN;
13271327
lookup_flags |= LOOKUP_CACHED;
13281328
}

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,

fs/proc/base.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2817,7 +2817,7 @@ static int proc_##LSM##_attr_dir_iterate(struct file *filp, \
28172817
\
28182818
static const struct file_operations proc_##LSM##_attr_dir_ops = { \
28192819
.read = generic_read_dir, \
2820-
.iterate = proc_##LSM##_attr_dir_iterate, \
2820+
.iterate_shared = proc_##LSM##_attr_dir_iterate, \
28212821
.llseek = default_llseek, \
28222822
}; \
28232823
\

fs/readdir.c

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,53 @@
2424

2525
#include <asm/unaligned.h>
2626

27+
/*
28+
* Some filesystems were never converted to '->iterate_shared()'
29+
* and their directory iterators want the inode lock held for
30+
* writing. This wrapper allows for converting from the shared
31+
* semantics to the exclusive inode use.
32+
*/
33+
int wrap_directory_iterator(struct file *file,
34+
struct dir_context *ctx,
35+
int (*iter)(struct file *, struct dir_context *))
36+
{
37+
struct inode *inode = file_inode(file);
38+
int ret;
39+
40+
/*
41+
* We'd love to have an 'inode_upgrade_trylock()' operation,
42+
* see the comment in mmap_upgrade_trylock() in mm/memory.c.
43+
*
44+
* But considering this is for "filesystems that never got
45+
* converted", it really doesn't matter.
46+
*
47+
* Also note that since we have to return with the lock held
48+
* for reading, we can't use the "killable()" locking here,
49+
* since we do need to get the lock even if we're dying.
50+
*
51+
* We could do the write part killably and then get the read
52+
* lock unconditionally if it mattered, but see above on why
53+
* this does the very simplistic conversion.
54+
*/
55+
up_read(&inode->i_rwsem);
56+
down_write(&inode->i_rwsem);
57+
58+
/*
59+
* Since we dropped the inode lock, we should do the
60+
* DEADDIR test again. See 'iterate_dir()' below.
61+
*
62+
* Note that we don't need to re-do the f_pos games,
63+
* since the file must be locked wrt f_pos anyway.
64+
*/
65+
ret = -ENOENT;
66+
if (!IS_DEADDIR(inode))
67+
ret = iter(file, ctx);
68+
69+
downgrade_write(&inode->i_rwsem);
70+
return ret;
71+
}
72+
EXPORT_SYMBOL(wrap_directory_iterator);
73+
2774
/*
2875
* Note the "unsafe_put_user() semantics: we goto a
2976
* label for errors.
@@ -40,39 +87,28 @@
4087
int iterate_dir(struct file *file, struct dir_context *ctx)
4188
{
4289
struct inode *inode = file_inode(file);
43-
bool shared = false;
4490
int res = -ENOTDIR;
45-
if (file->f_op->iterate_shared)
46-
shared = true;
47-
else if (!file->f_op->iterate)
91+
92+
if (!file->f_op->iterate_shared)
4893
goto out;
4994

5095
res = security_file_permission(file, MAY_READ);
5196
if (res)
5297
goto out;
5398

54-
if (shared)
55-
res = down_read_killable(&inode->i_rwsem);
56-
else
57-
res = down_write_killable(&inode->i_rwsem);
99+
res = down_read_killable(&inode->i_rwsem);
58100
if (res)
59101
goto out;
60102

61103
res = -ENOENT;
62104
if (!IS_DEADDIR(inode)) {
63105
ctx->pos = file->f_pos;
64-
if (shared)
65-
res = file->f_op->iterate_shared(file, ctx);
66-
else
67-
res = file->f_op->iterate(file, ctx);
106+
res = file->f_op->iterate_shared(file, ctx);
68107
file->f_pos = ctx->pos;
69108
fsnotify_access(file);
70109
file_accessed(file);
71110
}
72-
if (shared)
73-
inode_unlock_shared(inode);
74-
else
75-
inode_unlock(inode);
111+
inode_unlock_shared(inode);
76112
out:
77113
return res;
78114
}

fs/vboxsf/dir.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,10 @@ static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx)
179179
return 0;
180180
}
181181

182+
WRAP_DIR_ITER(vboxsf_dir_iterate) // FIXME!
182183
const struct file_operations vboxsf_dir_fops = {
183184
.open = vboxsf_dir_open,
184-
.iterate = vboxsf_dir_iterate,
185+
.iterate_shared = shared_vboxsf_dir_iterate,
185186
.release = vboxsf_dir_release,
186187
.read = generic_read_dir,
187188
.llseek = generic_file_llseek,

include/linux/fs.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1780,7 +1780,6 @@ struct file_operations {
17801780
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
17811781
int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *,
17821782
unsigned int flags);
1783-
int (*iterate) (struct file *, struct dir_context *);
17841783
int (*iterate_shared) (struct file *, struct dir_context *);
17851784
__poll_t (*poll) (struct file *, struct poll_table_struct *);
17861785
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
@@ -1817,6 +1816,13 @@ struct file_operations {
18171816
unsigned int poll_flags);
18181817
} __randomize_layout;
18191818

1819+
/* Wrap a directory iterator that needs exclusive inode access */
1820+
int wrap_directory_iterator(struct file *, struct dir_context *,
1821+
int (*) (struct file *, struct dir_context *));
1822+
#define WRAP_DIR_ITER(x) \
1823+
static int shared_##x(struct file *file , struct dir_context *ctx) \
1824+
{ return wrap_directory_iterator(file, ctx, x); }
1825+
18201826
struct inode_operations {
18211827
struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
18221828
const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);

0 commit comments

Comments
 (0)