patch-2.3.41 linux/fs/udf/inode.c

Next file: linux/fs/udf/lowlevel.c
Previous file: linux/fs/udf/ialloc.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.40/linux/fs/udf/inode.c linux/fs/udf/inode.c
@@ -16,8 +16,8 @@
  *  Each contributing author retains all rights to their own work.
  *
  *  (C) 1998 Dave Boynton
- *  (C) 1998-1999 Ben Fennema
- *  (C) 1999 Stelias Computing Inc
+ *  (C) 1998-2000 Ben Fennema
+ *  (C) 1999-2000 Stelias Computing Inc
  *
  * HISTORY
  *
@@ -31,7 +31,6 @@
  *  03/07/99      rewrote udf_block_map (again)
  *                New funcs, inode_bmap, udf_next_aext
  *  04/19/99      Support for writing device EA's for major/minor #
- *
  */
 
 #include "udfdecl.h"
@@ -58,8 +57,6 @@
 	long_ad [EXTENT_MERGE_SIZE], int, int,
 	lb_addr, Uint32, struct buffer_head **);
 
-static DECLARE_MUTEX(read_semaphore);
-
 /*
  * udf_put_inode
  *
@@ -99,56 +96,14 @@
 {
 	inode->i_size = 0;
 	if (inode->i_blocks)
-		udf_truncate(inode);
+		inode->i_op->truncate(inode);
 	udf_free_inode(inode);
 }
 
 void udf_discard_prealloc(struct inode * inode)
 {
-#ifdef UDF_PREALLOCATE
-	lb_addr bloc, eloc;
-	Uint32 extoffset, elen, nelen, offset, adsize = 0;
-	struct buffer_head *bh = NULL;
-
-	if ((inode->i_size > 0) &&
-		(inode_bmap(inode, (inode->i_size-1) >> inode->i_sb->s_blocksize_bits,
-			&bloc, &extoffset, &eloc, &elen, &offset, &bh) ==
-				EXTENT_RECORDED_ALLOCATED))
-	{
-		if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
-			adsize = sizeof(short_ad);
-		else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
-			adsize = sizeof(long_ad);
-		else
-		{
-			udf_release_data(bh);
-			return;
-		}
-
-		nelen = (EXTENT_RECORDED_ALLOCATED << 30) |
-			((((elen - 1) & ~(inode->i_sb->s_blocksize - 1)) |
-			((inode->i_size - 1) & (inode->i_sb->s_blocksize - 1))) + 1);
-
-		if (nelen != ((EXTENT_RECORDED_ALLOCATED << 30) | elen))
-		{
-			extoffset -= adsize;
-			udf_write_aext(inode, bloc, &extoffset, eloc, nelen, &bh, 1);
-		}
-
-		if (udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0) ==
-			EXTENT_NOT_RECORDED_ALLOCATED)
-		{
-			udf_free_blocks(inode, eloc, 0, elen >> inode->i_sb->s_blocksize_bits);
-			memset(&eloc, 0x00, sizeof(lb_addr));
-			udf_write_aext(inode, bloc, &extoffset, eloc, 0, &bh, 1);
-			UDF_I_LENALLOC(inode) -= adsize;
-			udf_write_inode(inode);
-		}
-		udf_release_data(bh);
-	}
-	else if (bh)
-		udf_release_data(bh);
-#endif
+	if (inode->i_size && UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
+		udf_trunc(inode);
 }
 
 static int udf_alloc_block(struct inode *inode, Uint16 partition,
@@ -162,108 +117,138 @@
 	return result;
 }
 
-struct buffer_head * udf_expand_adinicb(struct inode *inode, int *block, int isdir, int *err)
+void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
 {
-	if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
-	{
-		long_ad newad;
-		int newblock;
-		struct buffer_head *sbh = NULL, *dbh = NULL;
+	struct inode * inode = filp->f_dentry->d_inode;
+	struct buffer_head *bh = NULL;
+	struct page *page;
+	unsigned long kaddr = 0;
 
-		if (!UDF_I_LENALLOC(inode))
-		{
-			UDF_I_EXT0OFFS(inode) = 0;
-			UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
-			mark_inode_dirty(inode);
-			if (inode->i_op == &udf_file_inode_operations_adinicb)
-				inode->i_op = &udf_file_inode_operations;
-			return NULL;
-		}
+	if (!UDF_I_LENALLOC(inode))
+	{
+		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+		mark_inode_dirty(inode);
+		inode->i_op = &udf_file_inode_operations;
+		filp->f_op = inode->i_op->default_file_ops;
+		return;
+	}
 
-		/* alloc block, and copy data to it */
-		*block = udf_alloc_block(inode,
-			UDF_I_LOCATION(inode).partitionReferenceNum,
-			UDF_I_LOCATION(inode).logicalBlockNum, err);
+	bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
+	if (!bh)
+		return;
+	page = grab_cache_page(&inode->i_data, 0);
+	if (!PageLocked(page))
+		BUG();
+	if (!Page_Uptodate(page))
+	{
+		kaddr = kmap(page);
+		memset((char *)kaddr + UDF_I_LENALLOC(inode), 0x00,
+			PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
+		memcpy((char *)kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
+			UDF_I_LENALLOC(inode));
+		kunmap(page);
+	}
+	memset(bh->b_data + udf_file_entry_alloc_offset(inode),
+		0, UDF_I_LENALLOC(inode));
+	UDF_I_LENALLOC(inode) = 0;
+	UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+	inode->i_blocks = inode->i_sb->s_blocksize / 512;
+	mark_buffer_dirty(bh, 1);
+	udf_release_data(bh);
 
-		if (!(*block))
-			return NULL;
-		newblock = udf_get_pblock(inode->i_sb, *block,
-			UDF_I_LOCATION(inode).partitionReferenceNum, 0);
-		if (!newblock)
-			return NULL;
-		sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
-		if (!sbh)
-			return NULL;
-		dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize);
-		if (!dbh)
-			return NULL;
-		
-		if (isdir)
-		{
-			struct udf_fileident_bh sfibh, dfibh;
-			loff_t f_pos = UDF_I_EXT0OFFS(inode) >> 2;
-			loff_t size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2;
-			struct FileIdentDesc cfi, *sfi, *dfi;
-
-			sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
-			sfibh.sbh = sfibh.ebh = sbh;
-			dfibh.soffset = dfibh.eoffset = 0;
-			dfibh.sbh = dfibh.ebh = dbh;
-			while ( (f_pos < size) )
-			{
-				sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
-				if (!sfi)
-				{
-					udf_release_data(sbh);
-					udf_release_data(dbh);
-					return NULL;
-				}
-				sfi->descTag.tagLocation = *block;
-				dfibh.soffset = dfibh.eoffset;
-				dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
-				dfi = (struct FileIdentDesc *)(dbh->b_data + dfibh.soffset);
-				if (udf_write_fi(sfi, dfi, &dfibh, sfi->impUse,
-					sfi->fileIdent + sfi->lengthOfImpUse))
-				{
-					udf_release_data(sbh);
-					udf_release_data(dbh);
-					return NULL;
-				}
-			}
-		}
-		else
-		{
-			memcpy(dbh->b_data, sbh->b_data + udf_file_entry_alloc_offset(inode),
-				UDF_I_LENALLOC(inode));
-		}
-		mark_buffer_dirty(dbh, 1);
+	block_write_full_page(filp->f_dentry, page);
+	UnlockPage(page);
+	page_cache_release(page);
 
