btrfs: add helper to describe block group flags
[sfrench/cifs-2.6.git] / fs / btrfs / volumes.c
index 2ebc827bed88ffc5c9eb08d2243654dded09fe43..bb38b86b837441a33a70edd286271c7723d3febe 100644 (file)
@@ -130,6 +130,60 @@ const char *get_raid_name(enum btrfs_raid_types type)
        return btrfs_raid_array[type].raid_name;
 }
 
+/*
+ * Fill @buf with textual description of @bg_flags, no more than @size_buf
+ * bytes including terminating null byte.
+ */
+void btrfs_describe_block_groups(u64 bg_flags, char *buf, u32 size_buf)
+{
+       int i;
+       int ret;
+       char *bp = buf;
+       u64 flags = bg_flags;
+       u32 size_bp = size_buf;
+
+       if (!flags) {
+               strcpy(bp, "NONE");
+               return;
+       }
+
+#define DESCRIBE_FLAG(flag, desc)                                              \
+       do {                                                            \
+               if (flags & (flag)) {                                   \
+                       ret = snprintf(bp, size_bp, "%s|", (desc));     \
+                       if (ret < 0 || ret >= size_bp)                  \
+                               goto out_overflow;                      \
+                       size_bp -= ret;                                 \
+                       bp += ret;                                      \
+                       flags &= ~(flag);                               \
+               }                                                       \
+       } while (0)
+
+       DESCRIBE_FLAG(BTRFS_BLOCK_GROUP_DATA, "data");
+       DESCRIBE_FLAG(BTRFS_BLOCK_GROUP_SYSTEM, "system");
+       DESCRIBE_FLAG(BTRFS_BLOCK_GROUP_METADATA, "metadata");
+
+       DESCRIBE_FLAG(BTRFS_AVAIL_ALLOC_BIT_SINGLE, "single");
+       for (i = 0; i < BTRFS_NR_RAID_TYPES; i++)
+               DESCRIBE_FLAG(btrfs_raid_array[i].bg_flag,
+                             btrfs_raid_array[i].raid_name);
+#undef DESCRIBE_FLAG
+
+       if (flags) {
+               ret = snprintf(bp, size_bp, "0x%llx|", flags);
+               size_bp -= ret;
+       }
+
+       if (size_bp < size_buf)
+               buf[size_buf - size_bp - 1] = '\0'; /* remove last | */
+
+       /*
+        * The text is trimmed, it's up to the caller to provide sufficiently
+        * large buffer
+        */
+out_overflow:;
+}
+
 static int init_first_rw_device(struct btrfs_trans_handle *trans,
                                struct btrfs_fs_info *fs_info);
 static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info);