]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
UDF: introduce struct extent_position
authorJan Kara <jack@suse.cz>
Tue, 8 May 2007 07:35:14 +0000 (00:35 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 8 May 2007 18:15:21 +0000 (11:15 -0700)
Introduce a structure extent_position to store a position of an extent and
the corresponding buffer_head in one place.

Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/udf/balloc.c
fs/udf/dir.c
fs/udf/directory.c
fs/udf/inode.c
fs/udf/namei.c
fs/udf/super.c
fs/udf/truncate.c
fs/udf/udfdecl.h

index ea521f846d97a4e3109b82feb8bb83f6d9201a1c..756dbbf0eafd04798b486bae1726f6cadea3ed16 100644 (file)
@@ -427,9 +427,9 @@ static void udf_table_free_blocks(struct super_block * sb,
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        uint32_t start, end;
-       uint32_t nextoffset, oextoffset, elen;
-       kernel_lb_addr nbloc, obloc, eloc;
-       struct buffer_head *obh, *nbh;
+       uint32_t elen;
+       kernel_lb_addr eloc;
+       struct extent_position oepos, epos;
        int8_t etype;
        int i;
 
@@ -457,14 +457,13 @@ static void udf_table_free_blocks(struct super_block * sb,
        start = bloc.logicalBlockNum + offset;
        end = bloc.logicalBlockNum + offset + count - 1;
 
-       oextoffset = nextoffset = sizeof(struct unallocSpaceEntry);
+       epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);
        elen = 0;
-       obloc = nbloc = UDF_I_LOCATION(table);
-
-       obh = nbh = NULL;
+       epos.block = oepos.block = UDF_I_LOCATION(table);
+       epos.bh = oepos.bh = NULL;
 
        while (count && (etype =
-               udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
+               udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
        {
                if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) ==
                        start))
@@ -482,7 +481,7 @@ static void udf_table_free_blocks(struct super_block * sb,
                                start += count;
                                count = 0;
                        }
-                       udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
+                       udf_write_aext(table, &oepos, eloc, elen, 1);
                }
                else if (eloc.logicalBlockNum == (end + 1))
                {
@@ -502,20 +501,20 @@ static void udf_table_free_blocks(struct super_block * sb,
                                end -= count;
                                count = 0;
                        }
-                       udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
+                       udf_write_aext(table, &oepos, eloc, elen, 1);
                }
 
-               if (nbh != obh)
+               if (epos.bh != oepos.bh)
                {
                        i = -1;
-                       obloc = nbloc;
-                       udf_release_data(obh);
-                       atomic_inc(&nbh->b_count);
-                       obh = nbh;
-                       oextoffset = 0;
+                       oepos.block = epos.block;
+                       udf_release_data(oepos.bh);
+                       atomic_inc(&epos.bh->b_count);
+                       oepos.bh = epos.bh;
+                       oepos.offset = 0;
                }
                else
-                       oextoffset = nextoffset;
+                       oepos.offset = epos.offset;
        }
 
        if (count)
@@ -547,55 +546,53 @@ static void udf_table_free_blocks(struct super_block * sb,
                        adsize = sizeof(long_ad);
                else
                {
-                       udf_release_data(obh);
-                       udf_release_data(nbh);
+                       udf_release_data(oepos.bh);
+                       udf_release_data(epos.bh);
                        goto error_return;
                }
 
-               if (nextoffset + (2 * adsize) > sb->s_blocksize)
+               if (epos.offset + (2 * adsize) > sb->s_blocksize)
                {
                        char *sptr, *dptr;
                        int loffset;
        
-                       udf_release_data(obh);
-                       obh = nbh;
-                       obloc = nbloc;
-                       oextoffset = nextoffset;
+                       udf_release_data(oepos.bh);
+                       oepos = epos;
 
                        /* Steal a block from the extent being free'd */
-                       nbloc.logicalBlockNum = eloc.logicalBlockNum;
+                       epos.block.logicalBlockNum = eloc.logicalBlockNum;
                        eloc.logicalBlockNum ++;
                        elen -= sb->s_blocksize;
 
-                       if (!(nbh = udf_tread(sb,
-                               udf_get_lb_pblock(sb, nbloc, 0))))
+                       if (!(epos.bh = udf_tread(sb,
+                               udf_get_lb_pblock(sb, epos.block, 0))))
                        {
-                               udf_release_data(obh);
+                               udf_release_data(oepos.bh);
                                goto error_return;
                        }
-                       aed = (struct allocExtDesc *)(nbh->b_data);
-                       aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
-                       if (nextoffset + adsize > sb->s_blocksize)
+                       aed = (struct allocExtDesc *)(epos.bh->b_data);
+                       aed->previousAllocExtLocation = cpu_to_le32(oepos.block.logicalBlockNum);
+                       if (epos.offset + adsize > sb->s_blocksize)
                        {
-                               loffset = nextoffset;
+                               loffset = epos.offset;
                                aed->lengthAllocDescs = cpu_to_le32(adsize);
-                               sptr = UDF_I_DATA(inode) + nextoffset -
+                               sptr = UDF_I_DATA(inode) + epos.offset -
                                        udf_file_entry_alloc_offset(inode) +
                                        UDF_I_LENEATTR(inode) - adsize;
-                               dptr = nbh->b_data + sizeof(struct allocExtDesc);
+                               dptr = epos.bh->b_data + sizeof(struct allocExtDesc);
                                memcpy(dptr, sptr, adsize);
-                               nextoffset = sizeof(struct allocExtDesc) + adsize;
+                               epos.offset = sizeof(struct allocExtDesc) + adsize;
                        }
                        else
                        {
-                               loffset = nextoffset + adsize;
+                               loffset = epos.offset + adsize;
                                aed->lengthAllocDescs = cpu_to_le32(0);
-                               sptr = (obh)->b_data + nextoffset;
-                               nextoffset = sizeof(struct allocExtDesc);
+                               sptr = oepos.bh->b_data + epos.offset;
+                               epos.offset = sizeof(struct allocExtDesc);
 
-                               if (obh)
+                               if (oepos.bh)
                                {
-                                       aed = (struct allocExtDesc *)(obh)->b_data;
+                                       aed = (struct allocExtDesc *)oepos.bh->b_data;
                                        aed->lengthAllocDescs =
                                                cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
                                }
@@ -606,11 +603,11 @@ static void udf_table_free_blocks(struct super_block * sb,
                                }
                        }
                        if (UDF_SB_UDFREV(sb) >= 0x0200)
-                               udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
-                                       nbloc.logicalBlockNum, sizeof(tag));
+                               udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1,
+                                       epos.block.logicalBlockNum, sizeof(tag));
                        else
-                               udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
-                                       nbloc.logicalBlockNum, sizeof(tag));
+                               udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1,
+                                       epos.block.logicalBlockNum, sizeof(tag));
                        switch (UDF_I_ALLOCTYPE(table))
                        {
                                case ICBTAG_FLAG_AD_SHORT:
@@ -619,7 +616,7 @@ static void udf_table_free_blocks(struct super_block * sb,
                                        sad->extLength = cpu_to_le32(
                                                EXT_NEXT_EXTENT_ALLOCDECS |
                                                sb->s_blocksize);
-                                       sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum);
+                                       sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum);
                                        break;
                                }
                                case ICBTAG_FLAG_AD_LONG:
@@ -628,14 +625,14 @@ static void udf_table_free_blocks(struct super_block * sb,
                                        lad->extLength = cpu_to_le32(
                                                EXT_NEXT_EXTENT_ALLOCDECS |
                                                sb->s_blocksize);
-                                       lad->extLocation = cpu_to_lelb(nbloc);
+                                       lad->extLocation = cpu_to_lelb(epos.block);
                                        break;
                                }
                        }
