btrfs-progs: fi du: don't call lookup_path_rootid for BTRFS_EMPTY_SUBVOL_DIR_OBJECTID
authorGoffredo Baroncelli <kreijack@inwind.it>
Fri, 18 Aug 2017 07:04:21 +0000 (09:04 +0200)
committerDavid Sterba <dsterba@suse.com>
Fri, 8 Sep 2017 14:15:05 +0000 (16:15 +0200)
When ino is BTRFS_EMPTY_SUBVOL_DIR_OBJECTID, the item is not referred to
any file-tree. So lookup_path_rootid() doesn't return any meaningful
value.

As was reported, this can be triggered by

$ btrfs sub create test1
$ btrfs sub create test1/test2
$ btrfs sub snap test1 test1.snap
$ btrfs fi du -s test1
  Total   Exclusive  Set shared  Filename
  0.00B       0.00B       0.00B  test1
$ btrfs fi du -s test1.snap
  Total   Exclusive  Set shared  Filename
ERROR: cannot check space of 'test1.snap': Inappropriate ioctl for device

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
Signed-off-by: David Sterba <dsterba@suse.com>
cmds-fi-du.c
ctree.h

index 4bf6af3..8a44665 100644 (file)
@@ -433,7 +433,6 @@ static int du_add_file(const char *filename, int dirfd,
        u64 file_total = 0;
        u64 file_shared = 0;
        u64 dir_set_shared = 0;
-       u64 subvol;
        int fd;
        DIR *dirstream = NULL;
 
@@ -462,16 +461,24 @@ static int du_add_file(const char *filename, int dirfd,
                goto out;
        }
 
-       ret = lookup_path_rootid(fd, &subvol);
-       if (ret)
-               goto out_close;
+       /*
+        * If st.st_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID ==2, there is no any
+        * related tree
+        */
+       if (st.st_ino != BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) {
+               u64 subvol;
 
-       if (inode_seen(st.st_ino, subvol))
-               goto out_close;
+               ret = lookup_path_rootid(fd, &subvol);
+               if (ret)
+                       goto out_close;
 
-       ret = mark_inode_seen(st.st_ino, subvol);
-       if (ret)
-               goto out_close;
+               if (inode_seen(st.st_ino, subvol))
+                       goto out_close;
+
+               ret = mark_inode_seen(st.st_ino, subvol);
+               if (ret)
+                       goto out_close;
+       }
 
        if (S_ISREG(st.st_mode)) {
                ret = du_calc_file_space(fd, shared_extents, &file_total,
diff --git a/ctree.h b/ctree.h
index 2818441..81c193f 100644 (file)
--- a/ctree.h
+++ b/ctree.h
@@ -138,6 +138,8 @@ struct btrfs_free_space_ctl;
  */
 #define BTRFS_DEV_ITEMS_OBJECTID 1ULL
 
+#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2ULL
+
 /*
  * the max metadata block size.  This limit is somewhat artificial,
  * but the memmove costs go through the roof for larger blocks.