linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Anand Jain <anand.jain@oracle.com>
To: linux-btrfs@vger.kernel.org
Cc: dsterba@suse.cz, jbacik@fusionio.com
Subject: [PATCH v5 2/3] btrfs-progs: fs show should handle if subvol(s) mounted
Date: Thu, 21 Nov 2013 11:28:41 +0800	[thread overview]
Message-ID: <1385004521-28886-1-git-send-email-anand.jain@oracle.com> (raw)
In-Reply-To: <1384514735-24761-2-git-send-email-anand.jain@oracle.com>

as of now with out this patch user would see
fsinfo per btrfs mount path but which mean multiple
entry if more than one subvol is mounted of the same
fsid. so this patch will handle that nicely.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---

v5: fixup missed mem free, thanks David
v4: rebase on integration-20131114
v3: accepts Josef suggested
v2: accepts Zach suggested

 cmds-filesystem.c |  104 +++++++++++++++++++++++++++++++++-------------------
 utils.c           |   60 ++++++++++++++++++++++++++++++
 utils.h           |    1 +
 3 files changed, 127 insertions(+), 38 deletions(-)

diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index c747193..bb827e1 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -318,6 +318,29 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info,
 	return 0;
 }
 
+static void handle_print(char *mnt, char *label)
+{
+	int fd;
+	struct btrfs_ioctl_fs_info_args fs_info_arg;
+	struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL;
+	struct btrfs_ioctl_space_args *space_info_arg;
+
+	if (get_fs_info(mnt, &fs_info_arg, &dev_info_arg)) {
+		fprintf(stdout, "ERROR: get_fs_info failed\n");
+		return;
+	}
+
+	fd = open(mnt, O_RDONLY);
+	if (fd != -1 && !get_df(fd, &space_info_arg)) {
+		print_one_fs(&fs_info_arg, dev_info_arg,
+				space_info_arg, label, mnt);
+		kfree(space_info_arg);
+	}
+	if (fd != -1)
+		close(fd);
+	kfree(dev_info_arg);
+}
+
 /* This function checks if the given input parameter is
  * an uuid or a path
  * return -1: some error in the given input
@@ -352,53 +375,52 @@ static int check_arg_type(char *input)
 
 static int btrfs_scan_kernel(void *search)
 {
-	int ret = 0, fd;
-	FILE *f;
-	struct mntent *mnt;
-	struct btrfs_ioctl_fs_info_args fs_info_arg;
-	struct btrfs_ioctl_dev_info_args *dev_info_arg = NULL;
-	struct btrfs_ioctl_space_args *space_info_arg;
+	int ret = 0;
 	char label[BTRFS_LABEL_SIZE];
-
-	f = setmntent("/proc/self/mounts", "r");
-	if (f == NULL)
-		return 1;
-
-	memset(label, 0, sizeof(label));
-	while ((mnt = getmntent(f)) != NULL) {
-		if (strcmp(mnt->mnt_type, "btrfs"))
+	char mnt[BTRFS_PATH_NAME_MAX + 1];
+	struct btrfs_ioctl_fslist *fslist;
+	struct btrfs_ioctl_fslist *fslist_saved;
+	u64 cnt_fs;
+	int cnt_mnt;
+	__u8 *fsid;
+	__u64 flags;
+	int found = 0;
+
+	ret = get_fslist(&fslist, &cnt_fs);
+	if (ret)
+		return ret;
+	fslist_saved = fslist;
+	while (cnt_fs--) {
+		fsid = fslist->fsid;
+		flags = fslist->flags;
+		fslist++;
+		if (!(flags & BTRFS_FS_MOUNTED))
 			continue;
-		ret = get_fs_info(mnt->mnt_dir, &fs_info_arg,
-				&dev_info_arg);
+		memset(mnt, 0, BTRFS_PATH_NAME_MAX + 1);
+		memset(label, 0, sizeof(label));
+		ret = fsid_to_mntpt(fsid, mnt, &cnt_mnt);
 		if (ret)
-			return ret;
-
-		if (get_label_mounted(mnt->mnt_dir, label)) {
-			kfree(dev_info_arg);
-			return 1;
+			break;
+		if (get_label_mounted(mnt, label)) {
+			ret = 1;
+			break;
 		}
-		if (search && !match_search_item_kernel(fs_info_arg.fsid,
-					mnt->mnt_dir, label, search)) {
-			kfree(dev_info_arg);
+
+		if (search && !match_search_item_kernel(fsid,
+					mnt, label, search))
 			continue;
-		}
 
-		fd = open(mnt->mnt_dir, O_RDONLY);
-		if ((fd != -1) && !get_df(fd, &space_info_arg)) {
-			print_one_fs(&fs_info_arg, dev_info_arg,
-					space_info_arg, label, mnt->mnt_dir);
-			kfree(space_info_arg);
-			memset(label, 0, sizeof(label));
+		handle_print(mnt, label);
+		if (search) {
+			found = 1;
+			break;
 		}
-		if (fd != -1)
-			close(fd);
-		kfree(dev_info_arg);
-		if (search)
-			return 0;
 	}
-	if (search)
+	if (fslist_saved)
+		kfree(fslist_saved);
+	if (search && !found)
 		return 1;
-	return 0;
+	return ret;
 }
 
 static const char * const cmd_show_usage[] = {
@@ -470,6 +492,12 @@ static int cmd_show(int argc, char **argv)
 				else
 					goto devs_only;
 			}
+		} else if (type == BTRFS_ARG_MNTPOINT) {
+			char label[BTRFS_LABEL_SIZE];
+			if (get_label_mounted(search, label))
+				return 1;
+			handle_print(search, label);
+			return 0;
 		}
 	}
 
diff --git a/utils.c b/utils.c
index 1ed7cde..ddbd623 100644
--- a/utils.c
+++ b/utils.c
@@ -2186,3 +2186,63 @@ out:
 	close(fd);
 	return ret;
 }
+
+/* This finds the mount point for a given fsid,
+ *  subvols of the same fs/fsid can be mounted
+ *  so here this picks and lowest subvol id
+ *  and returns the mount point
+*/
+int fsid_to_mntpt(__u8 *fsid, char *mntpt, int *mnt_cnt)
+{
+	int fd = -1, ret = 0;
+	DIR *dirstream = NULL;
+	FILE *f;
+	struct btrfs_ioctl_fs_info_args fi_args;
+	u64 svid, saved_svid = (u64)-1;
+	struct mntent *mnt;
+	int mcnt = 0;
+
+	*mnt_cnt = 0;
+	f = setmntent("/proc/self/mounts", "r");
+	if (f == NULL)
+		return 1;
+
+	while ((mnt = getmntent(f)) != NULL) {
+		if (strcmp(mnt->mnt_type, "btrfs"))
+			continue;
+		fd = open_file_or_dir(mnt->mnt_dir, &dirstream);
+		if (fd < 0) {
+			ret = -errno;
+			return ret;
+		}
+		ret = ioctl(fd, BTRFS_IOC_FS_INFO, &fi_args);
+		if (ret < 0) {
+			ret = -errno;
+			close_file_or_dir(fd, dirstream);
+			break;
+		}
+		if (uuid_compare(fsid, fi_args.fsid)) {
+			close_file_or_dir(fd, dirstream);
+			continue;
+		}
+
+		/* found */
+		mcnt++;
+		ret = btrfs_list_get_path_rootid(fd, &svid);
+		if (ret) {
+			/* error so just copy and return*/
+			strcpy(mntpt, mnt->mnt_dir);
+			close_file_or_dir(fd, dirstream);
+			break;
+		}
+		if (svid < saved_svid) {
+			strcpy(mntpt, mnt->mnt_dir);
+			saved_svid = svid;
+		}
+	}
+	endmntent(f);
+	if (mcnt)
+		*mnt_cnt = mcnt;
+
+	return ret;
+}
diff --git a/utils.h b/utils.h
index 2fc230b..00f1c18 100644
--- a/utils.h
+++ b/utils.h
@@ -97,5 +97,6 @@ int lookup_ino_rootid(int fd, u64 *rootid);
 int btrfs_scan_lblkid(int update_kernel);
 int get_btrfs_mount(const char *dev, char *mp, size_t mp_size);
 int get_fslist(struct btrfs_ioctl_fslist **out_fslist, u64 *out_count);
+int fsid_to_mntpt(__u8 *fsid, char *mntpt, int *mnt_cnt);
 
 #endif
-- 
1.7.1


  parent reply	other threads:[~2013-11-21  3:19 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-15 11:25 [PATCH v4 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control Anand Jain
2013-11-15 11:25 ` [PATCH v4 2/3] btrfs-progs: fs show should handle if subvol(s) mounted Anand Jain
2013-11-20 14:18   ` David Sterba
2013-11-21  3:32     ` Anand Jain
2013-11-22  7:56       ` David Sterba
2013-11-21  3:28   ` Anand Jain [this message]
2013-11-15 11:25 ` [PATCH v4 3/3] btrfs-progs: lblkid wouldn't find non mapper path input Anand Jain
2013-11-15 15:07 ` [PATCH v4 1/3] btrfs-progs: mechanism to fetch fsinfo from btrfs-control David Sterba

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1385004521-28886-1-git-send-email-anand.jain@oracle.com \
    --to=anand.jain@oracle.com \
    --cc=dsterba@suse.cz \
    --cc=jbacik@fusionio.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).