-                       if (obh)
+                       if (oepos.bh)
                        {
-                               udf_update_tag(obh->b_data, loffset);
-                               mark_buffer_dirty(obh);
+                               udf_update_tag(oepos.bh->b_data, loffset);
+                               mark_buffer_dirty(oepos.bh);
                        }
                        else
                                mark_inode_dirty(table);
@@ -643,26 +640,26 @@ static void udf_table_free_blocks(struct super_block * sb,
 
                if (elen) /* It's possible that stealing the block emptied the extent */
                {
-                       udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
+                       udf_write_aext(table, &epos, eloc, elen, 1);
 
-                       if (!nbh)
+                       if (!epos.bh)
                        {
                                UDF_I_LENALLOC(table) += adsize;
                                mark_inode_dirty(table);
                        }
                        else
                        {
-                               aed = (struct allocExtDesc *)nbh->b_data;
+                               aed = (struct allocExtDesc *)epos.bh->b_data;
                                aed->lengthAllocDescs =
                                        cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
-                               udf_update_tag(nbh->b_data, nextoffset);
-                               mark_buffer_dirty(nbh);
+                               udf_update_tag(epos.bh->b_data, epos.offset);
+                               mark_buffer_dirty(epos.bh);
                        }
                }
        }
 
-       udf_release_data(nbh);
-       udf_release_data(obh);
+       udf_release_data(epos.bh);
+       udf_release_data(oepos.bh);
 
 error_return:
        sb->s_dirt = 1;
@@ -677,9 +674,9 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        int alloc_count = 0;
-       uint32_t extoffset, elen, adsize;
-       kernel_lb_addr bloc, eloc;
-       struct buffer_head *bh;
+       uint32_t elen, adsize;
+       kernel_lb_addr eloc;
+       struct extent_position epos;
        int8_t etype = -1;
 
        if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
@@ -693,14 +690,13 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
                return 0;
 
        mutex_lock(&sbi->s_alloc_mutex);
-       extoffset = sizeof(struct unallocSpaceEntry);
-       bloc = UDF_I_LOCATION(table);
-
-       bh = NULL;
+       epos.offset = sizeof(struct unallocSpaceEntry);
+       epos.block = UDF_I_LOCATION(table);
+       epos.bh = NULL;
        eloc.logicalBlockNum = 0xFFFFFFFF;
 
        while (first_block != eloc.logicalBlockNum && (etype =
-               udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+               udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
        {
                udf_debug("eloc=%d, elen=%d, first_block=%d\n",
                        eloc.logicalBlockNum, elen, first_block);
@@ -709,7 +705,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 
        if (first_block == eloc.logicalBlockNum)
        {
-               extoffset -= adsize;
+               epos.offset -= adsize;
 
                alloc_count = (elen >> sb->s_blocksize_bits);
                if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
@@ -719,15 +715,15 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
                        alloc_count = block_count;
                        eloc.logicalBlockNum += alloc_count;
                        elen -= (alloc_count << sb->s_blocksize_bits);
-                       udf_write_aext(table, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1);
+                       udf_write_aext(table, &epos, eloc, (etype << 30) | elen, 1);
                }
                else
-                       udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);
+                       udf_delete_aext(table, epos, eloc, (etype << 30) | elen);
        }
        else
                alloc_count = 0;
 
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 
        if (alloc_count && UDF_SB_LVIDBH(sb))
        {
@@ -747,9 +743,9 @@ static int udf_table_new_block(struct super_block * sb,
        struct udf_sb_info *sbi = UDF_SB(sb);
        uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
        uint32_t newblock = 0, adsize;
-       uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;
-       kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc;
-       struct buffer_head *bh, *goal_bh;
+       uint32_t elen, goal_elen = 0;
+       kernel_lb_addr eloc, goal_eloc;
+       struct extent_position epos, goal_epos;
        int8_t etype;
 
        *err = -ENOSPC;
@@ -770,14 +766,12 @@ static int udf_table_new_block(struct super_block * sb,
           We store the buffer_head, bloc, and extoffset of the current closest
           match and use that when we are done.
        */
-
-       extoffset = sizeof(struct unallocSpaceEntry);
-       bloc = UDF_I_LOCATION(table);
-
-       goal_bh = bh = NULL;
+       epos.offset = sizeof(struct unallocSpaceEntry);
+       epos.block = UDF_I_LOCATION(table);
+       epos.bh = goal_epos.bh = NULL;
 
        while (spread && (etype =
-               udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+               udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
        {
                if (goal >= eloc.logicalBlockNum)
                {
@@ -793,24 +787,24 @@ static int udf_table_new_block(struct super_block * sb,
                if (nspread < spread)
                {
                        spread = nspread;
-                       if (goal_bh != bh)
+                       if (goal_epos.bh != epos.bh)
                        {
-                               udf_release_data(goal_bh);
-                               goal_bh = bh;
-                               atomic_inc(&goal_bh->b_count);
+                               udf_release_data(goal_epos.bh);
+                               goal_epos.bh = epos.bh;
+                               atomic_inc(&goal_epos.bh->b_count);
                        }
-                       goal_bloc = bloc;
-                       goal_extoffset = extoffset - adsize;
+                       goal_epos.block = epos.block;
+                       goal_epos.offset = epos.offset - adsize;
                        goal_eloc = eloc;
                        goal_elen = (etype << 30) | elen;
                }
        }
 
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 
        if (spread == 0xFFFFFFFF)
        {
-               udf_release_data(goal_bh);
+               udf_release_data(goal_epos.bh);
                mutex_unlock(&sbi->s_alloc_mutex);
                return 0;
        }
@@ -826,17 +820,17 @@ static int udf_table_new_block(struct super_block * sb,
 
        if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
        {
-               udf_release_data(goal_bh);
+               udf_release_data(goal_epos.bh);
                mutex_unlock(&sbi->s_alloc_mutex);
                *err = -EDQUOT;
                return 0;
        }
 
        if (goal_elen)
-               udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);
+               udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1);
        else
-               udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh);
-       udf_release_data(goal_bh);
+               udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
+       udf_release_data(goal_epos.bh);
 
        if (UDF_SB_LVIDBH(sb))
        {
index 3c50b82a2307dcc69fb314fbe899e034e0435991..00c15d3dd756fa7f455dfac05f81c07c60dfcf8d 100644 (file)
@@ -111,12 +111,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        uint16_t liu;
        uint8_t lfi;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
-       struct buffer_head * bh = NULL, * tmp, * bha[16];
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen;
+       struct buffer_head *tmp, *bha[16];
+       kernel_lb_addr eloc;
+       uint32_t elen;
        sector_t offset;
        int i, num;
        unsigned int dt_type;
+       struct extent_position epos = { NULL, 0, {0, 0}};
 
        if (nf_pos >= size)
                return 0;
@@ -128,22 +129,22 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        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))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return -EIO;
                }
        
@@ -171,7 +172,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        }
        else
        {
-               udf_release_data(bh);
+               udf_release_data(epos.bh);
                return -ENOENT;
        }
 
@@ -179,14 +180,14 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        {
                filp->f_pos = nf_pos + 1;
 
-               fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh.sbh != fibh.ebh)
                                udf_release_data(fibh.ebh);
                        udf_release_data(fibh.sbh);
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return 0;
                }
 
@@ -246,7 +247,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
                                if (fibh.sbh != fibh.ebh)
                                        udf_release_data(fibh.ebh);
                                udf_release_data(fibh.sbh);
-                               udf_release_data(bh);
+                               udf_release_data(epos.bh);
                                return 0;
                        }
                }