-		memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
-			0, UDF_I_LENALLOC(inode));
+	mark_inode_dirty(inode);
+	inode->i_version ++;
+	inode->i_op = &udf_file_inode_operations;
+	filp->f_op = inode->i_op->default_file_ops;
+}
 
-		memset(&newad, 0x00, sizeof(long_ad));
-		newad.extLength = UDF_I_EXT0LEN(inode) = inode->i_size;
-		newad.extLocation.logicalBlockNum = *block;
-		newad.extLocation.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
-		UDF_I_EXT0LOC(inode) = newad.extLocation;
-		/* UniqueID stuff */
+struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
+{
+	long_ad newad;
+	int newblock;
+	struct buffer_head *sbh = NULL, *dbh = NULL;
 
-		memcpy(sbh->b_data + udf_file_entry_alloc_offset(inode),
-			&newad, sizeof(newad));
+	struct udf_fileident_bh sfibh, dfibh;
+	loff_t f_pos = udf_ext0_offset(inode) >> 2;
+	int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
+	struct FileIdentDesc cfi, *sfi, *dfi;
 
-		UDF_I_LENALLOC(inode) = sizeof(newad);
-		UDF_I_EXT0OFFS(inode) = 0;
+	if (!inode->i_size)
+	{
 		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
-		inode->i_blocks += inode->i_sb->s_blocksize / 512;
-		udf_release_data(sbh);
 		mark_inode_dirty(inode);
-		inode->i_version ++;
-		if (inode->i_op == &udf_file_inode_operations_adinicb)
-			inode->i_op = &udf_file_inode_operations;
-		return dbh;
+		return NULL;
 	}
-	else
+
+	/* alloc block, and copy data to it */
+	*block = udf_alloc_block(inode,
+		UDF_I_LOCATION(inode).partitionReferenceNum,
+		UDF_I_LOCATION(inode).logicalBlockNum, err);
+
+	if (!(*block))
+		return NULL;
+	newblock = udf_get_pblock(inode->i_sb, *block,
+		UDF_I_LOCATION(inode).partitionReferenceNum, 0);
+	if (!newblock)
+		return NULL;
+	sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
+	if (!sbh)
 		return NULL;
+	dbh = udf_tread(inode->i_sb, newblock, inode->i_sb->s_blocksize);
+	if (!dbh)
+		return NULL;
+
+	sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
+	sfibh.sbh = sfibh.ebh = sbh;
+	dfibh.soffset = dfibh.eoffset = 0;
+	dfibh.sbh = dfibh.ebh = dbh;
+	while ( (f_pos < size) )
+	{
+		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
+		if (!sfi)
+		{
+			udf_release_data(sbh);
+			udf_release_data(dbh);
+			return NULL;
+		}
+		sfi->descTag.tagLocation = *block;
+		dfibh.soffset = dfibh.eoffset;
+		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
+		dfi = (struct FileIdentDesc *)(dbh->b_data + dfibh.soffset);
+		if (udf_write_fi(sfi, dfi, &dfibh, sfi->impUse,
+			sfi->fileIdent + sfi->lengthOfImpUse))
+		{
+			udf_release_data(sbh);
+			udf_release_data(dbh);
+			return NULL;
+		}
+	}
+	mark_buffer_dirty(dbh, 1);
+
+	memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
+		0, UDF_I_LENALLOC(inode));
+
+	memset(&newad, 0x00, sizeof(long_ad));
+	newad.extLength = inode->i_size;
+	newad.extLocation.logicalBlockNum = *block;
+	newad.extLocation.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
+	/* UniqueID stuff */
+
+	memcpy(sbh->b_data + udf_file_entry_alloc_offset(inode),
+		&newad, sizeof(newad));
+
+	UDF_I_LENALLOC(inode) = sizeof(newad);
+	UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+	inode->i_blocks = inode->i_sb->s_blocksize / 512;
+	mark_buffer_dirty(sbh, 1);
+	udf_release_data(sbh);
+	mark_inode_dirty(inode);
+	inode->i_version ++;
+	return dbh;
 }
 
 struct buffer_head * udf_getblk(struct inode * inode, long block,
@@ -282,6 +267,8 @@
 		bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
 		if (buffer_new(&dummy))
 		{
+			if (!buffer_uptodate(bh))
+				wait_on_buffer(bh);
 			memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
 			mark_buffer_uptodate(bh, 1);
 			mark_buffer_dirty(bh, 1);
@@ -310,6 +297,8 @@
 	}
 
 	err = -EIO;
+	new = 0;
+	bh = NULL;
 
 	lock_kernel();
 
@@ -479,7 +468,7 @@
 	}
 
 	/* 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 */
 	if ((laarr[c].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
 		newblocknum = laarr[c].extLocation.logicalBlockNum + offset;
 	else /* otherwise, allocate a new block */
@@ -522,12 +511,6 @@
 
 	udf_release_data(pbh);
 
-	if (pextoffset == udf_file_entry_alloc_offset(inode))
-	{
-		UDF_I_EXT0LEN(inode) = laarr[0].extLength;
-		UDF_I_EXT0LOC(inode) = laarr[0].extLocation;
-	}
-
 	if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum,
 		UDF_I_LOCATION(inode).partitionReferenceNum, 0)))
 	{
@@ -541,11 +524,9 @@
 	inode->i_ctime = CURRENT_TIME;
 	UDF_I_UCTIME(inode) = CURRENT_UTIME;
 	inode->i_blocks += inode->i_sb->s_blocksize / 512;
-#if 0
-	if (IS_SYNC(inode) || UDF_I_OSYNC(inode))
+	if (IS_SYNC(inode))
 		udf_sync_inode(inode);
 	else
-#endif
 		mark_inode_dirty(inode);
 	return result;
 }
