浏览代码

UDF: introduce struct extent_position

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

Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Jan Kara 18 年之前
父节点
当前提交
ff116fc8d1
共有 8 个文件被更改,包括 434 次插入445 次删除
  1. 83 89
      fs/udf/balloc.c
  2. 13 12
      fs/udf/dir.c
  3. 8 12
      fs/udf/directory.c
  4. 169 174
      fs/udf/inode.c
  5. 61 61
      fs/udf/namei.c
  6. 8 9
      fs/udf/super.c
  7. 78 81
      fs/udf/truncate.c
  8. 14 7
      fs/udf/udfdecl.h

+ 83 - 89
fs/udf/balloc.c

@@ -427,9 +427,9 @@ static void udf_table_free_blocks(struct super_block * sb,
 {
 {
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	uint32_t start, end;
 	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;
 	int8_t etype;
 	int i;
 	int i;
 
 
@@ -457,14 +457,13 @@ static void udf_table_free_blocks(struct super_block * sb,
 	start = bloc.logicalBlockNum + offset;
 	start = bloc.logicalBlockNum + offset;
 	end = bloc.logicalBlockNum + offset + count - 1;
 	end = bloc.logicalBlockNum + offset + count - 1;
 
 
-	oextoffset = nextoffset = sizeof(struct unallocSpaceEntry);
+	epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);
 	elen = 0;
 	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 =
 	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)) ==
 		if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) ==
 			start))
 			start))
@@ -482,7 +481,7 @@ static void udf_table_free_blocks(struct super_block * sb,
 				start += count;
 				start += count;
 				count = 0;
 				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))
 		else if (eloc.logicalBlockNum == (end + 1))
 		{
 		{
@@ -502,20 +501,20 @@ static void udf_table_free_blocks(struct super_block * sb,
 				end -= count;
 				end -= count;
 				count = 0;
 				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;
 			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
 		else
-			oextoffset = nextoffset;
+			oepos.offset = epos.offset;
 	}
 	}
 
 
 	if (count)
 	if (count)
@@ -547,55 +546,53 @@ static void udf_table_free_blocks(struct super_block * sb,
 			adsize = sizeof(long_ad);
 			adsize = sizeof(long_ad);
 		else
 		else
 		{
 		{
-			udf_release_data(obh);
-			udf_release_data(nbh);
+			udf_release_data(oepos.bh);
+			udf_release_data(epos.bh);
 			goto error_return;
 			goto error_return;
 		}
 		}
 
 
-		if (nextoffset + (2 * adsize) > sb->s_blocksize)
+		if (epos.offset + (2 * adsize) > sb->s_blocksize)
 		{
 		{
 			char *sptr, *dptr;
 			char *sptr, *dptr;
 			int loffset;
 			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 */
 			/* Steal a block from the extent being free'd */
-			nbloc.logicalBlockNum = eloc.logicalBlockNum;
+			epos.block.logicalBlockNum = eloc.logicalBlockNum;
 			eloc.logicalBlockNum ++;
 			eloc.logicalBlockNum ++;
 			elen -= sb->s_blocksize;
 			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;
 				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);
 				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_file_entry_alloc_offset(inode) +
 					UDF_I_LENEATTR(inode) - adsize;
 					UDF_I_LENEATTR(inode) - adsize;
-				dptr = nbh->b_data + sizeof(struct allocExtDesc);
+				dptr = epos.bh->b_data + sizeof(struct allocExtDesc);
 				memcpy(dptr, sptr, adsize);
 				memcpy(dptr, sptr, adsize);
-				nextoffset = sizeof(struct allocExtDesc) + adsize;
+				epos.offset = sizeof(struct allocExtDesc) + adsize;
 			}
 			}
 			else
 			else
 			{
 			{
-				loffset = nextoffset + adsize;
+				loffset = epos.offset + adsize;
 				aed->lengthAllocDescs = cpu_to_le32(0);
 				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 =
 					aed->lengthAllocDescs =
 						cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 						cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 				}
 				}
@@ -606,11 +603,11 @@ static void udf_table_free_blocks(struct super_block * sb,
 				}
 				}
 			}
 			}
 			if (UDF_SB_UDFREV(sb) >= 0x0200)
 			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
 			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))
 			switch (UDF_I_ALLOCTYPE(table))
 			{
 			{
 				case ICBTAG_FLAG_AD_SHORT:
 				case ICBTAG_FLAG_AD_SHORT:
@@ -619,7 +616,7 @@ static void udf_table_free_blocks(struct super_block * sb,
 					sad->extLength = cpu_to_le32(
 					sad->extLength = cpu_to_le32(
 						EXT_NEXT_EXTENT_ALLOCDECS |
 						EXT_NEXT_EXTENT_ALLOCDECS |
 						sb->s_blocksize);
 						sb->s_blocksize);
-					sad->extPosition = cpu_to_le32(nbloc.logicalBlockNum);
+					sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum);
 					break;
 					break;
 				}
 				}
 				case ICBTAG_FLAG_AD_LONG:
 				case ICBTAG_FLAG_AD_LONG:
@@ -628,14 +625,14 @@ static void udf_table_free_blocks(struct super_block * sb,
 					lad->extLength = cpu_to_le32(
 					lad->extLength = cpu_to_le32(
 						EXT_NEXT_EXTENT_ALLOCDECS |
 						EXT_NEXT_EXTENT_ALLOCDECS |
 						sb->s_blocksize);
 						sb->s_blocksize);
-					lad->extLocation = cpu_to_lelb(nbloc);
+					lad->extLocation = cpu_to_lelb(epos.block);
 					break;
 					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
 			else
 				mark_inode_dirty(table);
 				mark_inode_dirty(table);
@@ -643,26 +640,26 @@ static void udf_table_free_blocks(struct super_block * sb,
 
 
 		if (elen) /* It's possible that stealing the block emptied the extent */
 		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;
 				UDF_I_LENALLOC(table) += adsize;
 				mark_inode_dirty(table);
 				mark_inode_dirty(table);
 			}
 			}
 			else
 			else
 			{
 			{
-				aed = (struct allocExtDesc *)nbh->b_data;
+				aed = (struct allocExtDesc *)epos.bh->b_data;
 				aed->lengthAllocDescs =
 				aed->lengthAllocDescs =
 					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 					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:
 error_return:
 	sb->s_dirt = 1;
 	sb->s_dirt = 1;
@@ -677,9 +674,9 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 {
 {
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	int alloc_count = 0;
 	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;
 	int8_t etype = -1;
 
 
 	if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
 	if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))
@@ -693,14 +690,13 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 		return 0;
 		return 0;
 
 
 	mutex_lock(&sbi->s_alloc_mutex);
 	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;
 	eloc.logicalBlockNum = 0xFFFFFFFF;
 
 
 	while (first_block != eloc.logicalBlockNum && (etype =
 	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",
 		udf_debug("eloc=%d, elen=%d, first_block=%d\n",
 			eloc.logicalBlockNum, elen, first_block);
 			eloc.logicalBlockNum, elen, first_block);
@@ -709,7 +705,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 
 
 	if (first_block == eloc.logicalBlockNum)
 	if (first_block == eloc.logicalBlockNum)
 	{
 	{
-		extoffset -= adsize;
+		epos.offset -= adsize;
 
 
 		alloc_count = (elen >> sb->s_blocksize_bits);
 		alloc_count = (elen >> sb->s_blocksize_bits);
 		if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
 		if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count))
@@ -719,15 +715,15 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 			alloc_count = block_count;
 			alloc_count = block_count;
 			eloc.logicalBlockNum += alloc_count;
 			eloc.logicalBlockNum += alloc_count;
 			elen -= (alloc_count << sb->s_blocksize_bits);
 			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
 		else
-			udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);
+			udf_delete_aext(table, epos, eloc, (etype << 30) | elen);
 	}
 	}
 	else
 	else
 		alloc_count = 0;
 		alloc_count = 0;
 
 
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 
 
 	if (alloc_count && UDF_SB_LVIDBH(sb))
 	if (alloc_count && UDF_SB_LVIDBH(sb))
 	{
 	{
@@ -747,9 +743,9 @@ static int udf_table_new_block(struct super_block * sb,
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
 	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
 	uint32_t newblock = 0, adsize;
 	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;
 	int8_t etype;
 
 
 	*err = -ENOSPC;
 	*err = -ENOSPC;
@@ -770,14 +766,12 @@ static int udf_table_new_block(struct super_block * sb,
 	   We store the buffer_head, bloc, and extoffset of the current closest
 	   We store the buffer_head, bloc, and extoffset of the current closest
 	   match and use that when we are done.
 	   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 =
 	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)
 		if (goal >= eloc.logicalBlockNum)
 		{
 		{
@@ -793,24 +787,24 @@ static int udf_table_new_block(struct super_block * sb,
 		if (nspread < spread)
 		if (nspread < spread)
 		{
 		{
 			spread = nspread;
 			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_eloc = eloc;
 			goal_elen = (etype << 30) | elen;
 			goal_elen = (etype << 30) | elen;
 		}
 		}
 	}
 	}
 
 
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 
 
 	if (spread == 0xFFFFFFFF)
 	if (spread == 0xFFFFFFFF)
 	{
 	{
-		udf_release_data(goal_bh);
+		udf_release_data(goal_epos.bh);
 		mutex_unlock(&sbi->s_alloc_mutex);
 		mutex_unlock(&sbi->s_alloc_mutex);
 		return 0;
 		return 0;
 	}
 	}
@@ -826,17 +820,17 @@ static int udf_table_new_block(struct super_block * sb,
 
 
 	if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
 	if (inode && DQUOT_ALLOC_BLOCK(inode, 1))
 	{
 	{
-		udf_release_data(goal_bh);
+		udf_release_data(goal_epos.bh);
 		mutex_unlock(&sbi->s_alloc_mutex);
 		mutex_unlock(&sbi->s_alloc_mutex);
 		*err = -EDQUOT;
 		*err = -EDQUOT;
 		return 0;
 		return 0;
 	}
 	}
 
 
 	if (goal_elen)
 	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
 	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))
 	if (UDF_SB_LVIDBH(sb))
 	{
 	{

+ 13 - 12
fs/udf/dir.c

@@ -111,12 +111,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 	uint16_t liu;
 	uint16_t liu;
 	uint8_t lfi;
 	uint8_t lfi;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	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;
 	sector_t offset;
 	int i, num;
 	int i, num;
 	unsigned int dt_type;
 	unsigned int dt_type;
+	struct extent_position epos = { NULL, 0, {0, 0}};
 
 
 	if (nf_pos >= size)
 	if (nf_pos >= size)
 		return 0;
 		return 0;
@@ -128,22 +129,22 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 		fibh.sbh = fibh.ebh = NULL;
 		fibh.sbh = fibh.ebh = NULL;
 	else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
 	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);
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
 			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)
 			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-				extoffset -= sizeof(long_ad);
+				epos.offset -= sizeof(long_ad);
 		}
 		}
 		else
 		else
 			offset = 0;
 			offset = 0;
 
 
 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		{
 		{
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return -EIO;
 			return -EIO;
 		}
 		}
 	
 	
@@ -171,7 +172,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 	}
 	}
 	else
 	else
 	{
 	{
-		udf_release_data(bh);
+		udf_release_data(epos.bh);
 		return -ENOENT;
 		return -ENOENT;
 	}
 	}
 
 
@@ -179,14 +180,14 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 	{
 	{
 		filp->f_pos = nf_pos + 1;
 		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 (!fi)
 		{
 		{
 			if (fibh.sbh != fibh.ebh)
 			if (fibh.sbh != fibh.ebh)
 				udf_release_data(fibh.ebh);
 				udf_release_data(fibh.ebh);
 			udf_release_data(fibh.sbh);
 			udf_release_data(fibh.sbh);
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return 0;
 			return 0;
 		}
 		}
 
 
@@ -246,7 +247,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 				if (fibh.sbh != fibh.ebh)
 				if (fibh.sbh != fibh.ebh)
 					udf_release_data(fibh.ebh);
 					udf_release_data(fibh.ebh);
 				udf_release_data(fibh.sbh);
 				udf_release_data(fibh.sbh);
-				udf_release_data(bh);
+				udf_release_data(epos.bh);
 	 			return 0;
 	 			return 0;
 			}
 			}
 		}
 		}
