Merge tag 'vfs-6.9.uuid' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs uuid updates from Christian Brauner: "This adds two new ioctl()s for getting the filesystem uuid and retrieving the sysfs path based on the path of a mounted filesystem. Getting the filesystem uuid has been implemented in filesystem specific code for a while it's now lifted as a generic ioctl" * tag 'vfs-6.9.uuid' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: xfs: add support for FS_IOC_GETFSSYSFSPATH fs: add FS_IOC_GETFSSYSFSPATH fat: Hook up sb->s_uuid fs: FS_IOC_GETUUID ovl: convert to super_set_uuid() fs: super_set_uuid()
This commit is contained in:
@@ -82,8 +82,9 @@ Code Seq# Include File Comments
|
|||||||
0x10 00-0F drivers/char/s390/vmcp.h
|
0x10 00-0F drivers/char/s390/vmcp.h
|
||||||
0x10 10-1F arch/s390/include/uapi/sclp_ctl.h
|
0x10 10-1F arch/s390/include/uapi/sclp_ctl.h
|
||||||
0x10 20-2F arch/s390/include/uapi/asm/hypfs.h
|
0x10 20-2F arch/s390/include/uapi/asm/hypfs.h
|
||||||
0x12 all linux/fs.h
|
0x12 all linux/fs.h BLK* ioctls
|
||||||
linux/blkpg.h
|
linux/blkpg.h
|
||||||
|
0x15 all linux/fs.h FS_IOC_* ioctls
|
||||||
0x1b all InfiniBand Subsystem
|
0x1b all InfiniBand Subsystem
|
||||||
<http://infiniband.sourceforge.net/>
|
<http://infiniband.sourceforge.net/>
|
||||||
0x20 all drivers/cdrom/cm206.h
|
0x20 all drivers/cdrom/cm206.h
|
||||||
|
|||||||
+1
-1
@@ -5346,7 +5346,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
|||||||
sb->s_qcop = &ext4_qctl_operations;
|
sb->s_qcop = &ext4_qctl_operations;
|
||||||
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
|
sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
|
||||||
#endif
|
#endif
|
||||||
memcpy(&sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
|
super_set_uuid(sb, es->s_uuid, sizeof(es->s_uuid));
|
||||||
|
|
||||||
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
|
INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
|
||||||
mutex_init(&sbi->s_orphan_lock);
|
mutex_init(&sbi->s_orphan_lock);
|
||||||
|
|||||||
+1
-1
@@ -4496,7 +4496,7 @@ try_onemore:
|
|||||||
sb->s_time_gran = 1;
|
sb->s_time_gran = 1;
|
||||||
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
|
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
|
||||||
(test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0);
|
(test_opt(sbi, POSIX_ACL) ? SB_POSIXACL : 0);
|
||||||
memcpy(&sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid));
|
super_set_uuid(sb, (void *) raw_super->uuid, sizeof(raw_super->uuid));
|
||||||
sb->s_iflags |= SB_I_CGROUPWB;
|
sb->s_iflags |= SB_I_CGROUPWB;
|
||||||
|
|
||||||
/* init f2fs-specific super block info */
|
/* init f2fs-specific super block info */
|
||||||
|
|||||||
@@ -1762,6 +1762,9 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
|||||||
else /* fat 16 or 12 */
|
else /* fat 16 or 12 */
|
||||||
sbi->vol_id = bpb.fat16_vol_id;
|
sbi->vol_id = bpb.fat16_vol_id;
|
||||||
|
|
||||||
|
__le32 vol_id_le = cpu_to_le32(sbi->vol_id);
|
||||||
|
super_set_uuid(sb, (void *) &vol_id_le, sizeof(vol_id_le));
|
||||||
|
|
||||||
sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
|
sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
|
||||||
sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
|
sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf)
|
|||||||
|
|
||||||
memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
|
memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
|
||||||
memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
|
memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
|
||||||
memcpy(&s->s_uuid, str->sb_uuid, 16);
|
super_set_uuid(s, str->sb_uuid, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+33
@@ -763,6 +763,33 @@ static int ioctl_fssetxattr(struct file *file, void __user *argp)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ioctl_getfsuuid(struct file *file, void __user *argp)
|
||||||
|
{
|
||||||
|
struct super_block *sb = file_inode(file)->i_sb;
|
||||||
|
struct fsuuid2 u = { .len = sb->s_uuid_len, };
|
||||||
|
|
||||||
|
if (!sb->s_uuid_len)
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
memcpy(&u.uuid[0], &sb->s_uuid, sb->s_uuid_len);
|
||||||
|
|
||||||
|
return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
|
||||||
|
{
|
||||||
|
struct super_block *sb = file_inode(file)->i_sb;
|
||||||
|
|
||||||
|
if (!strlen(sb->s_sysfs_name))
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
struct fs_sysfs_path u = {};
|
||||||
|
|
||||||
|
u.len = scnprintf(u.name, sizeof(u.name), "%s/%s", sb->s_type->name, sb->s_sysfs_name);
|
||||||
|
|
||||||
|
return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
|
* do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
|
||||||
* It's just a simple helper for sys_ioctl and compat_sys_ioctl.
|
* It's just a simple helper for sys_ioctl and compat_sys_ioctl.
|
||||||
@@ -845,6 +872,12 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
|
|||||||
case FS_IOC_FSSETXATTR:
|
case FS_IOC_FSSETXATTR:
|
||||||
return ioctl_fssetxattr(filp, argp);
|
return ioctl_fssetxattr(filp, argp);
|
||||||
|
|
||||||
|
case FS_IOC_GETFSUUID:
|
||||||
|
return ioctl_getfsuuid(filp, argp);
|
||||||
|
|
||||||
|
case FS_IOC_GETFSSYSFSPATH:
|
||||||
|
return ioctl_get_fs_sysfs_path(filp, argp);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (S_ISREG(inode->i_mode))
|
if (S_ISREG(inode->i_mode))
|
||||||
return file_ioctl(filp, cmd, argp);
|
return file_ioctl(filp, cmd, argp);
|
||||||
|
|||||||
+3
-1
@@ -358,7 +358,9 @@ int kernfs_get_tree(struct fs_context *fc)
|
|||||||
}
|
}
|
||||||
sb->s_flags |= SB_ACTIVE;
|
sb->s_flags |= SB_ACTIVE;
|
||||||
|
|
||||||
uuid_gen(&sb->s_uuid);
|
uuid_t uuid;
|
||||||
|
uuid_gen(&uuid);
|
||||||
|
super_set_uuid(sb, uuid.b, sizeof(uuid));
|
||||||
|
|
||||||
down_write(&root->kernfs_supers_rwsem);
|
down_write(&root->kernfs_supers_rwsem);
|
||||||
list_add(&info->node, &info->root->supers);
|
list_add(&info->node, &info->root->supers);
|
||||||
|
|||||||
+2
-2
@@ -2027,8 +2027,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
|
|||||||
cbits = le32_to_cpu(di->id2.i_super.s_clustersize_bits);
|
cbits = le32_to_cpu(di->id2.i_super.s_clustersize_bits);
|
||||||
bbits = le32_to_cpu(di->id2.i_super.s_blocksize_bits);
|
bbits = le32_to_cpu(di->id2.i_super.s_blocksize_bits);
|
||||||
sb->s_maxbytes = ocfs2_max_file_offset(bbits, cbits);
|
sb->s_maxbytes = ocfs2_max_file_offset(bbits, cbits);
|
||||||
memcpy(&sb->s_uuid, di->id2.i_super.s_uuid,
|
super_set_uuid(sb, di->id2.i_super.s_uuid,
|
||||||
sizeof(di->id2.i_super.s_uuid));
|
sizeof(di->id2.i_super.s_uuid));
|
||||||
|
|
||||||
osb->osb_dx_mask = (1 << (cbits - bbits)) - 1;
|
osb->osb_dx_mask = (1 << (cbits - bbits)) - 1;
|
||||||
|
|
||||||
|
|||||||
+11
-7
@@ -774,13 +774,14 @@ bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs,
|
|||||||
const struct path *upperpath)
|
const struct path *upperpath)
|
||||||
{
|
{
|
||||||
bool set = false;
|
bool set = false;
|
||||||
|
uuid_t uuid;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
/* Try to load existing persistent uuid */
|
/* Try to load existing persistent uuid */
|
||||||
res = ovl_path_getxattr(ofs, upperpath, OVL_XATTR_UUID, sb->s_uuid.b,
|
res = ovl_path_getxattr(ofs, upperpath, OVL_XATTR_UUID, uuid.b,
|
||||||
UUID_SIZE);
|
UUID_SIZE);
|
||||||
if (res == UUID_SIZE)
|
if (res == UUID_SIZE)
|
||||||
return true;
|
goto set_uuid;
|
||||||
|
|
||||||
if (res != -ENODATA)
|
if (res != -ENODATA)
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -808,17 +809,20 @@ bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generate overlay instance uuid */
|
/* Generate overlay instance uuid */
|
||||||
uuid_gen(&sb->s_uuid);
|
uuid_gen(&uuid);
|
||||||
|
|
||||||
/* Try to store persistent uuid */
|
/* Try to store persistent uuid */
|
||||||
set = true;
|
set = true;
|
||||||
res = ovl_setxattr(ofs, upperpath->dentry, OVL_XATTR_UUID, sb->s_uuid.b,
|
res = ovl_setxattr(ofs, upperpath->dentry, OVL_XATTR_UUID, uuid.b,
|
||||||
UUID_SIZE);
|
UUID_SIZE);
|
||||||
if (res == 0)
|
if (res)
|
||||||
return true;
|
goto fail;
|
||||||
|
|
||||||
|
set_uuid:
|
||||||
|
super_set_uuid(sb, uuid.b, sizeof(uuid));
|
||||||
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
memset(sb->s_uuid.b, 0, UUID_SIZE);
|
|
||||||
ofs->config.uuid = OVL_UUID_NULL;
|
ofs->config.uuid = OVL_UUID_NULL;
|
||||||
pr_warn("failed to %s uuid (%pd2, err=%i); falling back to uuid=null.\n",
|
pr_warn("failed to %s uuid (%pd2, err=%i); falling back to uuid=null.\n",
|
||||||
set ? "set" : "get", upperpath->dentry, res);
|
set ? "set" : "get", upperpath->dentry, res);
|
||||||
|
|||||||
+1
-1
@@ -2246,7 +2246,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
|||||||
goto out_umount;
|
goto out_umount;
|
||||||
}
|
}
|
||||||
|
|
||||||
import_uuid(&sb->s_uuid, c->uuid);
|
super_set_uuid(sb, c->uuid, sizeof(c->uuid));
|
||||||
|
|
||||||
mutex_unlock(&c->umount_mutex);
|
mutex_unlock(&c->umount_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+3
-1
@@ -62,7 +62,7 @@ xfs_uuid_mount(
|
|||||||
int hole, i;
|
int hole, i;
|
||||||
|
|
||||||
/* Publish UUID in struct super_block */
|
/* Publish UUID in struct super_block */
|
||||||
uuid_copy(&mp->m_super->s_uuid, uuid);
|
super_set_uuid(mp->m_super, uuid->b, sizeof(*uuid));
|
||||||
|
|
||||||
if (xfs_has_nouuid(mp))
|
if (xfs_has_nouuid(mp))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -706,6 +706,8 @@ xfs_mountfs(
|
|||||||
/* enable fail_at_unmount as default */
|
/* enable fail_at_unmount as default */
|
||||||
mp->m_fail_unmount = true;
|
mp->m_fail_unmount = true;
|
||||||
|
|
||||||
|
super_set_sysfs_name_id(mp->m_super);
|
||||||
|
|
||||||
error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype,
|
error = xfs_sysfs_init(&mp->m_kobj, &xfs_mp_ktype,
|
||||||
NULL, mp->m_super->s_id);
|
NULL, mp->m_super->s_id);
|
||||||
if (error)
|
if (error)
|
||||||
|
|||||||
@@ -1264,8 +1264,22 @@ struct super_block {
|
|||||||
struct fsnotify_mark_connector __rcu *s_fsnotify_marks;
|
struct fsnotify_mark_connector __rcu *s_fsnotify_marks;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* q: why are s_id and s_sysfs_name not the same? both are human
|
||||||
|
* readable strings that identify the filesystem
|
||||||
|
* a: s_id is allowed to change at runtime; it's used in log messages,
|
||||||
|
* and we want to when a device starts out as single device (s_id is dev
|
||||||
|
* name) but then a device is hot added and we have to switch to
|
||||||
|
* identifying it by UUID
|
||||||
|
* but s_sysfs_name is a handle for programmatic access, and can't
|
||||||
|
* change at runtime
|
||||||
|
*/
|
||||||
char s_id[32]; /* Informational name */
|
char s_id[32]; /* Informational name */
|
||||||
uuid_t s_uuid; /* UUID */
|
uuid_t s_uuid; /* UUID */
|
||||||
|
u8 s_uuid_len; /* Default 16, possibly smaller for weird filesystems */
|
||||||
|
|
||||||
|
/* if set, fs shows up under sysfs at /sys/fs/$FSTYP/s_sysfs_name */
|
||||||
|
char s_sysfs_name[UUID_STRING_LEN + 1];
|
||||||
|
|
||||||
unsigned int s_max_links;
|
unsigned int s_max_links;
|
||||||
|
|
||||||
@@ -2538,6 +2552,44 @@ extern __printf(2, 3)
|
|||||||
int super_setup_bdi_name(struct super_block *sb, char *fmt, ...);
|
int super_setup_bdi_name(struct super_block *sb, char *fmt, ...);
|
||||||
extern int super_setup_bdi(struct super_block *sb);
|
extern int super_setup_bdi(struct super_block *sb);
|
||||||
|
|
||||||
|
static inline void super_set_uuid(struct super_block *sb, const u8 *uuid, unsigned len)
|
||||||
|
{
|
||||||
|
if (WARN_ON(len > sizeof(sb->s_uuid)))
|
||||||
|
len = sizeof(sb->s_uuid);
|
||||||
|
sb->s_uuid_len = len;
|
||||||
|
memcpy(&sb->s_uuid, uuid, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set sb sysfs name based on sb->s_bdev */
|
||||||
|
static inline void super_set_sysfs_name_bdev(struct super_block *sb)
|
||||||
|
{
|
||||||
|
snprintf(sb->s_sysfs_name, sizeof(sb->s_sysfs_name), "%pg", sb->s_bdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set sb sysfs name based on sb->s_uuid */
|
||||||
|
static inline void super_set_sysfs_name_uuid(struct super_block *sb)
|
||||||
|
{
|
||||||
|
WARN_ON(sb->s_uuid_len != sizeof(sb->s_uuid));
|
||||||
|
snprintf(sb->s_sysfs_name, sizeof(sb->s_sysfs_name), "%pU", sb->s_uuid.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set sb sysfs name based on sb->s_id */
|
||||||
|
static inline void super_set_sysfs_name_id(struct super_block *sb)
|
||||||
|
{
|
||||||
|
strscpy(sb->s_sysfs_name, sb->s_id, sizeof(sb->s_sysfs_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to use something standard before you use this */
|
||||||
|
__printf(2, 3)
|
||||||
|
static inline void super_set_sysfs_name_generic(struct super_block *sb, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(sb->s_sysfs_name, sizeof(sb->s_sysfs_name), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
extern int current_umask(void);
|
extern int current_umask(void);
|
||||||
|
|
||||||
extern void ihold(struct inode * inode);
|
extern void ihold(struct inode * inode);
|
||||||
|
|||||||
@@ -64,6 +64,24 @@ struct fstrim_range {
|
|||||||
__u64 minlen;
|
__u64 minlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We include a length field because some filesystems (vfat) have an identifier
|
||||||
|
* that we do want to expose as a UUID, but doesn't have the standard length.
|
||||||
|
*
|
||||||
|
* We use a fixed size buffer beacuse this interface will, by fiat, never
|
||||||
|
* support "UUIDs" longer than 16 bytes; we don't want to force all downstream
|
||||||
|
* users to have to deal with that.
|
||||||
|
*/
|
||||||
|
struct fsuuid2 {
|
||||||
|
__u8 len;
|
||||||
|
__u8 uuid[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_sysfs_path {
|
||||||
|
__u8 len;
|
||||||
|
__u8 name[128];
|
||||||
|
};
|
||||||
|
|
||||||
/* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
|
/* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
|
||||||
#define FILE_DEDUPE_RANGE_SAME 0
|
#define FILE_DEDUPE_RANGE_SAME 0
|
||||||
#define FILE_DEDUPE_RANGE_DIFFERS 1
|
#define FILE_DEDUPE_RANGE_DIFFERS 1
|
||||||
@@ -215,6 +233,13 @@ struct fsxattr {
|
|||||||
#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
|
#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr)
|
||||||
#define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX])
|
#define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX])
|
||||||
#define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX])
|
#define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX])
|
||||||
|
/* Returns the external filesystem UUID, the same one blkid returns */
|
||||||
|
#define FS_IOC_GETFSUUID _IOR(0x15, 0, struct fsuuid2)
|
||||||
|
/*
|
||||||
|
* Returns the path component under /sys/fs/ that refers to this filesystem;
|
||||||
|
* also /sys/kernel/debug/ for filesystems with debugfs exports
|
||||||
|
*/
|
||||||
|
#define FS_IOC_GETFSSYSFSPATH _IOR(0x15, 1, struct fs_sysfs_path)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
|
* Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)
|
||||||
|
|||||||
+3
-1
@@ -4355,7 +4355,9 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc)
|
|||||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||||
sb->s_flags |= SB_POSIXACL;
|
sb->s_flags |= SB_POSIXACL;
|
||||||
#endif
|
#endif
|
||||||
uuid_gen(&sb->s_uuid);
|
uuid_t uuid;
|
||||||
|
uuid_gen(&uuid);
|
||||||
|
super_set_uuid(sb, uuid.b, sizeof(uuid));
|
||||||
|
|
||||||
#ifdef CONFIG_TMPFS_QUOTA
|
#ifdef CONFIG_TMPFS_QUOTA
|
||||||
if (ctx->seen & SHMEM_SEEN_QUOTA) {
|
if (ctx->seen & SHMEM_SEEN_QUOTA) {
|
||||||
|
|||||||
Reference in New Issue
Block a user