@@ -830,9 +811,16 @@
  *
  * 12/19/98 dgb  Updated to fix size problems.
  */
+
 void
 udf_read_inode(struct inode *inode)
 {
+	memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(lb_addr));
+}
+
+void
+__udf_read_inode(struct inode *inode)
+{
 	struct buffer_head *bh = NULL;
 	struct FileEntry *fe;
 	Uint16 ident;
@@ -851,17 +839,9 @@
 	 *      i_op = NULL;
 	 */
 
-	inode->i_blksize = inode->i_sb->s_blocksize;
+	inode->i_blksize = PAGE_SIZE;
 	inode->i_version = 1;
 
-	UDF_I_EXT0LEN(inode)=0;
-	UDF_I_EXT0LOC(inode).logicalBlockNum = 0xFFFFFFFF;
-	UDF_I_EXT0LOC(inode).partitionReferenceNum = 0xFFFF;
-	UDF_I_EXT0OFFS(inode)=0;
-	UDF_I_ALLOCTYPE(inode)=0;
-
-	memcpy(&UDF_I_LOCATION(inode), &UDF_SB_LOCATION(inode->i_sb), sizeof(lb_addr));
-
 	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
 
 	if (!bh)
@@ -904,11 +884,11 @@
 					if (ident == TID_FILE_ENTRY ||
 						ident == TID_EXTENDED_FILE_ENTRY)
 					{
-						memcpy(&UDF_SB_LOCATION(inode->i_sb), &loc, sizeof(lb_addr));
+						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(lb_addr));
 						udf_release_data(bh);
 						udf_release_data(ibh);
 						udf_release_data(nbh);
-						udf_read_inode(inode);
+						__udf_read_inode(inode);
 						return;
 					}
 					else
