summaryrefslogtreecommitdiffstats
path: root/fs/udf/inode.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-18 00:24:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-18 00:24:27 +0000
commitb9558d5f86c471a125abf1fb3a3882fb053b1f8c (patch)
tree707b53ec64e740a7da87d5f36485e3cd9b1c794e /fs/udf/inode.c
parentb3ac367c7a3e6047abe74817db27e34e759f279f (diff)
Merge with Linux 2.3.41.
Diffstat (limited to 'fs/udf/inode.c')
-rw-r--r--fs/udf/inode.c467
1 files changed, 223 insertions, 244 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index e2e12df8e..2ea1f980b 100644
--- a/fs/udf/inode.c
+++ b/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 @@ static void udf_update_extents(struct inode *,
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 @@ void udf_delete_inode(struct inode * inode)
{
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 @@ static int udf_alloc_block(struct inode *inode, Uint16 partition,
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 @@ struct buffer_head * udf_getblk(struct inode * inode, long block,
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 @@ int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result
}
err = -EIO;
+ new = 0;
+ bh = NULL;
lock_kernel();
@@ -479,7 +468,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
}
/* 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 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
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 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
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 @@ struct buffer_head * udf_bread(struct inode * inode, int block,
*
* 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 @@ udf_read_inode(struct inode *inode)
* 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 @@ udf_read_inode(struct inode *inode)
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 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
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 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
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 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
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 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
}
case FILE_TYPE_SYMLINK:
{
- /* untested! */
inode->i_op = &udf_symlink_inode_operations;
inode->i_mode = S_IFLNK|S_IRWXUGO;
break;
@@ -1184,7 +1105,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
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 @@ udf_iget(struct super_block *sb, lb_addr ino)
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 @@ udf_iget(struct super_block *sb, lb_addr ino)
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 @@ int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
}
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 @@ int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
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 @@ int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
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;
@@ -2029,3 +1953,58 @@ long udf_block_map(struct inode *inode, long 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;
+}