diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 00:24:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 00:24:27 +0000 |
commit | b9558d5f86c471a125abf1fb3a3882fb053b1f8c (patch) | |
tree | 707b53ec64e740a7da87d5f36485e3cd9b1c794e /fs/udf/inode.c | |
parent | b3ac367c7a3e6047abe74817db27e34e759f279f (diff) |
Merge with Linux 2.3.41.
Diffstat (limited to 'fs/udf/inode.c')
-rw-r--r-- | fs/udf/inode.c | 467 |
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; +} |