patch-2.4.6 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
- Lines: 1085
- Date:
Mon Jul 2 14:10:02 2001
- Orig file:
v2.4.5/linux/fs/udf/inode.c
- Orig date:
Sun Jan 28 13:28:09 2001
diff -u --recursive --new-file v2.4.5/linux/fs/udf/inode.c linux/fs/udf/inode.c
@@ -7,7 +7,7 @@
* CONTACTS
* E-mail regarding any portion of the Linux UDF file system should be
* directed to the development team mailing list (run by majordomo):
- * linux_udf@hootie.lvld.hp.com
+ * linux_udf@hpesjro.fc.hp.com
*
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
@@ -106,23 +106,27 @@
lock_kernel();
if (is_bad_inode(inode))
- {
- clear_inode(inode);
- goto out;
- }
+ goto no_delete;
inode->i_size = 0;
udf_truncate(inode);
udf_update_inode(inode, IS_SYNC(inode));
udf_free_inode(inode);
-out:
+
unlock_kernel();
+ return;
+no_delete:
+ unlock_kernel();
+ clear_inode(inode);
}
void udf_discard_prealloc(struct inode * inode)
{
- if (inode->i_size && UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
- udf_trunc(inode);
+ if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
+ UDF_I_ALLOCTYPE(inode) != ICB_FLAG_AD_IN_ICB)
+ {
+ udf_truncate_extents(inode);
+ }
}
static int udf_writepage(struct page *page)
@@ -146,18 +150,19 @@
}
struct address_space_operations udf_aops = {
- readpage: udf_readpage,
- writepage: udf_writepage,
+ readpage: udf_readpage,
+ writepage: udf_writepage,
sync_page: block_sync_page,
prepare_write: udf_prepare_write,
commit_write: generic_commit_write,
- bmap: udf_bmap,
+ bmap: udf_bmap,
};
void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
{
struct buffer_head *bh = NULL;
struct page *page;
+ char *kaddr;
int block;
/* from now on we have normal address_space methods */
@@ -182,7 +187,7 @@
PAGE_BUG(page);
if (!Page_Uptodate(page))
{
- char *kaddr = kmap(page);
+ kaddr = kmap(page);
memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
@@ -198,8 +203,7 @@
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);
+ mark_buffer_dirty_inode(bh, inode);
udf_release_data(bh);
inode->i_data.a_ops->writepage(page);
@@ -245,9 +249,14 @@
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);
+ dbh = udf_tgetblk(inode->i_sb, newblock, inode->i_sb->s_blocksize);
if (!dbh)
return NULL;
+ lock_buffer(dbh);
+ memset(dbh->b_data, 0x00, inode->i_sb->s_blocksize);
+ mark_buffer_uptodate(dbh, 1);
+ unlock_buffer(dbh);
+ mark_buffer_dirty_inode(dbh, inode);
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
sfibh.sbh = sfibh.ebh = sbh;
@@ -266,7 +275,7 @@
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,
+ if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
sfi->fileIdent + sfi->lengthOfImpUse))
{
udf_release_data(sbh);
@@ -274,7 +283,7 @@
return NULL;
}
}
- mark_buffer_dirty(dbh);
+ mark_buffer_dirty_inode(dbh, inode);
memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
0, UDF_I_LENALLOC(inode));
@@ -288,6 +297,7 @@
eloc.logicalBlockNum = *block;
eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
elen = inode->i_size;
+ UDF_I_LENEXTENTS(inode) = elen;
extoffset = udf_file_entry_alloc_offset(inode);
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
/* UniqueID stuff */
@@ -361,23 +371,21 @@
int create, int * err)
{
struct buffer_head dummy;
- int error;
dummy.b_state = 0;
dummy.b_blocknr = -1000;
- error = udf_get_block(inode, block, &dummy, create);
- *err = error;
- if (!error & buffer_mapped(&dummy))
+ *err = udf_get_block(inode, block, &dummy, create);
+ if (!*err && buffer_mapped(&dummy))
{
struct buffer_head *bh;
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);
+ lock_buffer(bh);
memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
- mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ mark_buffer_dirty_inode(bh, inode);
}
return bh;
}
@@ -387,22 +395,22 @@
static struct buffer_head * inode_getblk(struct inode * inode, long block,
int *err, long *phys, int *new)
{
- struct buffer_head *pbh = NULL, *cbh = NULL, *result = NULL;
+ struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
long_ad laarr[EXTENT_MERGE_SIZE];
Uint32 pextoffset = 0, cextoffset = 0, nextoffset = 0;
int count = 0, startnum = 0, endnum = 0;
Uint32 elen = 0;
- lb_addr eloc, pbloc = UDF_I_LOCATION(inode), cbloc = UDF_I_LOCATION(inode);
+ lb_addr eloc, pbloc, cbloc, nbloc;
int c = 1;
int lbcount = 0, b_off = 0, offset = 0;
Uint32 newblocknum, newblock;
- int etype;
+ char etype;
int goal = 0, pgoal = UDF_I_LOCATION(inode).logicalBlockNum;
char lastblock = 0;
pextoffset = cextoffset = nextoffset = udf_file_entry_alloc_offset(inode);
b_off = block << inode->i_sb->s_blocksize_bits;
- pbloc = cbloc = UDF_I_LOCATION(inode);
+ pbloc = cbloc = nbloc = UDF_I_LOCATION(inode);
/* find the extent which contains the block we are looking for.
alternate between laarr[0] and laarr[1] for locations of the
@@ -412,17 +420,25 @@
if (pbh != cbh)
{
udf_release_data(pbh);
- pbh = cbh;
atomic_inc(&cbh->b_count);
- pbloc = cbloc;
+ pbh = cbh;
+ }
+ if (cbh != nbh)
+ {
+ udf_release_data(cbh);
+ atomic_inc(&nbh->b_count);
+ cbh = nbh;
}
lbcount += elen;
+ pbloc = cbloc;
+ cbloc = nbloc;
+
pextoffset = cextoffset;
cextoffset = nextoffset;
- if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1)
+ if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) == -1)
break;
c = !c;
@@ -433,7 +449,7 @@
if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
pgoal = eloc.logicalBlockNum +
((elen + inode->i_sb->s_blocksize - 1) >>
- inode->i_sb->s_blocksize);
+ inode->i_sb->s_blocksize_bits);
count ++;
} while (lbcount + elen <= b_off);
@@ -451,10 +467,11 @@
elen = (EXTENT_RECORDED_ALLOCATED << 30) |
((elen + inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
- etype = udf_write_aext(inode, cbloc, &cextoffset, eloc, elen, &cbh, 1);
+ etype = udf_write_aext(inode, nbloc, &cextoffset, eloc, elen, nbh, 1);
}
udf_release_data(pbh);
udf_release_data(cbh);
+ udf_release_data(nbh);
newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset);
*phys = newblock;
return NULL;
@@ -470,6 +487,9 @@
(((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) &
~(inode->i_sb->s_blocksize - 1));
+ UDF_I_LENEXTENTS(inode) =
+ (UDF_I_LENEXTENTS(inode) + inode->i_sb->s_blocksize - 1) &
+ ~(inode->i_sb->s_blocksize - 1);
}
c = !c;
laarr[c].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
@@ -494,7 +514,7 @@
/* if the current block is located in a extent, read the next extent */
if (etype != -1)
{
- if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 0)) != -1)
+ if ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 0)) != -1)
{
laarr[c+1].extLength = (etype << 30) | elen;
laarr[c+1].extLocation = eloc;
@@ -505,7 +525,11 @@
else
lastblock = 1;
}
- udf_release_data(cbh);
+ udf_release_data(nbh);
+ if (!pbh)
+ pbh = cbh;
+ else
+ udf_release_data(cbh);
/* if the current extent is not recorded but allocated, get the
block in the extent corresponding to the requested block */
@@ -529,6 +553,7 @@
*err = -ENOSPC;
return NULL;
}
+ UDF_I_LENEXTENTS(inode) += inode->i_sb->s_blocksize;
}
/* if the extent the requsted block is located in contains multiple blocks,
@@ -629,17 +654,24 @@
{
int start, length = 0, currlength = 0, i;
- if (*endnum >= (c+1) && !lastblock)
- return;
-
- if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
+ if (*endnum >= (c+1))
{
- start = c+1;
- length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) +
- inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
+ if (!lastblock)
+ return;
+ else
+ start = c;
}
else
- start = c;
+ {
+ if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
+ {
+ start = c+1;
+ length = currlength = (((laarr[c+1].extLength & UDF_EXTENT_LENGTH_MASK) +
+ inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
+ }
+ else
+ start = c;
+ }
for (i=start+1; i<=*endnum; i++)
{
@@ -667,6 +699,7 @@
if (numalloc)
{
+ UDF_I_LENEXTENTS(inode) += numalloc << inode->i_sb->s_blocksize_bits;
if (start == (c+1))
laarr[start].extLength +=
(numalloc << inode->i_sb->s_blocksize_bits);
@@ -784,7 +817,7 @@
{
udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0);
udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation,
- laarr[i].extLength, pbh, 1);
+ laarr[i].extLength, *pbh, 1);
}
}
@@ -800,29 +833,6 @@
if (!bh)
return NULL;
-#if 0
- if (create &&
- S_ISDIR(inode->i_mode) &&
- inode->i_blocks > prev_blocks)
- {
- int i;
- struct buffer_head *tmp_bh = NULL;
-
- for (i=1;
- i < UDF_DEFAULT_PREALLOC_DIR_BLOCKS;
- i++)
- {
- tmp_bh = udf_getblk(inode, block+i, create, err);
- if (!tmp_bh)
- {
- udf_release_data(bh);
- return 0;
- }
- udf_release_data(tmp_bh);
- }
- }
-#endif
-
if (buffer_uptodate(bh))
return bh;
ll_rw_block(READ, 1, &bh);
@@ -834,6 +844,62 @@
return NULL;
}
+void udf_truncate(struct inode * inode)
+{
+ int offset;
+ struct buffer_head *bh;
+ int err;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode)))
+ return;
+ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+ return;
+
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ {
+ if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
+ inode->i_size))
+ {
+ udf_expand_file_adinicb(inode, inode->i_size, &err);
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ {
+ inode->i_size = UDF_I_LENALLOC(inode);
+ return;
+ }
+ else
+ udf_truncate_extents(inode);
+ }
+ else
+ {
+ offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
+ udf_file_entry_alloc_offset(inode);
+
+ if ((bh = udf_tread(inode->i_sb,
+ udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0),
+ inode->i_sb->s_blocksize)))
+ {
+ memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
+ mark_buffer_dirty(bh);
+ udf_release_data(bh);
+ }
+ UDF_I_LENALLOC(inode) = inode->i_size;
+ }
+ }
+ else
+ {
+ block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block);
+ udf_truncate_extents(inode);
+ }
+
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME;
+ if (IS_SYNC(inode))
+ udf_sync_inode (inode);
+ else
+ mark_inode_dirty(inode);
+}
+
/*
* udf_read_inode
*
@@ -891,7 +957,8 @@
return;
}
- if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY)
+ if (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY &&
+ ident != TID_UNALLOCATED_SPACE_ENTRY)
{
printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n",
inode->i_ino, ident);
@@ -969,16 +1036,24 @@
fe = (struct FileEntry *)bh->b_data;
efe = (struct ExtendedFileEntry *)bh->b_data;
- if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY)
- UDF_I_EXTENDED_FE(inode) = 1;
- else /* fe->descTag.tagIdent == TID_FILE_ENTRY */
- UDF_I_EXTENDED_FE(inode) = 0;
-
if (le16_to_cpu(fe->icbTag.strategyType) == 4)
UDF_I_STRAT4096(inode) = 0;
else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */
UDF_I_STRAT4096(inode) = 1;
+ UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK;
+ if (fe->descTag.tagIdent == TID_EXTENDED_FILE_ENTRY)
+ UDF_I_EXTENDED_FE(inode) = 1;
+ else if (fe->descTag.tagIdent == TID_FILE_ENTRY)
+ UDF_I_EXTENDED_FE(inode) = 0;
+ else if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
+ {
+ UDF_I_LENALLOC(inode) =
+ le32_to_cpu(
+ ((struct UnallocatedSpaceEntry *)bh->b_data)->lengthAllocDescs);
+ return;
+ }
+
inode->i_uid = le32_to_cpu(fe->uid);
if ( inode->i_uid == -1 ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid;
@@ -990,6 +1065,7 @@
inode->i_nlink = 1;
inode->i_size = le64_to_cpu(fe->informationLength);
+ UDF_I_LENEXTENTS(inode) = inode->i_size;
inode->i_mode = udf_convert_permissions(fe);
inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
@@ -997,39 +1073,43 @@
UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
- UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICB_FLAG_ALLOC_MASK;
-
if (UDF_I_EXTENDED_FE(inode) == 0)
{
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
if ( udf_stamp_to_time(&convtime, &convtime_usec,
+ lets_to_cpu(fe->accessTime)) )
+ {
+ inode->i_atime = convtime;
+ }
+ else
+ {
+ inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+ }
+
+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(fe->modificationTime)) )
{
inode->i_mtime = convtime;
UDF_I_UMTIME(inode) = convtime_usec;
- inode->i_ctime = convtime;
- UDF_I_UCTIME(inode) = convtime_usec;
}
else
{
inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UMTIME(inode) = 0;
- inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
- UDF_I_UCTIME(inode) = 0;
}
if ( udf_stamp_to_time(&convtime, &convtime_usec,
- lets_to_cpu(fe->accessTime)) )
+ lets_to_cpu(fe->attrTime)) )
{
- inode->i_atime = convtime;
- UDF_I_UATIME(inode) = convtime_usec;
+ inode->i_ctime = convtime;
+ UDF_I_UCTIME(inode) = convtime_usec;
}
else
{
- inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
- UDF_I_UATIME(inode) = convtime_usec;
+ inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
+ UDF_I_UCTIME(inode) = 0;
}
UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
@@ -1044,6 +1124,16 @@
(inode->i_sb->s_blocksize_bits - 9);
if ( udf_stamp_to_time(&convtime, &convtime_usec,
+ lets_to_cpu(efe->accessTime)) )
+ {
+ inode->i_atime = convtime;
+ }
+ else
+ {
+ inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
+ }
+
+ if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(efe->modificationTime)) )
{
inode->i_mtime = convtime;
@@ -1056,19 +1146,19 @@
}
if ( udf_stamp_to_time(&convtime, &convtime_usec,
- lets_to_cpu(efe->accessTime)) )
+ lets_to_cpu(efe->createTime)) )
{
- inode->i_atime = convtime;
- UDF_I_UATIME(inode) = convtime_usec;
+ UDF_I_CRTIME(inode) = convtime;
+ UDF_I_UCRTIME(inode) = convtime_usec;
}
else
{
- inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
- UDF_I_UATIME(inode) = 0;
+ UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb);
+ UDF_I_UCRTIME(inode) = 0;
}
if ( udf_stamp_to_time(&convtime, &convtime_usec,
- lets_to_cpu(efe->createTime)) )
+ lets_to_cpu(efe->attrTime)) )
{
inode->i_ctime = convtime;
UDF_I_UCTIME(inode) = convtime_usec;
@@ -1096,6 +1186,7 @@
inode->i_nlink ++;
break;
}
+ case FILE_TYPE_REALTIME:
case FILE_TYPE_REGULAR:
case FILE_TYPE_NONE:
{
@@ -1171,11 +1262,11 @@
flags = le16_to_cpu(fe->icbTag.flags);
mode = (( permissions ) & S_IRWXO) |
- (( permissions >> 2 ) & S_IRWXG) |
- (( permissions >> 4 ) & S_IRWXU) |
- (( flags & ICB_FLAG_SETUID) ? S_ISUID : 0) |
- (( flags & ICB_FLAG_SETGID) ? S_ISGID : 0) |
- (( flags & ICB_FLAG_STICKY) ? S_ISVTX : 0);
+ (( permissions >> 2 ) & S_IRWXG) |
+ (( permissions >> 4 ) & S_IRWXU) |
+ (( flags & ICB_FLAG_SETUID) ? S_ISUID : 0) |
+ (( flags & ICB_FLAG_SETGID) ? S_ISGID : 0) |
+ (( flags & ICB_FLAG_STICKY) ? S_ISVTX : 0);
return mode;
}
@@ -1221,8 +1312,9 @@
int err = 0;
bh = udf_tread(inode->i_sb,
- udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0),
- inode->i_sb->s_blocksize);
+ udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0),
+ inode->i_sb->s_blocksize);
+
if (!bh)
{
udf_debug("bread failure\n");
@@ -1233,7 +1325,7 @@
if (UDF_I_NEW_INODE(inode) == 1)
{
if (UDF_I_EXTENDED_FE(inode) == 0)
- memset(bh->b_data, 0x0, sizeof(struct FileEntry));
+ memset(bh->b_data, 0x00, sizeof(struct FileEntry));
else
memset(bh->b_data, 0x00, sizeof(struct ExtendedFileEntry));
memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
@@ -1242,20 +1334,41 @@
UDF_I_NEW_INODE(inode) = 0;
}
+ if (fe->descTag.tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
+ {
+ struct UnallocatedSpaceEntry *use =
+ (struct UnallocatedSpaceEntry *)bh->b_data;
+
+ use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
+ crclen = sizeof(struct UnallocatedSpaceEntry) + UDF_I_LENALLOC(inode) -
+ sizeof(tag);
+ use->descTag.descCRCLength = cpu_to_le16(crclen);
+ use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0));
+
+ use->descTag.tagChecksum = 0;
+ for (i=0; i<16; i++)
+ if (i != 4)
+ use->descTag.tagChecksum += ((Uint8 *)&(use->descTag))[i];
+
+ mark_buffer_dirty(bh);
+ udf_release_data(bh);
+ return err;
+ }
+
if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
fe->uid = cpu_to_le32(inode->i_uid);
if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid)
fe->gid = cpu_to_le32(inode->i_gid);
- udfperms = ((inode->i_mode & S_IRWXO) ) |
- ((inode->i_mode & S_IRWXG) << 2) |
- ((inode->i_mode & S_IRWXU) << 4);
-
- udfperms |= (le32_to_cpu(fe->permissions) &
- (PERM_O_DELETE | PERM_O_CHATTR |
- PERM_G_DELETE | PERM_G_CHATTR |
- PERM_U_DELETE | PERM_U_CHATTR));
+ udfperms = ((inode->i_mode & S_IRWXO) ) |
+ ((inode->i_mode & S_IRWXG) << 2) |
+ ((inode->i_mode & S_IRWXU) << 4);
+
+ udfperms |= (le32_to_cpu(fe->permissions) &
+ (PERM_O_DELETE | PERM_O_CHATTR |
+ PERM_G_DELETE | PERM_G_CHATTR |
+ PERM_U_DELETE | PERM_U_CHATTR));
fe->permissions = cpu_to_le32(udfperms);
if (S_ISDIR(inode->i_mode))
@@ -1292,7 +1405,7 @@
eid->identSuffix[1] = UDF_OS_ID_LINUX;
dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8;
dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF;
- mark_buffer_dirty(tbh);
+ mark_buffer_dirty_inode(tbh, inode);
udf_release_data(tbh);
}
@@ -1302,10 +1415,12 @@
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
(inode->i_sb->s_blocksize_bits - 9));
- if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode)))
+ if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0))
fe->accessTime = cpu_to_lets(cpu_time);
if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
fe->modificationTime = cpu_to_lets(cpu_time);
+ if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
+ fe->attrTime = cpu_to_lets(cpu_time);
memset(&(fe->impIdent), 0, sizeof(EntityID));
strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
@@ -1318,16 +1433,40 @@
}
else
{
+ efe->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64(
- (inode->i_blocks + (2 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
+ (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
(inode->i_sb->s_blocksize_bits - 9));
- if (udf_time_to_stamp(&cpu_time, inode->i_atime, UDF_I_UATIME(inode)))
+ if (UDF_I_CRTIME(inode) >= inode->i_atime)
+ {
+ UDF_I_CRTIME(inode) = inode->i_atime;
+ UDF_I_UCRTIME(inode) = 0;
+ }
+ if (UDF_I_CRTIME(inode) > inode->i_mtime ||
+ (UDF_I_CRTIME(inode) == inode->i_mtime &&
+ UDF_I_UCRTIME(inode) > UDF_I_UMTIME(inode)))
+ {
+ UDF_I_CRTIME(inode) = inode->i_mtime;
+ UDF_I_UCRTIME(inode) = UDF_I_UMTIME(inode);
+ }
+ if (UDF_I_CRTIME(inode) > inode->i_ctime ||
+ (UDF_I_CRTIME(inode) == inode->i_ctime &&
+ UDF_I_UCRTIME(inode) > UDF_I_UCTIME(inode)))
+ {
+ UDF_I_CRTIME(inode) = inode->i_ctime;
+ UDF_I_UCRTIME(inode) = UDF_I_UCTIME(inode);
+ }
+
+ if (udf_time_to_stamp(&cpu_time, inode->i_atime, 0))
efe->accessTime = cpu_to_lets(cpu_time);
if (udf_time_to_stamp(&cpu_time, inode->i_mtime, UDF_I_UMTIME(inode)))
efe->modificationTime = cpu_to_lets(cpu_time);
- if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
+ if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode), UDF_I_UCRTIME(inode)))
efe->createTime = cpu_to_lets(cpu_time);
+ if (udf_time_to_stamp(&cpu_time, inode->i_ctime, UDF_I_UCTIME(inode)))
+ efe->attrTime = cpu_to_lets(cpu_time);
+
memset(&(efe->impIdent), 0, sizeof(EntityID));
strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
@@ -1363,7 +1502,7 @@
else if (S_ISFIFO(inode->i_mode))
fe->icbTag.fileType = FILE_TYPE_FIFO;
- icbflags = UDF_I_ALLOCTYPE(inode) |
+ icbflags = UDF_I_ALLOCTYPE(inode) |
((inode->i_mode & S_ISUID) ? ICB_FLAG_SETUID : 0) |
((inode->i_mode & S_ISGID) ? ICB_FLAG_SETGID : 0) |
((inode->i_mode & S_ISVTX) ? ICB_FLAG_STICKY : 0) |
@@ -1444,12 +1583,19 @@
{
memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
__udf_read_inode(inode);
+ if (is_bad_inode(inode))
+ {
+ iput(inode);
+ return NULL;
+ }
}
if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) )
{
udf_debug("block=%d, partition=%d out of range\n",
ino.logicalBlockNum, ino.partitionReferenceNum);
+ make_bad_inode(inode);
+ iput(inode);
return NULL;
}
@@ -1496,13 +1642,20 @@
{
return -1;
}
- if (!(nbh = udf_tread(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), inode->i_sb->s_blocksize)))
{
return -1;
}
+ lock_buffer(nbh);
+ memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);
+ mark_buffer_uptodate(nbh, 1);
+ unlock_buffer(nbh);
+ mark_buffer_dirty_inode(nbh, inode);
+
aed = (struct AllocExtDesc *)(nbh->b_data);
- aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
+ if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
+ aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
if (*extoffset + adsize > inode->i_sb->s_blocksize)
{
loffset = *extoffset;
@@ -1551,16 +1704,20 @@
EXTENT_NEXT_EXTENT_ALLOCDECS << 30 |
inode->i_sb->s_blocksize);
lad->extLocation = cpu_to_lelb(*bloc);
+ memset(lad->impUse, 0x00, sizeof(lad->impUse));
break;
}
}
- udf_update_tag((*bh)->b_data, loffset);
- mark_buffer_dirty(*bh);
+ if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
+ udf_update_tag((*bh)->b_data, loffset);
+ else
+ udf_update_tag((*bh)->b_data, sizeof(struct AllocExtDesc));
+ mark_buffer_dirty_inode(*bh, inode);
udf_release_data(*bh);
*bh = nbh;
}
- ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, bh, inc);
+ ret = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
{
@@ -1572,23 +1729,26 @@
aed = (struct AllocExtDesc *)(*bh)->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
- udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize));
- mark_buffer_dirty(*bh);
+ 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));
+ else
+ udf_update_tag((*bh)->b_data, sizeof(struct AllocExtDesc));
+ mark_buffer_dirty_inode(*bh, inode);
}
return ret;
}
int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
- lb_addr eloc, Uint32 elen, struct buffer_head **bh, int inc)
+ lb_addr eloc, Uint32 elen, struct buffer_head *bh, int inc)
{
int adsize;
short_ad *sad = NULL;
long_ad *lad = NULL;
- if (!(*bh))
+ if (!(bh))
{
- if (!(*bh = udf_tread(inode->i_sb,
+ if (!(bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, bloc, 0),
inode->i_sb->s_blocksize)))
{
@@ -1597,6 +1757,8 @@
return -1;
}
}
+ else
+ atomic_inc(&bh->b_count);
if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
@@ -1609,39 +1771,47 @@
{
case ICB_FLAG_AD_SHORT:
{
- sad = (short_ad *)((*bh)->b_data + *extoffset);
+ sad = (short_ad *)((bh)->b_data + *extoffset);
sad->extLength = cpu_to_le32(elen);
sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
break;
}
case ICB_FLAG_AD_LONG:
{
- lad = (long_ad *)((*bh)->b_data + *extoffset);
+ lad = (long_ad *)((bh)->b_data + *extoffset);
lad->extLength = cpu_to_le32(elen);
lad->extLocation = cpu_to_lelb(eloc);
+ memset(lad->impUse, 0x00, sizeof(lad->impUse));
break;
}
}
if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
{
- struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data;
- udf_update_tag((*bh)->b_data,
- le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc));
+ 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,
+ le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc));
+ }
+ mark_buffer_dirty_inode(bh, inode);
}
else
+ {
mark_inode_dirty(inode);
-
- mark_buffer_dirty(*bh);
+ mark_buffer_dirty(bh);
+ }
if (inc)
*extoffset += adsize;
+ udf_release_data(bh);
return (elen >> 30);
}
int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc)
{
+ Uint16 tagIdent;
int pos, alen;
Uint8 etype;
@@ -1657,18 +1827,33 @@
}
}
+ tagIdent = ((tag *)(*bh)->b_data)->tagIdent;
+
if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
{
- pos = udf_file_entry_alloc_offset(inode);
- alen = UDF_I_LENALLOC(inode) + pos;
+ if (tagIdent == TID_FILE_ENTRY || tagIdent == TID_EXTENDED_FILE_ENTRY ||
+ UDF_I_NEW_INODE(inode))
+ {
+ pos = udf_file_entry_alloc_offset(inode);
+ alen = UDF_I_LENALLOC(inode) + pos;
+ }
+ else if (tagIdent == TID_UNALLOCATED_SPACE_ENTRY)
+ {
+ pos = sizeof(struct UnallocatedSpaceEntry);
+ alen = UDF_I_LENALLOC(inode) + pos;
+ }
+ else
+ return -1;
}
- else
+ else if (tagIdent == TID_ALLOC_EXTENT_DESC)
{
struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data;
pos = sizeof(struct AllocExtDesc);
alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
}
+ else
+ return -1;
if (!(*extoffset))
*extoffset = pos;
@@ -1829,7 +2014,7 @@
}
int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
- lb_addr neloc, Uint32 nelen, struct buffer_head *bh)
+ lb_addr neloc, Uint32 nelen, struct buffer_head *bh)
{
lb_addr oeloc;
Uint32 oelen;
@@ -1851,7 +2036,7 @@
while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
{
- udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1);
+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
neloc = oeloc;
nelen = (type << 30) | oelen;
@@ -1867,7 +2052,7 @@
struct buffer_head *obh;
lb_addr obloc;
int oextoffset, adsize;
- int type;
+ char type;
struct AllocExtDesc *aed;
if (!(nbh))
@@ -1901,7 +2086,7 @@
while ((type = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
{
- udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, &obh, 1);
+ udf_write_aext(inode, obloc, &oextoffset, eloc, (type << 30) | elen, obh, 1);
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
{
obloc = nbloc;
@@ -1917,8 +2102,8 @@
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
{
udf_free_blocks(inode, nbloc, 0, 1);
- udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1);
- udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1);
+ udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
+ udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
{
UDF_I_LENALLOC(inode) -= (adsize * 2);
@@ -1929,13 +2114,16 @@
aed = (struct AllocExtDesc *)(obh)->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));
- udf_update_tag((obh)->b_data, oextoffset - (2*adsize));
- mark_buffer_dirty(obh);
+ 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));
+ else
+ udf_update_tag((obh)->b_data, sizeof(struct AllocExtDesc));
+ mark_buffer_dirty_inode(obh, inode);
}
}
else
{
- udf_write_aext(inode, obloc, &oextoffset, eloc, elen, &obh, 1);
+ udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
{
UDF_I_LENALLOC(inode) -= adsize;
@@ -1946,8 +2134,11 @@
aed = (struct AllocExtDesc *)(obh)->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);
- udf_update_tag((obh)->b_data, oextoffset - adsize);
- mark_buffer_dirty(obh);
+ 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);
+ else
+ udf_update_tag((obh)->b_data, sizeof(struct AllocExtDesc));
+ mark_buffer_dirty_inode(obh, inode);
}
}
@@ -1959,7 +2150,8 @@
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;
+ Uint64 lbcount = 0, bcount = block << inode->i_sb->s_blocksize_bits;
+ char etype;
if (block < 0)
{
@@ -1980,31 +2172,34 @@
{
if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
{
- *offset = block - lbcount;
+ *offset = bcount - lbcount;
+ UDF_I_LENEXTENTS(inode) = lbcount;
return -1;
}
- lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >>
- inode->i_sb->s_blocksize_bits);
- } while (lbcount <= block);
+ lbcount += *elen;
+ } while (lbcount <= bcount);
- *offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >>
- inode->i_sb->s_blocksize_bits) - lbcount;
+ *offset = bcount + *elen - lbcount;
return etype;
}
-long udf_locked_block_map(struct inode *inode, long block)
+long udf_block_map(struct inode *inode, long block)
{
lb_addr eloc, bloc;
Uint32 offset, extoffset, elen;
struct buffer_head *bh = NULL;
int ret;
+ lock_kernel();
+
if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
- ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);
+ ret = udf_get_lb_pblock(inode->i_sb, eloc, offset >> inode->i_sb->s_blocksize_bits);
else
ret = 0;
+ unlock_kernel();
+
if (bh)
udf_release_data(bh);
@@ -2012,14 +2207,4 @@
return udf_fixed_to_variable(ret);
else
return ret;
-}
-
-long udf_block_map(struct inode *inode, long block)
-{
- int ret;
-
- lock_kernel();
- ret = udf_locked_block_map(inode, block);
- unlock_kernel();
- return ret;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)