LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 0/6] UDF cleanup and fixes
@ 2007-03-06 16:44 Jan Kara
  2007-03-06 16:46 ` [PATCH 1/6] " Jan Kara
                   ` (7 more replies)
  0 siblings, 8 replies; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:44 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

  Hello,

  the patches attached to six following emails implement some cleanup and
fixes in the UDF code. The main two fixes are:
  1) UDF now works correctly for files larger than 1GB.
  2) Deleting a directory updates number of links to the parent directory
     correctly.
See headers of following patches for details.

The patches sustained some torturing so I hope that I did not introduce
more bugs than I've fixed ;).  Andrew, could you please put the patches
into -mm kernels for testing?  Thanks.

									Honza

-- 
Jan Kara <jack@suse.cz>
SuSE CR Labs

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 1/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
@ 2007-03-06 16:46 ` Jan Kara
  2007-03-07  9:37   ` Christoph Hellwig
  2007-03-06 16:46 ` [PATCH 2/6] " Jan Kara
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:46 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

  Use sector_t and loff_t for file offsets in UDF filesystem. Otherwise
an overflow may occur for long files. Also make inode_bmap() return offset in
the extent in number of blocks instead of number of bytes - for most callers
this is more convenient.

Signed-off-by: Jan Kara <jack@suse.cz>

diff -rupX /home/jack/.kerndiffexclude linux-2.6.20/fs/udf/dir.c linux-2.6.20-1-udf_bmap_sector_t/fs/udf/dir.c
--- linux-2.6.20/fs/udf/dir.c	2007-02-07 12:03:24.000000000 +0100
+++ linux-2.6.20-1-udf_bmap_sector_t/fs/udf/dir.c	2007-02-19 17:03:07.000000000 +0100
@@ -113,7 +113,8 @@ do_udf_readdir(struct inode * dir, struc
 	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;
+	uint32_t extoffset, elen;
+	sector_t offset;
 	int i, num;
 	unsigned int dt_type;
 
@@ -129,7 +130,6 @@ do_udf_readdir(struct inode * dir, struc
 	else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
-		offset >>= dir->i_sb->s_blocksize_bits;
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20/fs/udf/directory.c linux-2.6.20-1-udf_bmap_sector_t/fs/udf/directory.c
--- linux-2.6.20/fs/udf/directory.c	2007-02-19 15:37:14.000000000 +0100
+++ linux-2.6.20-1-udf_bmap_sector_t/fs/udf/directory.c	2007-02-21 17:58:54.000000000 +0100
@@ -77,7 +77,7 @@ udf_fileident_read(struct inode *dir, lo
 	struct fileIdentDesc *cfi,
 	kernel_lb_addr *bloc, uint32_t *extoffset, 
 	kernel_lb_addr *eloc, uint32_t *elen,
-	uint32_t *offset, struct buffer_head **bh)
+	sector_t *offset, struct buffer_head **bh)
 {
 	struct fileIdentDesc *fi;
 	int i, num, block;
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20/fs/udf/inode.c linux-2.6.20-1-udf_bmap_sector_t/fs/udf/inode.c
--- linux-2.6.20/fs/udf/inode.c	2007-02-19 14:13:12.000000000 +0100
+++ linux-2.6.20-1-udf_bmap_sector_t/fs/udf/inode.c	2007-02-19 17:04:27.000000000 +0100
@@ -49,7 +49,7 @@ MODULE_LICENSE("GPL");
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
-static struct buffer_head *inode_getblk(struct inode *, long, int *,
+static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
 	long *, int *);
 static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
 	kernel_lb_addr, uint32_t, struct buffer_head *);
@@ -354,7 +354,7 @@ udf_getblk(struct inode *inode, long blo
 	return NULL;
 }
 
-static struct buffer_head * inode_getblk(struct inode * inode, long block,
+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;
@@ -364,14 +364,15 @@ static struct buffer_head * inode_getblk
 	uint32_t elen = 0;
 	kernel_lb_addr eloc, pbloc, cbloc, nbloc;
 	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;
 
 	pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
-	b_off = (uint64_t)block << inode->i_sb->s_blocksize_bits;
+	b_off = (loff_t)block << inode->i_sb->s_blocksize_bits;
 	pbloc = cbloc = nbloc = UDF_I_LOCATION(inode);
 
 	/* find the extent which contains the block we are looking for.
@@ -1948,10 +1949,10 @@ int8_t udf_delete_aext(struct inode *ino
 	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, kernel_lb_addr *bloc, uint32_t *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset, struct buffer_head **bh)
 {
-	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)
@@ -1968,29 +1969,30 @@ int8_t inode_bmap(struct inode *inode, i
 	{
 		if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 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;
+	uint32_t extoffset, elen;
+	sector_t offset;
 	struct buffer_head *bh = NULL;
 	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);
+		ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
 	else
 		ret = 0;
 
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20/fs/udf/namei.c linux-2.6.20-1-udf_bmap_sector_t/fs/udf/namei.c
--- linux-2.6.20/fs/udf/namei.c	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-1-udf_bmap_sector_t/fs/udf/namei.c	2007-02-19 17:03:07.000000000 +0100
@@ -156,7 +156,8 @@ udf_find_entry(struct inode *dir, struct
 	uint16_t liu;
 	loff_t size;
 	kernel_lb_addr bloc, eloc;
-	uint32_t extoffset, elen, offset;
+	uint32_t extoffset, elen;
+	sector_t offset;
 	struct buffer_head *bh = NULL;
 
 	size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
@@ -168,7 +169,6 @@ udf_find_entry(struct inode *dir, struct
 	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
-		offset >>= dir->i_sb->s_blocksize_bits;
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
@@ -354,7 +354,8 @@ udf_add_entry(struct inode *dir, struct 
 	uint16_t liu;
 	int block;
 	kernel_lb_addr bloc, eloc;
-	uint32_t extoffset, elen, offset;
+	uint32_t extoffset, elen;
+	sector_t offset;
 	struct buffer_head *bh = NULL;
 
 	sb = dir->i_sb;
@@ -386,7 +387,6 @@ udf_add_entry(struct inode *dir, struct 
 	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
-		offset >>= dir->i_sb->s_blocksize_bits;
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
@@ -782,7 +782,8 @@ static int empty_dir(struct inode *dir)
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	int block;
 	kernel_lb_addr bloc, eloc;
-	uint32_t extoffset, elen, offset;
+	uint32_t extoffset, elen;
+	sector_t offset;
 	struct buffer_head *bh = NULL;
 
 	f_pos = (udf_ext0_offset(dir) >> 2);
@@ -794,7 +795,6 @@ static int empty_dir(struct inode *dir)
 	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 		&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
 	{
-		offset >>= dir->i_sb->s_blocksize_bits;
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20/fs/udf/truncate.c linux-2.6.20-1-udf_bmap_sector_t/fs/udf/truncate.c
--- linux-2.6.20/fs/udf/truncate.c	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-1-udf_bmap_sector_t/fs/udf/truncate.c	2007-03-01 16:03:25.000000000 +0100
@@ -125,9 +125,10 @@ void udf_discard_prealloc(struct inode *
 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;
+	uint32_t extoffset, elen, nelen = 0, lelen = 0, lenalloc;
 	int8_t etype;
-	int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
+	sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset;
+	loff_t byte_offset;
 	struct buffer_head *bh = NULL;
 	int adsize;
 
@@ -139,14 +140,14 @@ void udf_truncate_extents(struct inode *
 		adsize = 0;
 
 	etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
-	offset += (inode->i_size & (inode->i_sb->s_blocksize - 1));
+	byte_offset = (offset << inode->i_sb->s_blocksize_bits) + (inode->i_size & (inode->i_sb->s_blocksize-1));
 	if (etype != -1)
 	{
 		extoffset -= adsize;
-		extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, offset);
+		extent_trunc(inode, bloc, extoffset, eloc, etype, elen, bh, byte_offset);
 		extoffset += adsize;
 
-		if (offset)
+		if (byte_offset)
 			lenalloc = extoffset;
 		else
 			lenalloc = extoffset - adsize;
@@ -237,7 +238,7 @@ void udf_truncate_extents(struct inode *
 	}
 	else if (inode->i_size)
 	{
-		if (offset)
+		if (byte_offset)
 		{
 			/*
 			 *  OK, there is not extent covering inode->i_size and
@@ -248,7 +249,7 @@ void udf_truncate_extents(struct 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;
+				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
 				udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
 			}
 			else {
@@ -257,7 +258,7 @@ void udf_truncate_extents(struct inode *
 				if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
 				{
 					extoffset -= adsize;
-					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
+					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + byte_offset);
 					udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
 				}
 				else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
@@ -265,7 +266,7 @@ void udf_truncate_extents(struct inode *
 					kernel_lb_addr neloc = { 0, 0 };
 					extoffset -= adsize;
 					nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
-						((elen + offset + inode->i_sb->s_blocksize - 1) &
+						((elen + byte_offset + inode->i_sb->s_blocksize - 1) &
 						~(inode->i_sb->s_blocksize - 1));
 					udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
 					udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
@@ -281,7 +282,7 @@ void udf_truncate_extents(struct inode *
 						udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
 					}
 					memset(&eloc, 0x00, sizeof(kernel_lb_addr));
-					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
+					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
 					udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
 				}
 			}
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20/fs/udf/udfdecl.h linux-2.6.20-1-udf_bmap_sector_t/fs/udf/udfdecl.h
--- linux-2.6.20/fs/udf/udfdecl.h	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-1-udf_bmap_sector_t/fs/udf/udfdecl.h	2007-02-22 13:37:39.000000000 +0100
@@ -98,8 +98,8 @@ extern void udf_read_inode(struct inode 
 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 long udf_block_map(struct inode *, sector_t);
+extern int8_t inode_bmap(struct inode *, sector_t, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, sector_t *, struct buffer_head **);
 extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
 extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
 extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
@@ -151,7 +151,7 @@ extern int udf_new_block(struct super_bl
 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 *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, sector_t *, struct buffer_head **);
 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);

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
  2007-03-06 16:46 ` [PATCH 1/6] " Jan Kara
