Skip to contentSkip to conversation

Btrfs: add a "df" ioctl for btrfs

PATCH In review Josef Bacik 3 participants 9 messages Jan 12, 2010 – Jan 14, 2010 Btrfs file system

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Btrfs: add a "df" ioctl for btrfs

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

---
 fs/btrfs/ioctl.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/ioctl.h |   15 ++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletions(-)
fs/btrfs/ioctl.c +46 -0
index 9070b86..0b710d5 100644
@@ -1623,6 +1623,50 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
 	return 0;
 }
 
+long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
+{
+	struct btrfs_ioctl_space_args space_args;
+	struct btrfs_ioctl_space_info space;
+	struct btrfs_ioctl_space_info *dest;
+	struct btrfs_space_info *info;
+	int ret = 0;
+
+	if (copy_from_user(&space_args,
+			   (struct btrfs_ioctl_space_args __user *)arg,
+			   sizeof(space_args)))
+		return -EFAULT;
+
+	space_args.total_spaces = 0;
+	dest = (struct btrfs_ioctl_space_info *)
+		(arg + sizeof(struct btrfs_ioctl_space_args));
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(info, &root->fs_info->space_info, list) {
+		if (!space_args.space_slots) {
+			space_args.total_spaces++;
+			continue;
+		}
+		if (space_args.total_spaces >= space_args.space_slots)
+			break;
+		printk("Saving space %llu\n", space_args.total_spaces);
+		space.flags = info->flags;
+		space.total_bytes = info->total_bytes;
+		space.used_bytes = info->bytes_used;
+		if (copy_to_user(dest, &space, sizeof(space))) {
+			ret = -EFAULT;
+			break;
+		}
+		dest++;
+		space_args.total_spaces++;
+	}
+	rcu_read_unlock();
+
+	if (copy_to_user(arg, &space_args, sizeof(space_args)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
 /*
  * there are many ways the trans_start and trans_end ioctls can lead
  * to deadlocks.  They should only be used by applications that
@@ -1691,6 +1735,8 @@ long btrfs_ioctl(struct file *file, unsigned int
 		return btrfs_ioctl_trans_end(file);
 	case BTRFS_IOC_SNAP_LISTING:
 		return btrfs_ioctl_snap_listing(file, argp);
+	case BTRFS_IOC_SPACE_INFO:
+		return btrfs_ioctl_space_info(root, argp);
 	case BTRFS_IOC_SYNC:
 		btrfs_sync_fs(file->f_dentry->d_sb, 1);
 		return 0;
fs/btrfs/ioctl.h +14 -1
index 9e5074c..850e0ee 100644
@@ -54,6 +54,18 @@ struct btrfs_ioctl_subvol_leaf {
 	struct btrfs_ioctl_subvol_items items[];
 };
 
+struct btrfs_ioctl_space_info {
+	u32 flags;
+	u64 total_bytes;
+	u64 used_bytes;
+};
+
+struct btrfs_ioctl_space_args {
+	u64 space_slots;
+	u64 total_spaces;
+	struct btrfs_ioctl_space_info spaces[0];
+};
+
 #define BTRFS_SUBVOL_LEAF_SIZE_MIN sizeof(struct btrfs_ioctl_subvol_leaf) + \
 	sizeof(struct btrfs_ioctl_subvol_items)
 
@@ -97,5 +109,6 @@ struct btrfs_ioctl_clone_range_args {
 #define BTRFS_IOC_SNAP_LISTING _IOWR(BTRFS_IOCTL_MAGIC, 16, \
 				   struct btrfs_ioctl_subvol_args)
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 17, u64)
-
+#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 18, \
+				    struct btrfs_ioctl_space_args)
 #endif
Signature · 1 line
1.5.4.3
#1 lore raw
Quoted 5 lines · Josef Bacik

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

Sorry, here's one without my debugging printk still sitting there. Thanks,

Josef

---
 fs/btrfs/ioctl.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/ioctl.h |   15 ++++++++++++++-
 2 files changed, 59 insertions(+), 1 deletions(-)
fs/btrfs/ioctl.c +45 -0
index 9070b86..7405e42 100644
@@ -1623,6 +1623,49 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
 	return 0;
 }
 
+long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
+{
+	struct btrfs_ioctl_space_args space_args;
+	struct btrfs_ioctl_space_info space;
+	struct btrfs_ioctl_space_info *dest;
+	struct btrfs_space_info *info;
+	int ret = 0;
+
+	if (copy_from_user(&space_args,
+			   (struct btrfs_ioctl_space_args __user *)arg,
+			   sizeof(space_args)))
+		return -EFAULT;
+
+	space_args.total_spaces = 0;
+	dest = (struct btrfs_ioctl_space_info *)
+		(arg + sizeof(struct btrfs_ioctl_space_args));
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(info, &root->fs_info->space_info, list) {
+		if (!space_args.space_slots) {
+			space_args.total_spaces++;
+			continue;
+		}
+		if (space_args.total_spaces >= space_args.space_slots)
+			break;
+		space.flags = info->flags;
+		space.total_bytes = info->total_bytes;
+		space.used_bytes = info->bytes_used;
+		if (copy_to_user(dest, &space, sizeof(space))) {
+			ret = -EFAULT;
+			break;
+		}
+		dest++;
+		space_args.total_spaces++;
+	}
+	rcu_read_unlock();
+
+	if (copy_to_user(arg, &space_args, sizeof(space_args)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
 /*
  * there are many ways the trans_start and trans_end ioctls can lead
  * to deadlocks.  They should only be used by applications that
@@ -1691,6 +1734,8 @@ long btrfs_ioctl(struct file *file, unsigned int
 		return btrfs_ioctl_trans_end(file);
 	case BTRFS_IOC_SNAP_LISTING:
 		return btrfs_ioctl_snap_listing(file, argp);
+	case BTRFS_IOC_SPACE_INFO:
+		return btrfs_ioctl_space_info(root, argp);
 	case BTRFS_IOC_SYNC:
 		btrfs_sync_fs(file->f_dentry->d_sb, 1);
 		return 0;
fs/btrfs/ioctl.h +14 -1
index 9e5074c..850e0ee 100644
@@ -54,6 +54,18 @@ struct btrfs_ioctl_subvol_leaf {
 	struct btrfs_ioctl_subvol_items items[];
 };
 
+struct btrfs_ioctl_space_info {
+	u32 flags;
+	u64 total_bytes;
+	u64 used_bytes;
+};
+
+struct btrfs_ioctl_space_args {
+	u64 space_slots;
+	u64 total_spaces;
+	struct btrfs_ioctl_space_info spaces[0];
+};
+
 #define BTRFS_SUBVOL_LEAF_SIZE_MIN sizeof(struct btrfs_ioctl_subvol_leaf) + \
 	sizeof(struct btrfs_ioctl_subvol_items)
 
@@ -97,5 +109,6 @@ struct btrfs_ioctl_clone_range_args {
 #define BTRFS_IOC_SNAP_LISTING _IOWR(BTRFS_IOCTL_MAGIC, 16, \
 				   struct btrfs_ioctl_subvol_args)
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 17, u64)
-
+#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 18, \
+				    struct btrfs_ioctl_space_args)
 #endif
Signature · 1 line
1.5.4.3
#2 lore raw
In reply to Josef Bacik
Quoted 4 lines · Josef Bacik

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

Just as discussed before I think it's a really bad idea. We always had df reporting inconsistencies due to the way metadata is managed, and btrfs isn't special in that way.

so, NACK

#3 lore raw
Quoted 11 lines · Christoph Hellwig
Quoted 4 lines · Josef Bacik

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

Just as discussed before I think it's a really bad idea. We always had df reporting inconsistencies due to the way metadata is managed, and btrfs isn't special in that way.

so, NACK

Right, this isn't changing how DF works, it just lets me get a better insight into the fs if I need it. It's very helpful to me to see how the fs is broken up and whats in use for debugging ENOSPC things, as well as being nice to have something to show users how their volume is being used.

Think of it more as a debugging thing than a replacement for df :). Thanks,

Josef

#4 lore raw
In reply to Christoph Hellwig
Quoted 9 lines · Christoph Hellwig
Quoted 4 lines · Josef Bacik

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

Just as discussed before I think it's a really bad idea. We always had df reporting inconsistencies due to the way metadata is managed, and btrfs isn't special in that way.

This is more than just df being inaccurate, it's a way to find out how much space is used by each of the raid modes. We've had a ton of feature requests for this, and it really helps identify drives that have a ton of free space tied up for data vs metadata.

-chris

#5 lore raw
Quoted 4 lines · Chris Mason

This is more than just df being inaccurate, it's a way to find out how much space is used by each of the raid modes. We've had a ton of feature requests for this, and it really helps identify drives that have a ton of free space tied up for data vs metadata.

Which again is not a fs specific feature. Much better to add a statfs revision to the core that does this for everone. That would also have the nice side effect that we could actually make it statvfs and could get rid of the braindamage in glibc's current statvfs wrapper.

#6 lore raw
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines · Chris Mason

This is more than just df being inaccurate, it's a way to find out how much space is used by each of the raid modes. We've had a ton of feature requests for this, and it really helps identify drives that have a ton of free space tied up for data vs metadata.

Which again is not a fs specific feature. Much better to add a statfs revision to the core that does this for everone.

Is anyone else splitting metadata and raid levels up like btrfs is? As far as I know we're the only snowflake in the kernel working like this. I'm not against a generic revision, but I think btrfs needs to send out significantly more data than the others.

Quoted 4 lines

That would also
have the nice side effect that we could actually make it statvfs and could get rid of the braindamage in glibc's current statvfs wrapper.

-chris

#7 lore raw
In reply to Josef Bacik
Quoted 10 lines · Josef Bacik

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

fs/btrfs/ioctl.h +0 -0
index 9e5074c..850e0ee 100644

fs/btrfs/ioctl.h struct btrfs_ioctl_subvol_leaf { · line 61

Quoted 8 lines
fs/btrfs/ioctl.h +5 -0
@@ -54,6 +54,18 @@ struct btrfs_ioctl_subvol_leaf {
 	struct btrfs_ioctl_subvol_items items[];
 };
 
+struct btrfs_ioctl_space_info {
+	u32 flags;
+	u64 total_bytes;
+	u64 used_bytes;
+};

Could you please bump that u32 to a u64?

-chris

#8 lore raw
Quoted 14 lines · Chris Mason
Quoted 13 lines · Josef Bacik

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

fs/btrfs/ioctl.h +0 -0
index 9e5074c..850e0ee 100644
@@ -54,6 +54,18 @@ struct btrfs_ioctl_subvol_leaf {
 	struct btrfs_ioctl_subvol_items items[];
 };
 
Quoted 8 lines

fs/btrfs/ioctl.h struct btrfs_ioctl_subvol_leaf { · line 61

Quoted 5 lines
fs/btrfs/ioctl.h +5 -0
+struct btrfs_ioctl_space_info {
+	u32 flags;
+	u64 total_bytes;
+	u64 used_bytes;
+};

Could you please bump that u32 to a u64?

Here you are, sorry about that. Thanks,

Josef

Quoted 1 line

From 6c486aea6268c2e214ba3c73cb2bb1422335c84b Mon Sep 17 00:00:00 2001

From: Josef Bacik <[email protected]>
Date: Wed, 13 Jan 2010 13:02:59 -0500
Subject: [PATCH] Btrfs: add a "df" ioctl for btrfs

df is a very loaded question in btrfs. This gives us a way to get the per-space usage information so we can tell exactly what is in use where. This will help us figure out ENOSPC problems, and help users better understand where their disk space is going.

---
 fs/btrfs/ioctl.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/ioctl.h |   15 ++++++++++++++-
 2 files changed, 59 insertions(+), 1 deletions(-)
fs/btrfs/ioctl.c +45 -0
index 9070b86..7405e42 100644
@@ -1623,6 +1623,49 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
 	return 0;
 }
 
+long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
+{
+	struct btrfs_ioctl_space_args space_args;
+	struct btrfs_ioctl_space_info space;
+	struct btrfs_ioctl_space_info *dest;
+	struct btrfs_space_info *info;
+	int ret = 0;
+
+	if (copy_from_user(&space_args,
+			   (struct btrfs_ioctl_space_args __user *)arg,
+			   sizeof(space_args)))
+		return -EFAULT;
+
+	space_args.total_spaces = 0;
+	dest = (struct btrfs_ioctl_space_info *)
+		(arg + sizeof(struct btrfs_ioctl_space_args));
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(info, &root->fs_info->space_info, list) {
+		if (!space_args.space_slots) {
+			space_args.total_spaces++;
+			continue;
+		}
+		if (space_args.total_spaces >= space_args.space_slots)
+			break;
+		space.flags = info->flags;
+		space.total_bytes = info->total_bytes;
+		space.used_bytes = info->bytes_used;
+		if (copy_to_user(dest, &space, sizeof(space))) {
+			ret = -EFAULT;
+			break;
+		}
+		dest++;
+		space_args.total_spaces++;
+	}
+	rcu_read_unlock();
+
+	if (copy_to_user(arg, &space_args, sizeof(space_args)))
+		ret = -EFAULT;
+
+	return ret;
+}
+
 /*
  * there are many ways the trans_start and trans_end ioctls can lead
  * to deadlocks.  They should only be used by applications that
@@ -1691,6 +1734,8 @@ long btrfs_ioctl(struct file *file, unsigned int
 		return btrfs_ioctl_trans_end(file);
 	case BTRFS_IOC_SNAP_LISTING:
 		return btrfs_ioctl_snap_listing(file, argp);
+	case BTRFS_IOC_SPACE_INFO:
+		return btrfs_ioctl_space_info(root, argp);
 	case BTRFS_IOC_SYNC:
 		btrfs_sync_fs(file->f_dentry->d_sb, 1);
 		return 0;
fs/btrfs/ioctl.h +14 -1
index 9e5074c..d5a8e7a 100644
@@ -54,6 +54,18 @@ struct btrfs_ioctl_subvol_leaf {
 	struct btrfs_ioctl_subvol_items items[];
 };
 
+struct btrfs_ioctl_space_info {
+	u64 flags;
+	u64 total_bytes;
+	u64 used_bytes;
+};
+
+struct btrfs_ioctl_space_args {
+	u64 space_slots;
+	u64 total_spaces;
+	struct btrfs_ioctl_space_info spaces[0];
+};
+
 #define BTRFS_SUBVOL_LEAF_SIZE_MIN sizeof(struct btrfs_ioctl_subvol_leaf) + \
 	sizeof(struct btrfs_ioctl_subvol_items)
 
@@ -97,5 +109,6 @@ struct btrfs_ioctl_clone_range_args {
 #define BTRFS_IOC_SNAP_LISTING _IOWR(BTRFS_IOCTL_MAGIC, 16, \
 				   struct btrfs_ioctl_subvol_args)
 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 17, u64)
-
+#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 18, \
+				    struct btrfs_ioctl_space_args)
 #endif
Signature · 1 line
1.5.4.3