btrfs-progs: Schedule quota rescan if qgroup assign caused inconsistence.
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Fri, 27 Feb 2015 08:26:39 +0000 (16:26 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 31 Aug 2015 17:25:11 +0000 (19:25 +0200)
NOTE: This patch needs to cooperate with kernel patches, which will fix
a kernel bug that never clear INCONSISTENT bit and return 1 if quota
assign makes qgroup data inconsistent.

Some qgroup assign will cause qgroup data inconsistent, like remove a
qgroup with shared extents from a parent qgroup. But some won't, like
assign a empty(OK, nodesize rfer and exel) to a qgroup.

Newer kernel will return 1 if qgroup data inconsistent and in that case
we should schedule a quota rescan.

This patch will do this in btrfs-progs.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
cmds-qgroup.c

index 9a7de34..6436e9c 100644 (file)
@@ -64,13 +64,33 @@ static int qgroup_assign(int assign, int argc, char **argv)
 
        ret = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args);
        e = errno;
-       close_file_or_dir(fd, dirstream);
        if (ret < 0) {
                fprintf(stderr, "ERROR: unable to assign quota group: %s\n",
                        strerror(e));
+               close_file_or_dir(fd, dirstream);
                return 1;
        }
-       return 0;
+
+       /*
+        * If ret > 0, it means assign caused qgroup data inconsistent state.
+        * Schedule a quota rescan if requested.
+        *
+        * The return value change only happens in newer kernel. But will not
+        * cause problem since old kernel has a bug that will never clear
+        * INCONSISTENT bit.
+        */
+       if (ret > 0) {
+               struct btrfs_ioctl_quota_rescan_args args;
+
+               printf("Quota data changed, quota rescan scheduled\n");
+               memset(&args, 0, sizeof(args));
+               ret = ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &args);
+               if (ret < 0)
+                       fprintf(stderr, "ERROR: quota rescan failed: %s\n",
+                               strerror(errno));
+       }
+       close_file_or_dir(fd, dirstream);
+       return ret;
 }
 
 static int qgroup_create(int create, int argc, char **argv)