patch-2.3.49 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.48/linux/fs/udf/inode.c linux/fs/udf/inode.c
@@ -74,7 +74,10 @@
  */
 void udf_put_inode(struct inode * inode)
 {
+	lock_kernel();
 	udf_discard_prealloc(inode);
+	write_inode_now(inode);
+	unlock_kernel();
 }
 
 /*
@@ -95,10 +98,20 @@
  */
 void udf_delete_inode(struct inode * inode)
 {
+	lock_kernel();
+
+	if (is_bad_inode(inode))
+	{
+		clear_inode(inode);
+		goto out;
+	}
+
 	inode->i_size = 0;
-	if (inode->i_blocks)
-		udf_truncate(inode);
+	udf_truncate(inode);
+	write_inode_now(inode);
 	udf_free_inode(inode);
+out:
+	unlock_kernel();
 }
 
 void udf_discard_prealloc(struct inode * inode)
@@ -107,64 +120,61 @@
 		udf_trunc(inode);
 }
 
-static int udf_alloc_block(struct inode *inode, Uint16 partition,
-	Uint32 goal, int *err)
-{
-	int result = 0;
-	wait_on_super(inode->i_sb);
-
-	result = udf_new_block(inode, partition, goal, err);
-
-	return result;
-}
-
 static int udf_writepage(struct dentry *dentry, struct page *page)
 {
-	return block_write_full_page(page,udf_get_block);
+	return block_write_full_page(page, udf_get_block);
 }
+
 static int udf_readpage(struct dentry *dentry, struct page *page)
 {
-	return block_read_full_page(page,udf_get_block);
+	return block_read_full_page(page, udf_get_block);
 }
+
 static int udf_prepare_write(struct page *page, unsigned from, unsigned to)
 {
-	return block_prepare_write(page,from,to,udf_get_block);
+	return block_prepare_write(page, from, to, udf_get_block);
 }
+
 static int udf_bmap(struct address_space *mapping, long block)
 {
 	return generic_block_bmap(mapping,block,udf_get_block);
 }