@@ -257,7 +258,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
        if (fibh.sbh != fibh.ebh)
                udf_release_data(fibh.ebh);
        udf_release_data(fibh.sbh);
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 
        return 0;
 }
index 024ccac8b7f4374c67731a2299c9e8a8c96fdf88..9f66cfe124c6076a0628d2e2731416648336a8ad 100644 (file)
@@ -75,9 +75,9 @@ struct fileIdentDesc *
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
        struct udf_fileident_bh *fibh,
        struct fileIdentDesc *cfi,
-       kernel_lb_addr *bloc, uint32_t *extoffset, 
+       struct extent_position *epos,
        kernel_lb_addr *eloc, uint32_t *elen,
-       sector_t *offset, struct buffer_head **bh)
+       sector_t *offset)
 {
        struct fileIdentDesc *fi;
        int i, num, block;
@@ -105,13 +105,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 
        if (fibh->eoffset == dir->i_sb->s_blocksize)
        {
-               int lextoffset = *extoffset;
+               int lextoffset = epos->offset;
 
-               if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
+               if (udf_next_aext(dir, epos, eloc, elen, 1) !=
                        (EXT_RECORDED_ALLOCATED >> 30))
-               {
                        return NULL;
-               }
 
                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 
@@ -120,7 +118,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
                if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
                        *offset = 0;
                else
-                       *extoffset = lextoffset;
+                       epos->offset = lextoffset;
 
                udf_release_data(fibh->sbh);
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
@@ -169,13 +167,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
        }
        else if (fibh->eoffset > dir->i_sb->s_blocksize)
        {
-               int lextoffset = *extoffset;
+               int lextoffset = epos->offset;
 
-               if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
+               if (udf_next_aext(dir, epos, eloc, elen, 1) !=
                        (EXT_RECORDED_ALLOCATED >> 30))
-               {
                        return NULL;
-               }
 
                block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 
@@ -184,7 +180,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
                if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
                        *offset = 0;
                else
-                       *extoffset = lextoffset;
+                       epos->offset = lextoffset;
 
                fibh->soffset -= dir->i_sb->s_blocksize;
                fibh->eoffset -= dir->i_sb->s_blocksize;
index 6b094250d805b26888b8825a48b8ee7ddfc0df68..a106acb58292383c2e456c81288bce0f2a624675 100644 (file)
@@ -51,8 +51,8 @@ static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
 static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
        long *, int *);
-static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
-       kernel_lb_addr, uint32_t, struct buffer_head *);
+static int8_t udf_insert_aext(struct inode *, struct extent_position,
+       kernel_lb_addr, uint32_t);
 static void udf_split_extents(struct inode *, int *, int, int,
        kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_prealloc_extents(struct inode *, int, int,
@@ -61,7 +61,7 @@ static void udf_merge_extents(struct inode *,
         kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_update_extents(struct inode *,
        kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
-       kernel_lb_addr, uint32_t, struct buffer_head **);
+       struct extent_position *);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /*
@@ -194,10 +194,11 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
 struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
 {
        int newblock;
-       struct buffer_head *sbh = NULL, *dbh = NULL;
-       kernel_lb_addr bloc, eloc;
-       uint32_t elen, extoffset;
+       struct buffer_head *dbh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
        uint8_t alloctype;
+       struct extent_position epos;
 
        struct udf_fileident_bh sfibh, dfibh;
        loff_t f_pos = udf_ext0_offset(inode) >> 2;
@@ -237,13 +238,13 @@ 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;
-       sbh = sfibh.sbh = sfibh.ebh = NULL;
+       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);
+               sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
                if (!sfi)
                {
                        udf_release_data(dbh);
@@ -266,16 +267,17 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 
        memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
        UDF_I_LENALLOC(inode) = 0;
-       bloc = UDF_I_LOCATION(inode);
        eloc.logicalBlockNum = *block;
        eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
        elen = inode->i_size;
        UDF_I_LENEXTENTS(inode) = elen;
-       extoffset = udf_file_entry_alloc_offset(inode);
-       udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
+       epos.bh = NULL;
+       epos.block = UDF_I_LOCATION(inode);
+       epos.offset = udf_file_entry_alloc_offset(inode);
+       udf_add_aext(inode, &epos, eloc, elen, 0);
        /* UniqueID stuff */
 
-       udf_release_data(sbh);
+       udf_release_data(epos.bh);
        mark_inode_dirty(inode);
        return dbh;
 }
@@ -357,12 +359,12 @@ udf_getblk(struct inode *inode, long block, int create, int *err)
 static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
        int *err, long *phys, int *new)
 {
-       struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
+       struct buffer_head *result = NULL;
        kernel_long_ad laarr[EXTENT_MERGE_SIZE];
-       uint32_t pextoffset = 0, cextoffset = 0, nextoffset = 0;
+       struct extent_position prev_epos, cur_epos, next_epos;
        int count = 0, startnum = 0, endnum = 0;
        uint32_t elen = 0;
-       kernel_lb_addr eloc, pbloc, cbloc, nbloc;
+       kernel_lb_addr eloc;
        int c = 1;
        loff_t lbcount = 0, b_off = 0;
        uint32_t newblocknum, newblock;
@@ -371,37 +373,39 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
        int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
        char lastblock = 0;
 
-       pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
+       prev_epos.offset = udf_file_entry_alloc_offset(inode);
+       prev_epos.block = UDF_I_LOCATION(inode);
+       prev_epos.bh = NULL;
+       cur_epos = next_epos = prev_epos;
        b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
-       pbloc = cbloc = nbloc = UDF_I_LOCATION(inode);
 
        /* find the extent which contains the block we are looking for.
        alternate between laarr[0] and laarr[1] for locations of the
        current extent, and the previous extent */
        do
        {
-               if (pbh != cbh)
+               if (prev_epos.bh != cur_epos.bh)
                {
-                       udf_release_data(pbh);
-                       atomic_inc(&cbh->b_count);
-                       pbh = cbh;
+                       udf_release_data(prev_epos.bh);
+                       atomic_inc(&cur_epos.bh->b_count);
+                       prev_epos.bh = cur_epos.bh;
                }
-               if (cbh != nbh)
+               if (cur_epos.bh != next_epos.bh)
                {
-                       udf_release_data(cbh);
-                       atomic_inc(&nbh->b_count);
-                       cbh = nbh;
+                       udf_release_data(cur_epos.bh);
+                       atomic_inc(&next_epos.bh->b_count);
+                       cur_epos.bh = next_epos.bh;
                }
 
                lbcount += elen;
 
-               pbloc = cbloc;
-               cbloc = nbloc;
+               prev_epos.block = cur_epos.block;
+               cur_epos.block = next_epos.block;
 
-               pextoffset = cextoffset;
-               cextoffset = nextoffset;
+               prev_epos.offset = cur_epos.offset;
+               cur_epos.offset = next_epos.offset;
 
-               if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) == -1)
+               if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 1)) == -1)
                        break;
 
                c = !c;
@@ -430,11 +434,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
                        elen = EXT_RECORDED_ALLOCATED |
                                ((elen + inode->i_sb->s_blocksize - 1) &
                                ~(inode->i_sb->s_blocksize - 1));
-                       etype = udf_write_aext(inode, nbloc, &cextoffset, eloc, elen, nbh, 1);
+                       etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1);
                }
-               udf_release_data(pbh);
-               udf_release_data(cbh);
-               udf_release_data(nbh);
+               udf_release_data(prev_epos.bh);
+               udf_release_data(cur_epos.bh);
+               udf_release_data(next_epos.bh);
                newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
                *phys = newblock;
                return NULL;
