| autofs-5.0.4 - expire specific submount only |
| |
| From: Ian Kent <raven@themaw.net> |
| |
| The submount shutdown at expire assumes that certain locks are not |
| held but when notifying submounts containing nested submounts not |
| all locks were being released. This leads to occassional deadlock |
| when child submounts attempt to shutdown. |
| |
| |
| CHANGELOG | 1 + |
| lib/master.c | 33 ++++++++------------------------- |
| 2 files changed, 9 insertions(+), 25 deletions(-) |
| |
| |
| diff --git a/CHANGELOG b/CHANGELOG |
| index 4e8209e..88ca579 100644 |
| |
| |
| @@ -1,6 +1,7 @@ |
| ??/??/2009 autofs-5.0.5 |
| ----------------------- |
| - fix dumb libxml2 check |
| +- fix nested submount expire deadlock. |
| |
| 4/11/2008 autofs-5.0.4 |
| ----------------------- |
| diff --git a/lib/master.c b/lib/master.c |
| index a243e6a..e1cc062 100644 |
| |
| |
| @@ -834,7 +834,6 @@ int master_notify_submount(struct autofs_point *ap, const char *path, enum state |
| { |
| struct list_head *head, *p; |
| struct autofs_point *this = NULL; |
| - size_t plen = strlen(path); |
| int ret = 1; |
| |
| mounts_mutex_lock(ap); |
| @@ -842,37 +841,19 @@ int master_notify_submount(struct autofs_point *ap, const char *path, enum state |
| head = &ap->submounts; |
| p = head->prev; |
| while (p != head) { |
| - size_t len; |
| - |
| this = list_entry(p, struct autofs_point, mounts); |
| p = p->prev; |
| |
| if (!master_submount_list_empty(this)) { |
| - if (!master_notify_submount(this, path, state)) { |
| - ret = 0; |
| - break; |
| - } |
| + mounts_mutex_unlock(ap); |
| + return master_notify_submount(this, path, state); |
| } |
| |
| - len = strlen(this->path); |
| - |
| - /* Initial path not the same */ |
| - if (strncmp(this->path, path, len)) |
| + /* path not the same */ |
| + if (strcmp(this->path, path)) |
| continue; |
| |
| - /* |
| - * Part of submount tree? |
| - * We must wait till we get to submount itself. |
| - * If it is tell caller by returning true. |
| - */ |
| - if (plen > len) { |
| - /* Not part of this directory tree */ |
| - if (path[len] != '/') |
| - continue; |
| - break; |
| - } |
| - |
| - /* Now we have a submount to expire */ |
| + /* Now we have found the submount we want to expire */ |
| |
| st_mutex_lock(); |
| |
| @@ -901,8 +882,10 @@ int master_notify_submount(struct autofs_point *ap, const char *path, enum state |
| struct timespec t = { 0, 300000000 }; |
| struct timespec r; |
| |
| - if (this->state != ST_SHUTDOWN) |
| + if (this->state != ST_SHUTDOWN) { |
| + ret = 0; |
| break; |
| + } |
| |
| st_mutex_unlock(); |
| mounts_mutex_unlock(ap); |