@@ -257,7 +258,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 	if (fibh.sbh != fibh.ebh)
 	if (fibh.sbh != fibh.ebh)
 		udf_release_data(fibh.ebh);
 		udf_release_data(fibh.ebh);
 	udf_release_data(fibh.sbh);
 	udf_release_data(fibh.sbh);
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 
 
 	return 0;
 	return 0;
 }
 }

+ 8 - 12
fs/udf/directory.c

@@ -75,9 +75,9 @@ struct fileIdentDesc *
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 	struct udf_fileident_bh *fibh,
 	struct udf_fileident_bh *fibh,
 	struct fileIdentDesc *cfi,
 	struct fileIdentDesc *cfi,
-	kernel_lb_addr *bloc, uint32_t *extoffset, 
+	struct extent_position *epos,
 	kernel_lb_addr *eloc, uint32_t *elen,
 	kernel_lb_addr *eloc, uint32_t *elen,
-	sector_t *offset, struct buffer_head **bh)
+	sector_t *offset)
 {
 {
 	struct fileIdentDesc *fi;
 	struct fileIdentDesc *fi;
 	int i, num, block;
 	int i, num, block;
@@ -105,13 +105,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 
 
 	if (fibh->eoffset == dir->i_sb->s_blocksize)
 	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))
 			(EXT_RECORDED_ALLOCATED >> 30))
-		{
 			return NULL;
 			return NULL;
-		}
 
 
 		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 
 
@@ -120,7 +118,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
 		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
 			*offset = 0;
 			*offset = 0;
 		else
 		else
-			*extoffset = lextoffset;
+			epos->offset = lextoffset;
 
 
 		udf_release_data(fibh->sbh);
 		udf_release_data(fibh->sbh);
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
@@ -169,13 +167,11 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 	}
 	}
 	else if (fibh->eoffset > dir->i_sb->s_blocksize)
 	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))
 			(EXT_RECORDED_ALLOCATED >> 30))
-		{
 			return NULL;
 			return NULL;
-		}
 
 
 		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 		block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
 
 
@@ -184,7 +180,7 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
 		if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
 			*offset = 0;
 			*offset = 0;
 		else
 		else
-			*extoffset = lextoffset;
+			epos->offset = lextoffset;
 
 
 		fibh->soffset -= dir->i_sb->s_blocksize;
 		fibh->soffset -= dir->i_sb->s_blocksize;
 		fibh->eoffset -= dir->i_sb->s_blocksize;
 		fibh->eoffset -= dir->i_sb->s_blocksize;

+ 169 - 174
fs/udf/inode.c

@@ -51,8 +51,8 @@ static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
 static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
 static struct buffer_head *inode_getblk(struct inode *, sector_t, int *,
 	long *, 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,
 static void udf_split_extents(struct inode *, int *, int, int,
 	kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 	kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_prealloc_extents(struct inode *, int, int,
 static void udf_prealloc_extents(struct inode *, int, int,
@@ -61,7 +61,7 @@ static void udf_merge_extents(struct inode *,
 	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_update_extents(struct inode *,
 static void udf_update_extents(struct inode *,
 	kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
 	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);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 
 /*
 /*
@@ -194,10 +194,11 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
 struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
 struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
 {
 {
 	int newblock;
 	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;
 	uint8_t alloctype;
+	struct extent_position epos;
 
 
 	struct udf_fileident_bh sfibh, dfibh;
 	struct udf_fileident_bh sfibh, dfibh;
 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
@@ -237,13 +238,13 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 	mark_buffer_dirty_inode(dbh, inode);
 	mark_buffer_dirty_inode(dbh, inode);
 
 
 	sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
 	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.soffset = dfibh.eoffset = 0;
 	dfibh.sbh = dfibh.ebh = dbh;
 	dfibh.sbh = dfibh.ebh = dbh;
 	while ( (f_pos < size) )
 	while ( (f_pos < size) )
 	{
 	{
 		UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 		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)
 		if (!sfi)
 		{
 		{
 			udf_release_data(dbh);
 			udf_release_data(dbh);
@@ -266,16 +267,17 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 
 
 	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
 	memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
 	UDF_I_LENALLOC(inode) = 0;
 	UDF_I_LENALLOC(inode) = 0;
-	bloc = UDF_I_LOCATION(inode);
 	eloc.logicalBlockNum = *block;
 	eloc.logicalBlockNum = *block;
 	eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
 	eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
 	elen = inode->i_size;
 	elen = inode->i_size;
 	UDF_I_LENEXTENTS(inode) = elen;
 	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 */
 	/* UniqueID stuff */
 
 
-	udf_release_data(sbh);
+	udf_release_data(epos.bh);
 	mark_inode_dirty(inode);
 	mark_inode_dirty(inode);
 	return dbh;
 	return dbh;
 }
 }
@@ -357,12 +359,12 @@ udf_getblk(struct inode *inode, long block, int create, int *err)
 static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 	int *err, long *phys, int *new)
 	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];
 	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;
 	int count = 0, startnum = 0, endnum = 0;
 	uint32_t elen = 0;
 	uint32_t elen = 0;
-	kernel_lb_addr eloc, pbloc, cbloc, nbloc;
+	kernel_lb_addr eloc;
 	int c = 1;
 	int c = 1;
 	loff_t lbcount = 0, b_off = 0;
 	loff_t lbcount = 0, b_off = 0;
 	uint32_t newblocknum, newblock;
 	uint32_t newblocknum, newblock;
@@ -371,37 +373,39 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 	int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
 	int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
 	char lastblock = 0;
 	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;
 	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.
 	/* find the extent which contains the block we are looking for.
        alternate between laarr[0] and laarr[1] for locations of the
        alternate between laarr[0] and laarr[1] for locations of the
        current extent, and the previous extent */
        current extent, and the previous extent */
 	do
 	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;
 		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;
 			break;
 
 
 		c = !c;
 		c = !c;
@@ -430,11 +434,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 			elen = EXT_RECORDED_ALLOCATED |
 			elen = EXT_RECORDED_ALLOCATED |
 				((elen + inode->i_sb->s_blocksize - 1) &
 				((elen + inode->i_sb->s_blocksize - 1) &
 				~(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);
 		newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
 		*phys = newblock;
 		*phys = newblock;
 		return NULL;
 		return NULL;
@@ -477,7 +481,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 	/* if the current block is located in a extent, read the next extent */
 	/* if the current block is located in a extent, read the next extent */
 	if (etype != -1)
 	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].extLength = (etype << 30) | elen;
 			laarr[c+1].extLocation = eloc;
 			laarr[c+1].extLocation = eloc;
@@ -488,8 +492,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 		else
 		else
 			lastblock = 1;
 			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
 	/* if the current extent is not recorded but allocated, get the
 		block in the extent corresponding to the requested block */
 		block in the extent corresponding to the requested block */
@@ -509,7 +513,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 		if (!(newblocknum = udf_new_block(inode->i_sb, inode,
 		if (!(newblocknum = udf_new_block(inode->i_sb, inode,
 			UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
 			UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
 		{
 		{
-			udf_release_data(pbh);
+			udf_release_data(prev_epos.bh);
 			*err = -ENOSPC;
 			*err = -ENOSPC;
 			return NULL;
 			return NULL;
 		}
 		}
@@ -532,9 +536,9 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
 	/* write back the new extents, inserting new extents if the new number
 	/* write back the new extents, inserting new extents if the new number
        of extents is greater than the old number, and deleting extents if
        of extents is greater than the old number, and deleting extents if
        the new number of extents is less than the old number */
        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,
 	if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
 		UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
 		UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
@@ -796,7 +800,7 @@ static void udf_merge_extents(struct inode *inode,
 
 
 static void udf_update_extents(struct inode *inode,
 static void udf_update_extents(struct inode *inode,
 	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
 	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;
 	int start = 0, i;
 	kernel_lb_addr tmploc;
 	kernel_lb_addr tmploc;
@@ -805,28 +809,26 @@ static void udf_update_extents(struct inode *inode,
 	if (startnum > endnum)
 	if (startnum > endnum)
 	{
 	{
 		for (i=0; i<(startnum-endnum); i++)
 		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)
 	else if (startnum < endnum)
 	{
 	{
 		for (i=0; i<(endnum-startnum); i++)
 		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 ++;
 			start ++;
 		}
 		}
 	}
 	}
 
 
 	for (i=start; i<endnum; i++)
 	for (i=start; i<endnum; i++)
 	{
 	{
-		udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0);
-		udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation,
-			laarr[i].extLength, *pbh, 1);
+		udf_next_aext(inode, epos, &tmploc, &tmplen, 0);
+		udf_write_aext(inode, epos, laarr[i].extLocation,
+			laarr[i].extLength, 1);
 	}
 	}
 }
 }
 
 
@@ -1557,8 +1559,8 @@ udf_iget(struct super_block *sb, kernel_lb_addr ino)
 	return NULL;
 	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;
 	int adsize;
 	short_ad *sad = NULL;
 	short_ad *sad = NULL;
@@ -1567,10 +1569,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 	int8_t etype;
 	int8_t etype;
 	uint8_t *ptr;
 	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
 	else
-		ptr = (*bh)->b_data + *extoffset;
+		ptr = epos->bh->b_data + epos->offset;
 
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 		adsize = sizeof(short_ad);
 		adsize = sizeof(short_ad);
@@ -1579,20 +1581,20 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 	else
 	else
 		return -1;
 		return -1;
 
 
-	if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)
+	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize)
 	{
 	{
 		char *sptr, *dptr;
 		char *sptr, *dptr;
 		struct buffer_head *nbh;
 		struct buffer_head *nbh;
 		int err, loffset;
 		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)))
 			obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
 		{
 		{
 			return -1;
 			return -1;
 		}
 		}
 		if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
 		if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
-			*bloc, 0))))
+			epos->block, 0))))
 		{
 		{
 			return -1;
 			return -1;
 		}
 		}
@@ -1605,25 +1607,25 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 		aed = (struct allocExtDesc *)(nbh->b_data);
 		aed = (struct allocExtDesc *)(nbh->b_data);
 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
 			aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
 			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);
 			aed->lengthAllocDescs = cpu_to_le32(adsize);
 			sptr = ptr - adsize;
 			sptr = ptr - adsize;
 			dptr = nbh->b_data + sizeof(struct allocExtDesc);
 			dptr = nbh->b_data + sizeof(struct allocExtDesc);
 			memcpy(dptr, sptr, adsize);
 			memcpy(dptr, sptr, adsize);
-			*extoffset = sizeof(struct allocExtDesc) + adsize;
+			epos->offset = sizeof(struct allocExtDesc) + adsize;
 		}
 		}
 		else
 		else
 		{
 		{
-			loffset = *extoffset + adsize;
+			loffset = epos->offset + adsize;
 			aed->lengthAllocDescs = cpu_to_le32(0);
 			aed->lengthAllocDescs = cpu_to_le32(0);
 			sptr = ptr;
 			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 =
 				aed->lengthAllocDescs =
 					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 			}
 			}
@@ -1635,10 +1637,10 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 		}
 		}
 		if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
 		if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)
 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,
-				bloc->logicalBlockNum, sizeof(tag));
+				epos->block.logicalBlockNum, sizeof(tag));
 		else
 		else
 			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,
 			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))
 		switch (UDF_I_ALLOCTYPE(inode))
 		{
 		{
 			case ICBTAG_FLAG_AD_SHORT:
 			case ICBTAG_FLAG_AD_SHORT:
@@ -1647,7 +1649,7 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 				sad->extLength = cpu_to_le32(
 				sad->extLength = cpu_to_le32(
 					EXT_NEXT_EXTENT_ALLOCDECS |
 					EXT_NEXT_EXTENT_ALLOCDECS |
 					inode->i_sb->s_blocksize);
 					inode->i_sb->s_blocksize);
-				sad->extPosition = cpu_to_le32(bloc->logicalBlockNum);
+				sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum);
 				break;
 				break;
 			}
 			}
 			case ICBTAG_FLAG_AD_LONG:
 			case ICBTAG_FLAG_AD_LONG:
@@ -1656,60 +1658,57 @@ int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 				lad->extLength = cpu_to_le32(
 				lad->extLength = cpu_to_le32(
 					EXT_NEXT_EXTENT_ALLOCDECS |
 					EXT_NEXT_EXTENT_ALLOCDECS |
 					inode->i_sb->s_blocksize);
 					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));
 				memset(lad->impUse, 0x00, sizeof(lad->impUse));
 				break;
 				break;
 			}
 			}
 		}
 		}
