1 /* -*- linux-c -*- --------------------------------------------------------- * 2 * 3 * linux/fs/autofs/waitq.c 4 * 5 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved 6 * 7 * This file is part of the Linux kernel and is made available under 8 * the terms of the GNU General Public License, version 2, or at your 9 * option, any later version, incorporated herein by reference. 10 * 11 * ------------------------------------------------------------------------- */ 12 13 #include <linux/slab.h> 14 #include <linux/time.h> 15 #include <linux/signal.h> 16 #include <linux/file.h> 17 #include "autofs_i.h" 18 19 /* We make this a static variable rather than a part of the superblock; it 20 is better if we don't reassign numbers easily even across filesystems */ 21 static autofs_wqt_t autofs_next_wait_queue = 1; 22 23 /* These are the signals we allow interrupting a pending mount */ 24 #define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT)) 25 26 void autofs_catatonic_mode(struct autofs_sb_info *sbi) 27 { 28 struct autofs_wait_queue *wq, *nwq; 29 30 DPRINTK(("autofs: entering catatonic mode\n")); 31 32 sbi->catatonic = 1; 33 wq = sbi->queues; 34 sbi->queues = NULL; /* Erase all wait queues */ 35 while ( wq ) { 36 nwq = wq->next; 37 wq->status = -ENOENT; /* Magic is gone - report failure */ 38 kfree(wq->name); 39 wq->name = NULL; 40 wake_up(&wq->queue); 41 wq = nwq; 42 } 43 fput(sbi->pipe); /* Close the pipe */ 44 sbi->pipe = NULL; 45 autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ 46 } 47 48 static int autofs_write(struct file *file, const void *addr, int bytes) 49 { 50 unsigned long sigpipe, flags; 51 mm_segment_t fs; 52 const char *data = (const char *)addr; 53 ssize_t wr = 0; 54 55 /** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ 56 57 sigpipe = sigismember(¤t->pending.signal, SIGPIPE); 58 59 /* Save pointer to user space and point back to kernel space */ 60 fs = get_fs(); 61 set_fs(KERNEL_DS); 62 63 while (bytes && 64 (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) { 65 data += wr; 66 bytes -= wr; 67 } 68 69 set_fs(fs); 70 71 /* Keep the currently executing process from receiving a 72 SIGPIPE unless it was already supposed to get one */ 73 if (wr == -EPIPE && !sigpipe) { 74 spin_lock_irqsave(¤t->sighand->siglock, flags); 75 sigdelset(¤t->pending.signal, SIGPIPE); 76 recalc_sigpending(); 77 spin_unlock_irqrestore(¤t->sighand->siglock, flags); 78 } 79 80 return (bytes > 0); 81 } 82 83 static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_queue *wq) 84 { 85 struct autofs_packet_missing pkt; 86 87 DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token)); 88 autofs_say(wq->name,wq->len); 89 90 memset(&pkt,0,sizeof pkt); /* For security reasons */ 91 92 pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; 93 pkt.hdr.type = autofs_ptype_missing; 94 pkt.wait_queue_token = wq->wait_queue_token; 95 pkt.len = wq->len; 96 memcpy(pkt.name, wq->name, pkt.len); 97 pkt.name[pkt.len] = '\0'; 98 99 if ( autofs_write(sbi->pipe,&pkt,sizeof(struct autofs_packet_missing)) ) 100 autofs_catatonic_mode(sbi); 101 } 102 103 int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name) 104 { 105 struct autofs_wait_queue *wq; 106 int status; 107 108 /* In catatonic mode, we don't wait for nobody */ 109 if ( sbi->catatonic ) 110 return -ENOENT; 111 112 /* We shouldn't be able to get here, but just in case */ 113 if ( name->len > NAME_MAX ) 114 return -ENOENT; 115 116 for ( wq = sbi->queues ; wq ; wq = wq->next ) { 117 if ( wq->hash == name->hash && 118 wq->len == name->len && 119 wq->name && !memcmp(wq->name,name->name,name->len) ) 120 break; 121 } 122 123 if ( !wq ) { 124 /* Create a new wait queue */ 125 wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); 126 if ( !wq ) 127 return -ENOMEM; 128 129 wq->name = kmalloc(name->len,GFP_KERNEL); 130 if ( !wq->name ) { 131 kfree(wq); 132 return -ENOMEM; 133 } 134 wq->wait_queue_token = autofs_next_wait_queue++; 135 init_waitqueue_head(&wq->queue); 136 wq->hash = name->hash; 137 wq->len = name->len; 138 wq->status = -EINTR; /* Status return if interrupted */ 139 memcpy(wq->name, name->name, name->len); 140 wq->next = sbi->queues; 141 sbi->queues = wq; 142 143 /* autofs_notify_daemon() may block */ 144 wq->wait_ctr = 2; 145 autofs_notify_daemon(sbi,wq); 146 } else 147 wq->wait_ctr++; 148 149 /* wq->name is NULL if and only if the lock is already released */ 150 151 if ( sbi->catatonic ) { 152 /* We might have slept, so check again for catatonic mode */ 153 wq->status = -ENOENT; 154 kfree(wq->name); 155 wq->name = NULL; 156 } 157 158 if ( wq->name ) { 159 /* Block all but "shutdown" signals while waiting */ 160 sigset_t sigmask; 161 162 siginitsetinv(&sigmask, SHUTDOWN_SIGS); 163 sigprocmask(SIG_BLOCK, &sigmask, &sigmask); 164 165 interruptible_sleep_on(&wq->queue); 166 167 sigprocmask(SIG_SETMASK, &sigmask, NULL); 168 } else { 169 DPRINTK(("autofs_wait: skipped sleeping\n")); 170 } 171 172 status = wq->status; 173 174 if ( ! --wq->wait_ctr ) /* Are we the last process to need status? */ 175 kfree(wq); 176 177 return status; 178 } 179 180 181 int autofs_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_token, int status) 182 { 183 struct autofs_wait_queue *wq, **wql; 184 185 for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) { 186 if ( wq->wait_queue_token == wait_queue_token ) 187 break; 188 } 189 if ( !wq ) 190 return -EINVAL; 191 192 *wql = wq->next; /* Unlink from chain */ 193 kfree(wq->name); 194 wq->name = NULL; /* Do not wait on this queue */ 195 196 wq->status = status; 197 198 if ( ! --wq->wait_ctr ) /* Is anyone still waiting for this guy? */ 199 kfree(wq); 200 else 201 wake_up(&wq->queue); 202 203 return 0; 204 } 205 206