Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / fs / udf / super.c
index bbad849..e45789f 100644 (file)
  *    http://www.ecma.ch/
  *    http://www.iso.org/
  *
- * CONTACTS
- *  E-mail regarding any portion of the Linux UDF file system should be
- *  directed to the development team mailing list (run by majordomo):
- *       linux_udf@hpesjro.fc.hp.com
- *
  * COPYRIGHT
  *  This file is distributed under the terms of the GNU General Public
  *  License (GPL). Copies of the GPL can be obtained from:
@@ -85,13 +80,13 @@ static void udf_write_super(struct super_block *);
 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 int udf_load_partition(struct super_block *, lb_addr *);
-static int udf_load_logicalvol(struct super_block *, struct buffer_head *, lb_addr *);
-static void udf_load_logicalvolint(struct super_block *, extent_ad);
+static int udf_load_partition(struct super_block *, kernel_lb_addr *);
+static int udf_load_logicalvol(struct super_block *, struct buffer_head *, kernel_lb_addr *);
+static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
 static void udf_find_anchor(struct super_block *);
-static int udf_find_fileset(struct super_block *, lb_addr *, lb_addr *);
+static int udf_find_fileset(struct super_block *, kernel_lb_addr *, kernel_lb_addr *);
 static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
-static void udf_load_fileset(struct super_block *, struct buffer_head *, lb_addr *);
+static void udf_load_fileset(struct super_block *, struct buffer_head *, kernel_lb_addr *);
 static void udf_load_partdesc(struct super_block *, struct buffer_head *);
 static void udf_open_lvid(struct super_block *);
 static void udf_close_lvid(struct super_block *);
@@ -145,7 +140,8 @@ static int init_inodecache(void)
 {
        udf_inode_cachep = kmem_cache_create("udf_inode_cache",
                                             sizeof(struct udf_inode_info),
-                                            0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+                                            0, (SLAB_RECLAIM_ACCOUNT|
+                                               SLAB_MEM_SPREAD),
                                             init_once, NULL);
        if (udf_inode_cachep == NULL)
                return -ENOMEM;
@@ -162,9 +158,7 @@ static void destroy_inodecache(void)
 static struct super_operations udf_sb_ops = {
        .alloc_inode            = udf_alloc_inode,
        .destroy_inode          = udf_destroy_inode,
-       .read_inode             = udf_read_inode,
        .write_inode            = udf_write_inode,
-       .put_inode              = udf_put_inode,
        .delete_inode           = udf_delete_inode,
        .clear_inode            = udf_clear_inode,
        .put_super              = udf_put_super,
@@ -194,7 +188,6 @@ struct udf_options
 static int __init init_udf_fs(void)
 {
        int err;
-       printk(KERN_NOTICE "udf: registering filesystem\n");
        err = init_inodecache();
        if (err)
                goto out1;
@@ -210,7 +203,6 @@ out1:
 
 static void __exit exit_udf_fs(void)
 {
-       printk(KERN_NOTICE "udf: unregistering filesystem\n");
        unregister_filesystem(&udf_fstype);
        destroy_inodecache();
 }
@@ -278,7 +270,7 @@ enum {
        Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock,
        Opt_anchor, Opt_volume, Opt_partition, Opt_fileset,
        Opt_rootdir, Opt_utf8, Opt_iocharset,
-       Opt_err
+       Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore
 };
 
 static match_table_t tokens = {
@@ -291,6 +283,10 @@ static match_table_t tokens = {
        {Opt_adinicb, "adinicb"},
        {Opt_shortad, "shortad"},
        {Opt_longad, "longad"},
+       {Opt_uforget, "uid=forget"},
+       {Opt_uignore, "uid=ignore"},
+       {Opt_gforget, "gid=forget"},
+       {Opt_gignore, "gid=ignore"},
        {Opt_gid, "gid=%u"},
        {Opt_uid, "uid=%u"},
        {Opt_umask, "umask=%o"},
@@ -417,12 +413,24 @@ udf_parse_options(char *options, struct udf_options *uopt)
                        case Opt_utf8:
                                uopt->flags |= (1 << UDF_FLAG_UTF8);
                                break;
-#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
+#ifdef CONFIG_UDF_NLS
                        case Opt_iocharset:
                                uopt->nls_map = load_nls(args[0].from);
                                uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
                                break;
 #endif
+                       case Opt_uignore:
+                               uopt->flags |= (1 << UDF_FLAG_UID_IGNORE);
+                               break;
+                       case Opt_uforget:
+                               uopt->flags |= (1 << UDF_FLAG_UID_FORGET);
+                               break;
+                       case Opt_gignore:
+                           uopt->flags |= (1 << UDF_FLAG_GID_IGNORE);
+                               break;
+                       case Opt_gforget:
+                           uopt->flags |= (1 << UDF_FLAG_GID_FORGET);
+                               break;
                        default:
                                printk(KERN_ERR "udf: bad mount option \"%s\" "
                                                "or missing value\n", p);
@@ -653,8 +661,7 @@ udf_find_anchor(struct super_block *sb)
                 *     lastblock
                 *  however, if the disc isn't closed, it could be 512 */
 
-               for (i=0; (!lastblock && i<sizeof(last)/sizeof(int)); i++)
-               {
+               for (i = 0; !lastblock && i < ARRAY_SIZE(last); i++) {
                        if (last[i] < 0 || !(bh = sb_bread(sb, last[i])))
                        {
                                ident = location = 0;
@@ -665,7 +672,7 @@ udf_find_anchor(struct super_block *sb)
                                location = le32_to_cpu(((tag *)bh->b_data)->tagLocation);
                                udf_release_data(bh);
                        }
-       
+
                        if (ident == TAG_IDENT_AVDP)
                        {
                                if (location == last[i] - UDF_SB_SESSION(sb))
@@ -746,8 +753,7 @@ udf_find_anchor(struct super_block *sb)
                }
        }
 
-       for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
-       {
+       for (i = 0; i < ARRAY_SIZE(UDF_SB_ANCHOR(sb)); i++) {
                if (UDF_SB_ANCHOR(sb)[i])
                {
                        if (!(bh = udf_read_tagged(sb,
@@ -771,7 +777,7 @@ udf_find_anchor(struct super_block *sb)
 }
 
 static int 
-udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
+udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr *root)
 {
        struct buffer_head *bh = NULL;
        long lastblock;
@@ -794,7 +800,7 @@ udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
 
        if (!bh) /* Search backwards through the partitions */
        {
-               lb_addr newfileset;
+               kernel_lb_addr newfileset;
 
                return 1;
                
@@ -876,7 +882,7 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
        if ( udf_stamp_to_time(&recording, &recording_usec,
                lets_to_cpu(pvoldesc->recordingDateAndTime)) )
        {
-               timestamp ts;
+               kernel_timestamp ts;
                ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
                udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
                        recording, recording_usec,
@@ -903,7 +909,7 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
 }
 
 static void 
-udf_load_fileset(struct super_block *sb, struct buffer_head *bh, lb_addr *root)
+udf_load_fileset(struct super_block *sb, struct buffer_head *bh, kernel_lb_addr *root)
 {
        struct fileSetDesc *fset;
 
@@ -950,7 +956,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
                                phd = (struct partitionHeaderDesc *)(p->partitionContentsUse);
                                if (phd->unallocSpaceTable.extLength)
                                {
-                                       lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.extPosition), i };
+                                       kernel_lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.extPosition), i };
 
                                        UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table =
                                                udf_iget(sb, loc);
@@ -976,7 +982,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
                                        udf_debug("partitionIntegrityTable (part %d)\n", i);
                                if (phd->freedSpaceTable.extLength)
                                {
-                                       lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i };
+                                       kernel_lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i };
 
                                        UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table =
                                                udf_iget(sb, loc);
@@ -1015,7 +1021,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
 }
 
 static int 
-udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fileset)
+udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, kernel_lb_addr *fileset)
 {
        struct logicalVolDesc *lvd;
        int i, j, offset;
@@ -1043,12 +1049,12 @@ udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fi
                        struct udfPartitionMap2 *upm2 = (struct udfPartitionMap2 *)&(lvd->partitionMaps[offset]);
                        if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
                        {
-                               if (le16_to_cpu(((uint16_t *)upm2->partIdent.identSuffix)[0]) == 0x0150)
+                               if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0150)
                                {
                                        UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP15;
                                        UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt15;
                                }
-                               else if (le16_to_cpu(((uint16_t *)upm2->partIdent.identSuffix)[0]) == 0x0200)
+                               else if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0200)
                                {
                                        UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP20;
                                        UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt20;
@@ -1112,7 +1118,7 @@ udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fi
  *
  */
 static void
-udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
+udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
 {
        struct buffer_head *bh = NULL;
        uint16_t ident;
@@ -1152,7 +1158,7 @@ udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
  *     Written, tested, and released.
  */
 static  int
-udf_process_sequence(struct super_block *sb, long block, long lastblock, lb_addr *fileset)
+udf_process_sequence(struct super_block *sb, long block, long lastblock, kernel_lb_addr *fileset)
 {
        struct buffer_head *bh = NULL;
        struct udf_vds_record vds[VDS_POS_LENGTH];
@@ -1295,7 +1301,7 @@ udf_check_valid(struct super_block *sb, int novrs, int silent)
 }
 
 static int
-udf_load_partition(struct super_block *sb, lb_addr *fileset)
+udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
 {
        struct anchorVolDescPtr *anchor;
        uint16_t ident;
@@ -1306,8 +1312,7 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
        if (!sb)
                return 1;
 
-       for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
-       {
+       for (i = 0; i < ARRAY_SIZE(UDF_SB_ANCHOR(sb)); i++) {
                if (UDF_SB_ANCHOR(sb)[i] && (bh = udf_read_tagged(sb,
                        UDF_SB_ANCHOR(sb)[i], UDF_SB_ANCHOR(sb)[i], &ident)))
                {
@@ -1318,7 +1323,7 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
                        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);
@@ -1337,12 +1342,10 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
                }
        }
 
-       if (i == sizeof(UDF_SB_ANCHOR(sb))/sizeof(int))
-       {
+       if (i == ARRAY_SIZE(UDF_SB_ANCHOR(sb))) {
                udf_debug("No Anchor block found\n");
                return 1;
-       }
-       else
+       } else
                udf_debug("Using anchor in block %d\n", UDF_SB_ANCHOR(sb)[i]);
 
        for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
@@ -1352,7 +1355,7 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
                        case UDF_VIRTUAL_MAP15:
                        case UDF_VIRTUAL_MAP20:
                        {
-                               lb_addr ino;
+                               kernel_lb_addr ino;
 
                                if (!UDF_SB_LASTBLOCK(sb))
                                {
@@ -1417,7 +1420,7 @@ static void udf_open_lvid(struct super_block *sb)
        if (UDF_SB_LVIDBH(sb))
        {
                int i;
-               timestamp cpu_time;
+               kernel_timestamp cpu_time;
 
                UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
                UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1445,7 +1448,7 @@ static void udf_close_lvid(struct super_block *sb)
                UDF_SB_LVID(sb)->integrityType == LVID_INTEGRITY_TYPE_OPEN)
        {
                int i;
-               timestamp cpu_time;
+               kernel_timestamp cpu_time;
 
                UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
                UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1457,7 +1460,7 @@ static void udf_close_lvid(struct super_block *sb)
                        UDF_SB_LVIDIU(sb)->minUDFReadRev = cpu_to_le16(UDF_SB_UDFREV(sb));
                if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev))
                        UDF_SB_LVIDIU(sb)->minUDFWriteRev = cpu_to_le16(UDF_SB_UDFREV(sb));
-               UDF_SB_LVID(sb)->integrityType = LVID_INTEGRITY_TYPE_CLOSE;
+               UDF_SB_LVID(sb)->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
 
                UDF_SB_LVID(sb)->descTag.descCRC =
                        cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
@@ -1494,7 +1497,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        int i;
        struct inode *inode=NULL;
        struct udf_options uopt;
-       lb_addr rootdir, fileset;
+       kernel_lb_addr rootdir, fileset;
        struct udf_sb_info *sbi;
 
        uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
@@ -1508,6 +1511,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sb->s_fs_info = sbi;
        memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
 
+       mutex_init(&sbi->s_alloc_mutex);
+
        if (!udf_parse_options((char *)options, &uopt))
                goto error_out;
 
@@ -1518,7 +1523,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                        "utf8 cannot be combined with iocharset\n");
                goto error_out;
        }
-#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
+#ifdef CONFIG_UDF_NLS
        if ((uopt.flags & (1 << UDF_FLAG_NLS_MAP)) && !uopt.nls_map)
        {
                uopt.nls_map = load_nls_default();
@@ -1569,6 +1574,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sb->dq_op = NULL;
        sb->s_dirt = 0;
        sb->s_magic = UDF_SUPER_MAGIC;
+       sb->s_time_gran = 1000;
 
        if (udf_load_partition(sb, &fileset))
        {
@@ -1587,7 +1593,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                if (minUDFReadRev > UDF_MAX_READ_VERSION)
                {
                        printk("UDF-fs: minUDFReadRev=%x (max is %x)\n",
-                               UDF_SB_LVIDIU(sb)->minUDFReadRev, UDF_MAX_READ_VERSION);
+                               le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev),
+                               UDF_MAX_READ_VERSION);
                        goto error_out;
                }
                else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
@@ -1617,7 +1624,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
        if (!silent)
        {
-               timestamp ts;
+               kernel_timestamp ts;
                udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb));
                udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
                        UDFFS_VERSION, UDFFS_DATE,
@@ -1668,7 +1675,7 @@ error_out:
                                udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
                }
        }
-#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
+#ifdef CONFIG_UDF_NLS
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
                unload_nls(UDF_SB(sb)->s_nls_map);
 #endif
@@ -1746,7 +1753,7 @@ udf_put_super(struct super_block *sb)
                                udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]);
                }
        }
-#if defined(CONFIG_NLS) || defined(CONFIG_NLS_MODULE)
+#ifdef CONFIG_UDF_NLS
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
                unload_nls(UDF_SB(sb)->s_nls_map);
 #endif
@@ -1800,7 +1807,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
        unsigned int accum = 0;
        int index;
        int block = 0, newblock;
-       lb_addr loc;
+       kernel_lb_addr loc;
        uint32_t bytes;
        uint8_t value;
        uint8_t *ptr;
@@ -1826,7 +1833,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
        }
 
        bm = (struct spaceBitmapDesc *)bh->b_data;
-       bytes = bm->numOfBytes;
+       bytes = le32_to_cpu(bm->numOfBytes);
        index = sizeof(struct spaceBitmapDesc); /* offset in first block only */
        ptr = (uint8_t *)bh->b_data;
 
@@ -1867,7 +1874,7 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
 {
        unsigned int accum = 0;
        uint32_t extoffset, elen;
-       lb_addr bloc, eloc;
+       kernel_lb_addr bloc, eloc;
        int8_t etype;
        struct buffer_head *bh = NULL;