]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Apr 2008 20:43:46 +0000 (13:43 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Apr 2008 20:43:46 +0000 (13:43 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: Suppress hidinput for Samsung IR control
  HID: remove 60x GTCO devices from blacklist
  HID: export headers properly
  HID: WiseGroup 866 Dual Joypad needs output reports quirk
  HID: ThrustMaster FF driver is no longer experimental
  HID: Logitech diNovo Mini pad support
  HID: fix race between open() and disconnect() in usbhid
  HID: make hid_input_field and usbhid_modify_dquirk static
  HID: pass numbered reports properly to hidraw
  HID: fix misplaced rdesc quirk
  HID: force feedback driver for Logitech Rumblepad 2
  HID: move wait from hid to usbhid
  HID: make function from dbg_hid
  HID: fix sparse warnings
  HID: only dump report traffic with debug level 2
  HID: patch to add NOGET for DMI/Acomdata
  HID: Sunplus Wireless Desktop needs report descriptor fixup
  HID: quirk for MS Wireless Desktop Receiver (model 1028)
  HID: fixup fullspeed interval on highspeed Afatech DVB-T IR kbd
  HID: fix build failure in hiddev_ioctl with gcc 3.2

27 files changed:
drivers/block/brd.c
fs/Kconfig
fs/udf/Makefile
fs/udf/balloc.c
fs/udf/crc.c [deleted file]
fs/udf/dir.c
fs/udf/ecma_167.h
fs/udf/file.c
fs/udf/ialloc.c
fs/udf/inode.c
fs/udf/lowlevel.c
fs/udf/misc.c
fs/udf/namei.c
fs/udf/partition.c
fs/udf/super.c
fs/udf/symlink.c
fs/udf/truncate.c
fs/udf/udf_i.h
fs/udf/udf_sb.h
fs/udf/udfdecl.h
fs/udf/udfend.h
fs/udf/udftime.c
fs/udf/unicode.c
include/linux/Kbuild
include/linux/udf_fs.h [deleted file]
include/linux/udf_fs_i.h
include/linux/udf_fs_sb.h [deleted file]

index 85364804364fc3a058114b30379927dcd974621f..7bd76639544c18d78d8b4ed87fb6befb7dcf685d 100644 (file)
@@ -108,7 +108,7 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector)
 #ifndef CONFIG_BLK_DEV_XIP
        gfp_flags |= __GFP_HIGHMEM;
 #endif
-       page = alloc_page(GFP_NOIO | __GFP_HIGHMEM | __GFP_ZERO);
+       page = alloc_page(gfp_flags);
        if (!page)
                return NULL;
 
index 028ae38ecc52538038d76051c6862345fe431349..8b18a875867751cc9a95bdf85a9f6f9935b6b68d 100644 (file)
@@ -689,6 +689,7 @@ config ZISOFS
 
 config UDF_FS
        tristate "UDF file system support"
+       select CRC_ITU_T
        help
          This is the new file system used on some CD-ROMs and DVDs. Say Y if
          you intend to mount DVD discs or CDRW's written in packet mode, or
index be845e7540ef07d39f78bab7bb7abedf53718ded..0d4503f7446dcb5e8bb3a8441fd83537284de838 100644 (file)
@@ -6,4 +6,4 @@ obj-$(CONFIG_UDF_FS) += udf.o
 
 udf-objs     := balloc.o dir.o file.o ialloc.o inode.o lowlevel.o namei.o \
                partition.o super.o truncate.o symlink.o fsync.o \
-               crc.o directory.o misc.o udftime.o unicode.o
+               directory.o misc.o udftime.o unicode.o
index f855dcbbdfb854e1704566ae0cebd187c656c45f..1b809bd494bd098a0a7855ba10f300f66a08d46a 100644 (file)
@@ -149,8 +149,7 @@ static bool udf_add_free_space(struct udf_sb_info *sbi,
                return false;
 
        lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
-       lvid->freeSpaceTable[partition] = cpu_to_le32(le32_to_cpu(
-                                       lvid->freeSpaceTable[partition]) + cnt);
+       le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
        return true;
 }
 
@@ -589,10 +588,8 @@ static void udf_table_free_blocks(struct super_block *sb,
                                        sptr = oepos.bh->b_data + epos.offset;
                                        aed = (struct allocExtDesc *)
                                                oepos.bh->b_data;
-                                       aed->lengthAllocDescs =
-                                               cpu_to_le32(le32_to_cpu(
-                                                       aed->lengthAllocDescs) +
-                                                               adsize);
+                                       le32_add_cpu(&aed->lengthAllocDescs,
+                                                       adsize);
                                } else {
                                        sptr = iinfo->i_ext.i_data +
                                                                epos.offset;
@@ -645,9 +642,7 @@ static void udf_table_free_blocks(struct super_block *sb,
                                mark_inode_dirty(table);
                        } else {
                                aed = (struct allocExtDesc *)epos.bh->b_data;
-                               aed->lengthAllocDescs =
-                                       cpu_to_le32(le32_to_cpu(
-                                           aed->lengthAllocDescs) + adsize);
+                               le32_add_cpu(&aed->lengthAllocDescs, adsize);
                                udf_update_tag(epos.bh->b_data, epos.offset);
                                mark_buffer_dirty(epos.bh);
                        }
diff --git a/fs/udf/crc.c b/fs/udf/crc.c
deleted file mode 100644 (file)
index b166129..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * crc.c
- *
- * PURPOSE
- *     Routines to generate, calculate, and test a 16-bit CRC.
- *
- * DESCRIPTION
- *     The CRC code was devised by Don P. Mitchell of AT&T Bell Laboratories
- *     and Ned W. Rhodes of Software Systems Group. It has been published in
- *     "Design and Validation of Computer Protocols", Prentice Hall,
- *     Englewood Cliffs, NJ, 1991, Chapter 3, ISBN 0-13-539925-4.
- *
- *     Copyright is held by AT&T.
- *
- *     AT&T gives permission for the free use of the CRC source code.
- *
- * COPYRIGHT
- *     This file is distributed under the terms of the GNU General Public
- *     License (GPL). Copies of the GPL can be obtained from:
- *             ftp://prep.ai.mit.edu/pub/gnu/GPL
- *     Each contributing author retains all rights to their own work.
- */
-
-#include "udfdecl.h"
-
-static uint16_t crc_table[256] = {
-       0x0000U, 0x1021U, 0x2042U, 0x3063U, 0x4084U, 0x50a5U, 0x60c6U, 0x70e7U,
-       0x8108U, 0x9129U, 0xa14aU, 0xb16bU, 0xc18cU, 0xd1adU, 0xe1ceU, 0xf1efU,
-       0x1231U, 0x0210U, 0x3273U, 0x2252U, 0x52b5U, 0x4294U, 0x72f7U, 0x62d6U,
-       0x9339U, 0x8318U, 0xb37bU, 0xa35aU, 0xd3bdU, 0xc39cU, 0xf3ffU, 0xe3deU,
-       0x2462U, 0x3443U, 0x0420U, 0x1401U, 0x64e6U, 0x74c7U, 0x44a4U, 0x5485U,
-       0xa56aU, 0xb54bU, 0x8528U, 0x9509U, 0xe5eeU, 0xf5cfU, 0xc5acU, 0xd58dU,
-       0x3653U, 0x2672U, 0x1611U, 0x0630U, 0x76d7U, 0x66f6U, 0x5695U, 0x46b4U,
-       0xb75bU, 0xa77aU, 0x9719U, 0x8738U, 0xf7dfU, 0xe7feU, 0xd79dU, 0xc7bcU,
-       0x48c4U, 0x58e5U, 0x6886U, 0x78a7U, 0x0840U, 0x1861U, 0x2802U, 0x3823U,
-       0xc9ccU, 0xd9edU, 0xe98eU, 0xf9afU, 0x8948U, 0x9969U, 0xa90aU, 0xb92bU,
-       0x5af5U, 0x4ad4U, 0x7ab7U, 0x6a96U, 0x1a71U, 0x0a50U, 0x3a33U, 0x2a12U,
-       0xdbfdU, 0xcbdcU, 0xfbbfU, 0xeb9eU, 0x9b79U, 0x8b58U, 0xbb3bU, 0xab1aU,
-       0x6ca6U, 0x7c87U, 0x4ce4U, 0x5cc5U, 0x2c22U, 0x3c03U, 0x0c60U, 0x1c41U,
-       0xedaeU, 0xfd8fU, 0xcdecU, 0xddcdU, 0xad2aU, 0xbd0bU, 0x8d68U, 0x9d49U,
-       0x7e97U, 0x6eb6U, 0x5ed5U, 0x4ef4U, 0x3e13U, 0x2e32U, 0x1e51U, 0x0e70U,
-       0xff9fU, 0xefbeU, 0xdfddU, 0xcffcU, 0xbf1bU, 0xaf3aU, 0x9f59U, 0x8f78U,
-       0x9188U, 0x81a9U, 0xb1caU, 0xa1ebU, 0xd10cU, 0xc12dU, 0xf14eU, 0xe16fU,
-       0x1080U, 0x00a1U, 0x30c2U, 0x20e3U, 0x5004U, 0x4025U, 0x7046U, 0x6067U,
-       0x83b9U, 0x9398U, 0xa3fbU, 0xb3daU, 0xc33dU, 0xd31cU, 0xe37fU, 0xf35eU,
-       0x02b1U, 0x1290U, 0x22f3U, 0x32d2U, 0x4235U, 0x5214U, 0x6277U, 0x7256U,
-       0xb5eaU, 0xa5cbU, 0x95a8U, 0x8589U, 0xf56eU, 0xe54fU, 0xd52cU, 0xc50dU,
-       0x34e2U, 0x24c3U, 0x14a0U, 0x0481U, 0x7466U, 0x6447U, 0x5424U, 0x4405U,
-       0xa7dbU, 0xb7faU, 0x8799U, 0x97b8U, 0xe75fU, 0xf77eU, 0xc71dU, 0xd73cU,
-       0x26d3U, 0x36f2U, 0x0691U, 0x16b0U, 0x6657U, 0x7676U, 0x4615U, 0x5634U,
-       0xd94cU, 0xc96dU, 0xf90eU, 0xe92fU, 0x99c8U, 0x89e9U, 0xb98aU, 0xa9abU,
-       0x5844U, 0x4865U, 0x7806U, 0x6827U, 0x18c0U, 0x08e1U, 0x3882U, 0x28a3U,
-       0xcb7dU, 0xdb5cU, 0xeb3fU, 0xfb1eU, 0x8bf9U, 0x9bd8U, 0xabbbU, 0xbb9aU,
-       0x4a75U, 0x5a54U, 0x6a37U, 0x7a16U, 0x0af1U, 0x1ad0U, 0x2ab3U, 0x3a92U,
-       0xfd2eU, 0xed0fU, 0xdd6cU, 0xcd4dU, 0xbdaaU, 0xad8bU, 0x9de8U, 0x8dc9U,
-       0x7c26U, 0x6c07U, 0x5c64U, 0x4c45U, 0x3ca2U, 0x2c83U, 0x1ce0U, 0x0cc1U,
-       0xef1fU, 0xff3eU, 0xcf5dU, 0xdf7cU, 0xaf9bU, 0xbfbaU, 0x8fd9U, 0x9ff8U,
-       0x6e17U, 0x7e36U, 0x4e55U, 0x5e74U, 0x2e93U, 0x3eb2U, 0x0ed1U, 0x1ef0U
-};
-
-/*
- * udf_crc
- *
- * PURPOSE
- *     Calculate a 16-bit CRC checksum using ITU-T V.41 polynomial.
- *
- * DESCRIPTION
- *     The OSTA-UDF(tm) 1.50 standard states that using CRCs is mandatory.
- *     The polynomial used is: x^16 + x^12 + x^15 + 1
- *
- * PRE-CONDITIONS
- *     data            Pointer to the data block.
- *     size            Size of the data block.
- *
- * POST-CONDITIONS
- *     <return>        CRC of the data block.
- *
- * HISTORY
- *     July 21, 1997 - Andrew E. Mileski
- *     Adapted from OSTA-UDF(tm) 1.50 standard.
- */
-uint16_t udf_crc(uint8_t *data, uint32_t size, uint16_t crc)
-{
-       while (size--)
-               crc = crc_table[(crc >> 8 ^ *(data++)) & 0xffU] ^ (crc << 8);
-
-       return crc;
-}
-
-/****************************************************************************/
-#if defined(TEST)
-
-/*
- * PURPOSE
- *     Test udf_crc()
- *
- * HISTORY
- *     July 21, 1997 - Andrew E. Mileski
- *     Adapted from OSTA-UDF(tm) 1.50 standard.
- */
-
-unsigned char bytes[] = { 0x70U, 0x6AU, 0x77U };
-
-int main(void)
-{
-       unsigned short x;
-
-       x = udf_crc(bytes, sizeof bytes);
-       printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U);
-
-       return 0;
-}
-
-#endif /* defined(TEST) */
-
-/****************************************************************************/
-#if defined(GENERATE)
-
-/*
- * PURPOSE
- *     Generate a table for fast 16-bit CRC calculations (any polynomial).
- *
- * DESCRIPTION
- *     The ITU-T V.41 polynomial is 010041.
- *
- * HISTORY
- *     July 21, 1997 - Andrew E. Mileski
- *     Adapted from OSTA-UDF(tm) 1.50 standard.
- */
-
-#include <stdio.h>
-
-int main(int argc, char **argv)
-{
-       unsigned long crc, poly;
-       int n, i;
-
-       /* Get the polynomial */
-       sscanf(argv[1], "%lo", &poly);
-       if (poly & 0xffff0000U) {
-               fprintf(stderr, "polynomial is too large\en");
-               exit(1);
-       }
-
-       printf("/* CRC 0%o */\n", poly);
-
-       /* Create a table */
-       printf("static unsigned short crc_table[256] = {\n");
-       for (n = 0; n < 256; n++) {
-               if (n % 8 == 0)
-                       printf("\t");
-               crc = n << 8;
-               for (i = 0; i < 8; i++) {
-                       if (crc & 0x8000U)
-                               crc = (crc << 1) ^ poly;
-                       else
-                               crc <<= 1;
-                       crc &= 0xFFFFU;
-               }
-               if (n == 255)
-                       printf("0x%04xU ", crc);
-               else
-                       printf("0x%04xU, ", crc);
-               if (n % 8 == 7)
-                       printf("\n");
-       }
-       printf("};\n");
-
-       return 0;
-}
-
-#endif /* defined(GENERATE) */
index 8d8643ada1994c55d449f9c63646f1fc71ec597d..62dc270c69d1addaffb0919e1d5308421a2d1200 100644 (file)
 static int do_udf_readdir(struct inode *dir, struct file *filp,
                          filldir_t filldir, void *dirent)
 {
-       struct udf_fileident_bh fibh;
+       struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
        struct fileIdentDesc *fi = NULL;
        struct fileIdentDesc cfi;
        int block, iblock;
        loff_t nf_pos = (filp->f_pos - 1) << 2;
        int flen;
-       char fname[UDF_NAME_LEN];
+       char *fname = NULL;
        char *nameptr;
        uint16_t liu;
        uint8_t lfi;
@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
        kernel_lb_addr eloc;
        uint32_t elen;
        sector_t offset;
-       int i, num;
+       int i, num, ret = 0;
        unsigned int dt_type;
        struct extent_position epos = { NULL, 0, {0, 0} };
        struct udf_inode_info *iinfo;
 
        if (nf_pos >= size)
-               return 0;
+               goto out;
+
+       fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+       if (!fname) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        if (nf_pos == 0)
                nf_pos = udf_ext0_offset(dir);
 
        fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
        iinfo = UDF_I(dir);
-       if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
-               fibh.sbh = fibh.ebh = NULL;
-       } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
-                             &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
+       if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+               if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
+                   &epos, &eloc, &elen, &offset)
+                   != (EXT_RECORDED_ALLOCATED >> 30)) {
+                       ret = -ENOENT;
+                       goto out;
+               }
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
                        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
                }
 
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
-                       brelse(epos.bh);
-                       return -EIO;
+                       ret = -EIO;
+                       goto out;
                }
 
                if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
                                        brelse(bha[i]);
                        }
                }
-       } else {
-               brelse(epos.bh);
-               return -ENOENT;
        }
 
        while (nf_pos < size) {
@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
 
                fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
                                        &elen, &offset);
-               if (!fi) {
-                       if (fibh.sbh != fibh.ebh)
-                               brelse(fibh.ebh);
-                       brelse(fibh.sbh);
-                       brelse(epos.bh);
-                       return 0;
-               }
+               if (!fi)
+                       goto out;
 
                liu = le16_to_cpu(cfi.lengthOfImpUse);
                lfi = cfi.lengthFileIdent;
@@ -167,53 +168,23 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
                        dt_type = DT_UNKNOWN;
                }
 
-               if (flen) {
-                       if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
-                               if (fibh.sbh != fibh.ebh)
-                                       brelse(fibh.ebh);
-                               brelse(fibh.sbh);
-                               brelse(epos.bh);
-                               return 0;
-                       }
-               }
+               if (flen && filldir(dirent, fname, flen, filp->f_pos,
+                                   iblock, dt_type) < 0)
+                       goto out;
        } /* end while */
 
        filp->f_pos = (nf_pos >> 2) + 1;
 
+out:
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
        brelse(fibh.sbh);
        brelse(epos.bh);
+       kfree(fname);
 
-       return 0;
+       return ret;
 }
 
-/*
- * udf_readdir
- *
- * PURPOSE
- *     Read a directory entry.
- *
- * DESCRIPTION
- *     Optional - sys_getdents() will return -ENOTDIR if this routine is not
- *     available.
- *
- *     Refer to sys_getdents() in fs/readdir.c
- *     sys_getdents() -> .
- *
- * PRE-CONDITIONS
- *     filp                    Pointer to directory file.
- *     buf                     Pointer to directory entry buffer.
- *     filldir                 Pointer to filldir function.
- *
- * POST-CONDITIONS
- *     <return>                >=0 on success.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-
 static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        struct inode *dir = filp->f_path.dentry->d_inode;
index 56387711589b0aaf2ad30ad5a9150480e6e1f522..a0974df82b318b27d2be5e772eb5cf276f6658e1 100644 (file)
@@ -70,19 +70,6 @@ typedef struct {
        uint8_t         microseconds;
 } __attribute__ ((packed)) timestamp;
 
-typedef struct {
-       uint16_t        typeAndTimezone;
-       int16_t         year;
-       uint8_t         month;
-       uint8_t         day;
-       uint8_t         hour;
-       uint8_t         minute;
-       uint8_t         second;
-       uint8_t         centiseconds;
-       uint8_t         hundredsOfMicroseconds;
-       uint8_t         microseconds;
-} __attribute__ ((packed)) kernel_timestamp;
-
 /* Type and Time Zone (ECMA 167r3 1/7.3.1) */
 #define TIMESTAMP_TYPE_MASK            0xF000
 #define TIMESTAMP_TYPE_CUT             0x0000
index 97c71ae7c68922f3cbe2f2ea48f0fb8a623fbc1d..0ed6e146a0d9968939a45b09fec96a2bf42e9e5e 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "udfdecl.h"
 #include <linux/fs.h>
-#include <linux/udf_fs.h>
 #include <asm/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/string.h> /* memset */
@@ -144,40 +143,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        return retval;
 }
 
-/*
- * udf_ioctl
- *
- * PURPOSE
- *     Issue an ioctl.
- *
- * DESCRIPTION
- *     Optional - sys_ioctl() will return -ENOTTY if this routine is not
- *     available, and the ioctl cannot be handled without filesystem help.
- *
- *     sys_ioctl() handles these ioctls that apply only to regular files:
- *             FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
- *     These ioctls are also handled by sys_ioctl():
- *             FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
- *     All other ioctls are passed to the filesystem.
- *
- *     Refer to sys_ioctl() in fs/ioctl.c
- *     sys_ioctl() -> .
- *
- * PRE-CONDITIONS
- *     inode                   Pointer to inode that ioctl was issued on.
- *     filp                    Pointer to file that ioctl was issued on.
- *     cmd                     The ioctl command.
- *     arg                     The ioctl argument [can be interpreted as a
- *                             user-space pointer if desired].
- *
- * POST-CONDITIONS
- *     <return>                Success (>=0) or an error code (<=0) that
- *                             sys_ioctl() will return.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
 int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
              unsigned long arg)
 {
@@ -225,18 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        return result;
 }
 
-/*
- * udf_release_file
- *
- * PURPOSE
- *  Called when all references to the file are closed
- *
- * DESCRIPTION
- *  Discard prealloced blocks
- *
- * HISTORY
- *
- */
 static int udf_release_file(struct inode *inode, struct file *filp)
 {
        if (filp->f_mode & FMODE_WRITE) {
index 84360315aca2083001727f1defc0d453b4c07779..eb9cfa23dc3d37f690edd63c9bf893844493979a 100644 (file)
@@ -21,7 +21,6 @@
 #include "udfdecl.h"
 #include <linux/fs.h>
 #include <linux/quotaops.h>
-#include <linux/udf_fs.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -47,11 +46,9 @@ void udf_free_inode(struct inode *inode)
                struct logicalVolIntegrityDescImpUse *lvidiu =
                                                        udf_sb_lvidiu(sbi);
                if (S_ISDIR(inode->i_mode))
-                       lvidiu->numDirs =
-                               cpu_to_le32(le32_to_cpu(lvidiu->numDirs) - 1);
+                       le32_add_cpu(&lvidiu->numDirs, -1);
                else
-                       lvidiu->numFiles =
-                               cpu_to_le32(le32_to_cpu(lvidiu->numFiles) - 1);
+                       le32_add_cpu(&lvidiu->numFiles, -1);
 
                mark_buffer_dirty(sbi->s_lvid_bh);
        }
@@ -105,11 +102,9 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err)
                lvhd = (struct logicalVolHeaderDesc *)
                                (lvid->logicalVolContentsUse);
                if (S_ISDIR(mode))
-                       lvidiu->numDirs =
-                               cpu_to_le32(le32_to_cpu(lvidiu->numDirs) + 1);
+                       le32_add_cpu(&lvidiu->numDirs, 1);
                else
-                       lvidiu->numFiles =
-                               cpu_to_le32(le32_to_cpu(lvidiu->numFiles) + 1);
+                       le32_add_cpu(&lvidiu->numFiles, 1);
                iinfo->i_unique = uniqueID = le64_to_cpu(lvhd->uniqueID);
                if (!(++uniqueID & 0x00000000FFFFFFFFUL))
                        uniqueID += 16;
index 24cfa55d0fdc4a2ecd4964f4c759a8babd428e72..6e74b117aaf0e58d078e59d88817562de8379a1d 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
+#include <linux/crc-itu-t.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -66,22 +67,7 @@ static void udf_update_extents(struct inode *,
                               struct extent_position *);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
-/*
- * udf_delete_inode
- *
- * PURPOSE
- *     Clean-up before the specified inode is destroyed.
- *
- * DESCRIPTION
- *     This routine is called when the kernel destroys an inode structure
- *     ie. when iput() finds i_count == 0.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- *
- *  Called at the last iput() if i_nlink is zero.
- */
+
 void udf_delete_inode(struct inode *inode)
 {
        truncate_inode_pages(&inode->i_data, 0);
@@ -323,9 +309,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
 
        lock_kernel();
 
-       if (block < 0)
-               goto abort_negative;
-
        iinfo = UDF_I(inode);
        if (block == iinfo->i_next_alloc_block + 1) {
                iinfo->i_next_alloc_block++;
@@ -347,10 +330,6 @@ static int udf_get_block(struct inode *inode, sector_t block,
 abort:
        unlock_kernel();
        return err;
-
-abort_negative:
-       udf_warning(inode->i_sb, "udf_get_block", "block < 0");
-       goto abort;
 }
 
 static struct buffer_head *udf_getblk(struct inode *inode, long block,
@@ -1116,42 +1095,36 @@ static void __udf_read_inode(struct inode *inode)
        fe = (struct fileEntry *)bh->b_data;
 
        if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
-               struct buffer_head *ibh = NULL, *nbh = NULL;
-               struct indirectEntry *ie;
+               struct buffer_head *ibh;
 
                ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1,
                                        &ident);
-               if (ident == TAG_IDENT_IE) {
-                       if (ibh) {
-                               kernel_lb_addr loc;
-                               ie = (struct indirectEntry *)ibh->b_data;
-
-                               loc = lelb_to_cpu(ie->indirectICB.extLocation);
-
-                               if (ie->indirectICB.extLength &&
-                                   (nbh = udf_read_ptagged(inode->i_sb, loc, 0,
-                                                           &ident))) {
-                                       if (ident == TAG_IDENT_FE ||
-                                           ident == TAG_IDENT_EFE) {
-                                               memcpy(&iinfo->i_location,
-                                                      &loc,
-                                                      sizeof(kernel_lb_addr));
-                                               brelse(bh);
-                                               brelse(ibh);
-                                               brelse(nbh);
-                                               __udf_read_inode(inode);
-                                               return;
-                                       } else {
-                                               brelse(nbh);
-                                               brelse(ibh);
-                                       }
-                               } else {
+               if (ident == TAG_IDENT_IE && ibh) {
+                       struct buffer_head *nbh = NULL;
+                       kernel_lb_addr loc;
+                       struct indirectEntry *ie;
+
+                       ie = (struct indirectEntry *)ibh->b_data;
+                       loc = lelb_to_cpu(ie->indirectICB.extLocation);
+
+                       if (ie->indirectICB.extLength &&
+                               (nbh = udf_read_ptagged(inode->i_sb, loc, 0,
+                                                       &ident))) {
+                               if (ident == TAG_IDENT_FE ||
+                                       ident == TAG_IDENT_EFE) {
+                                       memcpy(&iinfo->i_location,
+                                               &loc,
+                                               sizeof(kernel_lb_addr));
+                                       brelse(bh);
                                        brelse(ibh);
+                                       brelse(nbh);
+                                       __udf_read_inode(inode);
+                                       return;
                                }
+                               brelse(nbh);
                        }
-               } else {
-                       brelse(ibh);
                }
+               brelse(ibh);
        } else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
                printk(KERN_ERR "udf: unsupported strategy type: %d\n",
                       le16_to_cpu(fe->icbTag.strategyType));
@@ -1168,8 +1141,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
 {
        struct fileEntry *fe;
        struct extendedFileEntry *efe;
-       time_t convtime;
-       long convtime_usec;
        int offset;
        struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
        struct udf_inode_info *iinfo = UDF_I(inode);
@@ -1257,29 +1228,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
                        (inode->i_sb->s_blocksize_bits - 9);
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(fe->accessTime))) {
-                       inode->i_atime.tv_sec = convtime;
-                       inode->i_atime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
                        inode->i_atime = sbi->s_record_time;
-               }
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(fe->modificationTime))) {
-                       inode->i_mtime.tv_sec = convtime;
-                       inode->i_mtime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&inode->i_mtime,
+                                           fe->modificationTime))
                        inode->i_mtime = sbi->s_record_time;
-               }
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(fe->attrTime))) {
-                       inode->i_ctime.tv_sec = convtime;
-                       inode->i_ctime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
                        inode->i_ctime = sbi->s_record_time;
-               }
 
                iinfo->i_unique = le64_to_cpu(fe->uniqueID);
                iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
@@ -1289,37 +1246,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
                    (inode->i_sb->s_blocksize_bits - 9);
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(efe->accessTime))) {
-                       inode->i_atime.tv_sec = convtime;
-                       inode->i_atime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
                        inode->i_atime = sbi->s_record_time;
-               }
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(efe->modificationTime))) {
-                       inode->i_mtime.tv_sec = convtime;
-                       inode->i_mtime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&inode->i_mtime,
+                                           efe->modificationTime))
                        inode->i_mtime = sbi->s_record_time;
-               }
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(efe->createTime))) {
-                       iinfo->i_crtime.tv_sec = convtime;
-                       iinfo->i_crtime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
                        iinfo->i_crtime = sbi->s_record_time;
-               }
 
-               if (udf_stamp_to_time(&convtime, &convtime_usec,
-                                     lets_to_cpu(efe->attrTime))) {
-                       inode->i_ctime.tv_sec = convtime;
-                       inode->i_ctime.tv_nsec = convtime_usec * 1000;
-               } else {
+               if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
                        inode->i_ctime = sbi->s_record_time;
-               }
 
                iinfo->i_unique = le64_to_cpu(efe->uniqueID);
                iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
@@ -1338,6 +1276,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        case ICBTAG_FILE_TYPE_REALTIME:
        case ICBTAG_FILE_TYPE_REGULAR:
        case ICBTAG_FILE_TYPE_UNDEF:
+       case ICBTAG_FILE_TYPE_VAT20:
                if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
                        inode->i_data.a_ops = &udf_adinicb_aops;
                else
@@ -1363,6 +1302,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                inode->i_op = &page_symlink_inode_operations;
                inode->i_mode = S_IFLNK | S_IRWXUGO;
                break;
+       case ICBTAG_FILE_TYPE_MAIN:
+               udf_debug("METADATA FILE-----\n");
+               break;
+       case ICBTAG_FILE_TYPE_MIRROR:
+               udf_debug("METADATA MIRROR FILE-----\n");
+               break;
+       case ICBTAG_FILE_TYPE_BITMAP:
+               udf_debug("METADATA BITMAP FILE-----\n");
+               break;
        default:
                printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown "
                                "file type=%d\n", inode->i_ino,
@@ -1416,21 +1364,6 @@ static mode_t udf_convert_permissions(struct fileEntry *fe)
        return mode;
 }
 
-/*
- * udf_write_inode
- *
- * PURPOSE
- *     Write out the specified inode.
- *
- * DESCRIPTION
- *     This routine is called whenever an inode is synced.
- *     Currently this routine is just a placeholder.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-
 int udf_write_inode(struct inode *inode, int sync)
 {
        int ret;
@@ -1455,7 +1388,6 @@ static int udf_update_inode(struct inode *inode, int do_sync)
        uint32_t udfperms;
        uint16_t icbflags;
        uint16_t crclen;
-       kernel_timestamp cpu_time;
        int err = 0;
        struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
        unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits;
@@ -1488,9 +1420,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
                                                iinfo->i_location.
                                                        logicalBlockNum);
                use->descTag.descCRCLength = cpu_to_le16(crclen);
-               use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use +
-                                                          sizeof(tag), crclen,
-                                                          0));
+               use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
+                                                          sizeof(tag),
+                                                          crclen));
                use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
 
                mark_buffer_dirty(bh);
@@ -1558,12 +1490,9 @@ static int udf_update_inode(struct inode *inode, int do_sync)
                        (inode->i_blocks + (1 << (blocksize_bits - 9)) - 1) >>
                        (blocksize_bits - 9));
 
-               if (udf_time_to_stamp(&cpu_time, inode->i_atime))
-                       fe->accessTime = cpu_to_lets(cpu_time);
-               if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
-                       fe->modificationTime = cpu_to_lets(cpu_time);
-               if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
-                       fe->attrTime = cpu_to_lets(cpu_time);
+               udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
+               udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
+               udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
                memset(&(fe->impIdent), 0, sizeof(regid));
                strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
                fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
@@ -1598,14 +1527,10 @@ static int udf_update_inode(struct inode *inode, int do_sync)
                     iinfo->i_crtime.tv_nsec > inode->i_ctime.tv_nsec))
                        iinfo->i_crtime = inode->i_ctime;
 
-               if (udf_time_to_stamp(&cpu_time, inode->i_atime))
-                       efe->accessTime = cpu_to_lets(cpu_time);
-               if (udf_time_to_stamp(&cpu_time, inode->i_mtime))
-                       efe->modificationTime = cpu_to_lets(cpu_time);
-               if (udf_time_to_stamp(&cpu_time, iinfo->i_crtime))
-                       efe->createTime = cpu_to_lets(cpu_time);
-               if (udf_time_to_stamp(&cpu_time, inode->i_ctime))
-                       efe->attrTime = cpu_to_lets(cpu_time);
+               udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
+               udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
+               udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
+               udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
 
                memset(&(efe->impIdent), 0, sizeof(regid));
                strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
@@ -1660,8 +1585,8 @@ static int udf_update_inode(struct inode *inode, int do_sync)
        crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc -
                                                                sizeof(tag);
        fe->descTag.descCRCLength = cpu_to_le16(crclen);
-       fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag),
-                                                 crclen, 0));
+       fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag),
+                                                 crclen));
        fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
 
        /* write the data blocks */
@@ -1778,9 +1703,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
 
                        if (epos->bh) {
                                aed = (struct allocExtDesc *)epos->bh->b_data;
-                               aed->lengthAllocDescs =
-                                       cpu_to_le32(le32_to_cpu(
-                                       aed->lengthAllocDescs) + adsize);
+                               le32_add_cpu(&aed->lengthAllocDescs, adsize);
                        } else {
                                iinfo->i_lenAlloc += adsize;
                                mark_inode_dirty(inode);
@@ -1830,9 +1753,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
                mark_inode_dirty(inode);
        } else {
                aed = (struct allocExtDesc *)epos->bh->b_data;
-               aed->lengthAllocDescs =
-                       cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) +
-                                   adsize);
+               le32_add_cpu(&aed->lengthAllocDescs, adsize);
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
                                UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
                        udf_update_tag(epos->bh->b_data,
@@ -2046,9 +1967,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
                        mark_inode_dirty(inode);
                } else {
                        aed = (struct allocExtDesc *)oepos.bh->b_data;
-                       aed->lengthAllocDescs =
-                               cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
-                                           (2 * adsize));
+                       le32_add_cpu(&aed->lengthAllocDescs, -(2 * adsize));
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
                            UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
                                udf_update_tag(oepos.bh->b_data,
@@ -2065,9 +1984,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
                        mark_inode_dirty(inode);
                } else {
                        aed = (struct allocExtDesc *)oepos.bh->b_data;
-                       aed->lengthAllocDescs =
-                               cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) -
-                                           adsize);
+                       le32_add_cpu(&aed->lengthAllocDescs, -adsize);
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||
                            UDF_SB(inode->i_sb)->s_udfrev >= 0x0201)
                                udf_update_tag(oepos.bh->b_data,
@@ -2095,11 +2012,6 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
        int8_t etype;
        struct udf_inode_info *iinfo;
 
-       if (block < 0) {
-               printk(KERN_ERR "udf: inode_bmap: block < 0\n");
-               return -1;
-       }
-
        iinfo = UDF_I(inode);
        pos->offset = 0;
        pos->block = iinfo->i_location;
index 579bae71e67efe7dc62d69d3998b184da2f14f93..703843f30ffd383f556639af7146c0d99a212c25 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/cdrom.h>
 #include <asm/uaccess.h>
 
-#include <linux/udf_fs.h>
 #include "udf_sb.h"
 
 unsigned int udf_get_last_session(struct super_block *sb)
index a1d6da0caf7132121e7b5d69ea880aeeb97d1875..84bf0fd4a4f1e24a3ff70f0e8de32fb514feb6e1 100644 (file)
@@ -23,8 +23,8 @@
 
 #include <linux/fs.h>
 #include <linux/string.h>
-#include <linux/udf_fs.h>
 #include <linux/buffer_head.h>
+#include <linux/crc-itu-t.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -136,8 +136,8 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size,
                /* rewrite CRC + checksum of eahd */
                crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag);
                eahd->descTag.descCRCLength = cpu_to_le16(crclen);
