sh: convert /proc/cpu/aligmnent, /proc/cpu/kernel_alignment to seq_file
[safe/jmp/linux-2.6] / fs / udf / super.c
index 3c2d35d..9d1b8c2 100644 (file)
@@ -81,12 +81,9 @@ static char error_buf[1024];
 /* These are the "meat" - everything else is stuffing */
 static int udf_fill_super(struct super_block *, void *, int);
 static void udf_put_super(struct super_block *);
-static void udf_write_super(struct super_block *);
+static int udf_sync_fs(struct super_block *, int);
 static int udf_remount_fs(struct super_block *, int *, char *);
-static int udf_check_valid(struct super_block *, int, int);
-static int udf_vrs(struct super_block *sb, int silent);
 static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
-static void udf_find_anchor(struct super_block *);
 static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *,
                            struct kernel_lb_addr *);
 static void udf_load_fileset(struct super_block *, struct buffer_head *,
@@ -181,7 +178,7 @@ static const struct super_operations udf_sb_ops = {
        .delete_inode   = udf_delete_inode,
        .clear_inode    = udf_clear_inode,
        .put_super      = udf_put_super,
-       .write_super    = udf_write_super,
+       .sync_fs        = udf_sync_fs,
        .statfs         = udf_statfs,
        .remount_fs     = udf_remount_fs,
        .show_options   = udf_show_options,
@@ -260,7 +257,7 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt)
 
        if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT))
                seq_puts(seq, ",nostrict");
-       if (sb->s_blocksize != UDF_DEFAULT_BLOCKSIZE)
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET))
                seq_printf(seq, ",bs=%lu", sb->s_blocksize);
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
                seq_puts(seq, ",unhide");
@@ -292,14 +289,8 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt)
                seq_printf(seq, ",session=%u", sbi->s_session);
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET))
                seq_printf(seq, ",lastblock=%u", sbi->s_last_block);
-       /*
-        * s_anchor[2] could be zeroed out in case there is no anchor
-        * in the specified block, but then the "anchor=N" option
-        * originally given by the user wasn't effective, so it's OK
-        * if we don't show it.
-        */
-       if (sbi->s_anchor[2] != 0)
-               seq_printf(seq, ",anchor=%u", sbi->s_anchor[2]);
+       if (sbi->s_anchor != 0)
+               seq_printf(seq, ",anchor=%u", sbi->s_anchor);
        /*
         * volume, partition, fileset and rootdir seem to be ignored
         * currently
@@ -416,7 +407,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
        int option;
 
        uopt->novrs = 0;
-       uopt->blocksize = UDF_DEFAULT_BLOCKSIZE;
        uopt->partition = 0xFFFF;
        uopt->session = 0xFFFFFFFF;
        uopt->lastblock = 0;
@@ -439,10 +429,12 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
                switch (token) {
                case Opt_novrs:
                        uopt->novrs = 1;
+                       break;
                case Opt_bs:
                        if (match_int(&args[0], &option))
                                return 0;
                        uopt->blocksize = option;
+                       uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET);
                        break;
                case Opt_unhide:
                        uopt->flags |= (1 << UDF_FLAG_UNHIDE);
@@ -561,17 +553,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
        return 1;
 }
 
-static void udf_write_super(struct super_block *sb)
-{
-       lock_kernel();
-
-       if (!(sb->s_flags & MS_RDONLY))
-               udf_open_lvid(sb);
-       sb->s_dirt = 0;
-
-       unlock_kernel();
-}
-
 static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
 {
        struct udf_options uopt;
@@ -587,6 +568,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
        if (!udf_parse_options(options, &uopt, true))
                return -EINVAL;
 
+       lock_kernel();
        sbi->s_flags = uopt.flags;
        sbi->s_uid   = uopt.uid;
        sbi->s_gid   = uopt.gid;
@@ -600,32 +582,32 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
                        *flags |= MS_RDONLY;
        }
 
-       if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+       if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
+               unlock_kernel();
                return 0;
+       }
        if (*flags & MS_RDONLY)
                udf_close_lvid(sb);
        else
                udf_open_lvid(sb);
 
+       unlock_kernel();
        return 0;
 }
 
-static int udf_vrs(struct super_block *sb, int silent)
+/* Check Volume Structure Descriptors (ECMA 167 2/9.1) */
+/* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
+static loff_t udf_check_vsd(struct super_block *sb)
 {
        struct volStructDesc *vsd = NULL;
        loff_t sector = 32768;
        int sectorsize;
        struct buffer_head *bh = NULL;
-       int iso9660 = 0;
        int nsr02 = 0;
        int nsr03 = 0;
        struct udf_sb_info *sbi;
 
-       /* Block size must be a multiple of 512 */
-       if (sb->s_blocksize & 511)
-               return 0;
        sbi = UDF_SB(sb);
