]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] UDF sync with CVS
authorBen Fennema <bfennema@falcon.csc.calpoly.edu>
Sun, 17 Nov 2002 03:35:24 +0000 (19:35 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sun, 17 Nov 2002 03:35:24 +0000 (19:35 -0800)
This patch updates udf to the CVS version:
  - removes UDF_RW
  - fixes a extraneous read after write which killed CDRW performance
  - fixes setting the session
  - fix a array index bug in udf_prealloc_extents
  - fix symlinks to correspond to the UDF spec

19 files changed:
fs/Kconfig
fs/udf/balloc.c
fs/udf/dir.c
fs/udf/directory.c
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/osta_udf.h
fs/udf/super.c
fs/udf/symlink.c
fs/udf/truncate.c
fs/udf/udf_i.h
fs/udf/udfdecl.h
fs/udf/unicode.c
include/linux/udf_fs.h
include/linux/udf_fs_i.h

index 8d68c53cb20c2bc94d73c76955b016101dc4572c..53e8624b63886fd2b1160714b8c505b35459a5d8 100644 (file)
@@ -1037,15 +1037,12 @@ config SYSV_FS
          If you haven't heard about all of this before, it's safe to say N.
 
 config UDF_FS
-       tristate "UDF file system support (read only)"
+       tristate "UDF file system support"
        ---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
-         if written to by other UDF utilities, such as DirectCD. This UDF
-         file system support is read-only. If you want to write to UDF
-         file systems on some media, you need to say Y to "UDF read-write
-         support" below in addition. Please read
-         <file:Documentation/filesystems/udf.txt>.
+         if written to by other UDF utilities, such as DirectCD.
+         Please read <file:Documentation/filesystems/udf.txt>.
 
          This file system support is also available as a module ( = code
          which can be inserted in and removed from the running kernel
@@ -1055,14 +1052,6 @@ config UDF_FS
 
          If unsure, say N.
 
-config UDF_RW
-       bool "UDF write support (DANGEROUS)"
-       depends on UDF_FS && EXPERIMENTAL
-       help
-         Say Y if you want to test write support for UDF file systems.
-         Due to lack of support for writing to CDR/CDRW's, this option
-         is only supported for hard discs, DVD-RAM, and loopback files.
-
 config UFS_FS
        tristate "UFS file system support (read only)"
        ---help---
index 165447eec88aff05631530fe41d3d649f896e4e4..8f7d9eff554b0a00ad516ec55db2dc0cfd6b6f92 100644 (file)
@@ -461,8 +461,7 @@ static void udf_table_free_blocks(struct super_block * sb,
        elen = 0;
        obloc = nbloc = UDF_I_LOCATION(table);
 
-       obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0));
-       atomic_inc(&nbh->b_count);
+       obh = nbh = NULL;
 
        while (count && (etype =
                udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
@@ -506,7 +505,7 @@ static void udf_table_free_blocks(struct super_block * sb,
                        udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
                }
 
-               if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+               if (nbh != obh)
                {
                        i = -1;
                        obloc = nbloc;
@@ -580,7 +579,10 @@ static void udf_table_free_blocks(struct super_block * sb,
                        {
                                loffset = nextoffset;
                                aed->lengthAllocDescs = cpu_to_le32(adsize);
-                               sptr = (obh)->b_data + nextoffset - adsize;
+                               if (obh)
+                                       sptr = UDF_I_DATA(inode) + nextoffset -  udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
+                               else
+                                       sptr = obh->b_data + nextoffset - adsize;
                                dptr = nbh->b_data + sizeof(struct allocExtDesc);
                                memcpy(dptr, sptr, adsize);
                                nextoffset = sizeof(struct allocExtDesc) + adsize;
@@ -591,8 +593,8 @@ static void udf_table_free_blocks(struct super_block * sb,
                                aed->lengthAllocDescs = cpu_to_le32(0);
                                sptr = (obh)->b_data + nextoffset;
                                nextoffset = sizeof(struct allocExtDesc);
-       
-                               if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
+
+                               if (obh)
                                {
                                        aed = (struct allocExtDesc *)(obh)->b_data;
                                        aed->lengthAllocDescs =
@@ -631,15 +633,20 @@ static void udf_table_free_blocks(struct super_block * sb,
                                        break;
                                }
                        }
-                       udf_update_tag(obh->b_data, loffset);
-                       mark_buffer_dirty(obh);
+                       if (obh)
+                       {
+                               udf_update_tag(obh->b_data, loffset);
+                               mark_buffer_dirty(obh);
+                       }
+                       else
+                               mark_inode_dirty(table);
                }
 
                if (elen) /* It's possible that stealing the block emptied the extent */
                {
                        udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
 
-                       if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
+                       if (!nbh)
                        {
                                UDF_I_LENALLOC(table) += adsize;
                                mark_inode_dirty(table);
@@ -690,7 +697,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
        extoffset = sizeof(struct unallocSpaceEntry);
        bloc = UDF_I_LOCATION(table);
 
-       bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
+       bh = NULL;
        eloc.logicalBlockNum = 0xFFFFFFFF;
 
        while (first_block != eloc.logicalBlockNum && (etype =
@@ -768,8 +775,7 @@ static int udf_table_new_block(struct super_block * sb,
        extoffset = sizeof(struct unallocSpaceEntry);
        bloc = UDF_I_LOCATION(table);
 
-       goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
-       atomic_inc(&goal_bh->b_count);
+       goal_bh = bh = NULL;
 
        while (spread && (etype =
                udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
index fe9ea5cea90c7fa595b739bea6c5e83cd8da89c3..78d6bc0acfefc853ce197dc61ecdd57237905179 100644 (file)
@@ -89,13 +89,14 @@ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        if ( filp->f_pos == 0 ) 
        {
-               if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
+               if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
+               {
                        unlock_kernel();
                        return 0;
                }
                filp->f_pos ++;
        }
+
        result = do_udf_readdir(dir, filp, filldir, dirent);
        UPDATE_ATIME(dir);
        unlock_kernel();
@@ -129,7 +130,9 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
                nf_pos = (udf_ext0_offset(dir) >> 2);
 
        fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-       if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
+       if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+               fibh.sbh = fibh.ebh = NULL;
+       else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
                &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                offset >>= dir->i_sb->s_blocksize_bits;
@@ -143,40 +146,40 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
                }
                else
                        offset = 0;
-       }
-       else
-       {
-               udf_release_data(bh);
-               return -ENOENT;
-       }
-
-       if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
-       {
-               udf_release_data(bh);
-               return -EIO;
-       }
 
-       if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
-       {
-               i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
-               if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
-                       i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
-               for (num=0; i>0; i--)
+               if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
                {
-                       block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
-                       tmp = udf_tgetblk(dir->i_sb, block);
-                       if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
-                               bha[num++] = tmp;
-                       else
-                               brelse(tmp);
+                       udf_release_data(bh);
+                       return -EIO;
                }
-               if (num)
+       
+               if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
                {
-                       ll_rw_block(READA, num, bha);
-                       for (i=0; i<num; i++)
-                               brelse(bha[i]);
+                       i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
+                       if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
+                               i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
+                       for (num=0; i>0; i--)
+                       {
+                               block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
+                               tmp = udf_tgetblk(dir->i_sb, block);
+                               if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
+                                       bha[num++] = tmp;
+                               else
+                                       brelse(tmp);
+                       }
+                       if (num)
+                       {
+                               ll_rw_block(READA, num, bha);
+                               for (i=0; i<num; i++)
+                                       brelse(bha[i]);
+                       }
                }
        }
+       else
+       {
+               udf_release_data(bh);
+               return -ENOENT;
+       }
 
        while ( nf_pos < size )
        {
index 45e810484221a1b72a466300be309c59f01fe4be..00384653ec64f17abea5ad47371b681276f3ba97 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "udfdecl.h"
+#include "udf_i.h"
 
 #include <linux/fs.h>
 #include <linux/string.h>
@@ -85,6 +86,24 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 
        fibh->soffset = fibh->eoffset;
 
+       if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+       {
+               fi = udf_get_fileident(UDF_I_DATA(dir) -
+                       (UDF_I_EFE(dir) ?
+                               sizeof(struct extendedFileEntry) :
+                               sizeof(struct fileEntry)),
+                       dir->i_sb->s_blocksize, &(fibh->eoffset));
+
+               if (!fi)
+                       return NULL;
+
+               *nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
+
+               memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
+
+               return fi;
+       }
+
        if (fibh->eoffset == dir->i_sb->s_blocksize)
        {
                int lextoffset = *extoffset;
@@ -276,53 +295,43 @@ udf_get_fileextent(void * buffer, int bufsize, int * offset)
 }
 
 short_ad *
-udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
+udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
 {
-       short_ad * sa;
-       uint8_t * ptr;
+       short_ad *sa;
 
-       if ( (!buffer) || (!offset) )
+       if ( (!ptr) || (!offset) )
        {
                printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
                return NULL;
        }
 
-       ptr = (uint8_t *)buffer;
-
-       if ( (*offset > 0) && (*offset < maxoffset) )
-               ptr += *offset;
-       else
+       if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
                return NULL;
-
-       if ((sa = (short_ad *)ptr)->extLength == 0)
+       else if ((sa = (short_ad *)ptr)->extLength == 0)
                return NULL;
-       else if (inc)
-               (*offset) += sizeof(short_ad);
+
+       if (inc)
+               *offset += sizeof(short_ad);
        return sa;
 }
 
 long_ad *
-udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
+udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc)
 {
-       long_ad * la;
-       uint8_t * ptr;
+       long_ad *la;
 
-       if ( (!buffer) || !(offset) ) 
+       if ( (!ptr) || (!offset) ) 
        {
                printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
                return NULL;
        }
 
-       ptr = (uint8_t *)buffer;
-
-       if ( (*offset > 0) && (*offset < maxoffset) )
-               ptr += *offset;
-       else
+       if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
                return NULL;
-
-       if ((la = (long_ad *)ptr)->extLength == 0)
+       else if ((la = (long_ad *)ptr)->extLength == 0)
                return NULL;
-       else if (inc)
-               (*offset) += sizeof(long_ad);
+
+       if (inc)
+               *offset += sizeof(long_ad);
        return la;
 }
index fd79831053101bacd823cc01209be6795d56c932..5016ee1dc7e5318e206cf9078cf768f9a370dfb6 100644 (file)
 static int udf_adinicb_readpage(struct file *file, struct page * page)
 {
        struct inode *inode = page->mapping->host;
-
-       struct buffer_head *bh;
-       int block;
        char *kaddr;
-       int err = 0;
 
        if (!PageLocked(page))
                PAGE_BUG(page);
 
        kaddr = kmap(page);
        memset(kaddr, 0, PAGE_CACHE_SIZE);
-       block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-       bh = sb_bread(inode->i_sb, block);
-       if (!bh)
-       {
-               SetPageError(page);
-               err = -EIO;
-               goto out;
-       }
-       memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
-       brelse(bh);
+       memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
        flush_dcache_page(page);
        SetPageUptodate(page);
-out:
        kunmap(page);
        unlock_page(page);
-       return err;
+       return 0;
 }
 
 static int udf_adinicb_writepage(struct page *page)
 {
        struct inode *inode = page->mapping->host;
-
-       struct buffer_head *bh;
-       int block;
        char *kaddr;
-       int err = 0;
 
        if (!PageLocked(page))
                PAGE_BUG(page);
 
        kaddr = kmap(page);
-       block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-       bh = sb_bread(inode->i_sb, block);
-       if (!bh)
-       {
-               SetPageError(page);
-               err = -EIO;
-               goto out;
-       }
-       memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
-       mark_buffer_dirty(bh);
-       brelse(bh);
+       memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
+       mark_inode_dirty(inode);
        SetPageUptodate(page);
-out:
        kunmap(page);
        unlock_page(page);
-       return err;
+       return 0;
 }
 
 static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
@@ -116,31 +88,17 @@ static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsig
 static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
        struct inode *inode = page->mapping->host;
-
-       struct buffer_head *bh;
-       int block;
        char *kaddr = page_address(page);
-       int err = 0;
 
-       block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-       bh = sb_bread(inode->i_sb, block);
-       if (!bh)
-       {
-               SetPageError(page);
-               err = -EIO;
-               goto out;
-       }
-       memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
+       memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
                kaddr + offset, to - offset);
-       mark_buffer_dirty(bh);
-       brelse(bh);
+       mark_inode_dirty(inode);
        SetPageUptodate(page);
-out:
        kunmap(page);
        /* only one page here */
        if (to > inode->i_size)
                inode->i_size = to;
-       return err;
+       return 0;
 }
 
 struct address_space_operations udf_adinicb_aops = {
@@ -232,9 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        unsigned long arg)
 {
        int result = -EINVAL;
-       struct buffer_head *bh = NULL;
-       long_ad eaicb;
-       uint8_t *ea = NULL;
 
        if ( permission(inode, MAY_READ) != 0 )
        {
@@ -249,7 +204,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                return -EINVAL;
        }
 
-       /* first, do ioctls that don't need to udf_read */
        switch (cmd)
        {
                case UDF_GETVOLIDENT:
@@ -267,50 +221,16 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 
                        return result;
                }
-       }
-
-       /* ok, we need to read the inode */
-       bh = udf_tread(inode->i_sb,
-               udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
-
-       if (!bh)
-       {
-               udf_debug("bread failed (inode=%ld)\n", inode->i_ino);
-               return -EIO;
-       }
-
-       if (UDF_I_EXTENDED_FE(inode) == 0)
-       {
-               struct fileEntry *fe;
-
-               fe = (struct fileEntry *)bh->b_data;
-               eaicb = lela_to_cpu(fe->extendedAttrICB);
-               if (UDF_I_LENEATTR(inode))
-                       ea = fe->extendedAttr;
-       }
-       else
-       {
-               struct extendedFileEntry *efe;
-
-               efe = (struct extendedFileEntry *)bh->b_data;
-               eaicb = lela_to_cpu(efe->extendedAttrICB);
-               if (UDF_I_LENEATTR(inode))
-                       ea = efe->extendedAttr;
-       }
-
-       switch (cmd) 
-       {
                case UDF_GETEASIZE:
                        result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
                        break;
 
                case UDF_GETEABLOCK:
-                       result = copy_to_user((char *)arg, ea,
+                       result = copy_to_user((char *)arg, UDF_I_DATA(inode),
                                UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
                        break;
        }
 
-       udf_release_data(bh);
        return result;
 }
 
index 12c0e02a189233e8d429c18479647c76057d494a..2eb7bea066a35a72d2e5397e3228be57ed3ac8c4 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/quotaops.h>
 #include <linux/udf_fs.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -135,13 +136,20 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
        inode->i_blocks = 0;
        UDF_I_LENEATTR(inode) = 0;
        UDF_I_LENALLOC(inode) = 0;
+       UDF_I_USE(inode) = 0;
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
        {
-               UDF_I_EXTENDED_FE(inode) = 1;
+               UDF_I_EFE(inode) = 1;
                UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
+               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+               memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
        }
        else
-               UDF_I_EXTENDED_FE(inode) = 0;
+       {
+               UDF_I_EFE(inode) = 0;
+               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+               memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+       }
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
                UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
        else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
@@ -152,7 +160,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
                UDF_I_CRTIME(inode) = CURRENT_TIME;
        UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
                UDF_I_UCRTIME(inode) = CURRENT_UTIME;
-       UDF_I_NEW_INODE(inode) = 1;
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
 
index 9f1df0e61896d003422b33a34c683c290b286366..e43476a79d1eeed9ea3b6b94708f30eedc43ed99 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
+#include <linux/slab.h>
 
 #include "udf_i.h"
 #include "udf_sb.h"
@@ -122,6 +123,11 @@ no_delete:
        clear_inode(inode);
 }
 
+void udf_clear_inode(struct inode *inode)
+{
+       kfree(UDF_I_DATA(inode));
+}
+
 void udf_discard_prealloc(struct inode * inode)
 {
        if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
@@ -162,10 +168,8 @@ struct address_space_operations udf_aops = {
 
 void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
 {
-       struct buffer_head *bh = NULL;
        struct page *page;
        char *kaddr;
-       int block;
 
        /* from now on we have normal address_space methods */
        inode->i_data.a_ops = &udf_aops;
@@ -180,10 +184,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
                return;
        }
 
-       block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-       bh = udf_tread(inode->i_sb, block);
-       if (!bh)
-               return;
        page = grab_cache_page(inode->i_mapping, 0);
        if (!PageLocked(page))
                PAGE_BUG(page);
@@ -192,21 +192,19 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
                kaddr = kmap(page);
                memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
                        PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
-               memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
+               memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
                        UDF_I_LENALLOC(inode));
                flush_dcache_page(page);
                SetPageUptodate(page);
                kunmap(page);
        }
-       memset(bh->b_data + udf_file_entry_alloc_offset(inode),
-               0, UDF_I_LENALLOC(inode));
+       memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
+               UDF_I_LENALLOC(inode));
        UDF_I_LENALLOC(inode) = 0;
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
                UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
        else
                UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
-       mark_buffer_dirty_inode(bh, inode);
-       udf_release_data(bh);
 
        if (inode->i_data.a_ops->writepage(page) == -EAGAIN)
                __set_page_dirty_nobuffers(page);
@@ -221,18 +219,21 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
        struct buffer_head *sbh = NULL, *dbh = NULL;
        lb_addr bloc, eloc;
        uint32_t elen, extoffset;
+       uint8_t alloctype;
 
        struct udf_fileident_bh sfibh, dfibh;
        loff_t f_pos = udf_ext0_offset(inode) >> 2;
        int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
        struct fileIdentDesc cfi, *sfi, *dfi;
 
+       if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+               alloctype = ICBTAG_FLAG_AD_SHORT;
+       else
+               alloctype = ICBTAG_FLAG_AD_LONG;
+
        if (!inode->i_size)
        {
-               if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
-                       UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
-               else
-                       UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
+               UDF_I_ALLOCTYPE(inode) = alloctype;
                mark_inode_dirty(inode);
                return NULL;
        }
@@ -248,9 +249,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
                UDF_I_LOCATION(inode).partitionReferenceNum, 0);
        if (!newblock)
                return NULL;
-       sbh = udf_tread(inode->i_sb, inode->i_ino);
-       if (!sbh)
-               return NULL;
        dbh = udf_tgetblk(inode->i_sb, newblock);
        if (!dbh)
                return NULL;
@@ -261,18 +259,19 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
        mark_buffer_dirty_inode(dbh, inode);
 
        sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
-       sfibh.sbh = sfibh.ebh = sbh;
+       sbh = sfibh.sbh = sfibh.ebh = NULL;
        dfibh.soffset = dfibh.eoffset = 0;
        dfibh.sbh = dfibh.ebh = dbh;
        while ( (f_pos < size) )
        {
+               UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
                sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
                if (!sfi)
                {
-                       udf_release_data(sbh);
                        udf_release_data(dbh);
                        return NULL;
                }
+               UDF_I_ALLOCTYPE(inode) = alloctype;
                sfi->descTag.tagLocation = *block;
                dfibh.soffset = dfibh.eoffset;
                dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
@@ -280,21 +279,15 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
                if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
                        sfi->fileIdent + sfi->lengthOfImpUse))
                {
-                       udf_release_data(sbh);
+                       UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
                        udf_release_data(dbh);
                        return NULL;
                }
        }
        mark_buffer_dirty_inode(dbh, inode);
 
-       memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
-               0, UDF_I_LENALLOC(inode));
-
+       memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
        UDF_I_LENALLOC(inode) = 0;
-       if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
-               UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
-       else
-               UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
        bloc = UDF_I_LOCATION(inode);
        eloc.logicalBlockNum = *block;
        eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
@@ -304,7 +297,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
        udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
        /* UniqueID stuff */
 
-       mark_buffer_dirty(sbh);
        udf_release_data(sbh);
        mark_inode_dirty(inode);
        return dbh;
@@ -725,7 +717,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
 
                                if (elen > numalloc)
                                {
-                                       laarr[c].extLength -=
+                                       laarr[i].extLength -=
                                                (numalloc << inode->i_sb->s_blocksize_bits);
                                        numalloc = 0;
                                }
@@ -847,7 +839,6 @@ struct buffer_head * udf_bread(struct inode * inode, int block,
 void udf_truncate(struct inode * inode)
 {
        int offset;
-       struct buffer_head *bh;
        int err;
 
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
@@ -874,16 +865,8 @@ void udf_truncate(struct inode * inode)
                }
                else
                {
-                       offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
-                               udf_file_entry_alloc_offset(inode);
-
-                       if ((bh = udf_tread(inode->i_sb,
-                               udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0))))
-                       {
-                               memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
-                               mark_buffer_dirty(bh);
-                               udf_release_data(bh);
-                       }
+                       offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
+                       memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - udf_file_entry_alloc_offset(inode));
                        UDF_I_LENALLOC(inode) = inode->i_size;
                }
        }
@@ -1031,8 +1014,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        long convtime_usec;
        int offset, alen;
 
-       UDF_I_NEW_INODE(inode) = 0;
-
        fe = (struct fileEntry *)bh->b_data;
        efe = (struct extendedFileEntry *)bh->b_data;
 
@@ -1053,14 +1034,28 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
        UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
        if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE)
-               UDF_I_EXTENDED_FE(inode) = 1;
+       {
+               UDF_I_EFE(inode) = 1;
+               UDF_I_USE(inode) = 0;
+               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
+               memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
+       }
        else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
-               UDF_I_EXTENDED_FE(inode) = 0;
+       {
+               UDF_I_EFE(inode) = 0;
+               UDF_I_USE(inode) = 0;
+               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
+               memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+       }
        else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
        {
+               UDF_I_EFE(inode) = 0;
+               UDF_I_USE(inode) = 1;
                UDF_I_LENALLOC(inode) =
                        le32_to_cpu(
                                ((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
+               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
+               memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
                return;
        }
 
@@ -1080,7 +1075,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        inode->i_mode = udf_convert_permissions(fe);
        inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
 
-       if (UDF_I_EXTENDED_FE(inode) == 0)
+       if (UDF_I_EFE(inode) == 0)
        {
                inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
                        (inode->i_sb->s_blocksize_bits - 9);
@@ -1326,19 +1321,11 @@ udf_update_inode(struct inode *inode, int do_sync)
                udf_debug("bread failure\n");
                return -EIO;
        }
+
+       memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
+
        fe = (struct fileEntry *)bh->b_data;
        efe = (struct extendedFileEntry *)bh->b_data;
-       if (UDF_I_NEW_INODE(inode) == 1)
-       {
-               if (UDF_I_EXTENDED_FE(inode) == 0)
-                       memset(bh->b_data, 0x00, sizeof(struct fileEntry));
-               else
-                       memset(bh->b_data, 0x00, sizeof(struct extendedFileEntry));
-               memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
-                       UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
-                       udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
-               UDF_I_NEW_INODE(inode) = 0;
-       }
 
        if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
        {
@@ -1346,6 +1333,7 @@ udf_update_inode(struct inode *inode, int do_sync)
                        (struct unallocSpaceEntry *)bh->b_data;
 
                use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
+               memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
                crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
                        sizeof(tag);
                use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
@@ -1416,8 +1404,9 @@ udf_update_inode(struct inode *inode, int do_sync)
                udf_release_data(tbh);
        }
 
-       if (UDF_I_EXTENDED_FE(inode) == 0)
+       if (UDF_I_EFE(inode) == 0)
        {
+               memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
                fe->logicalBlocksRecorded = cpu_to_le64(
                        (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
                        (inode->i_sb->s_blocksize_bits - 9));
@@ -1440,6 +1429,7 @@ udf_update_inode(struct inode *inode, int do_sync)
        }
        else
        {
+               memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
                efe->objectSize = cpu_to_le64(inode->i_size);
                efe->logicalBlocksRecorded = cpu_to_le64(
                        (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
@@ -1620,17 +1610,12 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
        long_ad *lad = NULL;
        struct allocExtDesc *aed;
        int8_t etype;
+       uint8_t *ptr;
 
-       if (!(*bh))
-       {
-               if (!(*bh = udf_tread(inode->i_sb,
-                       udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
-               {
-                       udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, *bloc, 0));
-                       return -1;
-               }
-       }
+       if (!*bh)
+               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+       else
+               ptr = (*bh)->b_data + *extoffset;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
                adsize = sizeof(short_ad);
@@ -1669,7 +1654,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                {
                        loffset = *extoffset;
                        aed->lengthAllocDescs = cpu_to_le32(adsize);
-                       sptr = (*bh)->b_data + *extoffset - adsize;
+                       sptr = ptr - adsize;
                        dptr = nbh->b_data + sizeof(struct allocExtDesc);
                        memcpy(dptr, sptr, adsize);
                        *extoffset = sizeof(struct allocExtDesc) + adsize;
@@ -1678,10 +1663,10 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                {
                        loffset = *extoffset + adsize;
                        aed->lengthAllocDescs = cpu_to_le32(0);
-                       sptr = (*bh)->b_data + *extoffset;
+                       sptr = ptr;
                        *extoffset = sizeof(struct allocExtDesc);
 
-                       if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+                       if (*bh)
                        {
                                aed = (struct allocExtDesc *)(*bh)->b_data;
                                aed->lengthAllocDescs =
@@ -1721,18 +1706,23 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                                break;
                        }
                }
-               if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                       udf_update_tag((*bh)->b_data, loffset);
+               if (*bh)
+               {
+                       if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
+                               udf_update_tag((*bh)->b_data, loffset);
+                       else
+                               udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(*bh, inode);
+                       udf_release_data(*bh);
+               }
                else
-                       udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-               mark_buffer_dirty_inode(*bh, inode);
-               udf_release_data(*bh);
+                       mark_inode_dirty(inode);
                *bh = nbh;
        }
 
        etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
 
-       if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
+       if (!*bh)
        {
                UDF_I_LENALLOC(inode) += adsize;
                mark_inode_dirty(inode);
@@ -1756,49 +1746,40 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
     lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
 {
        int adsize;
-       short_ad *sad = NULL;
-       long_ad *lad = NULL;
+       uint8_t *ptr;
 
-       if (!(bh))
-       {
-               if (!(bh = udf_tread(inode->i_sb,
-                       udf_get_lb_pblock(inode->i_sb, bloc, 0))))
-               {
-                       udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, bloc, 0));
-                       return -1;
-               }
-       }
+       if (!bh)
+               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
        else
+       {
+               ptr = bh->b_data + *extoffset;
                atomic_inc(&bh->b_count);
-
-       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
-               adsize = sizeof(short_ad);
-       else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
-               adsize = sizeof(long_ad);
-       else
-               return -1;
+       }
 
        switch (UDF_I_ALLOCTYPE(inode))
        {
                case ICBTAG_FLAG_AD_SHORT:
                {
-                       sad = (short_ad *)((bh)->b_data + *extoffset);
+                       short_ad *sad = (short_ad *)ptr;
                        sad->extLength = cpu_to_le32(elen);
                        sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
+                       adsize = sizeof(short_ad);
                        break;
                }
                case ICBTAG_FLAG_AD_LONG:
                {
-                       lad = (long_ad *)((bh)->b_data + *extoffset);
+                       long_ad *lad = (long_ad *)ptr;
                        lad->extLength = cpu_to_le32(elen);
                        lad->extLocation = cpu_to_lelb(eloc);
                        memset(lad->impUse, 0x00, sizeof(lad->impUse));
+                       adsize = sizeof(long_ad);
                        break;
                }
+               default:
+                       return -1;
        }
 
-       if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+       if (bh)
        {
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
                {
@@ -1807,30 +1788,28 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
                                le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
                }
                mark_buffer_dirty_inode(bh, inode);
+               udf_release_data(bh);
        }
        else
-       {
                mark_inode_dirty(inode);
-               mark_buffer_dirty(bh);
-       }
 
        if (inc)
                *extoffset += adsize;
-       udf_release_data(bh);
        return (elen >> 30);
 }
 
 int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
        lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
-       uint16_t tagIdent;
-       int pos, alen;
        int8_t etype;
 
-       if (!(*bh))
+       while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
+               (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
        {
-               if (!(*bh = udf_tread(inode->i_sb,
-                       udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
+               *bloc = *eloc;
+               *extoffset = sizeof(struct allocExtDesc);
+               udf_release_data(*bh);
+               if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
                {
                        udf_debug("reading block %d failed!\n",
                                udf_get_lb_pblock(inode->i_sb, *bloc, 0));
@@ -1838,154 +1817,38 @@ int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                }
        }
 
-       tagIdent = le16_to_cpu(((tag *)(*bh)->b_data)->tagIdent);
-
-       if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
-       {
-               if (tagIdent == TAG_IDENT_FE || tagIdent == TAG_IDENT_EFE ||
-                       UDF_I_NEW_INODE(inode))
-               {
-                       pos = udf_file_entry_alloc_offset(inode);
-                       alen = UDF_I_LENALLOC(inode) + pos;
-               }
-               else if (tagIdent == TAG_IDENT_USE)
-               {
-                       pos = sizeof(struct unallocSpaceEntry);
-                       alen = UDF_I_LENALLOC(inode) + pos;
-               }
-               else
-                       return -1;
-       }
-       else if (tagIdent == TAG_IDENT_AED)
-       {
-               struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
-
-               pos = sizeof(struct allocExtDesc);
-               alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
-       }
-       else
-               return -1;
-
-       if (!(*extoffset))
-               *extoffset = pos;
-
-       switch (UDF_I_ALLOCTYPE(inode))
-       {
-               case ICBTAG_FLAG_AD_SHORT:
-               {
-                       short_ad *sad;
-
-                       if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
-                               return -1;
-
-                       if ((etype = le32_to_cpu(sad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
-                       {
-                               bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
-                               *extoffset = 0;
-                               udf_release_data(*bh);
-                               *bh = NULL;
-                               return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
-                       }
-                       else
-                       {
-                               eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
-                               eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
-                               *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
-                       }
-                       break;
-               }
-               case ICBTAG_FLAG_AD_LONG:
-               {
-                       long_ad *lad;
-
-                       if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
-                               return -1;
-
-                       if ((etype = le32_to_cpu(lad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
-                       {
-                               *bloc = lelb_to_cpu(lad->extLocation);
-                               *extoffset = 0;
-                               udf_release_data(*bh);
-                               *bh = NULL;
-                               return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
-                       }
-                       else
-                       {
-                               *eloc = lelb_to_cpu(lad->extLocation);
-                               *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
-                       }
-                       break;
-               }
-               case ICBTAG_FLAG_AD_IN_ICB:
-               {
-                       if (UDF_I_LENALLOC(inode) == 0)
-                               return -1;
-                       etype = (EXT_RECORDED_ALLOCATED >> 30);
-                       *eloc = UDF_I_LOCATION(inode);
-                       *elen = UDF_I_LENALLOC(inode);
-                       break;
-               }
-               default:
-               {
-                       udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
-                       return -1;
-               }
-       }
-       if (*elen)
-               return etype;
-
-       udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
-               inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *elen, etype, *extoffset);
-       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
-               *extoffset -= sizeof(short_ad);
-       else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
-               *extoffset -= sizeof(long_ad);
-       return -1;
+       return etype;
 }
 
 int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
        lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
-       int pos, alen;
+       int alen;
        int8_t etype;
+       uint8_t *ptr;
 
-       if (!(*bh))
-       {
-               if (!(*bh = udf_tread(inode->i_sb,
-                       udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
-               {
-                       udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, *bloc, 0));
-                       return -1;
-               }
-       }
-
-       if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
+       if (!*bh)
        {
-               if (!(UDF_I_EXTENDED_FE(inode)))
-                       pos = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
-               else
-                       pos = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
-               alen = UDF_I_LENALLOC(inode) + pos;
+               if (!(*extoffset))
+                       *extoffset = udf_file_entry_alloc_offset(inode);
+               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+               alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
        }
        else
        {
-               struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
-
-               pos = sizeof(struct allocExtDesc);
-               alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
+               if (!(*extoffset))
+                       *extoffset = sizeof(struct allocExtDesc);
+               ptr = (*bh)->b_data + *extoffset;
+               alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
        }
 
-       if (!(*extoffset))
-               *extoffset = pos;
-
        switch (UDF_I_ALLOCTYPE(inode))
        {
                case ICBTAG_FLAG_AD_SHORT:
                {
                        short_ad *sad;
 
-                       if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
+                       if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
                                return -1;
 
                        etype = le32_to_cpu(sad->extLength) >> 30;
@@ -1998,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                {
                        long_ad *lad;
 
-                       if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
+                       if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
                                return -1;
 
                        etype = le32_to_cpu(lad->extLength) >> 30;
@@ -2012,15 +1875,8 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
                        return -1;
                }
        }
-       if (*elen)
-               return etype;
 
-       udf_debug("Empty Extent!\n");
-       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
-               *extoffset -= sizeof(short_ad);
-       else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
-               *extoffset -= sizeof(long_ad);
-       return -1;
+       return etype;
 }
 
 int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
@@ -2030,17 +1886,7 @@ int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
        uint32_t oelen;
        int8_t etype;
 
-       if (!bh)
-       {
-               if (!(bh = udf_tread(inode->i_sb,
-                       udf_get_lb_pblock(inode->i_sb, bloc, 0))))
-               {
-                       udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, bloc, 0));
-                       return -1;
-               }
-       }
-       else
+       if (bh)
                atomic_inc(&bh->b_count);
 
        while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
@@ -2064,19 +1910,11 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
        int8_t etype;
        struct allocExtDesc *aed;
 
-       if (!(nbh))
+       if (nbh)
        {
-               if (!(nbh = udf_tread(inode->i_sb,
-                       udf_get_lb_pblock(inode->i_sb, nbloc, 0))))
-               {
-                       udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, nbloc, 0));
-                       return -1;
-               }
-       }
-       else
                atomic_inc(&nbh->b_count);
-       atomic_inc(&nbh->b_count);
+               atomic_inc(&nbh->b_count);
+       }
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
                adsize = sizeof(short_ad);
@@ -2095,7 +1933,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
        while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
        {
                udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
-               if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+               if (obh != nbh)
                {
                        obloc = nbloc;
                        udf_release_data(obh);
@@ -2107,12 +1945,12 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
        memset(&eloc, 0x00, sizeof(lb_addr));
        elen = 0;
 
-       if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
+       if (nbh != obh)
        {
                udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
                udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
                udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-               if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+               if (!obh)
                {
                        UDF_I_LENALLOC(inode) -= (adsize * 2);
                        mark_inode_dirty(inode);
@@ -2132,7 +1970,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
        else
        {
                udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-               if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
+               if (!obh)
                {
                        UDF_I_LENALLOC(inode) -= adsize;
                        mark_inode_dirty(inode);
@@ -2207,9 +2045,7 @@ long udf_block_map(struct inode *inode, long block)
                ret = 0;
 
        unlock_kernel();
-
-       if (bh)
-               udf_release_data(bh);
+       udf_release_data(bh);
 
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
                return udf_fixed_to_variable(ret);
index 7e18f77008dd445b1199353805138ff36381eddd..f7d15571de4e1baf9825718b3c634eba539f5ce2 100644 (file)
@@ -71,15 +71,10 @@ unsigned long
 udf_get_last_block(struct super_block *sb)
 {
        struct block_device *bdev = sb->s_bdev;
-       int ret;
        unsigned long lblock = 0;
 
-       ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
-
-       if (ret) /* Hard Disk */
-       {
+       if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock))
                lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits;
-       }
 
        if (lblock)
                return lblock - 1;
index 2456861ffdda6d0978249a757e416c5935173f5c..eef11b0f169d1ea15da887543bf4e7a0f85ec851 100644 (file)
@@ -74,7 +74,7 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
 
        *bh = udf_tread(inode->i_sb, inode->i_ino);
 
-       if (UDF_I_EXTENDED_FE(inode) == 0)
+       if (UDF_I_EFE(inode) == 0)
        {
                struct fileEntry *fe;
 
@@ -190,7 +190,7 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
 
        *bh = udf_tread(inode->i_sb, inode->i_ino);
 
-       if (UDF_I_EXTENDED_FE(inode) == 0)
+       if (UDF_I_EFE(inode) == 0)
        {
                struct fileEntry *fe;
 
@@ -269,10 +269,10 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
        if (block == 0xFFFFFFFF)
                return NULL;
 
-       bh = udf_tread(sb, block);
+       bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
        if (!bh)
        {
-               udf_debug("block=%d, location=%d: read failed\n", block, location);
+               udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
                return NULL;
        }
 
@@ -283,7 +283,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
        if ( location != le32_to_cpu(tag_p->tagLocation) )
        {
                udf_debug("location mismatch block %u, tag %u != %u\n",
-                       block, le32_to_cpu(tag_p->tagLocation), location);
+                       block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
                goto error_out;
        }
        
@@ -315,7 +315,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
                return bh;
        }
        udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
-               block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
+               block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
 
 error_out:
        brelse(bh);
index 877f3f94bf10545ddd5642ee542d70bd2a4951b7..84d4c1fc109c639334ee5abb6e693b37e57a9b21 100644 (file)
@@ -56,12 +56,16 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
        uint8_t lfi = cfi->lengthFileIdent;
        int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
                sizeof(struct fileIdentDesc);
+       int adinicb = 0;
+
+       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
+               adinicb = 1;
 
        offset = fibh->soffset + sizeof(struct fileIdentDesc);
 
        if (impuse)
        {
-               if (offset + liu < 0)
+               if (adinicb || (offset + liu < 0))
                        memcpy((uint8_t *)sfi->impUse, impuse, liu);
                else if (offset >= 0)
                        memcpy(fibh->ebh->b_data + offset, impuse, liu);
@@ -76,7 +80,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
 
        if (fileident)
        {
-               if (offset + lfi < 0)
+               if (adinicb || (offset + lfi < 0))
                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
                else if (offset >= 0)
                        memcpy(fibh->ebh->b_data + offset, fileident, lfi);
@@ -89,7 +93,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
 
        offset += lfi;
 
-       if (offset + padlen < 0)
+       if (adinicb || (offset + padlen < 0))
                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
        else if (offset >= 0)
                memset(fibh->ebh->b_data + offset, 0x00, padlen);
@@ -123,7 +127,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
                        checksum += ((uint8_t *)&cfi->descTag)[i];
 
        cfi->descTag.tagChecksum = checksum;
-       if (sizeof(struct fileIdentDesc) <= -fibh->soffset)
+       if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset))
                memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
        else
        {
@@ -132,9 +136,14 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
                        sizeof(struct fileIdentDesc) + fibh->soffset);
        }
 
-       if (fibh->sbh != fibh->ebh)
-               mark_buffer_dirty_inode(fibh->ebh, inode);
-       mark_buffer_dirty_inode(fibh->sbh, inode);
+       if (adinicb)
+               mark_inode_dirty(inode);
+       else
+       {
+               if (fibh->sbh != fibh->ebh)
+                       mark_buffer_dirty_inode(fibh->ebh, inode);
+               mark_buffer_dirty_inode(fibh->sbh, inode);
+       }
        return 0;
 }
 
@@ -161,7 +170,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        f_pos = (udf_ext0_offset(dir) >> 2);
 
        fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-       if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+       if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+               fibh->sbh = fibh->ebh = NULL;
+       else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
                &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                offset >>= dir->i_sb->s_blocksize_bits;
@@ -175,6 +186,12 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
                }
                else
                        offset = 0;
+
+               if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
+               {
+                       udf_release_data(bh);
+                       return NULL;
+               }
        }
        else
        {
@@ -182,12 +199,6 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
                return NULL;
        }
 
-       if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
-       {
-               udf_release_data(bh);
-               return NULL;
-       }
-
        while ( (f_pos < size) )
        {
                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
@@ -304,7 +315,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry)
        {
                lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
                inode = udf_iget(dir->i_sb, lb);
-               if (!inode) {
+               if (!inode)
+               {
                        unlock_kernel();
                        return ERR_PTR(-EACCES);
                }
@@ -319,7 +331,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry)
                udf_release_data(fibh.sbh);
 
                inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
-               if ( !inode ) {
+               if ( !inode )
+               {
                        unlock_kernel();
                        return ERR_PTR(-EACCES);
                }
@@ -336,7 +349,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 {
        struct super_block *sb;
        struct fileIdentDesc *fi=NULL;
-       struct ustr unifilename;
        char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
        int namelen;
        loff_t f_pos;
@@ -361,30 +373,11 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                        return NULL;
                }
 
-               if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
+               if ( !(namelen = udf_put_filename(sb, dentry->d_name.name, name, dentry->d_name.len)))
                {
                        *err = -ENAMETOOLONG;
                        return NULL;
                }
-
-               if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
-               {
-                       if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
-                       {
-                               *err = -ENAMETOOLONG;
-                               return NULL;
-                       }
-               }
-               else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
-               {
-                       if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, name, &unifilename, UDF_NAME_LEN)) )
-                       {
-                               *err = -ENAMETOOLONG;
-                               return NULL;
-                       }
-               }
-               else
-                       return NULL;
        }
        else
                namelen = 0;
@@ -394,7 +387,9 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        f_pos = (udf_ext0_offset(dir) >> 2);
 
        fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-       if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+       if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+               fibh->sbh = fibh->ebh = NULL;
+       else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
                &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                offset >>= dir->i_sb->s_blocksize_bits;
@@ -415,94 +410,89 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                        *err = -EIO;
                        return NULL;
                }
-       
+
                block = UDF_I_LOCATION(dir).logicalBlockNum;
-       
-               while ( (f_pos < size) )
+
+       }
+       else
+       {
+               block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
+               fibh->sbh = fibh->ebh = NULL;
+               fibh->soffset = fibh->eoffset = sb->s_blocksize;
+               goto add;
+       }
+
+       while ( (f_pos < size) )
+       {
+               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+
+               if (!fi)
                {
-                       fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-       
-                       if (!fi)
-                       {
-                               if (fibh->sbh != fibh->ebh)
-                                       udf_release_data(fibh->ebh);
-                               udf_release_data(fibh->sbh);
-                               udf_release_data(bh);
-                               *err = -EIO;
-                               return NULL;
-                       }
-       
-                       liu = le16_to_cpu(cfi->lengthOfImpUse);
-                       lfi = cfi->lengthFileIdent;
-       
-                       if (fibh->sbh == fibh->ebh)
-                               nameptr = fi->fileIdent + liu;
+                       if (fibh->sbh != fibh->ebh)
+                               udf_release_data(fibh->ebh);
+                       udf_release_data(fibh->sbh);
+                       udf_release_data(bh);
+                       *err = -EIO;
+                       return NULL;
+               }
+
+               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
                        {
-                               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);
-                               }
+                               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 ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
+               {
+                       if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
                        {
-                               if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
+                               udf_release_data(bh);
+                               cfi->descTag.tagSerialNum = cpu_to_le16(1);
+                               cfi->fileVersionNum = cpu_to_le16(1);
+                               cfi->fileCharacteristics = 0;
+                               cfi->lengthFileIdent = namelen;
+                               cfi->lengthOfImpUse = cpu_to_le16(0);
+                               if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
+                                       return fi;
+                               else
                                {
-                                       udf_release_data(bh);
-                                       cfi->descTag.tagSerialNum = cpu_to_le16(1);
-                                       cfi->fileVersionNum = cpu_to_le16(1);
-                                       cfi->fileCharacteristics = 0;
-                                       cfi->lengthFileIdent = namelen;
-                                       cfi->lengthOfImpUse = cpu_to_le16(0);
-                                       if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
-                                               return fi;
-                                       else
-                                       {
-                                               *err = -EIO;
-                                               return NULL;
-                                       }
+                                       *err = -EIO;
+                                       return NULL;
                                }
                        }
+               }
 
-                       if (!lfi || !dentry)
-                               continue;
+               if (!lfi || !dentry)
+                       continue;
 
-                       if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
-                               udf_match(flen, fname, &(dentry->d_name)))
-                       {
-                               if (fibh->sbh != fibh->ebh)
-                                       udf_release_data(fibh->ebh);
-                               udf_release_data(fibh->sbh);
-                               udf_release_data(bh);
-                               *err = -EEXIST;
-                               return NULL;
-                       }
-               }
-       }
-       else
-       {
-               block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
-               if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+               if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
+                       udf_match(flen, fname, &(dentry->d_name)))
                {
-                       fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
-                       fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
-               }
-               else
-               {
-                       fibh->sbh = fibh->ebh = NULL;
-                       fibh->soffset = fibh->eoffset = sb->s_blocksize;
+                       if (fibh->sbh != fibh->ebh)
+                               udf_release_data(fibh->ebh);
+                       udf_release_data(fibh->sbh);
+                       udf_release_data(bh);
+                       *err = -EEXIST;
+                       return NULL;
                }
        }
 
+add:
        f_pos += nfidlen;
 
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
@@ -539,13 +529,17 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                        fibh->sbh = fibh->ebh;
                }
 
-               if (UDF_I_ALLOCTYPE(dir) != ICBTAG_FLAG_AD_IN_ICB)
+               if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+               {
+                       block = UDF_I_LOCATION(dir).logicalBlockNum;
+                       fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir));
+               }
+               else
+               {
                        block = eloc.logicalBlockNum + ((elen - 1) >>
                                dir->i_sb->s_blocksize_bits);
-               else
-                       block = UDF_I_LOCATION(dir).logicalBlockNum;
-                               
-               fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
+                       fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
+               }
        }
        else
        {
@@ -635,7 +629,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
 
        lock_kernel();
        inode = udf_new_inode(dir, mode, &err);
-       if (!inode) {
+       if (!inode)
+       {
                unlock_kernel();
                return err;
        }
@@ -796,7 +791,10 @@ static int empty_dir(struct inode *dir)
        f_pos = (udf_ext0_offset(dir) >> 2);
 
        fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
-       if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
+
+       if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
+               fibh.sbh = fibh.ebh = NULL;
+       else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
                &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                offset >>= dir->i_sb->s_blocksize_bits;
@@ -810,6 +808,12 @@ static int empty_dir(struct inode *dir)
                }
                else
                        offset = 0;
+
+               if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
+               {
+                       udf_release_data(bh);
+                       return 0;
+               }
        }
        else
        {
@@ -817,8 +821,6 @@ static int empty_dir(struct inode *dir)
                return 0;
        }
 
-       if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
-               return 0;
 
        while ( (f_pos < size) )
        {
@@ -835,6 +837,9 @@ static int empty_dir(struct inode *dir)
 
                if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)
                {
+                       if (fibh.sbh != fibh.ebh)
+                               udf_release_data(fibh.ebh);
+                       udf_release_data(fibh.sbh);
                        udf_release_data(bh);
                        return 0;
                }
@@ -950,6 +955,8 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
        char *ea;
        int err;
        int block;
+       char name[UDF_NAME_LEN];
+       int namelen;
 
        lock_kernel();
        if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
@@ -987,13 +994,10 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
                mark_buffer_dirty_inode(bh, inode);
+               ea = bh->b_data + udf_ext0_offset(inode);
        }
        else
-       {
-               block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
-               bh = udf_tread(inode->i_sb, block);
-       }
-       ea = bh->b_data + udf_ext0_offset(inode);
+               ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
 
        eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
        pc = (struct pathComponent *)ea;
@@ -1031,22 +1035,25 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
                pc->componentType = 5;
                pc->lengthComponentIdent = 0;
                pc->componentFileVersionNum = 0;
-               if (pc->componentIdent[0] == '.')
+               if (compstart[0] == '.')
                {
-                       if (pc->lengthComponentIdent == 1)
+                       if ((symname-compstart) == 1)
                                pc->componentType = 4;
-                       else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
+                       else if ((symname-compstart) == 2 && compstart[1] == '.')
                                pc->componentType = 3;
                }
 
                if (pc->componentType == 5)
                {
-                       if (elen + sizeof(struct pathComponent) + symname - compstart > eoffset)
+                       if ( !(namelen = udf_put_filename(inode->i_sb, compstart, name, symname-compstart)))
+                               goto out_no_entry;
+
+                       if (elen + sizeof(struct pathComponent) + namelen > eoffset)
                                goto out_no_entry;
                        else
-                               pc->lengthComponentIdent = symname - compstart;
+                               pc->lengthComponentIdent = namelen;
 
-                       memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
+                       memcpy(pc->componentIdent, name, namelen);
                }
 
                elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
@@ -1114,12 +1121,14 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
        struct fileIdentDesc cfi, *fi;
 
        lock_kernel();
-       if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) {
+       if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
+       {
                unlock_kernel();
                return -EMLINK;
        }
 
-       if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
+       if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
+       {
                unlock_kernel();
                return err;
        }
@@ -1204,10 +1213,21 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
                                goto end_rename;
                }
                retval = -EIO;
-               dir_bh = udf_bread(old_inode, 0, 0, &retval);
-               if (!dir_bh)
-                       goto end_rename;
-               dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
+               if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
+               {
+                       dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
+                               (UDF_I_EFE(old_inode) ?
+                                       sizeof(struct extendedFileEntry) :
+                                       sizeof(struct fileEntry)),
+                               old_inode->i_sb->s_blocksize, &offset);
+               }
+               else
+               {
+                       dir_bh = udf_bread(old_inode, 0, 0, &retval);
+                       if (!dir_bh)
+                               goto end_rename;
+                       dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
+               }
                if (!dir_fi)
                        goto end_rename;
                if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
