diff --git a/lustre/smfs/cache_space.c b/lustre/smfs/cache_space.c index a6092bfa6f6aa463b0488783019fd47d320f7769..674a2647245b4e59b910492d47b0bd2619e27780 100644 --- a/lustre/smfs/cache_space.c +++ b/lustre/smfs/cache_space.c @@ -116,6 +116,8 @@ static int cache_leaf_node(struct dentry *dentry, __u64 *active_entry) { struct inode *inode = dentry->d_inode; + if (!dentry->d_inode) + return 0; if (S_ISDIR(inode->i_mode)) { if (inode->i_nlink != 2) return 0; diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 78946b7e6026ed0a246dc1881b615e70e3574906..85fb5b4d762fe7de7448cb3684f17fa00a3e8a10 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -152,9 +152,6 @@ static struct dentry *smfs_lookup(struct inode *dir, struct dentry *dentry, GOTO(exit, rc = NULL); } SMFS_GET_INODE(dir->i_sb, cache_inode, dir, inode, rc2, exit); - } else { - d_add(dentry, NULL); - GOTO(exit, rc); } d_add(dentry, inode); diff --git a/lustre/smfs/smfs_cow.c b/lustre/smfs/smfs_cow.c index a6f241cefaa6e4a0593944bc415f61a7a2a4835e..c71e95175c49ffb06808cc45bf90641c76f149b1 100644 --- a/lustre/smfs/smfs_cow.c +++ b/lustre/smfs/smfs_cow.c @@ -177,6 +177,9 @@ static int smfs_init_snap_inode_info(struct inode *inode, struct inode *dir, int int rc = 0; ENTRY; + if (!inode) + RETURN(0); + if (dir) { I2SNAPI(inode)->sn_flags = I2SNAPI(dir)->sn_flags; I2SNAPI(inode)->sn_gen = I2SNAPI(dir)->sn_gen; @@ -710,7 +713,7 @@ static struct snap_info * smfs_find_create_snap_info(struct super_block *sb, struct snap_super_info *snap_sinfo = S2SNAPI(sb); struct fsfilt_operations *sops = snap_sinfo->snap_cache_fsfilt; struct snap_info *snap_info, *tmp; - ino_t *snap_root; + ino_t *snap_root = NULL; int rino_size, snap_count_size, rc = 0; ENTRY; @@ -768,6 +771,8 @@ exit: smfs_cleanup_snap_info(snap_info); OBD_FREE(snap_info, sizeof(struct snap_info)); } + if (snap_root) + OBD_FREE(snap_root, rino_size); RETURN(snap_info); } @@ -1369,39 +1374,82 @@ static cow_funcs smfs_cow_pre_funcs[HOOK_MAX + 1] = { [HOOK_WRITE] smfs_cow_write_pre, [HOOK_READDIR] smfs_cow_readdir_pre, }; -int smfs_cow_lookup_post(struct inode *dir, void *de, void *data1, - void *data2) + +static int smfs_revalidate_dotsnap_dentry(struct dentry *dentry, + struct inode *dir, int index) { - struct dentry *dentry = (struct dentry*)de; - struct inode *inode = dentry->d_inode; - struct fsfilt_operations *sops = I2SNAPCOPS(inode); - int index = I2SNAPI(dir)->sn_index; - ENTRY; + struct inode *inode = dentry->d_inode; + ENTRY; + + if (!inode) + RETURN(0); - LASSERT(inode); - - if (index > 0) { + if (index > 0 && index != DOT_SNAP_INDEX) { + struct fsfilt_operations *sops = I2SNAPCOPS(inode); struct inode *cache_ind = NULL; cache_ind = sops->fs_get_indirect(I2CI(inode), NULL, index); + if (cache_ind) { struct inode *ind_inode = NULL; LASSERT(cache_ind->i_ino != I2CI(inode)->i_ino); - ind_inode = smfs_get_inode(dir->i_sb, cache_ind->i_ino, + + ind_inode = smfs_get_inode(inode->i_sb, cache_ind->i_ino, dir, index); - /*replace the ind_inode here*/ list_del_init(&dentry->d_alias); iput(inode); - d_instantiate(dentry, ind_inode); + d_instantiate(dentry, ind_inode); + iput(cache_ind); } - if (cache_ind) - iput(cache_ind); } - inode = dentry->d_inode; + RETURN(0); +} + +static int smfs_revalidate_nd(struct dentry *dentry, struct nameidata *nd) +{ + struct inode *inode = dentry->d_inode; + ENTRY; + + if (!inode) + RETURN(0); + + if (smfs_under_dotsnap_inode(inode)) { + struct inode *dir = dentry->d_parent->d_inode; + int index = I2SNAPI(inode)->sn_index; + + smfs_revalidate_dotsnap_dentry(dentry, dir, index); + smfs_init_snap_inode_info(dentry->d_inode, dir, index); + } + + RETURN(0); +} + +static int smfs_delete_dentry(struct dentry *dentry) +{ + dentry->d_op = NULL; + return 0; +} - smfs_init_snap_inode_info(inode, dir, index); +struct dentry_operations smfs_cow_dops = { + .d_revalidate = smfs_revalidate_nd, + .d_delete = smfs_delete_dentry, +}; + +int smfs_cow_lookup_post(struct inode *dir, void *de, void *data1, + void *data2) +{ + struct dentry *dentry = (struct dentry*)de; + struct inode *inode = dentry->d_inode; + ENTRY; + + if (inode && smfs_under_dotsnap_inode(inode)) { + int index = I2SNAPI(dir)->sn_index; + smfs_revalidate_dotsnap_dentry(dentry, dir, index); + smfs_init_snap_inode_info(inode, dir, index); + } + dentry->d_op = &smfs_cow_dops; RETURN(0); } diff --git a/lustre/smfs/smfs_lib.c b/lustre/smfs/smfs_lib.c index 10a3bf9e8b7e4db431b853fd6381c9c393edaf36..b4561c7f2795d1b08f07ff1c67b7e69c24bc3c4c 100644 --- a/lustre/smfs/smfs_lib.c +++ b/lustre/smfs/smfs_lib.c @@ -163,6 +163,11 @@ err_out: static int smfs_umount_cache(struct smfs_super_info *smb) { + struct dentry *root = smb->smsi_sb->s_root; + + dput(root); + if (atomic_read(&root->d_inode->i_count) == 0) + igrab(root->d_inode); mntput(smb->smsi_mnt); smfs_cleanup_sm_ops(smb);