[PATCH 2/2] fat: Add FS_IOC_SETFSLABEL ioctl

Ethan Ferguson posted 2 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH 2/2] fat: Add FS_IOC_SETFSLABEL ioctl
Posted by Ethan Ferguson 1 month, 2 weeks ago
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@zetier.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
Re: [PATCH 2/2] fat: Add FS_IOC_SETFSLABEL ioctl
Posted by kernel test robot 1 month, 2 weeks ago
Hi Ethan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 9f2693489ef8558240d9e80bfad103650daed0af]

url:    https://github.com/intel-lab-lkp/linux/commits/Ethan-Ferguson/fat-Add-FS_IOC_GETFSLABEL-ioctl/20260211-062606
base:   9f2693489ef8558240d9e80bfad103650daed0af
patch link:    https://lore.kernel.org/r/20260210222310.357755-3-ethan.ferguson%40zetier.com
patch subject: [PATCH 2/2] fat: Add FS_IOC_SETFSLABEL ioctl
config: parisc-defconfig (https://download.01.org/0day-ci/archive/20260211/202602111002.F4q2b5Gx-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260211/202602111002.F4q2b5Gx-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602111002.F4q2b5Gx-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In function 'fat_get_entry',
       inlined from 'fat_rename_volume_label_dentry' at fs/fat/dir.c:1435:7:
>> fs/fat/dir.c:121:12: warning: 'bh' is used uninitialized [-Wuninitialized]
     121 |         if (*bh && *de &&
         |            ^
   fs/fat/dir.c: In function 'fat_rename_volume_label_dentry':
   fs/fat/dir.c:1430:29: note: 'bh' was declared here
    1430 |         struct buffer_head *bh;
         |                             ^~


vim +/bh +121 fs/fat/dir.c

^1da177e4c3f41 Linus Torvalds     2005-04-16  115  
^1da177e4c3f41 Linus Torvalds     2005-04-16  116  static inline int fat_get_entry(struct inode *dir, loff_t *pos,
^1da177e4c3f41 Linus Torvalds     2005-04-16  117  				struct buffer_head **bh,
^1da177e4c3f41 Linus Torvalds     2005-04-16  118  				struct msdos_dir_entry **de)
^1da177e4c3f41 Linus Torvalds     2005-04-16  119  {
^1da177e4c3f41 Linus Torvalds     2005-04-16  120  	/* Fast stuff first */
^1da177e4c3f41 Linus Torvalds     2005-04-16 @121  	if (*bh && *de &&
f08b4988f229fb Cruz Julian Bishop 2012-10-04  122  	   (*de - (struct msdos_dir_entry *)(*bh)->b_data) <
f08b4988f229fb Cruz Julian Bishop 2012-10-04  123  				MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
^1da177e4c3f41 Linus Torvalds     2005-04-16  124  		*pos += sizeof(struct msdos_dir_entry);
^1da177e4c3f41 Linus Torvalds     2005-04-16  125  		(*de)++;
^1da177e4c3f41 Linus Torvalds     2005-04-16  126  		return 0;
^1da177e4c3f41 Linus Torvalds     2005-04-16  127  	}
^1da177e4c3f41 Linus Torvalds     2005-04-16  128  	return fat__get_entry(dir, pos, bh, de);
^1da177e4c3f41 Linus Torvalds     2005-04-16  129  }
^1da177e4c3f41 Linus Torvalds     2005-04-16  130  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki