mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH RFC] Add FAT_IOCTL_GET_VOLUME_ID
@ 2013-07-03  2:19 bintian.wang
  2013-07-03  3:22 ` OGAWA Hirofumi
  0 siblings, 1 reply; 9+ messages in thread
From: bintian.wang @ 2013-07-03  2:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mike Lockwood, dmitry pervushin, Colin Cross,
	Android Kernel Team, OGAWA Hirofumi, Andrew Morton, John Stultz,
	Sean McNeil, Bintian Wang

From: Mike Lockwood <lockwood@android.com>

This patch, originally from Android kernel, adds vfat ioctl command
FAT_IOCTL_GET_VOLUME_ID, with this command we can get the vfat volume ID using
following code:

	ioctl(fd, FAT_IOCTL_GET_VOLUME_ID, &volume_ID)

This patch is a modified version of the patch by Mike Lockwood, with changes
from Dmitry Pervushin, who noticed the original patch makes some volume IDs
abiguous with error returns: for example, if volume id is 0xFFFFFDAD, that
matches -ENOIOCTLCMD, we get "FFFFFFFF" from the user space.

So add a parameter to ioctl to get the correct volume ID.

Android uses vfat volume ID to identify different sd card, when a new sd card
is inserted to device, android can scan the media on it and pop up new contents.

Cc: dmitry pervushin <dpervushin@gmail.com>
Cc: Mike Lockwood <lockwood@android.com>
Cc: Colin Cross <ccross@android.com>
Cc: Android Kernel Team <kernel-team@android.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Sean McNeil <sean@mcneil.com>

Signed-off-by: Bintian Wang <bintian.wang@linaro.org>
---
 fs/fat/fat.h                  |    1 +
 fs/fat/file.c                 |    8 ++++++++
 fs/fat/inode.c                |   12 ++++++++++++
 include/uapi/linux/msdos_fs.h |   10 ++++++++++
 4 files changed, 31 insertions(+)

diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 21664fc..4241e6f 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -86,6 +86,7 @@ struct msdos_sb_info {
 	const void *dir_ops;	      /* Opaque; default directory operations */
 	int dir_per_block;	      /* dir entries per block */
 	int dir_per_block_bits;	      /* log2(dir_per_block) */
+	unsigned int vol_id;		/*volume ID*/
 
 	int fatent_shift;
 	struct fatent_operations *fatent_ops;
diff --git a/fs/fat/file.c b/fs/fat/file.c
index b0b632e..9b104f5 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -114,6 +114,12 @@ out:
 	return err;
 }
 
+static int fat_ioctl_get_volume_id(struct inode *inode, u32 __user *user_attr)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	return put_user(sbi->vol_id, user_attr);
+}
+
 long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
@@ -124,6 +130,8 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return fat_ioctl_get_attributes(inode, user_attr);
 	case FAT_IOCTL_SET_ATTRIBUTES:
 		return fat_ioctl_set_attributes(filp, user_attr);
+	case FAT_IOCTL_GET_VOLUME_ID:
+		return fat_ioctl_get_volume_id(inode, user_attr);
 	default:
 		return -ENOTTY;	/* Inappropriate ioctl for device */
 	}
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 5d4513c..11b51bb 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1415,6 +1415,18 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 		brelse(fsinfo_bh);
 	}
 
+	/* interpret volume ID as a little endian 32 bit integer */
+	if (sbi->fat_bits == 32)
+		sbi->vol_id = (((u32)b->fat32.vol_id[0]) |
+					((u32)b->fat32.vol_id[1] << 8) |
+					((u32)b->fat32.vol_id[2] << 16) |
+					((u32)b->fat32.vol_id[3] << 24));
+	else /* fat 16 or 12 */
+		sbi->vol_id = (((u32)b->fat16.vol_id[0]) |
+					((u32)b->fat16.vol_id[1] << 8) |
+					((u32)b->fat16.vol_id[2] << 16) |
+					((u32)b->fat16.vol_id[3] << 24));
+
 	sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
 	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
diff --git a/include/uapi/linux/msdos_fs.h b/include/uapi/linux/msdos_fs.h
index f055e58..e284ff9 100644
--- a/include/uapi/linux/msdos_fs.h
+++ b/include/uapi/linux/msdos_fs.h
@@ -104,6 +104,8 @@ struct __fat_dirent {
 /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
 #define FAT_IOCTL_GET_ATTRIBUTES	_IOR('r', 0x10, __u32)
 #define FAT_IOCTL_SET_ATTRIBUTES	_IOW('r', 0x11, __u32)
+/*Android kernel has used 0x12, so we use 0x13*/
+#define FAT_IOCTL_GET_VOLUME_ID		_IOR('r', 0x13, __u32)
 
 struct fat_boot_sector {
 	__u8	ignored[3];	/* Boot strap short or near jump */
@@ -128,6 +130,10 @@ struct fat_boot_sector {
 			__u8	drive_number;	/* Physical drive number */
 			__u8	state;		/* undocumented, but used
 						   for mount state. */
+			__u8	signature;  /* extended boot signature */
+			__u8	vol_id[4];	/* volume ID */
+			__u8	vol_label[11];	/* volume label */
+			__u8	fs_type[8];		/* file system type */
 			/* other fiealds are not added here */
 		} fat16;
 
@@ -147,6 +153,10 @@ struct fat_boot_sector {
 			__u8	drive_number;   /* Physical drive number */
 			__u8    state;       	/* undocumented, but used
 						   for mount state. */
+			__u8	signature;  /* extended boot signature */
+			__u8	vol_id[4];	/* volume ID */
+			__u8	vol_label[11];	/* volume label */
+			__u8	fs_type[8];		/* file system type */
 			/* other fiealds are not added here */
 		} fat32;
 	};
-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 9+ messages in thread
* [PATCH RFC] Add FAT_IOCTL_GET_VOLUME_ID
@ 2013-07-01 11:40 bintian.wang
  2013-07-01 12:00 ` OGAWA Hirofumi
  0 siblings, 1 reply; 9+ messages in thread
From: bintian.wang @ 2013-07-01 11:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mike Lockwood, dmitry pervushin, Colin Cross,
	Android Kernel Team, OGAWA Hirofumi, Andrew Morton, John Stultz,
	Bintian Wang

From: Mike Lockwood <lockwood@android.com>

Adds vfat ioctl command FAT_IOCTL_GET_VOLUME_ID, with this command 
we can get the vfat volume ID using following code:

	ioctl(fd, FAT_IOCTL_GET_VOLUME_ID, &volume_ID)

This patch is a modified version of the android kernel patch by Mike Lockwood, 
the original patch makes the return value of ioctl() as the volume ID, 
Dmitry Pervushin noticed some volume IDs abiguous with error returns:
for example, if volume id is set to "0xFFFFFDAD", that matches -ENOIOCTLCMD, 
we get a wrong volume ID "0xFFFFFFFF" from the user space.

This patch fixes above bug by adding a parameter to ioctl to get the correct
volume ID.

Cc: dmitry pervushin <dpervushin@gmail.com>
Cc: Mike Lockwood <lockwood@android.com>
Cc: Colin Cross <ccross@android.com>
Cc: Android Kernel Team <kernel-team@android.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: John Stultz <john.stultz@linaro.org>

Signed-off-by: Bintian Wang <bintian.wang@linaro.org>
---
 fs/fat/fat.h                  |    1 +
 fs/fat/file.c                 |    8 ++++++++
 fs/fat/inode.c                |   12 ++++++++++++
 include/uapi/linux/msdos_fs.h |   10 ++++++++++
 4 files changed, 31 insertions(+)

diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 21664fc..4241e6f 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -86,6 +86,7 @@ struct msdos_sb_info {
 	const void *dir_ops;	      /* Opaque; default directory operations */
 	int dir_per_block;	      /* dir entries per block */
 	int dir_per_block_bits;	      /* log2(dir_per_block) */
+	unsigned int vol_id;		/*volume ID*/
 
 	int fatent_shift;
 	struct fatent_operations *fatent_ops;
diff --git a/fs/fat/file.c b/fs/fat/file.c
index b0b632e..ceef10e 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -114,6 +114,12 @@ out:
 	return err;
 }
 
+static unsigned int fat_ioctl_volume_id(struct inode *inode)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	return sbi->vol_id;
+}
+
 long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
@@ -124,6 +130,8 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return fat_ioctl_get_attributes(inode, user_attr);
 	case FAT_IOCTL_SET_ATTRIBUTES:
 		return fat_ioctl_set_attributes(filp, user_attr);
+	case FAT_IOCTL_GET_VOLUME_ID:
+		return put_user(fat_ioctl_volume_id(inode), user_attr);
 	default:
 		return -ENOTTY;	/* Inappropriate ioctl for device */
 	}
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 5d4513c..11b51bb 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1415,6 +1415,18 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 		brelse(fsinfo_bh);
 	}
 
+	/* interpret volume ID as a little endian 32 bit integer */
+	if (sbi->fat_bits == 32)
+		sbi->vol_id = (((u32)b->fat32.vol_id[0]) |
+					((u32)b->fat32.vol_id[1] << 8) |
+					((u32)b->fat32.vol_id[2] << 16) |
+					((u32)b->fat32.vol_id[3] << 24));
+	else /* fat 16 or 12 */
+		sbi->vol_id = (((u32)b->fat16.vol_id[0]) |
+					((u32)b->fat16.vol_id[1] << 8) |
+					((u32)b->fat16.vol_id[2] << 16) |
+					((u32)b->fat16.vol_id[3] << 24));
+
 	sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
 	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