-static struct address_space_operations udf_aops = {
-	readpage: udf_readpage,
-	writepage: udf_writepage,
-	prepare_write: udf_prepare_write,
-	commit_write: generic_commit_write,
-	bmap: udf_bmap
+
+struct address_space_operations udf_aops = {
+	readpage:			udf_readpage,
+	writepage:			udf_writepage,
+	prepare_write:		udf_prepare_write,
+	commit_write:		generic_commit_write,
+	bmap:				udf_bmap,
 };
 
-void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
+void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
 {
-	struct inode * inode = filp->f_dentry->d_inode;
 	struct buffer_head *bh = NULL;
 	struct page *page;
 	unsigned long kaddr = 0;
+	int block;
 
 	/* from now on we have normal address_space methods */
 	inode->i_data.a_ops = &udf_aops;
 
 	if (!UDF_I_LENALLOC(inode))
 	{
-		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+			UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+		else
+			UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
 		mark_inode_dirty(inode);
 		return;
 	}
 
-	bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
+	block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+	bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize);
 	if (!bh)
 		return;
-	page = grab_cache_page(&inode->i_data, 0);
+	page = grab_cache_page(inode->i_mapping, 0);
 	if (!PageLocked(page))
-		BUG();
+		PAGE_BUG(page);
 	if (!Page_Uptodate(page))
 	{
 		kaddr = kmap(page);
@@ -172,17 +182,21 @@
 			PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
 		memcpy((char *)kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
 			UDF_I_LENALLOC(inode));
+		SetPageUptodate(page);
 		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;
+	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+	else
+		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);
 
-	inode->i_data.a_ops->writepage(filp->f_dentry, page);
+	inode->i_data.a_ops->writepage(NULL, page);
 	UnlockPage(page);
 	page_cache_release(page);
 
@@ -192,9 +206,10 @@
 
 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;
+	lb_addr bloc, eloc;
+	Uint32 elen, extoffset;
 
 	struct udf_fileident_bh sfibh, dfibh;
 	loff_t f_pos = udf_ext0_offset(inode) >> 2;
@@ -203,13 +218,16 @@
 
 	if (!inode->i_size)
 	{
-		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+			UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+		else
+			UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
 		mark_inode_dirty(inode);
 		return NULL;
 	}
 
 	/* alloc block, and copy data to it */
-	*block = udf_alloc_block(inode,
+	*block = udf_new_block(inode,
 		UDF_I_LOCATION(inode).partitionReferenceNum,
 		UDF_I_LOCATION(inode).logicalBlockNum, err);
 
@@ -232,7 +250,7 @@
 	dfibh.sbh = dfibh.ebh = dbh;
 	while ( (f_pos < size) )
 	{
-		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
+		sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
 		if (!sfi)
 		{
 			udf_release_data(sbh);
@@ -256,17 +274,19 @@
 	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;
+	UDF_I_LENALLOC(inode) = 0;
+	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+	else
+		UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+	bloc = UDF_I_LOCATION(inode);
+	eloc.logicalBlockNum = *block;
+	eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
+	elen = inode->i_size;
+	extoffset = udf_file_entry_alloc_offset(inode);
+	udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
 	/* 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);
@@ -438,6 +458,14 @@
 	if (etype == -1)
 	{
 		endnum = startnum = ((count > 1) ? 1 : count);
+		if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
+		{
+			laarr[c].extLength =
+				(laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
+				(((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
+					inode->i_sb->s_blocksize - 1) &
+				~(inode->i_sb->s_blocksize - 1));
+		}
 		c = !c;
 		laarr[c].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
 			((offset + 1) << inode->i_sb->s_blocksize_bits);
@@ -506,7 +534,7 @@
 				goal = UDF_I_LOCATION(inode).logicalBlockNum + 1;
 		}
 
-		if (!(newblocknum = udf_alloc_block(inode,
+		if (!(newblocknum = udf_new_block(inode,
 			UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
 		{
 			udf_release_data(pbh);
@@ -613,7 +641,7 @@
 {
 	int start, length = 0, currlength = 0, i;
 
-	if (*endnum == (c+1) && !lastblock)
+	if (*endnum >= (c+1) && !lastblock)
 		return;
 
 	if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
@@ -644,7 +672,7 @@
 		int next = laarr[start].extLocation.logicalBlockNum +
 			(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
 			inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
-		int numalloc = udf_alloc_blocks(inode,
+		int numalloc = udf_prealloc_blocks(inode,
 			laarr[start].extLocation.partitionReferenceNum,
 			next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? length :
 				UDF_DEFAULT_PREALLOC_BLOCKS) - currlength);
@@ -864,7 +892,6 @@
 	 */
 
 	inode->i_blksize = PAGE_SIZE;
-	inode->i_version = 1;
 
 	bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
 
@@ -948,6 +975,9 @@
 	long convtime_usec;
 	int offset, alen;
 
+	inode->i_version = ++event;
+	UDF_I_NEW_INODE(inode) = 0;
+
 	fe = (struct FileEntry *)bh->b_data;
 	efe = (struct ExtendedFileEntry *)bh->b_data;
 
@@ -1183,7 +1213,9 @@
 
 void udf_write_inode(struct inode * inode)
 {
+	lock_kernel();
 	udf_update_inode(inode, 0);
+	unlock_kernel();
 }
 
 int udf_sync_inode(struct inode * inode)
@@ -1214,6 +1246,17 @@
 	}
 	fe = (struct FileEntry *)bh->b_data;
 	efe = (struct ExtendedFileEntry *)bh->b_data;
+	if (UDF_I_NEW_INODE(inode) == 1)
+	{
+		if (UDF_I_EXTENDED_FE(inode) == 0)
+			memset(bh->b_data, 0x0, sizeof(struct FileEntry));
+		else
+			memset(bh->b_data, 0x00, sizeof(struct ExtendedFileEntry));
+		memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
+			UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
+			udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
+		UDF_I_NEW_INODE(inode) = 0;
+	}
 
 	if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
 		fe->uid = cpu_to_le32(inode->i_uid);
@@ -1236,7 +1279,6 @@
 	else
 		fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
 
-
 	fe->informationLength = cpu_to_le64(inode->i_size);
 
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
@@ -1312,8 +1354,17 @@
 		efe->descTag.tagIdent = le16_to_cpu(TID_EXTENDED_FILE_ENTRY);
 		crclen = sizeof(struct ExtendedFileEntry);
 	}
-	fe->icbTag.strategyType = UDF_I_STRAT4096(inode) ? cpu_to_le16(4096) :
-		cpu_to_le16(4);
+	if (UDF_I_STRAT4096(inode))
+	{
+		fe->icbTag.strategyType = cpu_to_le16(4096);
+		fe->icbTag.strategyParameter = cpu_to_le16(1);
+		fe->icbTag.numEntries = cpu_to_le16(2);
+	}
+	else
+	{
+		fe->icbTag.strategyType = cpu_to_le16(4);
+		fe->icbTag.numEntries = cpu_to_le16(1);
+	}
 
 	if (S_ISDIR(inode->i_mode))
 		fe->icbTag.fileType = FILE_TYPE_DIRECTORY;
@@ -1454,11 +1505,10 @@
 		char *sptr, *dptr;
 		struct buffer_head *nbh;
 		int err, loffset;
-		Uint32	lblock = bloc->logicalBlockNum;
-		Uint16  lpart = bloc->partitionReferenceNum;
+		lb_addr obloc = *bloc;
 
 		if (!(bloc->logicalBlockNum = udf_new_block(inode,
-			lpart, lblock, &err)))
+			obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
 		{
 			return -1;
 		}
@@ -1468,7 +1518,7 @@
 			return -1;
 		}
 		aed = (struct AllocExtDesc *)(nbh->b_data);
-		aed->previousAllocExtLocation = cpu_to_le32(lblock);
+		aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
 		if (*extoffset + adsize > inode->i_sb->s_blocksize)
 		{
 			loffset = *extoffset;
@@ -1485,14 +1535,17 @@
 			sptr = (*bh)->b_data + *extoffset;
 			*extoffset = sizeof(struct AllocExtDesc);
 
-			if (UDF_I_LOCATION(inode).logicalBlockNum == lblock)
-				UDF_I_LENALLOC(inode) += adsize;
-			else
+			if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
 			{
 				aed = (struct AllocExtDesc *)(*bh)->b_data;
 				aed->lengthAllocDescs =
 					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
 			}
+			else
+			{
+				UDF_I_LENALLOC(inode) += adsize;
+				mark_inode_dirty(inode);
+			}
 		}
 		udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1,
 			bloc->logicalBlockNum, sizeof(tag));