-
        if (sb->s_blocksize < sizeof(struct volStructDesc))
                sectorsize = sizeof(struct volStructDesc);
        else
@@ -652,7 +634,6 @@ static int udf_vrs(struct super_block *sb, int silent)
                        break;
                } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,
                                    VSD_STD_ID_LEN)) {
-                       iso9660 = sector;
                        switch (vsd->structType) {
                        case 0:
                                udf_debug("ISO9660 Boot Record found\n");
@@ -704,139 +685,6 @@ static int udf_vrs(struct super_block *sb, int silent)
                return 0;
 }
 
-/*
- * Check whether there is an anchor block in the given block
- */
-static int udf_check_anchor_block(struct super_block *sb, sector_t block)
-{
-       struct buffer_head *bh;
-       uint16_t ident;
-
-       if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
-           udf_fixed_to_variable(block) >=
-           sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
-               return 0;
-
-       bh = udf_read_tagged(sb, block, block, &ident);
-       if (!bh)
-               return 0;
-       brelse(bh);
-
-       return ident == TAG_IDENT_AVDP;
-}
-
-/* Search for an anchor volume descriptor pointer */
-static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock)
-{
-       sector_t last[6];
-       int i;
-       struct udf_sb_info *sbi = UDF_SB(sb);
-       int last_count = 0;
-
-       last[last_count++] = lastblock;
-       if (lastblock >= 1)
-               last[last_count++] = lastblock - 1;
-       last[last_count++] = lastblock + 1;
-       if (lastblock >= 2)
-               last[last_count++] = lastblock - 2;
-       if (lastblock >= 150)
-               last[last_count++] = lastblock - 150;
-       if (lastblock >= 152)
-               last[last_count++] = lastblock - 152;
-
-       /*  according to spec, anchor is in either:
-        *     block 256
-        *     lastblock-256
-        *     lastblock
-        *  however, if the disc isn't closed, it could be 512 */
-
-       for (i = 0; i < last_count; i++) {
-               if (last[i] >= sb->s_bdev->bd_inode->i_size >>
-                               sb->s_blocksize_bits)
-                       continue;
-
-               if (udf_check_anchor_block(sb, last[i])) {
-                       sbi->s_anchor[0] = last[i];
-                       sbi->s_anchor[1] = last[i] - 256;
-                       return last[i];
-               }
-
-               if (last[i] < 256)
-                       continue;
-
-               if (udf_check_anchor_block(sb, last[i] - 256)) {
-                       sbi->s_anchor[1] = last[i] - 256;
-                       return last[i];
-               }
-       }
-
-       if (udf_check_anchor_block(sb, sbi->s_session + 256)) {
-               sbi->s_anchor[0] = sbi->s_session + 256;
-               return last[0];
-       }
-       if (udf_check_anchor_block(sb, sbi->s_session + 512)) {
-               sbi->s_anchor[0] = sbi->s_session + 512;
-               return last[0];
-       }
-       return 0;
-}
-
-/*
- * Find an anchor volume descriptor. The function expects sbi->s_lastblock to
- * be the last block on the media.
- *
- * Return 1 if not found, 0 if ok
- *
- */
-static void udf_find_anchor(struct super_block *sb)
-{
-       sector_t lastblock;
-       struct buffer_head *bh = NULL;
-       uint16_t ident;
-       int i;
-       struct udf_sb_info *sbi = UDF_SB(sb);
-
-       lastblock = udf_scan_anchors(sb, sbi->s_last_block);
-       if (lastblock)
-               goto check_anchor;
-
-       /* No anchor found? Try VARCONV conversion of block numbers */
-       UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
-       /* Firstly, we try to not convert number of the last block */
-       lastblock = udf_scan_anchors(sb,
-                               udf_variable_to_fixed(sbi->s_last_block));
-       if (lastblock)
-               goto check_anchor;
-
-       /* Secondly, we try with converted number of the last block */
-       lastblock = udf_scan_anchors(sb, sbi->s_last_block);
-       if (!lastblock) {
-               /* VARCONV didn't help. Clear it. */
-               UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
-       }
-
-check_anchor:
-       /*
-        * Check located anchors and the anchor block supplied via
-        * mount options
-        */
-       for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
-               if (!sbi->s_anchor[i])
-                       continue;
-               bh = udf_read_tagged(sb, sbi->s_anchor[i],
-                                       sbi->s_anchor[i], &ident);
-               if (!bh)
-                       sbi->s_anchor[i] = 0;
-               else {
-                       brelse(bh);
-                       if (ident != TAG_IDENT_AVDP)
-                               sbi->s_anchor[i] = 0;
-               }
-       }
-
-       sbi->s_last_block = lastblock;
-}
-
 static int udf_find_fileset(struct super_block *sb,
                            struct kernel_lb_addr *fileset,
                            struct kernel_lb_addr *root)