-		if (*bh)
+		if (epos->bh)
 		{
 		{
 			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
 			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
 			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
 		else
 			mark_inode_dirty(inode);
 			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;
 		UDF_I_LENALLOC(inode) += adsize;
 		mark_inode_dirty(inode);
 		mark_inode_dirty(inode);
 	}
 	}
 	else
 	else
 	{
 	{
-		aed = (struct allocExtDesc *)(*bh)->b_data;
+		aed = (struct allocExtDesc *)epos->bh->b_data;
 		aed->lengthAllocDescs =
 		aed->lengthAllocDescs =
 			cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 			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)
 		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
 		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;
 	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;
 	int adsize;
 	uint8_t *ptr;
 	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
 	else
-	{
-		ptr = bh->b_data + *extoffset;
-		atomic_inc(&bh->b_count);
-	}
+		ptr = epos->bh->b_data + epos->offset;
 
 
 	switch (UDF_I_ALLOCTYPE(inode))
 	switch (UDF_I_ALLOCTYPE(inode))
 	{
 	{
@@ -1734,40 +1733,39 @@ int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
 			return -1;
 			return -1;
 	}
 	}
 
 
-	if (bh)
+	if (epos->bh)
 	{
 	{
 		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
 		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));
 				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
 	else
 		mark_inode_dirty(inode);
 		mark_inode_dirty(inode);
 
 
 	if (inc)
 	if (inc)
-		*extoffset += adsize;
+		epos->offset += adsize;
 	return (elen >> 30);
 	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;
 	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))
 		(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_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;
 			return -1;
 		}
 		}
 	}
 	}
@@ -1775,26 +1773,26 @@ int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
 	return etype;
 	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;
 	int alen;
 	int8_t etype;
 	int8_t etype;
 	uint8_t *ptr;
 	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);
 		alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
 	}
 	}
 	else
 	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))
 	switch (UDF_I_ALLOCTYPE(inode))
@@ -1803,7 +1801,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
 		{
 		{
 			short_ad *sad;
 			short_ad *sad;
 
 
-			if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
+			if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc)))
 				return -1;
 				return -1;
 
 
 			etype = le32_to_cpu(sad->extLength) >> 30;
 			etype = le32_to_cpu(sad->extLength) >> 30;
@@ -1816,7 +1814,7 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
 		{
 		{
 			long_ad *lad;
 			long_ad *lad;
 
 
-			if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
+			if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, inc)))
 				return -1;
 				return -1;
 
 
 			etype = le32_to_cpu(lad->extLength) >> 30;
 			etype = le32_to_cpu(lad->extLength) >> 30;
@@ -1835,41 +1833,40 @@ int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffse
 }
 }
 
 
 static int8_t
 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;
 	kernel_lb_addr oeloc;
 	uint32_t oelen;
 	uint32_t oelen;
 	int8_t etype;
 	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;
 		neloc = oeloc;
 		nelen = (etype << 30) | oelen;
 		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);
 	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;
 	int8_t etype;
 	struct allocExtDesc *aed;
 	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)
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -1879,78 +1876,75 @@ int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset
 	else
 	else
 		adsize = 0;
 		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;
 		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));
 	memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 	elen = 0;
 	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);
 			UDF_I_LENALLOC(inode) -= (adsize * 2);
 			mark_inode_dirty(inode);
 			mark_inode_dirty(inode);
 		}
 		}
 		else
 		else
 		{
 		{
-			aed = (struct allocExtDesc *)(obh)->b_data;
+			aed = (struct allocExtDesc *)oepos.bh->b_data;
 			aed->lengthAllocDescs =
 			aed->lengthAllocDescs =
 				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
 				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)
 			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
 			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
 	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;
 			UDF_I_LENALLOC(inode) -= adsize;
 			mark_inode_dirty(inode);
 			mark_inode_dirty(inode);
 		}
 		}
 		else
 		else
 		{
 		{
-			aed = (struct allocExtDesc *)(obh)->b_data;
+			aed = (struct allocExtDesc *)oepos.bh->b_data;
 			aed->lengthAllocDescs =
 			aed->lengthAllocDescs =
 				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
 				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)
 			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
 			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);
 	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;
 	loff_t lbcount = 0, bcount = (loff_t)block << inode->i_sb->s_blocksize_bits;
 	int8_t etype;
 	int8_t etype;
@@ -1961,13 +1955,14 @@ int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uin
 		return -1;
 		return -1;
 	}
 	}
 
 
-	*extoffset = 0;
+	pos->offset = 0;
+	pos->block = UDF_I_LOCATION(inode);
+	pos->bh = NULL;
 	*elen = 0;
 	*elen = 0;
-	*bloc = UDF_I_LOCATION(inode);
 
 
 	do
 	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;
 			*offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;
 			UDF_I_LENEXTENTS(inode) = lbcount;
 			UDF_I_LENEXTENTS(inode) = lbcount;
@@ -1983,21 +1978,21 @@ int8_t inode_bmap(struct inode *inode, sector_t block, kernel_lb_addr *bloc, uin
 
 
 long udf_block_map(struct inode *inode, sector_t block)
 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;
 	sector_t offset;
-	struct buffer_head *bh = NULL;
+	struct extent_position epos = { NULL, 0, { 0, 0}};
 	int ret;
 	int ret;
 
 
 	lock_kernel();
 	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);
 		ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
 	else
 	else
 		ret = 0;
 		ret = 0;
 
 
 	unlock_kernel();
 	unlock_kernel();
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 
 
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
 	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
 		return udf_fixed_to_variable(ret);
 		return udf_fixed_to_variable(ret);

+ 61 - 61
fs/udf/namei.c

@@ -155,10 +155,10 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
 	uint8_t lfi;
 	uint8_t lfi;
 	uint16_t liu;
 	uint16_t liu;
 	loff_t size;
 	loff_t size;
-	kernel_lb_addr bloc, eloc;
-	uint32_t extoffset, elen;
+	kernel_lb_addr eloc;
+	uint32_t elen;
 	sector_t offset;
 	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;
 	size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	f_pos = (udf_ext0_offset(dir) >> 2);
 	f_pos = (udf_ext0_offset(dir) >> 2);
@@ -167,41 +167,41 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 		fibh->sbh = fibh->ebh = NULL;
 		fibh->sbh = fibh->ebh = NULL;
 	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 	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);
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
 			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)
 			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-				extoffset -= sizeof(long_ad);
