diff --git a/lustre/smfs/dir.c b/lustre/smfs/dir.c index 3835509a851735e787e3a543b14eca071764bc59..02526083d1138d99cd17497f8aec3cb66ce8400e 100644 --- a/lustre/smfs/dir.c +++ b/lustre/smfs/dir.c @@ -12,15 +12,75 @@ #include "smfs_internal.h" -static void d_unalloc(struct dentry *dentry) +#define NAME_ALLOC_LEN(len) ((len+16) & ~15) + +struct dentry parent; +struct dentry cache_dentry; + +static void smfs_clear_dentry(struct dentry *dentry) { - if (dentry) { - list_del(&dentry->d_hash); - INIT_LIST_HEAD(&dentry->d_hash); - dput(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); @@ -35,15 +95,12 @@ static void prepare_parent_dentry(struct dentry *dentry, struct inode *inode) INIT_LIST_HEAD(&dentry->d_subdirs); INIT_LIST_HEAD(&dentry->d_alias); } - static int smfs_create(struct inode *dir, struct dentry *dentry, int mode) { struct inode *cache_dir; struct inode *cache_inode, *inode; - struct dentry tmp; - struct dentry *cache_dentry; int rc; ENTRY; @@ -52,18 +109,15 @@ static int smfs_create(struct inode *dir, if (!cache_dir) RETURN(-ENOENT); - prepare_parent_dentry(&tmp, cache_dir); - cache_dentry = d_alloc(&tmp, &dentry->d_name); - - if (!cache_dentry) - RETURN(-ENOENT); - - if(cache_dir && cache_dir->i_op->create) - rc = cache_dir->i_op->create(cache_dir, cache_dentry, mode); + prepare_parent_dentry(&parent, cache_dir); + smfs_prepare_dentry(&cache_dentry, &parent, &dentry->d_name); + + if (cache_dir && cache_dir->i_op->create) + rc = cache_dir->i_op->create(cache_dir, &cache_dentry, mode); if (rc) GOTO(exit, rc); - cache_inode = cache_dentry->d_inode; + cache_inode = cache_dentry.d_inode; inode = iget(dir->i_sb, cache_inode->i_ino); @@ -74,7 +128,8 @@ static int smfs_create(struct inode *dir, sm_set_inode_ops(cache_inode, inode); exit: - d_unalloc(cache_dentry); + smfs_clear_dentry(&cache_dentry); + iput(cache_inode); RETURN(rc); } @@ -84,7 +139,7 @@ static struct dentry *smfs_lookup(struct inode *dir, struct inode *cache_dir; struct inode *cache_inode, *inode; struct dentry tmp; - struct dentry *cache_dentry; + struct dentry cache_dentry; struct dentry *rc = NULL; ENTRY; @@ -93,27 +148,26 @@ static struct dentry *smfs_lookup(struct inode *dir, if (!cache_dir) RETURN(ERR_PTR(-ENOENT)); prepare_parent_dentry(&tmp, cache_dir); - cache_dentry = d_alloc(&tmp, &dentry->d_name); + smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); - if (!cache_dentry) - RETURN(ERR_PTR(-ENOENT)); - 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 = cache_dentry.d_inode; inode = iget(dir->i_sb, cache_inode->i_ino); d_add(dentry, inode); exit: - d_unalloc(cache_dentry); + smfs_clear_dentry(&cache_dentry); + iput(cache_inode); + RETURN(rc); } @@ -140,7 +194,7 @@ 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 = NULL; + struct dentry cache_dentry; struct dentry tmp; struct dentry tmp_old; int rc = 0; @@ -153,19 +207,17 @@ static int smfs_link(struct dentry * old_dentry, RETURN(-ENOENT); prepare_parent_dentry(&tmp_old, cache_old_inode); - + smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); prepare_parent_dentry(&tmp, cache_dir); - cache_dentry = d_alloc(&tmp, &dentry->d_name); if (cache_dir->i_op->link) - rc = cache_dir->i_op->link(&tmp, cache_dir, cache_dentry); + rc = cache_dir->i_op->link(&tmp, cache_dir, &cache_dentry); if (rc == 0) { d_instantiate(dentry, inode); } - d_unalloc(cache_dentry); - + smfs_clear_dentry(&cache_dentry); RETURN(rc); } static int smfs_unlink(struct inode * dir, @@ -173,7 +225,7 @@ 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 = NULL; + struct dentry cache_dentry; struct dentry tmp; int rc = 0; @@ -181,18 +233,21 @@ static int smfs_unlink(struct inode * dir, RETURN(-ENOENT); prepare_parent_dentry(&tmp, cache_dir); - cache_dentry = d_alloc(&tmp, &dentry->d_name); - d_add(cache_dentry, cache_inode); + smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); + d_add(&cache_dentry, cache_inode); + igrab(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); - d_unalloc(cache_dentry); + iput(cache_dentry.d_inode); + smfs_clear_dentry(&cache_dentry); + RETURN(rc); } static int smfs_symlink (struct inode * dir, @@ -202,7 +257,7 @@ 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 = NULL; + struct dentry cache_dentry; struct dentry tmp; int rc = 0; @@ -210,12 +265,12 @@ static int smfs_symlink (struct inode * dir, RETURN(-ENOENT); prepare_parent_dentry(&tmp, NULL); - cache_dentry = d_alloc(&tmp, &dentry->d_name); + smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); if (cache_inode->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 = cache_dentry.d_inode; inode = iget(dir->i_sb, cache_inode->i_ino); @@ -224,7 +279,7 @@ static int smfs_symlink (struct inode * dir, else rc = -ENOENT; - d_unalloc(cache_dentry); + smfs_clear_dentry(&cache_dentry); RETURN(rc); } static int smfs_mkdir(struct inode * dir, @@ -234,7 +289,7 @@ 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 = NULL; + struct dentry cache_dentry; struct dentry tmp; int rc = 0; @@ -242,12 +297,12 @@ static int smfs_mkdir(struct inode * dir, RETURN(-ENOENT); prepare_parent_dentry(&tmp, NULL); - cache_dentry = d_alloc(&tmp, &dentry->d_name); + smfs_prepare_dentry(&cache_dentry, &tmp, &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 = cache_dentry.d_inode; inode = iget(dir->i_sb, cache_inode->i_ino); @@ -257,14 +312,14 @@ static int smfs_mkdir(struct inode * dir, d_instantiate(dentry, inode); duplicate_inode(cache_dir, dir); exit: - d_unalloc(cache_dentry); + smfs_clear_dentry(&cache_dentry); RETURN(rc); } static int smfs_rmdir(struct inode * dir, struct dentry *dentry) { struct inode *cache_dir = I2CI(dir); - struct dentry *cache_dentry = NULL; + struct dentry cache_dentry; struct dentry tmp; int rc = 0; @@ -272,15 +327,15 @@ static int smfs_rmdir(struct inode * dir, RETURN(-ENOENT); prepare_parent_dentry(&tmp, NULL); - cache_dentry = d_alloc(&tmp, &dentry->d_name); + smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); 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); - d_unalloc(cache_dentry); + smfs_clear_dentry(&cache_dentry); RETURN(rc); } @@ -288,7 +343,7 @@ static int smfs_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev) { struct inode *cache_dir = I2CI(dir); - struct dentry *cache_dentry = NULL; + struct dentry cache_dentry; struct dentry tmp; int rc = 0; @@ -296,15 +351,15 @@ static int smfs_mknod(struct inode * dir, struct dentry *dentry, RETURN(-ENOENT); prepare_parent_dentry(&tmp, NULL); - cache_dentry = d_alloc(&tmp, &dentry->d_name); + smfs_prepare_dentry(&cache_dentry, &tmp, &dentry->d_name); if (cache_dir->i_op->mknod) - rc = cache_dir->i_op->mknod(cache_dir, dentry, mode, rdev); + rc = cache_dir->i_op->mknod(cache_dir, &cache_dentry, mode, rdev); duplicate_inode(cache_dir, dir); - duplicate_inode(cache_dentry->d_inode, dentry->d_inode); + duplicate_inode(cache_dentry.d_inode, dentry->d_inode); - d_unalloc(cache_dentry); + smfs_clear_dentry(&cache_dentry); RETURN(rc); } static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, @@ -315,8 +370,8 @@ static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, 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 = NULL; - struct dentry *cache_new_dentry = NULL; + struct dentry cache_old_dentry; + struct dentry cache_new_dentry; struct dentry tmp_new; struct dentry tmp_old; int rc = 0; @@ -325,17 +380,17 @@ static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, RETURN(-ENOENT); prepare_parent_dentry(&tmp_old, old_dir); - cache_old_dentry = d_alloc(&tmp_old, &old_dentry->d_name); - d_add(cache_old_dentry, cache_old_inode); + smfs_prepare_dentry(&cache_old_dentry, &tmp_old, &old_dentry->d_name); + d_add(&cache_old_dentry, cache_old_inode); prepare_parent_dentry(&tmp_new, NULL); - cache_new_dentry = d_alloc(&tmp_new, &new_dentry->d_name); + smfs_prepare_dentry(&cache_new_dentry, &tmp_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); - cache_new_inode = cache_new_dentry->d_inode; + cache_new_inode = cache_new_dentry.d_inode; new_inode = iget(new_dir->i_sb, cache_new_inode->i_ino); d_instantiate(new_dentry, new_inode); @@ -343,8 +398,8 @@ static int smfs_rename(struct inode * old_dir, struct dentry *old_dentry, duplicate_inode(cache_old_dir, old_dir); duplicate_inode(cache_new_dir, new_dir); - d_unalloc(cache_old_dentry); - d_unalloc(cache_new_dentry); + smfs_clear_dentry(&cache_old_dentry); + smfs_clear_dentry(&cache_new_dentry); RETURN(rc); }