mirror of
https://github.com/torvalds/linux.git
synced 2026-01-25 15:03:52 +08:00
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:
@@ -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));
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user