+				epos.offset -= sizeof(long_ad);
 		}
 		}
 		else
 		else
 			offset = 0;
 			offset = 0;
 
 
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		{
 		{
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return NULL;
 			return NULL;
 		}
 		}
 	}
 	}
 	else
 	else
 	{
 	{
-		udf_release_data(bh);
+		udf_release_data(epos.bh);
 		return NULL;
 		return NULL;
 	}
 	}
 
 
 	while ( (f_pos < size) )
 	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 (!fi)
 		{
 		{
 			if (fibh->sbh != fibh->ebh)
 			if (fibh->sbh != fibh->ebh)
 				udf_release_data(fibh->ebh);
 				udf_release_data(fibh->ebh);
 			udf_release_data(fibh->sbh);
 			udf_release_data(fibh->sbh);
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return NULL;
 			return NULL;
 		}
 		}
 
 
@@ -247,7 +247,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
 		{
 		{
 			if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
 			if (udf_match(flen, fname, dentry->d_name.len, dentry->d_name.name))
 			{
 			{
-				udf_release_data(bh);
+				udf_release_data(epos.bh);
 				return fi;
 				return fi;
 			}
 			}
 		}
 		}
@@ -255,7 +255,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
 	if (fibh->sbh != fibh->ebh)
 	if (fibh->sbh != fibh->ebh)
 		udf_release_data(fibh->ebh);
 		udf_release_data(fibh->ebh);
 	udf_release_data(fibh->sbh);
 	udf_release_data(fibh->sbh);
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -353,10 +353,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 	uint8_t lfi;
 	uint8_t lfi;
 	uint16_t liu;
 	uint16_t liu;
 	int block;
 	int block;
-	kernel_lb_addr bloc, eloc;
-	uint32_t extoffset, elen;
+	kernel_lb_addr eloc;
+	uint32_t elen;
 	sector_t offset;
 	sector_t offset;
-	struct buffer_head *bh = NULL;
+	struct extent_position epos = { NULL, 0, { 0, 0 }};
 
 
 	sb = dir->i_sb;
 	sb = dir->i_sb;
 
 
@@ -385,22 +385,22 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 		fibh->sbh = fibh->ebh = NULL;
 		fibh->sbh = fibh->ebh = NULL;
 	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 	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);
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
 			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)
 			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-				extoffset -= sizeof(long_ad);
+				epos.offset -= sizeof(long_ad);
 		}
 		}
 		else
 		else
 			offset = 0;
 			offset = 0;
 
 
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
 		{
 		{
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			*err = -EIO;
 			*err = -EIO;
 			return NULL;
 			return NULL;
 		}
 		}
@@ -418,14 +418,14 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 
 
 	while ( (f_pos < size) )
 	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 (!fi)
 		{
 		{
 			if (fibh->sbh != fibh->ebh)
 			if (fibh->sbh != fibh->ebh)
 				udf_release_data(fibh->ebh);
 				udf_release_data(fibh->ebh);
 			udf_release_data(fibh->sbh);
 			udf_release_data(fibh->sbh);
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			*err = -EIO;
 			*err = -EIO;
 			return NULL;
 			return NULL;
 		}
 		}
@@ -455,7 +455,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 		{
 		{
 			if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
 			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->descTag.tagSerialNum = cpu_to_le16(1);
 				cfi->fileVersionNum = cpu_to_le16(1);
 				cfi->fileVersionNum = cpu_to_le16(1);
 				cfi->fileCharacteristics = 0;
 				cfi->fileCharacteristics = 0;
@@ -480,7 +480,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 			if (fibh->sbh != fibh->ebh)
 			if (fibh->sbh != fibh->ebh)
 				udf_release_data(fibh->ebh);
 				udf_release_data(fibh->ebh);
 			udf_release_data(fibh->sbh);
 			udf_release_data(fibh->sbh);
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			*err = -EEXIST;
 			*err = -EEXIST;
 			return NULL;
 			return NULL;
 		}
 		}
@@ -492,8 +492,8 @@ add:
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
 		sb->s_blocksize - fibh->eoffset < nfidlen)
 		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->soffset -= udf_ext0_offset(dir);
 		fibh->eoffset -= udf_ext0_offset(dir);
 		fibh->eoffset -= udf_ext0_offset(dir);
 		f_pos -= (udf_ext0_offset(dir) >> 2);
 		f_pos -= (udf_ext0_offset(dir) >> 2);
@@ -502,15 +502,15 @@ add:
 		udf_release_data(fibh->sbh);
 		udf_release_data(fibh->sbh);
 		if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
 		if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
 			return NULL;
 			return NULL;
