diff options
Diffstat (limited to 'fs/smbfs')
-rw-r--r-- | fs/smbfs/sock.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c index f14836199..45a0790fc 100644 --- a/fs/smbfs/sock.c +++ b/fs/smbfs/sock.c @@ -26,8 +26,6 @@ #define SMBFS_PARANOIA 1 /* #define SMBFS_DEBUG_VERBOSE 1 */ -#define _S(nr) (1<<((nr)-1)) - static int _recvfrom(struct socket *socket, unsigned char *ubuf, int size, unsigned flags) @@ -89,7 +87,7 @@ smb_data_callback(struct sock *sk, int len) struct socket *socket = sk->socket; unsigned char peek_buf[4]; int result; - unsigned long fs; + mm_segment_t fs; fs = get_fs(); set_fs(get_ds()); @@ -324,7 +322,7 @@ smb_get_length(struct socket *socket, unsigned char *header) { int result; unsigned char peek_buf[4]; - unsigned long fs; + mm_segment_t fs; re_recv: fs = get_fs(); @@ -599,8 +597,9 @@ out_error: int smb_request(struct smb_sb_info *server) { - unsigned long old_mask; - unsigned long fs; + unsigned long flags, sigpipe; + mm_segment_t fs; + sigset_t old_set; int len, result; unsigned char *buffer; @@ -619,8 +618,13 @@ smb_request(struct smb_sb_info *server) len = smb_len(buffer) + 4; pr_debug("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]); - old_mask = current->blocked; - current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); + spin_lock_irqsave(¤t->sigmask_lock, flags); + sigpipe = sigismember(¤t->signal, SIGPIPE); + old_set = current->blocked; + siginitsetinv(¤t->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP)); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); + fs = get_fs(); set_fs(get_ds()); @@ -629,9 +633,15 @@ smb_request(struct smb_sb_info *server) { result = smb_receive(server); } + /* read/write errors are handled by errno */ - current->signal &= ~_S(SIGPIPE); - current->blocked = old_mask; + spin_lock_irqsave(¤t->sigmask_lock, flags); + if (result == -EPIPE && !sigpipe) + sigdelset(¤t->signal, SIGPIPE); + current->blocked = old_set; + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); + set_fs(fs); if (result >= 0) @@ -758,8 +768,9 @@ smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, int *lrdata, unsigned char **rdata, int *lrparam, unsigned char **rparam) { - unsigned long old_mask; - unsigned long fs; + sigset_t old_set; + unsigned long flags, sigpipe; + mm_segment_t fs; int result; pr_debug("smb_trans2_request: com=%d, ld=%d, lp=%d\n", @@ -778,8 +789,13 @@ smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, if ((result = smb_dont_catch_keepalive(server)) != 0) goto bad_conn; - old_mask = current->blocked; - current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP)); + spin_lock_irqsave(¤t->sigmask_lock, flags); + sigpipe = sigismember(¤t->signal, SIGPIPE); + old_set = current->blocked; + siginitsetinv(¤t->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP)); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); + fs = get_fs(); set_fs(get_ds()); @@ -790,9 +806,15 @@ smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command, result = smb_receive_trans2(server, lrdata, rdata, lrparam, rparam); } + /* read/write errors are handled by errno */ - current->signal &= ~_S(SIGPIPE); - current->blocked = old_mask; + spin_lock_irqsave(¤t->sigmask_lock, flags); + if (result == -EPIPE && !sigpipe) + sigdelset(¤t->signal, SIGPIPE); + current->blocked = old_set; + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); + set_fs(fs); if (result >= 0) |