Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / fs / btrfs / volumes.c
index a324480..bdfe449 100644 (file)
@@ -3845,7 +3845,11 @@ static int alloc_profile_is_valid(u64 flags, int extended)
                return !extended; /* "0" is valid for usual profiles */
 
        /* true if exactly one bit set */
-       return is_power_of_2(flags);
+       /*
+        * Don't use is_power_of_2(unsigned long) because it won't work
+        * for the single profile (1ULL << 48) on 32-bit CPUs.
+        */
+       return flags != 0 && (flags & (flags - 1)) == 0;
 }
 
 static inline int balance_need_close(struct btrfs_fs_info *fs_info)
@@ -4063,7 +4067,13 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
        }
 
        num_devices = btrfs_num_devices(fs_info);
-       allowed = 0;
+
+       /*
+        * SINGLE profile on-disk has no profile bit, but in-memory we have a
+        * special bit for it, to make it easier to distinguish.  Thus we need
+        * to set it manually, or balance would refuse the profile.
+        */
+       allowed = BTRFS_AVAIL_ALLOC_BIT_SINGLE;
        for (i = 0; i < ARRAY_SIZE(btrfs_raid_array); i++)
                if (num_devices >= btrfs_raid_array[i].devs_min)
                        allowed |= btrfs_raid_array[i].bg_flag;