📄 dir.c
字号:
brelse(bh); bh = ocfs2_bread(inode, offset >> sb->s_blocksize_bits, &err, 0); if (!bh) { mlog(ML_ERROR, "directory #%"MLFu64" contains " "a hole at offset %lu\n", OCFS2_I(inode)->ip_blkno, offset); offset += sb->s_blocksize; continue; } de = (struct ocfs2_dir_entry *) bh->b_data; } if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { brelse(bh); return 1; } if (le64_to_cpu(de->inode)) { brelse(bh); return 0; } offset += le16_to_cpu(de->rec_len); de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len)); } brelse(bh); return 1;}/* returns a bh of the 1st new block in the allocation. */int ocfs2_do_extend_dir(struct super_block *sb, struct ocfs2_journal_handle *handle, struct inode *dir, struct buffer_head *parent_fe_bh, struct ocfs2_alloc_context *data_ac, struct ocfs2_alloc_context *meta_ac, struct buffer_head **new_bh){ int status; int extend; u64 p_blkno; spin_lock(&OCFS2_I(dir)->ip_lock); extend = (i_size_read(dir) == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)); spin_unlock(&OCFS2_I(dir)->ip_lock); if (extend) { status = ocfs2_extend_allocation(OCFS2_SB(sb), dir, 1, parent_fe_bh, handle, data_ac, meta_ac, NULL); BUG_ON(status == -EAGAIN); if (status < 0) { mlog_errno(status); goto bail; } } status = ocfs2_extent_map_get_blocks(dir, (dir->i_blocks >> (sb->s_blocksize_bits - 9)), 1, &p_blkno, NULL); if (status < 0) { mlog_errno(status); goto bail; } *new_bh = sb_getblk(sb, p_blkno); if (!*new_bh) { status = -EIO; mlog_errno(status); goto bail; } status = 0;bail: mlog_exit(status); return status;}/* assumes you already have a cluster lock on the directory. */static int ocfs2_extend_dir(struct ocfs2_super *osb, struct inode *dir, struct buffer_head *parent_fe_bh, struct buffer_head **new_de_bh){ int status = 0; int credits, num_free_extents, drop_alloc_sem = 0; loff_t dir_i_size; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; struct ocfs2_alloc_context *data_ac = NULL; struct ocfs2_alloc_context *meta_ac = NULL; struct ocfs2_journal_handle *handle = NULL; struct buffer_head *new_bh = NULL; struct ocfs2_dir_entry * de; struct super_block *sb = osb->sb; mlog_entry_void(); dir_i_size = i_size_read(dir); mlog(0, "extending dir %"MLFu64" (i_size = %lld)\n", OCFS2_I(dir)->ip_blkno, dir_i_size); handle = ocfs2_alloc_handle(osb); if (handle == NULL) { status = -ENOMEM; mlog_errno(status); goto bail; } /* dir->i_size is always block aligned. */ spin_lock(&OCFS2_I(dir)->ip_lock); if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) { spin_unlock(&OCFS2_I(dir)->ip_lock); num_free_extents = ocfs2_num_free_extents(osb, dir, fe); if (num_free_extents < 0) { status = num_free_extents; mlog_errno(status); goto bail; } if (!num_free_extents) { status = ocfs2_reserve_new_metadata(osb, handle, fe, &meta_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } } status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } credits = ocfs2_calc_extend_credits(sb, fe, 1); } else { spin_unlock(&OCFS2_I(dir)->ip_lock); credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; } down_write(&OCFS2_I(dir)->ip_alloc_sem); drop_alloc_sem = 1; handle = ocfs2_start_trans(osb, handle, credits); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; mlog_errno(status); goto bail; } status = ocfs2_do_extend_dir(osb->sb, handle, dir, parent_fe_bh, data_ac, meta_ac, &new_bh); if (status < 0) { mlog_errno(status); goto bail; } ocfs2_set_new_buffer_uptodate(dir, new_bh); status = ocfs2_journal_access(handle, dir, new_bh, OCFS2_JOURNAL_ACCESS_CREATE); if (status < 0) { mlog_errno(status); goto bail; } memset(new_bh->b_data, 0, sb->s_blocksize); de = (struct ocfs2_dir_entry *) new_bh->b_data; de->inode = 0; de->rec_len = cpu_to_le16(sb->s_blocksize); status = ocfs2_journal_dirty(handle, new_bh); if (status < 0) { mlog_errno(status); goto bail; } dir_i_size += dir->i_sb->s_blocksize; i_size_write(dir, dir_i_size); dir->i_blocks = ocfs2_align_bytes_to_sectors(dir_i_size); status = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh); if (status < 0) { mlog_errno(status); goto bail; } *new_de_bh = new_bh; get_bh(*new_de_bh);bail: if (drop_alloc_sem) up_write(&OCFS2_I(dir)->ip_alloc_sem); if (handle) ocfs2_commit_trans(handle); if (data_ac) ocfs2_free_alloc_context(data_ac); if (meta_ac) ocfs2_free_alloc_context(meta_ac); if (new_bh) brelse(new_bh); mlog_exit(status); return status;}/* * Search the dir for a good spot, extending it if necessary. The * block containing an appropriate record is returned in ret_de_bh. */int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, struct inode *dir, struct buffer_head *parent_fe_bh, const char *name, int namelen, struct buffer_head **ret_de_bh){ unsigned long offset; struct buffer_head * bh = NULL; unsigned short rec_len; struct ocfs2_dinode *fe; struct ocfs2_dir_entry *de; struct super_block *sb; int status; mlog_entry_void(); mlog(0, "getting ready to insert namelen %d into dir %"MLFu64"\n", namelen, OCFS2_I(dir)->ip_blkno); BUG_ON(!S_ISDIR(dir->i_mode)); fe = (struct ocfs2_dinode *) parent_fe_bh->b_data; BUG_ON(le64_to_cpu(fe->i_size) != i_size_read(dir)); sb = dir->i_sb; if (!namelen) { status = -EINVAL; mlog_errno(status); goto bail; } bh = ocfs2_bread(dir, 0, &status, 0); if (!bh) { mlog_errno(status); goto bail; } rec_len = OCFS2_DIR_REC_LEN(namelen); offset = 0; de = (struct ocfs2_dir_entry *) bh->b_data; while (1) { if ((char *)de >= sb->s_blocksize + bh->b_data) { brelse(bh); bh = NULL; if (i_size_read(dir) <= offset) { status = ocfs2_extend_dir(osb, dir, parent_fe_bh, &bh); if (status < 0) { mlog_errno(status); goto bail; } BUG_ON(!bh); *ret_de_bh = bh; get_bh(*ret_de_bh); goto bail; } bh = ocfs2_bread(dir, offset >> sb->s_blocksize_bits, &status, 0); if (!bh) { mlog_errno(status); goto bail; } /* move to next block */ de = (struct ocfs2_dir_entry *) bh->b_data; } if (!ocfs2_check_dir_entry(dir, de, bh, offset)) { status = -ENOENT; goto bail; } if (ocfs2_match(namelen, name, de)) { status = -EEXIST; goto bail; } if (((le64_to_cpu(de->inode) == 0) && (le16_to_cpu(de->rec_len) >= rec_len)) || (le16_to_cpu(de->rec_len) >= (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) { /* Ok, we found a spot. Return this bh and let * the caller actually fill it in. */ *ret_de_bh = bh; get_bh(*ret_de_bh); status = 0; goto bail; } offset += le16_to_cpu(de->rec_len); de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len)); } status = 0;bail: if (bh) brelse(bh); mlog_exit(status); return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -