linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/2] vfs / btrfs: add support for ustat()
@ 2014-07-15 23:07 Luis R. Rodriguez
  2014-07-15 23:07 ` [RFC 1/2] fs/super.c: add new super block sub devices super_block_dev Luis R. Rodriguez
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Luis R. Rodriguez @ 2014-07-15 23:07 UTC (permalink / raw)
  To: viro, clm, jbacik
  Cc: linux-fsdevel, linux-btrfs, linux-kernel, jeffm, fdmanana,
	Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@suse.com>

ustat() does not work for btrfs, the reason is the VFS layer
cannot get to the super block from the anonymous bdevs. The
way these are used within btrfs though are to actually use a
series of them per superblock. This modifies the way the
VFS exposes these bdevs by pegging them onto the super
block on a linked list. This should also allow us to grow
the subdevices on the super block with any other information
that might be better suited underneath so that the VFS
layer is aware. If this approach is reasonable then perhaps
we should next remove the exported symbol for get_anon_bdev()
as btrfs was the only user.

Luis R. Rodriguez (2):
  fs/super.c: add new super block sub devices super_block_dev
  btrfs: use the new VFS super_block_dev

 fs/btrfs/ctree.h   |  7 ++---
 fs/btrfs/disk-io.c | 10 +++---
 fs/btrfs/inode.c   |  2 +-
 fs/super.c         | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/fs.h | 10 ++++++
 5 files changed, 106 insertions(+), 13 deletions(-)

-- 
2.0.1


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

* [RFC 1/2] fs/super.c: add new super block sub devices super_block_dev
  2014-07-15 23:07 [RFC 0/2] vfs / btrfs: add support for ustat() Luis R. Rodriguez
@ 2014-07-15 23:07 ` Luis R. Rodriguez
  2014-07-15 23:07 ` [RFC 2/2] btrfs: use the new VFS super_block_dev Luis R. Rodriguez
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Luis R. Rodriguez @ 2014-07-15 23:07 UTC (permalink / raw)
  To: viro, clm, jbacik
  Cc: linux-fsdevel, linux-btrfs, linux-kernel, jeffm, fdmanana,
	Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@suse.com>

Modern filesystems are using the get_anon_bdev() for
internal notions of volumes, snapshots for a single super block
but never exposing them directly to the VFS layer. While this
works its leaves the VFS layer growing dumb over what filesystems
are doing. This creates a new super block subdevice which we can
use to start stuffing in information about the underlying bdev's
and its associated super block to start off with. This at least
now lets us implement proper support for ustat() once filesystems
are modified to use this data structure and respective helpers.

Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
---
 fs/super.c         | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/fs.h | 10 ++++++
 2 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/fs/super.c b/fs/super.c
index d20d5b1..f96ad1c 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -133,6 +133,90 @@ static unsigned long super_cache_count(struct shrinker *shrink,
 	return total_objects;
 }
 
+static bool super_dev_match(struct super_block *sb, dev_t dev)
+{
+	struct super_block_dev *sbdev;
+
+	if (sb->s_dev == dev)
+		return true;
+
+	if (list_empty(&sb->s_sbdevs))
+		return false;
+
+	list_for_each_entry(sbdev, &sb->s_sbdevs, entry)
+		if (sbdev->anon_dev ==  dev)
+			return true;
+
+	return false;
+}
+
+struct super_block_dev *get_anon_sbdev(struct super_block *sb)
+{
+	struct super_block_dev *sbdev;
+	int ret;
+
+	sbdev = kzalloc(sizeof(struct super_block_dev), GFP_USER);
+	if (!sbdev)
+		return NULL;
+
+	ret = get_anon_bdev(&sbdev->anon_dev);
+	if (ret) {
+		kfree(sbdev);
+		return NULL;
+	}
+
+	sbdev->sb = sb;
+
+	spin_lock(&sb_lock);
+	list_add_tail(&sbdev->entry, &sb->s_sbdevs);
+	spin_unlock(&sb_lock);
+
+	return sbdev;
+}
+EXPORT_SYMBOL_GPL(get_anon_sbdev);
+
+void free_anon_sbdev(struct super_block_dev *sbdev)
+{
+	struct super_block *sb;
+	struct super_block_dev *sbdev_i, *tmp;
+
+	if (!sbdev)
+		return;
+
+	sb = sbdev->sb;
+
+	spin_lock(&sb_lock);
+
+	WARN_ON(list_empty(&sb->s_sbdevs));
+
+	list_for_each_entry_safe(sbdev_i, tmp, &sb->s_sbdevs, entry) {
+		if (sbdev == sbdev_i) {
+			list_del_init(&sbdev_i->entry);
+			break;
+		}
+	}
+
+	spin_unlock(&sb_lock);
+
+	free_anon_bdev(sbdev->anon_dev);
+	kfree(sbdev);
+}
+EXPORT_SYMBOL_GPL(free_anon_sbdev);
+
+static void free_anon_sbdevs(struct super_block *sb)
+{
+	struct super_block_dev *sbdev, *tmp;
+
+	if (list_empty(&sb->s_sbdevs))
+		return;
+
+	list_for_each_entry_safe(sbdev, tmp, &sb->s_sbdevs, entry) {
+		list_del_init(&sbdev->entry);
+		free_anon_bdev(sbdev->anon_dev);
+		kfree(sbdev);
+	}
+}
+
 /**
  *	destroy_super	-	frees a superblock
  *	@s: superblock to free
@@ -150,6 +234,7 @@ static void destroy_super(struct super_block *s)
 	WARN_ON(!list_empty(&s->s_mounts));
 	kfree(s->s_subtype);
 	kfree(s->s_options);
+	free_anon_sbdevs(s);
 	kfree_rcu(s, rcu);
 }
 
@@ -188,6 +273,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
 	INIT_HLIST_NODE(&s->s_instances);
 	INIT_HLIST_BL_HEAD(&s->s_anon);
 	INIT_LIST_HEAD(&s->s_inodes);
+	INIT_LIST_HEAD(&s->s_sbdevs);
 
 	if (list_lru_init(&s->s_dentry_lru))
 		goto fail;
@@ -652,7 +738,7 @@ restart:
 	spin_unlock(&sb_lock);
 	return NULL;
 }
- 
+
 struct super_block *user_get_super(dev_t dev)
 {
 	struct super_block *sb;
@@ -662,7 +748,7 @@ rescan:
 	list_for_each_entry(sb, &super_blocks, s_list) {
 		if (hlist_unhashed(&sb->s_instances))
 			continue;
-		if (sb->s_dev ==  dev) {
+		if (super_dev_match(sb, dev)) {
 			sb->s_count++;
 			spin_unlock(&sb_lock);
 			down_read(&sb->s_umount);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e11d60c..9de1128 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1172,6 +1172,13 @@ struct sb_writers {
 #endif
 };
 
+/* we can expand this to help the VFS layer with modern filesystems */
+struct super_block_dev {
+	struct super_block	*sb;
+	struct list_head	entry;		/* For struct sb->s_sbdevs */
+	dev_t			anon_dev;
+};
+
 struct super_block {
 	struct list_head	s_list;		/* Keep this first */
 	dev_t			s_dev;		/* search index; _not_ kdev_t */
@@ -1196,6 +1203,7 @@ struct super_block {
 
 	struct list_head	s_inodes;	/* all inodes */
 	struct hlist_bl_head	s_anon;		/* anonymous dentries for (nfs) exporting */
+	struct list_head	s_sbdevs;	/* internal fs dev_t */
 	struct list_head	s_mounts;	/* list of mounts; _not_ for fs use */
 	struct block_device	*s_bdev;
 	struct backing_dev_info *s_bdi;
@@ -1796,6 +1804,8 @@ void deactivate_locked_super(struct super_block *sb);
 int set_anon_super(struct super_block *s, void *data);
 int get_anon_bdev(dev_t *);
 void free_anon_bdev(dev_t);
+struct super_block_dev *get_anon_sbdev(struct super_block *sb);
+void free_anon_sbdev(struct super_block_dev *sbdev);
 struct super_block *sget(struct file_system_type *type,
 			int (*test)(struct super_block *,void *),
 			int (*set)(struct super_block *,void *),
-- 
2.0.1


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

* [RFC 2/2] btrfs: use the new VFS super_block_dev
  2014-07-15 23:07 [RFC 0/2] vfs / btrfs: add support for ustat() Luis R. Rodriguez
  2014-07-15 23:07 ` [RFC 1/2] fs/super.c: add new super block sub devices super_block_dev Luis R. Rodriguez
@ 2014-07-15 23:07 ` Luis R. Rodriguez
  2014-07-16  5:29 ` [RFC 0/2] vfs / btrfs: add support for ustat() Christoph Hellwig
  2014-07-16 21:34 ` Luis R. Rodriguez
  3 siblings, 0 replies; 6+ messages in thread
From: Luis R. Rodriguez @ 2014-07-15 23:07 UTC (permalink / raw)
  To: viro, clm, jbacik
  Cc: linux-fsdevel, linux-btrfs, linux-kernel, jeffm, fdmanana,
	Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@suse.com>

Use the new VFS layer struct super_block_dev instead of carrying
the anonymous bdev's on our own. This makes the VFS layer aware of
all of our anonymous dev's on the super block.

Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
---
 fs/btrfs/ctree.h   |  7 ++-----
 fs/btrfs/disk-io.c | 10 +++++-----
 fs/btrfs/inode.c   |  2 +-
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index be91397..34247f6 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1846,11 +1846,8 @@ struct btrfs_root {
 	 * protected by inode_lock
 	 */
 	struct radix_tree_root delayed_nodes_tree;
-	/*
-	 * right now this just gets used so that a root has its own devid
-	 * for stat.  It may be used for more later
-	 */
-	dev_t anon_dev;
+
+	struct super_block_dev *sbdev;
 
 	spinlock_t root_item_lock;
 	atomic_t refs;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8bb4aa1..edc64a8 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1269,7 +1269,6 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 		root->defrag_trans_start = 0;
 	init_completion(&root->kobj_unregister);
 	root->root_key.objectid = objectid;
-	root->anon_dev = 0;
 
 	spin_lock_init(&root->root_item_lock);
 }
@@ -1572,9 +1571,11 @@ int btrfs_init_fs_root(struct btrfs_root *root)
 	spin_lock_init(&root->cache_lock);
 	init_waitqueue_head(&root->cache_wait);
 
-	ret = get_anon_bdev(&root->anon_dev);
-	if (ret)
+	root->sbdev = get_anon_sbdev(root->fs_info->sb);
+	if (!root->sbdev) {
+		ret = -ENOMEM;
 		goto free_writers;
+	}
 	return 0;
 
 free_writers:
@@ -3529,8 +3530,7 @@ static void free_fs_root(struct btrfs_root *root)
 	WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree));
 	btrfs_free_block_rsv(root, root->orphan_block_rsv);
 	root->orphan_block_rsv = NULL;
-	if (root->anon_dev)
-		free_anon_bdev(root->anon_dev);
+	free_anon_sbdev(root->sbdev);
 	if (root->subv_writers)
 		btrfs_free_subvolume_writers(root->subv_writers);
 	free_extent_buffer(root->node);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3668048..41a8bab 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8277,7 +8277,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
 	u32 blocksize = inode->i_sb->s_blocksize;
 
 	generic_fillattr(inode, stat);
-	stat->dev = BTRFS_I(inode)->root->anon_dev;
+	stat->dev = BTRFS_I(inode)->root->sbdev->anon_dev;
 	stat->blksize = PAGE_CACHE_SIZE;
 
 	spin_lock(&BTRFS_I(inode)->lock);
-- 
2.0.1


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

* Re: [RFC 0/2] vfs / btrfs: add support for ustat()
  2014-07-15 23:07 [RFC 0/2] vfs / btrfs: add support for ustat() Luis R. Rodriguez
  2014-07-15 23:07 ` [RFC 1/2] fs/super.c: add new super block sub devices super_block_dev Luis R. Rodriguez
  2014-07-15 23:07 ` [RFC 2/2] btrfs: use the new VFS super_block_dev Luis R. Rodriguez
@ 2014-07-16  5:29 ` Christoph Hellwig
  2014-07-16 19:13   ` Luis R. Rodriguez
  2014-07-16 21:34 ` Luis R. Rodriguez
  3 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2014-07-16  5:29 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: viro, clm, jbacik, linux-fsdevel, linux-btrfs, linux-kernel,
	jeffm, fdmanana, Luis R. Rodriguez

