diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-11-14 13:53:46 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-11-14 18:56:55 -0500 |
commit | 14fbf50d695207754daeb96270b3027a3821121f (patch) | |
tree | 05e80aa7e5e6a6bc07a9354f744ba9c599699569 /fs/cifs/misc.c | |
parent | e7ddee9037e7dd43de1ad08b51727e552aedd836 (diff) |
cifs: reinstate sharing of SMB sessions sans races
We do this by abandoning the global list of SMB sessions and instead
moving to a per-server list. This entails adding a new list head to the
TCP_Server_Info struct. The refcounting for the cifsSesInfo is moved to
a non-atomic variable. We have to protect it by a lock anyway, so there's
no benefit to making it an atomic. The list and refcount are protected
by the global cifs_tcp_ses_lock.
The patch also adds a new routines to find and put SMB sessions and
that properly take and put references under the lock.
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 | 16 |
1 files changed, 6 insertions, 10 deletions
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 88786ba02d27..46c8c7baccba 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -75,12 +75,11 @@ sesInfoAlloc(void) | |||
75 | 75 | ||
76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); | 76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); |
77 | if (ret_buf) { | 77 | if (ret_buf) { |
78 | write_lock(&GlobalSMBSeslock); | ||
79 | atomic_inc(&sesInfoAllocCount); | 78 | atomic_inc(&sesInfoAllocCount); |
80 | ret_buf->status = CifsNew; | 79 | ret_buf->status = CifsNew; |
81 | list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList); | 80 | ++ret_buf->ses_count; |
81 | INIT_LIST_HEAD(&ret_buf->smb_ses_list); | ||
82 | init_MUTEX(&ret_buf->sesSem); | 82 | init_MUTEX(&ret_buf->sesSem); |
83 | write_unlock(&GlobalSMBSeslock); | ||
84 | } | 83 | } |
85 | return ret_buf; | 84 | return ret_buf; |
86 | } | 85 | } |
@@ -93,10 +92,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) | |||
93 | return; | 92 | return; |
94 | } | 93 | } |
95 | 94 | ||
96 | write_lock(&GlobalSMBSeslock); | ||
97 | atomic_dec(&sesInfoAllocCount); | 95 | atomic_dec(&sesInfoAllocCount); |
98 | list_del(&buf_to_free->cifsSessionList); | ||
99 | write_unlock(&GlobalSMBSeslock); | ||
100 | kfree(buf_to_free->serverOS); | 96 | kfree(buf_to_free->serverOS); |
101 | kfree(buf_to_free->serverDomain); | 97 | kfree(buf_to_free->serverDomain); |
102 | kfree(buf_to_free->serverNOS); | 98 | kfree(buf_to_free->serverNOS); |
@@ -350,9 +346,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
350 | if (current->fsuid != treeCon->ses->linux_uid) { | 346 | if (current->fsuid != treeCon->ses->linux_uid) { |
351 | cFYI(1, ("Multiuser mode and UID " | 347 | cFYI(1, ("Multiuser mode and UID " |
352 | "did not match tcon uid")); | 348 | "did not match tcon uid")); |
353 | read_lock(&GlobalSMBSeslock); | 349 | read_lock(&cifs_tcp_ses_lock); |
354 | list_for_each(temp_item, &GlobalSMBSessionList) { | 350 | list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) { |
355 | ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); | 351 | ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list); |
356 | if (ses->linux_uid == current->fsuid) { | 352 | if (ses->linux_uid == current->fsuid) { |
357 | if (ses->server == treeCon->ses->server) { | 353 | if (ses->server == treeCon->ses->server) { |
358 | cFYI(1, ("found matching uid substitute right smb_uid")); | 354 | cFYI(1, ("found matching uid substitute right smb_uid")); |
@@ -364,7 +360,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
364 | } | 360 | } |
365 | } | 361 | } |
366 | } | 362 | } |
367 | read_unlock(&GlobalSMBSeslock); | 363 | read_unlock(&cifs_tcp_ses_lock); |
368 | } | 364 | } |
369 | } | 365 | } |
370 | } | 366 | } |