aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/misc.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2008-11-15 11:12:47 -0500
committerSteve French <sfrench@us.ibm.com>2008-11-16 22:14:12 -0500
commitf1987b44f642e96176adc88b7ce23a1d74806f89 (patch)
treefceaebf6b6d7eb1d1150120c44a842cbce8347f6 /fs/cifs/misc.c
parentd82c2df54e2f7e447476350848d8eccc8d2fe46a (diff)
cifs: reinstate sharing of tree connections
Use a similar approach to the SMB session sharing. Add a list of tcons attached to each SMB session. Move the refcount to non-atomic. Protect all of the above with the cifs_tcp_ses_lock. Add functions to properly find and put references to the tcons. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/misc.c')
-rw-r--r--fs/cifs/misc.c74
1 files changed, 35 insertions, 39 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 46c8c7baccba..addd1dcc2d79 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -79,6 +79,7 @@ sesInfoAlloc(void)
79 ret_buf->status = CifsNew; 79 ret_buf->status = CifsNew;
80 ++ret_buf->ses_count; 80 ++ret_buf->ses_count;
81 INIT_LIST_HEAD(&ret_buf->smb_ses_list); 81 INIT_LIST_HEAD(&ret_buf->smb_ses_list);
82 INIT_LIST_HEAD(&ret_buf->tcon_list);
82 init_MUTEX(&ret_buf->sesSem); 83 init_MUTEX(&ret_buf->sesSem);
83 } 84 }
84 return ret_buf; 85 return ret_buf;
@@ -107,17 +108,14 @@ tconInfoAlloc(void)
107 struct cifsTconInfo *ret_buf; 108 struct cifsTconInfo *ret_buf;
108 ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL); 109 ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL);
109 if (ret_buf) { 110 if (ret_buf) {
110 write_lock(&GlobalSMBSeslock);
111 atomic_inc(&tconInfoAllocCount); 111 atomic_inc(&tconInfoAllocCount);
112 list_add(&ret_buf->cifsConnectionList,
113 &GlobalTreeConnectionList);
114 ret_buf->tidStatus = CifsNew; 112 ret_buf->tidStatus = CifsNew;
113 ++ret_buf->tc_count;
115 INIT_LIST_HEAD(&ret_buf->openFileList); 114 INIT_LIST_HEAD(&ret_buf->openFileList);
116 init_MUTEX(&ret_buf->tconSem); 115 INIT_LIST_HEAD(&ret_buf->tcon_list);
117#ifdef CONFIG_CIFS_STATS 116#ifdef CONFIG_CIFS_STATS
118 spin_lock_init(&ret_buf->stat_lock); 117 spin_lock_init(&ret_buf->stat_lock);
119#endif 118#endif
120 write_unlock(&GlobalSMBSeslock);
121 } 119 }
122 return ret_buf; 120 return ret_buf;
123} 121}
@@ -129,10 +127,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
129 cFYI(1, ("Null buffer passed to tconInfoFree")); 127 cFYI(1, ("Null buffer passed to tconInfoFree"));
130 return; 128 return;
131 } 129 }
132 write_lock(&GlobalSMBSeslock);
133 atomic_dec(&tconInfoAllocCount); 130 atomic_dec(&tconInfoAllocCount);
134 list_del(&buf_to_free->cifsConnectionList);
135 write_unlock(&GlobalSMBSeslock);
136 kfree(buf_to_free->nativeFileSystem); 131 kfree(buf_to_free->nativeFileSystem);
137 kfree(buf_to_free); 132 kfree(buf_to_free);
138} 133}
@@ -493,9 +488,10 @@ bool
493is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) 488is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
494{ 489{
495 struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; 490 struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf;
496 struct list_head *tmp; 491 struct list_head *tmp, *tmp1, *tmp2;
497 struct list_head *tmp1; 492 struct cifsSesInfo *ses;
498 struct cifsTconInfo *tcon; 493 struct cifsTconInfo *tcon;
494 struct cifsInodeInfo *pCifsInode;
499 struct cifsFileInfo *netfile; 495 struct cifsFileInfo *netfile;
500 496
501 cFYI(1, ("Checking for oplock break or dnotify response")); 497 cFYI(1, ("Checking for oplock break or dnotify response"));
@@ -550,42 +546,42 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
550 return false; 546 return false;
551 547
552 /* look up tcon based on tid & uid */ 548 /* look up tcon based on tid & uid */
553 read_lock(&GlobalSMBSeslock); 549 read_lock(&cifs_tcp_ses_lock);
554 list_for_each(tmp, &GlobalTreeConnectionList) { 550 list_for_each(tmp, &srv->smb_ses_list) {
555 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 551 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
556 if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) { 552 list_for_each(tmp1, &ses->tcon_list) {
553 tcon = list_entry(tmp1, struct cifsTconInfo, tcon_list);
554 if (tcon->tid != buf->Tid)
555 continue;
556
557 cifs_stats_inc(&tcon->num_oplock_brks); 557 cifs_stats_inc(&tcon->num_oplock_brks);
558 list_for_each(tmp1, &tcon->openFileList) { 558 list_for_each(tmp2, &tcon->openFileList) {
559 netfile = list_entry(tmp1, struct cifsFileInfo, 559 netfile = list_entry(tmp2, struct cifsFileInfo,
560 tlist); 560 tlist);
561 if (pSMB->Fid == netfile->netfid) { 561 if (pSMB->Fid != netfile->netfid)
562 struct cifsInodeInfo *pCifsInode; 562 continue;
563 read_unlock(&GlobalSMBSeslock); 563
564 cFYI(1, 564 read_unlock(&cifs_tcp_ses_lock);
565 ("file id match, oplock break")); 565 cFYI(1, ("file id match, oplock break"));
566 pCifsInode = 566 pCifsInode = CIFS_I(netfile->pInode);
567 CIFS_I(netfile->pInode); 567 pCifsInode->clientCanCacheAll = false;
568 pCifsInode->clientCanCacheAll = false; 568 if (pSMB->OplockLevel == 0)
569 if (pSMB->OplockLevel == 0) 569 pCifsInode->clientCanCacheRead = false;
570 pCifsInode->clientCanCacheRead 570 pCifsInode->oplockPending = true;
571 = false; 571 AllocOplockQEntry(netfile->pInode,
572 pCifsInode->oplockPending = true; 572 netfile->netfid, tcon);
573 AllocOplockQEntry(netfile->pInode, 573 cFYI(1, ("about to wake up oplock thread"));
574 netfile->netfid, 574 if (oplockThread)
575 tcon); 575 wake_up_process(oplockThread);
576 cFYI(1, 576
577 ("about to wake up oplock thread")); 577 return true;
578 if (oplockThread)
579 wake_up_process(oplockThread);
580 return true;
581 }
582 } 578 }
583 read_unlock(&GlobalSMBSeslock); 579 read_unlock(&cifs_tcp_ses_lock);
584 cFYI(1, ("No matching file for oplock break")); 580 cFYI(1, ("No matching file for oplock break"));
585 return true; 581 return true;
586 } 582 }
587 } 583 }
588 read_unlock(&GlobalSMBSeslock); 584 read_unlock(&cifs_tcp_ses_lock);
589 cFYI(1, ("Can not process oplock break for non-existent connection")); 585 cFYI(1, ("Can not process oplock break for non-existent connection"));
590 return true; 586 return true;
591} 587}