@@ -957,11 +937,11 @@
 	else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */
 		UDF_I_STRAT4096(inode) = 1;
 
-	inode->i_uid = udf_convert_uid(le32_to_cpu(fe->uid));
-	if ( !inode->i_uid ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
+	inode->i_uid = le32_to_cpu(fe->uid);
+	if ( inode->i_uid == -1 ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
 
-	inode->i_gid = udf_convert_gid(le32_to_cpu(fe->gid));
-	if ( !inode->i_gid ) inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
+	inode->i_gid = le32_to_cpu(fe->gid);
+	if ( inode->i_gid == -1 ) inode->i_gid = UDF_SB(inode->i_sb)->s_gid;
 
 	inode->i_nlink = le16_to_cpu(fe->fileLinkCount);
 	if (!inode->i_nlink)
@@ -976,12 +956,6 @@
 	inode->i_mode = udf_convert_permissions(fe);
 	inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
 
-#ifdef UDF_PREALLOCATE
-#if 0
-	UDF_I_PREALLOC_BLOCK(inode) = 0;
-	UDF_I_PREALLOC_COUNT(inode) = 0;
-#endif
-#endif
 	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
 	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
 
@@ -1074,58 +1048,6 @@
 		alen = offset + UDF_I_LENALLOC(inode);
 	}
 
-	switch (UDF_I_ALLOCTYPE(inode))
-	{
-		case ICB_FLAG_AD_SHORT:
- 		{
- 			short_ad * sa;
-
-			sa = udf_get_fileshortad(fe, alen, &offset, 1);
-			if (sa)
-			{
-				UDF_I_EXT0LEN(inode) = le32_to_cpu(sa->extLength);
- 				UDF_I_EXT0LOC(inode).logicalBlockNum = le32_to_cpu(sa->extPosition);
-				UDF_I_EXT0LOC(inode).partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
-			}
-			break;
- 		}
-		case ICB_FLAG_AD_LONG:
-		{
-		    long_ad * la;
-
-		    la = udf_get_filelongad(fe, alen, &offset, 1);
-		    if (la)
-			{
-				UDF_I_EXT0LEN(inode) = le32_to_cpu(la->extLength);
-				UDF_I_EXT0LOC(inode).logicalBlockNum = le32_to_cpu(la->extLocation.logicalBlockNum);
-				UDF_I_EXT0LOC(inode).partitionReferenceNum = le16_to_cpu(la->extLocation.partitionReferenceNum);
-		    }
-			break;
-		}
-		case ICB_FLAG_AD_EXTENDED:
-		{
-			extent_ad * ext;
-
-		    ext = udf_get_fileextent(fe, alen, &offset);
-		    if ( (ext) && (ext->extLength) )
-			{
-				UDF_I_EXT0LEN(inode) = le32_to_cpu(ext->extLength);
-#if 0
-				UDF_I_EXT0LOC(inode) = ext->extLocation;
-#endif
-			}
-			break;
-		}
-		case ICB_FLAG_AD_IN_ICB: /* short directories */
-		{
-			UDF_I_EXT0LEN(inode) = le32_to_cpu(fe->lengthAllocDescs);
-			UDF_I_EXT0LOC(inode) = UDF_I_LOCATION(inode);
-			UDF_I_EXT0OFFS(inode) = sizeof(struct FileEntry) +
-				le32_to_cpu(fe->lengthExtendedAttr);
-			break;
-		}
-	} /* end switch ad_type */
-
 	switch (fe->icbTag.fileType)
 	{
 		case FILE_TYPE_DIRECTORY:
@@ -1162,7 +1084,6 @@
 		}
 		case FILE_TYPE_SYMLINK:
 		{
-			/* untested! */
 			inode->i_op = &udf_symlink_inode_operations;
 			inode->i_mode = S_IFLNK|S_IRWXUGO;
 			break;
@@ -1184,7 +1105,7 @@
 
 		if (dsea)
 		{
-			init_special_inode(inode, inode->i_mode, 
+			init_special_inode(inode, inode->i_mode,
 				((le32_to_cpu(dsea->majorDeviceIdent)) << 8) |
 				(le32_to_cpu(dsea->minorDeviceIdent) & 0xFF));
 			/* Developer ID ??? */
@@ -1440,19 +1361,11 @@
 
 	block = udf_get_lb_pblock(sb, ino, 0);
 
-	down(&read_semaphore); /* serialize access to UDF_SB_LOCATION() */
-	/* This is really icky.. should fix -- blf */
-
-	/* put the location where udf_read_inode can find it */
-	memcpy(&UDF_SB_LOCATION(sb), &ino, sizeof(lb_addr));
-
 	/* Get the inode */
 
 	inode = iget(sb, block);
 		/* calls udf_read_inode() ! */
 
-	up(&read_semaphore);
-
 	if (!inode)
 	{
 		printk(KERN_ERR "udf: iget() failed\n");
@@ -1463,6 +1376,12 @@
 		iput(inode);
 		return NULL;
 	}
+	else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&
+		UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)
+	{
+		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
+		__udf_read_inode(inode);
+	}
 
 	if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) )
 	{
@@ -1732,6 +1651,14 @@
 			}
 			break;
 		}
+		case ICB_FLAG_AD_IN_ICB:
+		{
+			*bloc = *eloc = UDF_I_LOCATION(inode);
+			*elen = UDF_I_LENALLOC(inode);
+			*extoffset = udf_file_entry_alloc_offset(inode);
+			etype = EXTENT_RECORDED_ALLOCATED;
+			break;
+		}
 		default:
 		{
 			udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
@@ -1741,7 +1668,8 @@
 	if (*elen)
 		return etype;
 
-	udf_debug("Empty Extent!\n");
+	udf_debug("Empty Extent, inode=%ld, alloctype=%d, elen=%d, etype=%d, extoffset=%d\n",
+		inode->i_ino, UDF_I_ALLOCTYPE(inode), *elen, etype, *extoffset);
 	if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
 		*extoffset -= sizeof(short_ad);
 	else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
@@ -1974,26 +1902,22 @@
 		return -1;
 	}
 
+	*extoffset = udf_file_entry_alloc_offset(inode);
+	*elen = 0;
 	b_off = block << inode->i_sb->s_blocksize_bits;
 	*bloc = UDF_I_LOCATION(inode);
-	*eloc = UDF_I_EXT0LOC(inode);
-	*elen = UDF_I_EXT0LEN(inode) & UDF_EXTENT_LENGTH_MASK;
-	*extoffset = udf_file_entry_alloc_offset(inode);
-	if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
-		*extoffset += sizeof(short_ad);
-	else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
-		*extoffset += sizeof(long_ad);
-	etype = UDF_I_EXT0LEN(inode) >> 30;
 