@@ -1257,7 +1277,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
        UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
        mark_inode_dirty(old_dir);
 
-       if (dir_bh)
+       if (dir_fi)
        {
                dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
                udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
index ab3b6b67da24e3ae70cb045686bf5a6b963df7ce..efa6acc026666f1a98b547811167e3ba3c8f6e0a 100644 (file)
@@ -83,7 +83,7 @@ struct appIdentSuffix
 {
        uint8_t         impUse[8];
 } __attribute__ ((packed));
+
 /* Logical Volume Integrity Descriptor (UDF 2.01 2.2.6) */
 /* Implementation Use (UDF 2.01 2.2.6.4) */
 struct logicalVolIntegrityDescImpUse
index e4a1d8de3ee8a9b838ab76eb3a53f915296eeb82..127f80f19202a3a0b138e6f9c5550c119dfed90b 100644 (file)
@@ -135,7 +135,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
            SLAB_CTOR_CONSTRUCTOR)
                inode_init_once(&ei->vfs_inode);
 }
+
 static int init_inodecache(void)
 {
        udf_inode_cachep = kmem_cache_create("udf_inode_cache",
@@ -161,6 +161,7 @@ static struct super_operations udf_sb_ops = {
        .write_inode            = udf_write_inode,
        .put_inode              = udf_put_inode,
        .delete_inode           = udf_delete_inode,
+       .clear_inode            = udf_clear_inode,
        .put_super              = udf_put_super,
        .write_super            = udf_write_super,
        .statfs                 = udf_statfs,
@@ -285,7 +286,8 @@ udf_parse_options(char *options, struct udf_options *uopt)
        if (!options)
                return 1;
 
-       while ((opt = strsep(&options, ",")) != NULL) {
+       while ((opt = strsep(&options, ",")) != NULL)
+       {
                if (!*opt)
                        continue;
                /* Make "opt=val" into two strings */
@@ -383,10 +385,6 @@ udf_remount_fs(struct super_block *sb, int *flags, char *options)
        UDF_SB(sb)->s_gid   = uopt.gid;
        UDF_SB(sb)->s_umask = uopt.umask;
 
-#if UDFFS_RW != 1
-       *flags |= MS_RDONLY;
-#endif
-
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
        if (*flags & MS_RDONLY)
@@ -591,14 +589,14 @@ udf_find_anchor(struct super_block *sb)
                        {
                                if (location == last[i] - UDF_SB_SESSION(sb))
                                {
-                                       lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
-                                       UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
+                                       lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb);
+                                       UDF_SB_ANCHOR(sb)[1] = last[i] - 256 - UDF_SB_SESSION(sb);
                                }
                                else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
                                {
                                        UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
-                                       lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
-                                       UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
+                                       lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb);
+                                       UDF_SB_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb);
                                }
                                else
                                        udf_debug("Anchor found at block %d, location mismatch %d.\n",
@@ -607,7 +605,7 @@ udf_find_anchor(struct super_block *sb)
                        else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
                        {
                                lastblock = last[i];
-                               UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
+                               UDF_SB_ANCHOR(sb)[3] = 512;
                        }
                        else
                        {
@@ -852,7 +850,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
                if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
                {
                        UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
-                       UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb);
+                       UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation);
                        if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
                                UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY;
                        if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE)
@@ -1428,10 +1426,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        sb->s_fs_info = sbi;
        memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
 
-#if UDFFS_RW != 1
-       sb->s_flags |= MS_RDONLY;
-#endif
-
        if (!udf_parse_options((char *)options, &uopt))
                goto error_out;
 
@@ -1478,7 +1472,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
        UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
        UDF_SB_ANCHOR(sb)[2] = uopt.anchor;
-       UDF_SB_ANCHOR(sb)[3] = UDF_SB_SESSION(sb) + 256;
+       UDF_SB_ANCHOR(sb)[3] = 256;
 
        if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
        {
@@ -1543,8 +1537,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        {
                timestamp ts;
                udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
-               udf_info("UDF %s-%s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
-                       UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE,
+               udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
+                       UDFFS_VERSION, UDFFS_DATE,
                        UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
                        ts.typeAndTimezone);
        }
@@ -1726,8 +1720,6 @@ udf_put_super(struct super_block *sb)
 static int
 udf_statfs(struct super_block *sb, struct statfs *buf)
 {
-       lock_kernel();
-
        buf->f_type = UDF_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
@@ -1740,8 +1732,6 @@ udf_statfs(struct super_block *sb, struct statfs *buf)
        /* __kernel_fsid_t f_fsid */
        buf->f_namelen = UDF_NAME_LEN;
 
-       unlock_kernel();
-
        return 0;
 }
 
@@ -1763,6 +1753,8 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
        uint16_t ident;
        struct spaceBitmapDesc *bm;
 
+       lock_kernel();
+
        loc.logicalBlockNum = bitmap->s_extPosition;
        loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
        bh = udf_read_ptagged(sb, loc, 0, &ident);
@@ -1770,13 +1762,13 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
        if (!bh)
        {
                printk(KERN_ERR "udf: udf_count_free failed\n");
-               return 0;
+               goto out;
        }
        else if (ident != TAG_IDENT_SBD)
        {
                udf_release_data(bh);
                printk(KERN_ERR "udf: udf_count_free failed\n");
-               return 0;
+               goto out;
        }
 
        bm = (struct spaceBitmapDesc *)bh->b_data;
@@ -1802,13 +1794,17 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
                        if (!bh)
                        {
                                udf_debug("read failed\n");
-                               return accum;
+                               goto out;
                        }
                        index = 0;
                        ptr = (uint8_t *)bh->b_data;
                }
        }
        udf_release_data(bh);
+
+out:
+       unlock_kernel();
+
        return accum;
 }
 
@@ -1821,6 +1817,8 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
        int8_t etype;
        struct buffer_head *bh = NULL;
 
+       lock_kernel();
+
        bloc = UDF_I_LOCATION(table);
        extoffset = sizeof(struct unallocSpaceEntry);
 
@@ -1829,6 +1827,9 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
                accum += (elen >> table->i_sb->s_blocksize_bits);
        }
        udf_release_data(bh);
