]> Pileus Git - ~andy/linux/blobdiff - fs/udf/super.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-sched
[~andy/linux] / fs / udf / super.c
index 7f75a949e1525687369777813008fb90a972dbd5..f3ac4abfc9467a093ac54ebdef4283e9eaec166c 100644 (file)
@@ -53,6 +53,8 @@
 #include <linux/vfs.h>
 #include <linux/vmalloc.h>
 #include <linux/errno.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
 #include <asm/byteorder.h>
 
 #include <linux/udf_fs.h>
@@ -71,6 +73,8 @@
 #define VDS_POS_TERMINATING_DESC       6
 #define VDS_POS_LENGTH                 7
 
+#define UDF_DEFAULT_BLOCKSIZE 2048
+
 static char error_buf[1024];
 
 /* These are the "meat" - everything else is stuffing */
@@ -95,6 +99,7 @@ static void udf_open_lvid(struct super_block *);
 static void udf_close_lvid(struct super_block *);
 static unsigned int udf_count_free(struct super_block *);
 static int udf_statfs(struct dentry *, struct kstatfs *);
+static int udf_show_options(struct seq_file *, struct vfsmount *);
 
 struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
 {
@@ -181,6 +186,7 @@ static const struct super_operations udf_sb_ops = {
        .write_super    = udf_write_super,
        .statfs         = udf_statfs,
        .remount_fs     = udf_remount_fs,
+       .show_options   = udf_show_options,
 };
 
 struct udf_options {
@@ -247,6 +253,61 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
        return 0;
 }
 
+static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt)
+{
+       struct super_block *sb = mnt->mnt_sb;
+       struct udf_sb_info *sbi = UDF_SB(sb);
+
+       if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT))
+               seq_puts(seq, ",nostrict");
+       if (sb->s_blocksize != UDF_DEFAULT_BLOCKSIZE)
+               seq_printf(seq, ",bs=%lu", sb->s_blocksize);
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
+               seq_puts(seq, ",unhide");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
+               seq_puts(seq, ",undelete");
+       if (!UDF_QUERY_FLAG(sb, UDF_FLAG_USE_AD_IN_ICB))
+               seq_puts(seq, ",noadinicb");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_USE_SHORT_AD))
+               seq_puts(seq, ",shortad");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_FORGET))
+               seq_puts(seq, ",uid=forget");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_IGNORE))
+               seq_puts(seq, ",uid=ignore");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_FORGET))
+               seq_puts(seq, ",gid=forget");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_IGNORE))
+               seq_puts(seq, ",gid=ignore");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UID_SET))
+               seq_printf(seq, ",uid=%u", sbi->s_uid);
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_GID_SET))
+               seq_printf(seq, ",gid=%u", sbi->s_gid);
+       if (sbi->s_umask != 0)
+               seq_printf(seq, ",umask=%o", sbi->s_umask);
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET))
+               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]);
+       /*
+        * volume, partition, fileset and rootdir seem to be ignored
+        * currently
+        */
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
+               seq_puts(seq, ",utf8");
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP) && sbi->s_nls_map)
+               seq_printf(seq, ",iocharset=%s", sbi->s_nls_map->charset);
+
+       return 0;
+}
+
 /*
  * udf_parse_options
  *
@@ -339,13 +400,14 @@ static match_table_t tokens = {
        {Opt_err,       NULL}
 };
 
-static int udf_parse_options(char *options, struct udf_options *uopt)
+static int udf_parse_options(char *options, struct udf_options *uopt,
+                            bool remount)
 {
        char *p;
        int option;
 
        uopt->novrs = 0;
-       uopt->blocksize = 2048;
+       uopt->blocksize = UDF_DEFAULT_BLOCKSIZE;
        uopt->partition = 0xFFFF;
        uopt->session = 0xFFFFFFFF;
        uopt->lastblock = 0;
@@ -415,11 +477,15 @@ static int udf_parse_options(char *options, struct udf_options *uopt)
                        if (match_int(args, &option))
                                return 0;
                        uopt->session = option;
+                       if (!remount)
+                               uopt->flags |= (1 << UDF_FLAG_SESSION_SET);
                        break;
                case Opt_lastblock:
                        if (match_int(args, &option))
                                return 0;
                        uopt->lastblock = option;
+                       if (!remount)
+                               uopt->flags |= (1 << UDF_FLAG_LASTBLOCK_SET);
                        break;
                case Opt_anchor:
                        if (match_int(args, &option))
@@ -497,7 +563,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
        uopt.gid   = sbi->s_gid;
        uopt.umask = sbi->s_umask;
 
-       if (!udf_parse_options(options, &uopt))
+       if (!udf_parse_options(options, &uopt, true))
                return -EINVAL;
 
        sbi->s_flags = uopt.flags;
@@ -1014,20 +1080,20 @@ static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
                                le32_to_cpu(p->partitionLength); /* blocks */
                        map->s_partition_root =
                                le32_to_cpu(p->partitionStartingLocation);
-                       if (le32_to_cpu(p->accessType) ==
-                                       PD_ACCESS_TYPE_READ_ONLY)
+                       if (p->accessType ==
+                                       cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
                                map->s_partition_flags |=
                                                UDF_PART_FLAG_READ_ONLY;
-                       if (le32_to_cpu(p->accessType) ==
-                                       PD_ACCESS_TYPE_WRITE_ONCE)
+                       if (p->accessType ==
+                                       cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
                                map->s_partition_flags |=
                                                UDF_PART_FLAG_WRITE_ONCE;
-                       if (le32_to_cpu(p->accessType) ==
-                                       PD_ACCESS_TYPE_REWRITABLE)
+                       if (p->accessType ==
+                                       cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
                                map->s_partition_flags |=
                                                UDF_PART_FLAG_REWRITABLE;
-                       if (le32_to_cpu(p->accessType) ==
-                                       PD_ACCESS_TYPE_OVERWRITABLE)
+                       if (p->accessType ==
+                                   cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
                                map->s_partition_flags |=
                                                UDF_PART_FLAG_OVERWRITABLE;
 
@@ -1447,44 +1513,45 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
        sbi = UDF_SB(sb);
 
        for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) {
-               if (sbi->s_anchor[i] &&
-                   (bh = udf_read_tagged(sb, sbi->s_anchor[i],
-                                         sbi->s_anchor[i], &ident))) {
-                       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(
+               if (!sbi->s_anchor[i])
+                       continue;
+               bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i],
+                                    &ident);
+               if (!bh)
+                       continue;
+
+               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(
+               reserve_e = le32_to_cpu(
                                anchor->reserveVolDescSeqExt.extLength);
-                       reserve_e = reserve_e >> sb->s_blocksize_bits;
-                       reserve_e += reserve_s;
+               reserve_e = reserve_e >> sb->s_blocksize_bits;
+               reserve_e += reserve_s;
 
-                       brelse(bh);
+               brelse(bh);
 
-                       /* 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;
-               }
+               /* 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;
        }
 
        if (i == ARRAY_SIZE(sbi->s_anchor)) {
                udf_debug("No Anchor block found\n");
                return 1;
-       } else
-               udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
+       }
+       udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]);
 
        for (i = 0; i < sbi->s_partitions; i++) {
                kernel_lb_addr uninitialized_var(ino);
@@ -1564,7 +1631,6 @@ static void udf_open_lvid(struct super_block *sb)
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct buffer_head *bh = sbi->s_lvid_bh;
        if (bh) {
-               int i;
                kernel_timestamp cpu_time;
                struct logicalVolIntegrityDesc *lvid =
                                (struct logicalVolIntegrityDesc *)bh->b_data;
@@ -1582,12 +1648,7 @@ static void udf_open_lvid(struct super_block *sb)
                                le16_to_cpu(lvid->descTag.descCRCLength),
                                0));
 
-               lvid->descTag.tagChecksum = 0;
-               for (i = 0; i < 16; i++)
-                       if (i != 4)
-                               lvid->descTag.tagChecksum +=
-                                       ((uint8_t *) &(lvid->descTag))[i];
-
+               lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
                mark_buffer_dirty(bh);
        }
 }
@@ -1595,7 +1656,6 @@ static void udf_open_lvid(struct super_block *sb)
 static void udf_close_lvid(struct super_block *sb)
 {
        kernel_timestamp cpu_time;
-       int i;
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
@@ -1626,12 +1686,7 @@ static void udf_close_lvid(struct super_block *sb)
                                le16_to_cpu(lvid->descTag.descCRCLength),
                                0));
 
-               lvid->descTag.tagChecksum = 0;
-               for (i = 0; i < 16; i++)
-                       if (i != 4)
-                               lvid->descTag.tagChecksum +=
-                                       ((uint8_t *)&(lvid->descTag))[i];
-
+               lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
                mark_buffer_dirty(bh);
        }
 }
@@ -1690,7 +1745,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
        mutex_init(&sbi->s_alloc_mutex);
 
-       if (!udf_parse_options((char *)options, &uopt))
+       if (!udf_parse_options((char *)options, &uopt, false))
                goto error_out;
 
        if (uopt.flags & (1 << UDF_FLAG_UTF8) &&
@@ -1803,9 +1858,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        if (!silent) {
                kernel_timestamp ts;
                udf_time_to_stamp(&ts, sbi->s_record_time);
-               udf_info("UDF %s (%s) Mounting volume '%s', "
+               udf_info("UDF: Mounting volume '%s', "
                         "timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
-                        UDFFS_VERSION, UDFFS_DATE,
                         sbi->s_volume_ident, ts.year, ts.month, ts.day,
                         ts.hour, ts.minute, ts.typeAndTimezone);
        }
@@ -2058,7 +2112,7 @@ static unsigned int udf_count_free_table(struct super_block *sb,
 
        lock_kernel();
 
-       epos.block = UDF_I_LOCATION(table);
+       epos.block = UDF_I(table)->i_location;
        epos.offset = sizeof(struct unallocSpaceEntry);
        epos.bh = NULL;