📄 inode.c
字号:
aed = (struct AllocExtDesc *)(nbh->b_data); 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; aed->lengthAllocDescs = cpu_to_le32(adsize); sptr = (*bh)->b_data + *extoffset - adsize; dptr = nbh->b_data + sizeof(struct AllocExtDesc); memcpy(dptr, sptr, adsize); *extoffset = sizeof(struct AllocExtDesc) + adsize; } else { loffset = *extoffset + adsize; aed->lengthAllocDescs = cpu_to_le32(0); sptr = (*bh)->b_data + *extoffset; *extoffset = sizeof(struct AllocExtDesc); 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)); switch (UDF_I_ALLOCTYPE(inode)) { case ICB_FLAG_AD_SHORT: { sad = (short_ad *)sptr; sad->extLength = cpu_to_le32( EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | inode->i_sb->s_blocksize); sad->extPosition = cpu_to_le32(bloc->logicalBlockNum); break; } case ICB_FLAG_AD_LONG: { lad = (long_ad *)sptr; lad->extLength = cpu_to_le32( EXTENT_NEXT_EXTENT_ALLOCDECS << 30 | inode->i_sb->s_blocksize); lad->extLocation = cpu_to_lelb(*bloc); memset(lad->impUse, 0x00, sizeof(lad->impUse)); break; } } 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); if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { UDF_I_LENALLOC(inode) += adsize; mark_inode_dirty(inode); } else { aed = (struct AllocExtDesc *)(*bh)->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); 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;}Sint8 udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset, 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 = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0)))) { udf_debug("reading block %d failed!\n", udf_get_lb_pblock(inode->i_sb, bloc, 0)); return -1; } } else atomic_inc(&bh->b_count); 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 return -1; switch (UDF_I_ALLOCTYPE(inode)) { case ICB_FLAG_AD_SHORT: { 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->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))) { 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); } if (inc) *extoffset += adsize; udf_release_data(bh); return (elen >> 30);}Sint8 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; Sint8 etype; if (!(*bh)) { if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0)))) { udf_debug("reading block %d failed!\n", udf_get_lb_pblock(inode->i_sb, *bloc, 0)); return -1; } } tagIdent = ((tag *)(*bh)->b_data)->tagIdent; if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { 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 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; switch (UDF_I_ALLOCTYPE(inode)) { case ICB_FLAG_AD_SHORT: { short_ad *sad; if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc))) return -1; if ((etype = le32_to_cpu(sad->extLength) >> 30) == EXTENT_NEXT_EXTENT_ALLOCDECS) { bloc->logicalBlockNum = le32_to_cpu(sad->extPosition); *extoffset = 0; udf_release_data(*bh); *bh = NULL; return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc); } else { eloc->logicalBlockNum = le32_to_cpu(sad->extPosition); eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK; } break; } case ICB_FLAG_AD_LONG: { long_ad *lad; if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc))) return -1; if ((etype = le32_to_cpu(lad->extLength) >> 30) == EXTENT_NEXT_EXTENT_ALLOCDECS) { *bloc = lelb_to_cpu(lad->extLocation); *extoffset = 0; udf_release_data(*bh); *bh = NULL; return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc); } else { *eloc = lelb_to_cpu(lad->extLocation); *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK; } break; } case ICB_FLAG_AD_IN_ICB: { if (UDF_I_LENALLOC(inode) == 0) return -1; etype = EXTENT_RECORDED_ALLOCATED; *eloc = UDF_I_LOCATION(inode); *elen = UDF_I_LENALLOC(inode); break; } default: { udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode)); return -1; } } if (*elen) return etype; 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) *extoffset -= sizeof(long_ad); return -1;}Sint8 udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset, lb_addr *eloc, Uint32 *elen, struct buffer_head **bh, int inc){ int pos, alen; Sint8 etype; if (!(*bh)) { if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0)))) { udf_debug("reading block %d failed!\n", udf_get_lb_pblock(inode->i_sb, *bloc, 0)); return -1; } } if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr))) { if (!(UDF_I_EXTENDED_FE(inode))) pos = sizeof(struct FileEntry) + UDF_I_LENEATTR(inode); else pos = sizeof(struct ExtendedFileEntry) + UDF_I_LENEATTR(inode); alen = UDF_I_LENALLOC(inode) + pos; } else { struct AllocExtDesc *aed = (struct AllocExtDesc *)(*bh)->b_data; pos = sizeof(struct AllocExtDesc); alen = le32_to_cpu(aed->lengthAllocDescs) + pos; } if (!(*extoffset)) *extoffset = pos; switch (UDF_I_ALLOCTYPE(inode)) { case ICB_FLAG_AD_SHORT: { short_ad *sad; if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc))) return -1; etype = le32_to_cpu(sad->extLength) >> 30; eloc->logicalBlockNum = le32_to_cpu(sad->extPosition); eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK; break; } case ICB_FLAG_AD_LONG: { long_ad *lad; if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc))) return -1; etype = le32_to_cpu(lad->extLength) >> 30; *eloc = lelb_to_cpu(lad->extLocation); *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK; break; } default: { udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode)); return -1; } } if (*elen) return etype; udf_debug("Empty Extent!\n"); 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); return -1;}Sint8 udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset, lb_addr neloc, Uint32 nelen, struct buffer_head *bh){ lb_addr oeloc; Uint32 oelen; Sint8 etype; if (!bh) { if (!(bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0)))) { udf_debug("reading block %d failed!\n", udf_get_lb_pblock(inode->i_sb, bloc, 0)); return -1; } } else atomic_inc(&bh->b_count); while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1) { udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); neloc = oeloc; nelen = (etype << 30) | oelen; } udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1); udf_release_data(bh); return (nelen >> 30);}Sint8 udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset, lb_addr eloc, Uint32 elen, struct buffer_head *nbh){ struct buffer_head *obh; lb_addr obloc; int oextoffset, adsize; Sint8 etype; struct AllocExtDesc *aed; if (!(nbh)) { if (!(nbh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, nbloc, 0)))) { udf_debug("reading block %d failed!\n", udf_get_lb_pblock(inode->i_sb, nbloc, 0)); return -1; } } else atomic_inc(&nbh->b_count); atomic_inc(&nbh->b_count); 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 adsize = 0; obh = nbh; obloc = nbloc; oextoffset = nextoffset; if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1) return -1; while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) { udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1); if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) { obloc = nbloc; udf_release_data(obh); atomic_inc(&nbh->b_count); obh = nbh; oextoffset = nextoffset - adsize; } } memset(&eloc, 0x00, sizeof(lb_addr)); elen = 0; if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) { udf_free_blocks(inode->i_sb, inode, nbloc, 0, 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); mark_inode_dirty(inode); } else { aed = (struct AllocExtDesc *)(obh)->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize)); 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); if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr))) { UDF_I_LENALLOC(inode) -= adsize; mark_inode_dirty(inode); } else { aed = (struct AllocExtDesc *)(obh)->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize); 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); } } udf_release_data(nbh); udf_release_data(obh); return (elen >> 30);}Sint8 inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset, lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh){ Uint64 lbcount = 0, bcount = (Uint64)block << inode->i_sb->s_blocksize_bits; Sint8 etype; if (block < 0) { printk(KERN_ERR "udf: inode_bmap: block < 0\n"); return -1; } if (!inode) { printk(KERN_ERR "udf: inode_bmap: NULL inode\n"); return -1; } *extoffset = 0; *elen = 0; *bloc = UDF_I_LOCATION(inode); do { if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1) { *offset = bcount - lbcount; UDF_I_LENEXTENTS(inode) = lbcount; return -1; } lbcount += *elen; } while (lbcount <= bcount); *offset = bcount + *elen - lbcount; return etype;}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 >> inode->i_sb->s_blocksize_bits); else ret = 0; unlock_kernel(); if (bh) udf_release_data(bh); if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV)) return udf_fixed_to_variable(ret); else return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -