Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 152874 Details for
Bug 174821
autofs problem with symbolic links
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Patch to resolve race between mount and expire
autofs4-2.6.9-54.EL-lookup_expire-race.patch (text/plain), 9.17 KB, created by
Ian Kent
on 2007-04-18 07:15:33 UTC
(
hide
)
Description:
Patch to resolve race between mount and expire
Filename:
MIME Type:
Creator:
Ian Kent
Created:
2007-04-18 07:15:33 UTC
Size:
9.17 KB
patch
obsolete
>--- linux-2.6.9/fs/autofs4/autofs_i.h.lookup-expire-race 2007-04-13 15:10:17.000000000 +0800 >+++ linux-2.6.9/fs/autofs4/autofs_i.h 2007-04-13 16:29:23.000000000 +0800 >@@ -52,6 +52,8 @@ struct autofs_info { > > int flags; > >+ struct list_head rehash; >+ > struct autofs_sb_info *sbi; > unsigned long last_used; > atomic_t count; >@@ -110,6 +112,8 @@ struct autofs_sb_info { > struct semaphore wq_sem; > spinlock_t fs_lock; > struct autofs_wait_queue *queues; /* Wait queue pointer */ >+ spinlock_t rehash_lock; >+ struct list_head rehash_list; > }; > > static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) >--- linux-2.6.9/fs/autofs4/root.c.lookup-expire-race 2007-04-13 16:27:47.000000000 +0800 >+++ linux-2.6.9/fs/autofs4/root.c 2007-04-13 16:35:34.000000000 +0800 >@@ -262,7 +262,7 @@ static int try_to_fill_dentry(struct den > */ > status = d_invalidate(dentry); > if (status != -EBUSY) >- return -ENOENT; >+ return -EAGAIN; > } > > DPRINTK("dentry=%p %.*s ino=%p", >@@ -411,6 +411,15 @@ static int autofs4_revalidate(struct den > if (status == 0) > return 1; > >+ /* >+ * A status of EAGAIN here means that the dentry has gone >+ * away while waiting for an expire to complete. If we are >+ * racing with expire lookup will wait for it so this must >+ * be a revalidate and we need to send it to lookup. >+ */ >+ if (status == -EAGAIN) >+ return 0; >+ > return status; > } > >@@ -455,6 +464,15 @@ void autofs4_dentry_release(struct dentr > de->d_fsdata = NULL; > > if (inf) { >+ struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); >+ >+ if (sbi) { >+ spin_lock(&sbi->rehash_lock); >+ if (!list_empty(&inf->rehash)) >+ list_del(&inf->rehash); >+ spin_unlock(&sbi->rehash_lock); >+ } >+ > inf->dentry = NULL; > inf->inode = NULL; > >@@ -474,10 +492,80 @@ static struct dentry_operations autofs4_ > .d_release = autofs4_dentry_release, > }; > >+static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) >+{ >+ unsigned int len = name->len; >+ unsigned int hash = name->hash; >+ const unsigned char *str = name->name; >+ struct list_head *p, *head; >+ >+ spin_lock(&dcache_lock); >+ spin_lock(&sbi->rehash_lock); >+ head = &sbi->rehash_list; >+ list_for_each(p, head) { >+ struct autofs_info *ino; >+ struct dentry *dentry; >+ struct qstr *qstr; >+ >+ ino = list_entry(p, struct autofs_info, rehash); >+ dentry = ino->dentry; >+ >+ spin_lock(&dentry->d_lock); >+ >+ /* Bad luck, we've already been dentry_iput */ >+ if (!dentry->d_inode) >+ goto next; >+ >+ qstr = &dentry->d_name; >+ >+ if (dentry->d_name.hash != hash) >+ goto next; >+ if (dentry->d_parent != parent) >+ goto next; >+ >+ if (qstr->len != len) >+ goto next; >+ if (memcmp(qstr->name, str, len)) >+ goto next; >+ >+ if (d_unhashed(dentry)) { >+ struct autofs_info *ino = autofs4_dentry_ino(dentry); >+ struct inode *inode = dentry->d_inode; >+ >+ list_del_init(&ino->rehash); >+ dget(dentry); >+ /* >+ * Make the rehashed dentry negative so the VFS >+ * behaves as it should. >+ */ >+ if (inode) { >+ dentry->d_inode = NULL; >+ list_del_init(&dentry->d_alias); >+ spin_unlock(&dentry->d_lock); >+ spin_unlock(&sbi->rehash_lock); >+ spin_unlock(&dcache_lock); >+ iput(inode); >+ return dentry; >+ } >+ spin_unlock(&dentry->d_lock); >+ spin_unlock(&sbi->rehash_lock); >+ spin_unlock(&dcache_lock); >+ return dentry; >+ } >+next: >+ spin_unlock(&dentry->d_lock); >+ } >+ spin_unlock(&sbi->rehash_lock); >+ spin_unlock(&dcache_lock); >+ >+ return NULL; >+} >+ > /* Lookups in the root directory */ > static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) > { > struct autofs_sb_info *sbi; >+ struct dentry *unhashed; > int oz_mode; > struct dentry *parent = dentry->d_parent; > >@@ -494,25 +582,46 @@ static struct dentry *autofs4_lookup(str > DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", > current->pid, process_group(current), sbi->catatonic, oz_mode); > >- /* >- * Mark the dentry incomplete, but add it. This is needed so >- * that the VFS layer knows about the dentry, and we can count >- * on catching any lookups through the revalidate. >- * >- * Let all the hard work be done by the revalidate function that >- * needs to be able to do this anyway.. >- * >- * We need to do this before we release the directory semaphore. >- */ >- dentry->d_op = &autofs4_root_dentry_operations; >+ unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); >+ if (!unhashed) { >+ /* >+ * Mark the dentry incomplete, but add it. This is needed so >+ * that the VFS layer knows about the dentry, and we can count >+ * on catching any lookups through the revalidate. >+ * >+ * Let all the hard work be done by the revalidate function that >+ * needs to be able to do this anyway.. >+ * >+ * We need to do this before we release the directory semaphore. >+ */ >+ dentry->d_op = &autofs4_root_dentry_operations; >+ >+ dentry->d_fsdata = NULL; >+ d_add(dentry, NULL); >+ } else { >+ struct autofs_info *ino = autofs4_dentry_ino(unhashed); >+ DPRINTK("rehash %p with %p", dentry, unhashed); >+ /* >+ * If we are racing with expire the request might not >+ * be quite complete but the directory has been removed >+ * so it must have been successful, so just wait for it. >+ */ >+ if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { >+ DPRINTK("wait for incomplete expire %p name=%.*s", >+ unhashed, unhashed->d_name.len, >+ unhashed->d_name.name); >+ autofs4_wait(sbi, unhashed, NFY_NONE); >+ DPRINTK("request completed"); >+ } >+ d_rehash(unhashed); >+ dentry = unhashed; >+ } > > if (!oz_mode) { > spin_lock(&dentry->d_lock); > dentry->d_flags |= DCACHE_AUTOFS_PENDING; > spin_unlock(&dentry->d_lock); > } >- dentry->d_fsdata = NULL; >- d_add(dentry, NULL); > > if (dentry->d_op && dentry->d_op->d_revalidate) { > up(&dir->i_sem); >@@ -531,6 +640,8 @@ static struct dentry *autofs4_lookup(str > if (sigismember (sigset, SIGKILL) || > sigismember (sigset, SIGQUIT) || > sigismember (sigset, SIGINT)) { >+ if (unhashed) >+ dput(unhashed); > return ERR_PTR(-ERESTARTNOINTR); > } > } >@@ -547,6 +658,8 @@ static struct dentry *autofs4_lookup(str > */ > if (dentry->d_inode && d_unhashed(dentry)) { > struct dentry *new; >+ if (unhashed) >+ dput(unhashed); > /* > * In the case of replicated server entries, if a mount > * attempt fails, the daemon will remove the directory and >@@ -559,6 +672,9 @@ static struct dentry *autofs4_lookup(str > return ERR_PTR(-ENOENT); > } > >+ if (unhashed) >+ return dentry; >+ > return NULL; > } > >@@ -619,9 +735,10 @@ static int autofs4_dir_symlink(struct in > * Normal filesystems would do a "d_delete()" to tell the VFS dcache > * that the file no longer exists. However, doing that means that the > * VFS layer can turn the dentry into a negative dentry. We don't want >- * this, because since the unlink is probably the result of an expire. >- * We simply d_drop it, which allows the dentry lookup to remount it >- * if necessary. >+ * this, because the unlink is probably the result of an expire. >+ * We simply d_drop it and add it to a rehash candidates list in the >+ * super block, which allows the dentry lookup to reuse it retaining >+ * the flags, such as expire in progress, in case we're racing with expire. > * > * If a process is blocked on the dentry waiting for the expire to finish, > * it will invalidate the dentry and try to mount with a new one. >@@ -650,7 +767,12 @@ static int autofs4_dir_unlink(struct ino > > dir->i_mtime = CURRENT_TIME; > >- d_drop(dentry); >+ spin_lock(&dcache_lock); >+ spin_lock(&sbi->rehash_lock); >+ list_add(&ino->rehash, &sbi->rehash_list); >+ spin_unlock(&sbi->rehash_lock); >+ __d_drop(dentry); >+ spin_unlock(&dcache_lock); > > return 0; > } >@@ -661,6 +783,9 @@ static int autofs4_dir_rmdir(struct inod > struct autofs_info *ino = autofs4_dentry_ino(dentry); > struct autofs_info *p_ino; > >+ DPRINTK("dentry %p, removing %.*s", >+ dentry, dentry->d_name.len, dentry->d_name.name); >+ > if (!autofs4_oz_mode(sbi)) > return -EACCES; > >@@ -669,6 +794,9 @@ static int autofs4_dir_rmdir(struct inod > spin_unlock(&dcache_lock); > return -ENOTEMPTY; > } >+ spin_lock(&sbi->rehash_lock); >+ list_add(&ino->rehash, &sbi->rehash_list); >+ spin_unlock(&sbi->rehash_lock); > __d_drop(dentry); > spin_unlock(&dcache_lock); > >--- linux-2.6.9/fs/autofs4/inode.c.lookup-expire-race 2007-04-13 15:10:17.000000000 +0800 >+++ linux-2.6.9/fs/autofs4/inode.c 2007-04-13 16:29:23.000000000 +0800 >@@ -48,6 +48,8 @@ struct autofs_info *autofs4_init_ino(str > ino->dentry = NULL; > ino->size = 0; > >+ INIT_LIST_HEAD(&ino->rehash); >+ > ino->last_used = jiffies; > atomic_set(&ino->count, 0); > >@@ -162,14 +164,13 @@ void autofs4_kill_sb(struct super_block > if (!sbi) > goto out_kill_sb; > >- sb->s_fs_info = NULL; >- >- if ( !sbi->catatonic ) >+ if (!sbi->catatonic) > autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ > > /* Clean up and release dangling references */ > autofs4_force_release(sbi); > >+ sb->s_fs_info = NULL; > kfree(sbi); > > out_kill_sb: >@@ -340,6 +341,8 @@ int autofs4_fill_super(struct super_bloc > init_MUTEX(&sbi->wq_sem); > spin_lock_init(&sbi->fs_lock); > sbi->queues = NULL; >+ spin_lock_init(&sbi->rehash_lock); >+ INIT_LIST_HEAD(&sbi->rehash_list); > s->s_blocksize = 1024; > s->s_blocksize_bits = 10; > s->s_magic = AUTOFS_SUPER_MAGIC;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 174821
:
146977
|
147032
| 152874 |
161842
|
173321
|
173361