@@ -477,7 +481,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
        /* if the current block is located in a extent, read the next extent */
        if (etype != -1)
        {
-               if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 0)) != -1)
+               if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1)
                {
                        laarr[c+1].extLength = (etype << 30) | elen;
                        laarr[c+1].extLocation = eloc;
@@ -488,8 +492,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
                else
                        lastblock = 1;
        }
-       udf_release_data(cbh);
-       udf_release_data(nbh);
+       udf_release_data(cur_epos.bh);
+       udf_release_data(next_epos.bh);
 
        /* if the current extent is not recorded but allocated, get the
                block in the extent corresponding to the requested block */
@@ -509,7 +513,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
                if (!(newblocknum = udf_new_block(inode->i_sb, inode,
                        UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
                {
-                       udf_release_data(pbh);
+                       udf_release_data(prev_epos.bh);
                        *err = -ENOSPC;
                        return NULL;
                }
@@ -532,9 +536,9 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
        /* write back the new extents, inserting new extents if the new number
        of extents is greater than the old number, and deleting extents if
        the new number of extents is less than the old number */
-       udf_update_extents(inode, laarr, startnum, endnum, pbloc, pextoffset, &pbh);
+       udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
 
-       udf_release_data(pbh);
+       udf_release_data(prev_epos.bh);
 
        if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
                UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
@@ -796,7 +800,7 @@ static void udf_merge_extents(struct inode *inode,
 
 static void udf_update_extents(struct inode *inode,
        kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
-       kernel_lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
+       struct extent_position *epos)
 {
        int start = 0, i;
        kernel_lb_addr tmploc;
@@ -805,28 +809,26 @@ static void udf_update_extents(struct inode *inode,
        if (startnum > endnum)
        {
                for (i=0; i<(startnum-endnum); i++)
-               {
-                       udf_delete_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
-                               laarr[i].extLength, *pbh);
-               }
+                       udf_delete_aext(inode, *epos, laarr[i].extLocation,
+                               laarr[i].extLength);
        }
        else if (startnum < endnum)
        {
                for (i=0; i<(endnum-startnum); i++)
                {
-                       udf_insert_aext(inode, pbloc, pextoffset, laarr[i].extLocation,
-                               laarr[i].extLength, *pbh);
-                       udf_next_aext(inode, &pbloc, &pextoffset, &laarr[i].extLocation,
-                               &laarr[i].extLength, pbh, 1);
+                       udf_insert_aext(inode, *epos, laarr[i].extLocation,
+                               laarr[i].extLength);
+                       udf_next_aext(inode, epos, &laarr[i].extLocation,
+                               &laarr[i].extLength, 1);
                        start ++;
                }
        }
 
        for (i=start; i<endnum; i++)
        {
-               udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0);
-               udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation,
-                       laarr[i].extLength, *pbh, 1);
+               udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
+               udf_write_aext(inode, epos, laarr[i].extLocation,
+                       laarr[i].extLength, 1);
        }
 }
 
@@ -1557,8 +1559,8 @@ udf_iget(struct super_block *sb, kernel_lb_addr ino)
        return NULL;
 }
 
-int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
-       kernel_lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
+int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
+       kernel_lb_addr eloc, uint32_t elen, int inc)
 {
        int adsize;
        short_ad *sad = NULL;
@@ -1567,10 +1569,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
        int8_t etype;
        uint8_t *ptr;
 
-       if (!*bh)
-               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+       if (!epos->bh)
+               ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
        else
-               ptr = (*bh)->b_data + *extoffset;
+               ptr = epos->bh->b_data + epos->offset;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
                adsize = sizeof(short_ad);
@@ -1579,20 +1581,20 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
        else
                return -1;
 
-       if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)
+       if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize)
        {
                char *sptr, *dptr;
                struct buffer_head *nbh;
                int err, loffset;
-               kernel_lb_addr obloc = *bloc;
+               kernel_lb_addr obloc = epos->block;
 
-               if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
+               if (!(epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL,
                        obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
                {
                        return -1;
                }
                if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
-                       *bloc, 0))))
+                       epos->block, 0))))
                {
                        return -1;
                }
@@ -1605,25 +1607,25 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                aed = (struct allocExtDesc *)(nbh->b_data);
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
                        aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
-               if (*extoffset + adsize > inode->i_sb->s_blocksize)
+               if (epos->offset + adsize > inode->i_sb->s_blocksize)
                {
-                       loffset = *extoffset;
+                       loffset = epos->offset;
                        aed->lengthAllocDescs = cpu_to_le32(adsize);
                        sptr = ptr - adsize;
                        dptr = nbh->b_data + sizeof(struct allocExtDesc);
                        memcpy(dptr, sptr, adsize);
-                       *extoffset = sizeof(struct allocExtDesc) + adsize;
+                       epos->offset = sizeof(struct allocExtDesc) + adsize;
                }
                else
                {
-                       loffset = *extoffset + adsize;
+                       loffset = epos->offset + adsize;
                        aed->lengthAllocDescs = cpu_to_le32(0);
                        sptr = ptr;
-                       *extoffset = sizeof(struct allocExtDesc);
+                       epos->offset = sizeof(struct allocExtDesc);
 
-                       if (*bh)
+                       if (epos->bh)
                        {
-                               aed = (struct allocExtDesc *)(*bh)->b_data;
+                               aed = (struct allocExtDesc *)epos->bh->b_data;
                                aed->lengthAllocDescs =
                                        cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
                        }
@@ -1635,10 +1637,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                }
                if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
                        udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
-                               bloc->logicalBlockNum, sizeof(tag));
+                               epos->block.logicalBlockNum, sizeof(tag));
                else
                        udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
-                               bloc->logicalBlockNum, sizeof(tag));
+                               epos->block.logicalBlockNum, sizeof(tag));
                switch (UDF_I_ALLOCTYPE(inode))
                {
                        case ICBTAG_FLAG_AD_SHORT:
@@ -1647,7 +1649,7 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                                sad->extLength = cpu_to_le32(
                                        EXT_NEXT_EXTENT_ALLOCDECS |
                                        inode->i_sb->s_blocksize);
-                               sad->extPosition = cpu_to_le32(bloc->logicalBlockNum);
+                               sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum);
                                break;
                        }
                        case ICBTAG_FLAG_AD_LONG:
@@ -1656,60 +1658,57 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
                                lad->extLength = cpu_to_le32(
                                        EXT_NEXT_EXTENT_ALLOCDECS |
                                        inode->i_sb->s_blocksize);
-                               lad->extLocation = cpu_to_lelb(*bloc);
+                               lad->extLocation = cpu_to_lelb(epos->block);
                                memset(lad->impUse, 0x00, sizeof(lad->impUse));
                                break;
                        }
                }
-               if (*bh)
+               if (epos->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);
+                               udf_update_tag(epos->bh->b_data, loffset);
                        else
-                               udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(*bh, inode);
-                       udf_release_data(*bh);
+                               udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(epos->bh, inode);
+                       udf_release_data(epos->bh);
                }
                else
                        mark_inode_dirty(inode);
-               *bh = nbh;
+               epos->bh = nbh;
        }
 
-       etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
+       etype = udf_write_aext(inode, epos, eloc, elen, inc);
 
-       if (!*bh)
+       if (!epos->bh)
        {
                UDF_I_LENALLOC(inode) += adsize;
                mark_inode_dirty(inode);
        }
        else
        {
-               aed = (struct allocExtDesc *)(*bh)->b_data;
+               aed = (struct allocExtDesc *)epos->bh->b_data;
                aed->lengthAllocDescs =
                        cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                       udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize));
+                       udf_update_tag(epos->bh->b_data, epos->offset + (inc ? 0 : adsize));
                else
-                       udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
-               mark_buffer_dirty_inode(*bh, inode);
+                       udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
+               mark_buffer_dirty_inode(epos->bh, inode);
        }
 
        return etype;
 }
 