+
+       unlock_kernel();
+
        return accum;
 }
        
index 417ed6dc6ddb504fdb4e4172a53bf6b4a5d2ec74..43f3051ef756484c58d14b959d42bb26f103b83a 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/buffer_head.h>
 #include "udf_i.h"
 
-static void udf_pc_to_char(char *from, int fromlen, char *to)
+static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen, char *to)
 {
        struct pathComponent *pc;
        int elen = 0;
@@ -66,9 +66,9 @@ static void udf_pc_to_char(char *from, int fromlen, char *to)
                                /* that would be . - just ignore */
                                break;
                        case 5:
-                               memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
-                               p += pc->lengthComponentIdent;
+                               p += udf_get_filename(sb, pc->componentIdent, p, pc->lengthComponentIdent);
                                *p++ = '/';
+                               break;
                }
                elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
        }
@@ -85,17 +85,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        char *symlink;
        int err = -EIO;
        char *p = kmap(page);
-       
+
        lock_kernel();
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
-       {
-               bh = udf_tread(inode->i_sb, inode->i_ino);
-
-               if (!bh)
-                       goto out;
-
-               symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
-       }
+               symlink = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
        else
        {
                bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
@@ -106,7 +99,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
                symlink = bh->b_data;
        }
 
-       udf_pc_to_char(symlink, inode->i_size, p);
+       udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
        udf_release_data(bh);
 
        unlock_kernel();
