Merge tag 'vfs-6.16-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs mount updates from Christian Brauner:
 "This contains minor mount updates for this cycle:

   - mnt->mnt_devname can never be NULL so simplify the code handling
     that case

   - Add a comment about concurrent changes during statmount() and
     listmount()

   - Update the STATMOUNT_SUPPORTED macro

   - Convert mount flags to an enum"

* tag 'vfs-6.16-rc1.mount' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  statmount: update STATMOUNT_SUPPORTED macro
  fs: convert mount flags to enum
  ->mnt_devname is never NULL
  mount: add a comment about concurrent changes with statmount()/listmount()
This commit is contained in:
Linus Torvalds
2025-05-26 09:55:56 -07:00
3 changed files with 77 additions and 55 deletions

View File

@@ -355,12 +355,13 @@ static struct mount *alloc_vfsmnt(const char *name)
if (err)
goto out_free_cache;
if (name) {
if (name)
mnt->mnt_devname = kstrdup_const(name,
GFP_KERNEL_ACCOUNT);
if (!mnt->mnt_devname)
goto out_free_id;
}
else
mnt->mnt_devname = "none";
if (!mnt->mnt_devname)
goto out_free_id;
#ifdef CONFIG_SMP
mnt->mnt_pcp = alloc_percpu(struct mnt_pcp);
@@ -1264,7 +1265,7 @@ struct vfsmount *vfs_create_mount(struct fs_context *fc)
if (!fc->root)
return ERR_PTR(-EINVAL);
mnt = alloc_vfsmnt(fc->source ?: "none");
mnt = alloc_vfsmnt(fc->source);
if (!mnt)
return ERR_PTR(-ENOMEM);
@@ -5491,7 +5492,7 @@ static int statmount_sb_source(struct kstatmount *s, struct seq_file *seq)
seq->buf[seq->count] = '\0';
seq->count = start;
seq_commit(seq, string_unescape_inplace(seq->buf + start, UNESCAPE_OCTAL));
} else if (r->mnt_devname) {
} else {
seq_puts(seq, r->mnt_devname);
}
return 0;
@@ -5804,7 +5805,9 @@ static int grab_requested_root(struct mnt_namespace *ns, struct path *root)
STATMOUNT_SB_SOURCE | \
STATMOUNT_OPT_ARRAY | \
STATMOUNT_OPT_SEC_ARRAY | \
STATMOUNT_SUPPORTED_MASK)
STATMOUNT_SUPPORTED_MASK | \
STATMOUNT_MNT_UIDMAP | \
STATMOUNT_MNT_GIDMAP)
static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
struct mnt_namespace *ns)
@@ -5839,13 +5842,29 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
return err;
s->root = root;
s->idmap = mnt_idmap(s->mnt);
if (s->mask & STATMOUNT_SB_BASIC)
statmount_sb_basic(s);
/*
* Note that mount properties in mnt->mnt_flags, mnt->mnt_idmap
* can change concurrently as we only hold the read-side of the
* namespace semaphore and mount properties may change with only
* the mount lock held.
*
* We could sample the mount lock sequence counter to detect
* those changes and retry. But it's not worth it. Worst that
* happens is that the mnt->mnt_idmap pointer is already changed
* while mnt->mnt_flags isn't or vica versa. So what.
*
* Both mnt->mnt_flags and mnt->mnt_idmap are set and retrieved
* via READ_ONCE()/WRITE_ONCE() and guard against theoretical
* torn read/write. That's all we care about right now.
*/
s->idmap = mnt_idmap(s->mnt);
if (s->mask & STATMOUNT_MNT_BASIC)
statmount_mnt_basic(s);
if (s->mask & STATMOUNT_SB_BASIC)
statmount_sb_basic(s);
if (s->mask & STATMOUNT_PROPAGATE_FROM)
statmount_propagate_from(s);
@@ -6157,6 +6176,10 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
return -ENOENT;
/*
* We only need to guard against mount topology changes as
* listmount() doesn't care about any mount properties.
*/
scoped_guard(rwsem_read, &namespace_sem)
ret = do_listmount(ns, kreq.mnt_id, last_mnt_id, kmnt_ids,
nr_mnt_ids, (flags & LISTMOUNT_REVERSE));

View File

