fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / udf / inode.c
index d04cff2..c846155 100644 (file)
@@ -49,10 +49,10 @@ MODULE_LICENSE("GPL");
 static mode_t udf_convert_permissions(struct fileEntry *);
 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 *, long, int *,
+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);
 
 /*
@@ -132,7 +132,7 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block)
        return generic_block_bmap(mapping,block,udf_get_block);
 }
 
-struct address_space_operations udf_aops = {
+const struct address_space_operations udf_aops = {
        .readpage               = udf_readpage,
        .writepage              = udf_writepage,
        .sync_page              = block_sync_page,
@@ -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,16 +238,16 @@ 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);
+                       brelse(dbh);
                        return NULL;
                }
                UDF_I_ALLOCTYPE(inode) = alloctype;
@@ -258,7 +259,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
                        sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
                {
                        UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
-                       udf_release_data(dbh);
+                       brelse(dbh);
                        return NULL;
                }
        }
@@ -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);
+       brelse(epos.bh);
        mark_inode_dirty(inode);
        return dbh;
 }
@@ -312,12 +314,10 @@ static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head
        err = 0;
 
        bh = inode_getblk(inode, block, &err, &phys, &new);
-       if (bh)
-               BUG();
+       BUG_ON(bh);
        if (err)
                goto abort;
-       if (!phys)
-               BUG();
+       BUG_ON(!phys);
 
        if (new)
                set_buffer_new(bh_result);
@@ -356,53 +356,153 @@ udf_getblk(struct inode *inode, long block, int create, int *err)
        return NULL;
 }
 
-static struct buffer_head * inode_getblk(struct inode * inode, long block,
+/* Extend the file by 'blocks' blocks, return the number of extents added */
+int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
+       kernel_long_ad *last_ext, sector_t blocks)
+{
+       sector_t add;
+       int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
+       struct super_block *sb = inode->i_sb;
+       kernel_lb_addr prealloc_loc = {0, 0};
+       int prealloc_len = 0;
+
+       /* The previous extent is fake and we should not extend by anything
+        * - there's nothing to do... */
+       if (!blocks && fake)
+               return 0;
+       /* Round the last extent up to a multiple of block size */
+       if (last_ext->extLength & (sb->s_blocksize - 1)) {
+               last_ext->extLength =
+                       (last_ext->extLength & UDF_EXTENT_FLAG_MASK) |
+                       (((last_ext->extLength & UDF_EXTENT_LENGTH_MASK) +
+                               sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
+               UDF_I_LENEXTENTS(inode) =
+                       (UDF_I_LENEXTENTS(inode) + sb->s_blocksize - 1) &
+                               ~(sb->s_blocksize - 1);
+       }
+       /* Last extent are just preallocated blocks? */
+       if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_ALLOCATED) {
+               /* Save the extent so that we can reattach it to the end */
+               prealloc_loc = last_ext->extLocation;
+               prealloc_len = last_ext->extLength;
+               /* Mark the extent as a hole */
+               last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+                       (last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
+               last_ext->extLocation.logicalBlockNum = 0;
+                       last_ext->extLocation.partitionReferenceNum = 0;
+       }
+       /* Can we merge with the previous extent? */
+       if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_NOT_ALLOCATED) {
+               add = ((1<<30) - sb->s_blocksize - (last_ext->extLength &
+                       UDF_EXTENT_LENGTH_MASK)) >> sb->s_blocksize_bits;
+               if (add > blocks)
+                       add = blocks;
+               blocks -= add;
+               last_ext->extLength += add << sb->s_blocksize_bits;
+       }
+
+       if (fake) {
+               udf_add_aext(inode, last_pos, last_ext->extLocation,
+                       last_ext->extLength, 1);
+               count++;
+       }
+       else
+               udf_write_aext(inode, last_pos, last_ext->extLocation, last_ext->extLength, 1);
+       /* Managed to do everything necessary? */
+       if (!blocks)
+               goto out;
+
+       /* All further extents will be NOT_RECORDED_NOT_ALLOCATED */
+       last_ext->extLocation.logicalBlockNum = 0;
+               last_ext->extLocation.partitionReferenceNum = 0;
+       add = (1 << (30-sb->s_blocksize_bits)) - 1;
+       last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | (add << sb->s_blocksize_bits);
+       /* Create enough extents to cover the whole hole */
+       while (blocks > add) {
+               blocks -= add;
+               if (udf_add_aext(inode, last_pos, last_ext->extLocation,
+                       last_ext->extLength, 1) == -1)
+                       return -1;
+               count++;
+       }
+       if (blocks) {
+               last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+                       (blocks << sb->s_blocksize_bits);
+               if (udf_add_aext(inode, last_pos, last_ext->extLocation,
+                       last_ext->extLength, 1) == -1)
+                       return -1;
+               count++;
+       }
+out:
+       /* Do we have some preallocated blocks saved? */
+       if (prealloc_len) {
+               if (udf_add_aext(inode, last_pos, prealloc_loc, prealloc_len, 1) == -1)
+                       return -1;
+               last_ext->extLocation = prealloc_loc;
+               last_ext->extLength = prealloc_len;
+               count++;
+       }
+       /* last_pos should point to the last written extent... */
+       if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
+               last_pos->offset -= sizeof(short_ad);
+       else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
+               last_pos->offset -= sizeof(long_ad);
+       else
+               return -1;
+       return count;
+}
+
+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;
+       static sector_t last_block;
+       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;
-       uint64_t lbcount = 0, b_off = 0;
-       uint32_t newblocknum, newblock, offset = 0;
+       loff_t lbcount = 0, b_off = 0;
+       uint32_t newblocknum, newblock;
+       sector_t offset = 0;
        int8_t etype;
        int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
-       char lastblock = 0;
+       int lastblock = 0;
 
-       pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
-       b_off = (uint64_t)block << inode->i_sb->s_blocksize_bits;
-       pbloc = cbloc = nbloc = UDF_I_LOCATION(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;
 
        /* 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;
+                       brelse(prev_epos.bh);
+                       get_bh(cur_epos.bh);
+                       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;
+                       brelse(cur_epos.bh);
+                       get_bh(next_epos.bh);
+                       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;
@@ -420,6 +520,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
 
        b_off -= lbcount;
        offset = b_off >> inode->i_sb->s_blocksize_bits;
+       /* Move into indirect extent if we are at a pointer to it */
+       udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);
 
        /* if the extent is allocated and recorded, return the block
        if the extent is not a multiple of the blocksize, round up */
@@ -431,54 +533,77 @@ static struct buffer_head * inode_getblk(struct inode * inode, long 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);
+               brelse(prev_epos.bh);
+               brelse(cur_epos.bh);
+               brelse(next_epos.bh);
                newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
                *phys = newblock;
                return NULL;
        }
 
