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 e1fbdeef85d..9ef5b291440 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -56,26 +56,27 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)  	mutex_unlock(&sbi->wq_mutex);  } -static int autofs4_write(struct file *file, const void *addr, int bytes) +static int autofs4_write(struct autofs_sb_info *sbi, +			 struct file *file, const void *addr, int bytes)  {  	unsigned long sigpipe, flags;  	mm_segment_t fs;  	const char *data = (const char *)addr;  	ssize_t wr = 0; -	/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/ -  	sigpipe = sigismember(¤t->pending.signal, SIGPIPE);  	/* Save pointer to user space and point back to kernel space */  	fs = get_fs();  	set_fs(KERNEL_DS); +	mutex_lock(&sbi->pipe_mutex);  	while (bytes &&  	       (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {  		data += wr;  		bytes -= wr;  	} +	mutex_lock(&sbi->pipe_mutex);  	set_fs(fs); @@ -110,6 +111,13 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,  	pkt.hdr.proto_version = sbi->version;  	pkt.hdr.type = type; +	mutex_lock(&sbi->wq_mutex); + +	/* Check if we have become catatonic */ +	if (sbi->catatonic) { +		mutex_unlock(&sbi->wq_mutex); +		return; +	}  	switch (type) {  	/* Kernel protocol v4 missing and expire packets */  	case autofs_ptype_missing: @@ -163,22 +171,18 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,  	}  	default:  		printk("autofs4_notify_daemon: bad type %d!\n", type); +		mutex_unlock(&sbi->wq_mutex);  		return;  	} -	/* Check if we have become catatonic */ -	mutex_lock(&sbi->wq_mutex); -	if (!sbi->catatonic) { -		pipe = sbi->pipe; -		get_file(pipe); -	} +	pipe = sbi->pipe; +	get_file(pipe); +  	mutex_unlock(&sbi->wq_mutex); -	if (pipe) { -		if (autofs4_write(pipe, &pkt, pktsz)) -			autofs4_catatonic_mode(sbi); -		fput(pipe); -	} +	if (autofs4_write(sbi, pipe, &pkt, pktsz)) +		autofs4_catatonic_mode(sbi); +	fput(pipe);  }  static int autofs4_getpath(struct autofs_sb_info *sbi, @@ -257,6 +261,9 @@ static int validate_request(struct autofs_wait_queue **wait,  	struct autofs_wait_queue *wq;  	struct autofs_info *ino; +	if (sbi->catatonic) +		return -ENOENT; +  	/* Wait in progress, continue; */  	wq = autofs4_find_wait(sbi, qstr);  	if (wq) { @@ -289,6 +296,9 @@ static int validate_request(struct autofs_wait_queue **wait,  			if (mutex_lock_interruptible(&sbi->wq_mutex))  				return -EINTR; +			if (sbi->catatonic) +				return -ENOENT; +  			wq = autofs4_find_wait(sbi, qstr);  			if (wq) {  				*wait = wq; @@ -389,7 +399,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,  	ret = validate_request(&wq, sbi, &qstr, dentry, notify);  	if (ret <= 0) { -		if (ret == 0) +		if (ret != -EINTR)  			mutex_unlock(&sbi->wq_mutex);  		kfree(qstr.name);  		return ret; | 
