You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
4.1 KiB
151 lines
4.1 KiB
7 years ago
|
autofs-5.1.3 - only take master map mutex for master map update
|
||
|
|
||
|
From: Ian Kent <raven@themaw.net>
|
||
|
|
||
|
When a map read is done it's neccessary to re-initialize the lookup
|
||
|
context which requires a write lock to be taken on the master map
|
||
|
entry source. Currently a map re-read also takes the master map lock
|
||
|
which will block new lookups.
|
||
|
|
||
|
If the lookup module thinks the map has been modified it will queue
|
||
|
a map read which will take these locks.
|
||
|
|
||
|
Now, when a bind mount (or symlink) is triggered by a lookup it's
|
||
|
necessary to trigger automounts that are included in the target path
|
||
|
for the dependent path to be valid.
|
||
|
|
||
|
When the target path triggers automounts in this way and refers to the
|
||
|
same master map entry, and a map re-read is scheduled and started and
|
||
|
manages to take the master map lock before the dependent lookup gets
|
||
|
past the master map lock check, the dependent path lookup will deadlock.
|
||
|
|
||
|
But the master map lock is meant to gaurd against master map entries
|
||
|
going away during lookups so isn't really needed for map reads as long
|
||
|
as the master map lock is held during the update of the mounted
|
||
|
automounts.
|
||
|
|
||
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
||
|
---
|
||
|
CHANGELOG | 1 +
|
||
|
daemon/state.c | 3 ---
|
||
|
lib/master.c | 45 +++++++++++++++++++++++++++++++++++++--------
|
||
|
3 files changed, 38 insertions(+), 11 deletions(-)
|
||
|
|
||
|
--- autofs-5.0.7.orig/daemon/state.c
|
||
|
+++ autofs-5.0.7/daemon/state.c
|
||
|
@@ -484,12 +484,9 @@ static void *do_readmap(void *arg)
|
||
|
|
||
|
info(ap->logopt, "re-reading map for %s", ap->path);
|
||
|
|
||
|
- pthread_cleanup_push(master_mutex_lock_cleanup, NULL);
|
||
|
- master_mutex_lock();
|
||
|
status = lookup_nss_read_map(ap, NULL, now);
|
||
|
if (!status)
|
||
|
pthread_exit(NULL);
|
||
|
- pthread_cleanup_pop(1);
|
||
|
|
||
|
if (ap->type == LKP_INDIRECT) {
|
||
|
struct ioctl_ops *ops = get_ioctl_ops();
|
||
|
--- autofs-5.0.7.orig/lib/master.c
|
||
|
+++ autofs-5.0.7/lib/master.c
|
||
|
@@ -1089,6 +1089,39 @@ next:
|
||
|
free(paths);
|
||
|
}
|
||
|
|
||
|
+static void wait_for_lookups_and_lock(struct master *master)
|
||
|
+{
|
||
|
+ struct list_head *p, *head;
|
||
|
+ int status;
|
||
|
+
|
||
|
+again:
|
||
|
+ master_mutex_lock();
|
||
|
+
|
||
|
+ head = &master->mounts;
|
||
|
+ p = head->next;
|
||
|
+ while (p != head) {
|
||
|
+ struct master_mapent *this;
|
||
|
+
|
||
|
+ this = list_entry(p, struct master_mapent, list);
|
||
|
+
|
||
|
+ status = pthread_rwlock_trywrlock(&this->source_lock);
|
||
|
+ if (status) {
|
||
|
+ struct timespec t = { 0, 200000000 };
|
||
|
+ struct timespec r;
|
||
|
+
|
||
|
+ master_mutex_unlock();
|
||
|
+
|
||
|
+ while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
||
|
+ memcpy(&t, &r, sizeof(struct timespec));
|
||
|
+
|
||
|
+ goto again;
|
||
|
+ }
|
||
|
+ master_source_unlock(this);
|
||
|
+
|
||
|
+ p = p->next;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
int master_read_master(struct master *master, time_t age, int readall)
|
||
|
{
|
||
|
unsigned int logopt = master->logopt;
|
||
|
@@ -1098,7 +1131,7 @@ int master_read_master(struct master *ma
|
||
|
* We need to clear and re-populate the null map entry cache
|
||
|
* before alowing anyone else to use it.
|
||
|
*/
|
||
|
- master_mutex_lock();
|
||
|
+ wait_for_lookups_and_lock(master);
|
||
|
if (master->nc) {
|
||
|
cache_writelock(master->nc);
|
||
|
nc = master->nc;
|
||
|
@@ -1118,21 +1151,19 @@ int master_read_master(struct master *ma
|
||
|
lookup_nss_read_master(master, age);
|
||
|
cache_unlock(nc);
|
||
|
master_add_amd_mount_section_mounts(master, age);
|
||
|
- master_mutex_unlock();
|
||
|
|
||
|
if (!master->read_fail)
|
||
|
master_mount_mounts(master, age, readall);
|
||
|
else {
|
||
|
master->read_fail = 0;
|
||
|
/* HUP signal sets readall == 1 only */
|
||
|
- if (!readall)
|
||
|
+ if (!readall) {
|
||
|
+ master_mutex_unlock();
|
||
|
return 0;
|
||
|
- else
|
||
|
+ } else
|
||
|
master_mount_mounts(master, age, readall);
|
||
|
}
|
||
|
|
||
|
- master_mutex_lock();
|
||
|
-
|
||
|
if (list_empty(&master->mounts))
|
||
|
warn(logopt, "no mounts in table");
|
||
|
|
||
|
@@ -1422,7 +1453,6 @@ int master_mount_mounts(struct master *m
|
||
|
int cur_state;
|
||
|
|
||
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
||
|
- master_mutex_lock();
|
||
|
|
||
|
head = &master->mounts;
|
||
|
p = head->next;
|
||
|
@@ -1510,7 +1540,6 @@ cont:
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- master_mutex_unlock();
|
||
|
pthread_setcancelstate(cur_state, NULL);
|
||
|
|
||
|
return 1;
|
||
|
--- autofs-5.0.7.orig/CHANGELOG
|
||
|
+++ autofs-5.0.7/CHANGELOG
|
||
|
@@ -257,6 +257,7 @@
|
||
|
- fix some man page problems.
|
||
|
- allow dot in OPTIONSTR value lexer pattern.
|
||
|
- revert fix argc off by one in mount_autofs.c.
|
||
|
+- only take master map mutex for master map update.
|
||
|
|
||
|
25/07/2012 autofs-5.0.7
|
||
|
=======================
|