-	while (lbcount + *elen <= b_off)
+	do
 	{
 		lbcount += *elen;
+
 		if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
 		{
 			*offset = (b_off - lbcount) >> inode->i_sb->s_blocksize_bits;
 			return -1;
 		}
-	}
+	} while (lbcount + *elen <= b_off);
+
 	*offset = (b_off - lbcount) >> inode->i_sb->s_blocksize_bits;
 
 	return etype;
@@ -2028,4 +1952,59 @@
 	ret = udf_locked_block_map(inode, block);
 	unlock_kernel();
 	return ret;
+}
+
+int udf_readpage_adinicb (struct dentry *dentry, struct page * page)
+{
+	struct inode *inode = dentry->d_inode;
+
+	struct buffer_head *bh;
+	int block;
+	unsigned long kaddr = 0;
+
+	if (!PageLocked(page))
+		PAGE_BUG(page);
+
+	kaddr = kmap(page);
+	memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
+	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+	bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
+	ll_rw_block (READ, 1, &bh);
+	wait_on_buffer(bh);
+	memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
+		inode->i_size);
+	brelse(bh);
+	SetPageUptodate(page);
+	kunmap(page);
+	UnlockPage(page);
+	return 0;
+}
+
+int udf_writepage_adinicb (struct dentry *dentry, struct page *page)
+{
+	struct inode *inode = dentry->d_inode;
+
+	struct buffer_head *bh;
+	int block;
+	unsigned long kaddr = 0;
+
+	if (!PageLocked(page))
+		BUG();
+
+	kaddr = kmap(page);
+	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+	bh = getblk (inode->i_dev, block, inode->i_sb->s_blocksize);
+	if (!buffer_uptodate(bh))
+	{
+		ll_rw_block (READ, 1, &bh);
+		wait_on_buffer(bh);
+	}
+	memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
+		inode->i_size);
+	ll_rw_block (WRITE, 1, &bh);
+	wait_on_buffer(bh);
+	brelse(bh);
+	SetPageUptodate(page);
+	kunmap(page);
+	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)