udf: Fix free space reporting for metadata and virtual partitions
[sfrench/cifs-2.6.git] / fs / udf / super.c
index 2d0b90800519ded9bb1ba50d67f1d66857940eb5..5a4a6fb368194faa5a376d9d5ef7466521355590 100644 (file)
@@ -2492,17 +2492,29 @@ static unsigned int udf_count_free_table(struct super_block *sb,
 static unsigned int udf_count_free(struct super_block *sb)
 {
        unsigned int accum = 0;
-       struct udf_sb_info *sbi;
+       struct udf_sb_info *sbi = UDF_SB(sb);
        struct udf_part_map *map;
+       unsigned int part = sbi->s_partition;
+       int ptype = sbi->s_partmaps[part].s_partition_type;
+
+       if (ptype == UDF_METADATA_MAP25) {
+               part = sbi->s_partmaps[part].s_type_specific.s_metadata.
+                                                       s_phys_partition_ref;
+       } else if (ptype == UDF_VIRTUAL_MAP15 || ptype == UDF_VIRTUAL_MAP20) {
+               /*
+                * Filesystems with VAT are append-only and we cannot write to
+                * them. Let's just report 0 here.
+                */
+               return 0;
+       }
 
-       sbi = UDF_SB(sb);
        if (sbi->s_lvid_bh) {
                struct logicalVolIntegrityDesc *lvid =
                        (struct logicalVolIntegrityDesc *)
                        sbi->s_lvid_bh->b_data;
-               if (le32_to_cpu(lvid->numOfPartitions) > sbi->s_partition) {
+               if (le32_to_cpu(lvid->numOfPartitions) > part) {
                        accum = le32_to_cpu(
-                                       lvid->freeSpaceTable[sbi->s_partition]);
+                                       lvid->freeSpaceTable[part]);
                        if (accum == 0xFFFFFFFF)
                                accum = 0;
                }
@@ -2511,7 +2523,7 @@ static unsigned int udf_count_free(struct super_block *sb)
        if (accum)
                return accum;
 
-       map = &sbi->s_partmaps[sbi->s_partition];
+       map = &sbi->s_partmaps[part];
        if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) {
                accum += udf_count_free_bitmap(sb,
                                               map->s_uspace.s_bitmap);