index 1391372211a2710c7aa9afdaa47560550f508d4c..16e64daf61d1b3f2becc06ea16efd5914a48beb0 100644 (file)
@@ -95,7 +95,7 @@ void udf_truncate_extents(struct inode * inode)
                else
                        lenalloc = extoffset - adsize;
 
-               if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+               if (!bh)
                        lenalloc -= udf_file_entry_alloc_offset(inode);
                else
                        lenalloc -= sizeof(struct allocExtDesc);
@@ -108,15 +108,15 @@ void udf_truncate_extents(struct inode * inode)
                                extoffset = 0;
                                if (lelen)
                                {
-                                       if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-                                               memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
+                                       if (!bh)
+                                               BUG();
                                        else
                                                memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
                                        udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
                                }
                                else
                                {
-                                       if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+                                       if (!bh)
                                        {
                                                UDF_I_LENALLOC(inode) = lenalloc;
                                                mark_inode_dirty(inode);
@@ -135,9 +135,9 @@ void udf_truncate_extents(struct inode * inode)
                                }
 
                                udf_release_data(bh);
-                               bh = NULL;
-
+                               extoffset = sizeof(struct allocExtDesc);
                                bloc = eloc;
+                               bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
                                if (elen)
                                        lelen = (elen + inode->i_sb->s_blocksize - 1) >>
                                                inode->i_sb->s_blocksize_bits;
@@ -153,15 +153,15 @@ void udf_truncate_extents(struct inode * inode)
 
                if (lelen)
                {
-                       if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
-                               memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
+                       if (!bh)
+                               BUG();
                        else
                                memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
                        udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
                }
                else
                {
-                       if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+                       if (!bh)
                        {
                                UDF_I_LENALLOC(inode) = lenalloc;
                                mark_inode_dirty(inode);
index a967f2c4a9d34feac65d80f46d44e56390324130..5d87e85e6062338bbe56392b08d7978c14e233b3 100644 (file)
@@ -13,14 +13,17 @@ static inline struct udf_inode_info *UDF_I(struct inode *inode)
 #define UDF_I_LENEXTENTS(X)    ( UDF_I(X)->i_lenExtents )
 #define UDF_I_UNIQUE(X)                ( UDF_I(X)->i_unique )
 #define UDF_I_ALLOCTYPE(X)     ( UDF_I(X)->i_alloc_type )
-#define UDF_I_EXTENDED_FE(X)   ( UDF_I(X)->i_extended_fe )
-#define UDF_I_STRAT4096(X)     ( UDF_I(X)->i_strat_4096 )
-#define UDF_I_NEW_INODE(X)     ( UDF_I(X)->i_new_inode )
+#define UDF_I_EFE(X)           ( UDF_I(X)->i_efe )
+#define UDF_I_USE(X)           ( UDF_I(X)->i_use )
+#define UDF_I_STRAT4096(X)     ( UDF_I(X)->i_strat4096 )
 #define UDF_I_NEXT_ALLOC_BLOCK(X)      ( UDF_I(X)->i_next_alloc_block )
 #define UDF_I_NEXT_ALLOC_GOAL(X)       ( UDF_I(X)->i_next_alloc_goal )
 #define UDF_I_UMTIME(X)                ( UDF_I(X)->i_umtime )
 #define UDF_I_UCTIME(X)                ( UDF_I(X)->i_uctime )
 #define UDF_I_CRTIME(X)                ( UDF_I(X)->i_crtime )
 #define UDF_I_UCRTIME(X)       ( UDF_I(X)->i_ucrtime )
+#define UDF_I_SAD(X)           ( UDF_I(X)->i_ext.i_sad )
+#define UDF_I_LAD(X)           ( UDF_I(X)->i_ext.i_lad )
+#define UDF_I_DATA(X)          ( UDF_I(X)->i_ext.i_data )
 
 #endif /* !defined(_LINUX_UDF_I_H) */
index c23edd0315b8fdfdd04915f31735b0f07bc8c4c6..a41c46ad97265ea3c6ca8efa7fc0961977cb1c40 100644 (file)
 #include <linux/version.h>
 #endif
 
-#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
-#define CONFIG_UDF_FS_MODULE
-#endif
-
 #include "udfend.h"
 
 #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
 #define CURRENT_UTIME  (xtime.tv_nsec / 1000)
 
 #define udf_file_entry_alloc_offset(inode)\
-       ((UDF_I_EXTENDED_FE(inode) ?\
-               sizeof(struct extendedFileEntry) :\
-               sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode))
+       (UDF_I_USE(inode) ?\
+               sizeof(struct unallocSpaceEntry) :\
+               ((UDF_I_EFE(inode) ?\
+                       sizeof(struct extendedFileEntry) :\
+                       sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)))
 
 #define udf_ext0_offset(inode)\
        (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\
@@ -114,6 +112,7 @@ extern void udf_truncate(struct inode *);
 extern void udf_read_inode(struct inode *);
 extern void udf_put_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
+extern void udf_clear_inode(struct inode *);
 extern void udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, long);
 extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
@@ -134,6 +133,10 @@ extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
 extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
 extern void udf_release_data(struct buffer_head *);
+extern uint32_t udf64_low32(uint64_t);
+extern uint32_t udf64_high32(uint64_t);
+extern void udf_update_tag(char *, int);
+extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
 
 /* lowlevel.c */
 extern unsigned int udf_get_last_session(struct super_block *);
@@ -148,6 +151,9 @@ extern int udf_relocate_blocks(struct super_block *, long, long *);
 
 /* unicode.c */
 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 *);
 
 /* ialloc.c */
 extern void udf_free_inode(struct inode *);
@@ -168,40 +174,17 @@ extern int udf_fsync_inode(struct inode *, int);
 /* directory.c */
 extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
 extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-
-/* unicode.c */
-extern int udf_ustr_to_dchars(uint8_t *, const struct ustr *, int);
-extern int udf_ustr_to_char(uint8_t *, const struct ustr *, int);
-extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
-extern int udf_dchars_to_ustr(struct ustr *, const uint8_t *, int);
-extern int udf_char_to_ustr(struct ustr *, const uint8_t *, int);
-extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
-extern int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
-extern int udf_build_ustr(struct ustr *, dstring *, int);
-extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
-extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
-extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
-extern int udf_CS0toNLS(struct nls_table *, struct ustr *, struct ustr *);
-extern int udf_NLStoCS0(struct nls_table *, dstring *, struct ustr *, int);
+extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
+extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
+extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
+extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
+extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
 
 /* crc.c */
 extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
 
-/* misc.c */
-extern uint32_t udf64_low32(uint64_t);
-extern uint32_t udf64_high32(uint64_t);
-extern void udf_update_tag(char *, int);
-extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
-
 /* udftime.c */
 extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
 extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
 
-/* directory.c */
-extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
-extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
-extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
-extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
-
 #endif /* __UDF_DECL_H */
index eb88a0173f170262301a56f22fd7e8b60beb7f81..5f9e87f1cc479c5521fb160dd446a30a2ed33abb 100644 (file)
 
 #include "udf_sb.h"
 
-int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen)
-{
-       if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
-               return 0;
-       memcpy(dest+1, src->u_name, src->u_len);
-       dest[0] = src->u_cmpID;
-       return src->u_len + 1;
-}
-
-int udf_ustr_to_char(uint8_t *dest, const struct ustr *src, int strlen)
-{
-       if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
-               return 0;
-       memcpy(dest, src->u_name, src->u_len);
-       return src->u_len;
-}
-
-int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
-{
-       if ( udf_ustr_to_dchars(dest, src, dlength-1) )
-       {
-               dest[dlength-1] = src->u_len + 1;
-               return dlength;
-       }
-       else
-               return 0;
-}
-
-int udf_dchars_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
-{
-       if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
-               return 0;
-       memset(dest, 0, sizeof(struct ustr));
-       memcpy(dest->u_name, src+1, strlen-1);
-       dest->u_cmpID = src[0];
-       dest->u_len = strlen-1;
-       return strlen-1;
-}
+static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
 
-int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
+static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
 {
        if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
                return 0;
@@ -82,15 +45,6 @@ int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
        return strlen;
 }
 
-
-int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
-{
-       if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
-               return dlength;
-       else
-               return 0;
-}
-
 /*
  * udf_build_ustr
  */
@@ -112,7 +66,7 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
 /*
  * udf_build_ustr_exact
  */
-int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
+static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
 {
        if ( (!dest) || (!ptr) || (!exactsize) )
                return -1;
@@ -224,7 +178,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
  *     November 12, 1997 - Andrew E. Mileski
  *     Written, tested, and released.
  */
-int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
+static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
 {
        unsigned c, i, max_val, utf_char;
        int utf_cnt;
@@ -318,7 +272,7 @@ error_out:
        return u_len + 1;
 }
 
-int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
+static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
 {
        uint8_t *ocu;
        uint32_t c;
@@ -360,7 +314,7 @@ int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
        return utf_o->u_len;
 }
 
-int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
+static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
 {
        unsigned len, i, max_val;
        uint16_t uni_char;
@@ -434,12 +388,42 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, int
        return 0;
 }
 
+int udf_put_filename(struct super_block *sb, const uint8_t *sname, uint8_t *dname, int flen)
+{
+       struct ustr unifilename;
+       int namelen;
+
+       if ( !(udf_char_to_ustr(&unifilename, sname, flen)) )
+       {
+               return 0;
+       }
+
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
+       {
+               if ( !(namelen = udf_UTF8toCS0(dname, &unifilename, UDF_NAME_LEN)) )
+               {
+                       return 0;
+               }
+       }
+       else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
+       {
+               if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, dname, &unifilename, UDF_NAME_LEN)) )
+               {
+                       return 0;
+               }
+       }
+       else
+               return 0;
+
+       return namelen;
+}
+
 #define ILLEGAL_CHAR_MARK      '_'
 #define EXT_MARK                       '.'
 #define CRC_MARK                       '#'
 #define EXT_SIZE                       5
 
