diff options
Diffstat (limited to 'src/basic/btrfs-util.c')
| -rw-r--r-- | src/basic/btrfs-util.c | 71 | 
1 files changed, 54 insertions, 17 deletions
| diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index 4c90bc0c80..be40dc5702 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -105,7 +105,7 @@ int btrfs_is_filesystem(int fd) {          return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);  } -int btrfs_is_subvol(int fd) { +int btrfs_is_subvol_fd(int fd) {          struct stat st;          assert(fd >= 0); @@ -121,6 +121,18 @@ int btrfs_is_subvol(int fd) {          return btrfs_is_filesystem(fd);  } +int btrfs_is_subvol(const char *path) { +        _cleanup_close_ int fd = -1; + +        assert(path); + +        fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); +        if (fd < 0) +                return -errno; + +        return btrfs_is_subvol_fd(fd); +} +  int btrfs_subvol_make(const char *path) {          struct btrfs_ioctl_vol_args args = {};          _cleanup_close_ int fd = -1; @@ -575,8 +587,12 @@ int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {                  unsigned i;                  args.key.nr_items = 256; -                if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) +                if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { +                        if (errno == ENOENT) /* quota tree is missing: quota disabled */ +                                break; +                          return -errno; +                }                  if (args.key.nr_items <= 0)                          break; @@ -1006,6 +1022,10 @@ static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {          for (c = 0;; c++) {                  if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) { +                        /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */ +                        if (errno == EINVAL) +                                return -ENOPROTOOPT; +                          if (errno == EBUSY && c < 10) {                                  (void) btrfs_quota_scan_wait(fd);                                  continue; @@ -1335,8 +1355,12 @@ int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupi                  unsigned i;                  args.key.nr_items = 256; -                if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) +                if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { +                        if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */ +                                break; +                          return -errno; +                }                  if (args.key.nr_items <= 0)                          break; @@ -1411,12 +1435,16 @@ static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_sub                  return n_old_qgroups;          r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id); -        if (r < 0) +        if (r == -ENXIO) +                /* We have no parent, hence nothing to copy. */ +                n_old_parent_qgroups = 0; +        else if (r < 0)                  return r; - -        n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups); -        if (n_old_parent_qgroups < 0) -                return n_old_parent_qgroups; +        else { +                n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups); +                if (n_old_parent_qgroups < 0) +                        return n_old_parent_qgroups; +        }          for (i = 0; i < n_old_qgroups; i++) {                  uint64_t id; @@ -1670,7 +1698,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag          assert(old_fd >= 0);          assert(new_path); -        r = btrfs_is_subvol(old_fd); +        r = btrfs_is_subvol_fd(old_fd);          if (r < 0)                  return r;          if (r == 0) { @@ -1766,8 +1794,12 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {                  unsigned i;                  args.key.nr_items = 256; -                if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) +                if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { +                        if (errno == ENOENT) /* quota tree missing: quota is disabled */ +                                break; +                          return -errno; +                }                  if (args.key.nr_items <= 0)                          break; @@ -1852,7 +1884,7 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed           */          if (subvol_id == 0) { -                r = btrfs_is_subvol(fd); +                r = btrfs_is_subvol_fd(fd);                  if (r < 0)                          return r;                  if (!r) @@ -1869,14 +1901,19 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed          if (n > 0) /* already parent qgroups set up, let's bail */                  return 0; +        qgroups = mfree(qgroups); +          r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol); -        if (r < 0) +        if (r == -ENXIO) +                /* No parent, hence no qgroup memberships */ +                n = 0; +        else if (r < 0)                  return r; - -        qgroups = mfree(qgroups); -        n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups); -        if (n < 0) -                return n; +        else { +                n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups); +                if (n < 0) +                        return n; +        }          if (insert_intermediary_qgroup) {                  uint64_t lowest = 256, new_qgroupid; | 
