[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260210222310.357755-3-ethan.ferguson@zetier.com>
Date: Tue, 10 Feb 2026 17:23:10 -0500
From: Ethan Ferguson <ethan.ferguson@...ier.com>
To: hirofumi@...l.parknet.co.jp
Cc: linux-fsdevel@...r.kernel.org,
linux-kernel@...r.kernel.org,
Ethan Ferguson <ethan.ferguson@...ier.com>
Subject: [PATCH 2/2] fat: Add FS_IOC_SETFSLABEL ioctl
Add support for writing to the volume label of a FAT filesystem via the
FS_IOC_SETFSLABEL ioctl.
Signed-off-by: Ethan Ferguson <ethan.ferguson@...ier.com>
---
fs/fat/dir.c | 22 ++++++++++++++++++++++
fs/fat/fat.h | 1 +
fs/fat/file.c | 19 +++++++++++++++++++
fs/fat/inode.c | 15 +++++++++++++++
4 files changed, 57 insertions(+)
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 92b091783966..13e87f4c6bf3 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -1423,3 +1423,25 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
return err;
}
EXPORT_SYMBOL_GPL(fat_add_entries);
+
+int fat_rename_volume_label_dentry(struct super_block *sb, char *vol_label)
+{
+ struct inode *root_inode = sb->s_root->d_inode;
+ struct buffer_head *bh;
+ struct msdos_dir_entry *de;
+ loff_t cpos = 0;
+
+ while (1) {
+ if (fat_get_entry(root_inode, &cpos, &bh, &de) == -1)
+ return -ENOENT;
+
+ if (de->attr == ATTR_VOLUME) {
+ memcpy(de->name, vol_label, MSDOS_NAME);
+ mark_inode_dirty(root_inode);
+ return 0;
+ }
+
+ brelse(bh);
+ }
+}
+EXPORT_SYMBOL_GPL(fat_rename_volume_label_dentry);
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index db9c854ddef8..5f1536c21adf 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -341,6 +341,7 @@ extern int fat_alloc_new_dir(struct inode *dir, struct timespec64 *ts);
extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
struct fat_slot_info *sinfo);
extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
+extern int fat_rename_volume_label_dentry(struct super_block *sb, char *vol_label);
/* fat/fatent.c */
struct fat_entry {
diff --git a/fs/fat/file.c b/fs/fat/file.c
index c55a99009a9c..2475a8f58596 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -160,6 +160,23 @@ static int fat_ioctl_get_volume_label(struct inode *inode, char __user *arg)
return copy_to_user(arg, sbi->vol_label, MSDOS_NAME);
}
+static int fat_ioctl_set_volume_label(struct inode *inode, char __user *arg)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+ char new_vol_label[MSDOS_NAME];
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(new_vol_label, arg, MSDOS_NAME))
+ return -EFAULT;
+
+ fat_rename_volume_label_dentry(inode->i_sb, new_vol_label);
+
+ memcpy(sbi->vol_label, new_vol_label, MSDOS_NAME);
+ return 0;
+}
+
long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct inode *inode = file_inode(filp);
@@ -174,6 +191,8 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return fat_ioctl_get_volume_id(inode, user_attr);
case FS_IOC_GETFSLABEL:
return fat_ioctl_get_volume_label(inode, (char __user *) arg);
+ case FS_IOC_SETFSLABEL:
+ return fat_ioctl_set_volume_label(inode, (char __user *) arg);
case FITRIM:
return fat_ioctl_fitrim(inode, arg);
default:
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index f6bd3f079e74..b40abb2b0010 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -736,6 +736,21 @@ static void delayed_free(struct rcu_head *p)
static void fat_put_super(struct super_block *sb)
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh = NULL;
+ struct fat_boot_sector *bs;
+
+ bh = sb_bread(sb, 0);
+ if (bh == NULL)
+ fat_msg(sb, KERN_ERR, "unable to read boot sector");
+ else if (!sb_rdonly(sb)) {
+ bs = (struct fat_boot_sector *)bh->b_data;
+ if (is_fat32(sbi))
+ memcpy(bs->fat32.vol_label, sbi->vol_label, MSDOS_NAME);
+ else
+ memcpy(bs->fat16.vol_label, sbi->vol_label, MSDOS_NAME);
+ mark_buffer_dirty(bh);
+ }
+ brelse(bh);
fat_set_state(sb, 0, 0);
--
2.53.0
Powered by blists - more mailing lists