+       last_block = block;
+       /* Are we beyond EOF? */
        if (etype == -1)
        {
-               endnum = startnum = ((count > 1) ? 1 : count);
-               if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
-               {
-                       laarr[c].extLength =
-                               (laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
-                               (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
-                                       inode->i_sb->s_blocksize - 1) &
-                               ~(inode->i_sb->s_blocksize - 1));
-                       UDF_I_LENEXTENTS(inode) =
-                               (UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) &
-                                       ~(inode->i_sb->s_blocksize - 1);
+               int ret;
+
+               if (count) {
+                       if (c)
+                               laarr[0] = laarr[1];
+                       startnum = 1;
+               }
+               else {
+                       /* Create a fake extent when there's not one */
+                       memset(&laarr[0].extLocation, 0x00, sizeof(kernel_lb_addr));
+                       laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
+                       /* Will udf_extend_file() create real extent from a fake one? */
+                       startnum = (offset > 0);
+               }
+               /* Create extents for the hole between EOF and offset */
+               ret = udf_extend_file(inode, &prev_epos, laarr, offset);
+               if (ret == -1) {
+                       brelse(prev_epos.bh);
+                       brelse(cur_epos.bh);
+                       brelse(next_epos.bh);
+                       /* We don't really know the error here so we just make
+                        * something up */
+                       *err = -ENOSPC;
+                       return NULL;
                }
-               c = !c;
-               laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
-                       ((offset + 1) << inode->i_sb->s_blocksize_bits);
-               memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
-               count ++;
-               endnum ++;
+               c = 0;
+               offset = 0;
+               count += ret;
+               /* We are not covered by a preallocated extent? */
+               if ((laarr[0].extLength & UDF_EXTENT_FLAG_MASK) != EXT_NOT_RECORDED_ALLOCATED) {
+                       /* Is there any real extent? - otherwise we overwrite
+                        * the fake one... */
+                       if (count)
+                               c = !c;
+                       laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
+                               inode->i_sb->s_blocksize;
+                       memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
+                       count ++;
+                       endnum ++;
+               }
+               endnum = c+1;
                lastblock = 1;
        }
-       else
+       else {
                endnum = startnum = ((count > 2) ? 2 : count);
 
-       /* if the current extent is in position 0, swap it with the previous */
-       if (!c && count != 1)
-       {
-               laarr[2] = laarr[0];
-               laarr[0] = laarr[1];
-               laarr[1] = laarr[2];
-               c = 1;
-       }
+               /* if the current extent is in position 0, swap it with the previous */
+               if (!c && count != 1)
+               {
+                       laarr[2] = laarr[0];
+                       laarr[0] = laarr[1];
+                       laarr[1] = laarr[2];
+                       c = 1;
+               }
 
-       /* 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 the current block is located in an extent, read the next extent */
+               if ((etype = udf_next_aext(inode, &next_epos, &eloc, &elen, 0)) != -1)
                {
                        laarr[c+1].extLength = (etype << 30) | elen;
                        laarr[c+1].extLocation = eloc;
@@ -486,11 +611,10 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                        startnum ++;
                        endnum ++;
                }
-               else
+               else {
                        lastblock = 1;
+               }
        }
-       udf_release_data(cbh);
-       udf_release_data(nbh);
 
        /* if the current extent is not recorded but allocated, get the
                block in the extent corresponding to the requested block */
@@ -510,7 +634,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
                if (!(newblocknum = udf_new_block(inode->i_sb, inode,
                        UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
                {
-                       udf_release_data(pbh);
+                       brelse(prev_epos.bh);
                        *err = -ENOSPC;
                        return NULL;
                }
@@ -531,11 +655,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
        udf_merge_extents(inode, laarr, &endnum);
 
        /* 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);
+       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, &prev_epos);
 
-       udf_release_data(pbh);
+       brelse(prev_epos.bh);
 
        if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
                UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
@@ -797,7 +921,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;
@@ -806,28 +930,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);
        }
 }
 
@@ -918,8 +1040,6 @@ __udf_read_inode(struct inode *inode)
         *      i_nlink = 1
         *      i_op = NULL;
         */
-       inode->i_blksize = PAGE_SIZE;
-
        bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
 
        if (!bh)
@@ -935,7 +1055,7 @@ __udf_read_inode(struct inode *inode)
        {
                printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",
                        inode->i_ino, ident);
-               udf_release_data(bh);
+               brelse(bh);
                make_bad_inode(inode);
                return;
        }
@@ -964,35 +1084,36 @@ __udf_read_inode(struct inode *inode)
                                                ident == TAG_IDENT_EFE)
                                        {
                                                memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
-                                               udf_release_data(bh);
-                                               udf_release_data(ibh);
-                                               udf_release_data(nbh);
+                                               brelse(bh);
+                                               brelse(ibh);
+                                               brelse(nbh);
                                                __udf_read_inode(inode);
                                                return;
                                        }
                                        else
                                        {
-                                               udf_release_data(nbh);
-                                               udf_release_data(ibh);
+                                               brelse(nbh);
+                                               brelse(ibh);
                                        }
                                }
                                else
-                                       udf_release_data(ibh);
+                                       brelse(ibh);
                        }
                }
                else
