[PATCH 1/3] Btrfs: do not inc uncorrectable_errors counter on ro scrubs

2013-11-03 Thread Ilya Dryomov
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

2013-11-03 Thread Ilya Dryomov
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

2013-11-03 Thread Goffredo Baroncelli
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

2013-11-03 Thread Goffredo Baroncelli
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

2013-11-03 Thread Jeff Mahoney
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

2013-11-03 Thread Michael Eitelwein
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

2013-11-03 Thread Goffredo Baroncelli
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

2013-11-03 Thread Anand Jain
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

2013-11-03 Thread Anand Jain
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

2013-11-03 Thread Anand Jain
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

2013-11-03 Thread Anand Jain
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

2013-11-03 Thread Anand Jain
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

2013-11-03 Thread Anand Jain



 (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

2013-11-03 Thread Anand Jain



 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

2013-11-03 Thread Anand Jain
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

2013-11-03 Thread Anand Jain
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