@@ -1239,11 +1087,23 @@ 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;
 
        /* VAT file entry is in the last recorded block */
        ino.partitionReferenceNum = type1_index;
        ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
        sbi->s_vat_inode = udf_iget(sb, &ino);
+       if (!sbi->s_vat_inode &&
+           sbi->s_last_block != blocks - 1) {
+               printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the"
+                      " last recorded block (%lu), retrying with the last "
+                      "block of the device (%lu).\n",
+                      (unsigned long)sbi->s_last_block,
+                      (unsigned long)blocks - 1);
+               ino.partitionReferenceNum = type1_index;
+               ino.logicalBlockNum = blocks - 1 - map->s_partition_root;
+               sbi->s_vat_inode = udf_iget(sb, &ino);
+       }
        if (!sbi->s_vat_inode)
                return 1;
 
@@ -1697,85 +1557,199 @@ static noinline int udf_process_sequence(struct super_block *sb, long block,
        return 0;
 }
 
+static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh,
+                            struct kernel_lb_addr *fileset)
+{
+       struct anchorVolDescPtr *anchor;
+       long main_s, main_e, reserve_s, reserve_e;
+       struct udf_sb_info *sbi;
+
+       sbi = UDF_SB(sb);
+       anchor = (struct anchorVolDescPtr *)bh->b_data;
+
+       /* Locate the main sequence */
+       main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation);
+       main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength);
+       main_e = main_e >> sb->s_blocksize_bits;
+       main_e += main_s;
+
+       /* Locate the reserve sequence */
+       reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation);
+       reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength);
+       reserve_e = reserve_e >> sb->s_blocksize_bits;
+       reserve_e += reserve_s;
+
+       /* Process the main & reserve sequences */
+       /* responsible for finding the PartitionDesc(s) */
+       if (!udf_process_sequence(sb, main_s, main_e, fileset))
+               return 1;
+       return !udf_process_sequence(sb, reserve_s, reserve_e, fileset);
+}
+
 /*
- * udf_check_valid()
+ * Check whether there is an anchor block in the given block and
+ * load Volume Descriptor Sequence if so.
  */