diff --git a/include/uapi/linux/msdos_fs.h b/include/uapi/linux/msdos_fs.h
index f055e58..e284ff9 100644
--- a/include/uapi/linux/msdos_fs.h
+++ b/include/uapi/linux/msdos_fs.h
@@ -104,6 +104,8 @@ struct __fat_dirent {
 /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
 #define FAT_IOCTL_GET_ATTRIBUTES	_IOR('r', 0x10, __u32)
 #define FAT_IOCTL_SET_ATTRIBUTES	_IOW('r', 0x11, __u32)
+/*Android kernel has used 0x12, so we use 0x13*/
+#define FAT_IOCTL_GET_VOLUME_ID		_IOR('r', 0x13, __u32)
 
 struct fat_boot_sector {
 	__u8	ignored[3];	/* Boot strap short or near jump */
@@ -128,6 +130,10 @@ struct fat_boot_sector {
 			__u8	drive_number;	/* Physical drive number */
 			__u8	state;		/* undocumented, but used
 						   for mount state. */
+			__u8	signature;  /* extended boot signature */
+			__u8	vol_id[4];	/* volume ID */
+			__u8	vol_label[11];	/* volume label */
+			__u8	fs_type[8];		/* file system type */
 			/* other fiealds are not added here */
 		} fat16;
 
@@ -147,6 +153,10 @@ struct fat_boot_sector {
 			__u8	drive_number;   /* Physical drive number */
 			__u8    state;       	/* undocumented, but used
 						   for mount state. */
+			__u8	signature;  /* extended boot signature */
+			__u8	vol_id[4];	/* volume ID */
+			__u8	vol_label[11];	/* volume label */
+			__u8	fs_type[8];		/* file system type */
 			/* other fiealds are not added here */
 		} fat32;
 	};
-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 9+ messages in thread
* [PATCH RFC] Add FAT_IOCTL_GET_VOLUME_ID
@ 2013-07-01  2:39 bintian.wang
  2013-07-01  6:12 ` OGAWA Hirofumi
  0 siblings, 1 reply; 9+ messages in thread
From: bintian.wang @ 2013-07-01  2:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: Mike Lockwood, dmitry pervushin, Colin Cross,
	Android Kernel Team, OGAWA Hirofumi, Andrew Morton, John Stultz,
	Bintian Wang

From: Mike Lockwood <lockwood@android.com>

This patch, originally from Android kernel, adds vfat directory ioctl command
FAT_IOCTL_GET_VOLUME_ID, with this command we can get the vfat volume ID using
following code:

	ioctl(dirfd(dir), FAT_IOCTL_GET_VOLUME_ID, &volume_ID)

This patch is a modified version of the patch by Mike Lockwood, with changes
from Dmitry Pervushin, who noticed the original patch makes some volume IDs
abiguous with error returns: for example, if volume id is 0xFFFFFDAD, that
matches -ENOIOCTLCMD, we get "FFFFFFFF" from the user space.

So add a parameter to ioctl to get the correct volume ID.

Cc: dmitry pervushin <dpervushin@gmail.com>
Cc: Mike Lockwood <lockwood@android.com>
Cc: Colin Cross <ccross@android.com>
Cc: Android Kernel Team <kernel-team@android.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: John Stultz <john.stultz@linaro.org>

Signed-off-by: Bintian Wang <bintian.wang@linaro.org>
---
 fs/fat/dir.c                  |   14 ++++++++++++++
 fs/fat/fat.h                  |    1 +
 fs/fat/inode.c                |    9 +++++++++
 include/uapi/linux/msdos_fs.h |   13 +++++++++++++
 4 files changed, 37 insertions(+)

diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 7a6f02c..4c59108 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -776,12 +776,19 @@ static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
 	return ret;
 }
 
+static unsigned int fat_ioctl_volume_id(struct inode *inode)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	return sbi->vol_id;
+}
+
 static long fat_dir_ioctl(struct file *filp, unsigned int cmd,
 			  unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
 	struct __fat_dirent __user *d1 = (struct __fat_dirent __user *)arg;
 	int short_only, both;
+	unsigned int id;
 
 	switch (cmd) {
 	case VFAT_IOCTL_READDIR_SHORT:
@@ -792,6 +799,9 @@ static long fat_dir_ioctl(struct file *filp, unsigned int cmd,
 		short_only = 0;
 		both = 1;
 		break;
+	case FAT_IOCTL_GET_VOLUME_ID:
+		id = fat_ioctl_volume_id(inode);
+		return copy_to_user((unsigned int *)arg, &id, sizeof(id));
 	default:
 		return fat_generic_ioctl(filp, cmd, arg);
 	}
@@ -822,6 +832,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
 	struct inode *inode = file_inode(filp);
 	struct compat_dirent __user *d1 = compat_ptr(arg);
 	int short_only, both;
+	unsigned int id;
 
 	switch (cmd) {
 	case VFAT_IOCTL_READDIR_SHORT32:
@@ -832,6 +843,9 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
 		short_only = 0;
 		both = 1;
 		break;
+	case FAT_IOCTL_GET_VOLUME_ID:
+		id = fat_ioctl_volume_id(inode);
+		return copy_to_user((unsigned int *)arg, &id, sizeof(id));
 	default:
 		return fat_generic_ioctl(filp, cmd, (unsigned long)arg);
 	}
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 21664fc..4241e6f 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -86,6 +86,7 @@ struct msdos_sb_info {
 	const void *dir_ops;	      /* Opaque; default directory operations */
 	int dir_per_block;	      /* dir entries per block */
 	int dir_per_block_bits;	      /* log2(dir_per_block) */
+	unsigned int vol_id;		/*volume ID*/
 
 	int fatent_shift;
 	struct fatent_operations *fatent_ops;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 5d4513c..a14dd4c 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1252,6 +1252,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 	struct inode *fsinfo_inode = NULL;
 	struct buffer_head *bh;
 	struct fat_boot_sector *b;
+	struct fat_boot_bsx *bsx;
 	struct msdos_sb_info *sbi;
 	u16 logical_sector_size;
 	u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
@@ -1398,6 +1399,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 			goto out_fail;
 		}
 
+		bsx = (struct fat_boot_bsx *)(bh->b_data + FAT32_BSX_OFFSET);
+
 		fsinfo = (struct fat_boot_fsinfo *)fsinfo_bh->b_data;
 		if (!IS_FSINFO(fsinfo)) {
 			fat_msg(sb, KERN_WARNING, "Invalid FSINFO signature: "
@@ -1413,8 +1416,14 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
 		}
 
 		brelse(fsinfo_bh);
+	} else {
+		bsx = (struct fat_boot_bsx *)(bh->b_data + FAT16_BSX_OFFSET);
 	}
 
+	/* interpret volume ID as a little endian 32 bit integer */
+	sbi->vol_id = (((u32)bsx->vol_id[0]) | ((u32)bsx->vol_id[1] << 8) |
+		((u32)bsx->vol_id[2] << 16) | ((u32)bsx->vol_id[3] << 24));
+
 	sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
 	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
diff --git a/include/uapi/linux/msdos_fs.h b/include/uapi/linux/msdos_fs.h
index f055e58..be142ee 100644
--- a/include/uapi/linux/msdos_fs.h
+++ b/include/uapi/linux/msdos_fs.h
@@ -104,6 +104,8 @@ struct __fat_dirent {
 /* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
 #define FAT_IOCTL_GET_ATTRIBUTES	_IOR('r', 0x10, __u32)
 #define FAT_IOCTL_SET_ATTRIBUTES	_IOW('r', 0x11, __u32)
+/*Android kernel has used 0x12, so we use 0x13*/
+#define FAT_IOCTL_GET_VOLUME_ID		_IOR('r', 0x13, __u32)
 
 struct fat_boot_sector {
 	__u8	ignored[3];	/* Boot strap short or near jump */
@@ -161,6 +163,17 @@ struct fat_boot_fsinfo {
 	__le32   reserved2[4];
 };
 
+struct fat_boot_bsx {
+	__u8     drive;     /* drive number */
+	__u8     reserved1;
+	__u8     signature; /* extended boot signature */
+	__u8     vol_id[4]; /* volume ID */
+	__u8     vol_label[11]; /* volume label */
+	__u8     type[8];   /* file system type */
+};
+#define FAT16_BSX_OFFSET 36 /* offset of fat_boot_bsx in FAT12 and FAT16 */
+#define FAT32_BSX_OFFSET 64 /* offset of fat_boot_bsx in FAT32 */
+
 struct msdos_dir_entry {
 	__u8	name[MSDOS_NAME];/* name and extension */
 	__u8	attr;		/* attribute bits */
-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-07-03  3:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-03  2:19 [PATCH RFC] Add FAT_IOCTL_GET_VOLUME_ID bintian.wang
2013-07-03  3:22 ` OGAWA Hirofumi
  -- strict thread matches above, loose matches on Subject: below --
2013-07-01 11:40 bintian.wang
2013-07-01 12:00 ` OGAWA Hirofumi
2013-07-01  2:39 bintian.wang
2013-07-01  6:12 ` OGAWA Hirofumi
2013-07-01  6:19   ` OGAWA Hirofumi
     [not found]     ` <CAJ2TvK=SVMfuFw+U46z-iCS1sYZgnmdk+sr30NeNFTayot7g8g@mail.gmail.com>
     [not found]       ` <CAO+d-qrq9XD2d0FtoA7ZkCsSkka0sfgERb-OeNoU2kLXpF+PVA@mail.gmail.com>
2013-07-01  9:29         ` OGAWA Hirofumi
     [not found]           ` <CAO+d-qqs0uUqNcmOhgZdKeaJQxd5y+TyKVFSpgknoUkX2YidfQ@mail.gmail.com>
2013-07-01 11:43             ` OGAWA Hirofumi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®