Skip to content

Commit ae8c511

Browse files
Kent Overstreetbrauner
authored andcommitted
fs: add FS_IOC_GETFSSYSFSPATH
Add a new ioctl for getting the sysfs name of a filesystem - the path under /sys/fs. This is going to let us standardize exporting data from sysfs across filesystems, e.g. time stats. The returned path will always be of the form "$FSTYP/$SYSFS_IDENTIFIER", where the sysfs identifier may be a UUID (for bcachefs) or a device name (xfs). Cc: Christian Brauner <[email protected]> Cc: Jan Kara <[email protected]> Cc: Dave Chinner <[email protected]> Cc: Darrick J. Wong <[email protected]> Cc: Theodore Ts'o <[email protected]> Cc: Josef Bacik <[email protected]> Signed-off-by: Kent Overstreet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent e2f7dd6 commit ae8c511

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

fs/ioctl.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,20 @@ static int ioctl_getfsuuid(struct file *file, void __user *argp)
776776
return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
777777
}
778778

779+
static int ioctl_get_fs_sysfs_path(struct file *file, void __user *argp)
780+
{
781+
struct super_block *sb = file_inode(file)->i_sb;
782+
783+
if (!strlen(sb->s_sysfs_name))
784+
return -ENOIOCTLCMD;
785+
786+
struct fs_sysfs_path u = {};
787+
788+
u.len = scnprintf(u.name, sizeof(u.name), "%s/%s", sb->s_type->name, sb->s_sysfs_name);
789+
790+
return copy_to_user(argp, &u, sizeof(u)) ? -EFAULT : 0;
791+
}
792+
779793
/*
780794
* do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
781795
* It's just a simple helper for sys_ioctl and compat_sys_ioctl.
@@ -861,6 +875,9 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
861875
case FS_IOC_GETFSUUID:
862876
return ioctl_getfsuuid(filp, argp);
863877

878+
case FS_IOC_GETFSSYSFSPATH:
879+
return ioctl_get_fs_sysfs_path(filp, argp);
880+
864881
default:
865882
if (S_ISREG(inode->i_mode))
866883
return file_ioctl(filp, cmd, argp);

include/linux/fs.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,10 +1255,23 @@ struct super_block {
12551255
struct fsnotify_mark_connector __rcu *s_fsnotify_marks;
12561256
#endif
12571257

1258+
/*
1259+
* q: why are s_id and s_sysfs_name not the same? both are human
1260+
* readable strings that identify the filesystem
1261+
* a: s_id is allowed to change at runtime; it's used in log messages,
1262+
* and we want to when a device starts out as single device (s_id is dev
1263+
* name) but then a device is hot added and we have to switch to
1264+
* identifying it by UUID
1265+
* but s_sysfs_name is a handle for programmatic access, and can't
1266+
* change at runtime
1267+
*/
12581268
char s_id[32]; /* Informational name */
12591269
uuid_t s_uuid; /* UUID */
12601270
u8 s_uuid_len; /* Default 16, possibly smaller for weird filesystems */
12611271

1272+
/* if set, fs shows up under sysfs at /sys/fs/$FSTYP/s_sysfs_name */
1273+
char s_sysfs_name[UUID_STRING_LEN + 1];
1274+
12621275
unsigned int s_max_links;
12631276

12641277
/*
@@ -2541,6 +2554,36 @@ static inline void super_set_uuid(struct super_block *sb, const u8 *uuid, unsign
25412554
memcpy(&sb->s_uuid, uuid, len);
25422555
}
25432556

2557+
/* set sb sysfs name based on sb->s_bdev */
2558+
static inline void super_set_sysfs_name_bdev(struct super_block *sb)
2559+
{
2560+
snprintf(sb->s_sysfs_name, sizeof(sb->s_sysfs_name), "%pg", sb->s_bdev);
2561+
}
2562+
2563+
/* set sb sysfs name based on sb->s_uuid */
2564+
static inline void super_set_sysfs_name_uuid(struct super_block *sb)
2565+
{
2566+
WARN_ON(sb->s_uuid_len != sizeof(sb->s_uuid));
2567+
snprintf(sb->s_sysfs_name, sizeof(sb->s_sysfs_name), "%pU", sb->s_uuid.b);
2568+
}
2569+
2570+
/* set sb sysfs name based on sb->s_id */
2571+
static inline void super_set_sysfs_name_id(struct super_block *sb)
2572+
{
2573+
strscpy(sb->s_sysfs_name, sb->s_id, sizeof(sb->s_sysfs_name));
2574+
}
2575+
2576+
/* try to use something standard before you use this */
2577+
__printf(2, 3)
2578+
static inline void super_set_sysfs_name_generic(struct super_block *sb, const char *fmt, ...)
2579+
{
2580+
va_list args;
2581+
2582+
va_start(args, fmt);
2583+
vsnprintf(sb->s_sysfs_name, sizeof(sb->s_sysfs_name), fmt, args);
2584+
va_end(args);
2585+
}
2586+
25442587
extern int current_umask(void);
25452588

25462589
extern void ihold(struct inode * inode);

include/uapi/linux/fs.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ struct fsuuid2 {
7777
__u8 uuid[16];
7878
};
7979

80+
struct fs_sysfs_path {
81+
__u8 len;
82+
__u8 name[128];
83+
};
84+
8085
/* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */
8186
#define FILE_DEDUPE_RANGE_SAME 0
8287
#define FILE_DEDUPE_RANGE_DIFFERS 1
@@ -230,6 +235,11 @@ struct fsxattr {
230235
#define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX])
231236
/* Returns the external filesystem UUID, the same one blkid returns */
232237
#define FS_IOC_GETFSUUID _IOR(0x15, 0, struct fsuuid2)
238+
/*
239+
* Returns the path component under /sys/fs/ that refers to this filesystem;
240+
* also /sys/kernel/debug/ for filesystems with debugfs exports
241+
*/
242+
#define FS_IOC_GETFSSYSFSPATH _IOR(0x15, 1, struct fs_sysfs_path)
233243

234244
/*
235245
* Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)

0 commit comments

Comments
 (0)