X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fsmfs%2Finode.c;h=8d89199c4fd04cc1fc1641082dd13f72f73f01db;hb=5399d2eb5b8731b81b86c501fdcf942a7803f60c;hp=bd45cfb8183f83d7236bbed49291935126f9bf51;hpb=c79f7a9cdeeef1e421e47cc853482b247d8bd969;p=fs%2Flustre-release.git diff --git a/lustre/smfs/inode.c b/lustre/smfs/inode.c index bd45cfb..8d89199 100644 --- a/lustre/smfs/inode.c +++ b/lustre/smfs/inode.c @@ -36,59 +36,112 @@ #include #include #include "smfs_internal.h" -static void smfs_init_cache_inode (struct inode *inode, void *opaque) + +static void smfs_init_inode_info(struct inode *inode, void *opaque) { - struct smfs_inode_info *sm_info = (struct smfs_inode_info *)opaque; - struct inode *cache_inode = NULL; - - cache_inode = iget(S2CSB(inode->i_sb), inode->i_ino); + if (!I2SMI(inode)) { + struct inode *cache_inode = NULL; + struct smfs_iget_args *sargs; + unsigned long ino; + + sargs = (struct smfs_iget_args *)opaque; + + /* getting backing fs inode. */ + ino = sargs ? sargs->s_ino : inode->i_ino; + cache_inode = iget(S2CSB(inode->i_sb), ino); + + OBD_ALLOC(inode->u.generic_ip, + sizeof(struct smfs_inode_info)); - if (sm_info) - memcpy(I2SMI(inode), sm_info, sizeof(struct smfs_inode_info)); + LASSERT(inode->u.generic_ip); + I2CI(inode) = cache_inode; - I2CI(inode) = cache_inode; - post_smfs_inode(inode, cache_inode); - sm_set_inode_ops(cache_inode, inode); -#if CONFIG_SNAPFS - if (sm_info) { - smfs_init_snap_inode_info(inode, &sm_info->sm_sninfo); + CDEBUG(D_INODE, "cache_inode i_count ino %lu i_count %d\n", + cache_inode->i_ino, atomic_read(&cache_inode->i_count)); + + post_smfs_inode(inode, cache_inode); + sm_set_inode_ops(cache_inode, inode); + + if (sargs) { + struct inode *dir = sargs->s_inode; + if (dir) + I2SMI(inode)->smi_flags = I2SMI(dir)->smi_flags; + } + } +} + +static void smfs_clear_inode_info(struct inode *inode) +{ + if (I2SMI(inode)) { + struct inode *cache_inode = I2CI(inode); + + LASSERTF(((atomic_read(&cache_inode->i_count) == 1) || + cache_inode == cache_inode->i_sb->s_root->d_inode), + "inode %p cache inode %p %lu i_count %d != 0 \n", + inode, cache_inode, cache_inode->i_ino, + atomic_read(&cache_inode->i_count)); + + if (cache_inode != cache_inode->i_sb->s_root->d_inode) + iput(cache_inode); + + OBD_FREE(inode->u.generic_ip, + sizeof(struct smfs_inode_info)); + inode->u.generic_ip = NULL; } -#endif } static void smfs_read_inode2(struct inode *inode, void *opaque) { ENTRY; - if (!inode) - return; + if (!inode) { + EXIT; + return; + } + CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino); - smfs_init_cache_inode(inode, opaque); + smfs_init_inode_info(inode, opaque); CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", inode->i_ino, atomic_read(&inode->i_count)); EXIT; - return; } #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) static int smfs_test_inode(struct inode *inode, unsigned long ino, - void *opaque) + void *opaque) #else static int smfs_test_inode(struct inode *inode, void *opaque) #endif { - struct snap_inode_info *sn_info = &I2SMI(inode)->sm_sninfo; - struct snap_inode_info *test_info = (struct snap_inode_info *)opaque; - - if (!sn_info || !test_info) - return 0; - if (sn_info->sn_index != test_info->sn_index) - return 0; - if (sn_info->sn_gen != test_info->sn_gen) + struct smfs_iget_args *sargs = (struct smfs_iget_args*)opaque; + + LASSERT(sargs); + + if (!sargs) + return 1; + + if (inode->i_ino != sargs->s_ino) return 0; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) - smfs_init_cache_inode(inode, opaque); + +#ifdef CONFIG_SNAPFS + if (SMFS_DO_COW(S2SMI(inode->i_sb)) && + !smfs_snap_test_inode(inode, opaque)) + return 0; #endif + if (I2SMI(inode)) { + struct inode *cache_inode = I2CI(inode); + + /* this is needed to make symatry between smfs_put_inode(). */ + LASSERT(cache_inode != NULL); + igrab(cache_inode); + + LASSERTF(cache_inode->i_ino == inode->i_ino, + "inode ino %lu != cache ino %lu", + cache_inode->i_ino, inode->i_ino); + } else { + smfs_init_inode_info(inode, opaque); + } + return 1; } @@ -100,117 +153,73 @@ int smfs_set_inode(struct inode *inode, void *opaque) } struct inode *smfs_iget(struct super_block *sb, ino_t hash, - struct smfs_inode_info *si_info) + struct smfs_iget_args *sargs) { struct inode *inode; - LASSERT(hash != 0); - inode = iget5_locked(sb, hash, smfs_test_inode, smfs_set_inode, - si_info); + inode = iget5_locked(sb, hash, smfs_test_inode, + smfs_set_inode, sargs); if (inode) { if (inode->i_state & I_NEW) unlock_new_inode(inode); - CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino, - inode->i_generation, inode); + CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p) index %d " + "ino %d\n", inode->i_ino, inode->i_generation, + inode, sargs->s_index, sargs->s_ino); + inode->i_ino = hash; } return inode; } #else struct inode *smfs_iget(struct super_block *sb, ino_t hash, - struct smfs_inode_info *si_info) + struct smfs_iget_args *sargs) { struct inode *inode; LASSERT(hash != 0); - inode = iget4(sb, hash, smfs_test_inode, si_info); - - if (inode) + inode = iget4(sb, hash, smfs_test_inode, sargs); + if (inode) { + struct inode *cache_inode = I2CI(inode); + LASSERTF((inode->i_ino == cache_inode->i_ino), + "inode %p ino %lu != cache inode %p ino %lu", + inode, inode->i_ino, cache_inode, cache_inode->i_ino); CDEBUG(D_VFSTRACE, "inode: %lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); + } return inode; } #endif -struct inode *smfs_get_inode (struct super_block *sb, ino_t hash, - struct inode *dir, int index) + +struct inode *smfs_get_inode(struct super_block *sb, ino_t hash, + struct inode *dir, int index) { - struct smfs_inode_info sm_info; - struct inode *inode = NULL; + struct smfs_iget_args sargs; + struct inode *inode; ENTRY; - - sm_info.smi_flags = I2SMI(dir)->smi_flags; - sm_info.sm_sninfo.sn_flags = I2SMI(dir)->sm_sninfo.sn_flags; - sm_info.sm_sninfo.sn_index = index; - sm_info.sm_sninfo.sn_gen = I2SMI(dir)->sm_sninfo.sn_gen; - inode = smfs_iget(sb, hash, &sm_info); + + sargs.s_ino = hash; + sargs.s_inode = dir; + sargs.s_index = index; + inode = smfs_iget(sb, hash, &sargs); RETURN(inode); -} -EXPORT_SYMBOL(smfs_get_inode); +} + static void smfs_delete_inode(struct inode *inode) { - struct inode *cache_inode; - ENTRY; - cache_inode = I2CI(inode); - - if (!cache_inode || !S2CSB(inode->i_sb)) - return; - - /* FIXME-WANGDI: because i_count of cache_inode may not be 0 or 1 in - * before smfs_delete inode, So we need to dec it to 1 before we call - * delete_inode of the bellow cache filesystem Check again latter. */ - - if (atomic_read(&cache_inode->i_count) < 1) - BUG(); - - while (atomic_read(&cache_inode->i_count) != 1) - atomic_dec(&cache_inode->i_count); - - pre_smfs_inode(inode, cache_inode); - - if (atomic_read(&cache_inode->i_count) < 1) - LBUG(); - - while (atomic_read(&cache_inode->i_count) != 1) { - atomic_dec(&cache_inode->i_count); - } - - pre_smfs_inode(inode, cache_inode); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - list_del(&cache_inode->i_hash); - INIT_LIST_HEAD(&cache_inode->i_hash); -#else - hlist_del_init(&cache_inode->i_hash); -#endif - - list_del(&cache_inode->i_list); - INIT_LIST_HEAD(&cache_inode->i_list); - - if (cache_inode->i_data.nrpages) - truncate_inode_pages(&cache_inode->i_data, 0); - - if (S2CSB(inode->i_sb)->s_op->delete_inode) - S2CSB(inode->i_sb)->s_op->delete_inode(cache_inode); - - post_smfs_inode(inode, cache_inode); - - I2CI(inode) = NULL; - return; + clear_inode(inode); + EXIT; } static void smfs_write_inode(struct inode *inode, int wait) { struct inode *cache_inode; - ENTRY; + cache_inode = I2CI(inode); + LASSERT(cache_inode != NULL); - if (!cache_inode) { - CWARN("cache inode null\n"); - return; - } pre_smfs_inode(inode, cache_inode); if (S2CSB(inode->i_sb)->s_op->write_inode) S2CSB(inode->i_sb)->s_op->write_inode(cache_inode, wait); @@ -222,12 +231,13 @@ static void smfs_write_inode(struct inode *inode, int wait) static void smfs_dirty_inode(struct inode *inode) { struct inode *cache_inode; - ENTRY; - cache_inode = I2CI(inode); - if (!cache_inode || !S2CSB(inode->i_sb)) + cache_inode = I2CI(inode); + if (!cache_inode || !S2CSB(inode->i_sb)) { + EXIT; return; + } pre_smfs_inode(inode, cache_inode); if (S2CSB(inode->i_sb)->s_op->dirty_inode) @@ -240,56 +250,50 @@ static void smfs_dirty_inode(struct inode *inode) static void smfs_put_inode(struct inode *inode) { struct inode *cache_inode; - ENTRY; + cache_inode = I2CI(inode); + LASSERT(cache_inode != NULL); - if (!cache_inode) { - CWARN("cache inode null\n"); - return; - } - - if (atomic_read(&cache_inode->i_count) > 1 && - cache_inode != cache_inode->i_sb->s_root->d_inode) + if (atomic_read(&cache_inode->i_count) > 1) iput(cache_inode); - - if (S2CSB(inode->i_sb)->s_op->put_inode) - S2CSB(inode->i_sb)->s_op->put_inode(cache_inode); + + /* + * check if we have to release backend inode. As iput() calls fs + * specific ->put_inode() first and than decrements inode rerfcount, we + * should check here ->i_count for 1, not for 0. + + * In principle we could rely on ->clear_inode(), but it will be called + * later, and thus we will have iputing of @inode and @cache_inode in + * different control paths, this is why we do it here. --umka + */ + if (atomic_read(&inode->i_count) == 1 && + cache_inode->i_sb->s_root->d_inode != cache_inode) + smfs_clear_inode_info(inode); EXIT; } -static void smfs_write_super(struct super_block *sb) +static void smfs_clear_inode(struct inode *inode) { ENTRY; - - if (!S2CSB(sb)) - return; - - if (S2CSB(sb)->s_op->write_super) - S2CSB(sb)->s_op->write_super(S2CSB(sb)); - duplicate_sb(sb, S2CSB(sb)); + smfs_clear_inode_info(inode); EXIT; - return; } -static void smfs_clear_inode(struct inode *inode) +static void smfs_write_super(struct super_block *sb) { - struct inode *cache_inode; - ENTRY; - if (!inode) return; - - cache_inode = I2CI(inode); - - if (cache_inode != cache_inode->i_sb->s_root->d_inode) { - iput(cache_inode); - SMFS_CLEAN_INODE_REC(inode); - I2CI(inode) = NULL; + if (!S2CSB(sb)) { + EXIT; + return; } + + if (S2CSB(sb)->s_op->write_super) + S2CSB(sb)->s_op->write_super(S2CSB(sb)); + duplicate_sb(sb, S2CSB(sb)); EXIT; - return; } static void smfs_write_super_lockfs(struct super_block *sb) @@ -298,8 +302,10 @@ static void smfs_write_super_lockfs(struct super_block *sb) ENTRY; cache_sb = S2CSB(sb); - if (!cache_sb) + if (!cache_sb) { + EXIT; return; + } if (cache_sb->s_op->write_super_lockfs) cache_sb->s_op->write_super_lockfs(cache_sb); @@ -314,8 +320,10 @@ static void smfs_unlockfs(struct super_block *sb) ENTRY; cache_sb = S2CSB(sb); - if (!cache_sb) + if (!cache_sb) { + EXIT; return; + } if (cache_sb->s_op->unlockfs) cache_sb->s_op->unlockfs(cache_sb); @@ -342,7 +350,6 @@ static int smfs_statfs(struct super_block *sb, struct kstatfs *buf) rc = cache_sb->s_op->statfs(cache_sb, buf); duplicate_sb(sb, cache_sb); - RETURN(rc); } static int smfs_remount(struct super_block *sb, int *flags, char *data) @@ -362,6 +369,7 @@ static int smfs_remount(struct super_block *sb, int *flags, char *data) duplicate_sb(sb, cache_sb); RETURN(rc); } + struct super_operations smfs_super_ops = { #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) .read_inode2 = smfs_read_inode2,