-		bloc = UDF_I_LOCATION(dir);
+		epos.block = UDF_I_LOCATION(dir);
 		eloc.logicalBlockNum = block;
 		eloc.logicalBlockNum = block;
 		eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
 		eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
 		elen = dir->i_sb->s_blocksize;
 		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)
 		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)
 		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)
 	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)))
 		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);
 			udf_release_data(fibh->sbh);
 			return NULL;
 			return NULL;
 		}
 		}
 
 
 		if (!(fibh->soffset))
 		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))
 				(EXT_RECORDED_ALLOCATED >> 30))
 			{
 			{
 				block = eloc.logicalBlockNum + ((elen - 1) >>
 				block = eloc.logicalBlockNum + ((elen - 1) >>
@@ -587,7 +587,7 @@ add:
 	cfi->lengthOfImpUse = cpu_to_le16(0);
 	cfi->lengthOfImpUse = cpu_to_le16(0);
 	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
 	if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
 	{
 	{
-		udf_release_data(bh);
+		udf_release_data(epos.bh);
 		dir->i_size += nfidlen;
 		dir->i_size += nfidlen;
 		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 		if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 			UDF_I_LENALLOC(dir) += nfidlen;
 			UDF_I_LENALLOC(dir) += nfidlen;
@@ -596,7 +596,7 @@ add:
 	}
 	}
 	else
 	else
 	{
 	{
-		udf_release_data(bh);
+		udf_release_data(epos.bh);
 		if (fibh->sbh != fibh->ebh)
 		if (fibh->sbh != fibh->ebh)
 			udf_release_data(fibh->ebh);
 			udf_release_data(fibh->ebh);
 		udf_release_data(fibh->sbh);
 		udf_release_data(fibh->sbh);
@@ -781,10 +781,10 @@ static int empty_dir(struct inode *dir)
 	loff_t f_pos;
 	loff_t f_pos;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	int block;
 	int block;
-	kernel_lb_addr bloc, eloc;
-	uint32_t extoffset, elen;
+	kernel_lb_addr eloc;
+	uint32_t elen;
 	sector_t offset;
 	sector_t offset;
-	struct buffer_head *bh = NULL;
+	struct extent_position epos = { NULL, 0, { 0, 0}};
 
 
 	f_pos = (udf_ext0_offset(dir) >> 2);
 	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)
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
 		fibh.sbh = fibh.ebh = NULL;
 		fibh.sbh = fibh.ebh = NULL;
 	else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2),
 	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);
 		block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
 		{
 		{
 			if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
 			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)
 			else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
-				extoffset -= sizeof(long_ad);
+				epos.offset -= sizeof(long_ad);
 		}
 		}
 		else
 		else
 			offset = 0;
 			offset = 0;
 
 
 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
 		{
 		{
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
 	else
 	else
 	{
 	{
-		udf_release_data(bh);
+		udf_release_data(epos.bh);
 		return 0;
 		return 0;
 	}
 	}
 
 
 
 
 	while ( (f_pos < size) )
 	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 (!fi)
 		{
 		{
 			if (fibh.sbh != fibh.ebh)
 			if (fibh.sbh != fibh.ebh)
 				udf_release_data(fibh.ebh);
 				udf_release_data(fibh.ebh);
 			udf_release_data(fibh.sbh);
 			udf_release_data(fibh.sbh);
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return 0;
 			return 0;
 		}
 		}
 
 
@@ -837,14 +837,14 @@ static int empty_dir(struct inode *dir)
 			if (fibh.sbh != fibh.ebh)
 			if (fibh.sbh != fibh.ebh)
 				udf_release_data(fibh.ebh);
 				udf_release_data(fibh.ebh);
 			udf_release_data(fibh.sbh);
 			udf_release_data(fibh.sbh);
-			udf_release_data(bh);
+			udf_release_data(epos.bh);
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
 	if (fibh.sbh != fibh.ebh)
 	if (fibh.sbh != fibh.ebh)
 		udf_release_data(fibh.ebh);
 		udf_release_data(fibh.ebh);
 	udf_release_data(fibh.sbh);
 	udf_release_data(fibh.sbh);
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 	return 1;
 	return 1;
 }
 }
 
 
@@ -941,7 +941,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 	struct pathComponent *pc;
 	struct pathComponent *pc;
 	char *compstart;
 	char *compstart;
 	struct udf_fileident_bh fibh;
 	struct udf_fileident_bh fibh;
-	struct buffer_head *bh = NULL;
+	struct extent_position epos = { NULL,  0, {0, 0}};
 	int eoffset, elen = 0;
 	int eoffset, elen = 0;
 	struct fileIdentDesc *fi;
 	struct fileIdentDesc *fi;
 	struct fileIdentDesc cfi;
 	struct fileIdentDesc cfi;
@@ -961,33 +961,33 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 
 
 	if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
 	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,
 		block = udf_new_block(inode->i_sb, inode,
 			UDF_I_LOCATION(inode).partitionReferenceNum,
 			UDF_I_LOCATION(inode).partitionReferenceNum,
 			UDF_I_LOCATION(inode).logicalBlockNum, &err);
 			UDF_I_LOCATION(inode).logicalBlockNum, &err);
 		if (!block)
 		if (!block)
 			goto out_no_entry;
 			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.logicalBlockNum = block;
 		eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
 		eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
 		elen = inode->i_sb->s_blocksize;
 		elen = inode->i_sb->s_blocksize;
 		UDF_I_LENEXTENTS(inode) = elen;
 		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,
 		block = udf_get_pblock(inode->i_sb, block,
 			UDF_I_LOCATION(inode).partitionReferenceNum, 0);
 			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
 	else
 		ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
 		ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
@@ -1060,7 +1060,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 		}
 		}
 	}
 	}
 
 
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 	inode->i_size = elen;
 	inode->i_size = elen;
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
 		UDF_I_LENALLOC(inode) = inode->i_size;
 		UDF_I_LENALLOC(inode) = inode->i_size;

+ 8 - 9
fs/udf/super.c

@@ -1883,21 +1883,20 @@ static unsigned int
 udf_count_free_table(struct super_block *sb, struct inode * table)
 udf_count_free_table(struct super_block *sb, struct inode * table)
 {
 {
 	unsigned int accum = 0;
 	unsigned int accum = 0;
-	uint32_t extoffset, elen;
-	kernel_lb_addr bloc, eloc;
+	uint32_t elen;
+	kernel_lb_addr eloc;
 	int8_t etype;
 	int8_t etype;
-	struct buffer_head *bh = NULL;
+	struct extent_position epos;
 
 
 	lock_kernel();
 	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);
 		accum += (elen >> table->i_sb->s_blocksize_bits);
-	}
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 
 
 	unlock_kernel();
 	unlock_kernel();
 
 

+ 78 - 81
fs/udf/truncate.c

@@ -28,8 +28,8 @@
 #include "udf_i.h"
 #include "udf_i.h"
 #include "udf_sb.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 };
 	kernel_lb_addr neloc = { 0, 0 };
 	int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 	int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
@@ -49,7 +49,7 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
 
 
 	if (elen != nelen)
 	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 (last_block - first_block > 0)
 		{
 		{
 			if (etype == (EXT_RECORDED_ALLOCATED >> 30))
 			if (etype == (EXT_RECORDED_ALLOCATED >> 30))
@@ -63,18 +63,16 @@ static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffse
 
 
 void udf_discard_prealloc(struct inode * inode)
 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;
 	uint64_t lbcount = 0;
 	int8_t etype = -1, netype;
 	int8_t etype = -1, netype;
-	struct buffer_head *bh = NULL;
 	int adsize;
 	int adsize;
 
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
 		inode->i_size == UDF_I_LENEXTENTS(inode))
 		inode->i_size == UDF_I_LENEXTENTS(inode))
-	{
 		return;
 		return;
-	}
 
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 		adsize = sizeof(short_ad);
 		adsize = sizeof(short_ad);
@@ -83,53 +81,55 @@ void udf_discard_prealloc(struct inode * inode)
 	else
 	else
 		adsize = 0;
 		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;
 		etype = netype;
 		lbcount += elen;
 		lbcount += elen;
 		if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
 		if (lbcount > inode->i_size && lbcount - inode->i_size < inode->i_sb->s_blocksize)
 		{
 		{
 			nelen = elen - (lbcount - inode->i_size);
 			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;
 			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;
 		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);
 			mark_inode_dirty(inode);
 		}
 		}
 		else
 		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)
 			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
 			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_I_LENEXTENTS(inode) = lbcount;
 
 
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 }
 }
 
 
 void udf_truncate_extents(struct inode * inode)
 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;
 	int8_t etype;
 	sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset;
 	sector_t first_block = inode->i_size >> inode->i_sb->s_blocksize_bits, offset;
 	loff_t byte_offset;
 	loff_t byte_offset;
-	struct buffer_head *bh = NULL;
 	int adsize;
 	int adsize;
 
 
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
 	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -137,102 +137,98 @@ void udf_truncate_extents(struct inode * inode)
 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
 	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
 		adsize = sizeof(long_ad);
 		adsize = sizeof(long_ad);
 	else
 	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));
 	byte_offset = (offset << inode->i_sb->s_blocksize_bits) + (inode->i_size & (inode->i_sb->s_blocksize-1));
 	if (etype != -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)
 		if (byte_offset)
-			lenalloc = extoffset;
+			lenalloc = epos.offset;
 		else
 		else
-			lenalloc = extoffset - adsize;
+			lenalloc = epos.offset - adsize;
 
 
-		if (!bh)
+		if (!epos.bh)
 			lenalloc -= udf_file_entry_alloc_offset(inode);
 			lenalloc -= udf_file_entry_alloc_offset(inode);
 		else
 		else
 			lenalloc -= sizeof(struct allocExtDesc);
 			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))
 			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();
 						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
 				else
 				{
 				{
-					if (!bh)
+					if (!epos.bh)
 					{
 					{
 						UDF_I_LENALLOC(inode) = lenalloc;
 						UDF_I_LENALLOC(inode) = lenalloc;
 						mark_inode_dirty(inode);
 						mark_inode_dirty(inode);
 					}
 					}
 					else
 					else
 					{
 					{
-						struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+						struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
 						aed->lengthAllocDescs = cpu_to_le32(lenalloc);
 						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(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));
 								sizeof(struct allocExtDesc));
 						else
 						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)
 				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;
 						inode->i_sb->s_blocksize_bits;
 				else
 				else
-					lelen = 1;
+					indirect_ext_len = 1;
 			}
 			}
 			else
 			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();
 				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
 		else
 		{
 		{
-			if (!bh)
+			if (!epos.bh)
 			{
 			{
 				UDF_I_LENALLOC(inode) = lenalloc;
 				UDF_I_LENALLOC(inode) = lenalloc;
 				mark_inode_dirty(inode);
 				mark_inode_dirty(inode);
 			}
 			}
 			else
 			else
 			{
 			{
-				struct allocExtDesc *aed = (struct allocExtDesc *)(bh->b_data);
+				struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
 				aed->lengthAllocDescs = cpu_to_le32(lenalloc);
 				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(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));
 						sizeof(struct allocExtDesc));
 				else
 				else
-					udf_update_tag(bh->b_data, sizeof(struct allocExtDesc));
-				mark_buffer_dirty_inode(bh, inode);
+					udf_update_tag(epos.bh->b_data, sizeof(struct allocExtDesc));
+				mark_buffer_dirty_inode(epos.bh, inode);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -245,50 +241,51 @@ void udf_truncate_extents(struct inode * inode)
 			 *  no extent above inode->i_size => truncate is
 			 *  no extent above inode->i_size => truncate is
 			 *  extending the file by 'offset'.
 			 *  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! */
 				/* File has no extents at all! */
 				memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 				memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
 				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 {
 			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))
 				if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
 				{
 				{
-					extoffset -= adsize;
+					epos.offset -= adsize;
 					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + byte_offset);
 					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))
 				else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
 				{
 				{
 					kernel_lb_addr neloc = { 0, 0 };
 					kernel_lb_addr neloc = { 0, 0 };
-					extoffset -= adsize;
+					epos.offset -= adsize;
 					nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
 					nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
 						((elen + byte_offset + inode->i_sb->s_blocksize - 1) &
 						((elen + byte_offset + inode->i_sb->s_blocksize - 1) &
 						~(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
 				else
 				{
 				{
 					if (elen & (inode->i_sb->s_blocksize - 1))
 					if (elen & (inode->i_sb->s_blocksize - 1))
 					{
 					{
-						extoffset -= adsize;
+						epos.offset -= adsize;
 						elen = EXT_RECORDED_ALLOCATED |
 						elen = EXT_RECORDED_ALLOCATED |
 							((elen + inode->i_sb->s_blocksize - 1) &
 							((elen + inode->i_sb->s_blocksize - 1) &
 							~(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));
 					memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | byte_offset;
 					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_I_LENEXTENTS(inode) = inode->i_size;
 
 
-	udf_release_data(bh);
+	udf_release_data(epos.bh);
 }
 }

+ 14 - 7
fs/udf/udfdecl.h

@@ -77,6 +77,13 @@ struct ustr
 	uint8_t u_len;
 	uint8_t u_len;
 };
 };
 
 
+struct extent_position {
+	struct buffer_head *bh;
+	uint32_t offset;
+	kernel_lb_addr block;
+};
+
+
 /* super.c */
 /* super.c */
 extern void udf_error(struct super_block *, const char *, const char *, ...);
 extern void udf_error(struct super_block *, const char *, const char *, ...);
 extern void udf_warning(struct super_block *, const char *, const char *, ...);
 extern void udf_warning(struct super_block *, const char *, const char *, ...);
@@ -99,12 +106,12 @@ extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
 extern int udf_write_inode(struct inode *, int);
 extern int udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, sector_t);
 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 */
 /* misc.c */
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
@@ -151,7 +158,7 @@ extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_
 extern int udf_fsync_file(struct file *, struct dentry *, int);
 extern int udf_fsync_file(struct file *, struct dentry *, int);
 
 
 /* directory.c */
 /* 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 struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
 extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
 extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
 extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
 extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);