diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-11-15 11:12:47 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-11-16 22:14:12 -0500 |
commit | f1987b44f642e96176adc88b7ce23a1d74806f89 (patch) | |
tree | fceaebf6b6d7eb1d1150120c44a842cbce8347f6 /fs/cifs/misc.c | |
parent | d82c2df54e2f7e447476350848d8eccc8d2fe46a (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.c | 74 |
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 | |||
493 | is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | 488 | is_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 | } |