@ 2007-03-06 16:46 ` Jan Kara
  2007-03-07  9:37   ` Christoph Hellwig
  2007-03-06 16:47 ` [PATCH 3/6] " Jan Kara
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:46 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

Introduce a structure extent_position to store a position of an extent and
the corresponding buffer_head in one place.

Signed-off-by: Jan Kara <jack@suse.cz>

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

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
  2007-03-06 16:46 ` [PATCH 1/6] " Jan Kara
  2007-03-06 16:46 ` [PATCH 2/6] " Jan Kara
@ 2007-03-06 16:47 ` Jan Kara
  2007-03-07  9:38   ` Christoph Hellwig
  2007-03-06 16:47 ` [PATCH 4/6] " Jan Kara
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:47 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

Make UDF use get_bh() instead of directly accessing b_count and use brelse()
instead of udf_release_data() which does just brelse()...

Signed-off-by: Jan Kara <jack@suse.cz>

diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/balloc.c linux-2.6.20-3-udf_buffer_handling/fs/udf/balloc.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/balloc.c	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/balloc.c	2007-03-06 16:38:05.000000000 +0100
@@ -508,8 +508,8 @@ static void udf_table_free_blocks(struct
 		{
 			i = -1;
 			oepos.block = epos.block;
-			udf_release_data(oepos.bh);
-			atomic_inc(&epos.bh->b_count);
+			brelse(oepos.bh);
+			get_bh(epos.bh);
 			oepos.bh = epos.bh;
 			oepos.offset = 0;
 		}
@@ -546,8 +546,8 @@ static void udf_table_free_blocks(struct
 			adsize = sizeof(long_ad);
 		else
 		{
-			udf_release_data(oepos.bh);
-			udf_release_data(epos.bh);
+			brelse(oepos.bh);
+			brelse(epos.bh);
 			goto error_return;
 		}
 
@@ -556,7 +556,7 @@ static void udf_table_free_blocks(struct
 			char *sptr, *dptr;
 			int loffset;
 	
-			udf_release_data(oepos.bh);
+			brelse(oepos.bh);
 			oepos = epos;
 
 			/* Steal a block from the extent being free'd */
@@ -567,7 +567,7 @@ static void udf_table_free_blocks(struct
 			if (!(epos.bh = udf_tread(sb,
 				udf_get_lb_pblock(sb, epos.block, 0))))
 			{
-				udf_release_data(oepos.bh);
+				brelse(oepos.bh);
 				goto error_return;
 			}
 			aed = (struct allocExtDesc *)(epos.bh->b_data);
@@ -658,8 +658,8 @@ static void udf_table_free_blocks(struct
 		}
 	}
 
-	udf_release_data(epos.bh);
-	udf_release_data(oepos.bh);
+	brelse(epos.bh);
+	brelse(oepos.bh);
 
 error_return:
 	sb->s_dirt = 1;
@@ -723,7 +723,7 @@ static int udf_table_prealloc_blocks(str
 	else
 		alloc_count = 0;
 
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 
 	if (alloc_count && UDF_SB_LVIDBH(sb))
 	{
@@ -789,9 +789,9 @@ static int udf_table_new_block(struct su
 			spread = nspread;
 			if (goal_epos.bh != epos.bh)
 			{
-				udf_release_data(goal_epos.bh);
+				brelse(goal_epos.bh);
 				goal_epos.bh = epos.bh;
-				atomic_inc(&goal_epos.bh->b_count);
+				get_bh(goal_epos.bh);
 			}
 			goal_epos.block = epos.block;
 			goal_epos.offset = epos.offset - adsize;
@@ -800,11 +800,11 @@ static int udf_table_new_block(struct su
 		}
 	}
 
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 
 	if (spread == 0xFFFFFFFF)
 	{
-		udf_release_data(goal_epos.bh);
+		brelse(goal_epos.bh);
 		mutex_unlock(&sbi->s_alloc_mutex);
 		return 0;
 	}
@@ -820,7 +820,7 @@ static int udf_table_new_block(struct su
 
 	if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
 	{
-		udf_release_data(goal_epos.bh);
+		brelse(goal_epos.bh);
 		mutex_unlock(&sbi->s_alloc_mutex);
 		*err = -EDQUOT;
 		return 0;
@@ -830,7 +830,7 @@ static int udf_table_new_block(struct su
 		udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1);
 	else
 		udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
-	udf_release_data(goal_epos.bh);
+	brelse(goal_epos.bh);
 
 	if (UDF_SB_LVIDBH(sb))
 	{
@@ -915,11 +915,14 @@ inline int udf_new_block(struct super_bl
 	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 -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/dir.c linux-2.6.20-3-udf_buffer_handling/fs/udf/dir.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/dir.c	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/dir.c	2007-02-22 14:57:59.000000000 +0100
@@ -144,7 +144,7 @@ do_udf_readdir(struct inode * dir, struc
 
 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		{
-			udf_release_data(epos.bh);
+			brelse(epos.bh);
 			return -EIO;
 		}
 	
@@ -172,7 +172,7 @@ do_udf_readdir(struct inode * dir, struc
 	}
 	else
 	{
-		udf_release_data(epos.bh);
+		brelse(epos.bh);
 		return -ENOENT;
 	}
 
@@ -185,9 +185,9 @@ do_udf_readdir(struct inode * dir, struc
 		if (!fi)
 		{
 			if (fibh.sbh != fibh.ebh)
-				udf_release_data(fibh.ebh);
-			udf_release_data(fibh.sbh);
-			udf_release_data(epos.bh);
+				brelse(fibh.ebh);
+			brelse(fibh.sbh);
+			brelse(epos.bh);
 			return 0;
 		}
 
@@ -245,9 +245,9 @@ do_udf_readdir(struct inode * dir, struc
 			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(epos.bh);
+					brelse(fibh.ebh);
+				brelse(fibh.sbh);
+				brelse(epos.bh);
 	 			return 0;
 			}
 		}
@@ -256,9 +256,9 @@ do_udf_readdir(struct inode * dir, struc
 	filp->f_pos = nf_pos + 1;
 
 	if (fibh.sbh != fibh.ebh)
-		udf_release_data(fibh.ebh);
-	udf_release_data(fibh.sbh);
-	udf_release_data(epos.bh);
+		brelse(fibh.ebh);
+	brelse(fibh.sbh);
+	brelse(epos.bh);
 
 	return 0;
 }
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/directory.c linux-2.6.20-3-udf_buffer_handling/fs/udf/directory.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/directory.c	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/directory.c	2007-02-22 14:57:59.000000000 +0100
@@ -36,14 +36,14 @@ udf_filead_read(struct inode *dir, uint8
 
 	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 @@ udf_filead_read(struct inode *dir, uint8
 		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;
@@ -120,7 +120,7 @@ udf_fileident_read(struct inode *dir, lo
 		else
 			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;
@@ -149,7 +149,7 @@ udf_fileident_read(struct inode *dir, lo
 	}
 	else if (fibh->sbh != fibh->ebh)
 	{
-		udf_release_data(fibh->sbh);
+		brelse(fibh->sbh);
 		fibh->sbh = fibh->ebh;
 	}
 
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/inode.c linux-2.6.20-3-udf_buffer_handling/fs/udf/inode.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/inode.c	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/inode.c	2007-02-22 14:57:59.000000000 +0100
@@ -247,7 +247,7 @@ struct buffer_head * udf_expand_dir_adin
 		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;
@@ -259,7 +259,7 @@ struct buffer_head * udf_expand_dir_adin
 			sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
 		{
 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
-			udf_release_data(dbh);
+			brelse(dbh);
 			return NULL;
 		}
 	}
@@ -277,7 +277,7 @@ struct buffer_head * udf_expand_dir_adin
 	udf_add_aext(inode, &epos, eloc, elen, 0);
 	/* UniqueID stuff */
 
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 	mark_inode_dirty(inode);
 	return dbh;
 }
@@ -386,14 +386,14 @@ static struct buffer_head * inode_getblk
 	{
 		if (prev_epos.bh != cur_epos.bh)
 		{
-			udf_release_data(prev_epos.bh);
-			atomic_inc(&cur_epos.bh->b_count);
+			brelse(prev_epos.bh);
+			get_bh(cur_epos.bh);
 			prev_epos.bh = cur_epos.bh;
 		}
 		if (cur_epos.bh != next_epos.bh)
 		{
-			udf_release_data(cur_epos.bh);
-			atomic_inc(&next_epos.bh->b_count);
+			brelse(cur_epos.bh);
+			get_bh(next_epos.bh);
 			cur_epos.bh = next_epos.bh;
 		}
 
@@ -436,9 +436,9 @@ static struct buffer_head * inode_getblk
 				~(inode->i_sb->s_blocksize - 1));
 			etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1);
 		}
-		udf_release_data(prev_epos.bh);
-		udf_release_data(cur_epos.bh);
-		udf_release_data(next_epos.bh);
+		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;
@@ -492,8 +492,8 @@ static struct buffer_head * inode_getblk
 		else
 			lastblock = 1;
 	}
-	udf_release_data(cur_epos.bh);
-	udf_release_data(next_epos.bh);
+	brelse(cur_epos.bh);
+	brelse(next_epos.bh);
 
 	/* if the current extent is not recorded but allocated, get the
 		block in the extent corresponding to the requested block */
@@ -513,7 +513,7 @@ static struct buffer_head * inode_getblk
 		if (!(newblocknum = udf_new_block(inode->i_sb, inode,
 			UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
 		{
-			udf_release_data(prev_epos.bh);
+			brelse(prev_epos.bh);
 			*err = -ENOSPC;
 			return NULL;
 		}
@@ -538,7 +538,7 @@ static struct buffer_head * inode_getblk
        the new number of extents is less than the old number */
 	udf_update_extents(inode, laarr, startnum, endnum, &prev_epos);
 
-	udf_release_data(prev_epos.bh);
+	brelse(prev_epos.bh);
 
 	if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
 		UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
@@ -934,7 +934,7 @@ __udf_read_inode(struct inode *inode)
 	{
 		printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",
 			inode->i_ino, ident);
-		udf_release_data(bh);
+		brelse(bh);
 		make_bad_inode(inode);
 		return;
 	}
@@ -963,35 +963,35 @@ __udf_read_inode(struct inode *inode)
 						ident == TAG_IDENT_EFE)
 					{
 						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
-						udf_release_data(bh);
-						udf_release_data(ibh);
-						udf_release_data(nbh);
+						brelse(bh);
+						brelse(ibh);
+						brelse(nbh);
 						__udf_read_inode(inode);
 						return;
 					}
 					else
 					{
-						udf_release_data(nbh);
-						udf_release_data(ibh);
+						brelse(nbh);
+						brelse(ibh);
 					}
 				}
 				else
-					udf_release_data(ibh);
+					brelse(ibh);
 			}
 		}
 		else
-			udf_release_data(ibh);
+			brelse(ibh);
 	}
 	else if (le16_to_cpu(fe->icbTag.strategyType) != 4)
 	{
 		printk(KERN_ERR "udf: unsupported strategy type: %d\n",
 			le16_to_cpu(fe->icbTag.strategyType));
-		udf_release_data(bh);
+		brelse(bh);
 		make_bad_inode(inode);
 		return;
 	}
 	udf_fill_inode(inode, bh);
-	udf_release_data(bh);
+	brelse(bh);
 }
 
 static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
@@ -1334,7 +1334,7 @@ udf_update_inode(struct inode *inode, in
 				use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i];
 
 		mark_buffer_dirty(bh);
-		udf_release_data(bh);
+		brelse(bh);
 		return err;
 	}
 
@@ -1523,7 +1523,7 @@ udf_update_inode(struct inode *inode, in
 			err = -EIO;
 		}
 	}
-	udf_release_data(bh);
+	brelse(bh);
 	return err;
 }
 
@@ -1670,7 +1670,7 @@ int8_t udf_add_aext(struct inode *inode,
 			else
 				udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));
 			mark_buffer_dirty_inode(epos->bh, inode);