-int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
-    kernel_lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
+int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
+    kernel_lb_addr eloc, uint32_t elen, int inc)
 {
        int adsize;
        uint8_t *ptr;
 
-       if (!bh)
-               ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
+       if (!epos->bh)
+               ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
        else
-       {
-               ptr = bh->b_data + *extoffset;
-               atomic_inc(&bh->b_count);
-       }
+               ptr = epos->bh->b_data + epos->offset;
 
        switch (UDF_I_ALLOCTYPE(inode))
        {
@@ -1734,40 +1733,39 @@ int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
                        return -1;
        }
 
-       if (bh)
+       if (epos->bh)
        {
                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
                {
-                       struct allocExtDesc *aed = (struct allocExtDesc *)(bh)->b_data;
-                       udf_update_tag((bh)->b_data,
+                       struct allocExtDesc *aed = (struct allocExtDesc *)epos->bh->b_data;
+                       udf_update_tag(epos->bh->b_data,
                                le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
                }
-               mark_buffer_dirty_inode(bh, inode);
-               udf_release_data(bh);
+               mark_buffer_dirty_inode(epos->bh, inode);
        }
        else
                mark_inode_dirty(inode);
 
        if (inc)
-               *extoffset += adsize;
+               epos->offset += adsize;
        return (elen >> 30);
 }
 
-int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
+       kernel_lb_addr *eloc, uint32_t *elen, int inc)
 {
        int8_t etype;
 
-       while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
+       while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
                (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
        {
-               *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))))
+               epos->block = *eloc;
+               epos->offset = sizeof(struct allocExtDesc);
+               udf_release_data(epos->bh);
+               if (!(epos->bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0))))
                {
                        udf_debug("reading block %d failed!\n",
-                               udf_get_lb_pblock(inode->i_sb, *bloc, 0));
+                               udf_get_lb_pblock(inode->i_sb, epos->block, 0));
                        return -1;
                }
        }
@@ -1775,26 +1773,26 @@ int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
        return etype;
 }
 
-int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_current_aext(struct inode *inode, struct extent_position *epos,
+       kernel_lb_addr *eloc, uint32_t *elen, int inc)
 {
        int alen;
        int8_t etype;
        uint8_t *ptr;
 
-       if (!*bh)
+       if (!epos->bh)
        {
-               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);
+               if (!epos->offset)
+                       epos->offset = udf_file_entry_alloc_offset(inode);
+               ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
                alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
        }
        else
        {
-               if (!(*extoffset))
-                       *extoffset = sizeof(struct allocExtDesc);
-               ptr = (*bh)->b_data + *extoffset;
-               alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
+               if (!epos->offset)
+                       epos->offset = sizeof(struct allocExtDesc);
+               ptr = epos->bh->b_data + epos->offset;
+               alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->lengthAllocDescs);
        }
 
        switch (UDF_I_ALLOCTYPE(inode))
@@ -1803,7 +1801,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
                {
                        short_ad *sad;
 
-                       if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
+                       if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc)))
                                return -1;
 
                        etype = le32_to_cpu(sad->extLength) >> 30;
@@ -1816,7 +1814,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
                {
                        long_ad *lad;
 
-                       if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
+                       if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, inc)))
                                return -1;
 
                        etype = le32_to_cpu(lad->extLength) >> 30;
@@ -1835,41 +1833,40 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
 }
 
 static int8_t
-udf_insert_aext(struct inode *inode, kernel_lb_addr bloc, int extoffset,
-               kernel_lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
+udf_insert_aext(struct inode *inode, struct extent_position epos,
+               kernel_lb_addr neloc, uint32_t nelen)
 {
        kernel_lb_addr oeloc;
        uint32_t oelen;
        int8_t etype;
 
-       if (bh)
-               atomic_inc(&bh->b_count);
+       if (epos.bh)
+               atomic_inc(&epos.bh->b_count);
 
-       while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
+       while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1)
        {
-               udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
+               udf_write_aext(inode, &epos, neloc, nelen, 1);
 
                neloc = oeloc;
                nelen = (etype << 30) | oelen;
        }
-       udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
-       udf_release_data(bh);
+       udf_add_aext(inode, &epos, neloc, nelen, 1);
+       udf_release_data(epos.bh);
        return (nelen >> 30);
 }
 
-int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset,
-       kernel_lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
+int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
+       kernel_lb_addr eloc, uint32_t elen)
 {
-       struct buffer_head *obh;
-       kernel_lb_addr obloc;
-       int oextoffset, adsize;
+       struct extent_position oepos;
+       int adsize;
        int8_t etype;
        struct allocExtDesc *aed;
 
-       if (nbh)
+       if (epos.bh)
        {
-               atomic_inc(&nbh->b_count);
-               atomic_inc(&nbh->b_count);
+               atomic_inc(&epos.bh->b_count);
+               atomic_inc(&epos.bh->b_count);
        }
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -1879,78 +1876,75 @@ int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset
        else
                adsize = 0;
 
-       obh = nbh;
-       obloc = nbloc;
-       oextoffset = nextoffset;
-
-       if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)
+       oepos = epos;
+       if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)
                return -1;
 
-       while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
+       while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
        {
-               udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
-               if (obh != nbh)
+               udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1);
+               if (oepos.bh != epos.bh)
                {
-                       obloc = nbloc;
-                       udf_release_data(obh);
-                       atomic_inc(&nbh->b_count);
-                       obh = nbh;
-                       oextoffset = nextoffset - adsize;
+                       oepos.block = epos.block;
+                       udf_release_data(oepos.bh);
+                       atomic_inc(&epos.bh->b_count);
+                       oepos.bh = epos.bh;
+                       oepos.offset = epos.offset - adsize;
                }
        }
        memset(&eloc, 0x00, sizeof(kernel_lb_addr));
        elen = 0;
 
-       if (nbh != obh)
+       if (epos.bh != oepos.bh)
        {
-               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 (!obh)
+               udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1);
+               udf_write_aext(inode, &oepos, eloc, elen, 1);
+               udf_write_aext(inode, &oepos, eloc, elen, 1);
+               if (!oepos.bh)
                {
                        UDF_I_LENALLOC(inode) -= (adsize * 2);
                        mark_inode_dirty(inode);
                }
                else
                {
-                       aed = (struct allocExtDesc *)(obh)->b_data;
+                       aed = (struct allocExtDesc *)oepos.bh->b_data;
                        aed->lengthAllocDescs =
                                cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag((obh)->b_data, oextoffset - (2*adsize));
+                               udf_update_tag(oepos.bh->b_data, oepos.offset - (2*adsize));
                        else
-                               udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(obh, inode);
+                               udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(oepos.bh, inode);
                }
        }
        else
        {
-               udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
-               if (!obh)
+               udf_write_aext(inode, &oepos, eloc, elen, 1);
+               if (!oepos.bh)
                {
                        UDF_I_LENALLOC(inode) -= adsize;
                        mark_inode_dirty(inode);
                }
                else
                {
-                       aed = (struct allocExtDesc *)(obh)->b_data;
+                       aed = (struct allocExtDesc *)oepos.bh->b_data;
                        aed->lengthAllocDescs =
                                cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag((obh)->b_data, oextoffset - adsize);
+                               udf_update_tag(oepos.bh->b_data, epos.offset - adsize);
                        else
-                               udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(obh, inode);
+                               udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(oepos.bh, inode);
                }
        }
        
-       udf_release_data(nbh);
-       udf_release_data(obh);
+       udf_release_data(epos.bh);
+       udf_release_data(oepos.bh);
        return (elen >> 30);
 }
 
