From c14cc63a63e94d490ac6517a555113c30d420db4 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 18 Jan 2011 12:06:04 +0800 Subject: [PATCH 01/11] autofs4 - fix get_next_positive_dentry() The initialization condition in fs/autofs4/expire.c:get_next_positive_dentry() appears to be incorrect. If prev == NULL I believe that root should be returned. Further down, at the current dentry check for it being simple_positive() it looks like the d_lock for dentry p should be dropped instead of dentry ret, otherwise when p is assinged to ret we end up with no lock on p and a lost lock on ret, which leads to a deadlock. Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/expire.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 3ed79d76c233..f43100b9662b 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -96,7 +96,7 @@ static struct dentry *get_next_positive_dentry(struct dentry *prev, struct dentry *p, *ret; if (prev == NULL) - return dget(prev); + return dget(root); spin_lock(&autofs4_lock); relock: @@ -133,7 +133,7 @@ again: spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED); /* Negative dentry - try next */ if (!simple_positive(ret)) { - spin_unlock(&ret->d_lock); + spin_unlock(&p->d_lock); p = ret; goto again; } From 8931221411f9ff950de8fd686dc5ab881394cb9a Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 18 Jan 2011 12:06:10 +0800 Subject: [PATCH 02/11] vfs - fix dentry ref count in do_lookup() There is a ref count problem in fs/namei.c:do_lookup(). When walking in ref-walk mode, if follow_managed() returns a fail we need to drop dentry and possibly vfsmount. Clean up properly, as we do in the other caller of follow_managed(). Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/namei.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index b753192d8c3f..7d77f24d32a9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1272,8 +1272,10 @@ done: path->mnt = mnt; path->dentry = dentry; err = follow_managed(path, nd->flags); - if (unlikely(err < 0)) + if (unlikely(err < 0)) { + path_put_conditional(path, nd); return err; + } *inode = path->dentry->d_inode; return 0; From c0bcc9d55252012805300ca01b9b7a143b4daf85 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Tue, 18 Jan 2011 12:06:15 +0800 Subject: [PATCH 03/11] autofs4 - fix debug print in autofs4_lookup() oz_mode isn't defined any more, use autofs4_oz_mode(sbi) instead. Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/root.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 1dba035fc376..427129ab5292 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -488,7 +488,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s sbi = autofs4_sbi(dir->i_sb); DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", - current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); + current->pid, task_pgrp_nr(current), sbi->catatonic, + autofs4_oz_mode(sbi)); active = autofs4_lookup_active(dentry); if (active) { From 292c5ee802e9b969b84ee671a5e3001d94230f5b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 17 Jan 2011 00:47:38 -0500 Subject: [PATCH 04/11] autofs4: keep symlink body in inode->i_private gets rid of all ->free()/->u.symlink machinery in autofs; we simply keep symlink bodies in inode->i_private and free them in ->evict_inode(). Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 5 ----- fs/autofs4/inode.c | 27 +++++++-------------------- fs/autofs4/root.c | 2 +- fs/autofs4/symlink.c | 3 +-- 4 files changed, 9 insertions(+), 28 deletions(-) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 1f016bfb42d5..99a4af8d9c83 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -91,11 +91,6 @@ struct autofs_info { mode_t mode; size_t size; - - void (*free)(struct autofs_info *); - union { - const char *symlink; - } u; }; #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 9e1a9dad23e1..cf8abc793d50 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -22,14 +22,6 @@ #include "autofs_i.h" #include -static void ino_lnkfree(struct autofs_info *ino) -{ - if (ino->u.symlink) { - kfree(ino->u.symlink); - ino->u.symlink = NULL; - } -} - struct autofs_info *autofs4_init_ino(struct autofs_info *ino, struct autofs_sb_info *sbi, mode_t mode) { @@ -60,16 +52,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, ino->sbi = sbi; - if (reinit && ino->free) - (ino->free)(ino); - - memset(&ino->u, 0, sizeof(ino->u)); - - ino->free = NULL; - - if (S_ISLNK(mode)) - ino->free = ino_lnkfree; - return ino; } @@ -79,8 +61,6 @@ void autofs4_free_ino(struct autofs_info *ino) ino->dentry->d_fsdata = NULL; ino->dentry = NULL; } - if (ino->free) - (ino->free)(ino); kfree(ino); } @@ -136,9 +116,16 @@ static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) return 0; } +static void autofs4_evict_inode(struct inode *inode) +{ + end_writeback(inode); + kfree(inode->i_private); +} + static const struct super_operations autofs4_sops = { .statfs = simple_statfs, .show_options = autofs4_show_options, + .evict_inode = autofs4_evict_inode, }; enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 427129ab5292..f47aceabf58f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -561,6 +561,7 @@ static int autofs4_dir_symlink(struct inode *dir, kfree(ino); return -ENOMEM; } + inode->i_private = cp; d_add(dentry, inode); dentry->d_fsdata = ino; @@ -570,7 +571,6 @@ static int autofs4_dir_symlink(struct inode *dir, if (p_ino && dentry->d_parent != dentry) atomic_inc(&p_ino->count); - ino->u.symlink = cp; dir->i_mtime = CURRENT_TIME; return 0; diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index b4ea82934d2e..f27c094a1919 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -14,8 +14,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) { - struct autofs_info *ino = autofs4_dentry_ino(dentry); - nd_set_link(nd, (char *)ino->u.symlink); + nd_set_link(nd, dentry->d_inode->i_private); return NULL; } From 14a2f00bde7668fe18d1c8355d26c7c96961e1f7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 17:13:33 -0500 Subject: [PATCH 05/11] autofs4: autofs4_mkroot() is not different from autofs4_init_ino() Kill it. Mind you, it's been an obfuscated call of autofs4_init_ino() ever since 2.3.99pre6-4... Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/inode.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index cf8abc793d50..7421b47b1bb9 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -215,17 +215,6 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, return (*pipefd < 0); } -static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) -{ - struct autofs_info *ino; - - ino = autofs4_init_ino(NULL, sbi, S_IFDIR | 0755); - if (!ino) - return NULL; - - return ino; -} - int autofs4_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; @@ -269,7 +258,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) /* * Get the root inode and dentry, but defer checking for errors. */ - ino = autofs4_mkroot(sbi); + ino = autofs4_init_ino(NULL, sbi, S_IFDIR | 0755); if (!ino) goto fail_free; root_inode = autofs4_get_inode(s, ino); From 09f12c03fa699ce7d030c47add60577138927d4f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 17:20:23 -0500 Subject: [PATCH 06/11] autofs4: pass mode to autofs4_get_inode() explicitly In all cases we'd set inf->mode to know value just before passing it to autofs4_get_inode(). That kills the need to store it in autofs_info and pass it to autofs_init_ino() Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 5 ++--- fs/autofs4/inode.c | 16 ++++++++-------- fs/autofs4/root.c | 10 +++++----- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 99a4af8d9c83..c6d66db67ff1 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -89,7 +89,6 @@ struct autofs_info { uid_t uid; gid_t gid; - mode_t mode; size_t size; }; @@ -170,7 +169,7 @@ static inline int autofs4_ispending(struct dentry *dentry) return 0; } -struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *); +struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *, mode_t); void autofs4_free_ino(struct autofs_info *); /* Expiration */ @@ -280,7 +279,7 @@ static inline void managed_dentry_clear_managed(struct dentry *dentry) /* Initializing function */ int autofs4_fill_super(struct super_block *, void *, int); -struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi, mode_t mode); +struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi); /* Queue management functions */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 7421b47b1bb9..6b6f43f00c46 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -23,7 +23,7 @@ #include struct autofs_info *autofs4_init_ino(struct autofs_info *ino, - struct autofs_sb_info *sbi, mode_t mode) + struct autofs_sb_info *sbi) { int reinit = 1; @@ -47,7 +47,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, ino->uid = 0; ino->gid = 0; - ino->mode = mode; ino->last_used = jiffies; ino->sbi = sbi; @@ -258,10 +257,10 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) /* * Get the root inode and dentry, but defer checking for errors. */ - ino = autofs4_init_ino(NULL, sbi, S_IFDIR | 0755); + ino = autofs4_init_ino(NULL, sbi); if (!ino) goto fail_free; - root_inode = autofs4_get_inode(s, ino); + root_inode = autofs4_get_inode(s, ino, S_IFDIR | 0755); if (!root_inode) goto fail_ino; @@ -345,14 +344,15 @@ fail_unlock: } struct inode *autofs4_get_inode(struct super_block *sb, - struct autofs_info *inf) + struct autofs_info *inf, + mode_t mode) { struct inode *inode = new_inode(sb); if (inode == NULL) return NULL; - inode->i_mode = inf->mode; + inode->i_mode = mode; if (sb->s_root) { inode->i_uid = sb->s_root->d_inode->i_uid; inode->i_gid = sb->s_root->d_inode->i_gid; @@ -360,11 +360,11 @@ struct inode *autofs4_get_inode(struct super_block *sb, inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_ino = get_next_ino(); - if (S_ISDIR(inf->mode)) { + if (S_ISDIR(mode)) { inode->i_nlink = 2; inode->i_op = &autofs4_dir_inode_operations; inode->i_fop = &autofs4_dir_operations; - } else if (S_ISLNK(inf->mode)) { + } else if (S_ISLNK(mode)) { inode->i_size = inf->size; inode->i_op = &autofs4_symlink_inode_operations; } diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index f47aceabf58f..e55dcdbeb450 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -508,7 +508,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) __managed_dentry_set_managed(dentry); - ino = autofs4_init_ino(NULL, sbi, 0555); + ino = autofs4_init_ino(NULL, sbi); if (!ino) return ERR_PTR(-ENOMEM); @@ -538,7 +538,7 @@ static int autofs4_dir_symlink(struct inode *dir, if (!autofs4_oz_mode(sbi)) return -EACCES; - ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555); + ino = autofs4_init_ino(ino, sbi); if (!ino) return -ENOMEM; @@ -554,7 +554,7 @@ static int autofs4_dir_symlink(struct inode *dir, strcpy(cp, symname); - inode = autofs4_get_inode(dir->i_sb, ino); + inode = autofs4_get_inode(dir->i_sb, ino, S_IFLNK | 0555); if (!inode) { kfree(cp); if (!dentry->d_fsdata) @@ -733,13 +733,13 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) DPRINTK("dentry %p, creating %.*s", dentry, dentry->d_name.len, dentry->d_name.name); - ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555); + ino = autofs4_init_ino(ino, sbi); if (!ino) return -ENOMEM; autofs4_del_active(dentry); - inode = autofs4_get_inode(dir->i_sb, ino); + inode = autofs4_get_inode(dir->i_sb, ino, S_IFDIR | 0555); if (!inode) { if (!dentry->d_fsdata) kfree(ino); From 0bf71d4d005176f6b6587ba64a377f9798213f21 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 17:39:15 -0500 Subject: [PATCH 07/11] autofs4: kill ->size in autofs_info It's used only to pass the length of symlink body to autofs4_get_inode() in autofs4_dir_symlink(). We can bloody well set inode->i_size in autofs4_dir_symlink() directly and be done with that. Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 2 -- fs/autofs4/inode.c | 2 -- fs/autofs4/root.c | 5 +++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index c6d66db67ff1..0925bacb5c3c 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -88,8 +88,6 @@ struct autofs_info { uid_t uid; gid_t gid; - - size_t size; }; #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 6b6f43f00c46..ac1a99ce820b 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -38,7 +38,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, if (!reinit) { ino->flags = 0; ino->dentry = NULL; - ino->size = 0; INIT_LIST_HEAD(&ino->active); ino->active_count = 0; INIT_LIST_HEAD(&ino->expiring); @@ -365,7 +364,6 @@ struct inode *autofs4_get_inode(struct super_block *sb, inode->i_op = &autofs4_dir_inode_operations; inode->i_fop = &autofs4_dir_operations; } else if (S_ISLNK(mode)) { - inode->i_size = inf->size; inode->i_op = &autofs4_symlink_inode_operations; } diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index e55dcdbeb450..1ad3c6ca9b03 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -530,6 +530,7 @@ static int autofs4_dir_symlink(struct inode *dir, struct autofs_info *ino = autofs4_dentry_ino(dentry); struct autofs_info *p_ino; struct inode *inode; + size_t size = strlen(symname); char *cp; DPRINTK("%s <- %.*s", symname, @@ -544,8 +545,7 @@ static int autofs4_dir_symlink(struct inode *dir, autofs4_del_active(dentry); - ino->size = strlen(symname); - cp = kmalloc(ino->size + 1, GFP_KERNEL); + cp = kmalloc(size + 1, GFP_KERNEL); if (!cp) { if (!dentry->d_fsdata) kfree(ino); @@ -562,6 +562,7 @@ static int autofs4_dir_symlink(struct inode *dir, return -ENOMEM; } inode->i_private = cp; + inode->i_size = size; d_add(dentry, inode); dentry->d_fsdata = ino; From 726a5e0688fd344110d8f2979d87f243a4ba1a48 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 17:43:52 -0500 Subject: [PATCH 08/11] autofs4: autofs4_get_inode() doesn't need autofs_info * argument anymore Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 2 +- fs/autofs4/inode.c | 6 ++---- fs/autofs4/root.c | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 0925bacb5c3c..8f15162f1672 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -167,7 +167,7 @@ static inline int autofs4_ispending(struct dentry *dentry) return 0; } -struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *, mode_t); +struct inode *autofs4_get_inode(struct super_block *, mode_t); void autofs4_free_ino(struct autofs_info *); /* Expiration */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index ac1a99ce820b..b3f9477c9745 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -259,7 +259,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) ino = autofs4_init_ino(NULL, sbi); if (!ino) goto fail_free; - root_inode = autofs4_get_inode(s, ino, S_IFDIR | 0755); + root_inode = autofs4_get_inode(s, S_IFDIR | 0755); if (!root_inode) goto fail_ino; @@ -342,9 +342,7 @@ fail_unlock: return -EINVAL; } -struct inode *autofs4_get_inode(struct super_block *sb, - struct autofs_info *inf, - mode_t mode) +struct inode *autofs4_get_inode(struct super_block *sb, mode_t mode) { struct inode *inode = new_inode(sb); diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 1ad3c6ca9b03..83e5379c5ade 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -554,7 +554,7 @@ static int autofs4_dir_symlink(struct inode *dir, strcpy(cp, symname); - inode = autofs4_get_inode(dir->i_sb, ino, S_IFLNK | 0555); + inode = autofs4_get_inode(dir->i_sb, S_IFLNK | 0555); if (!inode) { kfree(cp); if (!dentry->d_fsdata) @@ -740,7 +740,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) autofs4_del_active(dentry); - inode = autofs4_get_inode(dir->i_sb, ino, S_IFDIR | 0555); + inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555); if (!inode) { if (!dentry->d_fsdata) kfree(ino); From 5a37db302e698a83209eff22ca8f3fd05eb1d84b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 18:29:35 -0500 Subject: [PATCH 09/11] autofs4: mkdir and symlink always get a dentry that had passed lookup ... so ->d_fsdata will have been set up before we get there Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/root.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 83e5379c5ade..a5b93e8f49b5 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -539,18 +539,15 @@ static int autofs4_dir_symlink(struct inode *dir, if (!autofs4_oz_mode(sbi)) return -EACCES; - ino = autofs4_init_ino(ino, sbi); - if (!ino) - return -ENOMEM; + BUG_ON(!ino); + + autofs4_init_ino(ino, sbi); autofs4_del_active(dentry); cp = kmalloc(size + 1, GFP_KERNEL); - if (!cp) { - if (!dentry->d_fsdata) - kfree(ino); + if (!cp) return -ENOMEM; - } strcpy(cp, symname); @@ -565,8 +562,7 @@ static int autofs4_dir_symlink(struct inode *dir, inode->i_size = size; d_add(dentry, inode); - dentry->d_fsdata = ino; - ino->dentry = dget(dentry); + dget(dentry); atomic_inc(&ino->count); p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) @@ -734,25 +730,21 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) DPRINTK("dentry %p, creating %.*s", dentry, dentry->d_name.len, dentry->d_name.name); - ino = autofs4_init_ino(ino, sbi); - if (!ino) - return -ENOMEM; + BUG_ON(!ino); + + autofs4_init_ino(ino, sbi); autofs4_del_active(dentry); inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555); - if (!inode) { - if (!dentry->d_fsdata) - kfree(ino); + if (!inode) return -ENOMEM; - } d_add(dentry, inode); if (sbi->version < 5) autofs_set_leaf_automount_flags(dentry); - dentry->d_fsdata = ino; - ino->dentry = dget(dentry); + dget(dentry); atomic_inc(&ino->count); p_ino = autofs4_dentry_ino(dentry->d_parent); if (p_ino && dentry->d_parent != dentry) From 26e6c910670171410577c7df2aebe94cef76e150 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 18:43:40 -0500 Subject: [PATCH 10/11] autofs4: split autofs4_init_ino() split init_ino into new_ino and clean_ino; the former is what used to be init_ino(NULL, sbi), the latter is for cases where we passed non-NULL ino. Lose unused arguments. Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 3 ++- fs/autofs4/inode.c | 32 ++++++++++---------------------- fs/autofs4/root.c | 6 +++--- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 8f15162f1672..bfa0c6e542f2 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -277,7 +277,8 @@ static inline void managed_dentry_clear_managed(struct dentry *dentry) /* Initializing function */ int autofs4_fill_super(struct super_block *, void *, int); -struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info *sbi); +struct autofs_info *autofs4_new_ino(struct autofs_sb_info *); +void autofs4_clean_ino(struct autofs_info *); /* Queue management functions */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index b3f9477c9745..0df0c7c46fa2 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -22,35 +22,23 @@ #include "autofs_i.h" #include -struct autofs_info *autofs4_init_ino(struct autofs_info *ino, - struct autofs_sb_info *sbi) +struct autofs_info *autofs4_new_ino(struct autofs_sb_info *sbi) { - int reinit = 1; - - if (ino == NULL) { - reinit = 0; - ino = kmalloc(sizeof(*ino), GFP_KERNEL); - } - - if (ino == NULL) - return NULL; - - if (!reinit) { - ino->flags = 0; - ino->dentry = NULL; + struct autofs_info *ino = kzalloc(sizeof(*ino), GFP_KERNEL); + if (ino) { INIT_LIST_HEAD(&ino->active); - ino->active_count = 0; INIT_LIST_HEAD(&ino->expiring); - atomic_set(&ino->count, 0); + ino->last_used = jiffies; + ino->sbi = sbi; } + return ino; +} +void autofs4_clean_ino(struct autofs_info *ino) +{ ino->uid = 0; ino->gid = 0; ino->last_used = jiffies; - - ino->sbi = sbi; - - return ino; } void autofs4_free_ino(struct autofs_info *ino) @@ -256,7 +244,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) /* * Get the root inode and dentry, but defer checking for errors. */ - ino = autofs4_init_ino(NULL, sbi); + ino = autofs4_new_ino(sbi); if (!ino) goto fail_free; root_inode = autofs4_get_inode(s, S_IFDIR | 0755); diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index a5b93e8f49b5..f7c97c084c1f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -508,7 +508,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) __managed_dentry_set_managed(dentry); - ino = autofs4_init_ino(NULL, sbi); + ino = autofs4_new_ino(sbi); if (!ino) return ERR_PTR(-ENOMEM); @@ -541,7 +541,7 @@ static int autofs4_dir_symlink(struct inode *dir, BUG_ON(!ino); - autofs4_init_ino(ino, sbi); + autofs4_clean_ino(ino); autofs4_del_active(dentry); @@ -732,7 +732,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) BUG_ON(!ino); - autofs4_init_ino(ino, sbi); + autofs4_clean_ino(ino); autofs4_del_active(dentry); From b89b12b46211d971d75e5ca8249817bc9e11c453 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Jan 2011 21:42:32 -0500 Subject: [PATCH 11/11] autofs4: clean ->d_release() and autofs4_free_ino() up The latter is called only when both ino and dentry are about to be freed, so cleaning ->d_fsdata and ->dentry is pointless. Acked-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 1 - fs/autofs4/inode.c | 4 ---- fs/autofs4/root.c | 30 ++++++++++++++++-------------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index bfa0c6e542f2..54f923792728 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -338,5 +338,4 @@ static inline void autofs4_del_expiring(struct dentry *dentry) return; } -void autofs4_dentry_release(struct dentry *); extern void autofs4_kill_sb(struct super_block *); diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 0df0c7c46fa2..180fa2425e49 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -43,10 +43,6 @@ void autofs4_clean_ino(struct autofs_info *ino) void autofs4_free_ino(struct autofs_info *ino) { - if (ino->dentry) { - ino->dentry->d_fsdata = NULL; - ino->dentry = NULL; - } kfree(ino); } diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index f7c97c084c1f..014e7aba3b08 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -37,6 +37,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file); static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); static struct vfsmount *autofs4_d_automount(struct path *); static int autofs4_d_manage(struct dentry *, bool, bool); +static void autofs4_dentry_release(struct dentry *); const struct file_operations autofs4_root_operations = { .open = dcache_dir_open, @@ -138,25 +139,26 @@ out: return dcache_dir_open(inode, file); } -void autofs4_dentry_release(struct dentry *de) +static void autofs4_dentry_release(struct dentry *de) { - struct autofs_info *inf; + struct autofs_info *ino = autofs4_dentry_ino(de); + struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); DPRINTK("releasing %p", de); - inf = autofs4_dentry_ino(de); - if (inf) { - struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); - if (sbi) { - spin_lock(&sbi->lookup_lock); - if (!list_empty(&inf->active)) - list_del(&inf->active); - if (!list_empty(&inf->expiring)) - list_del(&inf->expiring); - spin_unlock(&sbi->lookup_lock); - } - autofs4_free_ino(inf); + if (!ino) + return; + + if (sbi) { + spin_lock(&sbi->lookup_lock); + if (!list_empty(&ino->active)) + list_del(&ino->active); + if (!list_empty(&ino->expiring)) + list_del(&ino->expiring); + spin_unlock(&sbi->lookup_lock); } + + autofs4_free_ino(ino); } static struct dentry *autofs4_lookup_active(struct dentry *dentry)