-			udf_release_data(epos->bh);
+			brelse(epos->bh);
 		}
 		else
 			mark_inode_dirty(inode);
@@ -1761,7 +1761,7 @@ int8_t udf_next_aext(struct inode *inode
 	{
 		epos->block = *eloc;
 		epos->offset = sizeof(struct allocExtDesc);
-		udf_release_data(epos->bh);
+		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",
@@ -1841,7 +1841,7 @@ udf_insert_aext(struct inode *inode, str
 	int8_t etype;
 
 	if (epos.bh)
-		atomic_inc(&epos.bh->b_count);
+		get_bh(epos.bh);
 
 	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1)
 	{
@@ -1851,7 +1851,7 @@ udf_insert_aext(struct inode *inode, str
 		nelen = (etype << 30) | oelen;
 	}
 	udf_add_aext(inode, &epos, neloc, nelen, 1);
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 	return (nelen >> 30);
 }
 
@@ -1865,8 +1865,8 @@ int8_t udf_delete_aext(struct inode *ino
 
 	if (epos.bh)
 	{
-		atomic_inc(&epos.bh->b_count);
-		atomic_inc(&epos.bh->b_count);
+		get_bh(epos.bh);
+		get_bh(epos.bh);
 	}
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -1886,8 +1886,8 @@ int8_t udf_delete_aext(struct inode *ino
 		if (oepos.bh != epos.bh)
 		{
 			oepos.block = epos.block;
-			udf_release_data(oepos.bh);
-			atomic_inc(&epos.bh->b_count);
+			brelse(oepos.bh);
+			get_bh(epos.bh);
 			oepos.bh = epos.bh;
 			oepos.offset = epos.offset - adsize;
 		}
@@ -1938,8 +1938,8 @@ int8_t udf_delete_aext(struct inode *ino
 		}
 	}
 	
-	udf_release_data(epos.bh);
-	udf_release_data(oepos.bh);
+	brelse(epos.bh);
+	brelse(oepos.bh);
 	return (elen >> 30);
 }
 
@@ -1992,7 +1992,7 @@ long udf_block_map(struct inode *inode, 
 		ret = 0;
 
 	unlock_kernel();
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
 		return udf_fixed_to_variable(ret);
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/misc.c linux-2.6.20-3-udf_buffer_handling/fs/udf/misc.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/misc.c	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/misc.c	2007-02-22 14:57:59.000000000 +0100
@@ -274,12 +274,6 @@ udf_read_ptagged(struct super_block *sb,
 		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 -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/namei.c linux-2.6.20-3-udf_buffer_handling/fs/udf/namei.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/namei.c	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/namei.c	2007-02-22 14:57:59.000000000 +0100
@@ -182,13 +182,13 @@ udf_find_entry(struct inode *dir, struct
 
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		{
-			udf_release_data(epos.bh);
+			brelse(epos.bh);
 			return NULL;
 		}
 	}
 	else
 	{
-		udf_release_data(epos.bh);
+		brelse(epos.bh);
 		return NULL;
 	}
 
@@ -199,9 +199,9 @@ udf_find_entry(struct inode *dir, struct
 		if (!fi)
 		{
 			if (fibh->sbh != fibh->ebh)
-				udf_release_data(fibh->ebh);
-			udf_release_data(fibh->sbh);
-			udf_release_data(epos.bh);
+				brelse(fibh->ebh);
+			brelse(fibh->sbh);
+			brelse(epos.bh);
 			return NULL;
 		}
 
@@ -247,15 +247,15 @@ udf_find_entry(struct inode *dir, struct
 		{
 			if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
 			{
-				udf_release_data(epos.bh);
+				brelse(epos.bh);
 				return fi;
 			}
 		}
 	}
 	if (fibh->sbh != fibh->ebh)
-		udf_release_data(fibh->ebh);
-	udf_release_data(fibh->sbh);
-	udf_release_data(epos.bh);
+		brelse(fibh->ebh);
+	brelse(fibh->sbh);
+	brelse(epos.bh);
 	return NULL;
 }
 
@@ -321,8 +321,8 @@ udf_lookup(struct inode *dir, struct den
 	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 )
@@ -400,7 +400,7 @@ udf_add_entry(struct inode *dir, struct 
 
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		{
-			udf_release_data(epos.bh);
+			brelse(epos.bh);
 			*err = -EIO;
 			return NULL;
 		}
@@ -423,9 +423,9 @@ udf_add_entry(struct inode *dir, struct 
 		if (!fi)
 		{
 			if (fibh->sbh != fibh->ebh)
-				udf_release_data(fibh->ebh);
-			udf_release_data(fibh->sbh);
-			udf_release_data(epos.bh);
+				brelse(fibh->ebh);
+			brelse(fibh->sbh);
+			brelse(epos.bh);
 			*err = -EIO;
 			return NULL;
 		}
@@ -455,7 +455,7 @@ udf_add_entry(struct inode *dir, struct 
 		{
 			if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
 			{
-				udf_release_data(epos.bh);
+				brelse(epos.bh);
 				cfi->descTag.tagSerialNum = cpu_to_le16(1);
 				cfi->fileVersionNum = cpu_to_le16(1);
 				cfi->fileCharacteristics = 0;
@@ -478,9 +478,9 @@ udf_add_entry(struct inode *dir, struct 
 			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(epos.bh);
+				brelse(fibh->ebh);
+			brelse(fibh->sbh);
+			brelse(epos.bh);
 			*err = -EEXIST;
 			return NULL;
 		}
@@ -492,14 +492,14 @@ add:
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
 		sb->s_blocksize - fibh->eoffset < nfidlen)
 	{
-		udf_release_data(epos.bh);
+		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;
 		epos.block = UDF_I_LOCATION(dir);
@@ -519,7 +519,7 @@ add:
 		fibh->eoffset += nfidlen;
 		if (fibh->sbh != fibh->ebh)
 		{
-			udf_release_data(fibh->sbh);
+			brelse(fibh->sbh);
 			fibh->sbh = fibh->ebh;
 		}
 
@@ -541,7 +541,7 @@ add:
 		fibh->eoffset += nfidlen - sb->s_blocksize;
 		if (fibh->sbh != fibh->ebh)
 		{
-			udf_release_data(fibh->sbh);
+			brelse(fibh->sbh);
 			fibh->sbh = fibh->ebh;
 		}
 
@@ -550,8 +550,8 @@ add:
 
 		if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
 		{
-			udf_release_data(epos.bh);
-			udf_release_data(fibh->sbh);
+			brelse(epos.bh);
+			brelse(fibh->sbh);
 			return NULL;
 		}
 
@@ -566,7 +566,7 @@ add:
 			else
 				block ++;
 
-			udf_release_data(fibh->sbh);
+			brelse(fibh->sbh);
 			fibh->sbh = fibh->ebh;
 			fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
 		}
@@ -587,7 +587,7 @@ add:
 	cfi->lengthOfImpUse = cpu_to_le16(0);
 	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
 	{
-		udf_release_data(epos.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 +596,10 @@ add:
 	}
 	else
 	{
-		udf_release_data(epos.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 +656,8 @@ static int udf_create(struct inode *dir,
 		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 +701,8 @@ static int udf_mknod(struct inode * dir,
 	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 +743,7 @@ static int udf_mkdir(struct inode * dir,
 		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 +766,8 @@ static int udf_mkdir(struct inode * dir,
 	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();
@@ -808,13 +808,13 @@ static int empty_dir(struct inode *dir)
 
 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		{
-			udf_release_data(epos.bh);
+			brelse(epos.bh);
 			return 0;
 		}
 	}
 	else
 	{
-		udf_release_data(epos.bh);
+		brelse(epos.bh);
 		return 0;
 	}
 
@@ -826,25 +826,25 @@ static int empty_dir(struct inode *dir)
 		if (!fi)
 		{
 			if (fibh.sbh != fibh.ebh)
-				udf_release_data(fibh.ebh);
-			udf_release_data(fibh.sbh);
-			udf_release_data(epos.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(epos.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(epos.bh);
+		brelse(fibh.ebh);
+	brelse(fibh.sbh);
+	brelse(epos.bh);
 	return 1;
 }
 
@@ -884,8 +884,8 @@ static int udf_rmdir(struct inode * 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;
@@ -928,8 +928,8 @@ static int udf_unlink(struct inode * dir
 
 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;
@@ -977,7 +977,7 @@ static int udf_symlink(struct inode * di
 		elen = inode->i_sb->s_blocksize;
 		UDF_I_LENEXTENTS(inode) = elen;
 		udf_add_aext(inode, &epos, eloc, elen, 0);
-		udf_release_data(epos.bh);
+		brelse(epos.bh);
 
 		block = udf_get_pblock(inode->i_sb, block,
 			UDF_I_LOCATION(inode).partitionReferenceNum, 0);
@@ -1060,7 +1060,7 @@ static int udf_symlink(struct inode * di
 		}
 	}
 
-	udf_release_data(epos.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;
@@ -1089,8 +1089,8 @@ static int udf_symlink(struct inode * di
 		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;
 
@@ -1145,8 +1145,8 @@ static int udf_link(struct dentry * old_
 		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);
 	inc_nlink(inode);
 	inode->i_ctime = current_fs_time(inode->i_sb);
 	mark_inode_dirty(inode);
@@ -1174,8 +1174,8 @@ static int udf_rename (struct inode * ol
 	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)
@@ -1188,8 +1188,8 @@ static int udf_rename (struct inode * ol
 		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;
 		}
 	}
@@ -1290,19 +1290,19 @@ static int udf_rename (struct inode * ol
 	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;
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/partition.c linux-2.6.20-3-udf_buffer_handling/fs/udf/partition.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/partition.c	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/partition.c	2007-02-22 14:57:59.000000000 +0100
@@ -81,7 +81,7 @@ uint32_t udf_get_pblock_virt15(struct su
 
 	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 -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/super.c linux-2.6.20-3-udf_buffer_handling/fs/udf/super.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/super.c	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/super.c	2007-02-22 14:57:59.000000000 +0100
@@ -565,7 +565,7 @@ udf_vrs(struct super_block *sb, int sile
 
 		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))
@@ -598,7 +598,7 @@ udf_vrs(struct super_block *sb, int sile
 		}
 		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))
@@ -609,7 +609,7 @@ udf_vrs(struct super_block *sb, int sile
 		{
 			nsr03 = sector;
 		}
-		udf_release_data(bh);
+		brelse(bh);
 	}
 
 	if (nsr03)
@@ -675,7 +675,7 @@ udf_find_anchor(struct super_block *sb)
 			{
 				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)
@@ -710,7 +710,7 @@ udf_find_anchor(struct super_block *sb)
 				{
 					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 &&
@@ -729,7 +729,7 @@ udf_find_anchor(struct super_block *sb)
 					{
 						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 &&
@@ -751,7 +751,7 @@ udf_find_anchor(struct super_block *sb)
 		{
 			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);
@@ -768,7 +768,7 @@ udf_find_anchor(struct super_block *sb)
 			}
 			else
 			{
-				udf_release_data(bh);
+				brelse(bh);
 				if ((ident != TAG_IDENT_AVDP) && (i ||
 					(ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE)))
 				{
@@ -797,7 +797,7 @@ udf_find_fileset(struct super_block *sb,
 			return 1;
 		else if (ident != TAG_IDENT_FSD)
 		{
-			udf_release_data(bh);
+			brelse(bh);
 			return 1;
 		}
 			
@@ -836,7 +836,7 @@ udf_find_fileset(struct super_block *sb,
 						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:
@@ -847,7 +847,7 @@ udf_find_fileset(struct super_block *sb,
 					default:
 					{
 						newfileset.logicalBlockNum ++;
-						udf_release_data(bh);
+						brelse(bh);
 						bh = NULL;
 						break;
 					}
@@ -867,7 +867,7 @@ udf_find_fileset(struct super_block *sb,
 
 		UDF_SB_PARTITION(sb) = fileset->partitionReferenceNum;
 		udf_load_fileset(sb, bh, root);
-		udf_release_data(bh);
+		brelse(bh);
 		return 0;
 	}
 	return 1;
@@ -1085,7 +1085,7 @@ udf_load_logicalvol(struct super_block *
 						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;
 						}
 					}
@@ -1139,12 +1139,12 @@ udf_load_logicalvolint(struct super_bloc
 			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);
 }
 
 /*
@@ -1247,7 +1247,7 @@ udf_process_sequence(struct super_block 
 					done = 1;
 				break;
 		}
-		udf_release_data(bh);
+		brelse(bh);
 	}
 	for (i=0; i<VDS_POS_LENGTH; i++)
 	{
@@ -1269,10 +1269,10 @@ udf_process_sequence(struct super_block 
 					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);
 		}
 	}
 
@@ -1335,7 +1335,7 @@ udf_load_partition(struct super_block *s
 			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) */
@@ -1410,7 +1410,7 @@ udf_load_partition(struct super_block *s
 							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);
@@ -1682,7 +1682,7 @@ error_out:
 		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
@@ -1691,7 +1691,7 @@ error_out:
 #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;
@@ -1760,7 +1760,7 @@ udf_put_super(struct super_block *sb)
 		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
@@ -1769,7 +1769,7 @@ udf_put_super(struct super_block *sb)
 #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;
@@ -1839,7 +1839,7 @@ udf_count_free_bitmap(struct super_block
 	}
 	else if (ident != TAG_IDENT_SBD)
 	{
-		udf_release_data(bh);
+		brelse(bh);
 		printk(KERN_ERR "udf: udf_count_free failed\n");
 		goto out;
 	}
@@ -1861,7 +1861,7 @@ udf_count_free_bitmap(struct super_block
 		}
 		if ( bytes )
 		{
-			udf_release_data(bh);
+			brelse(bh);
 			newblock = udf_get_lb_pblock(sb, loc, ++block);
 			bh = udf_tread(sb, newblock);
 			if (!bh)
@@ -1873,7 +1873,7 @@ udf_count_free_bitmap(struct super_block
 			ptr = (uint8_t *)bh->b_data;
 		}
 	}
-	udf_release_data(bh);
+	brelse(bh);
 
 out:
 	unlock_kernel();
@@ -1898,7 +1898,7 @@ udf_count_free_table(struct super_block 
 
 	while ((etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1)
 		accum += (elen >> table->i_sb->s_blocksize_bits);
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 
 	unlock_kernel();
 
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/symlink.c linux-2.6.20-3-udf_buffer_handling/fs/udf/symlink.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/symlink.c	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/symlink.c	2007-02-22 14:57:59.000000000 +0100
@@ -95,7 +95,7 @@ static int udf_symlink_filler(struct fil
 	}
 
 	udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
-	udf_release_data(bh);
+	brelse(bh);
 
 	unlock_kernel();
 	SetPageUptodate(page);
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/truncate.c linux-2.6.20-3-udf_buffer_handling/fs/udf/truncate.c
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/truncate.c	2007-03-06 15:02:06.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/truncate.c	2007-03-06 15:02:33.000000000 +0100
@@ -119,7 +119,7 @@ void udf_discard_prealloc(struct inode *
 	}
 	UDF_I_LENEXTENTS(inode) = lbcount;
 
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 }
 
 void udf_truncate_extents(struct inode * inode)
@@ -287,5 +287,5 @@ void udf_truncate_extents(struct inode *
 	}
 	UDF_I_LENEXTENTS(inode) = inode->i_size;
 
-	udf_release_data(epos.bh);
+	brelse(epos.bh);
 }
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/udfdecl.h linux-2.6.20-3-udf_buffer_handling/fs/udf/udfdecl.h
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/udfdecl.h	2007-02-22 14:52:17.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/udfdecl.h	2007-02-26 17:13:47.000000000 +0100
@@ -106,6 +106,7 @@ extern void udf_delete_inode(struct inod
 extern void udf_clear_inode(struct inode *);
 extern int udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, sector_t);
+extern 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);
@@ -120,7 +121,6 @@ extern struct genericFormat *udf_add_ext
 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);
 
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-2-udf_extent_position_t/fs/udf/udf_sb.h linux-2.6.20-3-udf_buffer_handling/fs/udf/udf_sb.h
--- linux-2.6.20-2-udf_extent_position_t/fs/udf/udf_sb.h	2006-11-29 22:57:37.000000000 +0100
+++ linux-2.6.20-3-udf_buffer_handling/fs/udf/udf_sb.h	2007-02-22 14:57:59.000000000 +0100
@@ -93,7 +93,7 @@ static inline struct udf_sb_info *UDF_SB
 	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);\

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 4/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
                   ` (2 preceding siblings ...)
  2007-03-06 16:47 ` [PATCH 3/6] " Jan Kara
@ 2007-03-06 16:47 ` Jan Kara
  2007-03-07  9:38   ` Christoph Hellwig
  2007-03-06 16:48 ` [PATCH 5/6] " Jan Kara
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:47 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

Add a few assertions into udf_discard_prealloc() to check that the file
is sane (mostly helps debugging further patches ;).

Signed-off-by: Jan Kara <jack@suse.cz>

diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-3-udf_buffer_handling/fs/udf/truncate.c linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/truncate.c
--- linux-2.6.20-3-udf_buffer_handling/fs/udf/truncate.c	2007-03-06 15:02:33.000000000 +0100
+++ linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/truncate.c	2007-03-06 15:03:00.000000000 +0100
@@ -88,8 +88,9 @@ void udf_discard_prealloc(struct inode *
 	{
 		etype = netype;
 		lbcount += elen;
-		if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
+		if (lbcount > inode->i_size && lbcount - elen < inode->i_size)
 		{
+			WARN_ON(lbcount - inode->i_size >= inode->i_sb->s_blocksize);
 			nelen = elen - (lbcount - inode->i_size);
 			epos.offset -= adsize;
 			extent_trunc(inode, &epos, eloc, etype, elen, nelen);
@@ -119,6 +120,7 @@ void udf_discard_prealloc(struct inode *
 	}
 	UDF_I_LENEXTENTS(inode) = lbcount;
 
+	WARN_ON(lbcount != inode->i_size);
 	brelse(epos.bh);
 }
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 5/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
                   ` (3 preceding siblings ...)
  2007-03-06 16:47 ` [PATCH 4/6] " Jan Kara
@ 2007-03-06 16:48 ` Jan Kara
  2007-03-07  9:38   ` Christoph Hellwig
  2007-03-06 16:48 ` [PATCH 6/6] " Jan Kara
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:48 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

Make UDF work correctly for files larger than 1GB. As no extent can
be longer than (1<<30)-blocksize bytes, we have to create several extents
if a big hole is being created. As a side-effect, we now don't discard
preallocated blocks when creating a hole.

Signed-off-by: Jan Kara <jack@suse.cz>

diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/inode.c linux-2.6.20-5-large_file_fix/fs/udf/inode.c
--- linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/inode.c	2007-02-22 15:42:18.000000000 +0100
+++ linux-2.6.20-5-large_file_fix/fs/udf/inode.c	2007-03-06 17:23:51.000000000 +0100
@@ -356,9 +356,106 @@ udf_getblk(struct inode *inode, long blo
 	return NULL;
 }
 
+/* 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)
 {
+	static sector_t last_block;
 	struct buffer_head *result = NULL;
 	kernel_long_ad laarr[EXTENT_MERGE_SIZE];
 	struct extent_position prev_epos, cur_epos, next_epos;
@@ -371,7 +468,7 @@ static struct buffer_head * inode_getblk
 	sector_t offset = 0;
 	int8_t etype;
 	int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
-	char lastblock = 0;
+	int lastblock = 0;
 
 	prev_epos.offset = udf_file_entry_alloc_offset(inode);
 	prev_epos.block = UDF_I_LOCATION(inode);
@@ -423,6 +520,8 @@ static struct buffer_head * inode_getblk
 
 	b_off -= lbcount;
 	offset = b_off >> inode->i_sb->s_blocksize_bits;
+	/* Move into indirect extent if we are at a pointer to it */
+	udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);
 
 	/* if the extent is allocated and recorded, return the block
        if the extent is not a multiple of the blocksize, round up */
@@ -444,43 +543,66 @@ static struct buffer_head * inode_getblk
 		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 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;
@@ -489,11 +611,10 @@ static struct buffer_head * inode_getblk
 			startnum ++;
 			endnum ++;
 		}
-		else
+		else {
 			lastblock = 1;
+		}
 	}
-	brelse(cur_epos.bh);
-	brelse(next_epos.bh);
 
 	/* if the current extent is not recorded but allocated, get the
 		block in the extent corresponding to the requested block */
@@ -534,8 +655,8 @@ static struct buffer_head * inode_getblk
 	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 */
+	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);
 
 	brelse(prev_epos.bh);
@@ -991,6 +1112,7 @@ __udf_read_inode(struct inode *inode)
 		return;
 	}
 	udf_fill_inode(inode, bh);
+
 	brelse(bh);
 }
 
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/super.c linux-2.6.20-5-large_file_fix/fs/udf/super.c
--- linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/super.c	2007-02-22 14:57:59.000000000 +0100
+++ linux-2.6.20-5-large_file_fix/fs/udf/super.c	2007-02-26 17:12:15.000000000 +0100
@@ -1663,7 +1663,7 @@ static int udf_fill_super(struct super_b
 		iput(inode);
 		goto error_out;
 	}
-	sb->s_maxbytes = 1<<30;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
 	return 0;
 
 error_out:
diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/truncate.c linux-2.6.20-5-large_file_fix/fs/udf/truncate.c
--- linux-2.6.20-4-udf_discard_prealloc_cleanup/fs/udf/truncate.c	2007-03-06 15:03:00.000000000 +0100
+++ linux-2.6.20-5-large_file_fix/fs/udf/truncate.c	2007-03-06 15:10:57.000000000 +0100
@@ -130,7 +130,8 @@ void udf_truncate_extents(struct inode *
 	kernel_lb_addr eloc, neloc = { 0, 0 };
 	uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc;
 	int8_t etype;
-	sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset;
+	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;
 
@@ -142,7 +143,7 @@ void udf_truncate_extents(struct inode *
 		BUG();
 
 	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
-	byte_offset = (offset << inode->i_sb->s_blocksize_bits) + (inode->i_size & (inode->i_sb->s_blocksize-1));
+	byte_offset = (offset << sb->s_blocksize_bits) + (inode->i_size & (sb->s_blocksize-1));
 	if (etype != -1)
 	{
 		epos.offset -= adsize;
@@ -169,7 +170,7 @@ void udf_truncate_extents(struct inode *
 					 * indirect extent - free it too */
 					if (!epos.bh)
 						BUG();
-					udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len);
+					udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len);
 				}
 				else
 				{
@@ -182,7 +183,7 @@ void udf_truncate_extents(struct inode *
 					{
 						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)
+						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
@@ -193,11 +194,11 @@ void udf_truncate_extents(struct inode *
 				brelse(epos.bh);
 				epos.offset = sizeof(struct allocExtDesc);
 				epos.block = eloc;
-				epos.bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, eloc, 0));
+				epos.bh = udf_tread(sb, udf_get_lb_pblock(sb, eloc, 0));
 				if (elen)
 					indirect_ext_len = (elen +
-						inode->i_sb->s_blocksize - 1) >>
-						inode->i_sb->s_blocksize_bits;
+						sb->s_blocksize - 1) >>
+						sb->s_blocksize_bits;
 				else
 					indirect_ext_len = 1;
 			}
@@ -212,7 +213,7 @@ void udf_truncate_extents(struct inode *
 		{
 			if (!epos.bh)
 				BUG();
-			udf_free_blocks(inode->i_sb, inode, epos.block, 0, indirect_ext_len);
+			udf_free_blocks(sb, inode, epos.block, 0, indirect_ext_len);
 		}
 		else
 		{
@@ -225,7 +226,7 @@ void udf_truncate_extents(struct inode *
 			{
 				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)
+				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
@@ -238,53 +239,28 @@ void udf_truncate_extents(struct inode *
 	{
 		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 ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
 			    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
-				/* File has no extents at all! */
-				memset(&eloc, 0x00, sizeof(kernel_lb_addr));
-				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
-				udf_add_aext(inode, &epos, eloc, elen, 1);
+				/* 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 {
 				epos.offset -= adsize;
-				etype = udf_next_aext(inode, &epos, &eloc, &elen, 1);
-
-				if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
-				{
-					epos.offset -= adsize;
-					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + byte_offset);
-					udf_write_aext(inode, &epos, eloc, elen, 0);
-				}
-				else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
-				{
-					kernel_lb_addr neloc = { 0, 0 };
-					epos.offset -= adsize;
-					nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
-						((elen + byte_offset + inode->i_sb->s_blocksize - 1) &
-						~(inode->i_sb->s_blocksize - 1));
-					udf_write_aext(inode, &epos, neloc, nelen, 1);
-					udf_add_aext(inode, &epos, eloc, (etype << 30) | elen, 1);
-				}
-				else
-				{
-					if (elen & (inode->i_sb->s_blocksize - 1))
-					{
-						epos.offset -= adsize;
-						elen = EXT_RECORDED_ALLOCATED |
-							((elen + inode->i_sb->s_blocksize - 1) &
-							~(inode->i_sb->s_blocksize - 1));
-						udf_write_aext(inode, &epos, eloc, elen, 1);
-					}
-					memset(&eloc, 0x00, sizeof(kernel_lb_addr));
-					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
-					udf_add_aext(inode, &epos, eloc, elen, 1);
-				}
+				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;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 6/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
                   ` (4 preceding siblings ...)
  2007-03-06 16:48 ` [PATCH 5/6] " Jan Kara
@ 2007-03-06 16:48 ` Jan Kara
  2007-03-07  9:38   ` Christoph Hellwig
  2007-03-30  4:59 ` [PATCH 0/6] " Tino Keitel
  2007-04-27 21:54 ` Eric Sandeen
  7 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-03-06 16:48 UTC (permalink / raw)
  To: linux-kernel; +Cc: jack, akpm

We have to decrease link-count of the parent directory when removing a
subdirectory.

Signed-off-by: Jan Kara <jack@suse.cz>

diff -rupX /home/jack/.kerndiffexclude linux-2.6.20-5-large_file_fix/fs/udf/namei.c linux-2.6.20-6-rmdir_fix/fs/udf/namei.c
--- linux-2.6.20-5-large_file_fix/fs/udf/namei.c	2007-02-22 14:57:59.000000000 +0100
+++ linux-2.6.20-6-rmdir_fix/fs/udf/namei.c	2007-03-01 16:26:45.000000000 +0100
@@ -878,7 +878,7 @@ static int udf_rmdir(struct inode * dir,
 			inode->i_nlink);
 	clear_nlink(inode);
 	inode->i_size = 0;
-	inode_dec_link_count(inode);
+	inode_dec_link_count(dir);
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
 	mark_inode_dirty(dir);
 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 1/6] UDF cleanup and fixes
  2007-03-06 16:46 ` [PATCH 1/6] " Jan Kara
@ 2007-03-07  9:37   ` Christoph Hellwig
  0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2007-03-07  9:37 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

On Tue, Mar 06, 2007 at 05:46:38PM +0100, Jan Kara wrote:
>   Use sector_t and loff_t for file offsets in UDF filesystem. Otherwise
> an overflow may occur for long files. Also make inode_bmap() return offset in
> the extent in number of blocks instead of number of bytes - for most callers
> this is more convenient.

Looks good, but can you make sure to add line breaks after 80 chars in
all the lines you touch?

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/6] UDF cleanup and fixes
  2007-03-06 16:46 ` [PATCH 2/6] " Jan Kara
@ 2007-03-07  9:37   ` Christoph Hellwig
  0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2007-03-07  9:37 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

On Tue, Mar 06, 2007 at 05:46:59PM +0100, Jan Kara wrote:
> Introduce a structure extent_position to store a position of an extent and
> the corresponding buffer_head in one place.

Looks good.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/6] UDF cleanup and fixes
  2007-03-06 16:47 ` [PATCH 3/6] " Jan Kara
@ 2007-03-07  9:38   ` Christoph Hellwig
  0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2007-03-07  9:38 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

On Tue, Mar 06, 2007 at 05:47:27PM +0100, Jan Kara wrote:
> Make UDF use get_bh() instead of directly accessing b_count and use brelse()
> instead of udf_release_data() which does just brelse()...

Looks good.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 6/6] UDF cleanup and fixes
  2007-03-06 16:48 ` [PATCH 6/6] " Jan Kara
@ 2007-03-07  9:38   ` Christoph Hellwig
  0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2007-03-07  9:38 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

On Tue, Mar 06, 2007 at 05:48:39PM +0100, Jan Kara wrote:
> We have to decrease link-count of the parent directory when removing a
> subdirectory.

Ok.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 4/6] UDF cleanup and fixes
  2007-03-06 16:47 ` [PATCH 4/6] " Jan Kara
@ 2007-03-07  9:38   ` Christoph Hellwig
  0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2007-03-07  9:38 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

On Tue, Mar 06, 2007 at 05:47:45PM +0100, Jan Kara wrote:
> Add a few assertions into udf_discard_prealloc() to check that the file
> is sane (mostly helps debugging further patches ;).

Ok.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/6] UDF cleanup and fixes
  2007-03-06 16:48 ` [PATCH 5/6] " Jan Kara
@ 2007-03-07  9:38   ` Christoph Hellwig
  0 siblings, 0 replies; 27+ messages in thread
From: Christoph Hellwig @ 2007-03-07  9:38 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

On Tue, Mar 06, 2007 at 05:48:05PM +0100, Jan Kara wrote:
> Make UDF work correctly for files larger than 1GB. As no extent can
> be longer than (1<<30)-blocksize bytes, we have to create several extents
> if a big hole is being created. As a side-effect, we now don't discard
> preallocated blocks when creating a hole.

Ok.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
                   ` (5 preceding siblings ...)
  2007-03-06 16:48 ` [PATCH 6/6] " Jan Kara
@ 2007-03-30  4:59 ` Tino Keitel
  2007-03-30 18:06   ` Chuck Ebbert
                     ` (2 more replies)
  2007-04-27 21:54 ` Eric Sandeen
  7 siblings, 3 replies; 27+ messages in thread
From: Tino Keitel @ 2007-03-30  4:59 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel

On Tue, Mar 06, 2007 at 17:44:47 +0100, Jan Kara wrote:
>   Hello,
> 
>   the patches attached to six following emails implement some cleanup and
> fixes in the UDF code. The main two fixes are:
>   1) UDF now works correctly for files larger than 1GB.

Hi,

I tried 2.6.20 with your patches and got the following behaviour:

$ ls -la dvd.udf 
-rw-r--r-- 1 root root 4699717632 Mar 29 15:36 dvd.udf
$ mount -o loop -t udf dvd.udf /media/udf/
$ df /media/udf/
Filesystem           1K-blocks      Used Available Use% Mounted on
/home/storage/dvd.udf
                       4588506 -8584746354 8589334860   -  /media/udf
                               ^^^^^^^^^^^^^^^^^^^^^^
$ ls -la /media/udf/
total 4587521
drwxr-xr-x 3 root root        144 Mar 29 15:36 .
drwxr-xr-x 9 root root       1024 Mar 20 12:02 ..
-rw-r--r-- 1 root root 4697620480 Mar 29 15:57 bk_usr.tar
drwxr-xr-x 2 root root         40 Mar 29 15:36 lost+found

Regards,
Tino

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-30  4:59 ` [PATCH 0/6] " Tino Keitel
@ 2007-03-30 18:06   ` Chuck Ebbert
  2007-03-31  9:46     ` Tino Keitel
  2007-04-02 12:54   ` Jan Kara
  2007-04-02 13:54   ` Jan Kara
  2 siblings, 1 reply; 27+ messages in thread
From: Chuck Ebbert @ 2007-03-30 18:06 UTC (permalink / raw)
  To: tino.keitel; +Cc: Jan Kara, linux-kernel

Tino Keitel wrote:
> On Tue, Mar 06, 2007 at 17:44:47 +0100, Jan Kara wrote:
>>   Hello,
>>
>>   the patches attached to six following emails implement some cleanup and
>> fixes in the UDF code. The main two fixes are:
>>   1) UDF now works correctly for files larger than 1GB.
> 
> Hi,
> 
> I tried 2.6.20 with your patches and got the following behaviour:
> 
> $ ls -la dvd.udf 
> -rw-r--r-- 1 root root 4699717632 Mar 29 15:36 dvd.udf
> $ mount -o loop -t udf dvd.udf /media/udf/
> $ df /media/udf/
> Filesystem           1K-blocks      Used Available Use% Mounted on
> /home/storage/dvd.udf
>                        4588506 -8584746354 8589334860   -  /media/udf
>                                ^^^^^^^^^^^^^^^^^^^^^^
> $ ls -la /media/udf/
> total 4587521
> drwxr-xr-x 3 root root        144 Mar 29 15:36 .
> drwxr-xr-x 9 root root       1024 Mar 20 12:02 ..
> -rw-r--r-- 1 root root 4697620480 Mar 29 15:57 bk_usr.tar
> drwxr-xr-x 2 root root         40 Mar 29 15:36 lost+found
> 

Is that on a 32-bit machine?

Seems to work okay on a 64-bit system here:

$ df /mnt/udf
Filesystem           1K-blocks      Used Available Use% Mounted on
/var/tmp/udf_fs        4798938       302   4798636   1% /mnt/udf
$ ll /var/tmp/udf_fs
-rw-r--r-- 1 root root 4915200000 Mar 30 13:49 /var/tmp/udf_fs

And after creating a large file in the filesystem:

$ ll /mnt/udf/udf_file
-rw-r--r-- 1 root root 4751360000 Mar 30 14:01 /mnt/udf/udf_file
$ df /mnt/udf
Filesystem           1K-blocks      Used Available Use% Mounted on
/var/tmp/udf_fs        4798938   4640304    158634  97% /mnt/udf



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-30 18:06   ` Chuck Ebbert
@ 2007-03-31  9:46     ` Tino Keitel
  2007-04-02 14:48       ` Chuck Ebbert
  0 siblings, 1 reply; 27+ messages in thread
From: Tino Keitel @ 2007-03-31  9:46 UTC (permalink / raw)
  To: Chuck Ebbert; +Cc: Jan Kara, linux-kernel

On Fri, Mar 30, 2007 at 14:06:34 -0400, Chuck Ebbert wrote:
> Tino Keitel wrote:
> > On Tue, Mar 06, 2007 at 17:44:47 +0100, Jan Kara wrote:
> >>   Hello,
> >>
> >>   the patches attached to six following emails implement some cleanup and
> >> fixes in the UDF code. The main two fixes are:
> >>   1) UDF now works correctly for files larger than 1GB.
> > 
> > Hi,
> > 
> > I tried 2.6.20 with your patches and got the following behaviour:
> > 
> > $ ls -la dvd.udf 
> > -rw-r--r-- 1 root root 4699717632 Mar 29 15:36 dvd.udf
> > $ mount -o loop -t udf dvd.udf /media/udf/
> > $ df /media/udf/
> > Filesystem           1K-blocks      Used Available Use% Mounted on
> > /home/storage/dvd.udf
> >                        4588506 -8584746354 8589334860   -  /media/udf
> >                                ^^^^^^^^^^^^^^^^^^^^^^
> > $ ls -la /media/udf/
> > total 4587521
> > drwxr-xr-x 3 root root        144 Mar 29 15:36 .
> > drwxr-xr-x 9 root root       1024 Mar 20 12:02 ..
> > -rw-r--r-- 1 root root 4697620480 Mar 29 15:57 bk_usr.tar
> > drwxr-xr-x 2 root root         40 Mar 29 15:36 lost+found
> > 
> 
> Is that on a 32-bit machine?

Yes, it's an Intel Core Duo.

Regards,
Tino

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-30  4:59 ` [PATCH 0/6] " Tino Keitel
  2007-03-30 18:06   ` Chuck Ebbert
@ 2007-04-02 12:54   ` Jan Kara
  2007-04-02 13:54   ` Jan Kara
  2 siblings, 0 replies; 27+ messages in thread
From: Jan Kara @ 2007-04-02 12:54 UTC (permalink / raw)
  To: Tino Keitel, linux-kernel

On Fri 30-03-07 06:59:23, Tino Keitel wrote:
> On Tue, Mar 06, 2007 at 17:44:47 +0100, Jan Kara wrote:
> >   Hello,
> > 
> >   the patches attached to six following emails implement some cleanup and
> > fixes in the UDF code. The main two fixes are:
> >   1) UDF now works correctly for files larger than 1GB.
> 
> Hi,
> 
> I tried 2.6.20 with your patches and got the following behaviour:
> 
> $ ls -la dvd.udf 
> -rw-r--r-- 1 root root 4699717632 Mar 29 15:36 dvd.udf
> $ mount -o loop -t udf dvd.udf /media/udf/
> $ df /media/udf/
> Filesystem           1K-blocks      Used Available Use% Mounted on
> /home/storage/dvd.udf
>                        4588506 -8584746354 8589334860   -  /media/udf
>                                ^^^^^^^^^^^^^^^^^^^^^^
> $ ls -la /media/udf/
> total 4587521
> drwxr-xr-x 3 root root        144 Mar 29 15:36 .
> drwxr-xr-x 9 root root       1024 Mar 20 12:02 ..
> -rw-r--r-- 1 root root 4697620480 Mar 29 15:57 bk_usr.tar
> drwxr-xr-x 2 root root         40 Mar 29 15:36 lost+found
  Thanks for report. I'll have a look at it. I've tested my patches on a
64-bit machine and obviously some computation overflows on a 32-bit one...

									Honza
-- 
Jan Kara <jack@suse.cz>
SuSE CR Labs

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-30  4:59 ` [PATCH 0/6] " Tino Keitel
  2007-03-30 18:06   ` Chuck Ebbert
  2007-04-02 12:54   ` Jan Kara
@ 2007-04-02 13:54   ` Jan Kara
  2 siblings, 0 replies; 27+ messages in thread
From: Jan Kara @ 2007-04-02 13:54 UTC (permalink / raw)
  To: linux-kernel; +Cc: Tino Keitel

On Fri 30-03-07 06:59:23, Tino Keitel wrote:
> On Tue, Mar 06, 2007 at 17:44:47 +0100, Jan Kara wrote:
> >   Hello,
> > 
> >   the patches attached to six following emails implement some cleanup and
> > fixes in the UDF code. The main two fixes are:
> >   1) UDF now works correctly for files larger than 1GB.
> 
> Hi,
> 
> I tried 2.6.20 with your patches and got the following behaviour:
> 
> $ ls -la dvd.udf 
> -rw-r--r-- 1 root root 4699717632 Mar 29 15:36 dvd.udf
> $ mount -o loop -t udf dvd.udf /media/udf/
> $ df /media/udf/
> Filesystem           1K-blocks      Used Available Use% Mounted on
> /home/storage/dvd.udf
>                        4588506 -8584746354 8589334860   -  /media/udf
>                                ^^^^^^^^^^^^^^^^^^^^^^
> $ ls -la /media/udf/
> total 4587521
> drwxr-xr-x 3 root root        144 Mar 29 15:36 .
> drwxr-xr-x 9 root root       1024 Mar 20 12:02 ..
> -rw-r--r-- 1 root root 4697620480 Mar 29 15:57 bk_usr.tar
> drwxr-xr-x 2 root root         40 Mar 29 15:36 lost+found
  Looking more into this it looks like a bug in accounting of free blocks
than some overflow. Was dvd.udf a freshly created image by mkudffs? Are
there any errors in the log or did fs report anything like ENOSPC?

									Honza
-- 
Jan Kara <jack@suse.cz>
SuSE CR Labs

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-31  9:46     ` Tino Keitel
@ 2007-04-02 14:48       ` Chuck Ebbert
  2007-04-04  6:36         ` Tino Keitel
  0 siblings, 1 reply; 27+ messages in thread
From: Chuck Ebbert @ 2007-04-02 14:48 UTC (permalink / raw)
  To: Chuck Ebbert, Jan Kara, linux-kernel

Tino Keitel wrote:
> On Fri, Mar 30, 2007 at 14:06:34 -0400, Chuck Ebbert wrote:
>> Tino Keitel wrote:
>>> On Tue, Mar 06, 2007 at 17:44:47 +0100, Jan Kara wrote:
>>>>   Hello,
>>>>
>>>>   the patches attached to six following emails implement some cleanup and
>>>> fixes in the UDF code. The main two fixes are:
>>>>   1) UDF now works correctly for files larger than 1GB.
>>> Hi,
>>>
>>> I tried 2.6.20 with your patches and got the following behaviour:
>>>
>>> $ ls -la dvd.udf 
>>> -rw-r--r-- 1 root root 4699717632 Mar 29 15:36 dvd.udf
>>> $ mount -o loop -t udf dvd.udf /media/udf/
>>> $ df /media/udf/
>>> Filesystem           1K-blocks      Used Available Use% Mounted on
>>> /home/storage/dvd.udf
>>>                        4588506 -8584746354 8589334860   -  /media/udf
>>>                                ^^^^^^^^^^^^^^^^^^^^^^
>>> $ ls -la /media/udf/
>>> total 4587521
>>> drwxr-xr-x 3 root root        144 Mar 29 15:36 .
>>> drwxr-xr-x 9 root root       1024 Mar 20 12:02 ..
>>> -rw-r--r-- 1 root root 4697620480 Mar 29 15:57 bk_usr.tar
>>> drwxr-xr-x 2 root root         40 Mar 29 15:36 lost+found
>>>
>> Is that on a 32-bit machine?
> 
> Yes, it's an Intel Core Duo.

Well, it works for me on 32-bit as well, right up to 100% full.
No problems at all...

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-04-02 14:48       ` Chuck Ebbert
@ 2007-04-04  6:36         ` Tino Keitel
  2007-04-12 16:01           ` Jan Kara
  0 siblings, 1 reply; 27+ messages in thread
From: Tino Keitel @ 2007-04-04  6:36 UTC (permalink / raw)
  To: Chuck Ebbert; +Cc: Jan Kara, linux-kernel

On Mon, Apr 02, 2007 at 10:48:27 -0400, Chuck Ebbert wrote:

[...]

> Well, it works for me on 32-bit as well, right up to 100% full.
> No problems at all...

Maybe it depends on the kernel. I patched 2.6.20 with the patches
above and got the described behaviour.

Regards,
Tino

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-04-12 16:01           ` Jan Kara
@ 2007-04-12 15:59             ` Tino Keitel
  2007-04-16 15:23               ` Jan Kara
  0 siblings, 1 reply; 27+ messages in thread
From: Tino Keitel @ 2007-04-12 15:59 UTC (permalink / raw)
  To: linux-kernel

On Thu, Apr 12, 2007 at 18:01:12 +0200, Jan Kara wrote:
> On Wed 04-04-07 08:36:20, Tino Keitel wrote:
> > On Mon, Apr 02, 2007 at 10:48:27 -0400, Chuck Ebbert wrote:
> > 
> > [...]
> > 
> > > Well, it works for me on 32-bit as well, right up to 100% full.
> > > No problems at all...
> > 
> > Maybe it depends on the kernel. I patched 2.6.20 with the patches
> > above and got the described behaviour.
>   I've sent you an email with a few questions but probably it got lost in
> the noise... Are you able to reproduce the problem? Have you reproduced the
> problem on a freshly created UDF image or was it some older image?

Hi,

I can't remember of any errors in the kernel or about not available
space. It was an image file that I expermimented with, and I did
multiple mkudffs runs on the file. Could it be that the behaviour was
caused by stale data inside the image?

Regards,
Tino


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-04-04  6:36         ` Tino Keitel
@ 2007-04-12 16:01           ` Jan Kara
  2007-04-12 15:59             ` Tino Keitel
  0 siblings, 1 reply; 27+ messages in thread
From: Jan Kara @ 2007-04-12 16:01 UTC (permalink / raw)
  To: Tino Keitel; +Cc: Chuck Ebbert, linux-kernel

On Wed 04-04-07 08:36:20, Tino Keitel wrote:
> On Mon, Apr 02, 2007 at 10:48:27 -0400, Chuck Ebbert wrote:
> 
> [...]
> 
> > Well, it works for me on 32-bit as well, right up to 100% full.
> > No problems at all...
> 
> Maybe it depends on the kernel. I patched 2.6.20 with the patches
> above and got the described behaviour.
  I've sent you an email with a few questions but probably it got lost in
the noise... Are you able to reproduce the problem? Have you reproduced the
problem on a freshly created UDF image or was it some older image?

									Honza
-- 
Jan Kara <jack@suse.cz>
SuSE CR Labs

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-04-12 15:59             ` Tino Keitel
@ 2007-04-16 15:23               ` Jan Kara
  0 siblings, 0 replies; 27+ messages in thread
From: Jan Kara @ 2007-04-16 15:23 UTC (permalink / raw)
  To: Tino Keitel; +Cc: linux-kernel

> On Thu, Apr 12, 2007 at 18:01:12 +0200, Jan Kara wrote:
> > On Wed 04-04-07 08:36:20, Tino Keitel wrote:
> > > On Mon, Apr 02, 2007 at 10:48:27 -0400, Chuck Ebbert wrote:
> > > 
> > > [...]
> > > 
> > > > Well, it works for me on 32-bit as well, right up to 100% full.
> > > > No problems at all...
> > > 
> > > Maybe it depends on the kernel. I patched 2.6.20 with the patches
> > > above and got the described behaviour.
> >   I've sent you an email with a few questions but probably it got lost in
> > the noise... Are you able to reproduce the problem? Have you reproduced the
> > problem on a freshly created UDF image or was it some older image?
> 
> Hi,
> 
> I can't remember of any errors in the kernel or about not available
> space. It was an image file that I expermimented with, and I did
> multiple mkudffs runs on the file. Could it be that the behaviour was
> caused by stale data inside the image?
  OK, thanks for info. Umm, I don't find it likely that some stale data
in the image would cause this but maybe something could confuse mkudffs
(like it was expecting zeros somewhere where they were not). If you had
some recipe how to reproduce the problem (it would be enough if you had
something like: I have this file, I run mkudffs, mount it, see wrong
free blocks count), I can have a look at it. Otherwise, it's hard to
track it down...

								Honza

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
                   ` (6 preceding siblings ...)
  2007-03-30  4:59 ` [PATCH 0/6] " Tino Keitel
@ 2007-04-27 21:54 ` Eric Sandeen
  2007-05-03 15:13   ` Jan Kara
  2007-05-22 20:39   ` Eric Sandeen
  7 siblings, 2 replies; 27+ messages in thread
From: Eric Sandeen @ 2007-04-27 21:54 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel, akpm

Jan Kara wrote:
>   Hello,
> 
>   the patches attached to six following emails implement some cleanup and
> fixes in the UDF code. The main two fixes are:
>   1) UDF now works correctly for files larger than 1GB.
>   2) Deleting a directory updates number of links to the parent directory
>      correctly.
> See headers of following patches for details.
> 
> The patches sustained some torturing so I hope that I did not introduce
> more bugs than I've fixed ;).  Andrew, could you please put the patches
> into -mm kernels for testing?  Thanks.
> 
> 									Honza
> 

Jan -

I ran 2.6.21 + your udf patches from -mm through some udf tests which,
oddly enough, can be found in the xfstests test suite in xfsprogs cvs
from sgi.

It looks much better than before, but I was able to trip some of your
asserts.  They were generated while fsx was running.  The good news,
though, is that fsx passed.  :)  I haven't looked into it much further
yet, but wanted to let you know.

Thanks,
-Eric


BUG: at /src/linux-2.6.21-rc5/fs/udf/truncate.c:123 udf_discard_prealloc()
 [<de969274>] udf_discard_prealloc+0x2d8/0x2ed [udf]
 [<de95eea5>] udf_release_file+0x15/0x1e [udf]
 [<c046f5f0>] __fput+0xa5/0x15b
 [<c046d0d2>] generic_file_open+0x0/0x45
 [<c046d3f3>] __dentry_open+0x115/0x17a
 [<c046d4d2>] nameidata_to_filp+0x24/0x33
 [<c046d513>] do_filp_open+0x32/0x39
 [<c046d278>] get_unused_fd+0x50/0xb6
 [<c046d55c>] do_sys_open+0x42/0xbe
 [<c046d611>] sys_open+0x1c/0x1e
 [<c0404db8>] syscall_call+0x7/0xb
 =======================
BUG: at /src/linux-2.6.21-rc5/fs/udf/truncate.c:123 udf_discard_prealloc()
 [<de969274>] udf_discard_prealloc+0x2d8/0x2ed [udf]
 [<de9632ae>] udf_clear_inode+0x1b/0x34 [udf]
 [<c047eb56>] clear_inode+0xb2/0x100
 [<c0459a95>] truncate_inode_pages+0x17/0x1a
 [<c047edfe>] dispose_list+0x33/0xb1
 [<c047f1f3>] invalidate_inodes+0xa8/0xbd
 [<c046fff2>] generic_shutdown_super+0x31/0xb7
 [<c0470095>] kill_block_super+0x1d/0x2d
 [<c047013d>] deactivate_super+0x52/0x65
 [<c0480de8>] sys_umount+0x1f2/0x21a
 [<c044e33f>] audit_syscall_entry+0x10d/0x137
 [<c0480e27>] sys_oldumount+0x17/0x1a
 [<c0404db8>] syscall_call+0x7/0xb

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-04-27 21:54 ` Eric Sandeen
@ 2007-05-03 15:13   ` Jan Kara
  2007-05-22 20:39   ` Eric Sandeen
  1 sibling, 0 replies; 27+ messages in thread
From: Jan Kara @ 2007-05-03 15:13 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: linux-kernel, akpm

On Fri 27-04-07 16:54:20, Eric Sandeen wrote:
> Jan Kara wrote:
> >   Hello,
> > 
> >   the patches attached to six following emails implement some cleanup and
> > fixes in the UDF code. The main two fixes are:
> >   1) UDF now works correctly for files larger than 1GB.
> >   2) Deleting a directory updates number of links to the parent directory
> >      correctly.
> > See headers of following patches for details.
> > 
> > The patches sustained some torturing so I hope that I did not introduce
> > more bugs than I've fixed ;).  Andrew, could you please put the patches
> > into -mm kernels for testing?  Thanks.
> > 
> > 									Honza
> > 
> 
> Jan -
> 
> I ran 2.6.21 + your udf patches from -mm through some udf tests which,
> oddly enough, can be found in the xfstests test suite in xfsprogs cvs
> from sgi.
> 
> It looks much better than before, but I was able to trip some of your
> asserts.  They were generated while fsx was running.  The good news,
> though, is that fsx passed.  :)  I haven't looked into it much further
> yet, but wanted to let you know.
  Thanks for the news. I'll try running fsx to see if I'll be able to
reproduce the problem (I think I was testing the patches with fsx but maybe
it didn't run long enough).

								Honza

> BUG: at /src/linux-2.6.21-rc5/fs/udf/truncate.c:123 udf_discard_prealloc()
>  [<de969274>] udf_discard_prealloc+0x2d8/0x2ed [udf]
>  [<de95eea5>] udf_release_file+0x15/0x1e [udf]
>  [<c046f5f0>] __fput+0xa5/0x15b
>  [<c046d0d2>] generic_file_open+0x0/0x45
>  [<c046d3f3>] __dentry_open+0x115/0x17a
>  [<c046d4d2>] nameidata_to_filp+0x24/0x33
>  [<c046d513>] do_filp_open+0x32/0x39
>  [<c046d278>] get_unused_fd+0x50/0xb6
>  [<c046d55c>] do_sys_open+0x42/0xbe
>  [<c046d611>] sys_open+0x1c/0x1e
>  [<c0404db8>] syscall_call+0x7/0xb
>  =======================
> BUG: at /src/linux-2.6.21-rc5/fs/udf/truncate.c:123 udf_discard_prealloc()
>  [<de969274>] udf_discard_prealloc+0x2d8/0x2ed [udf]
>  [<de9632ae>] udf_clear_inode+0x1b/0x34 [udf]
>  [<c047eb56>] clear_inode+0xb2/0x100
>  [<c0459a95>] truncate_inode_pages+0x17/0x1a
>  [<c047edfe>] dispose_list+0x33/0xb1
>  [<c047f1f3>] invalidate_inodes+0xa8/0xbd
>  [<c046fff2>] generic_shutdown_super+0x31/0xb7
>  [<c0470095>] kill_block_super+0x1d/0x2d
>  [<c047013d>] deactivate_super+0x52/0x65
>  [<c0480de8>] sys_umount+0x1f2/0x21a
>  [<c044e33f>] audit_syscall_entry+0x10d/0x137
>  [<c0480e27>] sys_oldumount+0x17/0x1a
>  [<c0404db8>] syscall_call+0x7/0xb
-- 
Jan Kara <jack@suse.cz>
SuSE CR Labs

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-04-27 21:54 ` Eric Sandeen
  2007-05-03 15:13   ` Jan Kara
@ 2007-05-22 20:39   ` Eric Sandeen
  2007-05-23  7:45     ` Jan Kara
  1 sibling, 1 reply; 27+ messages in thread
From: Eric Sandeen @ 2007-05-22 20:39 UTC (permalink / raw)
  To: Jan Kara; +Cc: linux-kernel

Eric Sandeen wrote:

> Jan -
> 
> I ran 2.6.21 + your udf patches from -mm through some udf tests which,
> oddly enough, can be found in the xfstests test suite in xfsprogs cvs
> from sgi.
> 
> It looks much better than before, but I was able to trip some of your
> asserts.  They were generated while fsx was running.  The good news,
> though, is that fsx passed.  :)  I haven't looked into it much further
> yet, but wanted to let you know.

Here's a short hacky testcase that trips the assert around line 123 of
udf/truncate.c  I'm looking into it but you may immediately see what the
problem is...?


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char ** argv)
{
        int fd;
        char buf[65536];

        fd = open("testfile", O_WRONLY|O_CREAT);
        lseek(fd, 16797, SEEK_SET);
        write(fd, buf, 22935);
        close(fd);

        fd = open("testfile", O_WRONLY);
        lseek(fd, 31281, SEEK_SET);
        write(fd, buf, 9592);
        close(fd);
}

-Eric

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 0/6] UDF cleanup and fixes
  2007-05-22 20:39   ` Eric Sandeen
@ 2007-05-23  7:45     ` Jan Kara
  0 siblings, 0 replies; 27+ messages in thread
From: Jan Kara @ 2007-05-23  7:45 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: linux-kernel

On Tue 22-05-07 15:39:31, Eric Sandeen wrote:
> Eric Sandeen wrote:
> 
> > Jan -
> > 
> > I ran 2.6.21 + your udf patches from -mm through some udf tests which,
> > oddly enough, can be found in the xfstests test suite in xfsprogs cvs
> > from sgi.
> > 
> > It looks much better than before, but I was able to trip some of your
> > asserts.  They were generated while fsx was running.  The good news,
> > though, is that fsx passed.  :)  I haven't looked into it much further
> > yet, but wanted to let you know.
> 
> Here's a short hacky testcase that trips the assert around line 123 of
> udf/truncate.c  I'm looking into it but you may immediately see what the
> problem is...?
  Yes, yesterday I've also managed to create a simple testcase - sorry for
not letting you know, I'd have saved you some time. I also know what the
problem is:
  1) discard_prealloc() shouldn't be called from udf_clear_inode() - at
that point inode won't be written any more and thus changes to it won't be
reflected. Actually, this bug is hidden by the fact that UDF calls
discard_prealloc() on each filp release but anyway.
  2) the second problem is extent rounding - when we discard prealloc we
also truncate the extent to match i_size. That is fine but if the buffer
remains in pagecache and is reused on second open, block_prepare_write()
won't call udf_get_block() (as the buffer is already mapped) and thus the
extent remains truncated even though we write after it's end. The easiest
way out would be to simply leave the extent length rounded to block
boundary but I have to check with the specification whether this is
allowed...

								Honza

-- 
Jan Kara <jack@suse.cz>
SuSE CR Labs

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2007-05-23  7:34 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-06 16:44 [PATCH 0/6] UDF cleanup and fixes Jan Kara
2007-03-06 16:46 ` [PATCH 1/6] " Jan Kara
2007-03-07  9:37   ` Christoph Hellwig
2007-03-06 16:46 ` [PATCH 2/6] " Jan Kara
2007-03-07  9:37   ` Christoph Hellwig
2007-03-06 16:47 ` [PATCH 3/6] " Jan Kara
2007-03-07  9:38   ` Christoph Hellwig
2007-03-06 16:47 ` [PATCH 4/6] " Jan Kara
2007-03-07  9:38   ` Christoph Hellwig
2007-03-06 16:48 ` [PATCH 5/6] " Jan Kara
2007-03-07  9:38   ` Christoph Hellwig
2007-03-06 16:48 ` [PATCH 6/6] " Jan Kara
2007-03-07  9:38   ` Christoph Hellwig
2007-03-30  4:59 ` [PATCH 0/6] " Tino Keitel
2007-03-30 18:06   ` Chuck Ebbert
2007-03-31  9:46     ` Tino Keitel
2007-04-02 14:48       ` Chuck Ebbert
2007-04-04  6:36         ` Tino Keitel
2007-04-12 16:01           ` Jan Kara
2007-04-12 15:59             ` Tino Keitel
2007-04-16 15:23               ` Jan Kara
2007-04-02 12:54   ` Jan Kara
2007-04-02 13:54   ` Jan Kara
2007-04-27 21:54 ` Eric Sandeen
2007-05-03 15:13   ` Jan Kara
2007-05-22 20:39   ` Eric Sandeen
2007-05-23  7:45     ` Jan Kara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).