-static int udf_check_valid(struct super_block *sb, int novrs, int silent)
+static int udf_check_anchor_block(struct super_block *sb, sector_t block,
+                                 struct kernel_lb_addr *fileset)
 {
-       long block;
-       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct buffer_head *bh;
+       uint16_t ident;
+       int ret;
 
-       if (novrs) {
-               udf_debug("Validity check skipped because of novrs option\n");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
+           udf_fixed_to_variable(block) >=
+           sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
+               return 0;
+
+       bh = udf_read_tagged(sb, block, block, &ident);
+       if (!bh)
+               return 0;
+       if (ident != TAG_IDENT_AVDP) {
+               brelse(bh);
                return 0;
        }
-       /* Check that it is NSR02 compliant */
-       /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
-       block = udf_vrs(sb, silent);
-       if (block == -1)
-               udf_debug("Failed to read byte 32768. Assuming open "
-                         "disc. Skipping validity check\n");
-       if (block && !sbi->s_last_block)
-               sbi->s_last_block = udf_get_last_block(sb);
-       return !block;
+       ret = udf_load_sequence(sb, bh, fileset);
+       brelse(bh);
+       return ret;
 }
 
-static int udf_load_sequence(struct super_block *sb, struct kernel_lb_addr *fileset)
+/* Search for an anchor volume descriptor pointer */
+static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock,
+                                struct kernel_lb_addr *fileset)
 {
-       struct anchorVolDescPtr *anchor;
-       uint16_t ident;
-       struct buffer_head *bh;
-       long main_s, main_e, reserve_s, reserve_e;
+       sector_t last[6];
        int i;
-       struct udf_sb_info *sbi;
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       int last_count = 0;
 
-       if (!sb)
-               return 1;
-       sbi = UDF_SB(sb);
+       /* First try user provided anchor */
+       if (sbi->s_anchor) {
+               if (udf_check_anchor_block(sb, sbi->s_anchor, fileset))
+                       return lastblock;
+       }
+       /*
+        * according to spec, anchor is in either:
+        *     block 256
+        *     lastblock-256
+        *     lastblock
+        *  however, if the disc isn't closed, it could be 512.
+        */
+       if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset))
+               return lastblock;
+       /*
+        * The trouble is which block is the last one. Drives often misreport
+        * this so we try various possibilities.
+        */
+       last[last_count++] = lastblock;
+       if (lastblock >= 1)
+               last[last_count++] = lastblock - 1;
+       last[last_count++] = lastblock + 1;
+       if (lastblock >= 2)
+               last[last_count++] = lastblock - 2;
+       if (lastblock >= 150)
+               last[last_count++] = lastblock - 150;
+       if (lastblock >= 152)
+               last[last_count++] = lastblock - 152;
 
-       for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
-               if (!sbi->s_anchor[i])
+       for (i = 0; i < last_count; i++) {
+               if (last[i] >= sb->s_bdev->bd_inode->i_size >>
+                               sb->s_blocksize_bits)
                        continue;
-
-               bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i],
-                                    &ident);
-               if (!bh)
+               if (udf_check_anchor_block(sb, last[i], fileset))
+                       return last[i];
+               if (last[i] < 256)
                        continue;
+               if (udf_check_anchor_block(sb, last[i] - 256, fileset))
+                       return last[i];
+       }
 
-               anchor = (struct anchorVolDescPtr *)bh->b_data;
+       /* Finally try block 512 in case media is open */
+       if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset))
+               return last[0];
+       return 0;
+}
 
-               /* Locate the main sequence */
-               main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation);
-               main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength);
-               main_e = main_e >> sb->s_blocksize_bits;
-               main_e += main_s;
+/*
+ * Find an anchor volume descriptor and load Volume Descriptor Sequence from
+ * area specified by it. The function expects sbi->s_lastblock to be the last
+ * block on the media.
+ *
+ * Return 1 if ok, 0 if not found.
+ *
+ */
+static int udf_find_anchor(struct super_block *sb,
+                          struct kernel_lb_addr *fileset)
+{
+       sector_t lastblock;
+       struct udf_sb_info *sbi = UDF_SB(sb);
 
-               /* Locate the reserve sequence */
-               reserve_s = le32_to_cpu(
-                               anchor->reserveVolDescSeqExt.extLocation);
-               reserve_e = le32_to_cpu(
-                               anchor->reserveVolDescSeqExt.extLength);
-               reserve_e = reserve_e >> sb->s_blocksize_bits;
-               reserve_e += reserve_s;
+       lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
+       if (lastblock)
+               goto out;
 
-               brelse(bh);
+       /* No anchor found? Try VARCONV conversion of block numbers */
+       UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+       /* Firstly, we try to not convert number of the last block */
+       lastblock = udf_scan_anchors(sb,
+                               udf_variable_to_fixed(sbi->s_last_block),
+                               fileset);
+       if (lastblock)
+               goto out;
 
-               /* Process the main & reserve sequences */
-               /* responsible for finding the PartitionDesc(s) */
-               if (!(udf_process_sequence(sb, main_s, main_e,
-                                          fileset) &&
-                     udf_process_sequence(sb, reserve_s, reserve_e,
-                                          fileset)))
-                       break;
+       /* Secondly, we try with converted number of the last block */
+       lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset);
+       if (!lastblock) {
+               /* VARCONV didn't help. Clear it. */
+               UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
+               return 0;
        }
