int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) { struct nilfs_inode_info *ii = NILFS_I(inode); struct the_nilfs *nilfs = inode->i_sb->s_fs_info; atomic_add(nr_dirty, &nilfs->ns_ndirtyblks); if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state)) return 0; spin_lock(&nilfs->ns_inode_lock); if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) { nilfs_warning(inode->i_sb, __func__, "cannot get inode (ino=%lu)\n", inode->i_ino); spin_unlock(&nilfs->ns_inode_lock); return -EINVAL; } list_move_tail(&ii->i_dirty, &nilfs->ns_dirty_files); set_bit(NILFS_I_QUEUED, &ii->i_state); } spin_unlock(&nilfs->ns_inode_lock); return 0; }
void nilfs_evict_inode(struct inode *inode) { struct nilfs_transaction_info ti; struct super_block *sb = inode->i_sb; struct nilfs_inode_info *ii = NILFS_I(inode); int ret; if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); end_writeback(inode); nilfs_clear_inode(inode); return; } nilfs_transaction_begin(sb, &ti, 0); if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); nilfs_truncate_bmap(ii, 0); nilfs_mark_inode_dirty(inode); end_writeback(inode); ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); if (!ret) atomic_dec(&ii->i_root->inodes_count); nilfs_clear_inode(inode); if (IS_SYNC(inode)) nilfs_set_transaction_flag(NILFS_TI_SYNC); nilfs_transaction_commit(sb); }
/** * nilfs_mdt_find_block - find and get a buffer on meta data file. * @inode: inode of the meta data file * @start: start block offset (inclusive) * @end: end block offset (inclusive) * @blkoff: block offset * @out_bh: place to store a pointer to buffer_head struct * * nilfs_mdt_find_block() looks up an existing block in range of * [@start, @end] and stores pointer to a buffer head of the block to * @out_bh, and block offset to @blkoff, respectively. @out_bh and * @blkoff are substituted only when zero is returned. * * Return Value: On success, it returns 0. On error, the following negative * error code is returned. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error * * %-ENOENT - no block was found in the range */ int nilfs_mdt_find_block(struct inode *inode, unsigned long start, unsigned long end, unsigned long *blkoff, struct buffer_head **out_bh) { __u64 next; int ret; if (unlikely(start > end)) return -ENOENT; ret = nilfs_mdt_read_block(inode, start, true, out_bh); if (!ret) { *blkoff = start; goto out; } if (unlikely(ret != -ENOENT || start == ULONG_MAX)) goto out; ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next); if (!ret) { if (next <= end) { ret = nilfs_mdt_read_block(inode, next, true, out_bh); if (!ret) *blkoff = next; } else { ret = -ENOENT; } } out: return ret; }
static int nilfs_iget_set(struct inode *inode, void *opaque) { struct nilfs_iget_args *args = opaque; inode->i_ino = args->ino; if (args->for_gc) { NILFS_I(inode)->i_state = 1 << NILFS_I_GCINODE; NILFS_I(inode)->i_cno = args->cno; NILFS_I(inode)->i_root = NULL; } else { if (args->root && args->ino == NILFS_ROOT_INO) nilfs_get_root(args->root); NILFS_I(inode)->i_root = args->root; } return 0; }
static void nilfs_clear_inode(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); #ifdef CONFIG_NILFS_POSIX_ACL if (ii->i_acl && ii->i_acl != NILFS_ACL_NOT_CACHED) { posix_acl_release(ii->i_acl); ii->i_acl = NILFS_ACL_NOT_CACHED; } if (ii->i_default_acl && ii->i_default_acl != NILFS_ACL_NOT_CACHED) { posix_acl_release(ii->i_default_acl); ii->i_default_acl = NILFS_ACL_NOT_CACHED; } #endif /* * Free resources allocated in nilfs_read_inode(), here. */ BUG_ON(!list_empty(&ii->i_dirty)); brelse(ii->i_bh); ii->i_bh = NULL; if (test_bit(NILFS_I_BMAP, &ii->i_state)) nilfs_bmap_clear(ii->i_bmap); nilfs_btnode_cache_clear(&ii->i_btnode_cache); }
static int nilfs_encode_fh(struct inode *inode, __u32 *fh, int *lenp, struct inode *parent) { struct nilfs_fid *fid = (struct nilfs_fid *)fh; struct nilfs_root *root = NILFS_I(inode)->i_root; int type; if (parent && *lenp < NILFS_FID_SIZE_CONNECTABLE) { *lenp = NILFS_FID_SIZE_CONNECTABLE; return FILEID_INVALID; } if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE) { *lenp = NILFS_FID_SIZE_NON_CONNECTABLE; return FILEID_INVALID; } fid->cno = root->cno; fid->ino = inode->i_ino; fid->gen = inode->i_generation; if (parent) { fid->parent_ino = parent->i_ino; fid->parent_gen = parent->i_generation; type = FILEID_NILFS_WITH_PARENT; *lenp = NILFS_FID_SIZE_CONNECTABLE; } else { type = FILEID_NILFS_WITHOUT_PARENT; *lenp = NILFS_FID_SIZE_NON_CONNECTABLE; } return type; }
int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) { struct nilfs_inode_info *ii = NILFS_I(inode); struct the_nilfs *nilfs = inode->i_sb->s_fs_info; atomic_add(nr_dirty, &nilfs->ns_ndirtyblks); if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state)) return 0; spin_lock(&nilfs->ns_inode_lock); if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { /* Because this routine may race with nilfs_dispose_list(), we have to check NILFS_I_QUEUED here, too. */ if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) { /* This will happen when somebody is freeing this inode. */ nilfs_warning(inode->i_sb, __func__, "cannot get inode (ino=%lu)\n", inode->i_ino); spin_unlock(&nilfs->ns_inode_lock); return -EINVAL; /* NILFS_I_DIRTY may remain for freeing inode */ } list_move_tail(&ii->i_dirty, &nilfs->ns_dirty_files); set_bit(NILFS_I_QUEUED, &ii->i_state); } spin_unlock(&nilfs->ns_inode_lock); return 0; }
void nilfs_evict_inode(struct inode *inode) { struct nilfs_transaction_info ti; struct super_block *sb = inode->i_sb; struct nilfs_inode_info *ii = NILFS_I(inode); int ret; if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { truncate_inode_pages_final(&inode->i_data); clear_inode(inode); nilfs_clear_inode(inode); return; } nilfs_transaction_begin(sb, &ti, 0); /* never fails */ truncate_inode_pages_final(&inode->i_data); /* TODO: some of the following operations may fail. */ nilfs_truncate_bmap(ii, 0); nilfs_mark_inode_dirty(inode); clear_inode(inode); ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); if (!ret) atomic64_dec(&ii->i_root->inodes_count); nilfs_clear_inode(inode); if (IS_SYNC(inode)) nilfs_set_transaction_flag(NILFS_TI_SYNC); nilfs_transaction_commit(sb); /* May construct a logical segment and may fail in sync mode. But delete_inode has no return value. */ }
int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, struct buffer_head **pbh) { struct nilfs_inode_info *ii = NILFS_I(inode); int err; spin_lock(&sbi->s_inode_lock); /* Caller of this function MUST lock s_inode_lock */ if (ii->i_bh == NULL) { spin_unlock(&sbi->s_inode_lock); err = nilfs_ifile_get_inode_block(sbi->s_ifile, inode->i_ino, pbh); if (unlikely(err)) return err; spin_lock(&sbi->s_inode_lock); if (ii->i_bh == NULL) ii->i_bh = *pbh; else { brelse(*pbh); *pbh = ii->i_bh; } } else *pbh = ii->i_bh; get_bh(*pbh); spin_unlock(&sbi->s_inode_lock); return 0; }
int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) { struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_inode_info *ii = NILFS_I(inode); int err; spin_lock(&nilfs->ns_inode_lock); if (ii->i_bh == NULL) { spin_unlock(&nilfs->ns_inode_lock); err = nilfs_ifile_get_inode_block(ii->i_root->ifile, inode->i_ino, pbh); if (unlikely(err)) return err; spin_lock(&nilfs->ns_inode_lock); if (ii->i_bh == NULL) ii->i_bh = *pbh; else { brelse(*pbh); *pbh = ii->i_bh; } } else *pbh = ii->i_bh; get_bh(*pbh); spin_unlock(&nilfs->ns_inode_lock); return 0; }
void nilfs_delete_inode(struct inode *inode) { struct nilfs_transaction_info ti; struct super_block *sb = inode->i_sb; struct nilfs_inode_info *ii = NILFS_I(inode); if (unlikely(is_bad_inode(inode))) { if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); clear_inode(inode); return; } nilfs_transaction_begin(sb, &ti, 0); /* never fails */ if (inode->i_data.nrpages) truncate_inode_pages(&inode->i_data, 0); nilfs_truncate_bmap(ii, 0); nilfs_free_inode(inode); /* nilfs_free_inode() marks inode buffer dirty */ if (IS_SYNC(inode)) nilfs_set_transaction_flag(NILFS_TI_SYNC); nilfs_transaction_commit(sb); /* May construct a logical segment and may fail in sync mode. But delete_inode has no return value. */ }
void nilfs_truncate(struct inode *inode) { unsigned long blkoff; unsigned int blocksize; struct nilfs_transaction_info ti; struct super_block *sb = inode->i_sb; struct nilfs_inode_info *ii = NILFS_I(inode); if (!test_bit(NILFS_I_BMAP, &ii->i_state)) return; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return; blocksize = sb->s_blocksize; blkoff = (inode->i_size + blocksize - 1) >> sb->s_blocksize_bits; nilfs_transaction_begin(sb, &ti, 0); /* never fails */ block_truncate_page(inode->i_mapping, inode->i_size, nilfs_get_block); nilfs_truncate_bmap(ii, blkoff); inode->i_mtime = inode->i_ctime = CURRENT_TIME; if (IS_SYNC(inode)) nilfs_set_transaction_flag(NILFS_TI_SYNC); nilfs_set_file_dirty(NILFS_SB(sb), inode, 0); nilfs_transaction_commit(sb); /* May construct a logical segment and may fail in sync mode. But truncate has no return value. */ }
void nilfs_write_inode_common(struct inode *inode, struct nilfs_inode *raw_inode, int has_bmap) { struct nilfs_inode_info *ii = NILFS_I(inode); raw_inode->i_mode = cpu_to_le16(inode->i_mode); raw_inode->i_uid = cpu_to_le32(inode->i_uid); raw_inode->i_gid = cpu_to_le32(inode->i_gid); raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); raw_inode->i_size = cpu_to_le64(inode->i_size); raw_inode->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); raw_inode->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec); raw_inode->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); raw_inode->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); raw_inode->i_blocks = cpu_to_le64(inode->i_blocks); raw_inode->i_flags = cpu_to_le32(ii->i_flags); raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (has_bmap) nilfs_bmap_write(ii->i_bmap, raw_inode); else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_device_code = cpu_to_le64(new_encode_dev(inode->i_rdev)); /* When extending inode, nilfs->ns_inode_size should be checked for substitutions of appended fields */ }
static int nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block, struct buffer_head *bh, void (*init_block)(struct inode *, struct buffer_head *, void *)) { struct nilfs_inode_info *ii = NILFS_I(inode); void *kaddr; int ret; /* Caller exclude read accesses using page lock */ /* set_buffer_new(bh); */ bh->b_blocknr = 0; ret = nilfs_bmap_insert(ii->i_bmap, block, (unsigned long)bh); if (unlikely(ret)) return ret; set_buffer_mapped(bh); kaddr = kmap_atomic(bh->b_page, KM_USER0); memset(kaddr + bh_offset(bh), 0, 1 << inode->i_blkbits); if (init_block) init_block(inode, bh, kaddr); flush_dcache_page(bh->b_page); kunmap_atomic(kaddr, KM_USER0); set_buffer_uptodate(bh); nilfs_mark_buffer_dirty(bh); nilfs_mdt_mark_dirty(inode); return 0; }
void nilfs_inode_add_blocks(struct inode *inode, int n) { struct nilfs_root *root = NILFS_I(inode)->i_root; inode_add_bytes(inode, i_blocksize(inode) * n); if (root) atomic64_add(n, &root->blocks_count); }
void nilfs_inode_sub_blocks(struct inode *inode, int n) { struct nilfs_root *root = NILFS_I(inode)->i_root; inode_sub_bytes(inode, (1 << inode->i_blkbits) * n); if (root) atomic_sub(n, &root->blocks_count); }
static void nilfs_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); if (nilfs_is_metadata_file_inode(inode)) nilfs_mdt_destroy(inode); kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); }
int nilfs_get_block(struct inode *inode, sector_t blkoff, struct buffer_head *bh_result, int create) { struct nilfs_inode_info *ii = NILFS_I(inode); struct the_nilfs *nilfs = inode->i_sb->s_fs_info; __u64 blknum = 0; int err = 0, ret; unsigned maxblocks = bh_result->b_size >> inode->i_blkbits; down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); ret = nilfs_bmap_lookup_contig(ii->i_bmap, blkoff, &blknum, maxblocks); up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); if (ret >= 0) { map_bh(bh_result, inode->i_sb, blknum); if (ret > 0) bh_result->b_size = (ret << inode->i_blkbits); goto out; } if (ret == -ENOENT && create) { struct nilfs_transaction_info ti; bh_result->b_blocknr = 0; err = nilfs_transaction_begin(inode->i_sb, &ti, 1); if (unlikely(err)) goto out; err = nilfs_bmap_insert(ii->i_bmap, (unsigned long)blkoff, (unsigned long)bh_result); if (unlikely(err != 0)) { if (err == -EEXIST) { printk(KERN_WARNING "nilfs_get_block: a race condition " "while inserting a data block. " "(inode number=%lu, file block " "offset=%llu)\n", inode->i_ino, (unsigned long long)blkoff); err = 0; } nilfs_transaction_abort(inode->i_sb); goto out; } nilfs_mark_inode_dirty(inode); nilfs_transaction_commit(inode->i_sb); set_buffer_new(bh_result); set_buffer_delay(bh_result); map_bh(bh_result, inode->i_sb, 0); } else if (ret == -ENOENT) { ; } else { err = ret; } out: return err; }
int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, __u64 vbn, struct buffer_head **out_bh) { int ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, vbn ? : pbn, pbn, out_bh); if (ret == -EEXIST) /* internal code (cache hit) */ ret = 0; return ret; }
struct inode *nilfs_gc_iget(struct the_nilfs *nilfs, ino_t ino, __u64 cno) { struct hlist_head *head = nilfs->ns_gc_inodes_h + ihash(ino, cno); struct hlist_node *node; struct inode *inode; hlist_for_each_entry(inode, node, head, i_hash) { if (inode->i_ino == ino && NILFS_I(inode)->i_cno == cno) return inode; } inode = alloc_gcinode(nilfs, ino, cno); if (likely(inode)) { hlist_add_head(&inode->i_hash, head); list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes); } return inode; }
int nilfs_permission(struct inode *inode, int mask) { struct nilfs_root *root = NILFS_I(inode)->i_root; if ((mask & MAY_WRITE) && root && root->cno != NILFS_CPTREE_CURRENT_CNO) return -EROFS; /* snapshot is not writable */ return generic_permission(inode, mask); }
int nilfs_init_gcdat_inode(struct the_nilfs *nilfs) { struct inode *dat = nilfs->ns_dat, *gcdat = nilfs->ns_gc_dat; struct nilfs_inode_info *dii = NILFS_I(dat), *gii = NILFS_I(gcdat); int err; gcdat->i_state = 0; gcdat->i_blocks = dat->i_blocks; gii->i_flags = dii->i_flags; gii->i_state = dii->i_state | (1 << NILFS_I_GCDAT); gii->i_cno = 0; nilfs_bmap_init_gcdat(gii->i_bmap, dii->i_bmap); err = nilfs_copy_dirty_pages(gcdat->i_mapping, dat->i_mapping); if (unlikely(err)) return err; return nilfs_copy_dirty_pages(&gii->i_btnode_cache, &dii->i_btnode_cache); }
void nilfs_destroy_inode(struct inode *inode) { struct nilfs_mdt_info *mdi = NILFS_MDT(inode); if (mdi) { kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ kfree(mdi); } kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); }
void nilfs_vinode_debug(const char *fname, int line, struct inode *inode, const char *m, ...) { struct nilfs_inode_info *ii; int n = 0, len; char b[MSIZ]; va_list args; len = snprintf(b, MSIZ, "VINODE %p ", inode); va_start(args, m); len += vsnprintf(b + len, MSIZ - len, m, args); va_end(args); if (inode == NULL) { printk(KERN_DEBUG "%s: inode=NULL %s at %d\n", m, fname, line); return; } ii = NILFS_I(inode); len += snprintf(b + len, MSIZ - len, ": current %p ino=%lu nlink=%u " "count=%u mode=0%o mapping=%p i_bh=%p", current, inode->i_ino, inode->i_nlink, atomic_read(&inode->i_count), inode->i_mode, inode->i_mapping, ii->i_bh); len += snprintf(b + len, MSIZ - len, " %s(%d) i_state=", fname, line); TEST_INODE_STATE(inode, DIRTY_SYNC, b, MSIZ, n, len); TEST_INODE_STATE(inode, DIRTY_DATASYNC, b, MSIZ, n, len); TEST_INODE_STATE(inode, DIRTY_PAGES, b, MSIZ, n, len); TEST_INODE_STATE(inode, LOCK, b, MSIZ, n, len); TEST_INODE_STATE(inode, FREEING, b, MSIZ, n, len); TEST_INODE_STATE(inode, CLEAR, b, MSIZ, n, len); TEST_INODE_STATE(inode, NEW, b, MSIZ, n, len); #ifdef I_WILL_FREE TEST_INODE_STATE(inode, WILL_FREE, b, MSIZ, n, len); #endif if (ii->i_state) { n = 0; len += snprintf(b + len, MSIZ - len, " vi_state="); TEST_NILFS_INODE_STATE(ii, NEW, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, DIRTY, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, QUEUED, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, BUSY, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, COLLECTED, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, UPDATED, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, INODE_DIRTY, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, BMAP, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, GCINODE, b, MSIZ, n, len); TEST_NILFS_INODE_STATE(ii, GCDAT, b, MSIZ, n, len); } printk(KERN_DEBUG "%s\n", b); if (ii->i_bh) BH_DEBUG(ii->i_bh, "ibh"); }
static int nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, int mode, struct buffer_head **out_bh) { struct buffer_head *bh; unsigned long blknum = 0; int ret = -ENOMEM; bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0); if (unlikely(!bh)) goto failed; ret = -EEXIST; /* internal code */ if (buffer_uptodate(bh)) goto out; if (mode == READA) { if (!trylock_buffer(bh)) { ret = -EBUSY; goto failed_bh; } } else /* mode == READ */ lock_buffer(bh); if (buffer_uptodate(bh)) { unlock_buffer(bh); goto out; } if (!buffer_mapped(bh)) { /* unused buffer */ ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, &blknum); if (unlikely(ret)) { unlock_buffer(bh); goto failed_bh; } bh->b_bdev = NILFS_MDT(inode)->mi_nilfs->ns_bdev; bh->b_blocknr = blknum; set_buffer_mapped(bh); } bh->b_end_io = end_buffer_read_sync; get_bh(bh); submit_bh(mode, bh); ret = 0; out: get_bh(bh); *out_bh = bh; failed_bh: unlock_page(bh->b_page); page_cache_release(bh->b_page); brelse(bh); failed: return ret; }
static void nilfs_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); struct nilfs_mdt_info *mdi = NILFS_MDT(inode); if (mdi) { kfree(mdi->mi_bgl); /* kfree(NULL) is safe */ kfree(mdi); } kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); }
void nilfs_clear_gcdat_inode(struct the_nilfs *nilfs) { struct inode *gcdat = nilfs->ns_gc_dat; struct nilfs_inode_info *gii = NILFS_I(gcdat); gcdat->i_state = I_CLEAR; gii->i_flags = 0; truncate_inode_pages(gcdat->i_mapping, 0); truncate_inode_pages(&gii->i_btnode_cache, 0); }
/** * nilfs_mdt_delete_block - make a hole on the meta data file. * @inode: inode of the meta data file * @block: block offset * * Return Value: On success, zero is returned. * On error, one of the following negative error code is returned. * * %-ENOMEM - Insufficient memory available. * * %-EIO - I/O error * * %-EINVAL - bmap is broken. (the caller should call nilfs_error()) */ int nilfs_mdt_delete_block(struct inode *inode, unsigned long block) { struct nilfs_inode_info *ii = NILFS_I(inode); int err; err = nilfs_bmap_delete(ii->i_bmap, block); if (!err || err == -ENOENT) { nilfs_mdt_mark_dirty(inode); nilfs_mdt_forget_block(inode, block); } return err; }
static int nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, int mode, int mode_flags, struct buffer_head **out_bh) { struct buffer_head *bh; __u64 blknum = 0; int ret = -ENOMEM; bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0); if (unlikely(!bh)) goto failed; ret = -EEXIST; /* internal code */ if (buffer_uptodate(bh)) goto out; if (mode_flags & REQ_RAHEAD) { if (!trylock_buffer(bh)) { ret = -EBUSY; goto failed_bh; } } else /* mode == READ */ lock_buffer(bh); if (buffer_uptodate(bh)) { unlock_buffer(bh); goto out; } ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, &blknum); if (unlikely(ret)) { unlock_buffer(bh); goto failed_bh; } map_bh(bh, inode->i_sb, (sector_t)blknum); bh->b_end_io = end_buffer_read_sync; get_bh(bh); submit_bh(mode, mode_flags, bh); ret = 0; trace_nilfs2_mdt_submit_block(inode, inode->i_ino, blkoff, mode); out: get_bh(bh); *out_bh = bh; failed_bh: unlock_page(bh->b_page); put_page(bh->b_page); brelse(bh); failed: return ret; }
static struct dentry * nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct inode *inode; ino_t ino; if (dentry->d_name.len > NILFS_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); ino = nilfs_inode_by_name(dir, &dentry->d_name); inode = ino ? nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino) : NULL; return d_splice_alias(inode, dentry); }