-               eahd->descTag.descCRC = cpu_to_le16(udf_crc((char *)eahd +
-                                               sizeof(tag), crclen, 0));
+               eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd +
+                                               sizeof(tag), crclen));
                eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag);
                iinfo->i_lenEAttr += size;
                return (struct genericFormat *)&ea[offset];
@@ -204,16 +204,15 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 {
        tag *tag_p;
        struct buffer_head *bh = NULL;
-       struct udf_sb_info *sbi = UDF_SB(sb);
 
        /* Read the block */
        if (block == 0xFFFFFFFF)
                return NULL;
 
-       bh = udf_tread(sb, block + sbi->s_session);
+       bh = udf_tread(sb, block);
        if (!bh) {
                udf_debug("block=%d, location=%d: read failed\n",
-                         block + sbi->s_session, location);
+                         block, location);
                return NULL;
        }
 
@@ -223,8 +222,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 
        if (location != le32_to_cpu(tag_p->tagLocation)) {
                udf_debug("location mismatch block %u, tag %u != %u\n",
-                         block + sbi->s_session,
-                         le32_to_cpu(tag_p->tagLocation), location);
+                         block, le32_to_cpu(tag_p->tagLocation), location);
                goto error_out;
        }
 
@@ -244,13 +242,13 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 
        /* Verify the descriptor CRC */
        if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize ||
-           le16_to_cpu(tag_p->descCRC) == udf_crc(bh->b_data + sizeof(tag),
-                                       le16_to_cpu(tag_p->descCRCLength), 0))
+           le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
+                                       bh->b_data + sizeof(tag),
+                                       le16_to_cpu(tag_p->descCRCLength)))
                return bh;
 
-       udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
-                 block + sbi->s_session, le16_to_cpu(tag_p->descCRC),
-                 le16_to_cpu(tag_p->descCRCLength));
+       udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", block,
+           le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
 
 error_out:
        brelse(bh);
@@ -270,7 +268,7 @@ void udf_update_tag(char *data, int length)
        length -= sizeof(tag);
 
        tptr->descCRCLength = cpu_to_le16(length);
-       tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
+       tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length));
        tptr->tagChecksum = udf_tag_checksum(tptr);
 }
 
index 112a5fb0b27ba201285e71593ccda10323277516..ba5537d4bc151fcbe9575d89a30b2b0c860e92ae 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/sched.h>
+#include <linux/crc-itu-t.h>
 
 static inline int udf_match(int len1, const char *name1, int len2,
                            const char *name2)
@@ -97,25 +98,23 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
                memset(fibh->ebh->b_data, 0x00, padlen + offset);
        }
 
-       crc = udf_crc((uint8_t *)cfi + sizeof(tag),
-                     sizeof(struct fileIdentDesc) - sizeof(tag), 0);
+       crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag),
+                     sizeof(struct fileIdentDesc) - sizeof(tag));
 
        if (fibh->sbh == fibh->ebh) {
-               crc = udf_crc((uint8_t *)sfi->impUse,
+               crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
                              crclen + sizeof(tag) -
-                             sizeof(struct fileIdentDesc), crc);
+                             sizeof(struct fileIdentDesc));
        } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
-               crc = udf_crc(fibh->ebh->b_data +
+               crc = crc_itu_t(crc, fibh->ebh->b_data +
                                        sizeof(struct fileIdentDesc) +
                                        fibh->soffset,
                              crclen + sizeof(tag) -
-                                       sizeof(struct fileIdentDesc),
-                             crc);
+                                       sizeof(struct fileIdentDesc));
        } else {
-               crc = udf_crc((uint8_t *)sfi->impUse,
-                             -fibh->soffset - sizeof(struct fileIdentDesc),
-                             crc);
-               crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
+               crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
+                             -fibh->soffset - sizeof(struct fileIdentDesc));
+               crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
        }
 
        cfi->descTag.descCRC = cpu_to_le16(crc);
@@ -149,7 +148,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
        struct fileIdentDesc *fi = NULL;
        loff_t f_pos;
        int block, flen;
-       char fname[UDF_NAME_LEN];
+       char *fname = NULL;
        char *nameptr;
        uint8_t lfi;
        uint16_t liu;
@@ -163,12 +162,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
        size = udf_ext0_offset(dir) + dir->i_size;
        f_pos = udf_ext0_offset(dir);
 
+       fibh->sbh = fibh->ebh = NULL;
        fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
-       if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
-               fibh->sbh = fibh->ebh = NULL;
-       else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
-                             &epos, &eloc, &elen, &offset) ==
-                                       (EXT_RECORDED_ALLOCATED >> 30)) {
+       if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+               if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
+                   &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
+                       goto out_err;
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -179,25 +178,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
                        offset = 0;
 
                fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
-               if (!fibh->sbh) {
-                       brelse(epos.bh);
-                       return NULL;
-               }
-       } else {
-               brelse(epos.bh);
-               return NULL;
+               if (!fibh->sbh)
+                       goto out_err;
        }
 
+       fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+       if (!fname)
+               goto out_err;
+
        while (f_pos < size) {
                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
                                        &elen, &offset);
-               if (!fi) {
-                       if (fibh->sbh != fibh->ebh)
-                               brelse(fibh->ebh);
-                       brelse(fibh->sbh);
-                       brelse(epos.bh);
-                       return NULL;
-               }
+               if (!fi)
+                       goto out_err;
 
                liu = le16_to_cpu(cfi->lengthOfImpUse);
                lfi = cfi->lengthFileIdent;
@@ -237,53 +230,22 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
 
                flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
                if (flen && udf_match(flen, fname, dentry->d_name.len,
-                                     dentry->d_name.name)) {
-                       brelse(epos.bh);
-                       return fi;
-               }
+                                     dentry->d_name.name))
+                       goto out_ok;
        }
 
+out_err:
+       fi = NULL;
        if (fibh->sbh != fibh->ebh)
                brelse(fibh->ebh);
        brelse(fibh->sbh);
+out_ok:
        brelse(epos.bh);
+       kfree(fname);
 
-       return NULL;
+       return fi;
 }
 
-/*
- * udf_lookup
- *
- * PURPOSE
- *     Look-up the inode for a given name.
- *
- * DESCRIPTION
- *     Required - lookup_dentry() will return -ENOTDIR if this routine is not
- *     available for a directory. The filesystem is useless if this routine is
- *     not available for at least the filesystem's root directory.
- *
- *     This routine is passed an incomplete dentry - it must be completed by
- *     calling d_add(dentry, inode). If the name does not exist, then the
- *     specified inode must be set to null. An error should only be returned
- *     when the lookup fails for a reason other than the name not existing.
- *     Note that the directory inode semaphore is held during the call.
- *
- *     Refer to lookup_dentry() in fs/namei.c
- *     lookup_dentry() -> lookup() -> real_lookup() -> .
- *
- * PRE-CONDITIONS
- *     dir                     Pointer to inode of parent directory.
- *     dentry                  Pointer to dentry to complete.
- *     nd                      Pointer to lookup nameidata
- *
- * POST-CONDITIONS
- *     <return>                Zero on success.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-
 static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
                                 struct nameidata *nd)
 {
@@ -336,11 +298,9 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
 {
        struct super_block *sb = dir->i_sb;
        struct fileIdentDesc *fi = NULL;
-       char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
+       char *name = NULL;
        int namelen;
        loff_t f_pos;
-       int flen;
-       char *nameptr;
        loff_t size = udf_ext0_offset(dir) + dir->i_size;
        int nfidlen;
        uint8_t lfi;
@@ -352,16 +312,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
        struct extent_position epos = {};
        struct udf_inode_info *dinfo;
 
+       fibh->sbh = fibh->ebh = NULL;
+       name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+       if (!name) {
+               *err = -ENOMEM;
+               goto out_err;
+       }
+
        if (dentry) {
                if (!dentry->d_name.len) {
                        *err = -EINVAL;
-                       return NULL;
+                       goto out_err;
                }
                namelen = udf_put_filename(sb, dentry->d_name.name, name,
                                                 dentry->d_name.len);
                if (!namelen) {
                        *err = -ENAMETOOLONG;
-                       return NULL;
+                       goto out_err;
                }
        } else {
                namelen = 0;
@@ -373,11 +340,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
 
        fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
        dinfo = UDF_I(dir);
-       if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
-               fibh->sbh = fibh->ebh = NULL;
-       else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
-                             &epos, &eloc, &elen, &offset) ==
-                                       (EXT_RECORDED_ALLOCATED >> 30)) {
+       if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+               if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
+                   &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
+                       block = udf_get_lb_pblock(dir->i_sb,
+                                       dinfo->i_location, 0);
+                       fibh->soffset = fibh->eoffset = sb->s_blocksize;
+                       goto add;
+               }
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -389,17 +359,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
 
                fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
                if (!fibh->sbh) {
-                       brelse(epos.bh);
                        *err = -EIO;
-                       return NULL;
+                       goto out_err;
                }
 
                block = dinfo->i_location.logicalBlockNum;
-       } else {
-               block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
-               fibh->sbh = fibh->ebh = NULL;
-               fibh->soffset = fibh->eoffset = sb->s_blocksize;
-               goto add;
        }
 
        while (f_pos < size) {
@@ -407,41 +371,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
                                        &elen, &offset);
 
                if (!fi) {
-                       if (fibh->sbh != fibh->ebh)
-                               brelse(fibh->ebh);
-                       brelse(fibh->sbh);
-                       brelse(epos.bh);
                        *err = -EIO;
-                       return NULL;
+                       goto out_err;
                }
 
                liu = le16_to_cpu(cfi->lengthOfImpUse);
                lfi = cfi->lengthFileIdent;
 
-               if (fibh->sbh == fibh->ebh)
-                       nameptr = fi->fileIdent + liu;
-               else {
-                       int poffset;    /* Unpaded ending offset */
-
-                       poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
-                                       liu + lfi;
-
-                       if (poffset >= lfi)
-                               nameptr = (char *)(fibh->ebh->b_data +
-                                                  poffset - lfi);
-                       else {
-                               nameptr = fname;
-                               memcpy(nameptr, fi->fileIdent + liu,
-                                       lfi - poffset);
-                               memcpy(nameptr + lfi - poffset,
-                                       fibh->ebh->b_data, poffset);
-                       }
-               }
-
                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
                        if (((sizeof(struct fileIdentDesc) +
                                        liu + lfi + 3) & ~3) == nfidlen) {
-                               brelse(epos.bh);
                                cfi->descTag.tagSerialNum = cpu_to_le16(1);
                                cfi->fileVersionNum = cpu_to_le16(1);
                                cfi->fileCharacteristics = 0;
@@ -449,27 +388,13 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
                                cfi->lengthOfImpUse = cpu_to_le16(0);
                                if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
                                                  name))
-                                       return fi;
+                                       goto out_ok;
                                else {
                                        *err = -EIO;
-                                       return NULL;
+                                       goto out_err;
                                }
                        }
                }
-
-               if (!lfi || !dentry)
-                       continue;
-
-               flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
-               if (flen && udf_match(flen, fname, dentry->d_name.len,
-                                     dentry->d_name.name)) {
-                       if (fibh->sbh != fibh->ebh)
-                               brelse(fibh->ebh);
-                       brelse(fibh->sbh);
-                       brelse(epos.bh);
-                       *err = -EEXIST;
-                       return NULL;
-               }
        }
 
 add:
@@ -496,7 +421,7 @@ add:
                fibh->sbh = fibh->ebh =
                                udf_expand_dir_adinicb(dir, &block, err);
                if (!fibh->sbh)
-                       return NULL;
+                       goto out_err;
                epos.block = dinfo->i_location;
                epos.offset = udf_file_entry_alloc_offset(dir);
                /* Load extent udf_expand_dir_adinicb() has created */
@@ -537,11 +462,8 @@ add:
                                                dir->i_sb->s_blocksize_bits);
                fibh->ebh = udf_bread(dir,
                                f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
-               if (!fibh->ebh) {
-                       brelse(epos.bh);
-                       brelse(fibh->sbh);
-                       return NULL;
-               }
+               if (!fibh->ebh)
+                       goto out_err;
 
                if (!fibh->soffset) {
                        if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
@@ -572,20 +494,25 @@ add:
        cfi->lengthFileIdent = namelen;
        cfi->lengthOfImpUse = cpu_to_le16(0);
        if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
-               brelse(epos.bh);
                dir->i_size += nfidlen;
                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
                        dinfo->i_lenAlloc += nfidlen;
                mark_inode_dirty(dir);
-               return fi;
+               goto out_ok;
        } else {
-               brelse(epos.bh);
-               if (fibh->sbh != fibh->ebh)
-                       brelse(fibh->ebh);
-               brelse(fibh->sbh);
                *err = -EIO;
-               return NULL;
+               goto out_err;
        }
+
+out_err:
+       fi = NULL;
+       if (fibh->sbh != fibh->ebh)
+               brelse(fibh->ebh);
+       brelse(fibh->sbh);
+out_ok:
+       brelse(epos.bh);
+       kfree(name);
+       return fi;
 }
 
 static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
@@ -940,7 +867,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
        char *ea;
        int err;
        int block;
-       char name[UDF_NAME_LEN];
+       char *name = NULL;
        int namelen;
        struct buffer_head *bh;
        struct udf_inode_info *iinfo;
@@ -950,6 +877,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
        if (!inode)
                goto out;
 
+       name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+       if (!name) {
+               err = -ENOMEM;
+               goto out_no_entry;
+       }
+
        iinfo = UDF_I(inode);
        inode->i_mode = S_IFLNK | S_IRWXUGO;
        inode->i_data.a_ops = &udf_symlink_aops;
@@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
        err = 0;
 
 out:
+       kfree(name);
        unlock_kernel();
        return err;
 
index fc533345ab89198a12fb472765f7c9073a356970..63610f026ae15046d701d3ab45ab93a04ff51371 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <linux/fs.h>
 #include <linux/string.h>
-#include <linux/udf_fs.h>
 #include <linux/slab.h>
 #include <linux/buffer_head.h>
 
@@ -55,11 +54,10 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct udf_part_map *map;
        struct udf_virtual_data *vdata;
-       struct udf_inode_info *iinfo;
+       struct udf_inode_info *iinfo = UDF_I(sbi->s_vat_inode);
 
        map = &sbi->s_partmaps[partition];
        vdata = &map->s_type_specific.s_virtual;
-       index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
 
        if (block > vdata->s_num_entries) {
                udf_debug("Trying to access block beyond end of VAT "
@@ -67,6 +65,12 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
                return 0xFFFFFFFF;
        }
 
+       if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+               loc = le32_to_cpu(((__le32 *)(iinfo->i_ext.i_data +
+                       vdata->s_start_offset))[block]);
+               goto translate;
+       }
+       index = (sb->s_blocksize - vdata->s_start_offset) / sizeof(uint32_t);
        if (block >= index) {
                block -= index;
                newblock = 1 + (block / (sb->s_blocksize / sizeof(uint32_t)));
@@ -89,7 +93,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block,
 
        brelse(bh);
 
-       iinfo = UDF_I(sbi->s_vat_inode);
+translate:
        if (iinfo->i_location.partitionReferenceNum == partition) {
                udf_debug("recursive call to udf_get_pblock!\n");
                return 0xFFFFFFFF;
@@ -263,3 +267,58 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
 
        return 0;
 }
+
+static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
+                                       uint16_t partition, uint32_t offset)
+{
+       struct super_block *sb = inode->i_sb;
+       struct udf_part_map *map;
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t ext_offset;
+       struct extent_position epos = {};
+       uint32_t phyblock;
+
+       if (inode_bmap(inode, block, &epos, &eloc, &elen, &ext_offset) !=
+                                               (EXT_RECORDED_ALLOCATED >> 30))
+               phyblock = 0xFFFFFFFF;
+       else {
+               map = &UDF_SB(sb)->s_partmaps[partition];
+               /* map to sparable/physical partition desc */
+               phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
+                       map->s_partition_num, ext_offset + offset);
+       }
+
+       brelse(epos.bh);
+       return phyblock;
+}
+
+uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
+                               uint16_t partition, uint32_t offset)
+{
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct udf_part_map *map;
+       struct udf_meta_data *mdata;
+       uint32_t retblk;
+       struct inode *inode;
+
+       udf_debug("READING from METADATA\n");
+
+       map = &sbi->s_partmaps[partition];
+       mdata = &map->s_type_specific.s_metadata;
+       inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
+
+       /* We shouldn't mount such media... */
+       BUG_ON(!inode);
+       retblk = udf_try_read_meta(inode, block, partition, offset);
+       if (retblk == 0xFFFFFFFF) {
+               udf_warning(sb, __func__, "error reading from METADATA, "
+                       "trying to read from MIRROR");
+               inode = mdata->s_mirror_fe;
+               if (!inode)
+                       return 0xFFFFFFFF;
+               retblk = udf_try_read_meta(inode, block, partition, offset);
+       }
+
+       return retblk;
+}
index f3ac4abfc9467a093ac54ebdef4283e9eaec166c..b564fc140fe4e90efc24b7b7f231a5676aa979b6 100644 (file)
 #include <linux/errno.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
+#include <linux/bitmap.h>
+#include <linux/crc-itu-t.h>
 #include <asm/byteorder.h>
 
-#include <linux/udf_fs.h>
 #include "udf_sb.h"
 #include "udf_i.h"
 
@@ -84,22 +85,19 @@ 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 *, 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 *, 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 *,
                             kernel_lb_addr *);
-static int 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 *);
 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 *);
+static void udf_error(struct super_block *sb, const char *function,
+                     const char *fmt, ...);
 
 struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
 {
@@ -587,48 +585,10 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
        return 0;
 }
 
-/*
- * udf_set_blocksize
- *
- * PURPOSE
- *     Set the block size to be used in all transfers.
- *
- * DESCRIPTION
- *     To allow room for a DMA transfer, it is best to guess big when unsure.
- *     This routine picks 2048 bytes as the blocksize when guessing. This
- *     should be adequate until devices with larger block sizes become common.
- *
- *     Note that the Linux kernel can currently only deal with blocksizes of
- *     512, 1024, 2048, 4096, and 8192 bytes.
- *
- * PRE-CONDITIONS
- *     sb                      Pointer to _locked_ superblock.
- *
- * POST-CONDITIONS
- *     sb->s_blocksize         Blocksize.
- *     sb->s_blocksize_bits    log2 of blocksize.
- *     <return>        0       Blocksize is valid.
- *     <return>        1       Blocksize is invalid.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-static int udf_set_blocksize(struct super_block *sb, int bsize)
-{
-       if (!sb_min_blocksize(sb, bsize)) {
-               udf_debug("Bad block size (%d)\n", bsize);
-               printk(KERN_ERR "udf: bad block size (%d)\n", bsize);
-               return 0;
-       }
-
-       return sb->s_blocksize;
-}
-
 static int udf_vrs(struct super_block *sb, int silent)
 {
        struct volStructDesc *vsd = NULL;
-       int sector = 32768;
+       loff_t sector = 32768;
        int sectorsize;
        struct buffer_head *bh = NULL;
        int iso9660 = 0;
@@ -649,7 +609,8 @@ static int udf_vrs(struct super_block *sb, int silent)
        sector += (sbi->s_session << sb->s_blocksize_bits);
 
        udf_debug("Starting at sector %u (%ld byte sectors)\n",
-                 (sector >> sb->s_blocksize_bits), sb->s_blocksize);
+                 (unsigned int)(sector >> sb->s_blocksize_bits),
+                 sb->s_blocksize);
        /* Process the sequence (if applicable) */
        for (; !nsr02 && !nsr03; sector += sectorsize) {
                /* Read a block */
@@ -719,162 +680,140 @@ static int udf_vrs(struct super_block *sb, int silent)
 }
 
 /*
- * udf_find_anchor
- *
- * PURPOSE
- *     Find an anchor volume descriptor.
- *
- * PRE-CONDITIONS
- *     sb                      Pointer to _locked_ superblock.
- *     lastblock               Last block on media.
- *
- * POST-CONDITIONS
- *     <return>                1 if not found, 0 if ok
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
+ * Check whether there is an anchor block in the given block
  */
-static void udf_find_anchor(struct super_block *sb)
+static int udf_check_anchor_block(struct super_block *sb, sector_t block,
+                                       bool varconv)
 {
-       int lastblock;
        struct buffer_head *bh = NULL;
+       tag *t;
        uint16_t ident;
        uint32_t location;
-       int i;
-       struct udf_sb_info *sbi;
 
-       sbi = UDF_SB(sb);
-       lastblock = sbi->s_last_block;
+       if (varconv) {
+               if (udf_fixed_to_variable(block) >=
+                   sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
+                       return 0;
+               bh = sb_bread(sb, udf_fixed_to_variable(block));
+       }
+       else
+               bh = sb_bread(sb, block);
 
-       if (lastblock) {
-               int varlastblock = udf_variable_to_fixed(lastblock);
-               int last[] =  { lastblock, lastblock - 2,
-                               lastblock - 150, lastblock - 152,
-                               varlastblock, varlastblock - 2,
-                               varlastblock - 150, varlastblock - 152 };
-
-               lastblock = 0;
-
-               /* Search for an anchor volume descriptor pointer */
-
-               /*  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; !lastblock && i < ARRAY_SIZE(last); i++) {
-                       ident = location = 0;
-                       if (last[i] >= 0) {
-                               bh = sb_bread(sb, last[i]);
-                               if (bh) {
-                                       tag *t = (tag *)bh->b_data;
-                                       ident = le16_to_cpu(t->tagIdent);
-                                       location = le32_to_cpu(t->tagLocation);
-                                       brelse(bh);
-                               }
-                       }
+       if (!bh)
+               return 0;
 
-                       if (ident == TAG_IDENT_AVDP) {
-                               if (location == last[i] - sbi->s_session) {
-                                       lastblock = last[i] - sbi->s_session;
-                                       sbi->s_anchor[0] = lastblock;
-                                       sbi->s_anchor[1] = lastblock - 256;
-                               } else if (location ==
-                                               udf_variable_to_fixed(last[i]) -
-                                                       sbi->s_session) {
-                                       UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
-                                       lastblock =
-                                               udf_variable_to_fixed(last[i]) -
-                                                       sbi->s_session;
-                                       sbi->s_anchor[0] = lastblock;
-                                       sbi->s_anchor[1] = lastblock - 256 -
-                                                               sbi->s_session;
-                               } else {
-                                       udf_debug("Anchor found at block %d, "
-                                                 "location mismatch %d.\n",
-                                                 last[i], location);
-                               }
-                       } else if (ident == TAG_IDENT_FE ||
-                                       ident == TAG_IDENT_EFE) {
-                               lastblock = last[i];
-                               sbi->s_anchor[3] = 512;
-                       } else {
-                               ident = location = 0;
-                               if (last[i] >= 256) {
-                                       bh = sb_bread(sb, last[i] - 256);
-                                       if (bh) {
-                                               tag *t = (tag *)bh->b_data;
-                                               ident = le16_to_cpu(
-                                                               t->tagIdent);
-                                               location = le32_to_cpu(
-                                                               t->tagLocation);
-                                               brelse(bh);
-                                       }
-                               }
+       t = (tag *)bh->b_data;
+       ident = le16_to_cpu(t->tagIdent);
+       location = le32_to_cpu(t->tagLocation);
+       brelse(bh);
+       if (ident != TAG_IDENT_AVDP)
+               return 0;
+       return location == block;
+}
 
-                               if (ident == TAG_IDENT_AVDP &&
-                                   location == last[i] - 256 -
-                                               sbi->s_session) {
-                                       lastblock = last[i];
-                                       sbi->s_anchor[1] = last[i] - 256;
-                               } else {
-                                       ident = location = 0;
-                                       if (last[i] >= 312 + sbi->s_session) {
-                                               bh = sb_bread(sb,
-                                                               last[i] - 312 -
-                                                               sbi->s_session);
-                                               if (bh) {
-                                                       tag *t = (tag *)
-                                                                bh->b_data;
-                                                       ident = le16_to_cpu(
-                                                               t->tagIdent);
-                                                       location = le32_to_cpu(
-                                                               t->tagLocation);
-                                                       brelse(bh);
-                                               }
-                                       }
+/* Search for an anchor volume descriptor pointer */
+static sector_t udf_scan_anchors(struct super_block *sb, bool varconv,
+                                       sector_t lastblock)
+{
+       sector_t last[6];
+       int i;
+       struct udf_sb_info *sbi = UDF_SB(sb);
 
-                                       if (ident == TAG_IDENT_AVDP &&
-                                           location == udf_variable_to_fixed(last[i]) - 256) {
-                                               UDF_SET_FLAG(sb,
-                                                            UDF_FLAG_VARCONV);
-                                               lastblock = udf_variable_to_fixed(last[i]);
-                                               sbi->s_anchor[1] = lastblock - 256;
-                                       }
-                               }
-                       }
+       last[0] = lastblock;
+       last[1] = last[0] - 1;
+       last[2] = last[0] + 1;
+       last[3] = last[0] - 2;
+       last[4] = last[0] - 150;
+       last[5] = last[0] - 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 < ARRAY_SIZE(last); i++) {
+               if (last[i] < 0)
+                       continue;
+               if (last[i] >= sb->s_bdev->bd_inode->i_size >>
+                               sb->s_blocksize_bits)
+                       continue;
+
+               if (udf_check_anchor_block(sb, last[i], varconv)) {
+                       sbi->s_anchor[0] = last[i];
+                       sbi->s_anchor[1] = last[i] - 256;
+                       return last[i];
                }
-       }
 
-       if (!lastblock) {
-               /* We haven't found the lastblock. check 312 */
-               bh = sb_bread(sb, 312 + sbi->s_session);
-               if (bh) {
-                       tag *t = (tag *)bh->b_data;
-                       ident = le16_to_cpu(t->tagIdent);
-                       location = le32_to_cpu(t->tagLocation);
-                       brelse(bh);
+               if (last[i] < 256)
+                       continue;
 
-                       if (ident == TAG_IDENT_AVDP && location == 256)
-                               UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+               if (udf_check_anchor_block(sb, last[i] - 256, varconv)) {
+                       sbi->s_anchor[1] = last[i] - 256;
+                       return last[i];
                }
        }
 
+       if (udf_check_anchor_block(sb, sbi->s_session + 256, varconv)) {
+               sbi->s_anchor[0] = sbi->s_session + 256;
+               return last[0];
+       }
+       if (udf_check_anchor_block(sb, sbi->s_session + 512, varconv)) {
+               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, 0, sbi->s_last_block);
+       if (lastblock)
+               goto check_anchor;
+
+       /* No anchor found? Try VARCONV conversion of block numbers */
+       /* Firstly, we try to not convert number of the last block */
+       lastblock = udf_scan_anchors(sb, 1,
+                               udf_variable_to_fixed(sbi->s_last_block));
+       if (lastblock) {
+               UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+               goto check_anchor;
+       }
+
+       /* Secondly, we try with converted number of the last block */
+       lastblock = udf_scan_anchors(sb, 1, sbi->s_last_block);
+       if (lastblock)
+               UDF_SET_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]) {
-                       bh = udf_read_tagged(sb, sbi->s_anchor[i],
-                                            sbi->s_anchor[i], &ident);
-                       if (!bh)
+               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;
-                       else {
-                               brelse(bh);
-                               if ((ident != TAG_IDENT_AVDP) &&
-                                   (i || (ident != TAG_IDENT_FE &&
-                                          ident != TAG_IDENT_EFE)))
-                                       sbi->s_anchor[i] = 0;
-                       }
                }
        }
 
@@ -971,27 +910,30 @@ static int udf_find_fileset(struct super_block *sb,
        return 1;
 }
 
-static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
+static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 {
        struct primaryVolDesc *pvoldesc;
-       time_t recording;
-       long recording_usec;
        struct ustr instr;
        struct ustr outstr;
+       struct buffer_head *bh;
+       uint16_t ident;
+
+       bh = udf_read_tagged(sb, block, block, &ident);
+       if (!bh)
+               return 1;
+       BUG_ON(ident != TAG_IDENT_PVD);
 
        pvoldesc = (struct primaryVolDesc *)bh->b_data;
 
-       if (udf_stamp_to_time(&recording, &recording_usec,
-                             lets_to_cpu(pvoldesc->recordingDateAndTime))) {
-               kernel_timestamp ts;
-               ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
-               udf_debug("recording time %ld/%ld, %04u/%02u/%02u"
+       if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
+                             pvoldesc->recordingDateAndTime)) {
+#ifdef UDFFS_DEBUG
+               timestamp *ts = &pvoldesc->recordingDateAndTime;
+               udf_debug("recording time %04u/%02u/%02u"
                          " %02u:%02u (%x)\n",
-                         recording, recording_usec,
-                         ts.year, ts.month, ts.day, ts.hour,
-                         ts.minute, ts.typeAndTimezone);
-               UDF_SB(sb)->s_record_time.tv_sec = recording;
-               UDF_SB(sb)->s_record_time.tv_nsec = recording_usec * 1000;
+                         le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
+                         ts->minute, le16_to_cpu(ts->typeAndTimezone));
+#endif
        }
 
        if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32))
@@ -1005,6 +947,104 @@ static void udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
        if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128))
                if (udf_CS0toUTF8(&outstr, &instr))
                        udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
+
+       brelse(bh);
+       return 0;
+}
+
+static int udf_load_metadata_files(struct super_block *sb, int partition)
+{
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct udf_part_map *map;
+       struct udf_meta_data *mdata;
+       kernel_lb_addr addr;
+       int fe_error = 0;
+
+       map = &sbi->s_partmaps[partition];
+       mdata = &map->s_type_specific.s_metadata;
+
+       /* metadata address */
+       addr.logicalBlockNum =  mdata->s_meta_file_loc;
+       addr.partitionReferenceNum = map->s_partition_num;
+
+       udf_debug("Metadata file location: block = %d part = %d\n",
+                         addr.logicalBlockNum, addr.partitionReferenceNum);
+
+       mdata->s_metadata_fe = udf_iget(sb, addr);
+
+       if (mdata->s_metadata_fe == NULL) {
+               udf_warning(sb, __func__, "metadata inode efe not found, "
+                               "will try mirror inode.");
+               fe_error = 1;
+       } else if (UDF_I(mdata->s_metadata_fe)->i_alloc_type !=
+                ICBTAG_FLAG_AD_SHORT) {
+               udf_warning(sb, __func__, "metadata inode efe does not have "
+                       "short allocation descriptors!");
+               fe_error = 1;
+               iput(mdata->s_metadata_fe);
+               mdata->s_metadata_fe = NULL;
+       }
+
+       /* mirror file entry */
+       addr.logicalBlockNum = mdata->s_mirror_file_loc;
+       addr.partitionReferenceNum = map->s_partition_num;
+
+       udf_debug("Mirror metadata file location: block = %d part = %d\n",
+                         addr.logicalBlockNum, addr.partitionReferenceNum);
+
+       mdata->s_mirror_fe = udf_iget(sb, addr);
+
+       if (mdata->s_mirror_fe == NULL) {
+               if (fe_error) {
+                       udf_error(sb, __func__, "mirror inode efe not found "
+                       "and metadata inode is missing too, exiting...");
+                       goto error_exit;
+               } else
+                       udf_warning(sb, __func__, "mirror inode efe not found,"
+                                       " but metadata inode is OK");
+       } else if (UDF_I(mdata->s_mirror_fe)->i_alloc_type !=
+                ICBTAG_FLAG_AD_SHORT) {
+               udf_warning(sb, __func__, "mirror inode efe does not have "
+                       "short allocation descriptors!");
+               iput(mdata->s_mirror_fe);
+               mdata->s_mirror_fe = NULL;
+               if (fe_error)
+                       goto error_exit;
+       }
+
+       /*
+        * bitmap file entry
+        * Note:
+        * Load only if bitmap file location differs from 0xFFFFFFFF (DCN-5102)
+       */
+       if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
+               addr.logicalBlockNum = mdata->s_bitmap_file_loc;
+               addr.partitionReferenceNum = map->s_partition_num;
+
+               udf_debug("Bitmap file location: block = %d part = %d\n",
+                       addr.logicalBlockNum, addr.partitionReferenceNum);
+
+               mdata->s_bitmap_fe = udf_iget(sb, addr);
+
+               if (mdata->s_bitmap_fe == NULL) {
+                       if (sb->s_flags & MS_RDONLY)
+                               udf_warning(sb, __func__, "bitmap inode efe "
+                                       "not found but it's ok since the disc"
+                                       " is mounted read-only");
+                       else {
+                               udf_error(sb, __func__, "bitmap inode efe not "
+                                       "found and attempted read-write mount");
+                               goto error_exit;
+                       }
+               }
+       }
+
+       udf_debug("udf_load_metadata_files Ok\n");
+
+       return 0;
+
+error_exit:
+       return 1;
 }
 
 static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
@@ -1025,10 +1065,9 @@ static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh,
 int udf_compute_nr_groups(struct super_block *sb, u32 partition)
 {
        struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition];
-       return (map->s_partition_len +
-               (sizeof(struct spaceBitmapDesc) << 3) +
-               (sb->s_blocksize * 8) - 1) /
-               (sb->s_blocksize * 8);
+       return DIV_ROUND_UP(map->s_partition_len +
+                           (sizeof(struct spaceBitmapDesc) << 3),
+                           sb->s_blocksize * 8);
 }
 
 static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
@@ -1059,134 +1098,241 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
        return bitmap;
 }
 
-static int udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
+static int udf_fill_partdesc_info(struct super_block *sb,
+               struct partitionDesc *p, int p_index)
+{
+       struct udf_part_map *map;
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct partitionHeaderDesc *phd;
+
+       map = &sbi->s_partmaps[p_index];
+
+       map->s_partition_len = le32_to_cpu(p->partitionLength); /* blocks */
+       map->s_partition_root = le32_to_cpu(p->partitionStartingLocation);
+
+       if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
+               map->s_partition_flags |= UDF_PART_FLAG_READ_ONLY;
+       if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
+               map->s_partition_flags |= UDF_PART_FLAG_WRITE_ONCE;
+       if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
+               map->s_partition_flags |= UDF_PART_FLAG_REWRITABLE;
+       if (p->accessType == cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
+               map->s_partition_flags |= UDF_PART_FLAG_OVERWRITABLE;
+
+       udf_debug("Partition (%d type %x) starts at physical %d, "
+                 "block length %d\n", p_index,
+                 map->s_partition_type, map->s_partition_root,
+                 map->s_partition_len);
+
+       if (strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR02) &&
+           strcmp(p->partitionContents.ident, PD_PARTITION_CONTENTS_NSR03))
+               return 0;
+
+       phd = (struct partitionHeaderDesc *)p->partitionContentsUse;
+       if (phd->unallocSpaceTable.extLength) {
+               kernel_lb_addr loc = {
+                       .logicalBlockNum = le32_to_cpu(
+                               phd->unallocSpaceTable.extPosition),
+                       .partitionReferenceNum = p_index,
+               };
+
+               map->s_uspace.s_table = udf_iget(sb, loc);
+               if (!map->s_uspace.s_table) {
+                       udf_debug("cannot load unallocSpaceTable (part %d)\n",
+                                       p_index);
+                       return 1;
+               }
+               map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
+               udf_debug("unallocSpaceTable (part %d) @ %ld\n",
+                               p_index, map->s_uspace.s_table->i_ino);
+       }
+
+       if (phd->unallocSpaceBitmap.extLength) {
+               struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
+               if (!bitmap)
+                       return 1;
+               map->s_uspace.s_bitmap = bitmap;
+               bitmap->s_extLength = le32_to_cpu(
+                               phd->unallocSpaceBitmap.extLength);
+               bitmap->s_extPosition = le32_to_cpu(
+                               phd->unallocSpaceBitmap.extPosition);
+               map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
+               udf_debug("unallocSpaceBitmap (part %d) @ %d\n", p_index,
+                                               bitmap->s_extPosition);
+       }
+
+       if (phd->partitionIntegrityTable.extLength)
+               udf_debug("partitionIntegrityTable (part %d)\n", p_index);
+
+       if (phd->freedSpaceTable.extLength) {
+               kernel_lb_addr loc = {
+                       .logicalBlockNum = le32_to_cpu(
+                               phd->freedSpaceTable.extPosition),
+                       .partitionReferenceNum = p_index,
+               };
+
+               map->s_fspace.s_table = udf_iget(sb, loc);
+               if (!map->s_fspace.s_table) {
+                       udf_debug("cannot load freedSpaceTable (part %d)\n",
+                               p_index);
+                       return 1;
+               }
+
+               map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
+               udf_debug("freedSpaceTable (part %d) @ %ld\n",
+                               p_index, map->s_fspace.s_table->i_ino);
+       }
+
+       if (phd->freedSpaceBitmap.extLength) {
+               struct udf_bitmap *bitmap = udf_sb_alloc_bitmap(sb, p_index);
+               if (!bitmap)
+                       return 1;
+               map->s_fspace.s_bitmap = bitmap;
+               bitmap->s_extLength = le32_to_cpu(
+                               phd->freedSpaceBitmap.extLength);
+               bitmap->s_extPosition = le32_to_cpu(
+                               phd->freedSpaceBitmap.extPosition);
+               map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
+               udf_debug("freedSpaceBitmap (part %d) @ %d\n", p_index,
+                                       bitmap->s_extPosition);
+       }
+       return 0;
+}
+
+static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
+{
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct udf_part_map *map = &sbi->s_partmaps[p_index];
+       kernel_lb_addr ino;
+       struct buffer_head *bh = NULL;
+       struct udf_inode_info *vati;
+       uint32_t pos;
+       struct virtualAllocationTable20 *vat20;
+
+       /* 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)
+               return 1;
+
+       if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
+               map->s_type_specific.s_virtual.s_start_offset = 0;
+               map->s_type_specific.s_virtual.s_num_entries =
+                       (sbi->s_vat_inode->i_size - 36) >> 2;
+       } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
+               vati = UDF_I(sbi->s_vat_inode);
+               if (vati->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+                       pos = udf_block_map(sbi->s_vat_inode, 0);
+                       bh = sb_bread(sb, pos);
+                       if (!bh)
+                               return 1;
+                       vat20 = (struct virtualAllocationTable20 *)bh->b_data;
+               } else {
+                       vat20 = (struct virtualAllocationTable20 *)
+                                                       vati->i_ext.i_data;
+               }
+
+               map->s_type_specific.s_virtual.s_start_offset =
+                       le16_to_cpu(vat20->lengthHeader);
+               map->s_type_specific.s_virtual.s_num_entries =
+                       (sbi->s_vat_inode->i_size -
+                               map->s_type_specific.s_virtual.
+                                       s_start_offset) >> 2;
+               brelse(bh);
+       }
+       return 0;
+}
+
+static int udf_load_partdesc(struct super_block *sb, sector_t block)
 {
+       struct buffer_head *bh;
        struct partitionDesc *p;
-       int i;
        struct udf_part_map *map;
-       struct udf_sb_info *sbi;
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       int i, type1_idx;
+       uint16_t partitionNumber;
+       uint16_t ident;
+       int ret = 0;
+
+       bh = udf_read_tagged(sb, block, block, &ident);
+       if (!bh)
+               return 1;
+       if (ident != TAG_IDENT_PD)
+               goto out_bh;
 
        p = (struct partitionDesc *)bh->b_data;
-       sbi = UDF_SB(sb);
+       partitionNumber = le16_to_cpu(p->partitionNumber);
 
+       /* First scan for TYPE1, SPARABLE and METADATA partitions */
        for (i = 0; i < sbi->s_partitions; i++) {
                map = &sbi->s_partmaps[i];
                udf_debug("Searching map: (%d == %d)\n",
-                         map->s_partition_num,
-                         le16_to_cpu(p->partitionNumber));
-               if (map->s_partition_num ==
-                               le16_to_cpu(p->partitionNumber)) {
-                       map->s_partition_len =
-                               le32_to_cpu(p->partitionLength); /* blocks */
-                       map->s_partition_root =
-                               le32_to_cpu(p->partitionStartingLocation);
-                       if (p->accessType ==
-                                       cpu_to_le32(PD_ACCESS_TYPE_READ_ONLY))
-                               map->s_partition_flags |=
-                                               UDF_PART_FLAG_READ_ONLY;
-                       if (p->accessType ==
-                                       cpu_to_le32(PD_ACCESS_TYPE_WRITE_ONCE))
-                               map->s_partition_flags |=
-                                               UDF_PART_FLAG_WRITE_ONCE;
-                       if (p->accessType ==
-                                       cpu_to_le32(PD_ACCESS_TYPE_REWRITABLE))
-                               map->s_partition_flags |=
-                                               UDF_PART_FLAG_REWRITABLE;
-                       if (p->accessType ==
-                                   cpu_to_le32(PD_ACCESS_TYPE_OVERWRITABLE))
-                               map->s_partition_flags |=
-                                               UDF_PART_FLAG_OVERWRITABLE;
-
-                       if (!strcmp(p->partitionContents.ident,
-                                   PD_PARTITION_CONTENTS_NSR02) ||
-                           !strcmp(p->partitionContents.ident,
-                                   PD_PARTITION_CONTENTS_NSR03)) {
-                               struct partitionHeaderDesc *phd;
-
-                               phd = (struct partitionHeaderDesc *)
-                                               (p->partitionContentsUse);
-                               if (phd->unallocSpaceTable.extLength) {
-                                       kernel_lb_addr loc = {
-                                               .logicalBlockNum = le32_to_cpu(phd->unallocSpaceTable.extPosition),
-                                               .partitionReferenceNum = i,
-                                       };
-
-                                       map->s_uspace.s_table =
-                                               udf_iget(sb, loc);
-                                       if (!map->s_uspace.s_table) {
-                                               udf_debug("cannot load unallocSpaceTable (part %d)\n", i);
-                                               return 1;
-                                       }
-                                       map->s_partition_flags |=
-                                               UDF_PART_FLAG_UNALLOC_TABLE;
-                                       udf_debug("unallocSpaceTable (part %d) @ %ld\n",
-                                                 i, map->s_uspace.s_table->i_ino);
-                               }
-                               if (phd->unallocSpaceBitmap.extLength) {
-                                       struct udf_bitmap *bitmap =
-                                               udf_sb_alloc_bitmap(sb, i);
-                                       map->s_uspace.s_bitmap = bitmap;
-                                       if (bitmap != NULL) {
-                                               bitmap->s_extLength =
-                                                       le32_to_cpu(phd->unallocSpaceBitmap.extLength);
-                                               bitmap->s_extPosition =
-                                                       le32_to_cpu(phd->unallocSpaceBitmap.extPosition);
-                                               map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_BITMAP;
-                                               udf_debug("unallocSpaceBitmap (part %d) @ %d\n",
-                                                         i, bitmap->s_extPosition);
-                                       }
-                               }
-                               if (phd->partitionIntegrityTable.extLength)
-                                       udf_debug("partitionIntegrityTable (part %d)\n", i);
-                               if (phd->freedSpaceTable.extLength) {
-                                       kernel_lb_addr loc = {
-                                               .logicalBlockNum = le32_to_cpu(phd->freedSpaceTable.extPosition),
-                                               .partitionReferenceNum = i,
-                                       };
-
-                                       map->s_fspace.s_table =
-                                               udf_iget(sb, loc);
-                                       if (!map->s_fspace.s_table) {
-                                               udf_debug("cannot load freedSpaceTable (part %d)\n", i);
-                                               return 1;
-                                       }
-                                       map->s_partition_flags |=
-                                               UDF_PART_FLAG_FREED_TABLE;
-                                       udf_debug("freedSpaceTable (part %d) @ %ld\n",
-                                                 i, map->s_fspace.s_table->i_ino);
-                               }
-                               if (phd->freedSpaceBitmap.extLength) {
-                                       struct udf_bitmap *bitmap =
-                                               udf_sb_alloc_bitmap(sb, i);
-                                       map->s_fspace.s_bitmap = bitmap;
-                                       if (bitmap != NULL) {
-                                               bitmap->s_extLength =
-                                                       le32_to_cpu(phd->freedSpaceBitmap.extLength);
-                                               bitmap->s_extPosition =
-                                                       le32_to_cpu(phd->freedSpaceBitmap.extPosition);
-                                               map->s_partition_flags |= UDF_PART_FLAG_FREED_BITMAP;
-                                               udf_debug("freedSpaceBitmap (part %d) @ %d\n",
-                                                         i, bitmap->s_extPosition);
-                                       }
-                               }
-                       }
+                         map->s_partition_num, partitionNumber);
+               if (map->s_partition_num == partitionNumber &&
+                   (map->s_partition_type == UDF_TYPE1_MAP15 ||
+                    map->s_partition_type == UDF_SPARABLE_MAP15))
                        break;
-               }
        }
-       if (i == sbi->s_partitions)
+
+       if (i >= sbi->s_partitions) {
                udf_debug("Partition (%d) not found in partition map\n",
-                         le16_to_cpu(p->partitionNumber));
-       else
-               udf_debug("Partition (%d:%d type %x) starts at physical %d, "
-                         "block length %d\n",
-                         le16_to_cpu(p->partitionNumber), i,
-                         map->s_partition_type,
-                         map->s_partition_root,
-                         map->s_partition_len);
-       return 0;
+                         partitionNumber);
+               goto out_bh;
+       }
+
+       ret = udf_fill_partdesc_info(sb, p, i);
+
+       /*
+        * Now rescan for VIRTUAL or METADATA partitions when SPARABLE and
+        * PHYSICAL partitions are already set up
+        */
+       type1_idx = i;
+       for (i = 0; i < sbi->s_partitions; i++) {
+               map = &sbi->s_partmaps[i];
+
+               if (map->s_partition_num == partitionNumber &&
+                   (map->s_partition_type == UDF_VIRTUAL_MAP15 ||
+                    map->s_partition_type == UDF_VIRTUAL_MAP20 ||
+                    map->s_partition_type == UDF_METADATA_MAP25))
+                       break;
+       }
+
+       if (i >= sbi->s_partitions)
+               goto out_bh;
+
+       ret = udf_fill_partdesc_info(sb, p, i);
+       if (ret)
+               goto out_bh;
+
+       if (map->s_partition_type == UDF_METADATA_MAP25) {
+               ret = udf_load_metadata_files(sb, i);
+               if (ret) {
+                       printk(KERN_ERR "UDF-fs: error loading MetaData "
+                       "partition map %d\n", i);
+                       goto out_bh;
+               }
+       } else {
+               ret = udf_load_vat(sb, i, type1_idx);
+               if (ret)
+                       goto out_bh;
+               /*
+                * Mark filesystem read-only if we have a partition with
+                * virtual map since we don't handle writing to it (we
+                * overwrite blocks instead of relocating them).
+                */
+               sb->s_flags |= MS_RDONLY;
+               printk(KERN_NOTICE "UDF-fs: Filesystem marked read-only "
+                       "because writing to pseudooverwrite partition is "
+                       "not implemented.\n");
+       }
+out_bh:
+       /* In case loading failed, we handle cleanup in udf_fill_super */
+       brelse(bh);
+       return ret;
 }
 
-static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
+static int udf_load_logicalvol(struct super_block *sb, sector_t block,
                               kernel_lb_addr *fileset)
 {
        struct logicalVolDesc *lvd;
@@ -1194,12 +1340,21 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
        uint8_t type;
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct genericPartitionMap *gpm;
+       uint16_t ident;
+       struct buffer_head *bh;
+       int ret = 0;
 
+       bh = udf_read_tagged(sb, block, block, &ident);
+       if (!bh)
+               return 1;
+       BUG_ON(ident != TAG_IDENT_LVD);
        lvd = (struct logicalVolDesc *)bh->b_data;
 
        i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
-       if (i != 0)
-               return i;
+       if (i != 0) {
+               ret = i;
+               goto out_bh;
+       }
 
        for (i = 0, offset = 0;
             i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
@@ -1223,12 +1378,12 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
                                u16 suf =
                                        le16_to_cpu(((__le16 *)upm2->partIdent.
                                                        identSuffix)[0]);
-                               if (suf == 0x0150) {
+                               if (suf < 0x0200) {
                                        map->s_partition_type =
                                                        UDF_VIRTUAL_MAP15;
                                        map->s_partition_func =
                                                        udf_get_pblock_virt15;
-                               } else if (suf == 0x0200) {
+                               } else {
                                        map->s_partition_type =
                                                        UDF_VIRTUAL_MAP20;
                                        map->s_partition_func =
@@ -1238,7 +1393,6 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
                                                UDF_ID_SPARABLE,
                                                strlen(UDF_ID_SPARABLE))) {
                                uint32_t loc;
-                               uint16_t ident;
                                struct sparingTable *st;
                                struct sparablePartitionMap *spm =
                                        (struct sparablePartitionMap *)gpm;
@@ -1256,22 +1410,64 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
                                        map->s_type_specific.s_sparing.
                                                        s_spar_map[j] = bh2;
 
-                                       if (bh2 != NULL) {
-                                               st = (struct sparingTable *)
-                                                               bh2->b_data;
-                                               if (ident != 0 || strncmp(
-                                                       st->sparingIdent.ident,
-                                                       UDF_ID_SPARING,
-                                                       strlen(UDF_ID_SPARING))) {
-                                                       brelse(bh2);
-                                                       map->s_type_specific.
-                                                               s_sparing.
-                                                               s_spar_map[j] =
-                                                                       NULL;
-                                               }
+                                       if (bh2 == NULL)
+                                               continue;
+
+                                       st = (struct sparingTable *)bh2->b_data;
+                                       if (ident != 0 || strncmp(
+                                               st->sparingIdent.ident,
+                                               UDF_ID_SPARING,
+                                               strlen(UDF_ID_SPARING))) {
+                                               brelse(bh2);
+                                               map->s_type_specific.s_sparing.
+                                                       s_spar_map[j] = NULL;
                                        }
                                }
                                map->s_partition_func = udf_get_pblock_spar15;
+                       } else if (!strncmp(upm2->partIdent.ident,
+                                               UDF_ID_METADATA,
+                                               strlen(UDF_ID_METADATA))) {
+                               struct udf_meta_data *mdata =
+                                       &map->s_type_specific.s_metadata;
+                               struct metadataPartitionMap *mdm =
+                                               (struct metadataPartitionMap *)
+                                               &(lvd->partitionMaps[offset]);
+                               udf_debug("Parsing Logical vol part %d "
+                                       "type %d  id=%s\n", i, type,
+                                       UDF_ID_METADATA);
+
+                               map->s_partition_type = UDF_METADATA_MAP25;
+                               map->s_partition_func = udf_get_pblock_meta25;
+
+                               mdata->s_meta_file_loc   =
+                                       le32_to_cpu(mdm->metadataFileLoc);
+                               mdata->s_mirror_file_loc =
+                                       le32_to_cpu(mdm->metadataMirrorFileLoc);
+                               mdata->s_bitmap_file_loc =
+                                       le32_to_cpu(mdm->metadataBitmapFileLoc);
+                               mdata->s_alloc_unit_size =
+                                       le32_to_cpu(mdm->allocUnitSize);
+                               mdata->s_align_unit_size =
+                                       le16_to_cpu(mdm->alignUnitSize);
+                               mdata->s_dup_md_flag     =
+                                       mdm->flags & 0x01;
+
+                               udf_debug("Metadata Ident suffix=0x%x\n",
+                                       (le16_to_cpu(
+                                        ((__le16 *)
+                                             mdm->partIdent.identSuffix)[0])));
+                               udf_debug("Metadata part num=%d\n",
+                                       le16_to_cpu(mdm->partitionNum));
+                               udf_debug("Metadata part alloc unit size=%d\n",
+                                       le32_to_cpu(mdm->allocUnitSize));
+                               udf_debug("Metadata file loc=%d\n",
+                                       le32_to_cpu(mdm->metadataFileLoc));
+                               udf_debug("Mirror file loc=%d\n",
+                                      le32_to_cpu(mdm->metadataMirrorFileLoc));
+                               udf_debug("Bitmap file loc=%d\n",
+                                      le32_to_cpu(mdm->metadataBitmapFileLoc));
+                               udf_debug("Duplicate Flag: %d %d\n",
+                                       mdata->s_dup_md_flag, mdm->flags);
                        } else {
                                udf_debug("Unknown ident: %s\n",
                                          upm2->partIdent.ident);
@@ -1296,7 +1492,9 @@ static int udf_load_logicalvol(struct super_block *sb, struct buffer_head *bh,
        if (lvd->integritySeqExt.extLength)
                udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
 
-       return 0;
+out_bh:
+       brelse(bh);
+       return ret;
 }
 
 /*
@@ -1345,7 +1543,7 @@ static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
  *     July 1, 1997 - Andrew E. Mileski
  *     Written, tested, and released.
  */
-static int udf_process_sequence(struct super_block *sb, long block,
+static noinline int udf_process_sequence(struct super_block *sb, long block,
                                long lastblock, kernel_lb_addr *fileset)
 {
        struct buffer_head *bh = NULL;
@@ -1354,19 +1552,25 @@ static int udf_process_sequence(struct super_block *sb, long block,
        struct generic_desc *gd;
        struct volDescPtr *vdp;
        int done = 0;
-       int i, j;
        uint32_t vdsn;
        uint16_t ident;
        long next_s = 0, next_e = 0;
 
        memset(vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
 
-       /* Read the main descriptor sequence */
+       /*
+        * Read the main descriptor sequence and find which descriptors
+        * are in it.
+        */
        for (; (!done && block <= lastblock); block++) {
 
                bh = udf_read_tagged(sb, block, block, &ident);
-               if (!bh)
-                       break;
+               if (!bh) {
+                       printk(KERN_ERR "udf: Block %Lu of volume descriptor "
+                              "sequence is corrupted or we could not read "
+                              "it.\n", (unsigned long long)block);
+                       return 1;
+               }
 
                /* Process each descriptor (ISO 13346 3/8.3-8.4) */
                gd = (struct generic_desc *)bh->b_data;
@@ -1432,41 +1636,31 @@ static int udf_process_sequence(struct super_block *sb, long block,
                }
                brelse(bh);
        }
-       for (i = 0; i < VDS_POS_LENGTH; i++) {
-               if (vds[i].block) {
-                       bh = udf_read_tagged(sb, vds[i].block, vds[i].block,
-                                            &ident);
-
-                       if (i == VDS_POS_PRIMARY_VOL_DESC) {
-                               udf_load_pvoldesc(sb, bh);
-                       } else if (i == VDS_POS_LOGICAL_VOL_DESC) {
-                               if (udf_load_logicalvol(sb, bh, fileset)) {
-                                       brelse(bh);
-                                       return 1;
-                               }
-                       } else if (i == VDS_POS_PARTITION_DESC) {
-                               struct buffer_head *bh2 = NULL;
-                               if (udf_load_partdesc(sb, bh)) {
-                                       brelse(bh);
-                                       return 1;
-                               }
-                               for (j = vds[i].block + 1;
-                                    j <  vds[VDS_POS_TERMINATING_DESC].block;
-                                    j++) {
-                                       bh2 = udf_read_tagged(sb, j, j, &ident);
-                                       gd = (struct generic_desc *)bh2->b_data;
-                                       if (ident == TAG_IDENT_PD)
-                                               if (udf_load_partdesc(sb,
-                                                                     bh2)) {
-                                                       brelse(bh);
-                                                       brelse(bh2);
-                                                       return 1;
-                                               }
-                                       brelse(bh2);
-                               }
-                       }
-                       brelse(bh);
-               }
+       /*
+        * Now read interesting descriptors again and process them
+        * in a suitable order
+        */
+       if (!vds[VDS_POS_PRIMARY_VOL_DESC].block) {
+               printk(KERN_ERR "udf: Primary Volume Descriptor not found!\n");
+               return 1;
+       }
+       if (udf_load_pvoldesc(sb, vds[VDS_POS_PRIMARY_VOL_DESC].block))
+               return 1;
+
+       if (vds[VDS_POS_LOGICAL_VOL_DESC].block && udf_load_logicalvol(sb,
+           vds[VDS_POS_LOGICAL_VOL_DESC].block, fileset))
+               return 1;
+
+       if (vds[VDS_POS_PARTITION_DESC].block) {
+               /*
+                * We rescan the whole descriptor sequence to find
+                * partition descriptor blocks and process them.
+                */
+               for (block = vds[VDS_POS_PARTITION_DESC].block;
+                    block < vds[VDS_POS_TERMINATING_DESC].block;
+                    block++)
+                       if (udf_load_partdesc(sb, block))
+                               return 1;
        }
 
        return 0;
@@ -1478,6 +1672,7 @@ static int udf_process_sequence(struct super_block *sb, long block,
 static int udf_check_valid(struct super_block *sb, int novrs, int silent)
 {
        long block;
+       struct udf_sb_info *sbi = UDF_SB(sb);
 
        if (novrs) {
                udf_debug("Validity check skipped because of novrs option\n");
@@ -1485,27 +1680,22 @@ static int udf_check_valid(struct super_block *sb, int novrs, int silent)
        }
        /* Check that it is NSR02 compliant */
        /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */
-       else {
-               block = udf_vrs(sb, silent);
-               if (block == -1) {
-                       struct udf_sb_info *sbi = UDF_SB(sb);
-                       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);
-                       return 0;
-               } else
-                       return !block;
-       }
+       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;
 }
 
-static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
+static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset)
 {
        struct anchorVolDescPtr *anchor;
        uint16_t ident;
        struct buffer_head *bh;
        long main_s, main_e, reserve_s, reserve_e;
-       int i, j;
+       int i;
        struct udf_sb_info *sbi;
 
        if (!sb)
@@ -1515,6 +1705,7 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
        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)
@@ -1553,76 +1744,6 @@ static int udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
        }
        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);
-               struct udf_part_map *map = &sbi->s_partmaps[i];
-               switch (map->s_partition_type) {
-               case UDF_VIRTUAL_MAP15:
-               case UDF_VIRTUAL_MAP20:
-                       if (!sbi->s_last_block) {
-                               sbi->s_last_block = udf_get_last_block(sb);
-                               udf_find_anchor(sb);
-                       }
-
-                       if (!sbi->s_last_block) {
-                               udf_debug("Unable to determine Lastblock (For "
-                                         "Virtual Partition)\n");
-                               return 1;
-                       }
-
-                       for (j = 0; j < sbi->s_partitions; j++) {
-                               struct udf_part_map *map2 = &sbi->s_partmaps[j];
-                               if (j != i &&
-                                   map->s_volumeseqnum ==
-                                               map2->s_volumeseqnum &&
-                                   map->s_partition_num ==
-                                               map2->s_partition_num) {
-                                       ino.partitionReferenceNum = j;
-                                       ino.logicalBlockNum =
-                                               sbi->s_last_block -
-                                                       map2->s_partition_root;
-                                       break;
-                               }
-                       }
-
-                       if (j == sbi->s_partitions)
-                               return 1;
-
-                       sbi->s_vat_inode = udf_iget(sb, ino);
-                       if (!sbi->s_vat_inode)
-                               return 1;
-
-                       if (map->s_partition_type == UDF_VIRTUAL_MAP15) {
-                               map->s_type_specific.s_virtual.s_start_offset =
-                                       udf_ext0_offset(sbi->s_vat_inode);
-                               map->s_type_specific.s_virtual.s_num_entries =
-                                       (sbi->s_vat_inode->i_size - 36) >> 2;
-                       } else if (map->s_partition_type == UDF_VIRTUAL_MAP20) {
-                               uint32_t pos;
-                               struct virtualAllocationTable20 *vat20;
-
-                               pos = udf_block_map(sbi->s_vat_inode, 0);
-                               bh = sb_bread(sb, pos);
-                               if (!bh)
-                                       return 1;
-                               vat20 = (struct virtualAllocationTable20 *)
-                                       bh->b_data +
-                                       udf_ext0_offset(sbi->s_vat_inode);
-                               map->s_type_specific.s_virtual.s_start_offset =
-                                       le16_to_cpu(vat20->lengthHeader) +
-                                       udf_ext0_offset(sbi->s_vat_inode);
-                               map->s_type_specific.s_virtual.s_num_entries =
-                                       (sbi->s_vat_inode->i_size -
-                                        map->s_type_specific.s_virtual.
-                                                       s_start_offset) >> 2;
-                               brelse(bh);
-                       }
-                       map->s_partition_root = udf_get_pblock(sb, 0, i, 0);
-                       map->s_partition_len =
-                               sbi->s_partmaps[ino.partitionReferenceNum].
-                                                               s_partition_len;
-               }
-       }
        return 0;
 }
 
@@ -1630,65 +1751,61 @@ 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) {
-               kernel_timestamp cpu_time;
-               struct logicalVolIntegrityDesc *lvid =
-                               (struct logicalVolIntegrityDesc *)bh->b_data;
-               struct logicalVolIntegrityDescImpUse *lvidiu =
-                                                       udf_sb_lvidiu(sbi);
+       struct logicalVolIntegrityDesc *lvid;
+       struct logicalVolIntegrityDescImpUse *lvidiu;
+       if (!bh)
+               return;
 
-               lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
-               lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-               if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
-                       lvid->recordingDateAndTime = cpu_to_lets(cpu_time);
-               lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
+       lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+       lvidiu = udf_sb_lvidiu(sbi);
 
-               lvid->descTag.descCRC = cpu_to_le16(
-                       udf_crc((char *)lvid + sizeof(tag),
-                               le16_to_cpu(lvid->descTag.descCRCLength),
-                               0));
+       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);
+       lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
 
-               lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
-               mark_buffer_dirty(bh);
-       }
+       lvid->descTag.descCRC = cpu_to_le16(
+               crc_itu_t(0, (char *)lvid + sizeof(tag),
+                       le16_to_cpu(lvid->descTag.descCRCLength)));
+
+       lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+       mark_buffer_dirty(bh);
 }
 
 static void udf_close_lvid(struct super_block *sb)
 {
-       kernel_timestamp cpu_time;
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
+       struct logicalVolIntegrityDescImpUse *lvidiu;
 
        if (!bh)
                return;
 
        lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
 
-       if (lvid->integrityType == LVID_INTEGRITY_TYPE_OPEN) {
-               struct logicalVolIntegrityDescImpUse *lvidiu =
-                                                       udf_sb_lvidiu(sbi);
-               lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
-               lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-               if (udf_time_to_stamp(&cpu_time, CURRENT_TIME))
-                       lvid->recordingDateAndTime = cpu_to_lets(cpu_time);
-               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))
-                       lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
-               if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
-                       lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
-               lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
-
-               lvid->descTag.descCRC = cpu_to_le16(
-                       udf_crc((char *)lvid + sizeof(tag),
-                               le16_to_cpu(lvid->descTag.descCRCLength),
-                               0));
-
-               lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
-               mark_buffer_dirty(bh);
-       }
+       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;
+       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME);
+       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))
+               lvidiu->minUDFReadRev = cpu_to_le16(sbi->s_udfrev);
+       if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFWriteRev))
+               lvidiu->minUDFWriteRev = cpu_to_le16(sbi->s_udfrev);
+       lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
+
+       lvid->descTag.descCRC = cpu_to_le16(
+                       crc_itu_t(0, (char *)lvid + sizeof(tag),
+                               le16_to_cpu(lvid->descTag.descCRCLength)));
+
+       lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+       mark_buffer_dirty(bh);
 }
 
 static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
@@ -1708,22 +1825,35 @@ static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
                vfree(bitmap);
 }
 
-/*
- * udf_read_super
- *
- * PURPOSE
- *     Complete the specified super block.
- *
- * PRE-CONDITIONS
- *     sb                      Pointer to superblock to complete - never NULL.
- *     sb->s_dev               Device to read suberblock from.
- *     options                 Pointer to mount options.
- *     silent                  Silent flag.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
+static void udf_free_partition(struct udf_part_map *map)
+{
+       int i;
+       struct udf_meta_data *mdata;
+
+       if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
+               iput(map->s_uspace.s_table);
+       if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
+               iput(map->s_fspace.s_table);
+       if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
+               udf_sb_free_bitmap(map->s_uspace.s_bitmap);
+       if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
+               udf_sb_free_bitmap(map->s_fspace.s_bitmap);
+       if (map->s_partition_type == UDF_SPARABLE_MAP15)
+               for (i = 0; i < 4; i++)
+                       brelse(map->s_type_specific.s_sparing.s_spar_map[i]);
+       else if (map->s_partition_type == UDF_METADATA_MAP25) {
+               mdata = &map->s_type_specific.s_metadata;
+               iput(mdata->s_metadata_fe);
+               mdata->s_metadata_fe = NULL;
+
+               iput(mdata->s_mirror_fe);
+               mdata->s_mirror_fe = NULL;
+
+               iput(mdata->s_bitmap_fe);
+               mdata->s_bitmap_fe = NULL;
+       }
+}
+
 static int udf_fill_super(struct super_block *sb, void *options, int silent)
 {
        int i;
@@ -1776,8 +1906,11 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sbi->s_nls_map = uopt.nls_map;
 
        /* Set the block size for all transfers */
-       if (!udf_set_blocksize(sb, uopt.blocksize))
+       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);
@@ -1789,7 +1922,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sbi->s_last_block = uopt.lastblock;
        sbi->s_anchor[0] = sbi->s_anchor[1] = 0;
        sbi->s_anchor[2] = uopt.anchor;
-       sbi->s_anchor[3] = 256;
 
        if (udf_check_valid(sb, uopt.novrs, silent)) {
                /* read volume recognition sequences */
@@ -1806,7 +1938,7 @@ 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_partition(sb, &fileset)) {
+       if (udf_load_sequence(sb, &fileset)) {
                printk(KERN_WARNING "UDF-fs: No partition found (1)\n");
                goto error_out;
        }
@@ -1856,12 +1988,12 @@ 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);
+               timestamp ts;
+               udf_time_to_disk_stamp(&ts, sbi->s_record_time);
                udf_info("UDF: Mounting volume '%s', "
                         "timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
-                        sbi->s_volume_ident, ts.year, ts.month, ts.day,
-                        ts.hour, ts.minute, ts.typeAndTimezone);
+                        sbi->s_volume_ident, le16_to_cpu(ts.year), ts.month, ts.day,
+                        ts.hour, ts.minute, le16_to_cpu(ts.typeAndTimezone));
        }
        if (!(sb->s_flags & MS_RDONLY))
                udf_open_lvid(sb);
@@ -1890,21 +2022,9 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 error_out:
        if (sbi->s_vat_inode)
                iput(sbi->s_vat_inode);
-       if (sbi->s_partitions) {
-               struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
-               if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
-                       iput(map->s_uspace.s_table);
-               if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
-                       iput(map->s_fspace.s_table);
-               if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
-                       udf_sb_free_bitmap(map->s_uspace.s_bitmap);
-               if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
-                       udf_sb_free_bitmap(map->s_fspace.s_bitmap);
-               if (map->s_partition_type == UDF_SPARABLE_MAP15)
-                       for (i = 0; i < 4; i++)
-                               brelse(map->s_type_specific.s_sparing.
-                                               s_spar_map[i]);
-       }
+       if (sbi->s_partitions)
+               for (i = 0; i < sbi->s_partitions; i++)
+                       udf_free_partition(&sbi->s_partmaps[i]);
 #ifdef CONFIG_UDF_NLS
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
                unload_nls(sbi->s_nls_map);
@@ -1920,8 +2040,8 @@ error_out:
        return -EINVAL;
 }
 
-void udf_error(struct super_block *sb, const char *function,
-              const char *fmt, ...)
+static void udf_error(struct super_block *sb, const char *function,
+                     const char *fmt, ...)
 {
        va_list args;
 
@@ -1948,19 +2068,6 @@ void udf_warning(struct super_block *sb, const char *function,
               sb->s_id, function, error_buf);
 }
 
-/*
- * udf_put_super
- *
- * PURPOSE
- *     Prepare for destruction of the superblock.
- *
- * DESCRIPTION
- *     Called before the filesystem is unmounted.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
 static void udf_put_super(struct super_block *sb)
 {
        int i;
@@ -1969,21 +2076,9 @@ static void udf_put_super(struct super_block *sb)
        sbi = UDF_SB(sb);
        if (sbi->s_vat_inode)
                iput(sbi->s_vat_inode);
-       if (sbi->s_partitions) {
-               struct udf_part_map *map = &sbi->s_partmaps[sbi->s_partition];
-               if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE)
-                       iput(map->s_uspace.s_table);
-               if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE)
-                       iput(map->s_fspace.s_table);
-               if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP)
-                       udf_sb_free_bitmap(map->s_uspace.s_bitmap);
-               if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP)
-                       udf_sb_free_bitmap(map->s_fspace.s_bitmap);
-               if (map->s_partition_type == UDF_SPARABLE_MAP15)
-                       for (i = 0; i < 4; i++)
-                               brelse(map->s_type_specific.s_sparing.
-                                               s_spar_map[i]);
-       }
+       if (sbi->s_partitions)
+               for (i = 0; i < sbi->s_partitions; i++)
+                       udf_free_partition(&sbi->s_partmaps[i]);
 #ifdef CONFIG_UDF_NLS
        if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
                unload_nls(sbi->s_nls_map);
@@ -1996,19 +2091,6 @@ static void udf_put_super(struct super_block *sb)
        sb->s_fs_info = NULL;
 }
 
-/*
- * udf_stat_fs
- *
- * PURPOSE
- *     Return info about the filesystem.
- *
- * DESCRIPTION
- *     Called by sys_statfs()
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
 static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
@@ -2035,10 +2117,6 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
-static unsigned char udf_bitmap_lookup[16] = {
-       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
-};
-
 static unsigned int udf_count_free_bitmap(struct super_block *sb,
                                          struct udf_bitmap *bitmap)
 {
@@ -2048,7 +2126,6 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
        int block = 0, newblock;
        kernel_lb_addr loc;
        uint32_t bytes;
-       uint8_t value;
        uint8_t *ptr;
        uint16_t ident;
        struct spaceBitmapDesc *bm;
@@ -2074,13 +2151,10 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb,
        ptr = (uint8_t *)bh->b_data;
 
        while (bytes > 0) {
-               while ((bytes > 0) && (index < sb->s_blocksize)) {
-                       value = ptr[index];
-                       accum += udf_bitmap_lookup[value & 0x0f];
-                       accum += udf_bitmap_lookup[value >> 4];
-                       index++;
-                       bytes--;
-               }
+               u32 cur_bytes = min_t(u32, bytes, sb->s_blocksize - index);
+               accum += bitmap_weight((const unsigned long *)(ptr + index),
+                                       cur_bytes * 8);
+               bytes -= cur_bytes;
                if (bytes) {
                        brelse(bh);
                        newblock = udf_get_lb_pblock(sb, loc, ++block);
index 6ec99221e50c6c02dd90df64e8b0a39d9bc771b8..c3265e1385d43c5c6ed0e2960cf9d83a72493e4a 100644 (file)
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/udf_fs.h>
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/stat.h>
index fe61be17cdab93315f5f66b32d5add96b20b1d23..65e19b4f9424c20f8f616b7ee5de3db55f33ed0e 100644 (file)
@@ -22,7 +22,6 @@
 #include "udfdecl.h"
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/udf_fs.h>
 #include <linux/buffer_head.h>
 
 #include "udf_i.h"
@@ -180,6 +179,24 @@ void udf_discard_prealloc(struct inode *inode)
        brelse(epos.bh);
 }
 
+static void udf_update_alloc_ext_desc(struct inode *inode,
+                                     struct extent_position *epos,
+                                     u32 lenalloc)
+{
+       struct super_block *sb = inode->i_sb;
+       struct udf_sb_info *sbi = UDF_SB(sb);
+
+       struct allocExtDesc *aed = (struct allocExtDesc *) (epos->bh->b_data);
+       int len = sizeof(struct allocExtDesc);
+
+       aed->lengthAllocDescs = cpu_to_le32(lenalloc);
+       if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || sbi->s_udfrev >= 0x0201)
+               len += lenalloc;
+
+       udf_update_tag(epos->bh->b_data, len);
+       mark_buffer_dirty_inode(epos->bh, inode);
+}
+
 void udf_truncate_extents(struct inode *inode)
 {
        struct extent_position epos;
@@ -187,7 +204,6 @@ void udf_truncate_extents(struct inode *inode)
        uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
        int8_t etype;
        struct super_block *sb = inode->i_sb;
-       struct udf_sb_info *sbi = UDF_SB(sb);
        sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset;
        loff_t byte_offset;
        int adsize;
@@ -224,35 +240,15 @@ void udf_truncate_extents(struct inode *inode)
                                if (indirect_ext_len) {
                                        /* We managed to free all extents in the
                                         * indirect extent - free it too */
-                                       if (!epos.bh)
-                                               BUG();
+                                       BUG_ON(!epos.bh);
                                        udf_free_blocks(sb, inode, epos.block,
                                                        0, indirect_ext_len);
-                               } else {
-                                       if (!epos.bh) {
-                                               iinfo->i_lenAlloc =
-                                                               lenalloc;
-                                               mark_inode_dirty(inode);
-                                       } else {
-                                               struct allocExtDesc *aed =
-                                                       (struct allocExtDesc *)
-                                                       (epos.bh->b_data);
-                                               int len =
-                                                   sizeof(struct allocExtDesc);
-
-                                               aed->lengthAllocDescs =
-                                                   cpu_to_le32(lenalloc);
-                                               if (!UDF_QUERY_FLAG(sb,
-                                                       UDF_FLAG_STRICT) ||
-                                                   sbi->s_udfrev >= 0x0201)
-                                                       len += lenalloc;
-
-                                               udf_update_tag(epos.bh->b_data,
-                                                               len);
-                                               mark_buffer_dirty_inode(
-                                                               epos.bh, inode);
-                                       }
-                               }
+                               } else if (!epos.bh) {
+                                       iinfo->i_lenAlloc = lenalloc;
+                                       mark_inode_dirty(inode);
+                               } else
+                                       udf_update_alloc_ext_desc(inode,
+                                                       &epos, lenalloc);
                                brelse(epos.bh);
                                epos.offset = sizeof(struct allocExtDesc);
                                epos.block = eloc;
@@ -272,29 +268,14 @@ void udf_truncate_extents(struct inode *inode)
                }
 
                if (indirect_ext_len) {
-                       if (!epos.bh)
-                               BUG();
+                       BUG_ON(!epos.bh);
                        udf_free_blocks(sb, inode, epos.block, 0,
                                        indirect_ext_len);
-               } else {
-                       if (!epos.bh) {
-                               iinfo->i_lenAlloc = lenalloc;
-                               mark_inode_dirty(inode);
-                       } else {
-                               struct allocExtDesc *aed =
-                                   (struct allocExtDesc *)(epos.bh->b_data);
-                               aed->lengthAllocDescs = cpu_to_le32(lenalloc);
-                               if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) ||
-                                   sbi->s_udfrev >= 0x0201)
-                                       udf_update_tag(epos.bh->b_data,
-                                               lenalloc +
-                                               sizeof(struct allocExtDesc));
-                               else
-                                       udf_update_tag(epos.bh->b_data,
-                                               sizeof(struct allocExtDesc));
-                               mark_buffer_dirty_inode(epos.bh, inode);
-                       }
-               }
+               } else if (!epos.bh) {
+                       iinfo->i_lenAlloc = lenalloc;
+                       mark_inode_dirty(inode);
+               } else
+                       udf_update_alloc_ext_desc(inode, &epos, lenalloc);
        } else if (inode->i_size) {
                if (byte_offset) {
                        kernel_long_ad extent;
index ccc52f16bf7d573291a94aedab5ef6d33cfc8bee..4f86b1d98a5d44ffbf1ae64bee4618c2dfcf3b4a 100644 (file)
@@ -1,10 +1,32 @@
-#ifndef __LINUX_UDF_I_H
-#define __LINUX_UDF_I_H
+#ifndef _UDF_I_H
+#define _UDF_I_H
+
+struct udf_inode_info {
+       struct timespec         i_crtime;
+       /* Physical address of inode */
+       kernel_lb_addr          i_location;
+       __u64                   i_unique;
+       __u32                   i_lenEAttr;
+       __u32                   i_lenAlloc;
+       __u64                   i_lenExtents;
+       __u32                   i_next_alloc_block;
+       __u32                   i_next_alloc_goal;
+       unsigned                i_alloc_type : 3;
+       unsigned                i_efe : 1;      /* extendedFileEntry */
+       unsigned                i_use : 1;      /* unallocSpaceEntry */
+       unsigned                i_strat4096 : 1;
+       unsigned                reserved : 26;
+       union {
+               short_ad        *i_sad;
+               long_ad         *i_lad;
+               __u8            *i_data;
+       } i_ext;
+       struct inode vfs_inode;
+};
 
-#include <linux/udf_fs_i.h>
 static inline struct udf_inode_info *UDF_I(struct inode *inode)
 {
        return list_entry(inode, struct udf_inode_info, vfs_inode);
 }
 
-#endif /* !defined(_LINUX_UDF_I_H) */
+#endif /* _UDF_I_H) */
index 737d1c604eea0330848b1223dc4e696f4fee0cb7..1c1c514a9725116f19cf559e3af969251d99c74e 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef __LINUX_UDF_SB_H
 #define __LINUX_UDF_SB_H
 
+#include <linux/mutex.h>
+
 /* Since UDF 2.01 is ISO 13346 based... */
 #define UDF_SUPER_MAGIC                        0x15013346
 
-#define UDF_MAX_READ_VERSION           0x0201
+#define UDF_MAX_READ_VERSION           0x0250
 #define UDF_MAX_WRITE_VERSION          0x0201
 
 #define UDF_FLAG_USE_EXTENDED_FE       0
 #define UDF_PART_FLAG_REWRITABLE       0x0040
 #define UDF_PART_FLAG_OVERWRITABLE     0x0080
 
+#define UDF_MAX_BLOCK_LOADED   8
+
+#define UDF_TYPE1_MAP15                        0x1511U
+#define UDF_VIRTUAL_MAP15              0x1512U
+#define UDF_VIRTUAL_MAP20              0x2012U
+#define UDF_SPARABLE_MAP15             0x1522U
+#define UDF_METADATA_MAP25             0x2511U
+
+#pragma pack(1) /* XXX(hch): Why?  This file just defines in-core structures */
+
+struct udf_meta_data {
+       __u32   s_meta_file_loc;
+       __u32   s_mirror_file_loc;
+       __u32   s_bitmap_file_loc;
+       __u32   s_alloc_unit_size;
+       __u16   s_align_unit_size;
+       __u8    s_dup_md_flag;
+       struct inode *s_metadata_fe;
+       struct inode *s_mirror_fe;
+       struct inode *s_bitmap_fe;
+};
+
+struct udf_sparing_data {
+       __u16   s_packet_len;
+       struct buffer_head *s_spar_map[4];
+};
+
+struct udf_virtual_data {
+       __u32   s_num_entries;
+       __u16   s_start_offset;
+};
+
+struct udf_bitmap {
+       __u32                   s_extLength;
+       __u32                   s_extPosition;
+       __u16                   s_nr_groups;
+       struct buffer_head      **s_block_bitmap;
+};
+
+struct udf_part_map {
+       union {
+               struct udf_bitmap       *s_bitmap;
+               struct inode            *s_table;
+       } s_uspace;
+       union {
+               struct udf_bitmap       *s_bitmap;
+               struct inode            *s_table;
+       } s_fspace;
+       __u32   s_partition_root;
+       __u32   s_partition_len;
+       __u16   s_partition_type;
+       __u16   s_partition_num;
+       union {
+               struct udf_sparing_data s_sparing;
+               struct udf_virtual_data s_virtual;
+               struct udf_meta_data s_metadata;
+       } s_type_specific;
+       __u32   (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
+       __u16   s_volumeseqnum;
+       __u16   s_partition_flags;
+};
+
+#pragma pack()
+
+struct udf_sb_info {
+       struct udf_part_map     *s_partmaps;
+       __u8                    s_volume_ident[32];
+
+       /* Overall info */
+       __u16                   s_partitions;
+       __u16                   s_partition;
+
+       /* Sector headers */
+       __s32                   s_session;
+       __u32                   s_anchor[3];
+       __u32                   s_last_block;
+
+       struct buffer_head      *s_lvid_bh;
+
+       /* Default permissions */
+       mode_t                  s_umask;
+       gid_t                   s_gid;
+       uid_t                   s_uid;
+
+       /* Root Info */
+       struct timespec         s_record_time;
+
+       /* Fileset Info */
+       __u16                   s_serial_number;
+
+       /* highest UDF revision we have recorded to this media */
+       __u16                   s_udfrev;
+
+       /* Miscellaneous flags */
+       __u32                   s_flags;
+
+       /* Encoding info */
+       struct nls_table        *s_nls_map;
+
+       /* VAT inode */
+       struct inode            *s_vat_inode;
+
+       struct mutex            s_alloc_mutex;
+};
+
 static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
index 681dc2b66cdbb9583e7c8f2d958f227f96928380..f3f45d029277a4f1b038c6baf38ca2cce8703739 100644 (file)
@@ -1,17 +1,37 @@
 #ifndef __UDF_DECL_H
 #define __UDF_DECL_H
 
-#include <linux/udf_fs.h>
 #include "ecma_167.h"
 #include "osta_udf.h"
 
 #include <linux/fs.h>
 #include <linux/types.h>
-#include <linux/udf_fs_i.h>
-#include <linux/udf_fs_sb.h>
 #include <linux/buffer_head.h>
+#include <linux/udf_fs_i.h>
 
+#include "udf_sb.h"
 #include "udfend.h"
+#include "udf_i.h"
+
+#define UDF_PREALLOCATE
+#define UDF_DEFAULT_PREALLOC_BLOCKS    8
+
+#define UDFFS_DEBUG
+
+#ifdef UDFFS_DEBUG
+#define udf_debug(f, a...) \
+do { \
+       printk(KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
+               __FILE__, __LINE__, __func__); \
+       printk(f, ##a); \
+} while (0)
+#else
+#define udf_debug(f, a...) /**/
+#endif
+
+#define udf_info(f, a...) \
+       printk(KERN_INFO "UDF-fs INFO " f, ##a);
+
 
 #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
 #define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
 #define UDF_NAME_LEN           256
 #define UDF_PATH_LEN           1023
 
-#define udf_file_entry_alloc_offset(inode)\
-       (UDF_I(inode)->i_use ?\
-               sizeof(struct unallocSpaceEntry) :\
-               ((UDF_I(inode)->i_efe ?\
-                       sizeof(struct extendedFileEntry) :\
-                       sizeof(struct fileEntry)) + UDF_I(inode)->i_lenEAttr))
-
-#define udf_ext0_offset(inode)\
-       (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB ?\
-               udf_file_entry_alloc_offset(inode) : 0)
+static inline size_t udf_file_entry_alloc_offset(struct inode *inode)
+{
+       struct udf_inode_info *iinfo = UDF_I(inode);
+       if (iinfo->i_use)
+               return sizeof(struct unallocSpaceEntry);
+       else if (iinfo->i_efe)
+               return sizeof(struct extendedFileEntry) + iinfo->i_lenEAttr;
+       else
+               return sizeof(struct fileEntry) + iinfo->i_lenEAttr;
+}
+
+static inline size_t udf_ext0_offset(struct inode *inode)
+{
+       if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+               return udf_file_entry_alloc_offset(inode);
+       else
+               return 0;
+}
 
 #define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset))
 
@@ -83,7 +111,6 @@ struct extent_position {
 };
 
 /* super.c */
-extern void udf_error(struct super_block *, const char *, const char *, ...);
 extern void udf_warning(struct super_block *, const char *, const char *, ...);
 
 /* namei.c */
@@ -150,6 +177,8 @@ extern uint32_t udf_get_pblock_virt20(struct super_block *, uint32_t, uint16_t,
                                      uint32_t);
 extern uint32_t udf_get_pblock_spar15(struct super_block *, uint32_t, uint16_t,
                                      uint32_t);
+extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t,
+                                         uint32_t);
 extern int udf_relocate_blocks(struct super_block *, long, long *);
 
 /* unicode.c */
@@ -157,7 +186,7 @@ extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
 extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *,
                            int);
 extern int udf_build_ustr(struct ustr *, dstring *, int);
-extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
+extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);
 
 /* ialloc.c */
 extern void udf_free_inode(struct inode *);
@@ -191,11 +220,9 @@ extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize,
 extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int);
 extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int);
 
-/* crc.c */
-extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
-
 /* udftime.c */
-extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
-extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
+extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest,
+                                               timestamp src);
+extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src);
 
 #endif                         /* __UDF_DECL_H */
index c4bd1203f857a5bb72c8df677c23aaebacc5f396..489f52fb428cd309fb73002be58ce8b38bb09f0d 100644 (file)
@@ -24,17 +24,6 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
        return out;
 }
 
-static inline kernel_timestamp lets_to_cpu(timestamp in)
-{
-       kernel_timestamp out;
-
-       memcpy(&out, &in, sizeof(timestamp));
-       out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
-       out.year = le16_to_cpu(in.year);
-
-       return out;
-}
-
 static inline short_ad lesa_to_cpu(short_ad in)
 {
        short_ad out;
@@ -85,15 +74,4 @@ static inline kernel_extent_ad leea_to_cpu(extent_ad in)
        return out;
 }
 
-static inline timestamp cpu_to_lets(kernel_timestamp in)
-{
-       timestamp out;
-
-       memcpy(&out, &in, sizeof(timestamp));
-       out.typeAndTimezone = cpu_to_le16(in.typeAndTimezone);
-       out.year = cpu_to_le16(in.year);
-
-       return out;
-}
-
 #endif /* __UDF_ENDIAN_H */
index ce595732ba6f37e0fd697ddc3ca4cfe9ab5f9423..5f811655c9b51abbdbd33f39113a9e963df66aa5 100644 (file)
@@ -85,39 +85,38 @@ extern struct timezone sys_tz;
 #define SECS_PER_HOUR  (60 * 60)
 #define SECS_PER_DAY   (SECS_PER_HOUR * 24)
 
-time_t *udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
+struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src)
 {
        int yday;
-       uint8_t type = src.typeAndTimezone >> 12;
+       u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
+       u16 year = le16_to_cpu(src.year);
+       uint8_t type = typeAndTimezone >> 12;
        int16_t offset;
 
        if (type == 1) {
-               offset = src.typeAndTimezone << 4;
+               offset = typeAndTimezone << 4;
                /* sign extent offset */
                offset = (offset >> 4);
                if (offset == -2047) /* unspecified offset */
                        offset = 0;
-       } else {
+       } else
                offset = 0;
-       }
 
-       if ((src.year < EPOCH_YEAR) ||
-           (src.year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
-               *dest = -1;
-               *dest_usec = -1;
+       if ((year < EPOCH_YEAR) ||
+           (year >= EPOCH_YEAR + MAX_YEAR_SECONDS)) {
                return NULL;
        }
-       *dest = year_seconds[src.year - EPOCH_YEAR];
-       *dest -= offset * 60;
+       dest->tv_sec = year_seconds[year - EPOCH_YEAR];
+       dest->tv_sec -= offset * 60;
 
-       yday = ((__mon_yday[__isleap(src.year)][src.month - 1]) + src.day - 1);
-       *dest += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
-       *dest_usec = src.centiseconds * 10000 +
-                       src.hundredsOfMicroseconds * 100 + src.microseconds;
+       yday = ((__mon_yday[__isleap(year)][src.month - 1]) + src.day - 1);
+       dest->tv_sec += (((yday * 24) + src.hour) * 60 + src.minute) * 60 + src.second;
+       dest->tv_nsec = 1000 * (src.centiseconds * 10000 +
+                       src.hundredsOfMicroseconds * 100 + src.microseconds);
        return dest;
 }
 
-kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
+timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts)
 {
        long int days, rem, y;
        const unsigned short int *ip;
@@ -128,7 +127,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
        if (!dest)
                return NULL;
 
-       dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
+       dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
 
        ts.tv_sec += offset * 60;
        days = ts.tv_sec / SECS_PER_DAY;
@@ -151,7 +150,7 @@ kernel_timestamp *udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
                         - LEAPS_THRU_END_OF(y - 1));
                y = yg;
        }
-       dest->year = y;
+       dest->year = cpu_to_le16(y);
        ip = __mon_yday[__isleap(y)];
        for (y = 11; days < (long int)ip[y]; --y)
                continue;
index e533b11703bf60a1e8e5d2a0d94b909585940a1d..9fdf8c93c58e7893616bea99730cc594a3731361 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>      /* for memset */
 #include <linux/nls.h>
-#include <linux/udf_fs.h>
+#include <linux/crc-itu-t.h>
 
 #include "udf_sb.h"
 
@@ -49,14 +49,16 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
 {
        int usesize;
 
-       if ((!dest) || (!ptr) || (!size))
+       if (!dest || !ptr || !size)
                return -1;
+       BUG_ON(size < 2);
 
-       memset(dest, 0, sizeof(struct ustr));
-       usesize = (size > UDF_NAME_LEN) ? UDF_NAME_LEN : size;
+       usesize = min_t(size_t, ptr[size - 1], sizeof(dest->u_name));
+       usesize = min(usesize, size - 2);
        dest->u_cmpID = ptr[0];
-       dest->u_len = ptr[size - 1];
-       memcpy(dest->u_name, ptr + 1, usesize - 1);
+       dest->u_len = usesize;
+       memcpy(dest->u_name, ptr + 1, usesize);
+       memset(dest->u_name + usesize, 0, sizeof(dest->u_name) - usesize);
 
        return 0;
 }
@@ -83,9 +85,6 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
  * PURPOSE
  *     Convert OSTA Compressed Unicode to the UTF-8 equivalent.
  *
- * DESCRIPTION
- *     This routine is only called by udf_filldir().
- *
  * PRE-CONDITIONS
  *     utf                     Pointer to UTF-8 output buffer.
  *     ocu                     Pointer to OSTA Compressed Unicode input buffer
@@ -99,43 +98,39 @@ static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
  *     November 12, 1997 - Andrew E. Mileski
  *     Written, tested, and released.
  */
-int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
+int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
 {
-       uint8_t *ocu;
-       uint32_t c;
+       const uint8_t *ocu;
        uint8_t cmp_id, ocu_len;
        int i;
 
-       ocu = ocu_i->u_name;
-
        ocu_len = ocu_i->u_len;
-       cmp_id = ocu_i->u_cmpID;
-       utf_o->u_len = 0;
-
        if (ocu_len == 0) {
                memset(utf_o, 0, sizeof(struct ustr));
-               utf_o->u_cmpID = 0;
-               utf_o->u_len = 0;
                return 0;
        }
 
-       if ((cmp_id != 8) && (cmp_id != 16)) {
+       cmp_id = ocu_i->u_cmpID;
+       if (cmp_id != 8 && cmp_id != 16) {
+               memset(utf_o, 0, sizeof(struct ustr));
                printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
                       cmp_id, ocu_i->u_name);
                return 0;
        }
 
+       ocu = ocu_i->u_name;
+       utf_o->u_len = 0;
        for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
 
                /* Expand OSTA compressed Unicode to Unicode */
-               c = ocu[i++];
+               uint32_t c = ocu[i++];
                if (cmp_id == 16)
                        c = (c << 8) | ocu[i++];
 
                /* Compress Unicode to UTF-8 */
-               if (c < 0x80U) {
+               if (c < 0x80U)
                        utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
-               else if (c < 0x800U) {
+               else if (c < 0x800U) {
                        utf_o->u_name[utf_o->u_len++] =
                                                (uint8_t)(0xc0 | (c >> 6));
                        utf_o->u_name[utf_o->u_len++] =
@@ -255,35 +250,32 @@ error_out:
 }
 
 static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
-                       struct ustr *ocu_i)
+                       const struct ustr *ocu_i)
 {
-       uint8_t *ocu;
-       uint32_t c;
+       const uint8_t *ocu;
        uint8_t cmp_id, ocu_len;
        int i;
 
-       ocu = ocu_i->u_name;
 
        ocu_len = ocu_i->u_len;
-       cmp_id = ocu_i->u_cmpID;
-       utf_o->u_len = 0;
-
        if (ocu_len == 0) {
                memset(utf_o, 0, sizeof(struct ustr));
-               utf_o->u_cmpID = 0;
-               utf_o->u_len = 0;
                return 0;
        }
 
-       if ((cmp_id != 8) && (cmp_id != 16)) {
+       cmp_id = ocu_i->u_cmpID;
+       if (cmp_id != 8 && cmp_id != 16) {
+               memset(utf_o, 0, sizeof(struct ustr));
                printk(KERN_ERR "udf: unknown compression code (%d) stri=%s\n",
                       cmp_id, ocu_i->u_name);
                return 0;
        }
 
+       ocu = ocu_i->u_name;
+       utf_o->u_len = 0;
        for (i = 0; (i < ocu_len) && (utf_o->u_len <= (UDF_NAME_LEN - 3));) {
                /* Expand OSTA compressed Unicode to Unicode */
-               c = ocu[i++];
+               uint32_t c = ocu[i++];
                if (cmp_id == 16)
                        c = (c << 8) | ocu[i++];
 
@@ -463,7 +455,7 @@ static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName,
                } else if (newIndex > 250)
                        newIndex = 250;
                newName[newIndex++] = CRC_MARK;
-               valueCRC = udf_crc(fidName, fidNameLen, 0);
+               valueCRC = crc_itu_t(0, fidName, fidNameLen);
                newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12];
                newName[newIndex++] = hexChar[(valueCRC & 0x0f00) >> 8];
                newName[newIndex++] = hexChar[(valueCRC & 0x00f0) >> 4];
index 5d741720332a48d6e8ee6606d23ede87ca06a342..97a88b2b0c8e08bd578c1c85cfb0b4f26078e0c8 100644 (file)
@@ -150,6 +150,7 @@ header-y += tiocl.h
 header-y += tipc.h
 header-y += tipc_config.h
 header-y += toshiba.h
+header-y += udf_fs_i.h
 header-y += ultrasound.h
 header-y += un.h
 header-y += utime.h
@@ -336,7 +337,6 @@ unifdef-y += time.h
 unifdef-y += timex.h
 unifdef-y += tty.h
 unifdef-y += types.h
-unifdef-y += udf_fs_i.h
 unifdef-y += udp.h
 unifdef-y += uinput.h
 unifdef-y += uio.h
diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h
deleted file mode 100644 (file)
index aa88654..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * udf_fs.h
- *
- * PURPOSE
- *  Included by fs/filesystems.c
- *
- * DESCRIPTION
- *  OSTA-UDF(tm) = Optical Storage Technology Association
- *  Universal Disk Format.
- *
- *  This code is based on version 2.50 of the UDF specification,
- *  and revision 3 of the ECMA 167 standard [equivalent to ISO 13346].
- *    http://www.osta.org/ *    http://www.ecma.ch/
- *    http://www.iso.org/
- *
- * COPYRIGHT
- *     This file is distributed under the terms of the GNU General Public
- *     License (GPL). Copies of the GPL can be obtained from:
- *             ftp://prep.ai.mit.edu/pub/gnu/GPL
- *     Each contributing author retains all rights to their own work.
- *
- *  (C) 1999-2004 Ben Fennema
- *  (C) 1999-2000 Stelias Computing Inc
- *
- * HISTORY
- *
- */
-
-#ifndef _UDF_FS_H
-#define _UDF_FS_H 1
-
-#define UDF_PREALLOCATE
-#define UDF_DEFAULT_PREALLOC_BLOCKS    8
-
-#undef UDFFS_DEBUG
-
-#ifdef UDFFS_DEBUG
-#define udf_debug(f, a...) \
-       do { \
-               printk (KERN_DEBUG "UDF-fs DEBUG %s:%d:%s: ", \
-                       __FILE__, __LINE__, __FUNCTION__); \
-               printk (f, ##a); \
-       } while (0)
-#else
-#define udf_debug(f, a...) /**/
-#endif
-
-#define udf_info(f, a...) \
-               printk (KERN_INFO "UDF-fs INFO " f, ##a);
-
-#endif /* _UDF_FS_H */
index ffaf05679ffb2dad2e5d4ee58fc899bf35612e3d..3536965913b09262f3bb202088f4ade104fd3417 100644 (file)
@@ -9,41 +9,10 @@
  *             ftp://prep.ai.mit.edu/pub/gnu/GPL
  *     Each contributing author retains all rights to their own work.
  */
-
 #ifndef _UDF_FS_I_H
 #define _UDF_FS_I_H 1
 
-#ifdef __KERNEL__
-
-struct udf_inode_info
-{
-       struct timespec         i_crtime;
-       /* Physical address of inode */
-       kernel_lb_addr          i_location;
-       __u64                   i_unique;
-       __u32                   i_lenEAttr;
-       __u32                   i_lenAlloc;
-       __u64                   i_lenExtents;
-       __u32                   i_next_alloc_block;
-       __u32                   i_next_alloc_goal;
-       unsigned                i_alloc_type : 3;
-       unsigned                i_efe : 1;
-       unsigned                i_use : 1;
-       unsigned                i_strat4096 : 1;
-       unsigned                reserved : 26;
-       union
-       {
-               short_ad        *i_sad;
-               long_ad         *i_lad;
-               __u8            *i_data;
-       } i_ext;
-       struct inode vfs_inode;
-};
-
-#endif
-
 /* exported IOCTLs, we have 'l', 0x40-0x7f */
-
 #define UDF_GETEASIZE   _IOR('l', 0x40, int)
 #define UDF_GETEABLOCK  _IOR('l', 0x41, void *)
 #define UDF_GETVOLIDENT _IOR('l', 0x42, void *)
diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h
deleted file mode 100644 (file)
index 9bc4735..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * udf_fs_sb.h
- * 
- * This include file is for the Linux kernel/module.
- *
- * COPYRIGHT
- *     This file is distributed under the terms of the GNU General Public
- *     License (GPL). Copies of the GPL can be obtained from:
- *             ftp://prep.ai.mit.edu/pub/gnu/GPL
- *     Each contributing author retains all rights to their own work.
- */
-
-#ifndef _UDF_FS_SB_H
-#define _UDF_FS_SB_H 1
-
-#include <linux/mutex.h>
-
-#pragma pack(1)
-
-#define UDF_MAX_BLOCK_LOADED   8
-
-#define UDF_TYPE1_MAP15                        0x1511U
-#define UDF_VIRTUAL_MAP15              0x1512U
-#define UDF_VIRTUAL_MAP20              0x2012U
-#define UDF_SPARABLE_MAP15             0x1522U
-
-struct udf_sparing_data
-{
-       __u16   s_packet_len;
-       struct buffer_head *s_spar_map[4];
-};
-
-struct udf_virtual_data
-{
-       __u32   s_num_entries;
-       __u16   s_start_offset;
-};
-
-struct udf_bitmap
-{
-       __u32                   s_extLength;
-       __u32                   s_extPosition;
-       __u16                   s_nr_groups;
-       struct buffer_head      **s_block_bitmap;
-};
-
-struct udf_part_map
-{
-       union
-       {
-               struct udf_bitmap       *s_bitmap;
-               struct inode            *s_table;
-       } s_uspace;
-       union
-       {
-               struct udf_bitmap       *s_bitmap;
-               struct inode            *s_table;
-       } s_fspace;
-       __u32   s_partition_root;
-       __u32   s_partition_len;
-       __u16   s_partition_type;
-       __u16   s_partition_num;
-       union
-       {
-               struct udf_sparing_data s_sparing;
-               struct udf_virtual_data s_virtual;
-       } s_type_specific;
-       __u32   (*s_partition_func)(struct super_block *, __u32, __u16, __u32);
-       __u16   s_volumeseqnum;
-       __u16   s_partition_flags;
-};
-
-#pragma pack()
-
-struct udf_sb_info
-{
-       struct udf_part_map     *s_partmaps;
-       __u8                    s_volume_ident[32];
-
-       /* Overall info */
-       __u16                   s_partitions;
-       __u16                   s_partition;
-
-       /* Sector headers */
-       __s32                   s_session;
-       __u32                   s_anchor[4];
-       __u32                   s_last_block;
-
-       struct buffer_head      *s_lvid_bh;
-
-       /* Default permissions */
-       mode_t                  s_umask;
-       gid_t                   s_gid;
-       uid_t                   s_uid;
-
-       /* Root Info */
-       struct timespec         s_record_time;
-
-       /* Fileset Info */
-       __u16                   s_serial_number;
-
-       /* highest UDF revision we have recorded to this media */
-       __u16                   s_udfrev;
-
-       /* Miscellaneous flags */
-       __u32                   s_flags;
-
-       /* Encoding info */
-       struct nls_table        *s_nls_map;
-
-       /* VAT inode */
-       struct inode            *s_vat_inode;
-
-       struct mutex            s_alloc_mutex;
-};
-
-#endif /* _UDF_FS_SB_H */