Isn't this the problem again the btrfs uses different assignments for
st_dev than s_dev?  I don't even want to think about a mess like this
before that is fixed.


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

* Re: [RFC 0/2] vfs / btrfs: add support for ustat()
  2014-07-16  5:29 ` [RFC 0/2] vfs / btrfs: add support for ustat() Christoph Hellwig
@ 2014-07-16 19:13   ` Luis R. Rodriguez
  0 siblings, 0 replies; 6+ messages in thread
From: Luis R. Rodriguez @ 2014-07-16 19:13 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Luis R. Rodriguez, viro, clm, jbacik, linux-fsdevel, linux-btrfs,
	linux-kernel, jeffm, fdmanana

[-- Attachment #1: Type: text/plain, Size: 938 bytes --]

On Tue, Jul 15, 2014 at 10:29:19PM -0700, Christoph Hellwig wrote:
> Isn't this the problem again the btrfs uses different assignments for
> st_dev than s_dev?  I don't even want to think about a mess like this
> before that is fixed.

As much as I'd like to see that happen based on discussions so far its unclear
if this is going to be possible unless strong commitment is reached... so what
this tried to do was to take the other way around the problem, by slowly
shifting out junk. Although I'm frankly new to this -- I think this approach might
be more feasible over time. As I see it this is an extension to Al's original
commit 0ee5dc676 but more in line with how they are really are used and exposes
more information to the VFS. As it stands now other filesystems can pop up and
do similar things, this at least extends the original API to fit the use case a
bit more closely to how its used and allows more room to grow.

  Luis

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

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

* Re: [RFC 0/2] vfs / btrfs: add support for ustat()
  2014-07-15 23:07 [RFC 0/2] vfs / btrfs: add support for ustat() Luis R. Rodriguez
                   ` (2 preceding siblings ...)
  2014-07-16  5:29 ` [RFC 0/2] vfs / btrfs: add support for ustat() Christoph Hellwig
@ 2014-07-16 21:34 ` Luis R. Rodriguez
  3 siblings, 0 replies; 6+ messages in thread
From: Luis R. Rodriguez @ 2014-07-16 21:34 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: viro, clm, jbacik, linux-fsdevel, linux-btrfs, linux-kernel,
	jeffm, fdmanana

On Tue, Jul 15, 2014 at 04:07:03PM -0700, Luis R. Rodriguez wrote:
> From: "Luis R. Rodriguez" <mcgrof@suse.com>
> 
> ustat() does not work for btrfs, the reason is the VFS layer
> cannot get to the super block from the anonymous bdevs. The
> way these are used within btrfs though are to actually use a
> series of them per superblock. This modifies the way the
> VFS exposes these bdevs by pegging them onto the super
> block on a linked list. This should also allow us to grow
> the subdevices on the super block with any other information
> that might be better suited underneath so that the VFS
> layer is aware. If this approach is reasonable then perhaps
> we should next remove the exported symbol for get_anon_bdev()
> as btrfs was the only user.
> 

Based on some private review I got this can be simplified leaving
the embedded the struct on the fs data structure and just using
it to expose it on the VFS. Will send a v2.

  Luis

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

end of thread, other threads:[~2014-07-16 21:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-15 23:07 [RFC 0/2] vfs / btrfs: add support for ustat() Luis R. Rodriguez
2014-07-15 23:07 ` [RFC 1/2] fs/super.c: add new super block sub devices super_block_dev Luis R. Rodriguez
2014-07-15 23:07 ` [RFC 2/2] btrfs: use the new VFS super_block_dev Luis R. Rodriguez
2014-07-16  5:29 ` [RFC 0/2] vfs / btrfs: add support for ustat() Christoph Hellwig
2014-07-16 19:13   ` Luis R. Rodriguez
2014-07-16 21:34 ` Luis R. Rodriguez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).