+out:
+       sbi->s_last_block = lastblock;
+       return 1;
+}
 
-       if (i == ARRAY_SIZE(sbi->s_anchor)) {
-               udf_debug("No Anchor block found\n");
-               return 1;
+/*
+ * Check Volume Structure Descriptor, find Anchor block and load Volume
+ * Descriptor Sequence
+ */
+static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
+                       int silent, struct kernel_lb_addr *fileset)
+{
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       loff_t nsr_off;
+
+       if (!sb_set_blocksize(sb, uopt->blocksize)) {
+               if (!silent)
+                       printk(KERN_WARNING "UDF-fs: Bad block size\n");
+               return 0;
+       }
+       sbi->s_last_block = uopt->lastblock;
+       if (!uopt->novrs) {
+               /* Check that it is NSR02 compliant */
+               nsr_off = udf_check_vsd(sb);
+               if (!nsr_off) {
+                       if (!silent)
+                               printk(KERN_WARNING "UDF-fs: No VRS found\n");
+                       return 0;
+               }
+               if (nsr_off == -1)
+                       udf_debug("Failed to read byte 32768. Assuming open "
+                                 "disc. Skipping validity check\n");
+               if (!sbi->s_last_block)
+                       sbi->s_last_block = udf_get_last_block(sb);
+       } else {
+               udf_debug("Validity check skipped because of novrs option\n");
        }
-       udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
 
-       return 0;
+       /* Look for anchor block and load Volume Descriptor Sequence */
+       sbi->s_anchor = uopt->anchor;
+       if (!udf_find_anchor(sb, fileset)) {
+               if (!silent)
+                       printk(KERN_WARNING "UDF-fs: No anchor found\n");
+               return 0;
+       }
+       return 1;
 }
 
 static void udf_open_lvid(struct super_block *sb)
@@ -1784,9 +1758,9 @@ static void udf_open_lvid(struct super_block *sb)
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
        struct logicalVolIntegrityDescImpUse *lvidiu;
+
        if (!bh)
                return;
-
        lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
        lvidiu = udf_sb_lvidiu(sbi);
 
@@ -1794,7 +1768,7 @@ static void udf_open_lvid(struct super_block *sb)
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
        udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
                                CURRENT_TIME);
-       lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
+       lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
 
        lvid->descTag.descCRC = cpu_to_le16(
                crc_itu_t(0, (char *)lvid + sizeof(struct tag),
@@ -1802,6 +1776,7 @@ static void udf_open_lvid(struct super_block *sb)
 
        lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
        mark_buffer_dirty(bh);
+       sbi->s_lvid_dirty = 0;
 }
 
 static void udf_close_lvid(struct super_block *sb)
@@ -1815,10 +1790,6 @@ static void udf_close_lvid(struct super_block *sb)
                return;
 
        lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
-
-       if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN)
-               return;
-
        lvidiu = udf_sb_lvidiu(sbi);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1837,6 +1808,7 @@ static void udf_close_lvid(struct super_block *sb)
 
        lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
        mark_buffer_dirty(bh);
+       sbi->s_lvid_dirty = 0;
 }
 
 static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
