aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/connect.c37
-rw-r--r--fs/cifs/transport.c3
-rw-r--r--fs/namei.c20
-rw-r--r--fs/open.c2
-rw-r--r--fs/super.c5
6 files changed, 51 insertions, 20 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index edd5b29b53c9..17afb0fbcaed 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -188,6 +188,8 @@ struct TCP_Server_Info {
188 /* multiplexed reads or writes */ 188 /* multiplexed reads or writes */
189 unsigned int maxBuf; /* maxBuf specifies the maximum */ 189 unsigned int maxBuf; /* maxBuf specifies the maximum */
190 /* message size the server can send or receive for non-raw SMBs */ 190 /* message size the server can send or receive for non-raw SMBs */
191 /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */
192 /* when socket is setup (and during reconnect) before NegProt sent */
191 unsigned int max_rw; /* maxRw specifies the maximum */ 193 unsigned int max_rw; /* maxRw specifies the maximum */
192 /* message size the server can send or receive for */ 194 /* message size the server can send or receive for */
193 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ 195 /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
@@ -652,7 +654,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
652#define MID_REQUEST_SUBMITTED 2 654#define MID_REQUEST_SUBMITTED 2
653#define MID_RESPONSE_RECEIVED 4 655#define MID_RESPONSE_RECEIVED 4
654#define MID_RETRY_NEEDED 8 /* session closed while this request out */ 656#define MID_RETRY_NEEDED 8 /* session closed while this request out */
655#define MID_NO_RESP_NEEDED 0x10 657#define MID_RESPONSE_MALFORMED 0x10
656 658
657/* Types of response buffer returned from SendReceive2 */ 659/* Types of response buffer returned from SendReceive2 */
658#define CIFS_NO_BUFFER 0 /* Response buffer not returned */ 660#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 257b6d895e20..8d6c17ab593d 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -338,10 +338,11 @@ cifs_echo_request(struct work_struct *work)
338 struct TCP_Server_Info, echo.work); 338 struct TCP_Server_Info, echo.work);
339 339
340 /* 340 /*
341 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is done. 341 * We cannot send an echo until the NEGOTIATE_PROTOCOL request is
342 * Also, no need to ping if we got a response recently 342 * done, which is indicated by maxBuf != 0. Also, no need to ping if
343 * we got a response recently
343 */ 344 */
344 if (server->tcpStatus != CifsGood || 345 if (server->maxBuf == 0 ||
345 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) 346 time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
346 goto requeue_echo; 347 goto requeue_echo;
347 348
@@ -585,11 +586,20 @@ incomplete_rcv:
585 total_read += 4; /* account for rfc1002 hdr */ 586 total_read += 4; /* account for rfc1002 hdr */
586 587
587 dump_smb(smb_buffer, total_read); 588 dump_smb(smb_buffer, total_read);
588 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read)) { 589
590 /*
591 * We know that we received enough to get to the MID as we
592 * checked the pdu_length earlier. Now check to see
593 * if the rest of the header is OK. We borrow the length
594 * var for the rest of the loop to avoid a new stack var.
595 *
596 * 48 bytes is enough to display the header and a little bit
597 * into the payload for debugging purposes.
598 */
599 length = checkSMB(smb_buffer, smb_buffer->Mid, total_read);
600 if (length != 0)
589 cifs_dump_mem("Bad SMB: ", smb_buffer, 601 cifs_dump_mem("Bad SMB: ", smb_buffer,
590 total_read < 48 ? total_read : 48); 602 min_t(unsigned int, total_read, 48));
591 continue;
592 }
593 603
594 mid_entry = NULL; 604 mid_entry = NULL;
595 server->lstrp = jiffies; 605 server->lstrp = jiffies;
@@ -601,7 +611,8 @@ incomplete_rcv:
601 if ((mid_entry->mid == smb_buffer->Mid) && 611 if ((mid_entry->mid == smb_buffer->Mid) &&
602 (mid_entry->midState == MID_REQUEST_SUBMITTED) && 612 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
603 (mid_entry->command == smb_buffer->Command)) { 613 (mid_entry->command == smb_buffer->Command)) {
604 if (check2ndT2(smb_buffer,server->maxBuf) > 0) { 614 if (length == 0 &&
615 check2ndT2(smb_buffer, server->maxBuf) > 0) {
605 /* We have a multipart transact2 resp */ 616 /* We have a multipart transact2 resp */
606 isMultiRsp = true; 617 isMultiRsp = true;
607 if (mid_entry->resp_buf) { 618 if (mid_entry->resp_buf) {
@@ -636,7 +647,12 @@ incomplete_rcv:
636 mid_entry->resp_buf = smb_buffer; 647 mid_entry->resp_buf = smb_buffer;
637 mid_entry->largeBuf = isLargeBuf; 648 mid_entry->largeBuf = isLargeBuf;
638multi_t2_fnd: 649multi_t2_fnd:
639 mid_entry->midState = MID_RESPONSE_RECEIVED; 650 if (length == 0)
651 mid_entry->midState =
652 MID_RESPONSE_RECEIVED;
653 else
654 mid_entry->midState =
655 MID_RESPONSE_MALFORMED;
640#ifdef CONFIG_CIFS_STATS2 656#ifdef CONFIG_CIFS_STATS2
641 mid_entry->when_received = jiffies; 657 mid_entry->when_received = jiffies;
642#endif 658#endif
@@ -657,6 +673,9 @@ multi_t2_fnd:
657 else 673 else
658 smallbuf = NULL; 674 smallbuf = NULL;
659 } 675 }
676 } else if (length != 0) {
677 /* response sanity checks failed */
678 continue;
660 } else if (!is_valid_oplock_break(smb_buffer, server) && 679 } else if (!is_valid_oplock_break(smb_buffer, server) &&
661 !isMultiRsp) { 680 !isMultiRsp) {
662 cERROR(1, "No task to wake, unknown frame received! " 681 cERROR(1, "No task to wake, unknown frame received! "
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index fbc5aace54b1..46d8756f2b24 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -457,6 +457,9 @@ sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
457 case MID_RETRY_NEEDED: 457 case MID_RETRY_NEEDED:
458 rc = -EAGAIN; 458 rc = -EAGAIN;
459 break; 459 break;
460 case MID_RESPONSE_MALFORMED:
461 rc = -EIO;
462 break;
460 default: 463 default:
461 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, 464 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
462 mid->mid, mid->midState); 465 mid->mid, mid->midState);
diff --git a/fs/namei.c b/fs/namei.c
index 7d77f24d32a9..ec4b2d0190a8 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -561,10 +561,14 @@ static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd)
561 */ 561 */
562void release_open_intent(struct nameidata *nd) 562void release_open_intent(struct nameidata *nd)
563{ 563{
564 if (nd->intent.open.file->f_path.dentry == NULL) 564 struct file *file = nd->intent.open.file;
565 put_filp(nd->intent.open.file); 565
566 else 566 if (file && !IS_ERR(file)) {
567 fput(nd->intent.open.file); 567 if (file->f_path.dentry == NULL)
568 put_filp(file);
569 else
570 fput(file);
571 }
568} 572}
569 573
570/* 574/*
@@ -2265,8 +2269,6 @@ static struct file *finish_open(struct nameidata *nd,
2265 return filp; 2269 return filp;
2266 2270
2267exit: 2271exit:
2268 if (!IS_ERR(nd->intent.open.file))
2269 release_open_intent(nd);
2270 path_put(&nd->path); 2272 path_put(&nd->path);
2271 return ERR_PTR(error); 2273 return ERR_PTR(error);
2272} 2274}
@@ -2389,8 +2391,6 @@ exit_mutex_unlock:
2389exit_dput: 2391exit_dput:
2390 path_put_conditional(path, nd); 2392 path_put_conditional(path, nd);
2391exit: 2393exit:
2392 if (!IS_ERR(nd->intent.open.file))
2393 release_open_intent(nd);
2394 path_put(&nd->path); 2394 path_put(&nd->path);
2395 return ERR_PTR(error); 2395 return ERR_PTR(error);
2396} 2396}
@@ -2477,6 +2477,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
2477 } 2477 }
2478 audit_inode(pathname, nd.path.dentry); 2478 audit_inode(pathname, nd.path.dentry);
2479 filp = finish_open(&nd, open_flag, acc_mode); 2479 filp = finish_open(&nd, open_flag, acc_mode);
2480 release_open_intent(&nd);
2480 return filp; 2481 return filp;
2481 2482
2482creat: 2483creat:
@@ -2553,6 +2554,7 @@ out:
2553 path_put(&nd.root); 2554 path_put(&nd.root);
2554 if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL)) 2555 if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL))
2555 goto reval; 2556 goto reval;
2557 release_open_intent(&nd);
2556 return filp; 2558 return filp;
2557 2559
2558exit_dput: 2560exit_dput:
@@ -2560,8 +2562,6 @@ exit_dput:
2560out_path: 2562out_path:
2561 path_put(&nd.path); 2563 path_put(&nd.path);
2562out_filp: 2564out_filp:
2563 if (!IS_ERR(nd.intent.open.file))
2564 release_open_intent(&nd);
2565 filp = ERR_PTR(error); 2565 filp = ERR_PTR(error);
2566 goto out; 2566 goto out;
2567} 2567}
diff --git a/fs/open.c b/fs/open.c
index e52389e1f05b..5a2c6ebc22b5 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -790,6 +790,8 @@ struct file *nameidata_to_filp(struct nameidata *nd)
790 790
791 /* Pick up the filp from the open intent */ 791 /* Pick up the filp from the open intent */
792 filp = nd->intent.open.file; 792 filp = nd->intent.open.file;
793 nd->intent.open.file = NULL;
794
793 /* Has the filesystem initialised the file for us? */ 795 /* Has the filesystem initialised the file for us? */
794 if (filp->f_path.dentry == NULL) { 796 if (filp->f_path.dentry == NULL) {
795 path_get(&nd->path); 797 path_get(&nd->path);
diff --git a/fs/super.c b/fs/super.c
index 74e149efed81..7e9dd4cc2c01 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -177,6 +177,11 @@ void deactivate_locked_super(struct super_block *s)
177 struct file_system_type *fs = s->s_type; 177 struct file_system_type *fs = s->s_type;
178 if (atomic_dec_and_test(&s->s_active)) { 178 if (atomic_dec_and_test(&s->s_active)) {
179 fs->kill_sb(s); 179 fs->kill_sb(s);
180 /*
181 * We need to call rcu_barrier so all the delayed rcu free
182 * inodes are flushed before we release the fs module.
183 */
184 rcu_barrier();
180 put_filesystem(fs); 185 put_filesystem(fs);
181 put_super(s); 186 put_super(s);
182 } else { 187 } else {