[PATCH 1/3] Btrfs: do not inc uncorrectable_errors counter on ro scrubs
Currently if we discover an error when scrubbing in ro mode we a) blindly increment the uncorrectable_errors counter, and b) spam the dmesg with the 'unable to fixup (regular) error at ...' message, even though a) we haven't tried to determine if the error is correctable or not, and b) we haven't tried to fixup anything. Fix this. Cc: Stefan Behrens sbehr...@giantdisaster.de Signed-off-by: Ilya Dryomov idryo...@gmail.com --- fs/btrfs/scrub.c |6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index f21e2df..f94b98d 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -938,8 +938,10 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) BTRFS_DEV_STAT_CORRUPTION_ERRS); } - if (sctx-readonly !sctx-is_dev_replace) - goto did_not_correct_error; + if (sctx-readonly) { + ASSERT(!sctx-is_dev_replace); + goto out; + } if (!is_metadata !have_csum) { struct scrub_fixup_nodatasum *fixup_nodatasum; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] Btrfs: disable online raid-repair on ro mounts
This disables the if needed, write the good copy back before the read is completed part of the read sequence for read-only mounts. Cc: Jan Schmidt list.bt...@jan-o-sch.net Signed-off-by: Ilya Dryomov idryo...@gmail.com --- fs/btrfs/extent_io.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c09a40d..a0b7403 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1979,6 +1979,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start, struct btrfs_mapping_tree *map_tree = fs_info-mapping_tree; int ret; + ASSERT(!(fs_info-sb-s_flags MS_RDONLY)); BUG_ON(!mirror_num); /* we can't repair anything in raid56 yet */ @@ -2035,6 +2036,9 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb, unsigned long i, num_pages = num_extent_pages(eb-start, eb-len); int ret = 0; + if (root-fs_info-sb-s_flags MS_RDONLY) + return -EROFS; + for (i = 0; i num_pages; i++) { struct page *p = extent_buffer_page(eb, i); ret = repair_io_failure(root-fs_info, start, PAGE_CACHE_SIZE, @@ -2056,12 +2060,12 @@ static int clean_io_failure(u64 start, struct page *page) u64 private; u64 private_failure; struct io_failure_record *failrec; - struct btrfs_fs_info *fs_info; + struct inode *inode = page-mapping-host; + struct btrfs_fs_info *fs_info = BTRFS_I(inode)-root-fs_info; struct extent_state *state; int num_copies; int did_repair = 0; int ret; - struct inode *inode = page-mapping-host; private = 0; ret = count_range_bits(BTRFS_I(inode)-io_failure_tree, private, @@ -2084,6 +2088,8 @@ static int clean_io_failure(u64 start, struct page *page) did_repair = 1; goto out; } + if (fs_info-sb-s_flags MS_RDONLY) + goto out; spin_lock(BTRFS_I(inode)-io_tree.lock); state = find_first_extent_bit_state(BTRFS_I(inode)-io_tree, @@ -2093,7 +2099,6 @@ static int clean_io_failure(u64 start, struct page *page) if (state state-start = failrec-start state-end = failrec-start + failrec-len - 1) { - fs_info = BTRFS_I(inode)-root-fs_info; num_copies = btrfs_num_copies(fs_info, failrec-logical, failrec-len); if (num_copies 1) { -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC][PATCH] BTRFS_PROG: mount.btrfs helper
Hi all, this patch provides a mount.btrfs helper for the mount command to mounting a btrfs filesystem. A btrfs filesystem could spans several disks. This helper scans all the partition to discover all the disks required to mount a filesystem. So it is not necessary any-more to scan manually the partitions to mount a filesystem via the btrfs device scan command. It adds in the option parameters the devices required to mount a filesystem. Supposing that a filesystem is composed by several disks (/dev/sd[cdef]), when the user does mount /dev/sdd /mnt, mount calls mount.btrfs which int turn calls the mount(2) syscall like: mount(/dev/sdd, /mnt, btrfs, 0, device=/dev/sdc,device=/dev/sde,device=/de/vsdf). This helper uses both the libblkid and libmount to discover the devices, to compute the parameters manipulation and to update the mtab file. I got the idea from the btrfs.wiki; its biggest gains is to avoid the separation of scanning phases (at boot time or during the block device discovery) from the mounting. Also mkfs.btrfs could avoid to re-do a rescan of the devices after a formatting. mount.btrfs doesn't add more requirement than the mount command. It would be possible to remove the btrfs command from the initramfs, and all the related scripts (in my debian both udev and btrfs-tools packages contains three udev rules for btrfs). Comments are welcome. -- gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] Provide mount.btrfs helper
This patch provides a mount.btrfs helper for the mount command to mounting a btrfs filesystem. A btrfs filesystem could span several disks. This helper scans all the partition to discover all the disks required to mount a filesystem. So it is not necessary any-more to scan the partitions to mount a filesystem. It adds in the option parameters the devices required to mount a filesystem. Supposing that a filesystem is composed by several disks (/dev/sd[cdef]), when the user does mount /dev/sdd /mnt, mount calls mount.btrfs which int turn calls the mount(2) so: mount(/dev/sdd, /mnt, btrfs, 0, device=/dev/sdc,device=/dev/sde,device=/de/vsdf). This helper uses both the libblkid and libmount to discover the devices, to compute the parameters manipulation and to update the mtab file. I got the idea from the btrfs.wiki; its biggest gains is to avoid the separation of scanning phases (at boot time or during the block device discovery) from the mounting. Also mkfs.btrfs could avoid to re-do a rescan of the devices after a formatting. mount.btrfs doesn't add more requirement than the mount command. It would be possible to remove the btrfs command from the initramfs, and all the related scripts (in my debian both udev and btrfs-tools packages contains three udev rules for btrfs). --- Makefile | 6 +- btrfs-mount.c | 617 ++ 2 files changed, 622 insertions(+), 1 deletion(-) create mode 100644 btrfs-mount.c diff --git a/Makefile b/Makefile index c43cb68..974e8ad 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,7 @@ MAKEOPTS = --no-print-directory Q=$(Q) progs = mkfs.btrfs btrfs-debug-tree btrfsck \ btrfs btrfs-map-logical btrfs-image btrfs-zero-log btrfs-convert \ - btrfs-find-root btrfstune btrfs-show-super + btrfs-find-root btrfstune btrfs-show-super mount.btrfs # external libs required by various binaries; for btrfs-foo, # specify btrfs_foo_libs = list of libs; see $($(subst...)) rules below @@ -171,6 +171,10 @@ ioctl-test: $(objects) $(libs) ioctl-test.o @echo [LD] $@ $(Q)$(CC) $(CFLAGS) -o ioctl-test $(objects) ioctl-test.o $(LDFLAGS) $(LIBS) +mount.btrfs: btrfs-mount.o + @echo [LD] $@ + $(Q)$(CC) $(CFLAGS) -o mount.btrfs -lmount -lblkid btrfs-mount.o $(LDFLAGS) + send-test: $(objects) $(libs) send-test.o @echo [LD] $@ $(Q)$(CC) $(CFLAGS) -o send-test $(objects) send-test.o $(LDFLAGS) $(LIBS) -lpthread diff --git a/btrfs-mount.c b/btrfs-mount.c new file mode 100644 index 000..fe07f9e --- /dev/null +++ b/btrfs-mount.c @@ -0,0 +1,617 @@ +#include stdio.h +#include unistd.h +#include string.h +#include stdlib.h +#include assert.h +#include sys/mount.h +#include errno.h +#include sys/types.h +#include sys/stat.h + +#include blkid/blkid.h +#include libmount/libmount.h + +#define MOUNT_FLAG_FAKE_MOUNT 1 +#define MOUNT_FLAG_VERBOSE 2 +#define MOUNT_FLAG_NOT_WRITIING_MTAB 4 +#define MOUNT_FLAG_IGNORE_SLOPPY_OPTS 8 + +struct btrfs_device { + char*device_name; + char*device_uuid; + char*fs_name; + char*fs_uuid; + struct btrfs_device *next; +}; + +/* Parse program args, and set the related variables */ +static int parse_args(int argc, char **argv, char **options, + char **spec, char **dir, int *flag) +{ + charopt; + + *options = NULL; + + while ((opt = getopt(argc, argv, sfnvo:)) != -1) { + + switch (opt) { + + case 's': /* tolerate sloppy mount options */ + *flag |= MOUNT_FLAG_IGNORE_SLOPPY_OPTS; + break; + case 'f': /* fake mount */ + *flag |= MOUNT_FLAG_FAKE_MOUNT; + break; + case 'n': /* mount without writing in mtab */ + *flag |= MOUNT_FLAG_NOT_WRITIING_MTAB; + break; + case 'v': /* verbose */ + *flag |= MOUNT_FLAG_VERBOSE; + break; + case 'o': + *options = optarg; + break; + default: + fprintf( stderr,ERROR: unknown option: '%c'\n, opt); + return 1; + } + } + + if (argc-optind != 2) { + fprintf(stderr, ERROR: two arguments are needed\n); + return 1; + } + + *spec = argv[optind]; + *dir = argv[optind+1]; + + return 0; + +} + +/* add a new string to the string array */ +static void add_to_list(struct btrfs_device **head, struct btrfs_device *d) +{ + d-next = (*head); + *head = d; +} + +/* free a btrfs_device struct */ +static void free_btrfs_device(struct
Re: [PATCH 01/13] btrfs: add ioctls to query/change feature bits online
On 11/1/13, 4:56 PM, Zach Brown wrote: +static int btrfs_ioctl_get_supported_features(struct file *file, + void __user *arg) +{ +struct btrfs_ioctl_feature_flags features[3]; + +features[0].compat_flags = BTRFS_FEATURE_COMPAT_SUPP; +features[0].compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_SUPP; +features[0].incompat_flags = BTRFS_FEATURE_INCOMPAT_SUPP; + +features[1].compat_flags = BTRFS_FEATURE_COMPAT_SAFE_SET; +features[1].compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; +features[1].incompat_flags = BTRFS_FEATURE_INCOMPAT_SAFE_SET; + +features[2].compat_flags = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; +features[2].compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; +features[2].incompat_flags = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; + +if (copy_to_user(arg, features, sizeof(features))) +return -EFAULT; If these are all constants shouldn't that just copy out of a static built flags array? Works for me. Change added. -Jeff #define cpp4ever(suff) \ BTRFS_FEATURE_COMPAT_#suff, BTRFS_FEATURE_COMPAT_RO_#suff, \ BTRFS_FEATURE_INCOMPAT_#suff static struct btrfs_ioctl_feature_flags features[3] = { { cpp4ever(SUPP) }, { cpp4ever(SAFE_SET) }, { cpp4ever(SAFE_CLEAR) }, }; if (copy_to_user(arg, features, sizeof(features))) return -EFAULT; ? - z -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- Jeff Mahoney SUSE Labs signature.asc Description: OpenPGP digital signature
BTRFS volume crashes after hard reset
Hi My computer froze and I had to power-cycle the PC. After reboot, attempting to mount the btrfs volume leads to a kernel oops: [ 970.140850] device fsid 65db2d61-0301-42c0-9f1b-94dd215f694c devid 1 transid 119849 /dev/sda3 [ 970.141475] btrfs: disk space caching is enabled [ 991.149365] [ cut here ] [ 991.149378] kernel BUG at /build/buildd/linux-3.2.0/fs/btrfs/free-space-cache.c:1515! [ 991.149386] invalid opcode: [#1] SMP [ 991.149393] CPU 3 [ 991.149397] Modules linked in: des_generic md4 nls_utf8 cifs ip6table_filter ip6_tables ebtable_nat ebtables pci_stub vboxpci(O) vboxnetadp(O) vboxnetflt(O) vboxdrv(O) ipt_MASQUERADE iptable_nat nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack ipt_REJECT xt_CHECKSUM iptable_mangle xt_tcpudp iptable_filter ip_tables x_tables kvm_amd kvm bnep rfcomm parport_pc ppdev binfmt_misc dm_crypt btusb bluetooth snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_intel snd_hda_codec bridge stp snd_hwdep snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device snd edac_core k10temp sp5100_tco i2c_piix4 edac_mce_amd soundcore snd_page_alloc psmouse serio_raw mac_hid lp parport btrfs zlib_deflate libcrc32c firewire_ohci firewire_core usbhid hid crc_itu_t floppy pata_atiixp wmi r8169 [ 991.149516] [ 991.149523] Pid: 4020, comm: mount Tainted: G O 3.2.0-32-generic #51-Ubuntu To Be Filled By O.E.M. To Be Filled By O.E.M./AOD790GX/128M [ 991.149536] RIP: 0010:[a00f2d38] [a00f2d38] remove_from_bitmap+0x248/0x250 [btrfs] [ 991.149590] RSP: 0018:8801726e1698 EFLAGS: 00010286 [ 991.149596] RAX: RBX: 880120ade700 RCX: 0003 [ 991.149602] RDX: 8001 RSI: 8000 RDI: 8801a0911000 [ 991.149608] RBP: 8801726e16f8 R08: 8801a0912000 R09: 8000 [ 991.149614] R10: 8800 R11: 0010a7815400 R12: 002c49c0 [ 991.149620] R13: 8801726e1718 R14: 8801726e1720 R15: 8801819b8840 [ 991.149627] FS: 7f9e6f719800() GS:8801afd8() knlGS:f75b86c0 [ 991.149633] CS: 0010 DS: ES: CR0: 8005003b [ 991.149639] CR2: 7ff9027b2110 CR3: 000159472000 CR4: 06e0 [ 991.149645] DR0: DR1: DR2: [ 991.149651] DR3: DR6: 0ff0 DR7: 0400 [ 991.149658] Process mount (pid: 4020, threadinfo 8801726e, task 8801727b4500) [ 991.149663] Stack: [ 991.149666] 880172682600 880172682600 880172682640 8801819b8864 [ 991.149678] 002c43303000 a000 0286 8801819b8840 [ 991.149688] 8801819b8864 880120ade700 [ 991.149698] Call Trace: [ 991.149742] [a00f3f99] btrfs_remove_free_space+0x69/0x330 [btrfs] [ 991.149779] [a00ae270] btrfs_alloc_logged_file_extent+0x1c0/0x1e0 [btrfs] [ 991.149811] [a009c93a] ? btrfs_free_path+0x2a/0x40 [btrfs] [ 991.149849] [a00ef2f8] replay_one_extent+0x518/0x570 [btrfs] [ 991.149861] [8108abc0] ? autoremove_wake_function+0x40/0x40 [ 991.149901] [a00efe2b] replay_one_buffer+0x26b/0x330 [btrfs] [ 991.149941] [a00dcb74] ? alloc_extent_buffer+0x74/0x410 [btrfs] [ 991.149979] [a00eccea] walk_down_log_tree+0x1ea/0x3b0 [btrfs] [ 991.150017] [a00ed1ad] walk_log_tree+0xbd/0x1d0 [btrfs] [ 991.150056] [a00f0ea1] btrfs_recover_log_trees+0x211/0x300 [btrfs] [ 991.150095] [a00efbc0] ? fixup_inode_link_counts+0x150/0x150 [btrfs] [ 991.150133] [a00bb635] open_ctree+0x14b5/0x1950 [btrfs] [ 991.150145] [81316eb4] ? snprintf+0x34/0x40 [ 991.150178] [a010abe2] btrfs_fill_super.isra.37+0x72/0x12c [btrfs] [ 991.150189] [811e4711] ? disk_name+0x61/0xc0 [ 991.150197] [813144d7] ? strlcpy+0x47/0x60 [ 991.150226] [a009a897] btrfs_mount+0x497/0x4e0 [btrfs] [ 991.150242] [8117bad3] mount_fs+0x43/0x1b0 [ 991.150254] [8119637a] vfs_kern_mount+0x6a/0xc0 [ 991.150265] [81197884] do_kern_mount+0x54/0x110 [ 991.150274] [811993e4] do_mount+0x1a4/0x260 [ 991.150282] [811998c0] sys_mount+0x90/0xe0 [ 991.150292] [81663442] system_call_fastpath+0x16/0x1b [ 991.150297] Code: e9 7d fe ff ff 66 0f 1f 44 00 00 b8 ea ff ff ff e9 c8 fe ff ff 48 89 de 4c 89 ff 89 45 b0 e8 80 e4 ff ff 8b 45 b0 e9 b2 fe ff ff 0f 0b 0f 0b 0f 1f 40 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 [ 991.150373] RIP [a00f2d38] remove_from_bitmap+0x248/0x250 [btrfs] [ 991.150409] RSP 8801726e1698 [ 991.150415] ---[ end trace 9a242a0fd54d816f ]--- How can I fix this? Michael -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at
Re: [RFC][PATCH] BTRFS_PROG: mount.btrfs helper
On 2013-11-03 22:23, Jeff Mahoney wrote: On 11/3/13, 1:38 PM, Goffredo Baroncelli wrote: Hi all, this patch provides a mount.btrfs helper for the mount command to mounting a btrfs filesystem. A btrfs filesystem could spans several disks. This helper scans all the partition to discover all the disks required to mount a filesystem. So it is not necessary any-more to scan manually the partitions to mount a filesystem via the btrfs device scan command. It adds in the option parameters the devices required to mount a filesystem. Supposing that a filesystem is composed by several disks (/dev/sd[cdef]), when the user does mount /dev/sdd /mnt, mount calls mount.btrfs which int turn calls the mount(2) syscall like: mount(/dev/sdd, /mnt, btrfs, 0, device=/dev/sdc,device=/dev/sde,device=/de/vsdf). This helper uses both the libblkid and libmount to discover the devices, to compute the parameters manipulation and to update the mtab file. I got the idea from the btrfs.wiki; its biggest gains is to avoid the separation of scanning phases (at boot time or during the block device discovery) from the mounting. Also mkfs.btrfs could avoid to re-do a rescan of the devices after a formatting. mount.btrfs doesn't add more requirement than the mount command. It would be possible to remove the btrfs command from the initramfs, and all the related scripts (in my debian both udev and btrfs-tools packages contains three udev rules for btrfs). Comments are welcome. I like the idea but I'm concerned how well this will perform on large systems with thousands of disks attached. btrfs dev scan can have a list of potential devices specified, but this helper defaults to all devices. liblkid uses a cache to increase the speed of a search. Only if some incoherency from the data is found (like a mkfs after a boot) a probe all is executed. But in this case we could update mkfs.btrfs to invalidate the blkid cache of disks involved (which should be done in any case) A quick test run with 2000 scsi_debug targets shows that btrfs dev scan can take 8 seconds, and that's with no actual I/O occurring. I don't think we want to specify the list of devices to scan on the mount command line, but perhaps an /etc config file that limits the scan to a list of devices (and defaults to all) similar to how mdadm.conf works would be a good improvement. I tried in qemu-kvm: # btrfs device scan # it took about 8sec # modprobe scsi_debug num_tgts=2000 # 8 seconds were required # before all udev instances ended But when I performed a blkid -c /dev/null (which should rebuild the cache) it takes ages I have to investigate a bit... -Jeff BR G.Baroncelli -- gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] btrfs: add framework to read fs info from btrfs-control
This adds ioctl BTRFS_IOC_GET_FSIDS which reads the fs info through the btrfs-control v2: accepts Zach suggested now holds uuid_mutex Signed-off-by: Anand Jain anand.j...@oracle.com --- fs/btrfs/super.c | 66 fs/btrfs/volumes.c | 39 ++ fs/btrfs/volumes.h |2 + include/uapi/linux/btrfs.h | 19 4 files changed, 120 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index e9c4e41..241f401 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1646,38 +1646,92 @@ static struct file_system_type btrfs_fs_type = { }; MODULE_ALIAS_FS(btrfs); +static int btrfs_ioc_get_fslist(void __user *arg) +{ + int ret = 0; + u64 sz_fslist_arg; + u64 sz_fslist; + u64 sz_out; + struct btrfs_ioctl_fslist_args *fslist_arg; + struct btrfs_ioctl_fslist_args *fslist_arg_tmp; + struct btrfs_ioctl_fslist *fslist; + + u64 cnt = 0, ucnt; + + sz_fslist_arg = sizeof(*fslist_arg); + sz_fslist = sizeof(*fslist); + if (copy_from_user(ucnt, + (struct btrfs_ioctl_fslist_args __user *)(arg + + offsetof(struct btrfs_ioctl_fslist_args, count)), + sizeof(ucnt))) + return -EFAULT; + + cnt = btrfs_get_fslist_cnt(); + + if (cnt ucnt) { + if (copy_to_user(arg + + offsetof(struct btrfs_ioctl_fslist_args, count), + cnt, sizeof(cnt))) + return -EFAULT; + return 1; + } + + sz_out = sz_fslist_arg + sz_fslist * cnt; + fslist_arg_tmp = fslist_arg = memdup_user(arg, sz_out); + if (IS_ERR(fslist_arg)) + return PTR_ERR(fslist_arg); + fslist = (struct btrfs_ioctl_fslist *) (++fslist_arg_tmp); + cnt = btrfs_get_fslist(fslist, cnt); + fslist_arg-count = cnt; + if (copy_to_user(arg, fslist_arg, sz_out)) { + ret = -EFAULT; + goto out; + } + ret = 0; +out: + kfree(fslist_arg); + return ret; +} + /* * used by btrfsctl to scan devices when no FS is mounted */ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct btrfs_ioctl_vol_args *vol; + struct btrfs_ioctl_vol_args *vol = NULL; struct btrfs_fs_devices *fs_devices; int ret = -ENOTTY; + void __user *argp = (void __user *)arg; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - vol = memdup_user((void __user *)arg, sizeof(*vol)); - if (IS_ERR(vol)) - return PTR_ERR(vol); - switch (cmd) { case BTRFS_IOC_SCAN_DEV: + vol = memdup_user((void __user *)arg, sizeof(*vol)); + if (IS_ERR(vol)) + return PTR_ERR(vol); ret = btrfs_scan_one_device(vol-name, FMODE_READ, btrfs_fs_type, fs_devices); + kfree(vol); break; case BTRFS_IOC_DEVICES_READY: + vol = memdup_user((void __user *)arg, sizeof(*vol)); + if (IS_ERR(vol)) + return PTR_ERR(vol); ret = btrfs_scan_one_device(vol-name, FMODE_READ, btrfs_fs_type, fs_devices); + kfree(vol); if (ret) break; ret = !(fs_devices-num_devices == fs_devices-total_devices); break; + case BTRFS_IOC_GET_FSLIST: + ret = btrfs_ioc_get_fslist(argp); + break; } - kfree(vol); return ret; } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5103cfe..b114372 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6289,3 +6289,42 @@ int btrfs_scratch_superblock(struct btrfs_device *device) return 0; } + +int btrfs_get_fslist_cnt(void) +{ + int cnt = 0; + struct btrfs_fs_devices *fs_devices; + + mutex_lock(uuid_mutex); + list_for_each_entry(fs_devices, fs_uuids, list) + cnt++; + mutex_unlock(uuid_mutex); + + return cnt; +} + +u64 btrfs_get_fslist(struct btrfs_ioctl_fslist *fslist, u64 ucnt) +{ + u64 cnt = 0; + struct btrfs_fs_devices *fs_devices; + + mutex_lock(uuid_mutex); + list_for_each_entry(fs_devices, fs_uuids, list) { + if (!(cnt ucnt)) + break; + memcpy(fslist-fsid, fs_devices-fsid, + BTRFS_FSID_SIZE); + fslist-num_devices = fs_devices-num_devices; + fslist-missing_devices = fs_devices-missing_devices; + fslist-total_devices = fs_devices-total_devices; + + if (fs_devices-opened) +
[PATCH 4/4] btrfs-progs: lblkid wouldn't find non mapper path input
A new test case when disk is unmounted and if the non mapper disk path is given as the argument to the btrfs filesystem show arg we still need this to work but lblkid will pull only mapper disks, it won't match. So this will normalize the input to find btrfs by fsid and pass it to the search. v2: accepts Josef suggested Signed-off-by: Anand Jain anand.j...@oracle.com --- cmds-filesystem.c | 59 +--- 1 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index f8e8475..f40178a 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -37,6 +37,7 @@ #include version.h #include commands.h #include list_sort.h +#include disk-io.h static const char * const filesystem_cmd_group_usage[] = { btrfs filesystem [group] command [args], @@ -414,6 +415,39 @@ static int btrfs_scan_kernel(void *search) return 0; } +static int dev_to_fsid(char *dev, __u8 *fsid) +{ + struct btrfs_super_block *disk_super; + char *buf; + int ret; + int fd; + + buf = malloc(4096); + if (!buf) + return -ENOMEM; + + fd = open(dev, O_RDONLY); + if (fd 0) { + ret = -errno; + free(buf); + return ret; + } + + disk_super = (struct btrfs_super_block *)buf; + ret = btrfs_read_dev_super(fd, disk_super, + BTRFS_SUPER_INFO_OFFSET); + if (ret) + goto out; + + memcpy(fsid, disk_super-fsid, BTRFS_FSID_SIZE); + ret = 0; + +out: + close(fd); + free(buf); + return ret; +} + static const char * const cmd_show_usage[] = { btrfs filesystem show [options] [path|uuid|device|label], Show the structure of a filesystem, @@ -434,6 +468,8 @@ static int cmd_show(int argc, char **argv) int type = 0; char mp[BTRFS_PATH_NAME_MAX + 1]; char path[PATH_MAX]; + __u8 fsid[BTRFS_FSID_SIZE]; + char uuid_buf[37]; while (1) { int long_index; @@ -466,6 +502,10 @@ static int cmd_show(int argc, char **argv) if (strlen(search) == 0) usage(cmd_show_usage); type = check_arg_type(search); + /*needs spl handling if input arg is block dev +*And if input arg is mount-point just print it +*right away + */ if (type == BTRFS_ARG_BLKDEV) { if (where == BTRFS_SCAN_DEV) { /* we need to do this because @@ -477,14 +517,25 @@ static int cmd_show(int argc, char **argv) } else { ret = get_btrfs_mount(search, mp, sizeof(mp)); - if (!ret) + if (!ret) { /* given block dev is mounted*/ search = mp; - else + type = BTRFS_ARG_MNTPOINT; + } else { + ret = dev_to_fsid(search, fsid); + if (ret) { + fprintf(stderr, + ERROR: No btrfs on %s\n, + search); + return 1; + } + uuid_unparse(fsid, uuid_buf); + search = uuid_buf; + type = BTRFS_ARG_UUID; goto devs_only; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; if (get_label_mounted(search, label)) return 1; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4 v2] btrfs-progs: fs show should handle if subvol(s) mounted
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. v2: accepts Zach suggested Signed-off-by: Anand Jain anand.j...@oracle.com --- cmds-filesystem.c | 90 + utils.c | 88 ++- utils.h |3 +- 3 files changed, 130 insertions(+), 51 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index d2cad81..f8e8475 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -317,6 +317,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 0 !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 0) + 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 @@ -350,47 +373,39 @@ 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; + + 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); + if (get_label_mounted(mnt, label)) return 1; - } - 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 0 !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)); - } - if (fd 0) - close(fd); - kfree(dev_info_arg); + handle_print(mnt, label); if (search) return 0; } @@ -469,6 +484,13 @@ static int cmd_show(int argc, char **argv) goto devs_only; } } + if (type == BTRFS_ARG_MNTPOINT) { + char label[BTRFS_LABEL_SIZE]; + if (get_label_mounted(search, label)) + return 1; + handle_print(search, label); + return 0; + } } if (where == BTRFS_SCAN_DEV) diff --git a/utils.c b/utils.c index 1798a7c..d466ffa 100644 --- a/utils.c +++ b/utils.c @@ -47,6 +47,7 @@ #include utils.h #include volumes.h #include ioctl.h +#include
[PATCH 1/4] btrfs-progs: make filesystem show by label work
with design revamp around filesystem show the fsid filter by label wasn't planned. but apparently that seemed to be necessary. this patch will fix it. Signed-off-by: Anand Jain anand.j...@oracle.com --- cmds-filesystem.c | 120 - 1 files changed, 73 insertions(+), 47 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index d08007e..d2cad81 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -179,6 +179,26 @@ static int cmd_df(int argc, char **argv) return !!ret; } +static int match_search_item_kernel(__u8 *fsid, char *mnt, char *label, + char *search) +{ + char uuidbuf[37]; + int search_len = strlen(search); + + search_len = min(search_len, 37); + uuid_unparse(fsid, uuidbuf); + if (!strncmp(uuidbuf, search, search_len)) + return 1; + + if (strlen(label) strcmp(label, search) == 0) + return 1; + + if (strcmp(mnt, search) == 0) + return 1; + + return 0; +} + static int uuid_search(struct btrfs_fs_devices *fs_devices, char *search) { char uuidbuf[37]; @@ -275,16 +295,18 @@ static int print_one_fs(struct btrfs_ioctl_fs_info_args *fs_info, struct btrfs_ioctl_dev_info_args *tmp_dev_info; uuid_unparse(fs_info-fsid, uuidbuf); - printf(Label: %s uuid: %s\n, - strlen(label) ? label : none, uuidbuf); + if (label strlen(label)) + printf(Label: '%s' , label); + else + printf(Label: none ); - printf(\tTotal devices %llu FS bytes used %s\n, - fs_info-num_devices, + printf( uuid: %s\n\tTotal devices %llu FS bytes used %s\n, uuidbuf, + fs_info-num_devices, pretty_size(calc_used_bytes(space_info))); for (i = 0; i fs_info-num_devices; i++) { tmp_dev_info = (struct btrfs_ioctl_dev_info_args *)dev_info[i]; - printf(\tdevid%llu size %s used %s path %s\n, + printf(\tdevid %4llu size %s used %s path %s\n, tmp_dev_info-devid, pretty_size(tmp_dev_info-total_bytes), pretty_size(tmp_dev_info-bytes_used), @@ -308,7 +330,7 @@ static int check_arg_type(char *input) char path[PATH_MAX]; if (!input) - return BTRFS_ARG_UNKNOWN; + return -EINVAL; if (realpath(input, path)) { if (is_block_device(input) == 1) @@ -320,7 +342,7 @@ static int check_arg_type(char *input) return BTRFS_ARG_UNKNOWN; } - if (!uuid_parse(input, out)) + if (strlen(input) == 36 !uuid_parse(input, out)) return BTRFS_ARG_UUID; return BTRFS_ARG_UNKNOWN; @@ -328,23 +350,19 @@ static int check_arg_type(char *input) static int btrfs_scan_kernel(void *search) { - int ret = 0, fd, type; + 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; char label[BTRFS_LABEL_SIZE]; - uuid_t uuid; f = setmntent(/proc/self/mounts, r); if (f == NULL) return 1; - type = check_arg_type(search); - if (type == BTRFS_ARG_BLKDEV) - return 1; - + memset(label, 0, sizeof(label)); while ((mnt = getmntent(f)) != NULL) { if (strcmp(mnt-mnt_type, btrfs)) continue; @@ -353,38 +371,36 @@ static int btrfs_scan_kernel(void *search) if (ret) return ret; - switch (type) { - case BTRFS_ARG_UUID: - ret = uuid_parse(search, uuid); - if (ret) - return 1; - if (uuid_compare(fs_info_arg.fsid, uuid)) - continue; - break; - case BTRFS_ARG_MNTPOINT: - if (strcmp(search, mnt-mnt_dir)) - continue; - break; - case BTRFS_ARG_UNKNOWN: - break; + if (get_label_mounted(mnt-mnt_dir, label)) { + kfree(dev_info_arg); + return 1; + } + if (search !match_search_item_kernel(fs_info_arg.fsid, + mnt-mnt_dir, label, search)) { + kfree(dev_info_arg); + continue; } fd = open(mnt-mnt_dir, O_RDONLY); if (fd 0 !get_df(fd, space_info_arg)) { - get_label_mounted(mnt-mnt_dir, label);
[PATCH 2/4 v2] btrfs-progs: mechanism to fetch fsinfo from btrfs-control
need fsinfo from btrfs-control that is when mount path is not known. current method of going through each mount points isn't efficient, and multiple subvol of a fsid could be mounted means extra logic to handle that. Further this will help to revamp check_mounted() (planned) check_mounted is heavily used in the btrfs-progs, it does full scan of all the disks in the system to confirm if a multi-disk btrfs is mounted it doesn't scalable well with few hundreds luns, check_mounted for sure needs a revamp. using this it can be done easily. which is planned. v2: commit reword Signed-off-by: Anand Jain anand.j...@oracle.com --- ioctl.h | 19 +++ utils.c | 80 +++ utils.h |1 + 3 files changed, 100 insertions(+), 0 deletions(-) diff --git a/ioctl.h b/ioctl.h index d21413f..29575d8 100644 --- a/ioctl.h +++ b/ioctl.h @@ -506,6 +506,23 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code) } } +/* fs flags */ +#define BTRFS_FS_MOUNTED (1LLU 0) + +struct btrfs_ioctl_fslist { + __u64 self_sz; /* in/out */ + __u8 fsid[BTRFS_FSID_SIZE]; /* out */ + __u64 num_devices; + __u64 missing_devices; + __u64 total_devices; + __u64 flags; +}; + +struct btrfs_ioctl_fslist_args { + __u64 self_sz; /* in/out */ + __u64 count;/* out */ +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ @@ -604,6 +621,8 @@ struct btrfs_ioctl_clone_range_args { struct btrfs_ioctl_dev_replace_args) #define BTRFS_IOC_DEDUP_CTL _IOWR(BTRFS_IOCTL_MAGIC, 55, \ struct btrfs_ioctl_dedup_args) +#define BTRFS_IOC_GET_FSLIST _IOWR(BTRFS_IOCTL_MAGIC, 56, \ + struct btrfs_ioctl_fslist_args) #ifdef __cplusplus } #endif diff --git a/utils.c b/utils.c index 5bedd97..1798a7c 100644 --- a/utils.c +++ b/utils.c @@ -2087,3 +2087,83 @@ int lookup_ino_rootid(int fd, u64 *rootid) return 0; } + +/* scans for fsid(s) in the kernel using the btrfs-control + * interface. + */ +int get_fslist(struct btrfs_ioctl_fslist **out_fslist, int *out_count) +{ + int ret, fd, e; + struct btrfs_ioctl_fslist_args *fsargs; + struct btrfs_ioctl_fslist *fslist; + struct btrfs_ioctl_fslist *fslist_tmp; + u64 sz; + int count; + + fd = open(/dev/btrfs-control, O_RDWR); + e = errno; + if (fd 0) { + perror(failed to open /dev/btrfs-control); + return -e; + } + + /* space to hold 512 fsids, doesn't matter if small +* it would fail and return count so then we try again +*/ + count = 512; +again: + sz = sizeof(*fsargs) + sizeof(*fslist) * count; + + fsargs = (struct btrfs_ioctl_fslist_args *) malloc(sz); + memset(fsargs, 0, sz); + + if (!fsargs) { + close(fd); + return -ENOMEM; + } + fsargs-count = count; + + ret = ioctl(fd, BTRFS_IOC_GET_FSLIST, fsargs); + e = errno; + if (ret == 1) { + /* out of size so reallocate */ + count = fsargs-count; + free(fsargs); + goto again; + } else if (ret 0) { + printf(ERROR: scan_fsid ioctl failed - %s\n, + strerror(e)); + ret = -e; + goto out; + } + + /* ioctl returns fsid count in count parameter*/ + + *out_count = count = fsargs-count; + if (count == 0) { + *out_fslist = NULL; + ret = 0; + goto out; + } + + fslist = (struct btrfs_ioctl_fslist *) (fsargs + + sizeof(*fsargs)); + + fslist_tmp = *out_fslist = (struct btrfs_ioctl_fslist *) + malloc(sizeof(*fslist) * count); + if (!fslist_tmp) { + ret = -ENOMEM; + goto out; + } + + while (count--) { + memcpy(fslist_tmp, fslist, sizeof(*fslist)); + fslist_tmp = fslist_tmp + sizeof(*fslist_tmp); + fslist = fslist + sizeof(*fslist); + } + ret = 0; +out: + free(fsargs); + close(fd); + return 0; +} diff --git a/utils.h b/utils.h index 6f4b10c..e20ad74 100644 --- a/utils.h +++ b/utils.h @@ -94,5 +94,6 @@ int ask_user(char *question); 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, int *out_count); #endif -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to
Re: [PATCH] btrfs: add framework to read fs info from btrfs-control
(sorry for the delay, various external issues) I have sent out the new patch set. Thanks for the comments. more inline. On 10/30/13 05:33 AM, Zach Brown wrote: This adds ioctl BTRFS_IOC_GET_FSIDS which reads the fs info through the btrfs-control Why not use sysfs? various sysfs interface for btrfs is still being a RFC ioctl would much simpler to get the bug fixed. + sz_fslist_arg = sizeof(*fslist_arg); + fslist_arg = memdup_user(arg, sz_fslist_arg); Doesn't check allocation failure. fixed it. + + sz_fslist = sizeof(*fslist) * fslist_arg-count; + kfree(fslist_arg); That allocation and copy and free gets a single u64. Use copy_from_user() for the u64. oh yes. thanks. + fslist_arg = memdup_user(arg, sz_fslist_arg + sz_fslist); Allocates an arbitrarily huge size that depends only on user input. Doesn't check failure again. And I bet you can scribble on kernel memory if you wrap the size. fixed it. now it finds the number of fsid and then allocates mem. + if (copy_to_user(arg, fslist_arg, sz_fslist_arg + sz_fslist)) + ret = -EFAULT; And there's no reason to buffer all this in the kernel to begin with. Just copy_to_user() as you iterate over each fs_devices. Ok in the v2 patch I have narrowed the allocation and copy to just what is present. but I still feel one-shot copy is better. Now I have also used uuid_mutex its bit less granular for the purpose here but taking into consideration that thread is from btrfs-control (and so no root pointer is readily available) for which it should be fine IMO. any comments. thanks. + fslist = (struct btrfs_ioctl_fslist *) fslist + + sizeof(*fslist); AKA fslist++. fixed it. - z Posted V2. Thanks, Anand -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] btrfs-progs: lblkid wouldn't find non mapper path input
Thanks for the comments. Sorry for the delay. more inline below. V2 has been sent out. On 10/30/13 12:40 AM, Josef Bacik wrote: On Wed, Oct 30, 2013 at 12:34:50AM +0800, Anand Jain wrote: A new test case when disk is unmounted and if the non mapper disk path is given as the argument to the btrfs filesystem showarg we still need this to work but lblkid will pull only mapper disks, it won't match. So this will normalize the input to find btrfs by fsid and pass it to the search. Signed-off-by: Anand Jainanand.j...@oracle.com --- cmds-filesystem.c | 52 +--- 1 files changed, 49 insertions(+), 3 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index fcabdb0..3a494fd 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -37,6 +37,7 @@ #include version.h #include commands.h #include list_sort.h +#include disk-io.h static const char * const filesystem_cmd_group_usage[] = { btrfs filesystem [group]command [args], @@ -414,6 +415,39 @@ static int btrfs_scan_kernel(void *search) return 0; } +static int dev_to_fsid(char *dev, __u8 *fsid) +{ + struct btrfs_super_block *disk_super; + char *buf; + int ret; + int fd; + + buf = malloc(4096); + if (!buf) + return -ENOMEM; + + fd = open(dev, O_RDONLY); + if (fd 0) { + ret = -errno; + free(buf); + return ret; + } + + disk_super = (struct btrfs_super_block *)buf; + ret = btrfs_read_dev_super(fd, disk_super, + BTRFS_SUPER_INFO_OFFSET); + if (ret) + goto out; + + memcpy(fsid, disk_super-fsid, BTRFS_FSID_SIZE); + ret = 0; + +out: + close(fd); + free(buf); + return ret; +} + static const char * const cmd_show_usage[] = { btrfs filesystem show [options] [path|uuid|device|label], Show the structure of a filesystem, @@ -434,6 +468,8 @@ static int cmd_show(int argc, char **argv) int type = 0; char mp[BTRFS_PATH_NAME_MAX + 1]; char path[PATH_MAX]; + __u8 fsid[BTRFS_FSID_SIZE]; + char uuid_buf[37]; No magic numbers. yep. but it followed the tradition # egrep 37 *.c | egrep char | wc -l 14 later I shall write a new patch to change all 14 together including this. while (1) { int long_index; @@ -480,11 +516,21 @@ static int cmd_show(int argc, char **argv) if (!ret) /* given block dev is mounted*/ search = mp; - else + else { This isn't the right format, needs to add braces for the if part too. ok. fixed it. (looks like checkpatch.pl needs an update which failed to catch this). + ret = dev_to_fsid(search, fsid); + if (ret) { + fprintf(stderr, + ERROR: No btrfs on %s\n, + search); + return 1; + } + uuid_unparse(fsid, uuid_buf); + search = uuid_buf; + type = BTRFS_ARG_UUID; goto devs_only; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { This looks like it will break something if we fall through from above? Thanks, Thanks for the comments. I reviewed again and I don't think so, here we need special handle if the input is a block dev (additionally if input is a mount-point we just want to finish the job). For rest of the input types (uuid or unknown = which could be a label) no special handling is required, just a fall though is fine. I have added the additional comments in the code. Thanks Anand Josef -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] btrfs: add framework to read fs info from btrfs-control
This adds ioctl BTRFS_IOC_GET_FSIDS which reads the fs info through the btrfs-control v2: accepts Zach suggested now holds uuid_mutex Signed-off-by: Anand Jain anand.j...@oracle.com --- fs/btrfs/super.c | 66 fs/btrfs/volumes.c | 39 ++ fs/btrfs/volumes.h |2 + include/uapi/linux/btrfs.h | 19 4 files changed, 120 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index e9c4e41..241f401 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1646,38 +1646,92 @@ static struct file_system_type btrfs_fs_type = { }; MODULE_ALIAS_FS(btrfs); +static int btrfs_ioc_get_fslist(void __user *arg) +{ + int ret = 0; + u64 sz_fslist_arg; + u64 sz_fslist; + u64 sz_out; + struct btrfs_ioctl_fslist_args *fslist_arg; + struct btrfs_ioctl_fslist_args *fslist_arg_tmp; + struct btrfs_ioctl_fslist *fslist; + + u64 cnt = 0, ucnt; + + sz_fslist_arg = sizeof(*fslist_arg); + sz_fslist = sizeof(*fslist); + if (copy_from_user(ucnt, + (struct btrfs_ioctl_fslist_args __user *)(arg + + offsetof(struct btrfs_ioctl_fslist_args, count)), + sizeof(ucnt))) + return -EFAULT; + + cnt = btrfs_get_fslist_cnt(); + + if (cnt ucnt) { + if (copy_to_user(arg + + offsetof(struct btrfs_ioctl_fslist_args, count), + cnt, sizeof(cnt))) + return -EFAULT; + return 1; + } + + sz_out = sz_fslist_arg + sz_fslist * cnt; + fslist_arg_tmp = fslist_arg = memdup_user(arg, sz_out); + if (IS_ERR(fslist_arg)) + return PTR_ERR(fslist_arg); + fslist = (struct btrfs_ioctl_fslist *) (++fslist_arg_tmp); + cnt = btrfs_get_fslist(fslist, cnt); + fslist_arg-count = cnt; + if (copy_to_user(arg, fslist_arg, sz_out)) { + ret = -EFAULT; + goto out; + } + ret = 0; +out: + kfree(fslist_arg); + return ret; +} + /* * used by btrfsctl to scan devices when no FS is mounted */ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct btrfs_ioctl_vol_args *vol; + struct btrfs_ioctl_vol_args *vol = NULL; struct btrfs_fs_devices *fs_devices; int ret = -ENOTTY; + void __user *argp = (void __user *)arg; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - vol = memdup_user((void __user *)arg, sizeof(*vol)); - if (IS_ERR(vol)) - return PTR_ERR(vol); - switch (cmd) { case BTRFS_IOC_SCAN_DEV: + vol = memdup_user((void __user *)arg, sizeof(*vol)); + if (IS_ERR(vol)) + return PTR_ERR(vol); ret = btrfs_scan_one_device(vol-name, FMODE_READ, btrfs_fs_type, fs_devices); + kfree(vol); break; case BTRFS_IOC_DEVICES_READY: + vol = memdup_user((void __user *)arg, sizeof(*vol)); + if (IS_ERR(vol)) + return PTR_ERR(vol); ret = btrfs_scan_one_device(vol-name, FMODE_READ, btrfs_fs_type, fs_devices); + kfree(vol); if (ret) break; ret = !(fs_devices-num_devices == fs_devices-total_devices); break; + case BTRFS_IOC_GET_FSLIST: + ret = btrfs_ioc_get_fslist(argp); + break; } - kfree(vol); return ret; } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5103cfe..b114372 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6289,3 +6289,42 @@ int btrfs_scratch_superblock(struct btrfs_device *device) return 0; } + +int btrfs_get_fslist_cnt(void) +{ + int cnt = 0; + struct btrfs_fs_devices *fs_devices; + + mutex_lock(uuid_mutex); + list_for_each_entry(fs_devices, fs_uuids, list) + cnt++; + mutex_unlock(uuid_mutex); + + return cnt; +} + +u64 btrfs_get_fslist(struct btrfs_ioctl_fslist *fslist, u64 ucnt) +{ + u64 cnt = 0; + struct btrfs_fs_devices *fs_devices; + + mutex_lock(uuid_mutex); + list_for_each_entry(fs_devices, fs_uuids, list) { + if (!(cnt ucnt)) + break; + memcpy(fslist-fsid, fs_devices-fsid, + BTRFS_FSID_SIZE); + fslist-num_devices = fs_devices-num_devices; + fslist-missing_devices = fs_devices-missing_devices; + fslist-total_devices = fs_devices-total_devices; + + if (fs_devices-opened) +
[PATCH 4/4 v2] btrfs-progs: lblkid wouldn't find non mapper path input
A new test case when disk is unmounted and if the non mapper disk path is given as the argument to the btrfs filesystem show arg we still need this to work but lblkid will pull only mapper disks, it won't match. So this will normalize the input to find btrfs by fsid and pass it to the search. v2: accepts Josef suggested Signed-off-by: Anand Jain anand.j...@oracle.com --- cmds-filesystem.c | 59 +--- 1 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cmds-filesystem.c b/cmds-filesystem.c index f8e8475..f40178a 100644 --- a/cmds-filesystem.c +++ b/cmds-filesystem.c @@ -37,6 +37,7 @@ #include version.h #include commands.h #include list_sort.h +#include disk-io.h static const char * const filesystem_cmd_group_usage[] = { btrfs filesystem [group] command [args], @@ -414,6 +415,39 @@ static int btrfs_scan_kernel(void *search) return 0; } +static int dev_to_fsid(char *dev, __u8 *fsid) +{ + struct btrfs_super_block *disk_super; + char *buf; + int ret; + int fd; + + buf = malloc(4096); + if (!buf) + return -ENOMEM; + + fd = open(dev, O_RDONLY); + if (fd 0) { + ret = -errno; + free(buf); + return ret; + } + + disk_super = (struct btrfs_super_block *)buf; + ret = btrfs_read_dev_super(fd, disk_super, + BTRFS_SUPER_INFO_OFFSET); + if (ret) + goto out; + + memcpy(fsid, disk_super-fsid, BTRFS_FSID_SIZE); + ret = 0; + +out: + close(fd); + free(buf); + return ret; +} + static const char * const cmd_show_usage[] = { btrfs filesystem show [options] [path|uuid|device|label], Show the structure of a filesystem, @@ -434,6 +468,8 @@ static int cmd_show(int argc, char **argv) int type = 0; char mp[BTRFS_PATH_NAME_MAX + 1]; char path[PATH_MAX]; + __u8 fsid[BTRFS_FSID_SIZE]; + char uuid_buf[37]; while (1) { int long_index; @@ -466,6 +502,10 @@ static int cmd_show(int argc, char **argv) if (strlen(search) == 0) usage(cmd_show_usage); type = check_arg_type(search); + /*needs spl handling if input arg is block dev +*And if input arg is mount-point just print it +*right away + */ if (type == BTRFS_ARG_BLKDEV) { if (where == BTRFS_SCAN_DEV) { /* we need to do this because @@ -477,14 +517,25 @@ static int cmd_show(int argc, char **argv) } else { ret = get_btrfs_mount(search, mp, sizeof(mp)); - if (!ret) + if (!ret) { /* given block dev is mounted*/ search = mp; - else + type = BTRFS_ARG_MNTPOINT; + } else { + ret = dev_to_fsid(search, fsid); + if (ret) { + fprintf(stderr, + ERROR: No btrfs on %s\n, + search); + return 1; + } + uuid_unparse(fsid, uuid_buf); + search = uuid_buf; + type = BTRFS_ARG_UUID; goto devs_only; + } } - } - if (type == BTRFS_ARG_MNTPOINT) { + } else if (type == BTRFS_ARG_MNTPOINT) { char label[BTRFS_LABEL_SIZE]; if (get_label_mounted(search, label)) return 1; -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-btrfs in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html