diff options
Diffstat (limited to 'fs/autofs4/waitq.c')
-rw-r--r-- | fs/autofs4/waitq.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index e1fbdeef85db..9ef5b2914407 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -56,26 +56,27 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
56 | mutex_unlock(&sbi->wq_mutex); | 56 | mutex_unlock(&sbi->wq_mutex); |
57 | } | 57 | } |
58 | 58 | ||
59 | static int autofs4_write(struct file *file, const void *addr, int bytes) | 59 | static int autofs4_write(struct autofs_sb_info *sbi, |
60 | struct file *file, const void *addr, int bytes) | ||
60 | { | 61 | { |
61 | unsigned long sigpipe, flags; | 62 | unsigned long sigpipe, flags; |
62 | mm_segment_t fs; | 63 | mm_segment_t fs; |
63 | const char *data = (const char *)addr; | 64 | const char *data = (const char *)addr; |
64 | ssize_t wr = 0; | 65 | ssize_t wr = 0; |
65 | 66 | ||
66 | /** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ | ||
67 | |||
68 | sigpipe = sigismember(¤t->pending.signal, SIGPIPE); | 67 | sigpipe = sigismember(¤t->pending.signal, SIGPIPE); |
69 | 68 | ||
70 | /* Save pointer to user space and point back to kernel space */ | 69 | /* Save pointer to user space and point back to kernel space */ |
71 | fs = get_fs(); | 70 | fs = get_fs(); |
72 | set_fs(KERNEL_DS); | 71 | set_fs(KERNEL_DS); |
73 | 72 | ||
73 | mutex_lock(&sbi->pipe_mutex); | ||
74 | while (bytes && | 74 | while (bytes && |
75 | (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) { | 75 | (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) { |
76 | data += wr; | 76 | data += wr; |
77 | bytes -= wr; | 77 | bytes -= wr; |
78 | } | 78 | } |
79 | mutex_lock(&sbi->pipe_mutex); | ||
79 | 80 | ||
80 | set_fs(fs); | 81 | set_fs(fs); |
81 | 82 | ||
@@ -110,6 +111,13 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
110 | 111 | ||
111 | pkt.hdr.proto_version = sbi->version; | 112 | pkt.hdr.proto_version = sbi->version; |
112 | pkt.hdr.type = type; | 113 | pkt.hdr.type = type; |
114 | mutex_lock(&sbi->wq_mutex); | ||
115 | |||
116 | /* Check if we have become catatonic */ | ||
117 | if (sbi->catatonic) { | ||
118 | mutex_unlock(&sbi->wq_mutex); | ||
119 | return; | ||
120 | } | ||
113 | switch (type) { | 121 | switch (type) { |
114 | /* Kernel protocol v4 missing and expire packets */ | 122 | /* Kernel protocol v4 missing and expire packets */ |
115 | case autofs_ptype_missing: | 123 | case autofs_ptype_missing: |
@@ -163,22 +171,18 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
163 | } | 171 | } |
164 | default: | 172 | default: |
165 | printk("autofs4_notify_daemon: bad type %d!\n", type); | 173 | printk("autofs4_notify_daemon: bad type %d!\n", type); |
174 | mutex_unlock(&sbi->wq_mutex); | ||
166 | return; | 175 | return; |
167 | } | 176 | } |
168 | 177 | ||
169 | /* Check if we have become catatonic */ | 178 | pipe = sbi->pipe; |
170 | mutex_lock(&sbi->wq_mutex); | 179 | get_file(pipe); |
171 | if (!sbi->catatonic) { | 180 | |
172 | pipe = sbi->pipe; | ||
173 | get_file(pipe); | ||
174 | } | ||
175 | mutex_unlock(&sbi->wq_mutex); | 181 | mutex_unlock(&sbi->wq_mutex); |
176 | 182 | ||
177 | if (pipe) { | 183 | if (autofs4_write(sbi, pipe, &pkt, pktsz)) |
178 | if (autofs4_write(pipe, &pkt, pktsz)) | 184 | autofs4_catatonic_mode(sbi); |
179 | autofs4_catatonic_mode(sbi); | 185 | fput(pipe); |
180 | fput(pipe); | ||
181 | } | ||
182 | } | 186 | } |
183 | 187 | ||
184 | static int autofs4_getpath(struct autofs_sb_info *sbi, | 188 | static int autofs4_getpath(struct autofs_sb_info *sbi, |
@@ -257,6 +261,9 @@ static int validate_request(struct autofs_wait_queue **wait, | |||
257 | struct autofs_wait_queue *wq; | 261 | struct autofs_wait_queue *wq; |
258 | struct autofs_info *ino; | 262 | struct autofs_info *ino; |
259 | 263 | ||
264 | if (sbi->catatonic) | ||
265 | return -ENOENT; | ||
266 | |||
260 | /* Wait in progress, continue; */ | 267 | /* Wait in progress, continue; */ |
261 | wq = autofs4_find_wait(sbi, qstr); | 268 | wq = autofs4_find_wait(sbi, qstr); |
262 | if (wq) { | 269 | if (wq) { |
@@ -289,6 +296,9 @@ static int validate_request(struct autofs_wait_queue **wait, | |||
289 | if (mutex_lock_interruptible(&sbi->wq_mutex)) | 296 | if (mutex_lock_interruptible(&sbi->wq_mutex)) |
290 | return -EINTR; | 297 | return -EINTR; |
291 | 298 | ||
299 | if (sbi->catatonic) | ||
300 | return -ENOENT; | ||
301 | |||
292 | wq = autofs4_find_wait(sbi, qstr); | 302 | wq = autofs4_find_wait(sbi, qstr); |
293 | if (wq) { | 303 | if (wq) { |
294 | *wait = wq; | 304 | *wait = wq; |
@@ -389,7 +399,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
389 | 399 | ||
390 | ret = validate_request(&wq, sbi, &qstr, dentry, notify); | 400 | ret = validate_request(&wq, sbi, &qstr, dentry, notify); |
391 | if (ret <= 0) { | 401 | if (ret <= 0) { |
392 | if (ret == 0) | 402 | if (ret != -EINTR) |
393 | mutex_unlock(&sbi->wq_mutex); | 403 | mutex_unlock(&sbi->wq_mutex); |
394 | kfree(qstr.name); | 404 | kfree(qstr.name); |
395 | return ret; | 405 | return ret; |