📄 inode.c
字号:
changed: while (partial > chain) { brelse(partial->bh);/*释放各级目录块*/ partial--; } goto reread;}/*同步写页*/static int ext2_writepage(struct page *page){ return block_write_full_page(page,ext2_get_block);/*块设备同步写页*/}/*同步读页*/static int ext2_readpage(struct file *file, struct page *page){ return block_read_full_page(page,ext2_get_block);/*块设备同步读页*/}/*准备写*/static int ext2_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){ return block_prepare_write(page,from,to,ext2_get_block);/*块设备准备写*/}/*块位图*/static int ext2_bmap(struct address_space *mapping, long block){ return generic_block_bmap(mapping,block,ext2_get_block);/*块位图*/}/*直接I/O*/static int ext2_direct_IO(int rw, struct inode * inode, struct kiobuf * iobuf, unsigned long blocknr, int blocksize){ return generic_direct_IO(rw, inode, iobuf, blocknr, blocksize, ext2_get_block);/*直接I/O*/}/*ext2文件系统中具体操作实现函数集*/struct address_space_operations ext2_aops = { readpage: ext2_readpage, writepage: ext2_writepage, sync_page: block_sync_page, prepare_write: ext2_prepare_write, commit_write: generic_commit_write, bmap: ext2_bmap, direct_IO: ext2_direct_IO,};/* * Probably it should be a library function... search for first non-zero word * or memcmp with zero_page, whatever is better for particular architecture. * Linus? */ /*查找第一个非0字或对零页进行比较*/static inline int all_zeroes(u32 *p, u32 *q){ while (p < q) if (*p++) return 0; return 1;}/** * ext2_find_shared - find the indirect blocks for partial truncation. * @inode: inode in question * @depth: depth of the affected branch * @offsets: offsets of pointers in that branch (see ext2_block_to_path) * @chain: place to store the pointers to partial indirect blocks * @top: place to the (detached) top of branch * * This is a helper function used by ext2_truncate(). * * When we do truncate() we may have to clean the ends of several indirect * blocks but leave the blocks themselves alive. Block is partially * truncated if some data below the new i_size is refered from it (and * it is on the path to the first completely truncated data block, indeed). * We have to free the top of that path along with everything to the right * of the path. Since no allocation past the truncation point is possible * until ext2_truncate() finishes, we may safely do the latter, but top * of branch may require special attention - pageout below the truncation * point might try to populate it. * * We atomically detach the top of branch from the tree, store the block * number of its root in *@top, pointers to buffer_heads of partially * truncated blocks - in @chain[].bh and pointers to their last elements * that should not be removed - in @chain[].p. Return value is the pointer * to last filled element of @chain. * * The work left to caller to do the actual freeing of subtrees: * a) free the subtree starting from *@top * b) free the subtrees whose roots are stored in * (@chain[i].p+1 .. end of @chain[i].bh->b_data) * c) free the subtrees growing from the inode past the @chain[0].p * (no partially truncated stuff there). *//*对部分切断寻找间接块*/static Indirect *ext2_find_shared(struct inode *inode, int depth, int offsets[4], Indirect chain[4], u32 *top){ Indirect *partial, *p;/*声明描述索引块中的索引项指针partial,p*/ int k, err; *top = 0; for (k = depth; k > 1 && !offsets[k-1]; k--) ; partial = ext2_get_branch(inode, k, offsets, chain, &err); /* Writer: pointers */ if (!partial) partial = chain + k-1; /* * If the branch acquired continuation since we've looked at it - * fine, it should all survive and (new) top doesn't belong to us. */ if (!partial->key && *partial->p) /* Writer: end */ goto no_top; for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--) ; /* * OK, we've found the last block that must survive. The rest of our * branch should be detached before unlocking. However, if that rest * of branch is all ours and does not grow immediately from the inode * it's easier to cheat and just decrement partial->p. */ if (p == chain + k - 1 && p > chain) { p->p--; } else { *top = *p->p; *p->p = 0; } /* Writer: end */ while(partial > p) { brelse(partial->bh);/*释放块在高速缓存中的缓冲区首部*/ partial--; }no_top: return partial;}/** * ext2_free_data - free a list of data blocks * @inode: inode we are dealing with * @p: array of block numbers * @q: points immediately past the end of array * * We are freeing all blocks refered from that array (numbers are * stored as little-endian 32-bit) and updating @inode->i_blocks * appropriately. */ /*释放一个数据块的链表*/static inline void ext2_free_data(struct inode *inode, u32 *p, u32 *q){ unsigned long block_to_free = 0, count = 0; unsigned long nr; for ( ; p < q ; p++) { nr = le32_to_cpu(*p); if (nr) { *p = 0; /* accumulate blocks to free if they're contiguous */ /*聚集要释放的相邻的块*/ if (count == 0) goto free_this; else if (block_to_free == nr - count) count++; else { mark_inode_dirty(inode);/*标记inode为脏*/ ext2_free_blocks (inode, block_to_free, count);/*释放块*/ free_this: block_to_free = nr; count = 1; } } } if (count > 0) { mark_inode_dirty(inode);/*标记inode为脏*/ ext2_free_blocks (inode, block_to_free, count);/*释放块*/ }}/** * ext2_free_branches - free an array of branches * @inode: inode we are dealing with * @p: array of block numbers * @q: pointer immediately past the end of array * @depth: depth of the branches to free * * We are freeing all blocks refered from these branches (numbers are * stored as little-endian 32-bit) and updating @inode->i_blocks * appropriately. */ /*释放一个块链表数组*/static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth){ struct buffer_head * bh; unsigned long nr; if (depth--) {/*块深度减一后,不为0*/ int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); for ( ; p < q ; p++) { nr = le32_to_cpu(*p); if (!nr) continue; *p = 0; bh = sb_bread(inode->i_sb, nr); /* * A read failure? Report error and clear slot * (should be rare). */ /*读取出错,给出提示*/ if (!bh) { ext2_error(inode->i_sb, "ext2_free_branches", "Read failure, inode=%ld, block=%ld", inode->i_ino, nr); continue; } ext2_free_branches(inode, (u32*)bh->b_data, (u32*)bh->b_data + addr_per_block, depth); /*释放一个块链表数组*/ bforget(bh); ext2_free_blocks(inode, nr, 1);/*释放块*/ mark_inode_dirty(inode);/*标记inode脏*/ } } else ext2_free_data(inode, p, q);}/*截短清空inode*/void ext2_truncate (struct inode * inode){ u32 *i_data = inode->u.ext2_i.i_data; int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb); int offsets[4]; Indirect chain[4]; Indirect *partial; int nr = 0; int n; long iblock; unsigned blocksize; if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))/*inode不是常规文件、目录、符号链接*/ return;/*直接返回*/ if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; ext2_discard_prealloc(inode);/*重新设置设备块组描述子和块组数据块位图*/ blocksize = inode->i_sb->s_blocksize;/*置块大小的值*/ iblock = (inode->i_size + blocksize-1) >> EXT2_BLOCK_SIZE_BITS(inode->i_sb); block_truncate_page(inode->i_mapping, inode->i_size, ext2_get_block); n = ext2_block_to_path(inode, iblock, offsets);/*以逻辑块号为索引查找物理块*/ if (n == 0) return; if (n == 1) { ext2_free_data(inode, i_data+offsets[0], i_data + EXT2_NDIR_BLOCKS); /*释放一个数据块的链表*/ goto do_indirects; } partial = ext2_find_shared(inode, n, offsets, chain, &nr); /* Kill the top of shared branch (already detached) */ if (nr) { if (partial == chain) mark_inode_dirty(inode);/*标记inode脏*/ else mark_buffer_dirty_inode(partial->bh, inode);/*标记inode的缓冲区脏*/ ext2_free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); /*释放一个块链表数组*/ } /* Clear the ends of indirect blocks on the shared branch */ while (partial > chain) { ext2_free_branches(inode, partial->p + 1, (u32*)partial->bh->b_data + addr_per_block, (chain+n-1) - partial); /*释放一个块链表数组*/ mark_buffer_dirty_inode(partial->bh, inode);/*标记inode的缓冲区脏*/ if (IS_SYNC(inode)) {/*inode标记为同步*/ ll_rw_block (WRITE, 1, &partial->bh); wait_on_buffer (partial->bh);/*在等待队列上等待buffer写入设备*/ } brelse (partial->bh);/*释放块在高速缓存中的缓冲区首部*/ partial--; }do_indirects: /* Kill the remaining (whole) subtrees */ switch (offsets[0]) { default: nr = i_data[EXT2_IND_BLOCK]; if (nr) { i_data[EXT2_IND_BLOCK] = 0; mark_inode_dirty(inode);/*标志inode脏*/ ext2_free_branches(inode, &nr, &nr+1, 1); /*释放一个块链表数组*/ } case EXT2_IND_BLOCK: nr = i_data[EXT2_DIND_BLOCK]; if (nr) { i_data[EXT2_DIND_BLOCK] = 0; mark_inode_dirty(inode);/*标志inode脏*/ ext2_free_branches(inode, &nr, &nr+1, 2); /*释放一个块链表数组*/ } case EXT2_DIND_BLOCK: nr = i_data[EXT2_TIND_BLOCK]; if (nr) { i_data[EXT2_TIND_BLOCK] = 0; mark_inode_dirty(inode);/*标志inode脏*/ ext2_free_branches(inode, &nr, &nr+1, 3); /*释放一个块链表数组*/ } case EXT2_TIND_BLOCK: ; } /*文件的最后修改时间=节点的修改时间=当前时间*/ inode->i_mtime = inode->i_ctime = CURRENT_TIME; if (IS_SYNC(inode))/*inode标志为需要同步*/ ext2_sync_inode (inode);/*同步inode到磁盘*/ else mark_inode_dirty(inode);/*标志inode脏*/}/*用来读取一个指定的索引节点信息*/void ext2_read_inode (struct inode * inode){ struct buffer_head * bh; struct ext2_inode * raw_inode;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -