?? inode.c
字號:
{ udf_release_data(pbh); *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, split the extent into at most three extents. blocks prior to requested block, requested block, and blocks after requested block */ udf_split_extents(inode, &c, offset, newblocknum, laarr, &endnum);#ifdef UDF_PREALLOCATE /* preallocate blocks */ udf_prealloc_extents(inode, c, lastblock, laarr, &endnum);#endif /* merge any continuous blocks in laarr */ udf_merge_extents(inode, laarr, &endnum); /* write back the new extents, inserting new extents if the new number of extents is greater than the old number, and deleting extents if the new number of extents is less than the old number */ udf_update_extents(inode, laarr, startnum, endnum, pbloc, pextoffset, &pbh); udf_release_data(pbh); if (!(newblock = udf_get_pblock(inode->i_sb, newblocknum, UDF_I_LOCATION(inode).partitionReferenceNum, 0))) { return NULL; } *phys = newblock; *err = 0; *new = 1; UDF_I_NEXT_ALLOC_BLOCK(inode) = block; UDF_I_NEXT_ALLOC_GOAL(inode) = newblocknum; inode->i_ctime = CURRENT_TIME; UDF_I_UCTIME(inode) = CURRENT_UTIME; if (IS_SYNC(inode)) udf_sync_inode(inode); else mark_inode_dirty(inode); return result;}static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum, long_ad laarr[EXTENT_MERGE_SIZE], int *endnum){ if ((laarr[*c].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED || (laarr[*c].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) { int curr = *c; int blen = ((laarr[curr].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits; int type = laarr[curr].extLength & ~UDF_EXTENT_LENGTH_MASK; if (blen == 1) ; else if (!offset || blen == offset + 1) { laarr[curr+2] = laarr[curr+1]; laarr[curr+1] = laarr[curr]; } else { laarr[curr+3] = laarr[curr+1]; laarr[curr+2] = laarr[curr+1] = laarr[curr]; } if (offset) { if ((type >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) { udf_free_blocks(inode->i_sb, inode, laarr[curr].extLocation, 0, offset); laarr[curr].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (offset << inode->i_sb->s_blocksize_bits); laarr[curr].extLocation.logicalBlockNum = 0; laarr[curr].extLocation.partitionReferenceNum = 0; } else laarr[curr].extLength = type | (offset << inode->i_sb->s_blocksize_bits); curr ++; (*c) ++; (*endnum) ++; } laarr[curr].extLocation.logicalBlockNum = newblocknum; if ((type >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) laarr[curr].extLocation.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; laarr[curr].extLength = (EXTENT_RECORDED_ALLOCATED << 30) | inode->i_sb->s_blocksize; curr ++; if (blen != offset + 1) { if ((type >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) laarr[curr].extLocation.logicalBlockNum += (offset + 1); laarr[curr].extLength = type | ((blen - (offset + 1)) << inode->i_sb->s_blocksize_bits); curr ++; (*endnum) ++; } }}static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, long_ad laarr[EXTENT_MERGE_SIZE], int *endnum){ int start, length = 0, currlength = 0, i; if (*endnum >= (c+1)) { if (!lastblock) return; else start = c; } else { 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++) { if (i == *endnum) { if (lastblock) length += UDF_DEFAULT_PREALLOC_BLOCKS; } else if ((laarr[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) length += (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits); else break; } if (length) { 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_prealloc_blocks(inode->i_sb, inode, laarr[start].extLocation.partitionReferenceNum, next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? length : UDF_DEFAULT_PREALLOC_BLOCKS) - currlength); 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); else { memmove(&laarr[c+2], &laarr[c+1], sizeof(long_ad) * (*endnum - (c+1))); (*endnum) ++; laarr[c+1].extLocation.logicalBlockNum = next; laarr[c+1].extLocation.partitionReferenceNum = laarr[c].extLocation.partitionReferenceNum; laarr[c+1].extLength = (EXTENT_NOT_RECORDED_ALLOCATED << 30) | (numalloc << inode->i_sb->s_blocksize_bits); start = c+1; } for (i=start+1; numalloc && i<*endnum; i++) { int elen = ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits; if (elen > numalloc) { laarr[c+1].extLength -= (numalloc << inode->i_sb->s_blocksize_bits); numalloc = 0; } else { numalloc -= elen; if (*endnum > (i+1)) memmove(&laarr[i], &laarr[i+1], sizeof(long_ad) * (*endnum - (i+1))); i --; (*endnum) --; } } } }}static void udf_merge_extents(struct inode *inode, long_ad laarr[EXTENT_MERGE_SIZE], int *endnum){ int i; for (i=0; i<(*endnum-1); i++) { if ((laarr[i].extLength >> 30) == (laarr[i+1].extLength >> 30)) { if (((laarr[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) || ((laarr[i+1].extLocation.logicalBlockNum - laarr[i].extLocation.logicalBlockNum) == (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits))) { if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + (laarr[i+1].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK) { laarr[i+1].extLength = (laarr[i+1].extLength - (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1); laarr[i].extLength = (UDF_EXTENT_LENGTH_MASK + 1) - inode->i_sb->s_blocksize; laarr[i+1].extLocation.logicalBlockNum = laarr[i].extLocation.logicalBlockNum + ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >> inode->i_sb->s_blocksize_bits); } else { laarr[i].extLength = laarr[i+1].extLength + (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1)); if (*endnum > (i+2)) memmove(&laarr[i+1], &laarr[i+2], sizeof(long_ad) * (*endnum - (i+2))); i --; (*endnum) --; } } } }}static void udf_update_extents(struct inode *inode, long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum, lb_addr pbloc, Uint32 pextoffset, struct buffer_head **pbh){ int start = 0, i; lb_addr tmploc; Uint32 tmplen; if (startnum > endnum) { for (i=0; i<(startnum-endnum); i++) { udf_delete_aext(inode, pbloc, pextoffset, laarr[i].extLocation, laarr[i].extLength, *pbh); } } else if (startnum < endnum) { for (i=0; i<(endnum-startnum); i++) { udf_insert_aext(inode, pbloc, pextoffset, laarr[i].extLocation, laarr[i].extLength, *pbh); udf_next_aext(inode, &pbloc, &pextoffset, &laarr[i].extLocation, &laarr[i].extLength, pbh, 1); start ++; } } for (i=start; i<endnum; i++) { udf_next_aext(inode, &pbloc, &pextoffset, &tmploc, &tmplen, pbh, 0); udf_write_aext(inode, pbloc, &pextoffset, laarr[i].extLocation, laarr[i].extLength, *pbh, 1); }}struct buffer_head * udf_bread(struct inode * inode, int block, int create, int * err){ struct buffer_head * bh = NULL; bh = udf_getblk(inode, block, create, err); if (!bh) return NULL; if (buffer_uptodate(bh)) return bh; ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) return bh; brelse(bh); *err = -EIO; 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)))) { 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 * * PURPOSE * Read an inode. * * DESCRIPTION * This routine is called by iget() [which is called by udf_iget()] * (clean_inode() will have been called first) * when an inode is first read into memory. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. * * 12/19/98 dgb Updated to fix size problems. */voidudf_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; /* * Set defaults, but the inode is still incomplete! * Note: get_new_inode() sets the following on a new inode: * i_sb = sb * i_dev = sb->s_dev; * i_no = ino * i_flags = sb->s_flags * i_state = 0 * clean_inode(): zero fills and sets * i_count = 1 * i_nlink = 1 * i_op = NULL; */ inode->i_blksize = PAGE_SIZE; bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident); if (!bh) { printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n", inode->i_ino); make_bad_inode(inode); return; } 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); udf_release_data(bh); make_bad_inode(inode); return; } fe = (struct FileEntry *)bh->b_data; if (le16_to_cpu(fe->icbTag.strategyType) == 4096) { struct buffer_head *ibh = NULL, *nbh = NULL; struct IndirectEntry *ie; ibh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1, &ident); if (ident == TID_INDIRECT_ENTRY) { if (ibh) { lb_addr loc; ie = (struct IndirectEntry *)ibh->b_data; loc = lelb_to_cpu(ie->indirectICB.extLocation); if (ie->indirectICB.extLength && (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident))) { if (ident == TID_FILE_ENTRY || ident == TID_EXTENDED_FILE_ENTRY) { 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); return; } else { udf_release_data(nbh); udf_release_data(ibh); } } else udf_release_data(ibh); } } else udf_release_data(ibh); } else if (le16_to_cpu(fe->icbTag.strategyType) != 4) { printk(KERN_ERR "udf: unsupported strategy type: %d\n", le16_to_cpu(fe->icbTag.strategyType)); udf_release_data(bh); make_bad_inode(inode); return; } udf_fill_inode(inode, bh); udf_release_data(bh);}static void udf_fill_inode(struct inode *inode, struct buffer_head *bh){ struct FileEntry *fe; struct ExtendedFileEntry *efe; time_t convtime; 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; 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; 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) 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; UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; UDF_I_NEXT_ALLOC_GOAL(inode) = 0; 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; } else { inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -