Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

romfs: use different way to generate fsid for BLOCK or MTD

Commit 8a59f5d25265 ("fs/romfs: return f_fsid for statfs(2)") generates
a 64bit id from sb->s_bdev->bd_dev. This is only correct when romfs is
defined with CONFIG_ROMFS_ON_BLOCK. If romfs is only defined with
CONFIG_ROMFS_ON_MTD, sb->s_bdev is NULL, referencing sb->s_bdev->bd_dev
will triger an oops.

Richard Weinberger points out that when CONFIG_ROMFS_BACKED_BY_BOTH=y,
both CONFIG_ROMFS_ON_BLOCK and CONFIG_ROMFS_ON_MTD are defined.
Therefore when calling huge_encode_dev() to generate a 64bit id, I use
the follow order to choose parameter,

- CONFIG_ROMFS_ON_BLOCK defined
use sb->s_bdev->bd_dev
- CONFIG_ROMFS_ON_BLOCK undefined and CONFIG_ROMFS_ON_MTD defined
use sb->s_dev when,
- both CONFIG_ROMFS_ON_BLOCK and CONFIG_ROMFS_ON_MTD undefined
leave id as 0

When CONFIG_ROMFS_ON_MTD is defined and sb->s_mtd is not NULL, sb->s_dev
is set to a device ID generated by MTD_BLOCK_MAJOR and mtd index,
otherwise sb->s_dev is 0.

This is a try-best effort to generate a uniq file system ID, if all the
above conditions are not meet, f_fsid of this romfs instance will be 0.
Generally only one romfs can be built on single MTD block device, this
method is enough to identify multiple romfs instances in a computer.

Link: http://lkml.kernel.org/r/1482928596-115155-1-git-send-email-colyli@suse.de
Signed-off-by: Coly Li <colyli@suse.de>
Reported-by: Nong Li <nongli1031@gmail.com>
Tested-by: Nong Li <nongli1031@gmail.com>
Cc: Richard Weinberger <richard.weinberger@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Coly Li and committed by
Linus Torvalds
f598f82e 4180c4c1

+22 -1
+22 -1
fs/romfs/super.c
··· 74 74 #include <linux/highmem.h> 75 75 #include <linux/pagemap.h> 76 76 #include <linux/uaccess.h> 77 + #include <linux/major.h> 77 78 #include "internal.h" 78 79 79 80 static struct kmem_cache *romfs_inode_cachep; ··· 417 416 static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf) 418 417 { 419 418 struct super_block *sb = dentry->d_sb; 420 - u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 419 + u64 id = 0; 420 + 421 + /* When calling huge_encode_dev(), 422 + * use sb->s_bdev->bd_dev when, 423 + * - CONFIG_ROMFS_ON_BLOCK defined 424 + * use sb->s_dev when, 425 + * - CONFIG_ROMFS_ON_BLOCK undefined and 426 + * - CONFIG_ROMFS_ON_MTD defined 427 + * leave id as 0 when, 428 + * - CONFIG_ROMFS_ON_BLOCK undefined and 429 + * - CONFIG_ROMFS_ON_MTD undefined 430 + */ 431 + if (sb->s_bdev) 432 + id = huge_encode_dev(sb->s_bdev->bd_dev); 433 + else if (sb->s_dev) 434 + id = huge_encode_dev(sb->s_dev); 421 435 422 436 buf->f_type = ROMFS_MAGIC; 423 437 buf->f_namelen = ROMFS_MAXFN; ··· 505 489 sb->s_flags |= MS_RDONLY | MS_NOATIME; 506 490 sb->s_op = &romfs_super_ops; 507 491 492 + #ifdef CONFIG_ROMFS_ON_MTD 493 + /* Use same dev ID from the underlying mtdblock device */ 494 + if (sb->s_mtd) 495 + sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index); 496 + #endif 508 497 /* read the image superblock and check it */ 509 498 rsb = kmalloc(512, GFP_KERNEL); 510 499 if (!rsb)