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.
150 lines
4.1 KiB
150 lines
4.1 KiB
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 |
|
=======================
|
|
|