diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 6996a0cbfdb47893d74e93cb1cf143bf52143303..58cf6e51ce43f7f2adcdea9140c54d6bf03cdbd3 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -13,71 +13,7 @@ #include "smfs_internal.h" #define NAME_ALLOC_LEN(len) ((len+16) & ~15) - -void smfs_clear_dentry(struct dentry *dentry) -{ - struct qstr *name = NULL; - - if (dentry) { - if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock)) - return; - list_del(&dentry->d_hash); - INIT_LIST_HEAD(&dentry->d_hash); - list_del(&dentry->d_child); - if (dentry->d_inode) { - dentry->d_inode = NULL; - list_del_init(&dentry->d_alias); - } - - name = &(dentry->d_name); - if (name->len > DNAME_INLINE_LEN-1) { - SM_FREE((char *)name->name, NAME_ALLOC_LEN(name->len)); - } - } -} - -int smfs_prepare_dentry(struct dentry *dentry, - struct dentry *parent, - struct qstr *name) -{ - char *str = NULL; - - if (name->len > DNAME_INLINE_LEN-1) { - SM_ALLOC(str, NAME_ALLOC_LEN(name->len)); - if (!str) - return (-ENOMEM); - } else - str = dentry->d_iname; - - memcpy(str, name->name, name->len); - str[name->len] = 0; - - atomic_set(&dentry->d_count, 1); - dentry->d_vfs_flags = 0; - dentry->d_flags = 0; - dentry->d_inode = NULL; - dentry->d_parent = NULL; - dentry->d_sb = NULL; - dentry->d_name.name = str; - dentry->d_name.len = name->len; - dentry->d_name.hash = name->hash; - dentry->d_op = NULL; - dentry->d_fsdata = NULL; - dentry->d_mounted = 0; - INIT_LIST_HEAD(&dentry->d_hash); - INIT_LIST_HEAD(&dentry->d_lru); - INIT_LIST_HEAD(&dentry->d_subdirs); - INIT_LIST_HEAD(&dentry->d_alias); - - if (parent) { - dentry->d_parent = dget(parent); - dentry->d_sb = parent->d_sb; - list_add(&dentry->d_child, &parent->d_subdirs); - } else - INIT_LIST_HEAD(&dentry->d_child); - - return 0; -} + static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode) { atomic_set(&dentry->d_count, 1); @@ -93,6 +29,14 @@ static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode) INIT_LIST_HEAD(&dentry->d_alias); } +void d_unalloc(struct dentry *dentry) +{ + + list_del(&dentry->d_hash); + INIT_LIST_HEAD(&dentry->d_hash); + dput(dentry); /* this will free the dentry memory */ +} + static int smfs_create(struct inode *dir, struct dentry *dentry, int mode) @@ -100,7 +44,7 @@ static int smfs_create(struct inode *dir, struct inode *cache_dir; struct inode *cache_inode = NULL, *inode; struct dentry parent; - struct dentry cache_dentry; + struct dentry *cache_dentry = NULL; int rc; ENTRY; @@ -110,14 +54,19 @@ static int smfs_create(struct inode *dir, RETURN(-ENOENT); prepare_parent_dentry(&parent, cache_dir); - smfs_prepare_dentry(&cache_dentry, &parent, &dentry->d_name); - + cache_dentry = d_alloc(&parent, &dentry->d_name); + + if (!cache_dentry) { + RETURN(-ENOMEM); + } + if (cache_dir && cache_dir->i_op->create) - rc = cache_dir->i_op->create(cache_dir, &cache_dentry, mode); + rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode); + if (rc) GOTO(exit, rc); - - cache_inode = cache_dentry.d_inode; + + cache_inode = igrab(cache_dentry->d_inode); inode = iget(dir->i_sb, cache_inode->i_ino); @@ -128,7 +77,7 @@ static int smfs_create(struct inode *dir, sm_set_inode_ops(cache_inode, inode); exit: - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); RETURN(rc); } @@ -137,8 +86,8 @@ static struct dentry *smfs_lookup(struct inode *dir, { struct inode *cache_dir; struct inode *cache_inode = NULL, *inode; - struct dentry tmp; - struct dentry cache_dentry; + struct dentry parent; + struct dentry *cache_dentry = NULL; struct dentry *rc = NULL; ENTRY; @@ -146,25 +95,25 @@ static struct dentry *smfs_lookup(struct inode *dir, cache_dir = I2CI(dir); if (!cache_dir) RETURN(ERR_PTR(-ENOENT)); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); if(cache_dir && cache_dir->i_op->lookup) - rc = cache_dir->i_op->lookup(cache_dir, &cache_dentry); + rc = cache_dir->i_op->lookup(cache_dir, cache_dentry); - if (rc || !cache_dentry.d_inode || - is_bad_inode(cache_dentry.d_inode) || - IS_ERR(cache_dentry.d_inode)) { + if (rc || !cache_dentry->d_inode || + is_bad_inode(cache_dentry->d_inode) || + IS_ERR(cache_dentry->d_inode)) { GOTO(exit, rc); } - cache_inode = cache_dentry.d_inode; + cache_inode = igrab(cache_dentry->d_inode); inode = iget(dir->i_sb, cache_inode->i_ino); d_add(dentry, inode); exit: - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); RETURN(rc); } @@ -191,10 +140,10 @@ static int smfs_link(struct dentry * old_dentry, struct inode *cache_old_inode = NULL; struct inode *cache_dir = I2CI(dir); struct inode *inode = NULL; - struct dentry cache_dentry; - struct dentry cache_old_dentry; - struct dentry tmp; - struct dentry tmp_old; + struct dentry *cache_dentry; + struct dentry *cache_old_dentry; + struct dentry parent; + struct dentry parent_old; int rc = 0; inode = old_dentry->d_inode; @@ -204,24 +153,32 @@ static int smfs_link(struct dentry * old_dentry, if (!cache_old_inode || !cache_dir) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); - prepare_parent_dentry(&tmp_old, cache_dir); - smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &dentry->d_name); - d_add(&cache_old_dentry, cache_old_inode); + prepare_parent_dentry(&parent_old, cache_dir); + cache_old_dentry = d_alloc(&parent_old, &dentry->d_name); + d_add(cache_old_dentry, cache_old_inode); if (cache_dir->i_op->link) - rc = cache_dir->i_op->link(&cache_old_dentry, cache_dir, &cache_dentry); + rc = cache_dir->i_op->link(cache_old_dentry, cache_dir, cache_dentry); - if (rc == 0) { - atomic_inc(&inode->i_count); - duplicate_inode(cache_old_dentry.d_inode, inode); - d_instantiate(dentry, inode); - } + if (rc) + GOTO(exit, rc); + + atomic_inc(&inode->i_count); + duplicate_inode(cache_old_dentry->d_inode, inode); + d_instantiate(dentry, inode); + +exit: + if (cache_dentry->d_inode) + igrab(cache_dentry->d_inode); + if (cache_old_dentry->d_inode) + igrab(cache_old_dentry->d_inode); - smfs_clear_dentry(&cache_dentry); - smfs_clear_dentry(&cache_old_dentry); + d_unalloc(cache_dentry); + d_unalloc(cache_old_dentry); + RETURN(rc); } @@ -230,24 +187,27 @@ static int smfs_unlink(struct inode * dir, { struct inode *cache_dir = I2CI(dir); struct inode *cache_inode = I2CI(dentry->d_inode); - struct dentry cache_dentry; - struct dentry tmp; + struct dentry *cache_dentry; + struct dentry parent; int rc = 0; if (!cache_dir || !cache_inode) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); - d_add(&cache_dentry, cache_inode); + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); + d_add(cache_dentry, cache_inode); if (cache_dir->i_op->unlink) - rc = cache_dir->i_op->unlink(cache_dir, &cache_dentry); + rc = cache_dir->i_op->unlink(cache_dir, cache_dentry); + - duplicate_inode(cache_dentry.d_inode, dentry->d_inode); + duplicate_inode(cache_dentry->d_inode, dentry->d_inode); duplicate_inode(cache_dir, dir); - smfs_clear_dentry(&cache_dentry); + igrab(cache_dentry->d_inode); + + d_unalloc(cache_dentry); RETURN(rc); } @@ -258,20 +218,20 @@ static int smfs_symlink (struct inode * dir, struct inode *cache_dir = I2CI(dir); struct inode *cache_inode = NULL; struct inode *inode = NULL; - struct dentry cache_dentry; - struct dentry tmp; + struct dentry *cache_dentry; + struct dentry parent; int rc = 0; if (!cache_dir) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); if (cache_dir->i_op->symlink) - rc = cache_dir->i_op->symlink(cache_dir, &cache_dentry, symname); + rc = cache_dir->i_op->symlink(cache_dir, cache_dentry, symname); - cache_inode = cache_dentry.d_inode; + cache_inode = igrab(cache_dentry->d_inode); inode = iget(dir->i_sb, cache_inode->i_ino); @@ -280,7 +240,8 @@ static int smfs_symlink (struct inode * dir, else rc = -ENOENT; - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); + RETURN(rc); } @@ -291,20 +252,20 @@ static int smfs_mkdir(struct inode * dir, struct inode *cache_dir = I2CI(dir); struct inode *cache_inode = NULL; struct inode *inode = NULL; - struct dentry cache_dentry; - struct dentry tmp; + struct dentry *cache_dentry; + struct dentry parent; int rc = 0; if (!cache_dir) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); if (cache_dir->i_op->mkdir) - rc = cache_dir->i_op->mkdir(cache_dir, &cache_dentry, mode); + rc = cache_dir->i_op->mkdir(cache_dir, cache_dentry, mode); - cache_inode = cache_dentry.d_inode; + cache_inode = igrab(cache_dentry->d_inode); inode = iget(dir->i_sb, cache_inode->i_ino); @@ -314,7 +275,7 @@ static int smfs_mkdir(struct inode * dir, d_instantiate(dentry, inode); duplicate_inode(cache_dir, dir); exit: - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); RETURN(rc); } @@ -323,24 +284,26 @@ static int smfs_rmdir(struct inode * dir, { struct inode *cache_dir = I2CI(dir); struct inode *cache_inode = I2CI(dentry->d_inode); - struct dentry cache_dentry; - struct dentry tmp; + struct dentry *cache_dentry; + struct dentry parent; int rc = 0; if (!cache_dir) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); - d_add(&cache_dentry, cache_inode); + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); + d_add(cache_dentry, cache_inode); + + igrab(cache_inode); if (cache_dir->i_op->rmdir) - rc = cache_dir->i_op->rmdir(cache_dir, &cache_dentry); + rc = cache_dir->i_op->rmdir(cache_dir, cache_dentry); duplicate_inode(cache_dir, dir); - duplicate_inode(cache_dentry.d_inode, dentry->d_inode); + duplicate_inode(cache_dentry->d_inode, dentry->d_inode); - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); RETURN(rc); } @@ -350,27 +313,30 @@ static int smfs_mknod(struct inode * dir, struct dentry *dentry, struct inode *cache_dir = I2CI(dir); struct inode *inode = NULL; struct inode *cache_inode = NULL; - struct dentry cache_dentry; - struct dentry tmp; + struct dentry *cache_dentry; + struct dentry parent; int rc = 0; if (!cache_dir) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); - + prepare_parent_dentry(&parent, cache_dir); + cache_dentry = d_alloc(&parent, &dentry->d_name); + if (cache_dir->i_op->mknod) - rc = cache_dir->i_op->mknod(cache_dir, &cache_dentry, mode, rdev); + rc = cache_dir->i_op->mknod(cache_dir, cache_dentry, mode, rdev); - if (!rc) { - cache_inode = cache_dentry.d_inode; - inode = iget(dir->i_sb, cache_inode->i_ino); - d_instantiate(dentry, inode); - duplicate_inode(cache_dir, dir); - duplicate_inode(cache_dentry.d_inode, dentry->d_inode); - } - smfs_clear_dentry(&cache_dentry); + if (cache_dentry->d_inode) + cache_inode = igrab(cache_dentry->d_inode); + if (rc) + GOTO(exit, rc); + + inode = iget(dir->i_sb, cache_inode->i_ino); + d_instantiate(dentry, inode); + duplicate_inode(cache_dir, dir); + duplicate_inode(cache_dentry->d_inode, dentry->d_inode); +exit: + d_unalloc(cache_dentry); RETURN(rc); } static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, @@ -379,33 +345,34 @@ static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode *cache_old_dir = I2CI(old_dir); struct inode *cache_new_dir = I2CI(new_dir); struct inode *cache_old_inode = I2CI(old_dentry->d_inode); - struct inode *cache_new_inode = NULL; - struct inode *new_inode = NULL; - struct dentry cache_old_dentry; - struct dentry cache_new_dentry; - struct dentry tmp_new; - struct dentry tmp_old; + struct dentry *cache_old_dentry; + struct dentry *cache_new_dentry; + struct dentry parent_new; + struct dentry parent_old; int rc = 0; if (!cache_old_dir || !cache_new_dir || !cache_old_inode) RETURN(-ENOENT); - prepare_parent_dentry(&tmp_old, cache_old_dir); - smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &old_dentry->d_name); - d_add(&cache_old_dentry, cache_old_inode); + prepare_parent_dentry(&parent_old, cache_old_dir); + cache_old_dentry = d_alloc(&parent_old, &old_dentry->d_name); + d_add(cache_old_dentry, cache_old_inode); + igrab(cache_old_inode); - prepare_parent_dentry(&tmp_new, cache_new_dir); - smfs_prepare_dentry(&cache_new_dentry, &tmp_new, &new_dentry->d_name); + prepare_parent_dentry(&parent_new, cache_new_dir); + cache_new_dentry = d_alloc(&parent_new, &new_dentry->d_name); if (cache_old_dir->i_op->rename) - rc = cache_old_dir->i_op->rename(cache_old_dir, &cache_old_dentry, - cache_new_dir, &cache_new_dentry); + rc = cache_old_dir->i_op->rename(cache_old_dir, cache_old_dentry, + cache_new_dir, cache_new_dentry); duplicate_inode(cache_old_dir, old_dir); duplicate_inode(cache_new_dir, new_dir); - smfs_clear_dentry(&cache_old_dentry); - smfs_clear_dentry(&cache_new_dentry); - + if (cache_new_dentry->d_inode) { + igrab(cache_new_dentry->d_inode); + } + d_unalloc(cache_old_dentry); + d_unalloc(cache_new_dentry); RETURN(rc); } diff --git a/lustre/smfs/inode.c b/lustre/smfs/inode.c index 24ff6c30a1dcd8847a6630cac064718798234469..ae985c37e35098319cdfa65cd6e5540e4fbcc4c9 100644 --- a/lustre/smfs/inode.c +++ b/lustre/smfs/inode.c @@ -86,7 +86,8 @@ static void smfs_clear_inode(struct inode *inode) atomic_dec(&cache_inode->i_count); } iput(cache_inode); - + + I2CI(inode) = NULL; return; } static void smfs_delete_inode(struct inode *inode) @@ -128,6 +129,7 @@ static void smfs_delete_inode(struct inode *inode) duplicate_inode(cache_inode, inode); + I2CI(inode) = NULL; return; } static void smfs_write_inode(struct inode *inode, int wait) diff --git a/lustre/smfs/symlink.c b/lustre/smfs/symlink.c index f590852581545d586754f6ebd9fc391e51b528b3..d424d938acfab8556ae59dac60d710fe34b4018f 100644 --- a/lustre/smfs/symlink.c +++ b/lustre/smfs/symlink.c @@ -16,37 +16,39 @@ static int smfs_readlink(struct dentry * dentry, char * buffer, int buflen) { struct inode *cache_inode = I2CI(dentry->d_inode); - struct dentry cache_dentry; + struct dentry *cache_dentry; int rc = 0; if (!cache_inode) RETURN(-ENOENT); - smfs_prepare_dentry(&cache_dentry, NULL, &dentry->d_name); - d_add(&cache_dentry, cache_inode); + cache_dentry = d_alloc(NULL, &dentry->d_name); + d_add(cache_dentry, cache_inode); + igrab(cache_inode); if (cache_inode->i_op && cache_inode->i_op->readlink) - rc = cache_inode->i_op->readlink(&cache_dentry, buffer, buflen); + rc = cache_inode->i_op->readlink(cache_dentry, buffer, buflen); - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); return rc; } static int smfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *cache_inode = I2CI(dentry->d_inode); - struct dentry cache_dentry; + struct dentry *cache_dentry; int rc = 0; if (!cache_inode) RETURN(-ENOENT); - smfs_prepare_dentry(&cache_dentry, NULL, &dentry->d_name); - d_add(&cache_dentry, cache_inode); + cache_dentry = d_alloc(NULL, &dentry->d_name); + d_add(cache_dentry, cache_inode); + igrab(cache_inode); if (cache_inode->i_op && cache_inode->i_op->follow_link) - rc = cache_inode->i_op->follow_link(&cache_dentry, nd); + rc = cache_inode->i_op->follow_link(cache_dentry, nd); - smfs_clear_dentry(&cache_dentry); + d_unalloc(cache_dentry); return rc; }