udf: allow implicit blocksize specification during mount
[sfrench/cifs-2.6.git] / fs / udf / super.c
index 4942549e7dc8b3758dd8c8fadb99e8fba4265c00..14b4bc1f680131c20b774a75716875f50c5d7418 100644 (file)
@@ -264,9 +264,6 @@ static void __exit exit_udf_fs(void)
        destroy_inodecache();
 }
 
-module_init(init_udf_fs)
-module_exit(exit_udf_fs)
-
 static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
@@ -1216,7 +1213,8 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
        struct udf_inode_info *vati;
        uint32_t pos;
        struct virtualAllocationTable20 *vat20;
-       sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
+       sector_t blocks = i_size_read(sb->s_bdev->bd_inode) >>
+                         sb->s_blocksize_bits;
 
        udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
        if (!sbi->s_vat_inode &&
@@ -1806,7 +1804,7 @@ static int udf_check_anchor_block(struct super_block *sb, sector_t block,
 
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
            udf_fixed_to_variable(block) >=
-           sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
+           i_size_read(sb->s_bdev->bd_inode) >> sb->s_blocksize_bits)
                return -EAGAIN;
 
        bh = udf_read_tagged(sb, block, block, &ident);
@@ -1868,7 +1866,7 @@ static int udf_scan_anchors(struct super_block *sb, sector_t *lastblock,
                last[last_count++] = *lastblock - 152;
 
        for (i = 0; i < last_count; i++) {
-               if (last[i] >= sb->s_bdev->bd_inode->i_size >>
+               if (last[i] >= i_size_read(sb->s_bdev->bd_inode) >>
                                sb->s_blocksize_bits)
                        continue;
                ret = udf_check_anchor_block(sb, last[i], fileset);
@@ -1957,7 +1955,7 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
                if (!nsr_off) {
                        if (!silent)
                                udf_warn(sb, "No VRS found\n");
-                       return 0;
+                       return -EINVAL;
                }
                if (nsr_off == -1)
                        udf_debug("Failed to read sector at offset %d. "
@@ -1986,6 +1984,7 @@ static void udf_open_lvid(struct super_block *sb)
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
        struct logicalVolIntegrityDescImpUse *lvidiu;
+       struct timespec ts;
 
        if (!bh)
                return;
@@ -1997,8 +1996,8 @@ static void udf_open_lvid(struct super_block *sb)
        mutex_lock(&sbi->s_alloc_mutex);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-       udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
-                               CURRENT_TIME);
+       ktime_get_real_ts(&ts);
+       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
        lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
 
        lvid->descTag.descCRC = cpu_to_le16(
@@ -2019,6 +2018,7 @@ static void udf_close_lvid(struct super_block *sb)
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
        struct logicalVolIntegrityDescImpUse *lvidiu;
+       struct timespec ts;
 
        if (!bh)
                return;
@@ -2030,7 +2030,8 @@ static void udf_close_lvid(struct super_block *sb)
        mutex_lock(&sbi->s_alloc_mutex);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
+       ktime_get_real_ts(&ts);
+       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
        if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
                lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
        if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
@@ -2158,15 +2159,25 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                ret = udf_load_vrs(sb, &uopt, silent, &fileset);
        } else {
                uopt.blocksize = bdev_logical_block_size(sb->s_bdev);
-               ret = udf_load_vrs(sb, &uopt, silent, &fileset);
-               if (ret == -EAGAIN && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
-                       if (!silent)
-                               pr_notice("Rescanning with blocksize %d\n",
-                                         UDF_DEFAULT_BLOCKSIZE);
-                       brelse(sbi->s_lvid_bh);
-                       sbi->s_lvid_bh = NULL;
-                       uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
+               while (uopt.blocksize <= 4096) {
                        ret = udf_load_vrs(sb, &uopt, silent, &fileset);
+                       if (ret < 0) {
+                               if (!silent && ret != -EACCES) {
+                                       pr_notice("Scanning with blocksize %d failed\n",
+                                                 uopt.blocksize);
+                               }
+                               brelse(sbi->s_lvid_bh);
+                               sbi->s_lvid_bh = NULL;
+                               /*
+                                * EACCES is special - we want to propagate to
+                                * upper layers that we cannot handle RW mount.
+                                */
+                               if (ret == -EACCES)
+                                       break;
+                       } else
+                               break;
+
+                       uopt.blocksize <<= 1;
                }
        }
        if (ret < 0) {
@@ -2497,3 +2508,9 @@ static unsigned int udf_count_free(struct super_block *sb)
 
        return accum;
 }
+
+MODULE_AUTHOR("Ben Fennema");
+MODULE_DESCRIPTION("Universal Disk Format Filesystem");
+MODULE_LICENSE("GPL");
+module_init(init_udf_fs)
+module_exit(exit_udf_fs)