-int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uint32_t *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset, struct buffer_head **bh)
+int8_t inode_bmap(struct inode *inode, sector_t block, struct extent_position *pos,
+       kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset)
 {
        loff_t lbcount = 0, bcount = (loff_t)block << inode->i_sb->s_blocksize_bits;
        int8_t etype;
@@ -1961,13 +1955,14 @@ int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uin
                return -1;
        }
 
-       *extoffset = 0;
+       pos->offset = 0;
+       pos->block = UDF_I_LOCATION(inode);
+       pos->bh = NULL;
        *elen = 0;
-       *bloc = UDF_I_LOCATION(inode);
 
        do
        {
-               if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
+               if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1)
                {
                        *offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
                        UDF_I_LENEXTENTS(inode) = lbcount;
@@ -1983,21 +1978,21 @@ int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uin
 
 long udf_block_map(struct inode *inode, sector_t block)
 {
-       kernel_lb_addr eloc, bloc;
-       uint32_t extoffset, elen;
+       kernel_lb_addr eloc;
+       uint32_t elen;
        sector_t offset;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos = { NULL, 0, { 0, 0}};
        int ret;
 
        lock_kernel();
 
-       if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
+       if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
                ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
        else
                ret = 0;
 
        unlock_kernel();
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
                return udf_fixed_to_variable(ret);
index b9859ac169c4cd2bce231d3913e3169c470f2226..f85ad13b3dffdad93bb8a8d14ecfa891980a911e 100644 (file)
@@ -155,10 +155,10 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        uint8_t lfi;
        uint16_t liu;
        loff_t size;
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen;
+       kernel_lb_addr eloc;
+       uint32_t elen;
        sector_t offset;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos = { NULL, 0, { 0, 0}};
 
        size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        f_pos = (udf_ext0_offset(dir) >> 2);
@@ -167,41 +167,41 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        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))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return NULL;
                }
        }
        else
        {
-               udf_release_data(bh);
+               udf_release_data(epos.bh);
                return NULL;
        }
 
        while ( (f_pos < size) )
        {
-               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh->sbh != fibh->ebh)
                                udf_release_data(fibh->ebh);
                        udf_release_data(fibh->sbh);
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return NULL;
                }
 
@@ -247,7 +247,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
                {
                        if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
                        {
-                               udf_release_data(bh);
+                               udf_release_data(epos.bh);
                                return fi;
                        }
                }
@@ -255,7 +255,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
        if (fibh->sbh != fibh->ebh)
                udf_release_data(fibh->ebh);
        udf_release_data(fibh->sbh);
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
        return NULL;
 }
 
@@ -353,10 +353,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        uint8_t lfi;
        uint16_t liu;
        int block;
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen;
+       kernel_lb_addr eloc;
+       uint32_t elen;
        sector_t offset;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos = { NULL, 0, { 0, 0 }};
 
        sb = dir->i_sb;
 
@@ -385,22 +385,22 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        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))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        *err = -EIO;
                        return NULL;
                }
@@ -418,14 +418,14 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 
        while ( (f_pos < size) )
        {
-               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh->sbh != fibh->ebh)
                                udf_release_data(fibh->ebh);
                        udf_release_data(fibh->sbh);
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        *err = -EIO;
                        return NULL;
                }
@@ -455,7 +455,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                {
                        if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
                        {
-                               udf_release_data(bh);
+                               udf_release_data(epos.bh);
                                cfi->descTag.tagSerialNum = cpu_to_le16(1);
                                cfi->fileVersionNum = cpu_to_le16(1);
                                cfi->fileCharacteristics = 0;
@@ -480,7 +480,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
                        if (fibh->sbh != fibh->ebh)
                                udf_release_data(fibh->ebh);
                        udf_release_data(fibh->sbh);
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        *err = -EEXIST;
                        return NULL;
                }
@@ -492,8 +492,8 @@ add:
        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
                sb->s_blocksize - fibh->eoffset < nfidlen)
        {
-               udf_release_data(bh);
-               bh = NULL;
+               udf_release_data(epos.bh);
+               epos.bh = NULL;
                fibh->soffset -= udf_ext0_offset(dir);
                fibh->eoffset -= udf_ext0_offset(dir);
                f_pos -= (udf_ext0_offset(dir) >> 2);
@@ -502,15 +502,15 @@ add:
                udf_release_data(fibh->sbh);
                if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
                        return NULL;
-               bloc = UDF_I_LOCATION(dir);
+               epos.block = UDF_I_LOCATION(dir);
                eloc.logicalBlockNum = block;
                eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
                elen = dir->i_sb->s_blocksize;
-               extoffset = udf_file_entry_alloc_offset(dir);
+               epos.offset = udf_file_entry_alloc_offset(dir);
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                       extoffset += sizeof(short_ad);
+                       epos.offset += sizeof(short_ad);
                else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                       extoffset += sizeof(long_ad);
+                       epos.offset += sizeof(long_ad);
        }
 
        if (sb->s_blocksize - fibh->eoffset >= nfidlen)
@@ -550,14 +550,14 @@ add:
 
                if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
                {
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        udf_release_data(fibh->sbh);
                        return NULL;
                }
 
                if (!(fibh->soffset))
                {
-                       if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==
+                       if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
                                (EXT_RECORDED_ALLOCATED >> 30))
                        {
                                block = eloc.logicalBlockNum + ((elen - 1) >>
@@ -587,7 +587,7 @@ add:
        cfi->lengthOfImpUse = cpu_to_le16(0);
        if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
        {
-               udf_release_data(bh);
+               udf_release_data(epos.bh);
                dir->i_size += nfidlen;
                if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
                        UDF_I_LENALLOC(dir) += nfidlen;
@@ -596,7 +596,7 @@ add:
        }
        else
        {
-               udf_release_data(bh);
+               udf_release_data(epos.bh);
                if (fibh->sbh != fibh->ebh)
                        udf_release_data(fibh->ebh);
                udf_release_data(fibh->sbh);
@@ -781,10 +781,10 @@ static int empty_dir(struct inode *dir)
        loff_t f_pos;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        int block;
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset, elen;
+       kernel_lb_addr eloc;
+       uint32_t elen;
        sector_t offset;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos = { NULL, 0, { 0, 0}};
 
        f_pos = (udf_ext0_offset(dir) >> 2);
 
@@ -793,42 +793,42 @@ static int empty_dir(struct inode *dir)
        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))
+               &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))
        {
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
-                               extoffset -= sizeof(short_ad);
+                               epos.offset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-                               extoffset -= sizeof(long_ad);
+                               epos.offset -= sizeof(long_ad);
                }
                else
                        offset = 0;
 
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
                {
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return 0;
                }
        }
        else
        {
-               udf_release_data(bh);
+               udf_release_data(epos.bh);
                return 0;
        }
 
 
        while ( (f_pos < size) )
        {
-               fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+               fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc, &elen, &offset);
 
                if (!fi)
                {
                        if (fibh.sbh != fibh.ebh)
                                udf_release_data(fibh.ebh);
                        udf_release_data(fibh.sbh);
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return 0;
                }
 
@@ -837,14 +837,14 @@ static int empty_dir(struct inode *dir)
                        if (fibh.sbh != fibh.ebh)
                                udf_release_data(fibh.ebh);
                        udf_release_data(fibh.sbh);
-                       udf_release_data(bh);
+                       udf_release_data(epos.bh);
                        return 0;
                }
        }
        if (fibh.sbh != fibh.ebh)
                udf_release_data(fibh.ebh);
        udf_release_data(fibh.sbh);
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
        return 1;
 }
 
@@ -941,7 +941,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
        struct pathComponent *pc;
        char *compstart;
        struct udf_fileident_bh fibh;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos = { NULL,  0, {0, 0}};
        int eoffset, elen = 0;
        struct fileIdentDesc *fi;
        struct fileIdentDesc cfi;
