ALT Linux Bugzilla
– Attachment 2145 Details for
Bug 12565
UDF + file with size >1G
New bug
|
Search
|
[?]
|
Help
Register
|
Log In
[x]
|
Forgot Password
Login:
[x]
|
EN
|
RU
[patch]
linux-2.6.18-udf.patch
linux-2.6.18-udf.patch (text/plain), 98.48 KB, created by
led
on 2007-08-14 19:51:14 MSD
(
hide
)
Description:
linux-2.6.18-udf.patch
Filename:
MIME Type:
Creator:
led
Created:
2007-08-14 19:51:14 MSD
Size:
98.48 KB
patch
obsolete
>diff -urN kernel-source-2.6.18.orig/fs/udf/balloc.c kernel-source-2.6.18/fs/udf/balloc.c >--- kernel-source-2.6.18.orig/fs/udf/balloc.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/balloc.c 2007-08-14 03:26:08 +0300 >@@ -427,9 +427,9 @@ > { > 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 @@ > 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 @@ > 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 @@ > 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; >+ brelse(oepos.bh); >+ get_bh(epos.bh); >+ oepos.bh = epos.bh; >+ oepos.offset = 0; > } > else >- oextoffset = nextoffset; >+ oepos.offset = epos.offset; > } > > if (count) >@@ -547,55 +546,53 @@ > adsize = sizeof(long_ad); > else > { >- udf_release_data(obh); >- udf_release_data(nbh); >+ brelse(oepos.bh); >+ brelse(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; >+ brelse(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); >+ brelse(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 @@ > } > } > 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 @@ > 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 @@ > 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 @@ > > 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); >+ brelse(epos.bh); >+ brelse(oepos.bh); > > error_return: > sb->s_dirt = 1; >@@ -677,9 +674,9 @@ > { > 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 @@ > 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 @@ > > 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 @@ > 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); >+ brelse(epos.bh); > > if (alloc_count && UDF_SB_LVIDBH(sb)) > { >@@ -747,9 +743,9 @@ > 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 @@ > 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 @@ > 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); >+ brelse(goal_epos.bh); >+ goal_epos.bh = epos.bh; >+ get_bh(goal_epos.bh); > } >- 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); >+ brelse(epos.bh); > > if (spread == 0xFFFFFFFF) > { >- udf_release_data(goal_bh); >+ brelse(goal_epos.bh); > mutex_unlock(&sbi->s_alloc_mutex); > return 0; > } >@@ -826,17 +820,17 @@ > > if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) > { >- udf_release_data(goal_bh); >+ brelse(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); >+ brelse(goal_epos.bh); > > if (UDF_SB_LVIDBH(sb)) > { >@@ -921,11 +915,14 @@ > struct inode * inode, > uint16_t partition, uint32_t goal, int *err) > { >+ int ret; >+ > if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) > { >- return udf_bitmap_new_block(sb, inode, >+ ret = udf_bitmap_new_block(sb, inode, > UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap, > partition, goal, err); >+ return ret; > } > else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) > { >diff -urN kernel-source-2.6.18.orig/fs/udf/dir.c kernel-source-2.6.18/fs/udf/dir.c >--- kernel-source-2.6.18.orig/fs/udf/dir.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/dir.c 2007-08-14 03:26:08 +0300 >@@ -111,11 +111,13 @@ > 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, offset; >+ 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; >@@ -127,23 +129,22 @@ > 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)) > { >- offset >>= dir->i_sb->s_blocksize_bits; > 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); >+ brelse(epos.bh); > return -EIO; > } > >@@ -171,7 +172,7 @@ > } > else > { >- udf_release_data(bh); >+ brelse(epos.bh); > return -ENOENT; > } > >@@ -179,14 +180,14 @@ > { > 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); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); >+ brelse(epos.bh); > return 0; > } > >@@ -244,9 +245,9 @@ > if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) > { > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >- udf_release_data(bh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); >+ brelse(epos.bh); > return 0; > } > } >@@ -255,9 +256,9 @@ > filp->f_pos = nf_pos + 1; > > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >- udf_release_data(bh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); >+ brelse(epos.bh); > > return 0; > } >diff -urN kernel-source-2.6.18.orig/fs/udf/directory.c kernel-source-2.6.18/fs/udf/directory.c >--- kernel-source-2.6.18.orig/fs/udf/directory.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/directory.c 2007-08-14 03:26:08 +0300 >@@ -36,14 +36,14 @@ > > if (!ad) > { >- udf_release_data(*bh); >+ brelse(*bh); > *error = 1; > return NULL; > } > > if (*offset == dir->i_sb->s_blocksize) > { >- udf_release_data(*bh); >+ brelse(*bh); > block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos); > if (!block) > return NULL; >@@ -57,7 +57,7 @@ > remainder = dir->i_sb->s_blocksize - loffset; > memcpy((uint8_t *)ad, (*bh)->b_data + loffset, remainder); > >- udf_release_data(*bh); >+ brelse(*bh); > block = udf_get_lb_pblock(dir->i_sb, fe_loc, ++*pos); > if (!block) > return NULL; >@@ -75,9 +75,9 @@ > 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, >- uint32_t *offset, struct buffer_head **bh) >+ sector_t *offset) > { > struct fileIdentDesc *fi; > int i, num, block; >@@ -105,13 +105,11 @@ > > 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,9 +118,9 @@ > if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen) > *offset = 0; > else >- *extoffset = lextoffset; >+ epos->offset = lextoffset; > >- udf_release_data(fibh->sbh); >+ brelse(fibh->sbh); > if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block))) > return NULL; > fibh->soffset = fibh->eoffset = 0; >@@ -151,7 +149,7 @@ > } > else if (fibh->sbh != fibh->ebh) > { >- udf_release_data(fibh->sbh); >+ brelse(fibh->sbh); > fibh->sbh = fibh->ebh; > } > >@@ -169,13 +167,11 @@ > } > 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 @@ > 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; >diff -urN kernel-source-2.6.18.orig/fs/udf/file.c kernel-source-2.6.18/fs/udf/file.c >--- kernel-source-2.6.18.orig/fs/udf/file.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/file.c 2007-08-14 11:35:53 +0300 >@@ -36,6 +36,7 @@ > #include <linux/smp_lock.h> > #include <linux/pagemap.h> > #include <linux/buffer_head.h> >+#include <linux/aio.h> > > #include "udf_i.h" > #include "udf_sb.h" >@@ -103,10 +104,11 @@ > .commit_write = udf_adinicb_commit_write, > }; > >-static ssize_t udf_file_write(struct file * file, const char __user * buf, >- size_t count, loff_t *ppos) >+static ssize_t udf_file_aio_write(struct kiocb *iocb, const char __user *buf, >+ size_t count, loff_t ppos) > { > ssize_t retval; >+ struct file *file = iocb->ki_filp; > struct inode *inode = file->f_dentry->d_inode; > int err, pos; > >@@ -115,7 +117,7 @@ > if (file->f_flags & O_APPEND) > pos = inode->i_size; > else >- pos = *ppos; >+ pos = ppos; > > if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) + > pos + count)) >@@ -136,7 +138,7 @@ > } > } > >- retval = generic_file_write(file, buf, count, ppos); >+ retval = generic_file_aio_write(iocb, buf, count, ppos); > > if (retval > 0) > mark_inode_dirty(inode); >@@ -249,16 +251,18 @@ > } > > const struct file_operations udf_file_operations = { >- .read = generic_file_read, >+ .read = do_sync_read, >+ .aio_read = generic_file_aio_read, > .ioctl = udf_ioctl, > .open = generic_file_open, > .mmap = generic_file_mmap, >- .write = udf_file_write, >+ .write = do_sync_write, >+ .aio_write = udf_file_aio_write, > .release = udf_release_file, > .fsync = udf_fsync_file, > .sendfile = generic_file_sendfile, > }; > >-struct inode_operations udf_file_inode_operations = { >+const struct inode_operations udf_file_inode_operations = { > .truncate = udf_truncate, > }; >diff -urN kernel-source-2.6.18.orig/fs/udf/fsync.c kernel-source-2.6.18/fs/udf/fsync.c >--- kernel-source-2.6.18.orig/fs/udf/fsync.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/fsync.c 2007-08-14 03:26:08 +0300 >@@ -21,7 +21,6 @@ > #include "udfdecl.h" > > #include <linux/fs.h> >-#include <linux/smp_lock.h> > > static int udf_fsync_inode(struct inode *, int); > >diff -urN kernel-source-2.6.18.orig/fs/udf/ialloc.c kernel-source-2.6.18/fs/udf/ialloc.c >--- kernel-source-2.6.18.orig/fs/udf/ialloc.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/ialloc.c 2007-08-14 03:26:08 +0300 >@@ -121,7 +121,6 @@ > UDF_I_LOCATION(inode).logicalBlockNum = block; > UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum; > inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0); >- inode->i_blksize = PAGE_SIZE; > inode->i_blocks = 0; > UDF_I_LENEATTR(inode) = 0; > UDF_I_LENALLOC(inode) = 0; >@@ -130,14 +129,12 @@ > { > UDF_I_EFE(inode) = 1; > UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE); >- UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL); >- memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); >+ UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL); > } > else > { > UDF_I_EFE(inode) = 0; >- UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL); >- memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry)); >+ UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL); > } > if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) > UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB; >diff -urN kernel-source-2.6.18.orig/fs/udf/inode.c kernel-source-2.6.18/fs/udf/inode.c >--- kernel-source-2.6.18.orig/fs/udf/inode.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/inode.c 2007-08-14 03:26:08 +0300 >@@ -49,10 +49,10 @@ > 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 @@ > 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); > > /* >@@ -100,14 +100,23 @@ > clear_inode(inode); > } > >+/* >+ * If we are going to release inode from memory, we discard preallocation and >+ * truncate last inode extent to proper length. We could use drop_inode() but >+ * it's called under inode_lock and thus we cannot mark inode dirty there. We >+ * use clear_inode() but we have to make sure to write inode as it's not written >+ * automatically. >+ */ > void udf_clear_inode(struct inode *inode) > { > if (!(inode->i_sb->s_flags & MS_RDONLY)) { > lock_kernel(); >+ /* Discard preallocation for directories, symlinks, etc. */ > udf_discard_prealloc(inode); >+ udf_truncate_tail_extent(inode); > unlock_kernel(); >+ write_inode_now(inode, 1); > } >- > kfree(UDF_I_DATA(inode)); > UDF_I_DATA(inode) = NULL; > } >@@ -194,10 +203,11 @@ > 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 +247,16 @@ > 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 +268,7 @@ > 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 +276,17 @@ > > 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; > } >@@ -354,53 +365,153 @@ > 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; >+ uint32_t elen = 0, tmpelen; >+ kernel_lb_addr eloc, tmpeloc; > 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; >@@ -418,6 +529,12 @@ > > b_off -= lbcount; > offset = b_off >> inode->i_sb->s_blocksize_bits; >+ /* >+ * Move prev_epos and cur_epos into indirect extent if we are at >+ * the pointer to it >+ */ >+ udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0); >+ udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0); > > /* if the extent is allocated and recorded, return the block > if the extent is not a multiple of the blocksize, round up */ >@@ -429,54 +546,77 @@ > 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; >@@ -484,11 +624,10 @@ > 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 */ >@@ -508,7 +647,7 @@ > 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; > } >@@ -529,11 +668,11 @@ > 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))) >@@ -795,7 +934,7 @@ > > 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; >@@ -804,28 +943,26 @@ > 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); > } > } > >@@ -916,8 +1053,6 @@ > * 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) >@@ -933,7 +1068,7 @@ > { > 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; > } >@@ -962,35 +1097,36 @@ > 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) >@@ -1333,7 +1469,7 @@ > use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i]; > > mark_buffer_dirty(bh); >- udf_release_data(bh); >+ brelse(bh); > return err; > } > >@@ -1522,7 +1658,7 @@ > err = -EIO; > } > } >- udf_release_data(bh); >+ brelse(bh); > return err; > } > >@@ -1558,8 +1694,8 @@ > 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; >@@ -1568,10 +1704,10 @@ > 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); >@@ -1580,20 +1716,20 @@ > 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; > } >@@ -1606,25 +1742,25 @@ > 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); > } >@@ -1636,10 +1772,10 @@ > } > 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: >@@ -1648,7 +1784,7 @@ > 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: >@@ -1657,60 +1793,57 @@ > 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)) > { >@@ -1735,40 +1868,39 @@ > 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; > } > } >@@ -1776,26 +1908,26 @@ > 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)) >@@ -1804,7 +1936,7 @@ > { > 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; >@@ -1817,7 +1949,7 @@ > { > 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; >@@ -1836,41 +1968,40 @@ > } > > 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) >@@ -1880,80 +2011,77 @@ > 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) >@@ -1962,42 +2090,44 @@ > 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); >diff -urN kernel-source-2.6.18.orig/fs/udf/misc.c kernel-source-2.6.18/fs/udf/misc.c >--- kernel-source-2.6.18.orig/fs/udf/misc.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/misc.c 2007-08-14 03:26:08 +0300 >@@ -274,12 +274,6 @@ > loc.logicalBlockNum + offset, ident); > } > >-void udf_release_data(struct buffer_head *bh) >-{ >- if (bh) >- brelse(bh); >-} >- > void udf_update_tag(char *data, int length) > { > tag *tptr = (tag *)data; >diff -urN kernel-source-2.6.18.orig/fs/udf/namei.c kernel-source-2.6.18/fs/udf/namei.c >--- kernel-source-2.6.18.orig/fs/udf/namei.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/namei.c 2007-08-14 03:26:08 +0300 >@@ -30,6 +30,7 @@ > #include <linux/quotaops.h> > #include <linux/smp_lock.h> > #include <linux/buffer_head.h> >+#include <linux/sched.h> > > static inline int udf_match(int len1, const char *name1, int len2, const char *name2) > { >@@ -155,9 +156,10 @@ > uint8_t lfi; > uint16_t liu; > loff_t size; >- kernel_lb_addr bloc, eloc; >- uint32_t extoffset, elen, offset; >- struct buffer_head *bh = NULL; >+ kernel_lb_addr eloc; >+ uint32_t elen; >+ sector_t offset; >+ struct extent_position epos = { NULL, 0, { 0, 0}}; > > size = (udf_ext0_offset(dir) + dir->i_size) >> 2; > f_pos = (udf_ext0_offset(dir) >> 2); >@@ -166,42 +168,41 @@ > 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)) > { >- offset >>= dir->i_sb->s_blocksize_bits; > 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); >+ brelse(epos.bh); > return NULL; > } > } > else > { >- udf_release_data(bh); >+ brelse(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); >+ brelse(fibh->ebh); >+ brelse(fibh->sbh); >+ brelse(epos.bh); > return NULL; > } > >@@ -247,15 +248,15 @@ > { > if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name)) > { >- udf_release_data(bh); >+ brelse(epos.bh); > return fi; > } > } > } > if (fibh->sbh != fibh->ebh) >- udf_release_data(fibh->ebh); >- udf_release_data(fibh->sbh); >- udf_release_data(bh); >+ brelse(fibh->ebh); >+ brelse(fibh->sbh); >+ brelse(epos.bh); > return NULL; > } > >@@ -321,8 +322,8 @@ > if (udf_find_entry(dir, dentry, &fibh, &cfi)) > { > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > > inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation)); > if ( !inode ) >@@ -353,9 +354,10 @@ > uint8_t lfi; > uint16_t liu; > int block; >- kernel_lb_addr bloc, eloc; >- uint32_t extoffset, elen, offset; >- struct buffer_head *bh = NULL; >+ kernel_lb_addr eloc; >+ uint32_t elen; >+ sector_t offset; >+ struct extent_position epos = { NULL, 0, { 0, 0 }}; > > sb = dir->i_sb; > >@@ -384,23 +386,22 @@ > 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)) > { >- offset >>= dir->i_sb->s_blocksize_bits; > 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); >+ brelse(epos.bh); > *err = -EIO; > return NULL; > } >@@ -418,14 +419,14 @@ > > 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); >+ brelse(fibh->ebh); >+ brelse(fibh->sbh); >+ brelse(epos.bh); > *err = -EIO; > return NULL; > } >@@ -455,7 +456,7 @@ > { > if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen) > { >- udf_release_data(bh); >+ brelse(epos.bh); > cfi->descTag.tagSerialNum = cpu_to_le16(1); > cfi->fileVersionNum = cpu_to_le16(1); > cfi->fileCharacteristics = 0; >@@ -478,9 +479,9 @@ > udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name)) > { > if (fibh->sbh != fibh->ebh) >- udf_release_data(fibh->ebh); >- udf_release_data(fibh->sbh); >- udf_release_data(bh); >+ brelse(fibh->ebh); >+ brelse(fibh->sbh); >+ brelse(epos.bh); > *err = -EEXIST; > return NULL; > } >@@ -492,25 +493,25 @@ > if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB && > sb->s_blocksize - fibh->eoffset < nfidlen) > { >- udf_release_data(bh); >- bh = NULL; >+ brelse(epos.bh); >+ epos.bh = NULL; > fibh->soffset -= udf_ext0_offset(dir); > fibh->eoffset -= udf_ext0_offset(dir); > f_pos -= (udf_ext0_offset(dir) >> 2); > if (fibh->sbh != fibh->ebh) >- udf_release_data(fibh->ebh); >- udf_release_data(fibh->sbh); >+ brelse(fibh->ebh); >+ brelse(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) >@@ -519,7 +520,7 @@ > fibh->eoffset += nfidlen; > if (fibh->sbh != fibh->ebh) > { >- udf_release_data(fibh->sbh); >+ brelse(fibh->sbh); > fibh->sbh = fibh->ebh; > } > >@@ -541,7 +542,7 @@ > fibh->eoffset += nfidlen - sb->s_blocksize; > if (fibh->sbh != fibh->ebh) > { >- udf_release_data(fibh->sbh); >+ brelse(fibh->sbh); > fibh->sbh = fibh->ebh; > } > >@@ -550,14 +551,14 @@ > > if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err))) > { >- udf_release_data(bh); >- udf_release_data(fibh->sbh); >+ brelse(epos.bh); >+ brelse(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) >> >@@ -566,7 +567,7 @@ > else > block ++; > >- udf_release_data(fibh->sbh); >+ brelse(fibh->sbh); > fibh->sbh = fibh->ebh; > fi = (struct fileIdentDesc *)(fibh->sbh->b_data); > } >@@ -587,7 +588,7 @@ > cfi->lengthOfImpUse = cpu_to_le16(0); > if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) > { >- udf_release_data(bh); >+ brelse(epos.bh); > dir->i_size += nfidlen; > if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) > UDF_I_LENALLOC(dir) += nfidlen; >@@ -596,10 +597,10 @@ > } > else > { >- udf_release_data(bh); >+ brelse(epos.bh); > if (fibh->sbh != fibh->ebh) >- udf_release_data(fibh->ebh); >- udf_release_data(fibh->sbh); >+ brelse(fibh->ebh); >+ brelse(fibh->sbh); > *err = -EIO; > return NULL; > } >@@ -656,8 +657,8 @@ > mark_inode_dirty(dir); > } > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > unlock_kernel(); > d_instantiate(dentry, inode); > return 0; >@@ -701,8 +702,8 @@ > mark_inode_dirty(inode); > > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > d_instantiate(dentry, inode); > err = 0; > out: >@@ -743,7 +744,7 @@ > cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL); > cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT; > udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL); >- udf_release_data(fibh.sbh); >+ brelse(fibh.sbh); > inode->i_mode = S_IFDIR | mode; > if (dir->i_mode & S_ISGID) > inode->i_mode |= S_ISGID; >@@ -766,8 +767,8 @@ > mark_inode_dirty(dir); > d_instantiate(dentry, inode); > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > err = 0; > out: > unlock_kernel(); >@@ -781,9 +782,10 @@ > 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, offset; >- struct buffer_head *bh = NULL; >+ kernel_lb_addr eloc; >+ uint32_t elen; >+ sector_t offset; >+ struct extent_position epos = { NULL, 0, { 0, 0}}; > > f_pos = (udf_ext0_offset(dir) >> 2); > >@@ -792,59 +794,58 @@ > 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)) > { >- offset >>= dir->i_sb->s_blocksize_bits; > 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); >+ brelse(epos.bh); > return 0; > } > } > else > { >- udf_release_data(bh); >+ brelse(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); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); >+ brelse(epos.bh); > return 0; > } > > if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) > { > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >- udf_release_data(bh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); >+ brelse(epos.bh); > return 0; > } > } > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >- udf_release_data(bh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); >+ brelse(epos.bh); > return 1; > } > >@@ -878,15 +879,14 @@ > inode->i_nlink); > inode->i_nlink = 0; > inode->i_size = 0; >- mark_inode_dirty(inode); >- dir->i_nlink --; >+ inode_dec_link_count(dir); > inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); > mark_inode_dirty(dir); > > end_rmdir: > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > out: > unlock_kernel(); > return retval; >@@ -923,15 +923,14 @@ > goto end_unlink; > dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); > mark_inode_dirty(dir); >- inode->i_nlink--; >- mark_inode_dirty(inode); >+ inode_dec_link_count(inode); > inode->i_ctime = dir->i_ctime; > retval = 0; > > end_unlink: > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > out: > unlock_kernel(); > return retval; >@@ -943,7 +942,7 @@ > 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; >@@ -963,33 +962,33 @@ > > 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); >+ brelse(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); >@@ -1062,7 +1061,7 @@ > } > } > >- udf_release_data(bh); >+ brelse(epos.bh); > inode->i_size = elen; > if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) > UDF_I_LENALLOC(inode) = inode->i_size; >@@ -1091,8 +1090,8 @@ > mark_inode_dirty(dir); > } > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > d_instantiate(dentry, inode); > err = 0; > >@@ -1101,8 +1100,7 @@ > return err; > > out_no_entry: >- inode->i_nlink--; >- mark_inode_dirty(inode); >+ inode_dec_link_count(inode); > iput(inode); > goto out; > } >@@ -1148,8 +1146,8 @@ > mark_inode_dirty(dir); > } > if (fibh.sbh != fibh.ebh) >- udf_release_data(fibh.ebh); >- udf_release_data(fibh.sbh); >+ brelse(fibh.ebh); >+ brelse(fibh.sbh); > inode->i_nlink ++; > inode->i_ctime = current_fs_time(inode->i_sb); > mark_inode_dirty(inode); >@@ -1177,8 +1175,8 @@ > if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi))) > { > if (ofibh.sbh != ofibh.ebh) >- udf_release_data(ofibh.ebh); >- udf_release_data(ofibh.sbh); >+ brelse(ofibh.ebh); >+ brelse(ofibh.sbh); > } > tloc = lelb_to_cpu(ocfi.icb.extLocation); > if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0) >@@ -1191,8 +1189,8 @@ > if (!new_inode) > { > if (nfibh.sbh != nfibh.ebh) >- udf_release_data(nfibh.ebh); >- udf_release_data(nfibh.sbh); >+ brelse(nfibh.ebh); >+ brelse(nfibh.sbh); > nfi = NULL; > } > } >@@ -1261,9 +1259,8 @@ > > if (new_inode) > { >- new_inode->i_nlink--; > new_inode->i_ctime = current_fs_time(new_inode->i_sb); >- mark_inode_dirty(new_inode); >+ inode_dec_link_count(new_inode); > } > old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb); > mark_inode_dirty(old_dir); >@@ -1279,12 +1276,10 @@ > } > else > mark_buffer_dirty_inode(dir_bh, old_inode); >- old_dir->i_nlink --; >- mark_inode_dirty(old_dir); >+ inode_dec_link_count(old_dir); > if (new_inode) > { >- new_inode->i_nlink --; >- mark_inode_dirty(new_inode); >+ inode_dec_link_count(new_inode); > } > else > { >@@ -1296,25 +1291,25 @@ > if (ofi) > { > if (ofibh.sbh != ofibh.ebh) >- udf_release_data(ofibh.ebh); >- udf_release_data(ofibh.sbh); >+ brelse(ofibh.ebh); >+ brelse(ofibh.sbh); > } > > retval = 0; > > end_rename: >- udf_release_data(dir_bh); >+ brelse(dir_bh); > if (nfi) > { > if (nfibh.sbh != nfibh.ebh) >- udf_release_data(nfibh.ebh); >- udf_release_data(nfibh.sbh); >+ brelse(nfibh.ebh); >+ brelse(nfibh.sbh); > } > unlock_kernel(); > return retval; > } > >-struct inode_operations udf_dir_inode_operations = { >+const struct inode_operations udf_dir_inode_operations = { > .lookup = udf_lookup, > .create = udf_create, > .link = udf_link, >diff -urN kernel-source-2.6.18.orig/fs/udf/partition.c kernel-source-2.6.18/fs/udf/partition.c >--- kernel-source-2.6.18.orig/fs/udf/partition.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/partition.c 2007-08-14 03:26:08 +0300 >@@ -81,7 +81,7 @@ > > loc = le32_to_cpu(((__le32 *)bh->b_data)[index]); > >- udf_release_data(bh); >+ brelse(bh); > > if (UDF_I_LOCATION(UDF_SB_VAT(sb)).partitionReferenceNum == partition) > { >diff -urN kernel-source-2.6.18.orig/fs/udf/super.c kernel-source-2.6.18/fs/udf/super.c >--- kernel-source-2.6.18.orig/fs/udf/super.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/super.c 2007-08-14 03:26:08 +0300 >@@ -107,12 +107,12 @@ > .fs_flags = FS_REQUIRES_DEV, > }; > >-static kmem_cache_t * udf_inode_cachep; >+static struct kmem_cache * udf_inode_cachep; > > static struct inode *udf_alloc_inode(struct super_block *sb) > { > struct udf_inode_info *ei; >- ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL); >+ ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, GFP_KERNEL); > if (!ei) > return NULL; > >@@ -130,16 +130,12 @@ > kmem_cache_free(udf_inode_cachep, UDF_I(inode)); > } > >-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) >+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) > { > struct udf_inode_info *ei = (struct udf_inode_info *) foo; > >- if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == >- SLAB_CTOR_CONSTRUCTOR) >- { >- ei->i_ext.i_data = NULL; >- inode_init_once(&ei->vfs_inode); >- } >+ ei->i_ext.i_data = NULL; >+ inode_init_once(&ei->vfs_inode); > } > > static int init_inodecache(void) >@@ -156,12 +152,11 @@ > > static void destroy_inodecache(void) > { >- if (kmem_cache_destroy(udf_inode_cachep)) >- printk(KERN_INFO "udf_inode_cache: not all structures were freed\n"); >+ kmem_cache_destroy(udf_inode_cachep); > } > > /* Superblock operations */ >-static struct super_operations udf_sb_ops = { >+static const struct super_operations udf_sb_ops = { > .alloc_inode = udf_alloc_inode, > .destroy_inode = udf_destroy_inode, > .write_inode = udf_write_inode, >@@ -566,7 +561,7 @@ > > if (vsd->stdIdent[0] == 0) > { >- udf_release_data(bh); >+ brelse(bh); > break; > } > else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN)) >@@ -599,7 +594,7 @@ > } > else if (!strncmp(vsd->stdIdent, VSD_STD_ID_TEA01, VSD_STD_ID_LEN)) > { >- udf_release_data(bh); >+ brelse(bh); > break; > } > else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR02, VSD_STD_ID_LEN)) >@@ -610,7 +605,7 @@ > { > nsr03 = sector; > } >- udf_release_data(bh); >+ brelse(bh); > } > > if (nsr03) >@@ -676,7 +671,7 @@ > { > ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); > location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); >- udf_release_data(bh); >+ brelse(bh); > } > > if (ident == TAG_IDENT_AVDP) >@@ -711,7 +706,7 @@ > { > ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); > location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); >- udf_release_data(bh); >+ brelse(bh); > } > > if (ident == TAG_IDENT_AVDP && >@@ -730,7 +725,7 @@ > { > ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); > location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); >- udf_release_data(bh); >+ brelse(bh); > } > > if (ident == TAG_IDENT_AVDP && >@@ -752,7 +747,7 @@ > { > ident = le16_to_cpu(((tag *)bh->b_data)->tagIdent); > location = le32_to_cpu(((tag *)bh->b_data)->tagLocation); >- udf_release_data(bh); >+ brelse(bh); > > if (ident == TAG_IDENT_AVDP && location == 256) > UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); >@@ -769,7 +764,7 @@ > } > else > { >- udf_release_data(bh); >+ brelse(bh); > if ((ident != TAG_IDENT_AVDP) && (i || > (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE))) > { >@@ -798,7 +793,7 @@ > return 1; > else if (ident != TAG_IDENT_FSD) > { >- udf_release_data(bh); >+ brelse(bh); > return 1; > } > >@@ -837,7 +832,7 @@ > newfileset.logicalBlockNum += 1 + > ((le32_to_cpu(sp->numOfBytes) + sizeof(struct spaceBitmapDesc) - 1) > >> sb->s_blocksize_bits); >- udf_release_data(bh); >+ brelse(bh); > break; > } > case TAG_IDENT_FSD: >@@ -848,7 +843,7 @@ > default: > { > newfileset.logicalBlockNum ++; >- udf_release_data(bh); >+ brelse(bh); > bh = NULL; > break; > } >@@ -868,7 +863,7 @@ > > UDF_SB_PARTITION(sb) = fileset->partitionReferenceNum; > udf_load_fileset(sb, bh, root); >- udf_release_data(bh); >+ brelse(bh); > return 0; > } > return 1; >@@ -1086,7 +1081,7 @@ > if (ident != 0 || > strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING))) > { >- udf_release_data(UDF_SB_TYPESPAR(sb,i).s_spar_map[j]); >+ brelse(UDF_SB_TYPESPAR(sb,i).s_spar_map[j]); > UDF_SB_TYPESPAR(sb,i).s_spar_map[j] = NULL; > } > } >@@ -1140,12 +1135,12 @@ > udf_load_logicalvolint(sb, leea_to_cpu(UDF_SB_LVID(sb)->nextIntegrityExt)); > > if (UDF_SB_LVIDBH(sb) != bh) >- udf_release_data(bh); >+ brelse(bh); > loc.extLength -= sb->s_blocksize; > loc.extLocation ++; > } > if (UDF_SB_LVIDBH(sb) != bh) >- udf_release_data(bh); >+ brelse(bh); > } > > /* >@@ -1248,7 +1243,7 @@ > done = 1; > break; > } >- udf_release_data(bh); >+ brelse(bh); > } > for (i=0; i<VDS_POS_LENGTH; i++) > { >@@ -1270,10 +1265,10 @@ > gd = (struct generic_desc *)bh2->b_data; > if (ident == TAG_IDENT_PD) > udf_load_partdesc(sb, bh2); >- udf_release_data(bh2); >+ brelse(bh2); > } > } >- udf_release_data(bh); >+ brelse(bh); > } > } > >@@ -1336,7 +1331,7 @@ > reserve_e = reserve_e >> sb->s_blocksize_bits; > reserve_e += reserve_s; > >- udf_release_data(bh); >+ brelse(bh); > > /* Process the main & reserve sequences */ > /* responsible for finding the PartitionDesc(s) */ >@@ -1356,7 +1351,7 @@ > > for (i=0; i<UDF_SB_NUMPARTS(sb); i++) > { >- switch UDF_SB_PARTTYPE(sb, i) >+ switch (UDF_SB_PARTTYPE(sb, i)) > { > case UDF_VIRTUAL_MAP15: > case UDF_VIRTUAL_MAP20: >@@ -1406,12 +1401,14 @@ > > pos = udf_block_map(UDF_SB_VAT(sb), 0); > bh = sb_bread(sb, pos); >+ if (!bh) >+ return 1; > UDF_SB_TYPEVIRT(sb,i).s_start_offset = > le16_to_cpu(((struct virtualAllocationTable20 *)bh->b_data + udf_ext0_offset(UDF_SB_VAT(sb)))->lengthHeader) + > udf_ext0_offset(UDF_SB_VAT(sb)); > UDF_SB_TYPEVIRT(sb,i).s_num_entries = (UDF_SB_VAT(sb)->i_size - > UDF_SB_TYPEVIRT(sb,i).s_start_offset) >> 2; >- udf_release_data(bh); >+ brelse(bh); > } > UDF_SB_PARTROOT(sb,i) = udf_get_pblock(sb, 0, i, 0); > UDF_SB_PARTLEN(sb,i) = UDF_SB_PARTLEN(sb,ino.partitionReferenceNum); >@@ -1622,6 +1619,11 @@ > goto error_out; > } > >+ if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_READ_ONLY) { >+ printk("UDF-fs: Partition marked readonly; forcing readonly mount\n"); >+ sb->s_flags |= MS_RDONLY; >+ } >+ > if ( udf_find_fileset(sb, &fileset, &rootdir) ) > { > printk("UDF-fs: No fileset found\n"); >@@ -1659,7 +1661,7 @@ > iput(inode); > goto error_out; > } >- sb->s_maxbytes = 1<<30; >+ sb->s_maxbytes = MAX_LFS_FILESIZE; > return 0; > > error_out: >@@ -1678,7 +1680,7 @@ > if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15) > { > for (i=0; i<4; i++) >- udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]); >+ brelse(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]); > } > } > #ifdef CONFIG_UDF_NLS >@@ -1687,7 +1689,7 @@ > #endif > if (!(sb->s_flags & MS_RDONLY)) > udf_close_lvid(sb); >- udf_release_data(UDF_SB_LVIDBH(sb)); >+ brelse(UDF_SB_LVIDBH(sb)); > UDF_SB_FREE(sb); > kfree(sbi); > sb->s_fs_info = NULL; >@@ -1705,7 +1707,7 @@ > sb->s_dirt = 1; > } > va_start(args, fmt); >- vsprintf(error_buf, fmt, args); >+ vsnprintf(error_buf, sizeof(error_buf), fmt, args); > va_end(args); > printk (KERN_CRIT "UDF-fs error (device %s): %s: %s\n", > sb->s_id, function, error_buf); >@@ -1717,7 +1719,7 @@ > va_list args; > > va_start (args, fmt); >- vsprintf(error_buf, fmt, args); >+ vsnprintf(error_buf, sizeof(error_buf), fmt, args); > va_end(args); > printk(KERN_WARNING "UDF-fs warning (device %s): %s: %s\n", > sb->s_id, function, error_buf); >@@ -1756,7 +1758,7 @@ > if (UDF_SB_PARTTYPE(sb, UDF_SB_PARTITION(sb)) == UDF_SPARABLE_MAP15) > { > for (i=0; i<4; i++) >- udf_release_data(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]); >+ brelse(UDF_SB_TYPESPAR(sb, UDF_SB_PARTITION(sb)).s_spar_map[i]); > } > } > #ifdef CONFIG_UDF_NLS >@@ -1765,7 +1767,7 @@ > #endif > if (!(sb->s_flags & MS_RDONLY)) > udf_close_lvid(sb); >- udf_release_data(UDF_SB_LVIDBH(sb)); >+ brelse(UDF_SB_LVIDBH(sb)); > UDF_SB_FREE(sb); > kfree(sb->s_fs_info); > sb->s_fs_info = NULL; >@@ -1835,7 +1837,7 @@ > } > else if (ident != TAG_IDENT_SBD) > { >- udf_release_data(bh); >+ brelse(bh); > printk(KERN_ERR "udf: udf_count_free failed\n"); > goto out; > } >@@ -1857,7 +1859,7 @@ > } > if ( bytes ) > { >- udf_release_data(bh); >+ brelse(bh); > newblock = udf_get_lb_pblock(sb, loc, ++block); > bh = udf_tread(sb, newblock); > if (!bh) >@@ -1869,7 +1871,7 @@ > ptr = (uint8_t *)bh->b_data; > } > } >- udf_release_data(bh); >+ brelse(bh); > > out: > unlock_kernel(); >@@ -1881,21 +1883,20 @@ > 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); >+ brelse(epos.bh); > > unlock_kernel(); > >diff -urN kernel-source-2.6.18.orig/fs/udf/symlink.c kernel-source-2.6.18/fs/udf/symlink.c >--- kernel-source-2.6.18.orig/fs/udf/symlink.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/symlink.c 2007-08-14 03:26:08 +0300 >@@ -95,7 +95,7 @@ > } > > udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); >- udf_release_data(bh); >+ brelse(bh); > > unlock_kernel(); > SetPageUptodate(page); >diff -urN kernel-source-2.6.18.orig/fs/udf/truncate.c kernel-source-2.6.18/fs/udf/truncate.c >--- kernel-source-2.6.18.orig/fs/udf/truncate.c 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/truncate.c 2007-08-14 03:26:08 +0300 >@@ -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 @@ > > 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)) >@@ -61,74 +61,125 @@ > } > } > >-void udf_discard_prealloc(struct inode * inode) >+/* >+ * Truncate the last extent to match i_size. This function assumes >+ * that preallocation extent is already truncated. >+ */ >+void udf_truncate_tail_extent(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)) >- { >+ inode->i_size == UDF_I_LENEXTENTS(inode)) >+ return; >+ /* Are we going to delete the file anyway? */ >+ if (inode->i_nlink == 0) > return; >- } > > if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) > adsize = sizeof(short_ad); > else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) > adsize = sizeof(long_ad); > else >- adsize = 0; >- >- bloc = UDF_I_LOCATION(inode); >+ BUG(); > >- 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) >- { >+ if (lbcount > inode->i_size) { >+ if (lbcount - inode->i_size >= inode->i_sb->s_blocksize) >+ printk(KERN_WARNING >+ "udf_truncate_tail_extent(): Too long " >+ "extent after EOF in inode %u: i_size: " >+ "%Ld lbcount: %Ld extent %u+%u\n", >+ (unsigned)inode->i_ino, >+ (long long)inode->i_size, >+ (long long)lbcount, >+ (unsigned)eloc.logicalBlockNum, >+ (unsigned)elen); > nelen = elen - (lbcount - inode->i_size); >- extent_trunc(inode, bloc, extoffset-adsize, eloc, etype, elen, bh, nelen); >- lbcount = inode->i_size; >+ epos.offset -= adsize; >+ extent_trunc(inode, &epos, eloc, etype, elen, nelen); >+ epos.offset += adsize; >+ if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) >+ printk(KERN_ERR "udf_truncate_tail_extent(): " >+ "Extent after EOF in inode %u.\n", >+ (unsigned)inode->i_ino); >+ break; > } > } >- if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) >- { >- extoffset -= adsize; >+ /* This inode entry is in-memory only and thus we don't have to mark >+ * the inode dirty */ >+ UDF_I_LENEXTENTS(inode) = inode->i_size; >+ brelse(epos.bh); >+} >+ >+void udf_discard_prealloc(struct inode *inode) >+{ >+ struct extent_position epos = { NULL, 0, {0, 0}}; >+ kernel_lb_addr eloc; >+ uint32_t elen; >+ uint64_t lbcount = 0; >+ int8_t etype = -1, netype; >+ 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); >+ else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) >+ adsize = sizeof(long_ad); >+ else >+ adsize = 0; >+ >+ epos.block = UDF_I_LOCATION(inode); >+ >+ /* Find the last extent in the file */ >+ while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { >+ etype = netype; >+ lbcount += elen; >+ } >+ if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { >+ epos.offset -= adsize; > lbcount -= elen; >- extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, 0); >- if (!bh) >- { >- UDF_I_LENALLOC(inode) = extoffset - udf_file_entry_alloc_offset(inode); >+ extent_trunc(inode, &epos, eloc, etype, elen, 0); >+ if (!epos.bh) { >+ 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)); >+ } else { >+ 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); > } > } >+ /* This inode entry is in-memory only and thus we don't have to mark >+ * the inode dirty */ > UDF_I_LENEXTENTS(inode) = lbcount; >- >- udf_release_data(bh); >+ brelse(epos.bh); > } > > void udf_truncate_extents(struct inode * inode) > { >- kernel_lb_addr bloc, eloc, neloc = { 0, 0 }; >- uint32_t extoffset, elen, offset, 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; >- int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits; >- struct buffer_head *bh = NULL; >+ struct super_block *sb = inode->i_sb; >+ sector_t first_block = inode->i_size >> sb->s_blocksize_bits, offset; >+ loff_t byte_offset; > int adsize; > > if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) >@@ -136,158 +187,130 @@ > 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); >- offset += (inode->i_size & (inode->i_sb->s_blocksize - 1)); >+ etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); >+ byte_offset = (offset << sb->s_blocksize_bits) + (inode->i_size & (sb->s_blocksize-1)); > if (etype != -1) > { >- extoffset -= adsize; >- extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset); >- extoffset += adsize; >- >- if (offset) >- lenalloc = extoffset; >+ epos.offset -= adsize; >+ extent_trunc(inode, &epos, eloc, etype, elen, byte_offset); >+ epos.offset += adsize; >+ if (byte_offset) >+ 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(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 + >+ if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201) >+ 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(sb, udf_get_lb_pblock(sb, eloc, 0)); > if (elen) >- lelen = (elen + inode->i_sb->s_blocksize - 1) >> >- inode->i_sb->s_blocksize_bits; >+ indirect_ext_len = (elen + >+ sb->s_blocksize - 1) >> >+ 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(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 + >+ if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(sb) >= 0x0201) >+ 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); > } > } > } > else if (inode->i_size) > { >- if (offset) >+ if (byte_offset) > { >+ kernel_long_ad extent; >+ > /* > * OK, there is not extent covering inode->i_size and > * no extent above inode->i_size => truncate is >- * extending the file by 'offset'. >+ * extending the file by 'offset' blocks. > */ >- if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) || >- (bh && extoffset == sizeof(struct allocExtDesc))) { >- /* File has no extents at all! */ >- memset(&eloc, 0x00, sizeof(kernel_lb_addr)); >- elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; >- udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); >+ if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || >+ (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { >+ /* File has no extents at all or has empty last >+ * indirect extent! Create a fake extent... */ >+ extent.extLocation.logicalBlockNum = 0; >+ extent.extLocation.partitionReferenceNum = 0; >+ extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; > } > else { >- extoffset -= adsize; >- etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1); >- if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) >- { >- extoffset -= adsize; >- elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset); >- udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); >- } >- else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) >- { >- kernel_lb_addr neloc = { 0, 0 }; >- extoffset -= adsize; >- nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | >- ((elen + 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); >- } >- else >- { >- if (elen & (inode->i_sb->s_blocksize - 1)) >- { >- extoffset -= 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); >- } >- memset(&eloc, 0x00, sizeof(kernel_lb_addr)); >- elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; >- udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); >- } >+ epos.offset -= adsize; >+ etype = udf_next_aext(inode, &epos, >+ &extent.extLocation, &extent.extLength, 0); >+ extent.extLength |= etype << 30; > } >+ udf_extend_file(inode, &epos, &extent, offset+((inode->i_size & (sb->s_blocksize-1)) != 0)); > } > } > UDF_I_LENEXTENTS(inode) = inode->i_size; > >- udf_release_data(bh); >+ brelse(epos.bh); > } >diff -urN kernel-source-2.6.18.orig/fs/udf/udfdecl.h kernel-source-2.6.18/fs/udf/udfdecl.h >--- kernel-source-2.6.18.orig/fs/udf/udfdecl.h 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/udfdecl.h 2007-08-14 03:26:08 +0300 >@@ -42,9 +42,9 @@ > struct buffer_head; > struct super_block; > >-extern struct inode_operations udf_dir_inode_operations; >+extern const struct inode_operations udf_dir_inode_operations; > extern const struct file_operations udf_dir_operations; >-extern struct inode_operations udf_file_inode_operations; >+extern const struct inode_operations udf_file_inode_operations; > extern const struct file_operations udf_file_operations; > extern const struct address_space_operations udf_aops; > extern const struct address_space_operations udf_adinicb_aops; >@@ -77,6 +77,13 @@ > 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 *, ...); >@@ -98,13 +105,14 @@ > 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 *, long); >-extern int8_t inode_bmap(struct inode *, int, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_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 long udf_block_map(struct inode *, sector_t); >+extern int udf_extend_file(struct inode *, struct extent_position *, kernel_long_ad *, sector_t); >+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); >@@ -113,7 +121,6 @@ > extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t); > extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *); > extern struct buffer_head *udf_read_ptagged(struct super_block *, kernel_lb_addr, uint32_t, uint16_t *); >-extern void udf_release_data(struct buffer_head *); > extern void udf_update_tag(char *, int); > extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int); > >@@ -139,6 +146,7 @@ > extern struct inode * udf_new_inode (struct inode *, int, int *); > > /* truncate.c */ >+extern void udf_truncate_tail_extent(struct inode *); > extern void udf_discard_prealloc(struct inode *); > extern void udf_truncate_extents(struct inode *); > >@@ -151,7 +159,7 @@ > 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 *, uint32_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); >diff -urN kernel-source-2.6.18.orig/fs/udf/udf_sb.h kernel-source-2.6.18/fs/udf/udf_sb.h >--- kernel-source-2.6.18.orig/fs/udf/udf_sb.h 2006-09-20 06:42:06 +0300 >+++ kernel-source-2.6.18/fs/udf/udf_sb.h 2007-08-14 03:26:08 +0300 >@@ -93,7 +93,7 @@ > for (i=0; i<nr_groups; i++)\ > {\ > if (UDF_SB_BITMAP(X,Y,Z,i))\ >- udf_release_data(UDF_SB_BITMAP(X,Y,Z,i));\ >+ brelse(UDF_SB_BITMAP(X,Y,Z,i));\ > }\ > if (size <= PAGE_SIZE)\ > kfree(UDF_SB_PARTMAPS(X)[Y].Z.s_bitmap);\
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 12565
: 2145