@@ -1547,7 +1600,7 @@
 	short_ad *sad = NULL;
 	long_ad *lad = NULL;
 
-    if (!(*bh))
+	if (!(*bh))
 	{
 		if (!(*bh = udf_tread(inode->i_sb,
 			udf_get_lb_pblock(inode->i_sb, bloc, 0),
@@ -1590,6 +1643,8 @@
 		udf_update_tag((*bh)->b_data,
 			le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc));
 	}
+	else
+		mark_inode_dirty(inode);
 
 	mark_buffer_dirty(*bh, 1);
 
@@ -1681,10 +1736,11 @@
 		}
 		case ICB_FLAG_AD_IN_ICB:
 		{
-			*bloc = *eloc = UDF_I_LOCATION(inode);
-			*elen = UDF_I_LENALLOC(inode);
-			*extoffset = udf_file_entry_alloc_offset(inode);
+			if (UDF_I_LENALLOC(inode) == 0)
+				return -1;
 			etype = EXTENT_RECORDED_ALLOCATED;
+			*eloc = UDF_I_LOCATION(inode);
+			*elen = UDF_I_LENALLOC(inode);
 			break;
 		}
 		default:
@@ -1696,8 +1752,8 @@
 	if (*elen)
 		return etype;
 
-	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);
+	udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
+		inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *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)
@@ -1917,7 +1973,7 @@
 int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
 	lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh)
 {
-	int etype, lbcount = 0, b_off;
+	int etype, lbcount = 0;
 
 	if (block < 0)
 	{
@@ -1930,23 +1986,23 @@
 		return -1;
 	}
 
-	*extoffset = udf_file_entry_alloc_offset(inode);
+	*extoffset = 0;
 	*elen = 0;
-	b_off = block << inode->i_sb->s_blocksize_bits;
 	*bloc = UDF_I_LOCATION(inode);
 
 	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;
+			*offset = block - lbcount;
 			return -1;
 		}
-	} while (lbcount + *elen <= b_off);
+		lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >>
+			inode->i_sb->s_blocksize_bits);
+	} while (lbcount <= block);
 
-	*offset = (b_off - lbcount) >> inode->i_sb->s_blocksize_bits;
+	*offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >>
+		inode->i_sb->s_blocksize_bits) - lbcount;
 
 	return etype;
 }
@@ -1966,7 +2022,7 @@
 	if (bh)
 		udf_release_data(bh);
 
-    if (UDF_SB(inode->i_sb)->s_flags & UDF_FLAG_VARCONV)
+	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
 		return udf_fixed_to_variable(ret);
 	else
 		return ret;

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