@@ -1888,6 +1860,7 @@ static void udf_free_partition(struct udf_part_map *map)
 static int udf_fill_super(struct super_block *sb, void *options, int silent)
 {
        int i;
+       int ret;
        struct inode *inode = NULL;
        struct udf_options uopt;
        struct kernel_lb_addr rootdir, fileset;
@@ -1940,13 +1913,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sbi->s_dmode = uopt.dmode;
        sbi->s_nls_map = uopt.nls_map;
 
-       /* Set the block size for all transfers */
-       if (!sb_min_blocksize(sb, uopt.blocksize)) {
-               udf_debug("Bad block size (%d)\n", uopt.blocksize);
-               printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize);
-               goto error_out;
-       }
-
        if (uopt.session == 0xFFFFFFFF)
                sbi->s_session = udf_get_last_session(sb);
        else
@@ -1954,18 +1920,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
        udf_debug("Multi-session=%d\n", sbi->s_session);
 
-       sbi->s_last_block = uopt.lastblock;
-       sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
-       sbi->s_anchor[2] = uopt.anchor;
-
-       if (udf_check_valid(sb, uopt.novrs, silent)) {
-               /* read volume recognition sequences */
-               printk(KERN_WARNING "UDF-fs: No VRS found\n");
-               goto error_out;
-       }
-
-       udf_find_anchor(sb);
-
        /* Fill in the rest of the superblock */
        sb->s_op = &udf_sb_ops;
        sb->s_export_op = &udf_export_ops;
@@ -1974,7 +1928,21 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sb->s_magic = UDF_SUPER_MAGIC;
        sb->s_time_gran = 1000;
 
-       if (udf_load_sequence(sb, &fileset)) {
+       if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) {
+               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 && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) {
+                       if (!silent)
+                               printk(KERN_NOTICE
+                                      "UDF-fs: Rescanning with blocksize "
+                                      "%d\n", UDF_DEFAULT_BLOCKSIZE);
+                       uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
+                       ret = udf_load_vrs(sb, &uopt, silent, &fileset);
+               }
+       }
+       if (!ret) {
                printk(KERN_WARNING "UDF-fs: No partition found (1)\n");
                goto error_out;
        }
@@ -2110,6 +2078,9 @@ static void udf_put_super(struct super_block *sb)
        struct udf_sb_info *sbi;
 
        sbi = UDF_SB(sb);
+
+       lock_kernel();
+
        if (sbi->s_vat_inode)
                iput(sbi->s_vat_inode);
        if (sbi->s_partitions)
@@ -2125,6 +2096,27 @@ static void udf_put_super(struct super_block *sb)
        kfree(sbi->s_partmaps);
        kfree(sb->s_fs_info);
        sb->s_fs_info = NULL;
+
+       unlock_kernel();
+}
+
+static int udf_sync_fs(struct super_block *sb, int wait)
+{
+       struct udf_sb_info *sbi = UDF_SB(sb);
+
+       mutex_lock(&sbi->s_alloc_mutex);
+       if (sbi->s_lvid_dirty) {
+               /*
+                * Blockdevice will be synced later so we don't have to submit
+                * the buffer for IO
+                */
+               mark_buffer_dirty(sbi->s_lvid_bh);
+               sb->s_dirt = 0;
+               sbi->s_lvid_dirty = 0;
+       }
+       mutex_unlock(&sbi->s_alloc_mutex);
+
+       return 0;
 }
 
 static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -2132,6 +2124,7 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct super_block *sb = dentry->d_sb;
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct logicalVolIntegrityDescImpUse *lvidiu;
+       u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
        if (sbi->s_lvid_bh != NULL)
                lvidiu = udf_sb_lvidiu(sbi);
@@ -2147,8 +2140,9 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
                                          le32_to_cpu(lvidiu->numDirs)) : 0)
                        + buf->f_bfree;
        buf->f_ffree = buf->f_bfree;
-       /* __kernel_fsid_t f_fsid */
        buf->f_namelen = UDF_NAME_LEN - 2;
+       buf->f_fsid.val[0] = (u32)id;
+       buf->f_fsid.val[1] = (u32)(id >> 32);
 
        return 0;
 }