-int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
+static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
 {
        int index, newIndex = 0, needsCRC = 0;  
        int extIndex = 0, newExtIndex = 0, hasExt = 0;
index 83eddc46650f68e282df17c7d3381f562d6e8242..45c1a58688abe4d3bda04ae19e919bc41e785335 100644 (file)
 #ifndef _UDF_FS_H
 #define _UDF_FS_H 1
 
-#include <linux/config.h>
-
 #define UDF_PREALLOCATE
 #define UDF_DEFAULT_PREALLOC_BLOCKS    8
 
-#define UDFFS_DATE                     "2002/03/11"
-#define UDFFS_VERSION                  "0.9.6"
-
-#if !defined(UDFFS_RW)
-
-#if defined(CONFIG_UDF_RW)
-#define UDFFS_RW                       1
-#else /* !defined(CONFIG_UDF_RW) */
-#define UDFFS_RW                       0
-#endif /* defined(CONFIG_UDF_RW) */
-
-#endif /* !defined(UDFFS_RW) */
+#define UDFFS_DATE                     "2002/11/15"
+#define UDFFS_VERSION                  "0.9.7"
 
 #define UDFFS_DEBUG
 
index 110468cb82df5d704c5aa4bcdf7ffc899ee6f2dc..f297d528aded0ca543e9c833533ddc4bcc9fc807 100644 (file)
 #ifndef _ECMA_167_H
 typedef struct
 {
-       __u32 logicalBlockNum;
-       __u16 partitionReferenceNum;
+       __u32                   logicalBlockNum;
+       __u16                   partitionReferenceNum;
 } __attribute__ ((packed)) lb_addr;
+
+typedef struct
+{
+       __u32                   extLength;
+       __u32                   extPosition;
+} __attribute__ ((packed)) short_ad;
+
+typedef struct
+{
+       __u32                   extLength;
+       lb_addr                 extLocation;
+       __u8                    impUse[6];
+} __attribute__ ((packed)) long_ad;
 #endif
 
 struct udf_inode_info
 {
-       long i_umtime;
-       long i_uctime;
-       long i_crtime;
-       long i_ucrtime;
+       long                    i_umtime;
+       long                    i_uctime;
+       long                    i_crtime;
+       long                    i_ucrtime;
        /* Physical address of inode */
-       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_extended_fe : 1;
-       unsigned i_strat_4096 : 1;
-       unsigned i_new_inode : 1;
-       unsigned reserved : 26;
+       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;
 };