@@ -961,33 +961,33 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 
        if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
        {
-               struct buffer_head *bh = NULL;
-               kernel_lb_addr bloc, eloc;
-               uint32_t elen, extoffset;
+               kernel_lb_addr eloc;
+               uint32_t elen;
 
                block = udf_new_block(inode->i_sb, inode,
                        UDF_I_LOCATION(inode).partitionReferenceNum,
                        UDF_I_LOCATION(inode).logicalBlockNum, &err);
                if (!block)
                        goto out_no_entry;
-               bloc = UDF_I_LOCATION(inode);
+               epos.block = UDF_I_LOCATION(inode);
+               epos.offset = udf_file_entry_alloc_offset(inode);
+               epos.bh = NULL;
                eloc.logicalBlockNum = block;
                eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
                elen = inode->i_sb->s_blocksize;
                UDF_I_LENEXTENTS(inode) = elen;
-               extoffset = udf_file_entry_alloc_offset(inode);
-               udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);
-               udf_release_data(bh);
+               udf_add_aext(inode, &epos, eloc, elen, 0);
+               udf_release_data(epos.bh);
 
                block = udf_get_pblock(inode->i_sb, block,
                        UDF_I_LOCATION(inode).partitionReferenceNum, 0);
-               bh = udf_tread(inode->i_sb, block);
-               lock_buffer(bh);
-               memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
-               set_buffer_uptodate(bh);
-               unlock_buffer(bh);
-               mark_buffer_dirty_inode(bh, inode);
-               ea = bh->b_data + udf_ext0_offset(inode);
+               epos.bh = udf_tread(inode->i_sb, block);
+               lock_buffer(epos.bh);
+               memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
+               set_buffer_uptodate(epos.bh);
+               unlock_buffer(epos.bh);
+               mark_buffer_dirty_inode(epos.bh, inode);
+               ea = epos.bh->b_data + udf_ext0_offset(inode);
        }
        else
                ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
@@ -1060,7 +1060,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
                }
        }
 
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
        inode->i_size = elen;
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
                UDF_I_LENALLOC(inode) = inode->i_size;
