summaryrefslogtreecommitdiffstats
path: root/fs/udf/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/super.c')
-rw-r--r--fs/udf/super.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 4942549e7dc8..14b4bc1f6801 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -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)