-                       udf_release_data(ibh);
+                       brelse(ibh);
        }
        else if (le16_to_cpu(fe->icbTag.strategyType) != 4)
        {
                printk(KERN_ERR "udf: unsupported strategy type: %d\n",
                        le16_to_cpu(fe->icbTag.strategyType));
-               udf_release_data(bh);
+               brelse(bh);
                make_bad_inode(inode);
                return;
        }
        udf_fill_inode(inode, bh);
-       udf_release_data(bh);
+
+       brelse(bh);
 }
 
 static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
@@ -1169,7 +1290,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                        inode->i_op = &udf_dir_inode_operations;
                        inode->i_fop = &udf_dir_operations;
                        inode->i_mode |= S_IFDIR;
-                       inode->i_nlink ++;
+                       inc_nlink(inode);
                        break;
                }
                case ICBTAG_FILE_TYPE_REALTIME:
@@ -1335,19 +1456,17 @@ udf_update_inode(struct inode *inode, int do_sync)
                                use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i];
 
                mark_buffer_dirty(bh);
-               udf_release_data(bh);
+               brelse(bh);
                return err;
        }
 
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
                fe->uid = cpu_to_le32(-1);
-       else if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
-               fe->uid = cpu_to_le32(inode->i_uid);
+       else fe->uid = cpu_to_le32(inode->i_uid);
 
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET))
                fe->gid = cpu_to_le32(-1);
