diff options
author | Matthew Wilcox <willy@infradead.org> | 2018-06-11 12:03:31 -0400 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-08-21 23:54:16 -0400 |
commit | 5a66847e4471be8250da9fadb8d400f1947b9872 (patch) | |
tree | 4c22a9c60caec299102ad83f67a8feabe18655fd | |
parent | 3aed4bc1e591959733b4e939e9965e65ffdff603 (diff) |
fs: Convert unnamed_dev_ida to new API
The new API is much easier for this user. Also add kerneldoc for
get_anon_bdev().
Signed-off-by: Matthew Wilcox <willy@infradead.org>
-rw-r--r-- | fs/super.c | 67 |
1 files changed, 24 insertions, 43 deletions
diff --git a/fs/super.c b/fs/super.c index 50728d9c1a05..5a1b22af82db 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -978,58 +978,42 @@ void emergency_thaw_all(void) | |||
978 | } | 978 | } |
979 | } | 979 | } |
980 | 980 | ||
981 | /* | ||
982 | * Unnamed block devices are dummy devices used by virtual | ||
983 | * filesystems which don't use real block-devices. -- jrs | ||
984 | */ | ||
985 | |||
986 | static DEFINE_IDA(unnamed_dev_ida); | 981 | static DEFINE_IDA(unnamed_dev_ida); |
987 | static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ | ||
988 | /* Many userspace utilities consider an FSID of 0 invalid. | ||
989 | * Always return at least 1 from get_anon_bdev. | ||
990 | */ | ||
991 | static int unnamed_dev_start = 1; | ||
992 | 982 | ||
983 | /** | ||
984 | * get_anon_bdev - Allocate a block device for filesystems which don't have one. | ||
985 | * @p: Pointer to a dev_t. | ||
986 | * | ||
987 | * Filesystems which don't use real block devices can call this function | ||
988 | * to allocate a virtual block device. | ||
989 | * | ||
990 | * Context: Any context. Frequently called while holding sb_lock. | ||
991 | * Return: 0 on success, -EMFILE if there are no anonymous bdevs left | ||
992 | * or -ENOMEM if memory allocation failed. | ||
993 | */ | ||
993 | int get_anon_bdev(dev_t *p) | 994 | int get_anon_bdev(dev_t *p) |
994 | { | 995 | { |
995 | int dev; | 996 | int dev; |
996 | int error; | ||
997 | 997 | ||
998 | retry: | 998 | /* |
999 | if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0) | 999 | * Many userspace utilities consider an FSID of 0 invalid. |
1000 | return -ENOMEM; | 1000 | * Always return at least 1 from get_anon_bdev. |
1001 | spin_lock(&unnamed_dev_lock); | 1001 | */ |
1002 | error = ida_get_new_above(&unnamed_dev_ida, unnamed_dev_start, &dev); | 1002 | dev = ida_alloc_range(&unnamed_dev_ida, 1, (1 << MINORBITS) - 1, |
1003 | if (!error) | 1003 | GFP_ATOMIC); |
1004 | unnamed_dev_start = dev + 1; | 1004 | if (dev == -ENOSPC) |
1005 | spin_unlock(&unnamed_dev_lock); | 1005 | dev = -EMFILE; |
1006 | if (error == -EAGAIN) | 1006 | if (dev < 0) |
1007 | /* We raced and lost with another CPU. */ | 1007 | return dev; |
1008 | goto retry; | 1008 | |
1009 | else if (error) | 1009 | *p = MKDEV(0, dev); |
1010 | return -EAGAIN; | ||
1011 | |||
1012 | if (dev >= (1 << MINORBITS)) { | ||
1013 | spin_lock(&unnamed_dev_lock); | ||
1014 | ida_remove(&unnamed_dev_ida, dev); | ||
1015 | if (unnamed_dev_start > dev) | ||
1016 | unnamed_dev_start = dev; | ||
1017 | spin_unlock(&unnamed_dev_lock); | ||
1018 | return -EMFILE; | ||
1019 | } | ||
1020 | *p = MKDEV(0, dev & MINORMASK); | ||
1021 | return 0; | 1010 | return 0; |
1022 | } | 1011 | } |
1023 | EXPORT_SYMBOL(get_anon_bdev); | 1012 | EXPORT_SYMBOL(get_anon_bdev); |
1024 | 1013 | ||
1025 | void free_anon_bdev(dev_t dev) | 1014 | void free_anon_bdev(dev_t dev) |
1026 | { | 1015 | { |
1027 | int slot = MINOR(dev); | 1016 | ida_free(&unnamed_dev_ida, MINOR(dev)); |
1028 | spin_lock(&unnamed_dev_lock); | ||
1029 | ida_remove(&unnamed_dev_ida, slot); | ||
1030 | if (slot < unnamed_dev_start) | ||
1031 | unnamed_dev_start = slot; | ||
1032 | spin_unlock(&unnamed_dev_lock); | ||
1033 | } | 1017 | } |
1034 | EXPORT_SYMBOL(free_anon_bdev); | 1018 | EXPORT_SYMBOL(free_anon_bdev); |
1035 | 1019 | ||
@@ -1037,7 +1021,6 @@ int set_anon_super(struct super_block *s, void *data) | |||
1037 | { | 1021 | { |
1038 | return get_anon_bdev(&s->s_dev); | 1022 | return get_anon_bdev(&s->s_dev); |
1039 | } | 1023 | } |
1040 | |||
1041 | EXPORT_SYMBOL(set_anon_super); | 1024 | EXPORT_SYMBOL(set_anon_super); |
1042 | 1025 | ||
1043 | void kill_anon_super(struct super_block *sb) | 1026 | void kill_anon_super(struct super_block *sb) |
@@ -1046,7 +1029,6 @@ void kill_anon_super(struct super_block *sb) | |||
1046 | generic_shutdown_super(sb); | 1029 | generic_shutdown_super(sb); |
1047 | free_anon_bdev(dev); | 1030 | free_anon_bdev(dev); |
1048 | } | 1031 | } |
1049 | |||
1050 | EXPORT_SYMBOL(kill_anon_super); | 1032 | EXPORT_SYMBOL(kill_anon_super); |
1051 | 1033 | ||
1052 | void kill_litter_super(struct super_block *sb) | 1034 | void kill_litter_super(struct super_block *sb) |
@@ -1055,7 +1037,6 @@ void kill_litter_super(struct super_block *sb) | |||
1055 | d_genocide(sb->s_root); | 1037 | d_genocide(sb->s_root); |
1056 | kill_anon_super(sb); | 1038 | kill_anon_super(sb); |
1057 | } | 1039 | } |
1058 | |||
1059 | EXPORT_SYMBOL(kill_litter_super); | 1040 | EXPORT_SYMBOL(kill_litter_super); |
1060 | 1041 | ||
1061 | static int ns_test_super(struct super_block *sb, void *data) | 1042 | static int ns_test_super(struct super_block *sb, void *data) |