From: Jeff Mahoney <jeffm@suse.com>
To: Anand Jain <Anand.Jain@oracle.com>
Cc: linux-btrfs <linux-btrfs@vger.kernel.org>,
David Sterba <dsterba@suse.cz>
Subject: Re: [PATCH] btrfs-progs: canonicalize pathnames for device commands
Date: Sun, 14 Sep 2014 18:47:25 -0400 [thread overview]
Message-ID: <54161AFD.3070604@suse.com> (raw)
In-Reply-To: <5413F2D0.3020006@oracle.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 9/13/14, 3:31 AM, Anand Jain wrote:
>
>
> Jeff,
>
> Nice patch. However its better if we do this in the btrfs kernel
> function btrfs_scan_one_device(). Since the non-canonicalize path
> can still sneak through the btrfs specific mount option "device=".
>
> Any comments ?
My initial reaction is to avoid playing naming names within the
kernel. But since it's device mapper-specific, it might not be too
messy to do that. In addition to the patch to the progs, we're also
carrying a patch to systemd since it has it's own little ioctl wrapper
to do the scanning. It needed to be fixed there as well.
- -Jeff
> Thanks, Anand
>
>
>
> On 06/05/2014 04:43 AM, Jeff Mahoney wrote:
>> mount(8) will canonicalize pathnames before passing them to the
>> kernel. Links to e.g. /dev/sda will be resolved to /dev/sda.
>> Links to /dev/dm-# will be resolved using the name of the device
>> mapper table to /dev/mapper/<name>.
>>
>> Btrfs will use whatever name the user passes to it, regardless of
>> whether it is canonical or not. That means that if a 'btrfs
>> device ready' is issued on any device node pointing to the
>> original device, it will adopt the new name instead of the name
>> that was used during mount.
>>
>> Mounting using /dev/sdb2 will result in df: /dev/sdb2
>> 209715200 39328 207577088 1% /mnt
>>
>> # ls -la /dev/whatever-i-like lrwxrwxrwx 1 root root 4 Jun 4
>> 13:36 /dev/whatever-i-like -> sdb2 # btrfs dev ready
>> /dev/whatever-i-like # df /mnt /dev/whatever-i-like 209715200
>> 39328 207577088 1% /mnt
>>
>> Likewise, mounting with /dev/mapper/whatever and using /dev/dm-0
>> with a btrfs device command results in df showing /dev/dm-0. This
>> can happen with multipath devices with friendly names enabled and
>> doing something like 'partprobe' which (at least with our
>> version) ends up issuing a 'change' uevent on the sysfs node.
>> That *always* uses the dm-# name, and we get confused users.
>>
>> This patch does the same canonicalization of the paths that mount
>> does so that we don't end up having inconsistent names reported
>> by ->show_devices later.
>>
>> Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- cmds-device.c |
>> 60 ++++++++++++++++++++++++++++++++++++++++++++-------------
>> cmds-replace.c | 13 ++++++++++-- utils.c | 57
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h
>> | 2 + 4 files changed, 117 insertions(+), 15 deletions(-)
>>
>> --- a/cmds-device.c +++ b/cmds-device.c @@ -95,6 +95,7 @@ static
>> int cmd_add_dev(int argc, char ** int devfd, res; u64
>> dev_block_count = 0; int mixed = 0; + char *path;
>>
>> res = test_dev_for_mkfs(argv[i], force, estr); if (res) { @@
>> -118,15 +119,24 @@ static int cmd_add_dev(int argc, char ** goto
>> error_out; }
>>
>> - strncpy_null(ioctl_args.name, argv[i]); + path =
>> canonicalize_path(argv[i]); + if (!path) { +
>> fprintf(stderr, + "ERROR: Could not canonicalize
>> pathname '%s': %s\n", + argv[i],
>> strerror(errno)); + ret++; + goto
>> error_out; + } + + strncpy_null(ioctl_args.name,
>> path); res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args); e =
>> errno; - if(res<0){ + if (res < 0) {
>> fprintf(stderr, "ERROR: error adding the device '%s' - %s\n", -
>> argv[i], strerror(e)); + path, strerror(e));
>> ret++; } - + free(path); }
>>
>> error_out: @@ -242,6 +252,7 @@ static int cmd_scan_dev(int argc,
>> char *
>>
>> for( i = devstart ; i < argc ; i++ ){ struct btrfs_ioctl_vol_args
>> args; + char *path;
>>
>> if (!is_block_device(argv[i])) { fprintf(stderr, @@ -249,9
>> +260,17 @@ static int cmd_scan_dev(int argc, char * ret = 1; goto
>> close_out; } - printf("Scanning for Btrfs filesystems in
>> '%s'\n", argv[i]); + path = canonicalize_path(argv[i]); +
>> if (!path) { + fprintf(stderr, +
>> "ERROR: Could not canonicalize path '%s': %s\n", +
>> argv[i], strerror(errno)); + ret = 1; +
>> goto close_out; + } + printf("Scanning for Btrfs
>> filesystems in '%s'\n", path);
>>
>> - strncpy_null(args.name, argv[i]); +
>> strncpy_null(args.name, path); /* * FIXME: which are the error
>> code returned by this ioctl ? * it seems that is impossible to
>> understand if there no is @@ -262,9 +281,11 @@ static int
>> cmd_scan_dev(int argc, char *
>>
>> if( ret < 0 ){ fprintf(stderr, "ERROR: unable to scan the device
>> '%s' - %s\n", - argv[i], strerror(e)); +
>> path, strerror(e)); + free(path); goto close_out; } +
>> free(path); }
>>
>> close_out: @@ -284,6 +305,7 @@ static int cmd_ready_dev(int argc,
>> char struct btrfs_ioctl_vol_args args; int fd; int ret;
>> + char *path;
>>
>> if (check_argc_min(argc, 2)) usage(cmd_ready_dev_usage); @@
>> -293,22 +315,34 @@ static int cmd_ready_dev(int argc, char
>> perror("failed to open /dev/btrfs-control"); return 1; } - if
>> (!is_block_device(argv[1])) { + + path =
>> canonicalize_path(argv[argc - 1]); + if (!path) {
>> fprintf(stderr, - "ERROR: %s is not a block device\n",
>> argv[1]); - close(fd); - return 1; +
>> "ERROR: Could not canonicalize pathname '%s': %s\n", +
>> argv[argc - 1], strerror(errno)); + ret = 1; + goto
>> out; }
>>
>> - strncpy(args.name, argv[argc - 1], BTRFS_PATH_NAME_MAX); +
>> if (!is_block_device(path)) { + fprintf(stderr, +
>> "ERROR: %s is not a block device\n", path); + ret = 1; +
>> goto out; + } + + strncpy(args.name, path,
>> BTRFS_PATH_NAME_MAX); ret = ioctl(fd, BTRFS_IOC_DEVICES_READY,
>> &args); if (ret < 0) { fprintf(stderr, "ERROR: unable to
>> determine if the device '%s'" - " is ready for
>> mounting - %s\n", argv[argc - 1], + " is ready for
>> mounting - %s\n", path, strerror(errno)); ret = 1; }
>>
>> +out: + free(path); close(fd); return ret; } ---
>> a/cmds-replace.c +++ b/cmds-replace.c @@ -134,7 +134,7 @@ static
>> int cmd_start_replace(int argc, c int fddstdev = -1; char *path;
>> char *srcdev; - char *dstdev; + char *dstdev = NULL; int
>> avoid_reading_from_srcdev = 0; int force_using_targetdev = 0;
>> struct stat st; @@ -204,7 +204,12 @@ static int
>> cmd_start_replace(int argc, c }
>>
>> srcdev = argv[optind]; - dstdev = argv[optind + 1]; +
>> dstdev = canonicalize_path(argv[optind + 1]); + if (!dstdev)
>> { + fprintf(stderr, + "ERROR: Could not
>> canonicalize path '%s': %s\n", + argv[optind + 1],
>> strerror(errno)); + }
>>
>> if (is_numerical(srcdev)) { struct btrfs_ioctl_fs_info_args
>> fi_args; @@ -278,6 +283,8 @@ static int cmd_start_replace(int
>> argc, c
>>
>> close(fddstdev); fddstdev = -1; + free(dstdev); + dstdev =
>> NULL;
>>
>> dev_replace_handle_sigint(fdmnt); if (!do_not_background) { @@
>> -312,6 +319,8 @@ static int cmd_start_replace(int argc, c return
>> 0;
>>
>> leave_with_error: + if (dstdev) + free(dstdev); if
>> (fdmnt != -1) close(fdmnt); if (fdsrcdev != -1) --- a/utils.c +++
>> b/utils.c @@ -987,6 +987,63 @@ static int
>> blk_file_in_dev_list(struct b }
>>
>> /* + * Resolve a pathname to a device mapper node to
>> /dev/mapper/<name> + * Returns NULL on invalid input or malloc
>> failure; Other failures + * will be handled by the caller using
>> the input pathame. + */ +char *canonicalize_dm_name(const char
>> *ptname) +{ + FILE *f; + size_t sz; + char
>> path[256], name[256], *res = NULL; + + if (!ptname ||
>> !*ptname) + return NULL; + + snprintf(path,
>> sizeof(path), "/sys/block/%s/dm/name", ptname); + if (!(f =
>> fopen(path, "r"))) + return NULL; + + /* read <name>\n
>> from sysfs */ + if (fgets(name, sizeof(name), f) && (sz =
>> strlen(name)) > 1) { + name[sz - 1] = '\0'; +
>> snprintf(path, sizeof(path), "/dev/mapper/%s", name); + +
>> if (access(path, F_OK) == 0) + res = strdup(path); +
>> } + fclose(f); + return res; +} + +/* + * Resolve a
>> pathname to a canonical device node, e.g. /dev/sda1 or + * to a
>> device mapper pathname. + * Returns NULL on invalid input or
>> malloc failure; Other failures + * will be handled by the caller
>> using the input pathame. + */ +char *canonicalize_path(const char
>> *path) +{ + char *canonical, *p; + + if (!path || !*path) +
>> return NULL; + + canonical = realpath(path, NULL); + if
>> (!canonical) + return strdup(path); + p =
>> strrchr(canonical, '/'); + if (p && strncmp(p, "/dm-", 4) == 0
>> && isdigit(*(p + 4))) { + char *dm =
>> canonicalize_dm_name(p + 1); + if (dm) { +
>> free(canonical); + return dm; + } + } +
>> return canonical; +} + +/* * returns 1 if the device was mounted,
>> < 0 on error or 0 if everything * is safe to continue. */ ---
>> a/utils.h +++ b/utils.h @@ -61,6 +61,8 @@ int
>> btrfs_add_to_fsid(struct btrfs_trans int btrfs_scan_for_fsid(int
>> run_ioctls); void btrfs_register_one_device(char *fname); int
>> btrfs_scan_one_dir(char *dirname, int run_ioctl); +char
>> *canonicalize_dm_name(const char *ptname); +char
>> *canonicalize_path(const char *path); int check_mounted(const
>> char *devicename); int check_mounted_where(int fd, const char
>> *file, char *where, int size, struct btrfs_fs_devices
>> **fs_devices_mnt);
>>
> -- To unsubscribe from this list: send the line "unsubscribe
> linux-btrfs" in the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
iQIcBAEBAgAGBQJUFhr9AAoJEB57S2MheeWyXzgQAMKR0b29uU0kyYbalOxjpVkB
yAvR5kFItcEgRSfUUyqJqL+atJZ2PrzU4fQsz6i25cOBfQC5EdZYO/QENXe7HleU
oCECYucZC14qTLwswhpMeCtyMrX98sjhQxZ6NPSmLZWi/Btc2QDdwwbij4B3KRnQ
lE/AWmtT/J0fqlmjr18ETdTjTCZVyxUpN809hZpHAwQAiDZhXqbTUveaFu3DpTyn
vDdM5LZ2oGPjS/3WgoNiFy36R1cnxIh3k/+aM/afU20T//dOn8Cdrh+k868hv9fV
f3YfkyoHzwBCXp8VaOZytkOy7HCLbTEpnnB7MbvrNo1ukOlrFZRVRMSUrco2QD6x
4UYfgBj/zuzxIUZotEnpAmE8ppbMBylqjx+dyIwviDCU0Huw9mEnraBf3Yunuf3k
za92pv/SYJnEFRl2w5ULhtR6GJ3RM8TQJOtWRJjPLkS3L30xvVOQZ1zXoazi/4yX
qp7bKKN/hzC8mPvp8aoCW5c+F652e4pmUplbR4RDaNCD7ipv60XfQBVYOJOGh2YX
+OCYERzFs4th3uPlKNDSfsLHwGY36bPC3mPdiaJW144MX1vHL5YKJiEKcnk5QZNY
BwWidSvdylitAmZeKeCRTOJJh/b+Q7/K72RdWSl6g5qipa/00Gc97Sl/jNOyZ7K6
URPW75jcC/KtA2gIArtL
=fAyc
-----END PGP SIGNATURE-----
next prev parent reply other threads:[~2014-09-14 22:47 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-04 20:43 [PATCH] btrfs-progs: canonicalize pathnames for device commands Jeff Mahoney
2014-06-18 16:32 ` David Sterba
2014-09-13 7:31 ` Anand Jain
2014-09-14 22:47 ` Jeff Mahoney [this message]
2014-09-15 18:02 ` Anand Jain
2014-09-24 6:33 ` Anand Jain
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=54161AFD.3070604@suse.com \
--to=jeffm@suse.com \
--cc=Anand.Jain@oracle.com \
--cc=dsterba@suse.cz \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.