index 023b304fdd996a85415f79226dd362d993145d7c..dafa05f0110b97c5833f08ee5678eab8be437736 100644 (file)
@@ -1883,21 +1883,20 @@ static unsigned int
 udf_count_free_table(struct super_block *sb, struct inode * table)
 {
        unsigned int accum = 0;
-       uint32_t extoffset, elen;
-       kernel_lb_addr bloc, eloc;
+       uint32_t elen;
+       kernel_lb_addr eloc;
        int8_t etype;
-       struct buffer_head *bh = NULL;
+       struct extent_position epos;
 
        lock_kernel();
 
-       bloc = UDF_I_LOCATION(table);
-       extoffset = sizeof(struct unallocSpaceEntry);
+       epos.block = UDF_I_LOCATION(table);
+       epos.offset = sizeof(struct unallocSpaceEntry);
+       epos.bh = NULL;
 
-       while ((etype = udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
-       {
+       while ((etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
                accum += (elen >> table->i_sb->s_blocksize_bits);
-       }
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 
        unlock_kernel();
 
index ebd0f37f8b1693f95d7ee19d8cabafa7acdf29cf..84191801f4c917ce1b25d712a289f259e9f41dcb 100644 (file)
@@ -28,8 +28,8 @@
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffset,
-       kernel_lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
+static void extent_trunc(struct inode * inode, struct extent_position *epos,
+       kernel_lb_addr eloc, int8_t etype, uint32_t elen, uint32_t nelen)
 {
        kernel_lb_addr neloc = { 0, 0 };
        int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
@@ -49,7 +49,7 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
 
        if (elen != nelen)
        {
-               udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
+               udf_write_aext(inode, epos, neloc, nelen, 0);
                if (last_block - first_block > 0)
                {
                        if (etype == (EXT_RECORDED_ALLOCATED >> 30))
@@ -63,18 +63,16 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
 
 void udf_discard_prealloc(struct inode * inode)
 {
-       kernel_lb_addr bloc, eloc;
-       uint32_t extoffset = 0, elen, nelen;
+       struct extent_position epos = { NULL, 0, {0, 0}};
+       kernel_lb_addr eloc;
+       uint32_t elen, nelen;
        uint64_t lbcount = 0;
        int8_t etype = -1, netype;
-       struct buffer_head *bh = NULL;
        int adsize;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
                inode->i_size == UDF_I_LENEXTENTS(inode))
-       {
                return;
-       }
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
                adsize = sizeof(short_ad);
@@ -83,53 +81,55 @@ void udf_discard_prealloc(struct inode * inode)
        else
                adsize = 0;
 
-       bloc = UDF_I_LOCATION(inode);
+       epos.block = UDF_I_LOCATION(inode);
 
-       while ((netype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
+       /* Find the last extent in the file */
+       while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
        {
                etype = netype;
                lbcount += elen;
                if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
                {
                        nelen = elen - (lbcount - inode->i_size);
-                       extent_trunc(inode, bloc, extoffset-adsize, eloc, etype, elen, bh, nelen);
+                       epos.offset -= adsize;
+                       extent_trunc(inode, &epos, eloc, etype, elen, nelen);
+                       epos.offset += adsize;
                        lbcount = inode->i_size;
                }
        }
-       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
-       {
-               extoffset -= adsize;
+       if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
+               epos.offset -= adsize;
                lbcount -= elen;
-               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
-               if (!bh)
+               extent_trunc(inode, &epos, eloc, etype, elen, 0);
+               if (!epos.bh)
                {
-                       UDF_I_LENALLOC(inode) = extoffset - udf_file_entry_alloc_offset(inode);
+                       UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode);
                        mark_inode_dirty(inode);
                }
                else
                {
-                       struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
-                       aed->lengthAllocDescs = cpu_to_le32(extoffset - sizeof(struct allocExtDesc));
+                       struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
+                       aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc));
                        if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                               udf_update_tag(bh->b_data, extoffset);
+                               udf_update_tag(epos.bh->b_data, epos.offset);
                        else
-                               udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-                       mark_buffer_dirty_inode(bh, inode);
+                               udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+                       mark_buffer_dirty_inode(epos.bh, inode);
                }
        }
        UDF_I_LENEXTENTS(inode) = lbcount;
 
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 }
 
 void udf_truncate_extents(struct inode * inode)
 {
-       kernel_lb_addr bloc, eloc, neloc = { 0, 0 };
-       uint32_t extoffset, elen, nelen = 0, lelen = 0, lenalloc;
+       struct extent_position epos;
+       kernel_lb_addr eloc, neloc = { 0, 0 };
+       uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
        int8_t etype;
        sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset;
        loff_t byte_offset;
-       struct buffer_head *bh = NULL;
        int adsize;
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -137,102 +137,98 @@ void udf_truncate_extents(struct inode * inode)
        else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
                adsize = sizeof(long_ad);
        else
-               adsize = 0;
+               BUG();
 
-       etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+       etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
        byte_offset = (offset << inode->i_sb->s_blocksize_bits) + (inode->i_size & (inode->i_sb->s_blocksize-1));
        if (etype != -1)
        {
-               extoffset -= adsize;
-               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, byte_offset);
-               extoffset += adsize;
-
+               epos.offset -= adsize;
+               extent_trunc(inode, &epos, eloc, etype, elen, byte_offset);
+               epos.offset += adsize;
                if (byte_offset)
-                       lenalloc = extoffset;
+                       lenalloc = epos.offset;
                else
-                       lenalloc = extoffset - adsize;
+                       lenalloc = epos.offset - adsize;
 
-               if (!bh)
+               if (!epos.bh)
                        lenalloc -= udf_file_entry_alloc_offset(inode);
                else
                        lenalloc -= sizeof(struct allocExtDesc);
 
-               while ((etype = udf_current_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0)) != -1)
+               while ((etype = udf_current_aext(inode, &epos, &eloc, &elen, 0)) != -1)
                {
                        if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
                        {
-                               udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
-                               extoffset = 0;
-                               if (lelen)
+                               udf_write_aext(inode, &epos, neloc, nelen, 0);
+                               if (indirect_ext_len)
                                {
-                                       if (!bh)
+                                       /* We managed to free all extents in the
+                                        * indirect extent - free it too */
+                                       if (!epos.bh)
                                                BUG();
-                                       else
-                                               memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
-                                       udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
+                                       udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len);
                                }
                                else
                                {
-                                       if (!bh)
+                                       if (!epos.bh)
                                        {
                                                UDF_I_LENALLOC(inode) = lenalloc;
                                                mark_inode_dirty(inode);
                                        }
                                        else
                                        {
-                                               struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+                                               struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
                                                aed->lengthAllocDescs = cpu_to_le32(lenalloc);
                                                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                                                       udf_update_tag(bh->b_data, lenalloc +
+                                                       udf_update_tag(epos.bh->b_data, lenalloc +
                                                                sizeof(struct allocExtDesc));
                                                else
-                                                       udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-                                               mark_buffer_dirty_inode(bh, inode);
+                                                       udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+                                               mark_buffer_dirty_inode(epos.bh, inode);
                                        }
                                }
-
-                               udf_release_data(bh);
-                               extoffset = sizeof(struct allocExtDesc);
-                               bloc = eloc;
-                               bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
+                               brelse(epos.bh);
+                               epos.offset = sizeof(struct allocExtDesc);
+                               epos.block = eloc;
+                               epos.bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, eloc, 0));
                                if (elen)
-                                       lelen = (elen + inode->i_sb->s_blocksize - 1) >>
+                                       indirect_ext_len = (elen +
+                                               inode->i_sb->s_blocksize - 1) >>
                                                inode->i_sb->s_blocksize_bits;
                                else
-                                       lelen = 1;
+                                       indirect_ext_len = 1;
                        }
                        else
                        {
-                               extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0);
-                               extoffset += adsize;
+                               extent_trunc(inode, &epos, eloc, etype, elen, 0);
+                               epos.offset += adsize;
                        }
                }
 
-               if (lelen)
+               if (indirect_ext_len)
                {
-                       if (!bh)
+                       if (!epos.bh)
                                BUG();
-                       else
-                               memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
-                       udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
+                       udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len);
                }
                else
                {
-                       if (!bh)
+                       if (!epos.bh)
                        {
                                UDF_I_LENALLOC(inode) = lenalloc;
                                mark_inode_dirty(inode);
                        }
                        else
                        {
-                               struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+                               struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
                                aed->lengthAllocDescs = cpu_to_le32(lenalloc);
                                if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
-                                       udf_update_tag(bh->b_data, lenalloc +
+                                       udf_update_tag(epos.bh->b_data, lenalloc +
                                                sizeof(struct allocExtDesc));
                                else
-                                       udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-                               mark_buffer_dirty_inode(bh, inode);
+                                       udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+                               mark_buffer_dirty_inode(epos.bh, inode);
                        }
                }
        }
@@ -245,50 +241,51 @@ void udf_truncate_extents(struct inode * inode)
                         *  no extent above inode->i_size => truncate is
                         *  extending the file by 'offset'.
                         */
-                       if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
-                           (bh && extoffset == sizeof(struct allocExtDesc))) {
+                       if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
+                           (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
                                /* File has no extents at all! */
                                memset(&eloc, 0x00, sizeof(kernel_lb_addr));
                                elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
-                               udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
+                               udf_add_aext(inode, &epos, eloc, elen, 1);
                        }
                        else {
-                               extoffset -= adsize;
-                               etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
+                               epos.offset -= adsize;
+                               etype = udf_next_aext(inode, &epos, &eloc, &elen, 1);
+
                                if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
                                {
-                                       extoffset -= adsize;
+                                       epos.offset -= adsize;
                                        elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + byte_offset);
-                                       udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
+                                       udf_write_aext(inode, &epos, eloc, elen, 0);
                                }
                                else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
                                {
                                        kernel_lb_addr neloc = { 0, 0 };
-                                       extoffset -= adsize;
+                                       epos.offset -= adsize;
                                        nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
                                                ((elen + byte_offset + inode->i_sb->s_blocksize - 1) &
                                                ~(inode->i_sb->s_blocksize - 1));
-                                       udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
-                                       udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
+                                       udf_write_aext(inode, &epos, neloc, nelen, 1);
+                                       udf_add_aext(inode, &epos, eloc, (etype << 30) | elen, 1);
                                }
                                else
                                {
                                        if (elen & (inode->i_sb->s_blocksize - 1))
                                        {
-                                               extoffset -= adsize;
+                                               epos.offset -= adsize;
                                                elen = EXT_RECORDED_ALLOCATED |
                                                        ((elen + inode->i_sb->s_blocksize - 1) &
                                                        ~(inode->i_sb->s_blocksize - 1));
-                                               udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
+                                               udf_write_aext(inode, &epos, eloc, elen, 1);
                                        }
                                        memset(&eloc, 0x00, sizeof(kernel_lb_addr));
                                        elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
-                                       udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
+                                       udf_add_aext(inode, &epos, eloc, elen, 1);
                                }
                        }
                }
        }
        UDF_I_LENEXTENTS(inode) = inode->i_size;
 
-       udf_release_data(bh);
+       udf_release_data(epos.bh);
 }
index d3deb32b53eb8cf30174c7e2b9366c4da7f7d4a8..a89f454de1c2a1eef329e40b34031c36412e8908 100644 (file)
@@ -77,6 +77,13 @@ struct ustr
        uint8_t u_len;
 };
 
+struct extent_position {
+       struct buffer_head *bh;
+       uint32_t offset;
+       kernel_lb_addr block;
+};
+
+
 /* super.c */
 extern void udf_error(struct super_block *, const char *, const char *, ...);
 extern void udf_warning(struct super_block *, const char *, const char *, ...);
@@ -99,12 +106,12 @@ extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
 extern int udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, sector_t);
-extern int8_t inode_bmap(struct inode *, sector_t, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, sector_t *, struct buffer_head **);
-extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
-extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
-extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_next_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
-extern int8_t udf_current_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, kernel_lb_addr *, uint32_t *, sector_t *);
+extern int8_t udf_add_aext(struct inode *, struct extent_position *, kernel_lb_addr, uint32_t, int);
+extern int8_t udf_write_aext(struct inode *, struct extent_position *, kernel_lb_addr, uint32_t, int);
+extern int8_t udf_delete_aext(struct inode *, struct extent_position, kernel_lb_addr, uint32_t);
+extern int8_t udf_next_aext(struct inode *, struct extent_position *, kernel_lb_addr *, uint32_t *, int);
+extern int8_t udf_current_aext(struct inode *, struct extent_position *, kernel_lb_addr *, uint32_t *, int);
 
 /* misc.c */
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
@@ -151,7 +158,7 @@ extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_
 extern int udf_fsync_file(struct file *, struct dentry *, int);
 
 /* directory.c */
-extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, sector_t *, struct buffer_head **);
+extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, struct extent_position *, kernel_lb_addr *, uint32_t *, sector_t *);
 extern struct fileIdentDesc * udf_get_fileident(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);