summaryrefslogtreecommitdiff
path: root/fs/super.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-26 11:48:42 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-26 11:48:42 -0700
commitaba16dc5cf9318b4e0fe92f8261779cd9f1d2d77 (patch)
tree1f53d2cee40e82efe6a727208307af475327af9a /fs/super.c
parentc4726e774ed27680c418e138234dfd2b8e1e89ac (diff)
parent1df895190233fcc30d46beca4550bcafb7b959a6 (diff)
Merge branch 'ida-4.19' of git://git.infradead.org/users/willy/linux-dax
Pull IDA updates from Matthew Wilcox: "A better IDA API: id = ida_alloc(ida, GFP_xxx); ida_free(ida, id); rather than the cumbersome ida_simple_get(), ida_simple_remove(). The new IDA API is similar to ida_simple_get() but better named. The internal restructuring of the IDA code removes the bitmap preallocation nonsense. I hope the net -200 lines of code is convincing" * 'ida-4.19' of git://git.infradead.org/users/willy/linux-dax: (29 commits) ida: Change ida_get_new_above to return the id ida: Remove old API test_ida: check_ida_destroy and check_ida_alloc test_ida: Convert check_ida_conv to new API test_ida: Move ida_check_max test_ida: Move ida_check_leaf idr-test: Convert ida_check_nomem to new API ida: Start new test_ida module target/iscsi: Allocate session IDs from an IDA iscsi target: fix session creation failure handling drm/vmwgfx: Convert to new IDA API dmaengine: Convert to new IDA API ppc: Convert vas ID allocation to new IDA API media: Convert entity ID allocation to new IDA API ppc: Convert mmu context allocation to new IDA API Convert net_namespace to new IDA API cb710: Convert to new IDA API rsxx: Convert to new IDA API osd: Convert to new IDA API sd: Convert to new IDA API ...
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c67
1 files changed, 24 insertions, 43 deletions
diff --git a/fs/super.c b/fs/super.c
index 7429588d6b49..f3a8c008e164 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -981,58 +981,42 @@ void emergency_thaw_all(void)
}
}
-/*
- * Unnamed block devices are dummy devices used by virtual
- * filesystems which don't use real block-devices. -- jrs
- */
-
static DEFINE_IDA(unnamed_dev_ida);
-static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
-/* Many userspace utilities consider an FSID of 0 invalid.
- * Always return at least 1 from get_anon_bdev.
- */
-static int unnamed_dev_start = 1;
+/**
+ * get_anon_bdev - Allocate a block device for filesystems which don't have one.
+ * @p: Pointer to a dev_t.
+ *
+ * Filesystems which don't use real block devices can call this function
+ * to allocate a virtual block device.
+ *
+ * Context: Any context. Frequently called while holding sb_lock.
+ * Return: 0 on success, -EMFILE if there are no anonymous bdevs left
+ * or -ENOMEM if memory allocation failed.
+ */
int get_anon_bdev(dev_t *p)
{
int dev;
- int error;
- retry:
- if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0)
- return -ENOMEM;
- spin_lock(&unnamed_dev_lock);
- error = ida_get_new_above(&unnamed_dev_ida, unnamed_dev_start, &dev);
- if (!error)
- unnamed_dev_start = dev + 1;
- spin_unlock(&unnamed_dev_lock);
- if (error == -EAGAIN)
- /* We raced and lost with another CPU. */
- goto retry;
- else if (error)
- return -EAGAIN;
-
- if (dev >= (1 << MINORBITS)) {
- spin_lock(&unnamed_dev_lock);
- ida_remove(&unnamed_dev_ida, dev);
- if (unnamed_dev_start > dev)
- unnamed_dev_start = dev;
- spin_unlock(&unnamed_dev_lock);
- return -EMFILE;
- }
- *p = MKDEV(0, dev & MINORMASK);
+ /*
+ * Many userspace utilities consider an FSID of 0 invalid.
+ * Always return at least 1 from get_anon_bdev.
+ */
+ dev = ida_alloc_range(&unnamed_dev_ida, 1, (1 << MINORBITS) - 1,
+ GFP_ATOMIC);
+ if (dev == -ENOSPC)
+ dev = -EMFILE;
+ if (dev < 0)
+ return dev;
+
+ *p = MKDEV(0, dev);
return 0;
}
EXPORT_SYMBOL(get_anon_bdev);
void free_anon_bdev(dev_t dev)
{
- int slot = MINOR(dev);
- spin_lock(&unnamed_dev_lock);
- ida_remove(&unnamed_dev_ida, slot);
- if (slot < unnamed_dev_start)
- unnamed_dev_start = slot;
- spin_unlock(&unnamed_dev_lock);
+ ida_free(&unnamed_dev_ida, MINOR(dev));
}
EXPORT_SYMBOL(free_anon_bdev);
@@ -1040,7 +1024,6 @@ int set_anon_super(struct super_block *s, void *data)
{
return get_anon_bdev(&s->s_dev);
}
-
EXPORT_SYMBOL(set_anon_super);
void kill_anon_super(struct super_block *sb)
@@ -1049,7 +1032,6 @@ void kill_anon_super(struct super_block *sb)
generic_shutdown_super(sb);
free_anon_bdev(dev);
}
-
EXPORT_SYMBOL(kill_anon_super);
void kill_litter_super(struct super_block *sb)
@@ -1058,7 +1040,6 @@ void kill_litter_super(struct super_block *sb)
d_genocide(sb->s_root);
kill_anon_super(sb);
}
-
EXPORT_SYMBOL(kill_litter_super);
static int ns_test_super(struct super_block *sb, void *data)