-       else if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid)
-               fe->gid = cpu_to_le32(inode->i_gid);
+       else fe->gid = cpu_to_le32(inode->i_gid);
 
        udfperms =      ((inode->i_mode & S_IRWXO)     ) |
                        ((inode->i_mode & S_IRWXG) << 2) |
@@ -1526,7 +1645,7 @@ udf_update_inode(struct inode *inode, int do_sync)
                        err = -EIO;
                }
        }
-       udf_release_data(bh);
+       brelse(bh);
        return err;
 }
 
@@ -1562,8 +1681,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;
@@ -1572,10 +1691,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);
@@ -1584,20 +1703,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;
                }
@@ -1610,25 +1729,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);
                        }
@@ -1640,10 +1759,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:
@@ -1652,7 +1771,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:
@@ -1661,60 +1780,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);
+                       brelse(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))
        {
@@ -1739,40 +1855,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);
+               brelse(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;
                }
        }
@@ -1780,26 +1895,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))
@@ -1808,7 +1923,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;
@@ -1821,7 +1936,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;
@@ -1840,41 +1955,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)
+               get_bh(epos.bh);
 
-       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);
+       brelse(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);
+               get_bh(epos.bh);
+               get_bh(epos.bh);
        }
 
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -1884,80 +1998,77 @@ 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;
+                       brelse(oepos.bh);
+                       get_bh(epos.bh);
+                       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);
+       brelse(epos.bh);
+       brelse(oepos.bh);
        return (elen >> 30);
 }
 
-int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t *extoffset,
-       kernel_lb_addr *eloc, uint32_t *elen, uint32_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)
 {
-       uint64_t lbcount = 0, bcount = (uint64_t)block << inode->i_sb->s_blocksize_bits;
+       loff_t lbcount = 0, bcount = (loff_t)block << inode->i_sb->s_blocksize_bits;
        int8_t etype;
 
        if (block < 0)
@@ -1966,42 +2077,44 @@ int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t
                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;
+                       *offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
                        UDF_I_LENEXTENTS(inode) = lbcount;
                        return -1;
                }
                lbcount += *elen;
        } while (lbcount <= bcount);
 
-       *offset = bcount + *elen - lbcount;
+       *offset = (bcount + *elen - lbcount) >> inode->i_sb->s_blocksize_bits;
 
        return etype;
 }
 
-long udf_block_map(struct inode *inode, long block)
+long udf_block_map(struct inode *inode, sector_t block)
 {
-       kernel_lb_addr eloc, bloc;
-       uint32_t offset, extoffset, elen;
-       struct buffer_head *bh = NULL;
+       kernel_lb_addr eloc;
+       uint32_t elen;
+       sector_t offset;
+       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))
-               ret = udf_get_lb_pblock(inode->i_sb, eloc, offset >> inode->i_sb->s_blocksize_bits);
+       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);
+       brelse(epos.bh);
 
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
                return udf_fixed_to_variable(ret);