@@ -111,7 +111,7 @@ static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
if (err)
goto out;
} else {
mangle(m, r->mnt_devname ? r->mnt_devname : "none");
mangle(m, r->mnt_devname);
}
seq_putc(m, ' ');
/* mountpoints outside of chroot jail will give SEQ_SKIP on this */
@@ -177,7 +177,7 @@ static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
if (err)
goto out;
} else {
mangle(m, r->mnt_devname ? r->mnt_devname : "none");
mangle(m, r->mnt_devname);
}
seq_puts(m, sb_rdonly(sb) ? " ro" : " rw");
err = show_sb_opts(m, sb);
@@ -199,17 +199,13 @@ static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
int err;
/* device */
seq_puts(m, "device ");
if (sb->s_op->show_devname) {
seq_puts(m, "device ");
err = sb->s_op->show_devname(m, mnt_path.dentry);
if (err)
goto out;
} else {
if (r->mnt_devname) {
seq_puts(m, "device ");
mangle(m, r->mnt_devname);
} else
seq_puts(m, "no device");
mangle(m, r->mnt_devname);
}
/* mount point */

View File

@@ -22,48 +22,51 @@ struct fs_context;
struct file;
struct path;
#define MNT_NOSUID 0x01
#define MNT_NODEV 0x02
#define MNT_NOEXEC 0x04
#define MNT_NOATIME 0x08
#define MNT_NODIRATIME 0x10
#define MNT_RELATIME 0x20
#define MNT_READONLY 0x40 /* does the user want this to be r/o? */
#define MNT_NOSYMFOLLOW 0x80
enum mount_flags {
MNT_NOSUID = 0x01,
MNT_NODEV = 0x02,
MNT_NOEXEC = 0x04,
MNT_NOATIME = 0x08,
MNT_NODIRATIME = 0x10,
MNT_RELATIME = 0x20,
MNT_READONLY = 0x40, /* does the user want this to be r/o? */
MNT_NOSYMFOLLOW = 0x80,
#define MNT_SHRINKABLE 0x100
#define MNT_WRITE_HOLD 0x200
MNT_SHRINKABLE = 0x100,
MNT_WRITE_HOLD = 0x200,
#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
/*
* MNT_SHARED_MASK is the set of flags that should be cleared when a
* mount becomes shared. Currently, this is only the flag that says a
* mount cannot be bind mounted, since this is how we create a mount
* that shares events with another mount. If you add a new MNT_*
* flag, consider how it interacts with shared mounts.
*/
#define MNT_SHARED_MASK (MNT_UNBINDABLE)
#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \
| MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \
| MNT_READONLY | MNT_NOSYMFOLLOW)
#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME )
MNT_SHARED = 0x1000, /* if the vfsmount is a shared mount */
MNT_UNBINDABLE = 0x2000, /* if the vfsmount is a unbindable mount */
#define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \
MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED)
MNT_INTERNAL = 0x4000,
#define MNT_INTERNAL 0x4000
MNT_LOCK_ATIME = 0x040000,
MNT_LOCK_NOEXEC = 0x080000,
MNT_LOCK_NOSUID = 0x100000,
MNT_LOCK_NODEV = 0x200000,
MNT_LOCK_READONLY = 0x400000,
MNT_LOCKED = 0x800000,
MNT_DOOMED = 0x1000000,
MNT_SYNC_UMOUNT = 0x2000000,
MNT_MARKED = 0x4000000,
MNT_UMOUNT = 0x8000000,
#define MNT_LOCK_ATIME 0x040000
#define MNT_LOCK_NOEXEC 0x080000
#define MNT_LOCK_NOSUID 0x100000
#define MNT_LOCK_NODEV 0x200000
#define MNT_LOCK_READONLY 0x400000
#define MNT_LOCKED 0x800000
#define MNT_DOOMED 0x1000000
#define MNT_SYNC_UMOUNT 0x2000000
#define MNT_MARKED 0x4000000
#define MNT_UMOUNT 0x8000000
/*
* MNT_SHARED_MASK is the set of flags that should be cleared when a
* mount becomes shared. Currently, this is only the flag that says a
* mount cannot be bind mounted, since this is how we create a mount
* that shares events with another mount. If you add a new MNT_*
* flag, consider how it interacts with shared mounts.
*/
MNT_SHARED_MASK = MNT_UNBINDABLE,
MNT_USER_SETTABLE_MASK = MNT_NOSUID | MNT_NODEV | MNT_NOEXEC
| MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME
| MNT_READONLY | MNT_NOSYMFOLLOW,
MNT_ATIME_MASK = MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME,
MNT_INTERNAL_FLAGS = MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL |
MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED,
};
struct vfsmount {
struct dentry *mnt_root; /* root of the mounted tree */