Handle mismatched open calls
Subsystems (2)
Hello Sachin Prabhu,
The patch 96b75d0508f8: "Handle mismatched open calls" from Mar 3, 2017, leads to the following static checker warning:
fs/cifs/cifssmb.c:1530 cifs_readv_receive() error: potential NULL dereference 'server->smallbuf'.
fs/cifs/cifssmb.c
1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1520 rdata->iov[0].iov_base, server->total_read);
1521
1522 mid->resp_buf = server->smallbuf;
1523 server->smallbuf = NULL;
^^^^^^^^^^^^^^^^^^^^^^^We set this to NULL here
1524
1525 /* how much data is in the response? */
1526 data_len = server->ops->read_data_length(buf);
1527 if (data_offset + data_len > buflen) {
1528 /* data_len is corrupt -- discard frame */
1529 rdata->result = -EIO;
1530 return cifs_readv_discard(server, mid);
^^^^^^but we need it here.
1531 } 1532 1533 length = rdata->read_into_pages(server, rdata, data_len); 1534 if (length < 0) 1535 return length;
regards,
dan carpenter
Quoted 34 lines · Dan Carpenter
Hello Sachin Prabhu,
The patch
96b75d0508f8: "Handle mismatched open calls" from Mar 3, 2017, leads to the following static checker warning:fs/cifs/cifssmb.c:1530 cifs_readv_receive() error: potential NULL dereference 'server->smallbuf'.
fs/cifs/cifssmb.c
1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", 1520 rdata->iov[0].iov_base,server->total_read); 1521
1522 mid->resp_buf =server->smallbuf;
1523 server->smallbuf = NULL; ^^^^^^^^^^^^^^^^^^^^^^^
We set this to NULL here1524
1525 /* how much data is in the response? */ 1526 data_len =server->ops->read_data_length(buf); 1527 if (data_offset+data_len> buflen) { 1528 /*data_lenis corrupt -- discard frame */ 1529 rdata->result =-EIO;
1530 returncifs_readv_discard(server, mid); ^^^^^^ but we need it here.1531 }
1532
1533 length =rdata->read_into_pages(server, rdata, data_len);
1534 if (length < 0)
1535 return length;
Quoted 2 lines
regards,
dan carpenter
Thanks Dan,
We should probably move that piece of code to the bottom of the function just before we return.
Sachin Prabhu
A message that is not in the archive (sent off-list or not yet received): [email protected]
Sachin Prabhu
Reviewed-by Pavel ShilovskyQuoted 36 lines · Sachin Prabhu
Quoted 35 lines · Dan Carpenter
Hello Sachin Prabhu,
The patch
96b75d0508f8: "Handle mismatched open calls" from Mar 3, 2017, leads to the following static checker warning:fs/cifs/cifssmb.c:1530 cifs_readv_receive() error: potential NULL dereference 'server->smallbuf'.
fs/cifs/cifssmb.c
1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", 1520 rdata->iov[0].iov_base, server-Quoted 1 line
total_read);1521
1522 mid->resp_buf =server->smallbuf;
1523 server->smallbuf = NULL;
^^^^^^^^^^^^^^^^^^^^^^^
We set this to NULL here1524
1525 /* how much data is in the response? */ 1526 data_len =server->ops->read_data_length(buf); 1527 if (data_offset+data_len> buflen) { 1528 /*data_lenis corrupt -- discard frame */ 1529 rdata->result =-EIO;
1530 returncifs_readv_discard(server, mid); ^^^^^^ but we need it here.1531 }
1532
1533 length =rdata->read_into_pages(server, rdata, data_len);
1534 if (length < 0)
1535 return length;
Quoted 5 lines
Quoted 2 lines
regards,
dan carpenterThanks Dan,
Hello Dan,
I have attached a patch which replaces the original "Handle mismatched open calls" patch from the for-next branch. Can you please run it against the static checker.
In the patch, we pass a buffer to cifs_discard_remaining_data() instead of using server->small_buf to obtain the rfc len.
Thanks
Sachin Prabhu
From 83f1e5cca033c358b98ebc53389787dfa9051934 Mon Sep 17 00:00:00 2001
From: Sachin Prabhu <[email protected]>
Date: Fri, 3 Mar 2017 15:41:38 -0800
Subject: [PATCH] Handle mismatched open calls
A signal can interrupt a SendReceive call which result in incoming responses to the call being ignored. This is a problem for calls such as open which results in the successful response being ignored. This results in an open file resource on the server.
The patch looks into responses which were cancelled after being sent and in case of successful open closes the open fids.
For this patch, the check is only done in SendReceive2()
RH-bz: 1403319
v2: Search for sess and tcon while under spinlock
v3: Allocate struct cancelled before we pick the tcon
v4: Rebase against latest upstream.
v5: Fix oops caused by async reads
v6: Pass buffer to cifs_discard_remaining_data()
--- fs/cifs/cifsglob.h | 11 ++++++++++ fs/cifs/cifsproto.h | 3 ++- fs/cifs/cifssmb.c | 11 ++++++---- fs/cifs/connect.c | 13 +++++++++-- fs/cifs/smb2misc.c | 48 ++++++++++++++++++++++++++++++++++++++++ fs/cifs/smb2ops.c | 8 +++++-- fs/cifs/smb2proto.h | 7 ++++++ fs/cifs/smb2transport.c | 58 +++++++++++++++++++++++++++++++++++++++++++++---- fs/cifs/transport.c | 3 +++ 9 files changed, 149 insertions(+), 13 deletions(-)
fs/cifs/cifsglob.h +11 -0
@@ -243,6 +243,7 @@ struct smb_version_operations {/* verify the message */ int (*check_message)(char *,unsigned int ,struct TCP_Server_Info *);bool (*is_oplock_break)(char *,struct TCP_Server_Info *); +int (*handle_cancelled_mid)(char *,struct TCP_Server_Info *);void (*downgrade_oplock)(struct TCP_Server_Info *,struct cifsInodeInfo *,bool );/* process transaction2 response */
@@ -1344,6 +1345,7 @@ struct mid_q_entry {void *callback_data;/* general purpose pointer for callback */ void *resp_buf;/* pointer to received SMB header */ int mid_state;/* wish this were enum but can not pass to wait_event */ +unsigned int mid_flags;__le16 command;/* smb command code */ bool large_buf:1; /* if valid response, is pointer to large buf */ bool multiRsp:1; /* multiple trans2 responses for one request */
@@ -1351,6 +1353,12 @@ struct mid_q_entry { bool decrypted:1; /* decrypted entry */ }; +struct close_cancelled_open { +struct cifs_fid fid; +struct cifs_tcon *tcon; +struct work_struct work; +}; +/* Make code in transport.c a little cleaner by moving update of optional stats into function below */ #ifdef CONFIG_CIFS_STATS2
@@ -1482,6 +1490,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,#define MID_RESPONSE_MALFORMED 0x10#define MID_SHUTDOWN 0x20 +/* Flags */ +#define MID_WAIT_CANCELLED 1/* Cancelled while waiting for response */ +/* Types of response buffer returned from SendReceive2 */ #define CIFS_NO_BUFFER 0/* Response buffer not returned */ #define CIFS_SMALL_BUFFER 1
fs/cifs/cifsproto.h +2 -1
@@ -79,7 +79,8 @@ extern void cifs_delete_mid(struct mid_q_entry *mid);extern void cifs_wake_up_task (struct mid_q_entry *mid);extern int cifs_handle_standard (struct TCP_Server_Info *server,struct mid_q_entry *mid); -extern int cifs_discard_remaining_data (struct TCP_Server_Info *server); +extern int cifs_discard_remaining_data (struct TCP_Server_Info *server, +char *buf); extern int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, mid_receive_t *receive, mid_callback_t *callback,
fs/cifs/cifssmb.c +7 -4
@@ -1400,9 +1400,9 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,* current bigbuf. */ int -cifs_discard_remaining_data (struct TCP_Server_Info *server) +cifs_discard_remaining_data (struct TCP_Server_Info *server,char *buf) { -unsigned int rfclen =get_rfc1002_length (server->smallbuf); +unsigned int rfclen =get_rfc1002_length (buf);int remaining = rfclen +4 - server->total_read;while (remaining >0 ) {
@@ -1426,7 +1426,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)int length;struct cifs_readdata *rdata = mid->callback_data; - length =cifs_discard_remaining_data (server); + length =cifs_discard_remaining_data (server, mid->resp_buf);dequeue_mid (mid, rdata->result);return length; }
@@ -1459,7 +1459,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)if (server->ops->is_status_pending && server->ops->is_status_pending (buf, server,0 )) { -cifs_discard_remaining_data (server); +cifs_discard_remaining_data (server, buf);return -1 ; }
@@ -1519,6 +1519,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)cifs_dbg (FYI ,"0: iov_base=%p iov_len=%u\n" , rdata->iov[0 ].iov_base, server->total_read); + mid->resp_buf = server->smallbuf; + server->smallbuf =NULL ; +/* how much data is in the response? */ data_len = server->ops->read_data_length (buf);if (data_offset + data_len > buflen) {
fs/cifs/connect.c +11 -2
@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p) server->lstrp = jiffies;if (mid_entry !=NULL ) { +if ((mid_entry->mid_flags &MID_WAIT_CANCELLED ) && + mid_entry->mid_state ==MID_RESPONSE_RECEIVED && + (server->ops->handle_cancelled_mid)) + server->ops->handle_cancelled_mid ( + mid_entry->resp_buf, + server); +if (!mid_entry->multiRsp || mid_entry->multiEnd) mid_entry->callback (mid_entry); - }else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break (buf, server)) { + }else if (server->ops->is_oplock_break && + server->ops->is_oplock_break (buf, server)) { +cifs_dbg (FYI ,"Received oplock break\n" ); + }else {cifs_dbg (VFS ,"No task to wake, unknown frame received! NumMids %d\n" ,atomic_read (&midCount)); cifs_dump_mem("Received Data is: ", buf,
fs/cifs/smb2misc.c +48 -0
51 lines not on this page · raw message
fs/cifs/smb2ops.c +6 -2
@@ -2195,7 +2195,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)if (rc) goto free_pages; - rc =cifs_discard_remaining_data (server); + rc =cifs_discard_remaining_data (server, buf);if (rc) goto free_pages;
@@ -2221,7 +2221,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)kfree (pages);return rc; discard_data: -cifs_discard_remaining_data (server); +cifs_discard_remaining_data (server, buf); goto free_pages; }
@@ -2329,6 +2329,7 @@ struct smb_version_operations smb20_operations = { .clear_stats = smb2_clear_stats, .print_stats = smb2_print_stats, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
@@ -2411,6 +2412,7 @@ struct smb_version_operations smb21_operations = { .clear_stats = smb2_clear_stats, .print_stats = smb2_print_stats, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
@@ -2495,6 +2497,7 @@ struct smb_version_operations smb30_operations = { .print_stats = smb2_print_stats, .dump_share_caps = smb2_dump_share_caps, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
@@ -2589,6 +2592,7 @@ struct smb_version_operations smb311_operations = { .print_stats = smb2_print_stats, .dump_share_caps = smb2_dump_share_caps, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
fs/cifs/smb2proto.h +7 -0
@@ -48,6 +48,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst);extern struct mid_q_entry *smb2_setup_async_request (struct TCP_Server_Info *server,struct smb_rqst *rqst); +extern struct cifs_ses *smb2_find_smb_ses (struct TCP_Server_Info *server, +__u64 ses_id); +extern struct cifs_tcon *smb2_find_smb_tcon (struct TCP_Server_Info *server, +__u64 ses_id,__u32 tid);extern int smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server); extern int smb3_calc_signature(struct smb_rqst *rqst,
@@ -164,6 +168,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,extern int SMB2_oplock_break (const unsigned int xid,struct cifs_tcon *tcon,const u64 persistent_fid,const u64 volatile_fid,const __u8 oplock_level); +extern int smb2_handle_cancelled_mid (char *buffer, +struct TCP_Server_Info *server); +void smb2_cancelled_close_fid (struct work_struct *work);extern int SMB2_QFS_info (const unsigned int xid,struct cifs_tcon *tcon,u64 persistent_file_id,u64 volatile_file_id,struct kstatfs *FSData);
fs/cifs/smb2transport.c +54 -4
83 lines not on this page · raw message
fs/cifs/transport.c +3 -0
@@ -752,9 +752,12 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, rc =wait_for_response (ses->server, midQ);if (rc !=0 ) { +cifs_dbg (FYI ,"Cancelling wait for mid %lu\n" , + (unsigned long )midQ->mid);send_cancel (ses->server, rqst, midQ);spin_lock (&GlobalMid_Lock);if (midQ->mid_state ==MID_REQUEST_SUBMITTED ) { + midQ->mid_flags |=MID_WAIT_CANCELLED ; midQ->callback = DeleteMidQEntry;spin_unlock (&GlobalMid_Lock);add_credits (ses->server,1 , optype);
Signature · 1 line
2.9.3
A message that is not in the archive (sent off-list or not yet received): [email protected]
Steve French
Appliedmerged into cifs-2-6.git - let me know if you see any problems with these ASAP
Quoted 54 lines · Sachin Prabhu
Quoted 36 lines · Sachin Prabhu
Quoted 35 lines · Dan Carpenter
Hello Sachin Prabhu,
The patch
96b75d0508f8: "Handle mismatched open calls" from Mar 3, 2017, leads to the following static checker warning:fs/cifs/cifssmb.c:1530 cifs_readv_receive() error: potential NULL dereference 'server->smallbuf'.
fs/cifs/cifssmb.c
1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
1520 rdata->iov[0].iov_base, server-Quoted 1 line
total_read);1521
1522mid->resp_buf=server->smallbuf;1523 server->smallbuf = NULL; ^^^^^^^^^^^^^^^^^^^^^^^We set this to NULL here
1524
1525 /* how much data is in the response? */ 1526 data_len = server->ops->read_data_length(buf); 1527 if (data_offset + data_len > buflen) { 1528 /* data_len is corrupt -- discard frame */ 1529 rdata->result = -EIO; 1530 return cifs_readv_discard(server, mid); ^^^^^^but we need it here.
1531 }
1532
1533 length = rdata->read_into_pages(server, rdata,data_len);
1534 if (length < 0)
1535 return length;Quoted 5 lines
Quoted 2 lines
regards,
dan carpenterThanks Dan,
Hello Dan,
I have attached a patch which replaces the original "Handle mismatched open calls" patch from the for-next branch. Can you please run it against the static checker.
In the patch, we pass a buffer to
cifs_discard_remaining_data()instead of usingserver->small_bufto obtain the rfc len.Thanks
Sachin Prabhu
Signature · 3 lines
Thanks, Steve
Sure, that takes care of the static checker warning. But then I had all sorts of style nits to whinge-bucket about which you didn't ask for...
fs/cifs/connect.c cifs_demultiplex_thread(void *p) · line 909
Quoted 11 lines · Sachin Prabhu
fs/cifs/connect.c +3
-0@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p) server->lstrp = jiffies;if (mid_entry !=NULL ) { +if ((mid_entry->mid_flags &MID_WAIT_CANCELLED ) && + mid_entry->mid_state ==MID_RESPONSE_RECEIVED && + (server->ops->handle_cancelled_mid))
Extra parens are not required. Please align it like this:
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && mid_entry->mid_state == MID_RESPONSE_RECEIVED && server->ops->handle_cancelled_mid)
Quoted 24 lines
fs/cifs/connect.c +8
-2+ server->ops->handle_cancelled_mid ( + mid_entry->resp_buf, + server); +if (!mid_entry->multiRsp || mid_entry->multiEnd) mid_entry->callback (mid_entry); - }else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break (buf, server)) { + }else if (server->ops->is_oplock_break && + server->ops->is_oplock_break (buf, server)) { +cifs_dbg (FYI ,"Received oplock break\n" ); + }else {cifs_dbg (VFS ,"No task to wake, unknown frame received! NumMids %d\n" ,atomic_read (&midCount)); cifs_dump_mem("Received Data is: ", buf,fs/cifs/smb2misc.c +1
-0@@ -659,3 +659,51 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)cifs_dbg (FYI ,"Can not process oplock break for non-existent connection\n" );return false; } +
fs/cifs/smb2misc.c smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) · line 672
Quoted 10 lines
fs/cifs/smb2misc.c +10
-0+void +smb2_cancelled_close_fid (struct work_struct *work) +{ +struct close_cancelled_open *cancelled =container_of (work, + struct close_cancelled_open, work); + +cifs_dbg (VFS ,"Close unmatched open\n" ); + +SMB2_close (0 , cancelled->tcon, cancelled->fid.persistent_fid, + cancelled->fid.volatile_fid);
Don't right align it. Do it like this:
SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, cancelled->fid.volatile_fid);
Quoted 4 lines
fs/cifs/smb2misc.c +4
-0+cifs_put_tcon (cancelled->tcon); +kfree (cancelled); +} +
fs/cifs/smb2misc.c smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) · line 686
Quoted 10 lines
fs/cifs/smb2misc.c +10
-0+int +smb2_handle_cancelled_mid (char *buffer,struct TCP_Server_Info *server) +{ +struct smb2_sync_hdr *sync_hdr =get_sync_hdr (buffer); +struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; +struct cifs_tcon *tcon; +struct close_cancelled_open *cancelled; + +if ((sync_hdr->Command !=SMB2_CREATE ) || + (sync_hdr->Status !=STATUS_SUCCESS ))
No need for extra parens. Align it like this:
if (sync_hdr->Command != SMB2_CREATE || sync_hdr->Status != STATUS_SUCCESS) return 0;
fs/cifs/smb2misc.c smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) · line 691
Quoted 5 lines
fs/cifs/smb2misc.c +5
-0+return 0 ; + + cancelled = (struct close_cancelled_open *) +kzalloc (sizeof (struct close_cancelled_open ), +GFP_KERNEL );
No need to cast kzalloc. Use sizeof(*cancelled).
cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
Quoted 18 lines
fs/cifs/smb2misc.c +18
-0+if (!cancelled) +return -ENOMEM ; + + tcon =smb2_find_smb_tcon (server, sync_hdr->SessionId, + sync_hdr->TreeId); +if (!tcon) { +kfree (cancelled); +return -ENOENT ; + } + + cancelled->fid.persistent_fid = rsp->PersistentFileId; + cancelled->fid.volatile_fid = rsp->VolatileFileId; + cancelled->tcon = tcon; +INIT_WORK (&cancelled->work, smb2_cancelled_close_fid); +queue_work (cifsiod_wq, &cancelled->work); + +return 0 ; +}
[ snip ]
fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct TCP_Server_Info *server) · line 119
Quoted 12 lines
fs/cifs/smb2transport.c +2
-2@@ -115,23 +115,72 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)return 0 ; } -struct cifs_ses * -smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +static struct cifs_ses * +_smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id)
Could you name this "locked" or something and get rid of the _ underscore prefix?
Quoted 18 lines
fs/cifs/smb2transport.c +8
-2{struct cifs_ses *ses; -spin_lock (&cifs_tcp_ses_lock);list_for_each_entry (ses, &server->smb_ses_list, smb_ses_list) {if (ses->Suid != ses_id)continue ; -spin_unlock (&cifs_tcp_ses_lock);return ses; } + +return NULL ; +} + +struct cifs_ses * +smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +{ +struct cifs_ses *ses;
fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct TCP_Server_Info *server) · line 145
Quoted 10 lines
fs/cifs/smb2transport.c +8
-0+ +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id);spin_unlock (&cifs_tcp_ses_lock); +return ses; +} + +static struct cifs_tcon * +_smb2_find_smb_sess_tcon (struct cifs_ses *ses,__u32 tid)
Just leave out the _ underscore prefix. This is a static function so there aren't that many users and they presumably know the locking rules. For smb2_find_smb_ses we have a locked and unlocked version of the function so it makes sense to put that in the name but here there is no need I think.
fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct TCP_Server_Info *server) · line 151
Quoted 6 lines
fs/cifs/smb2transport.c +6
-0+{ +struct list_head *tmp; +struct cifs_tcon *tcon; + +list_for_each (tmp, &ses->tcon_list) { + tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
list_for_each_entry()?
Quoted 36 lines
fs/cifs/smb2transport.c +29
-0+if (tcon->tid != tid) +continue ; + ++tcon->tc_count; +return tcon; + } +return NULL ; } +/* +* Obtain tcon corresponding to the tid in the given +* cifs_ses +*/ + +struct cifs_tcon * +smb2_find_smb_tcon (struct TCP_Server_Info *server,__u64 ses_id,__u32 tid) +{ +struct cifs_ses *ses; +struct cifs_tcon *tcon; + +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id); +if (!ses) { +spin_unlock (&cifs_tcp_ses_lock); +return NULL ; + } + tcon =_smb2_find_smb_sess_tcon (ses, tid); +spin_unlock (&cifs_tcp_ses_lock); + +return tcon; +} +int smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server) {
fs/cifs/smb2transport.c smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr, · line 563
Quoted 4 lines
fs/cifs/smb2transport.c +1
-0@@ -511,6 +560,7 @@ smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,atomic_inc (&midCount); temp->mid_state =MID_REQUEST_ALLOCATED ; + temp->mid_flags =0 ;
No need. We already memset() this to zero.
fs/cifs/transport.c cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, · line 756
Quoted 13 lines
fs/cifs/smb2transport.c +0
-0return temp; }fs/cifs/transport.c +2
-0@@ -752,9 +752,12 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, rc =wait_for_response (ses->server, midQ);if (rc !=0 ) { +cifs_dbg (FYI ,"Cancelling wait for mid %lu\n" , + (unsigned long )midQ->mid);
->mid is u64. Just do this:
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
fs/cifs/transport.c cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, · line 763
Quoted 7 lines
fs/cifs/transport.c +1
-0send_cancel (ses->server, rqst, midQ);spin_lock (&GlobalMid_Lock);if (midQ->mid_state ==MID_REQUEST_SUBMITTED ) { + midQ->mid_flags |=MID_WAIT_CANCELLED ; midQ->callback = DeleteMidQEntry;spin_unlock (&GlobalMid_Lock);add_credits (ses->server,1 , optype);
regards,
dan carpenter
Sachin Prabhu
Reviewed-by Pavel ShilovskyQuoted 4 lines · Dan Carpenter
Sure, that takes care of the static checker warning. But then I had all sorts of style nits to whinge-bucket about which you didn't ask for...
Thanks Dan,
I have incorporated all the requested changes into version 7 of the patch.
Is smatch the only tool you use for static analysis? I am considering adding it to my own dev process.
Steve, Can you please use this version instead.
Regards,
Sachin Prabhu
Quoted 268 lines · Sachin Prabhu
Quoted 13 lines
fs/cifs/connect.c +0
-0@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p)
server->lstrp= jiffies;
if (mid_entry!= NULL) {fs/cifs/connect.c +1
-0+ if ((mid_entry->mid_flags &
MID_WAIT_CANCELLED) &&fs/cifs/connect.c +1
-0+ mid_entry->mid_state ==
MID_RESPONSE_RECEIVED&&fs/cifs/connect.c +1
-0+ (server->ops-Quoted 1 line
Quoted 1 line
handle_cancelled_mid))Extra parens are not required. Please align it like this:
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && mid_entry->mid_state == MID_RESPONSE_RECEIVED && server->ops->handle_cancelled_mid)Quoted 44 lines
fs/cifs/connect.c +2
-0+ server->ops->handle_cancelled_mid( + mid_entry-Quoted 1 line
resp_buf,fs/cifs/connect.c +2
-0+ server); +if (!mid_entry->multiRsp || mid_entry-
Quoted 1 line
multiEnd)
mid_entry->callback(mid_entry);fs/cifs/connect.c +0
-2- } else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break(buf,server)) {
fs/cifs/connect.c +2
-0+ } else if (server->ops->is_oplock_break && + server->ops->is_oplock_break(buf,server)) {
fs/cifs/connect.c +2
-0+cifs_dbg (FYI ,"Received oplock break\n" ); + }else {
cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", atomic_read(&midCount)); cifs_dump_mem("Received Data is: ", buf,fs/cifs/smb2misc.c +0
-0@@ -659,3 +659,51 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg(FYI, "Can not process oplock break for non- existent connection\n");
return false;
}fs/cifs/smb2misc.c +5
-0+ +void +smb2_cancelled_close_fid (struct work_struct *work) +{ + struct close_cancelled_open *cancelled =container_of(work,
fs/cifs/smb2misc.c +1
-0+ struct
close_cancelled_open, work);fs/cifs/smb2misc.c +4
-0+ +cifs_dbg (VFS ,"Close unmatched open\n" ); + + SMB2_close(0, cancelled->tcon, cancelled-Quoted 1 line
fid.persistent_fid,
fs/cifs/smb2misc.c +1
-0+ cancelled-Quoted 1 line
Quoted 1 line
fid.volatile_fid);
Don't right align it. Do it like this:
SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, cancelled->fid.volatile_fid);Quoted 11 lines
fs/cifs/smb2misc.c +6
-0+cifs_put_tcon (cancelled->tcon); +kfree (cancelled); +} + +int +smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info*server)
fs/cifs/smb2misc.c +3
-0+{ +struct smb2_sync_hdr *sync_hdr =get_sync_hdr (buffer); + struct smb2_create_rsp *rsp = (struct smb2_create_rsp*)buffer;
fs/cifs/smb2misc.c
Quoted 5 lines
fs/cifs/smb2misc.c +5
-0+struct cifs_tcon *tcon; +struct close_cancelled_open *cancelled; + +if ((sync_hdr->Command !=SMB2_CREATE ) || + (sync_hdr->Status !=STATUS_SUCCESS ))No need for extra parens. Align it like this:
if (sync_hdr->Command != SMB2_CREATE || sync_hdr->Status != STATUS_SUCCESS) return 0;fs/cifs/smb2misc.c
Quoted 6 lines
fs/cifs/smb2misc.c +4
-0+return 0 ; + + cancelled = (struct close_cancelled_open *) + kzalloc(sizeof(struct
close_cancelled_open),fs/cifs/smb2misc.c +1
-0+ GFP_KERNEL);No need to cast kzalloc. Use
sizeof(*cancelled).cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);Quoted 18 lines
fs/cifs/smb2misc.c +18
-0+if (!cancelled) +return -ENOMEM ; + + tcon =smb2_find_smb_tcon (server, sync_hdr->SessionId, + sync_hdr->TreeId); +if (!tcon) { +kfree (cancelled); +return -ENOENT ; + } + + cancelled->fid.persistent_fid = rsp->PersistentFileId; + cancelled->fid.volatile_fid = rsp->VolatileFileId; + cancelled->tcon = tcon; +INIT_WORK (&cancelled->work, smb2_cancelled_close_fid); +queue_work (cifsiod_wq, &cancelled->work); + +return 0 ; +}[ snip ]
fs/cifs/smb2transport.c
Quoted 13 lines
fs/cifs/smb2transport.c +0
-0@@ -115,23 +115,72 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) return 0; }fs/cifs/smb2transport.c +2
-2-struct cifs_ses * -smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +static struct cifs_ses * +_smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id)Could you name this "locked" or something and get rid of the _ underscore prefix?
Quoted 24 lines
{
structcifs_ses*ses;fs/cifs/smb2transport.c +0
-1-spin_lock (&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list){
if (ses->Suid!=ses_id) continue;fs/cifs/smb2transport.c +0
-1-spin_unlock (&cifs_tcp_ses_lock);return ses;
}fs/cifs/smb2transport.c +11
-0+ +return NULL ; +} + +struct cifs_ses * +smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +{ +struct cifs_ses *ses; + +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id);
spin_unlock(&cifs_tcp_ses_lock);fs/cifs/smb2transport.c
Quoted 5 lines
fs/cifs/smb2transport.c +5
-0+return ses; +} + +static struct cifs_tcon * +_smb2_find_smb_sess_tcon(struct cifs_ses *ses, __u32 tid)Just leave out the _ underscore prefix. This is a static function so there aren't that many users and they presumably know the locking rules.
Forsmb2_find_smb_seswe have a locked and unlocked version of the function so it makes sense to put that in the name but here there is no need I think.Quoted 7 lines
fs/cifs/smb2transport.c +6
-0+{ +struct list_head *tmp; +struct cifs_tcon *tcon; + +list_for_each (tmp, &ses->tcon_list) { + tcon = list_entry(tmp, struct cifs_tcon,
tcon_list);
list_for_each_entry()?Quoted 42 lines
fs/cifs/smb2transport.c +6
-0+if (tcon->tid != tid) +continue ; + ++tcon->tc_count; +return tcon; + } +return NULL;
}fs/cifs/smb2transport.c +7
-0+/* +* Obtain tcon corresponding to the tid in the given +* cifs_ses +*/ + +struct cifs_tcon * +smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id,__u32 tid)
fs/cifs/smb2transport.c +16
-0+{ +struct cifs_ses *ses; +struct cifs_tcon *tcon; + +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id); +if (!ses) { +spin_unlock (&cifs_tcp_ses_lock); +return NULL ; + } + tcon =_smb2_find_smb_sess_tcon (ses, tid); +spin_unlock (&cifs_tcp_ses_lock); + +return tcon; +} +int
smb2_calc_signature(structsmb_rqst*rqst, structTCP_Server_Info*server)
{fs/cifs/smb2transport.c +0
-0@@ -511,6 +560,7 @@ smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
atomic_inc(&midCount);
temp->mid_state=MID_REQUEST_ALLOCATED;fs/cifs/smb2transport.c
Quoted 1 line
fs/cifs/smb2transport.c +1
-0+ temp->mid_flags =0 ;No need. We already
memset()this to zero.Quoted 12 lines
return temp;
}fs/cifs/transport.c +0
-0@@ -752,9 +752,12 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
rc =wait_for_response(ses->server, midQ); if (rc != 0) {fs/cifs/transport.c
Quoted 2 lines
fs/cifs/transport.c +2
-0+cifs_dbg (FYI ,"Cancelling wait for mid %lu\n" , + (unsigned long )midQ->mid);->mid is u64. Just do this:
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ-
Quoted 1 line
mid);
Quoted 15 lines
Quoted 7 lines
send_cancel(ses->server, rqst, midQ);spin_lock(&GlobalMid_Lock);
if (midQ->mid_state==MID_REQUEST_SUBMITTED) {fs/cifs/transport.c +1
-0+ midQ->mid_flags |=MID_WAIT_CANCELLED ;
midQ->callback= DeleteMidQEntry;spin_unlock(&GlobalMid_Lock);add_credits(ses->server, 1, optype);regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
From 198b9b9ae1b77d1d79cf72a947d0ee899baa34b4 Mon Sep 17 00:00:00 2001
From: Sachin Prabhu <[email protected]>
Date: Fri, 3 Mar 2017 15:41:38 -0800
Subject: [PATCH] [v7]Handle mismatched open calls
A signal can interrupt a SendReceive call which result in incoming responses to the call being ignored. This is a problem for calls such as open which results in the successful response being ignored. This results in an open file resource on the server.
The patch looks into responses which were cancelled after being sent and in case of successful open closes the open fids.
For this patch, the check is only done in SendReceive2()
RH-bz: 1403319
--- fs/cifs/cifsglob.h | 11 ++++++++++ fs/cifs/cifsproto.h | 3 ++- fs/cifs/cifssmb.c | 11 ++++++---- fs/cifs/connect.c | 13 ++++++++++-- fs/cifs/smb2misc.c | 46 +++++++++++++++++++++++++++++++++++++++++ fs/cifs/smb2ops.c | 8 +++++-- fs/cifs/smb2proto.h | 7 +++++++ fs/cifs/smb2transport.c | 55 +++++++++++++++++++++++++++++++++++++++++++++---- fs/cifs/transport.c | 2 ++ 9 files changed, 143 insertions(+), 13 deletions(-)
fs/cifs/cifsglob.h +11 -0
@@ -243,6 +243,7 @@ struct smb_version_operations {/* verify the message */ int (*check_message)(char *,unsigned int ,struct TCP_Server_Info *);bool (*is_oplock_break)(char *,struct TCP_Server_Info *); +int (*handle_cancelled_mid)(char *,struct TCP_Server_Info *);void (*downgrade_oplock)(struct TCP_Server_Info *,struct cifsInodeInfo *,bool );/* process transaction2 response */
@@ -1344,6 +1345,7 @@ struct mid_q_entry {void *callback_data;/* general purpose pointer for callback */ void *resp_buf;/* pointer to received SMB header */ int mid_state;/* wish this were enum but can not pass to wait_event */ +unsigned int mid_flags;__le16 command;/* smb command code */ bool large_buf:1; /* if valid response, is pointer to large buf */ bool multiRsp:1; /* multiple trans2 responses for one request */
@@ -1351,6 +1353,12 @@ struct mid_q_entry { bool decrypted:1; /* decrypted entry */ }; +struct close_cancelled_open { +struct cifs_fid fid; +struct cifs_tcon *tcon; +struct work_struct work; +}; +/* Make code in transport.c a little cleaner by moving update of optional stats into function below */ #ifdef CONFIG_CIFS_STATS2
@@ -1482,6 +1490,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,#define MID_RESPONSE_MALFORMED 0x10#define MID_SHUTDOWN 0x20 +/* Flags */ +#define MID_WAIT_CANCELLED 1/* Cancelled while waiting for response */ +/* Types of response buffer returned from SendReceive2 */ #define CIFS_NO_BUFFER 0/* Response buffer not returned */ #define CIFS_SMALL_BUFFER 1
fs/cifs/cifsproto.h +2 -1
@@ -79,7 +79,8 @@ extern void cifs_delete_mid(struct mid_q_entry *mid);extern void cifs_wake_up_task (struct mid_q_entry *mid);extern int cifs_handle_standard (struct TCP_Server_Info *server,struct mid_q_entry *mid); -extern int cifs_discard_remaining_data (struct TCP_Server_Info *server); +extern int cifs_discard_remaining_data (struct TCP_Server_Info *server, +char *buf); extern int cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst, mid_receive_t *receive, mid_callback_t *callback,
fs/cifs/cifssmb.c +7 -4
@@ -1400,9 +1400,9 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,* current bigbuf. */ int -cifs_discard_remaining_data (struct TCP_Server_Info *server) +cifs_discard_remaining_data (struct TCP_Server_Info *server,char *buf) { -unsigned int rfclen =get_rfc1002_length (server->smallbuf); +unsigned int rfclen =get_rfc1002_length (buf);int remaining = rfclen +4 - server->total_read;while (remaining >0 ) {
@@ -1426,7 +1426,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)int length;struct cifs_readdata *rdata = mid->callback_data; - length =cifs_discard_remaining_data (server); + length =cifs_discard_remaining_data (server, mid->resp_buf);dequeue_mid (mid, rdata->result);return length; }
@@ -1459,7 +1459,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)if (server->ops->is_status_pending && server->ops->is_status_pending (buf, server,0 )) { -cifs_discard_remaining_data (server); +cifs_discard_remaining_data (server, buf);return -1 ; }
@@ -1519,6 +1519,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)cifs_dbg (FYI ,"0: iov_base=%p iov_len=%u\n" , rdata->iov[0 ].iov_base, server->total_read); + mid->resp_buf = server->smallbuf; + server->smallbuf =NULL ; +/* how much data is in the response? */ data_len = server->ops->read_data_length (buf);if (data_offset + data_len > buflen) {
fs/cifs/connect.c +11 -2
@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p) server->lstrp = jiffies;if (mid_entry !=NULL ) { +if ((mid_entry->mid_flags &MID_WAIT_CANCELLED ) && + mid_entry->mid_state ==MID_RESPONSE_RECEIVED && + server->ops->handle_cancelled_mid) + server->ops->handle_cancelled_mid ( + mid_entry->resp_buf, + server); +if (!mid_entry->multiRsp || mid_entry->multiEnd) mid_entry->callback (mid_entry); - }else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break (buf, server)) { + }else if (server->ops->is_oplock_break && + server->ops->is_oplock_break (buf, server)) { +cifs_dbg (FYI ,"Received oplock break\n" ); + }else {cifs_dbg (VFS ,"No task to wake, unknown frame received! NumMids %d\n" ,atomic_read (&midCount)); cifs_dump_mem("Received Data is: ", buf,
fs/cifs/smb2misc.c +46 -0
49 lines not on this page · raw message
fs/cifs/smb2ops.c +6 -2
@@ -2195,7 +2195,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)if (rc) goto free_pages; - rc =cifs_discard_remaining_data (server); + rc =cifs_discard_remaining_data (server, buf);if (rc) goto free_pages;
@@ -2221,7 +2221,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)kfree (pages);return rc; discard_data: -cifs_discard_remaining_data (server); +cifs_discard_remaining_data (server, buf); goto free_pages; }
@@ -2329,6 +2329,7 @@ struct smb_version_operations smb20_operations = { .clear_stats = smb2_clear_stats, .print_stats = smb2_print_stats, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
@@ -2411,6 +2412,7 @@ struct smb_version_operations smb21_operations = { .clear_stats = smb2_clear_stats, .print_stats = smb2_print_stats, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
@@ -2495,6 +2497,7 @@ struct smb_version_operations smb30_operations = { .print_stats = smb2_print_stats, .dump_share_caps = smb2_dump_share_caps, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
@@ -2589,6 +2592,7 @@ struct smb_version_operations smb311_operations = { .print_stats = smb2_print_stats, .dump_share_caps = smb2_dump_share_caps, .is_oplock_break = smb2_is_valid_oplock_break, + .handle_cancelled_mid = smb2_handle_cancelled_mid, .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate,
fs/cifs/smb2proto.h +7 -0
@@ -48,6 +48,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst);extern struct mid_q_entry *smb2_setup_async_request (struct TCP_Server_Info *server,struct smb_rqst *rqst); +extern struct cifs_ses *smb2_find_smb_ses (struct TCP_Server_Info *server, +__u64 ses_id); +extern struct cifs_tcon *smb2_find_smb_tcon (struct TCP_Server_Info *server, +__u64 ses_id,__u32 tid);extern int smb2_calc_signature (struct smb_rqst *rqst,struct TCP_Server_Info *server); extern int smb3_calc_signature(struct smb_rqst *rqst,
@@ -164,6 +168,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,extern int SMB2_oplock_break (const unsigned int xid,struct cifs_tcon *tcon,const u64 persistent_fid,const u64 volatile_fid,const __u8 oplock_level); +extern int smb2_handle_cancelled_mid (char *buffer, +struct TCP_Server_Info *server); +void smb2_cancelled_close_fid (struct work_struct *work);extern int SMB2_QFS_info (const unsigned int xid,struct cifs_tcon *tcon,u64 persistent_file_id,u64 volatile_file_id,struct kstatfs *FSData);
fs/cifs/smb2transport.c +51 -4
74 lines not on this page · raw message
fs/cifs/transport.c +2 -0
@@ -752,9 +752,11 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, rc =wait_for_response (ses->server, midQ);if (rc !=0 ) { +cifs_dbg (FYI ,"Cancelling wait for mid %llu\n" , midQ->mid);send_cancel (ses->server, rqst, midQ);spin_lock (&GlobalMid_Lock);if (midQ->mid_state ==MID_REQUEST_SUBMITTED ) { + midQ->mid_flags |=MID_WAIT_CANCELLED ; midQ->callback = DeleteMidQEntry;spin_unlock (&GlobalMid_Lock);add_credits (ses->server,1 , optype);
Signature · 1 line
2.9.3
A message that is not in the archive (sent off-list or not yet received): [email protected]
Steve French
Appliedmerged into cifs-2.6.git for-next
Quoted 303 lines · Sachin Prabhu
Quoted 4 lines · Dan Carpenter
Sure, that takes care of the static checker warning. But then I had all sorts of style nits to whinge-bucket about which you didn't ask for...
Thanks Dan,
I have incorporated all the requested changes into version 7 of the patch.
Is smatch the only tool you use for static analysis? I am considering adding it to my own dev process.
Steve, Can you please use this version instead.
Regards,
Sachin PrabhuQuoted 283 lines · Sachin Prabhu
Quoted 9 lines
fs/cifs/connect.c +1
-0@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p) server->lstrp = jiffies;if (mid_entry !=NULL ) { + if ((mid_entry->mid_flags &Quoted 5 lines
MID_WAIT_CANCELLED) &&
+mid_entry->mid_state==MID_RESPONSE_RECEIVED&&
+ (server->ops-Quoted 1 line
handle_cancelled_mid))Extra parens are not required. Please align it like this:
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && mid_entry->mid_state == MID_RESPONSE_RECEIVED && server->ops->handle_cancelled_mid)Quoted 43 lines
fs/cifs/connect.c +2
-0+ server->ops->handle_cancelled_mid( + mid_entry-Quoted 1 line
resp_buf,fs/cifs/connect.c +2
-0+ server); + if (!mid_entry->multiRsp || mid_entry-Quoted 1 line
multiEnd)
mid_entry->callback(mid_entry);fs/cifs/connect.c +0
-2- } else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break(buf,server)) {
fs/cifs/connect.c +2
-0+ } else if (server->ops->is_oplock_break && + server->ops->is_oplock_break(buf,server)) {
fs/cifs/connect.c +2
-0+cifs_dbg (FYI ,"Received oplock break\n" ); + }else { cifs_dbg(VFS, "No task to wake, unknownframe received! NumMids %d\n",
atomic_read(&midCount));
cifs_dump_mem("Received Data is: ", buf,fs/cifs/smb2misc.c +5
-0@@ -659,3 +659,51 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) cifs_dbg(FYI, "Can not process oplock break for non- existent connection\n"); return false; } + +void +smb2_cancelled_close_fid(struct work_struct *work) +{ + struct close_cancelled_open *cancelled =container_of(work,
+ structclose_cancelled_open, work);fs/cifs/smb2misc.c +4
-0+ +cifs_dbg (VFS ,"Close unmatched open\n" ); + + SMB2_close(0, cancelled->tcon, cancelled-Quoted 1 line
fid.persistent_fid,
Quoted 2 lines
+ cancelled-
Quoted 1 line
fid.volatile_fid);
Don't right align it. Do it like this:
SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, cancelled->fid.volatile_fid);Quoted 11 lines
fs/cifs/smb2misc.c +6
-0+cifs_put_tcon (cancelled->tcon); +kfree (cancelled); +} + +int +smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info*server)
fs/cifs/smb2misc.c +3
-0+{ +struct smb2_sync_hdr *sync_hdr =get_sync_hdr (buffer); + struct smb2_create_rsp *rsp = (struct smb2_create_rsp*)buffer;
fs/cifs/smb2misc.c smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
Quoted 5 lines
fs/cifs/smb2misc.c +5
-0+struct cifs_tcon *tcon; +struct close_cancelled_open *cancelled; + +if ((sync_hdr->Command !=SMB2_CREATE ) || + (sync_hdr->Status !=STATUS_SUCCESS ))No need for extra parens. Align it like this:
if (sync_hdr->Command != SMB2_CREATE || sync_hdr->Status != STATUS_SUCCESS) return 0;Quoted 6 lines
fs/cifs/smb2misc.c +4
-0+return 0 ; + + cancelled = (struct close_cancelled_open *) + kzalloc(sizeof(struct
close_cancelled_open),
+GFP_KERNEL);No need to cast kzalloc. Use
sizeof(*cancelled).cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);Quoted 18 lines
fs/cifs/smb2misc.c +18
-0+if (!cancelled) +return -ENOMEM ; + + tcon =smb2_find_smb_tcon (server, sync_hdr->SessionId, + sync_hdr->TreeId); +if (!tcon) { +kfree (cancelled); +return -ENOENT ; + } + + cancelled->fid.persistent_fid = rsp->PersistentFileId; + cancelled->fid.volatile_fid = rsp->VolatileFileId; + cancelled->tcon = tcon; +INIT_WORK (&cancelled->work, smb2_cancelled_close_fid); +queue_work (cifsiod_wq, &cancelled->work); + +return 0 ; +}[ snip ]
fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct · line 120
Quoted 13 lines
fs/cifs/smb2transport.c +2
-2@@ -115,23 +115,72 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)return 0 ; } -struct cifs_ses * -smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +static struct cifs_ses * +_smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id)Could you name this "locked" or something and get rid of the _ underscore prefix?
Quoted 19 lines
fs/cifs/smb2transport.c +8
-2{struct cifs_ses *ses; -spin_lock (&cifs_tcp_ses_lock);list_for_each_entry (ses, &server->smb_ses_list, smb_ses_list) {if (ses->Suid != ses_id)continue ; -spin_unlock (&cifs_tcp_ses_lock);return ses; } + +return NULL ; +} + +struct cifs_ses * +smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +{ +struct cifs_ses *ses;fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
Quoted 10 lines
fs/cifs/smb2transport.c +8
-0+ +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id);spin_unlock (&cifs_tcp_ses_lock); +return ses; +} + +static struct cifs_tcon * +_smb2_find_smb_sess_tcon (struct cifs_ses *ses,__u32 tid)Just leave out the _ underscore prefix. This is a static function so there aren't that many users and they presumably know the locking rules.
Forsmb2_find_smb_seswe have a locked and unlocked version of the function so it makes sense to put that in the name but here there is no need I think.fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct · line 154
Quoted 7 lines
fs/cifs/smb2transport.c +6
-0+{ +struct list_head *tmp; +struct cifs_tcon *tcon; + +list_for_each (tmp, &ses->tcon_list) { + tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
list_for_each_entry()?Quoted 38 lines
fs/cifs/smb2transport.c +13
-0+if (tcon->tid != tid) +continue ; + ++tcon->tc_count; +return tcon; + } +return NULL ; } +/* +* Obtain tcon corresponding to the tid in the given +* cifs_ses +*/ + +struct cifs_tcon * +smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id,
__u32tid)fs/cifs/smb2transport.c +16
-0+{ +struct cifs_ses *ses; +struct cifs_tcon *tcon; + +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id); +if (!ses) { +spin_unlock (&cifs_tcp_ses_lock); +return NULL ; + } + tcon =_smb2_find_smb_sess_tcon (ses, tid); +spin_unlock (&cifs_tcp_ses_lock); + +return tcon; +} +int smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info*server)
{fs/cifs/smb2transport.c smb2_mid_entry_alloc(const struct smb2_sync_hdr · line 564
Quoted 5 lines
fs/cifs/smb2transport.c +1
-0@@ -511,6 +560,7 @@ smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,atomic_inc (&midCount); temp->mid_state =MID_REQUEST_ALLOCATED ; + temp->mid_flags =0 ;No need. We already
memset()this to zero.Quoted 8 lines
fs/cifs/smb2transport.c +0
-0return temp; }fs/cifs/transport.c +0
-0fs/cifs/transport.c cifs_send_recv(const unsigned int xid, struct · line 757
Quoted 6 lines
fs/cifs/transport.c +2
-0@@ -752,9 +752,12 @@ cifs_send_recv(const unsigned int xid, structcifs_ses *ses, rc =wait_for_response (ses->server, midQ);if (rc !=0 ) { +cifs_dbg (FYI ,"Cancelling wait for mid %lu\n" , + (unsigned long )midQ->mid);->mid is u64. Just do this:
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ-
fs/cifs/transport.c cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, · line 762
Quoted 10 lines
fs/cifs/transport.c +1
-0mid);send_cancel (ses->server, rqst, midQ);spin_lock (&GlobalMid_Lock);if (midQ->mid_state ==MID_REQUEST_SUBMITTED ) { + midQ->mid_flags |=MID_WAIT_CANCELLED ; midQ->callback = DeleteMidQEntry;spin_unlock (&GlobalMid_Lock);add_credits (ses->server,1 , optype);regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Thanks, Steve
A message that is not in the archive (sent off-list or not yet received): CAH2r5muHaA0JJ7E6fLFxO69wvLtuep8pC8_GdSsM_Lj2drYQOA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
git.samba.org is down at the moment - will repush when it comes back up
Quoted 313 lines · Steve French
merged into cifs-2.6.git for-next
Quoted 11 lines · Sachin Prabhu
Quoted 4 lines · Dan Carpenter
Sure, that takes care of the static checker warning. But then I had all sorts of style nits to whinge-bucket about which you didn't ask for...
Thanks Dan,
I have incorporated all the requested changes into version 7 of the patch.
Quoted 292 lines
Is smatch the only tool you use for static analysis? I am considering adding it to my own dev process.
Steve, Can you please use this version instead.
Regards,
Sachin PrabhuQuoted 283 lines · Sachin Prabhu
Quoted 9 lines
fs/cifs/connect.c +1
-0@@ -904,10 +904,19 @@ cifs_demultiplex_thread(void *p) server->lstrp = jiffies;if (mid_entry !=NULL ) { + if ((mid_entry->mid_flags &Quoted 5 lines
MID_WAIT_CANCELLED) &&
+mid_entry->mid_state==MID_RESPONSE_RECEIVED&&
+ (server->ops-Quoted 1 line
handle_cancelled_mid))Extra parens are not required. Please align it like this:
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && mid_entry->mid_state == MID_RESPONSE_RECEIVED && server->ops->handle_cancelled_mid)Quoted 43 lines
fs/cifs/connect.c +2
-0+ server->ops->handle_cancelled_mid( + mid_entry-Quoted 1 line
resp_buf,fs/cifs/connect.c +2
-0+ server); + if (!mid_entry->multiRsp || mid_entry-Quoted 1 line
multiEnd)
mid_entry->callback(mid_entry);fs/cifs/connect.c +0
-2- } else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break(buf,server)) {
fs/cifs/connect.c +2
-0+ } else if (server->ops->is_oplock_break && + server->ops->is_oplock_break(buf,server)) {
fs/cifs/connect.c +2
-0+cifs_dbg (FYI ,"Received oplock break\n" ); + }else { cifs_dbg(VFS, "No task to wake, unknownframe received! NumMids %d\n",
atomic_read(&midCount));
cifs_dump_mem("Received Data is: ", buf,fs/cifs/smb2misc.c +5
-0@@ -659,3 +659,51 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) cifs_dbg(FYI, "Can not process oplock break for non- existent connection\n"); return false; } + +void +smb2_cancelled_close_fid(struct work_struct *work) +{ + struct close_cancelled_open *cancelled =container_of(work,
+ structclose_cancelled_open, work);fs/cifs/smb2misc.c +4
-0+ +cifs_dbg (VFS ,"Close unmatched open\n" ); + + SMB2_close(0, cancelled->tcon, cancelled-Quoted 1 line
fid.persistent_fid,
Quoted 2 lines
+ cancelled-
Quoted 1 line
fid.volatile_fid);
Don't right align it. Do it like this:
SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, cancelled->fid.volatile_fid);Quoted 11 lines
fs/cifs/smb2misc.c +6
-0+cifs_put_tcon (cancelled->tcon); +kfree (cancelled); +} + +int +smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info*server)
fs/cifs/smb2misc.c +3
-0+{ +struct smb2_sync_hdr *sync_hdr =get_sync_hdr (buffer); + struct smb2_create_rsp *rsp = (struct smb2_create_rsp*)buffer;
fs/cifs/smb2misc.c smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
Quoted 5 lines
fs/cifs/smb2misc.c +5
-0+struct cifs_tcon *tcon; +struct close_cancelled_open *cancelled; + +if ((sync_hdr->Command !=SMB2_CREATE ) || + (sync_hdr->Status !=STATUS_SUCCESS ))No need for extra parens. Align it like this:
if (sync_hdr->Command != SMB2_CREATE || sync_hdr->Status != STATUS_SUCCESS) return 0;Quoted 6 lines
fs/cifs/smb2misc.c +4
-0+return 0 ; + + cancelled = (struct close_cancelled_open *) + kzalloc(sizeof(struct
close_cancelled_open),
+GFP_KERNEL);No need to cast kzalloc. Use
sizeof(*cancelled).cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);Quoted 18 lines
fs/cifs/smb2misc.c +18
-0+if (!cancelled) +return -ENOMEM ; + + tcon =smb2_find_smb_tcon (server, sync_hdr->SessionId, + sync_hdr->TreeId); +if (!tcon) { +kfree (cancelled); +return -ENOENT ; + } + + cancelled->fid.persistent_fid = rsp->PersistentFileId; + cancelled->fid.volatile_fid = rsp->VolatileFileId; + cancelled->tcon = tcon; +INIT_WORK (&cancelled->work, smb2_cancelled_close_fid); +queue_work (cifsiod_wq, &cancelled->work); + +return 0 ; +}[ snip ]
fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct · line 120
Quoted 13 lines
fs/cifs/smb2transport.c +2
-2@@ -115,23 +115,72 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)return 0 ; } -struct cifs_ses * -smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +static struct cifs_ses * +_smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id)Could you name this "locked" or something and get rid of the _ underscore prefix?
Quoted 19 lines
fs/cifs/smb2transport.c +8
-2{struct cifs_ses *ses; -spin_lock (&cifs_tcp_ses_lock);list_for_each_entry (ses, &server->smb_ses_list, smb_ses_list) {if (ses->Suid != ses_id)continue ; -spin_unlock (&cifs_tcp_ses_lock);return ses; } + +return NULL ; +} + +struct cifs_ses * +smb2_find_smb_ses (struct TCP_Server_Info *server,__u64 ses_id) +{ +struct cifs_ses *ses;fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
Quoted 10 lines
fs/cifs/smb2transport.c +8
-0+ +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id);spin_unlock (&cifs_tcp_ses_lock); +return ses; +} + +static struct cifs_tcon * +_smb2_find_smb_sess_tcon (struct cifs_ses *ses,__u32 tid)Just leave out the _ underscore prefix. This is a static function so there aren't that many users and they presumably know the locking rules.
Forsmb2_find_smb_seswe have a locked and unlocked version of the function so it makes sense to put that in the name but here there is no need I think.fs/cifs/smb2transport.c smb3_crypto_shash_allocate(struct · line 154
Quoted 7 lines
fs/cifs/smb2transport.c +6
-0+{ +struct list_head *tmp; +struct cifs_tcon *tcon; + +list_for_each (tmp, &ses->tcon_list) { + tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
list_for_each_entry()?Quoted 38 lines
fs/cifs/smb2transport.c +13
-0+if (tcon->tid != tid) +continue ; + ++tcon->tc_count; +return tcon; + } +return NULL ; } +/* +* Obtain tcon corresponding to the tid in the given +* cifs_ses +*/ + +struct cifs_tcon * +smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id,
__u32tid)fs/cifs/smb2transport.c +16
-0+{ +struct cifs_ses *ses; +struct cifs_tcon *tcon; + +spin_lock (&cifs_tcp_ses_lock); + ses =_smb2_find_smb_ses (server, ses_id); +if (!ses) { +spin_unlock (&cifs_tcp_ses_lock); +return NULL ; + } + tcon =_smb2_find_smb_sess_tcon (ses, tid); +spin_unlock (&cifs_tcp_ses_lock); + +return tcon; +} +int smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info*server)
{fs/cifs/smb2transport.c smb2_mid_entry_alloc(const struct smb2_sync_hdr · line 564
Quoted 5 lines
fs/cifs/smb2transport.c +1
-0@@ -511,6 +560,7 @@ smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,atomic_inc (&midCount); temp->mid_state =MID_REQUEST_ALLOCATED ; + temp->mid_flags =0 ;No need. We already
memset()this to zero.Quoted 8 lines
fs/cifs/smb2transport.c +0
-0return temp; }fs/cifs/transport.c +0
-0fs/cifs/transport.c cifs_send_recv(const unsigned int xid, struct · line 757
Quoted 6 lines
fs/cifs/transport.c +2
-0@@ -752,9 +752,12 @@ cifs_send_recv(const unsigned int xid, structcifs_ses *ses, rc =wait_for_response (ses->server, midQ);if (rc !=0 ) { +cifs_dbg (FYI ,"Cancelling wait for mid %lu\n" , + (unsigned long )midQ->mid);->mid is u64. Just do this:
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ-
fs/cifs/transport.c cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, · line 762
Quoted 10 lines
fs/cifs/transport.c +1
-0mid);send_cancel (ses->server, rqst, midQ);spin_lock (&GlobalMid_Lock);if (midQ->mid_state ==MID_REQUEST_SUBMITTED ) { + midQ->mid_flags |=MID_WAIT_CANCELLED ; midQ->callback = DeleteMidQEntry;spin_unlock (&GlobalMid_Lock);add_credits (ses->server,1 , optype);regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html--
Thanks,Steve
Signature · 3 lines
Thanks, Steve