Re: [RFC][PATCH] cifs: convert cifs_tcp_ses_lock from a rwlock to a spinlock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 18 Oct 2010 23:29:37 +0530
Suresh Jayaraman <sjayaraman@xxxxxxx> wrote:

> cifs_tcp_ses_lock is a rwlock with protects the cifs_tcp_ses_list,
> server->smb_ses_list and the ses->tcon_list. It also protects a few
> ref counters in server, ses and tcon. In most cases the critical section
> doesn't seem to be large, in a few cases where it is slightly large, there
> seem to be really no benefit from concurrent access. I briefly considered RCU
> mechanism but it appears to me that there is no real need.
> 
> Replace it with a spinlock and get rid of the last rwlock in the cifs code.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@xxxxxxx>
> ---
>  fs/cifs/cifs_debug.c |   12 ++++----
>  fs/cifs/cifsfs.c     |    8 +++---
>  fs/cifs/cifsglob.h   |    2 +-
>  fs/cifs/cifssmb.c    |    6 ++--
>  fs/cifs/connect.c    |   70 +++++++++++++++++++++++++-------------------------
>  fs/cifs/misc.c       |   14 +++++-----
>  fs/cifs/sess.c       |    4 +-
>  7 files changed, 58 insertions(+), 58 deletions(-)
> 
> diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
> index eb1ba49..103ab8b 100644
> --- a/fs/cifs/cifs_debug.c
> +++ b/fs/cifs/cifs_debug.c
> @@ -148,7 +148,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
>  	seq_printf(m, "Servers:");
>  
>  	i = 0;
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each(tmp1, &cifs_tcp_ses_list) {
>  		server = list_entry(tmp1, struct TCP_Server_Info,
>  				    tcp_ses_list);
> @@ -230,7 +230,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
>  			spin_unlock(&GlobalMid_Lock);
>  		}
>  	}
> -	read_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  	seq_putc(m, '\n');
>  
>  	/* BB add code to dump additional info such as TCP session info now */
> @@ -270,7 +270,7 @@ static ssize_t cifs_stats_proc_write(struct file *file,
>  		atomic_set(&totBufAllocCount, 0);
>  		atomic_set(&totSmBufAllocCount, 0);
>  #endif /* CONFIG_CIFS_STATS2 */
> -		read_lock(&cifs_tcp_ses_lock);
> +		spin_lock(&cifs_tcp_ses_lock);
>  		list_for_each(tmp1, &cifs_tcp_ses_list) {
>  			server = list_entry(tmp1, struct TCP_Server_Info,
>  					    tcp_ses_list);
> @@ -303,7 +303,7 @@ static ssize_t cifs_stats_proc_write(struct file *file,
>  				}
>  			}
>  		}
> -		read_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  	}
>  
>  	return count;
> @@ -343,7 +343,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
>  		GlobalCurrentXid, GlobalMaxActiveXid);
>  
>  	i = 0;
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each(tmp1, &cifs_tcp_ses_list) {
>  		server = list_entry(tmp1, struct TCP_Server_Info,
>  				    tcp_ses_list);
> @@ -397,7 +397,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
>  			}
>  		}
>  	}
> -	read_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	seq_putc(m, '\n');
>  	return 0;
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index f1d9c71..cb77915 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -482,16 +482,16 @@ static void cifs_umount_begin(struct super_block *sb)
>  
>  	tcon = cifs_sb_master_tcon(cifs_sb);
>  
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
>  		/* we have other mounts to same share or we have
>  		   already tried to force umount this and woken up
>  		   all waiting network requests, nothing to do */
> -		read_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		return;
>  	} else if (tcon->tc_count == 1)
>  		tcon->tidStatus = CifsExiting;
> -	read_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
>  	/* cancel_notify_requests(tcon); */
> @@ -940,7 +940,7 @@ init_cifs(void)
>  	GlobalTotalActiveXid = 0;
>  	GlobalMaxActiveXid = 0;
>  	memset(Local_System_Name, 0, 15);
> -	rwlock_init(&cifs_tcp_ses_lock);
> +	spin_lock_init(&cifs_tcp_ses_lock);
>  	spin_lock_init(&cifs_file_list_lock);
>  	spin_lock_init(&GlobalMid_Lock);
>  
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 18ee0ad..28337cb 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -703,7 +703,7 @@ GLOBAL_EXTERN struct list_head		cifs_tcp_ses_list;
>   * the reference counters for the server, smb session, and tcon. Finally,
>   * changes to the tcon->tidStatus should be done while holding this lock.
>   */
> -GLOBAL_EXTERN rwlock_t		cifs_tcp_ses_lock;
> +GLOBAL_EXTERN spinlock_t		cifs_tcp_ses_lock;
>  
>  /*
>   * This lock protects the cifs_file->llist and cifs_file->flist
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index bfb59a6..e98f1f3 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -593,9 +593,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
>  			rc = -EIO;
>  			goto neg_err_exit;
>  		}
> -		read_lock(&cifs_tcp_ses_lock);
> +		spin_lock(&cifs_tcp_ses_lock);
>  		if (server->srv_count > 1) {
> -			read_unlock(&cifs_tcp_ses_lock);
> +			spin_unlock(&cifs_tcp_ses_lock);
>  			if (memcmp(server->server_GUID,
>  				   pSMBr->u.extended_response.
>  				   GUID, 16) != 0) {
> @@ -605,7 +605,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
>  					16);
>  			}
>  		} else {
> -			read_unlock(&cifs_tcp_ses_lock);
> +			spin_unlock(&cifs_tcp_ses_lock);
>  			memcpy(server->server_GUID,
>  			       pSMBr->u.extended_response.GUID, 16);
>  		}
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 019f003..7e73176 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -150,7 +150,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
>  
>  	/* before reconnecting the tcp session, mark the smb session (uid)
>  		and the tid bad so they are not used until reconnected */
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each(tmp, &server->smb_ses_list) {
>  		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
>  		ses->need_reconnect = true;
> @@ -160,7 +160,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
>  			tcon->need_reconnect = true;
>  		}
>  	}
> -	read_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  	/* do not want to be sending data on a socket we are freeing */
>  	mutex_lock(&server->srv_mutex);
>  	if (server->ssocket) {
> @@ -637,9 +637,9 @@ multi_t2_fnd:
>  	} /* end while !EXITING */
>  
>  	/* take it off the list, if it's not already */
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_del_init(&server->tcp_ses_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	spin_lock(&GlobalMid_Lock);
>  	server->tcpStatus = CifsExiting;
> @@ -677,7 +677,7 @@ multi_t2_fnd:
>  	 * BB: we shouldn't have to do any of this. It shouldn't be
>  	 * possible to exit from the thread with active SMB sessions
>  	 */
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	if (list_empty(&server->pending_mid_q)) {
>  		/* loop through server session structures attached to this and
>  		    mark them dead */
> @@ -687,7 +687,7 @@ multi_t2_fnd:
>  			ses->status = CifsExiting;
>  			ses->server = NULL;
>  		}
> -		read_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  	} else {
>  		/* although we can not zero the server struct pointer yet,
>  		since there are active requests which may depnd on them,
> @@ -710,7 +710,7 @@ multi_t2_fnd:
>  			}
>  		}
>  		spin_unlock(&GlobalMid_Lock);
> -		read_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		/* 1/8th of sec is more than enough time for them to exit */
>  		msleep(125);
>  	}
> @@ -733,12 +733,12 @@ multi_t2_fnd:
>  	if a crazy root user tried to kill cifsd
>  	kernel thread explicitly this might happen) */
>  	/* BB: This shouldn't be necessary, see above */
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each(tmp, &server->smb_ses_list) {
>  		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
>  		ses->server = NULL;
>  	}
> -	read_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	kfree(server->hostname);
>  	task_to_wake = xchg(&server->tsk, NULL);
> @@ -1524,7 +1524,7 @@ cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
>  {
>  	struct TCP_Server_Info *server;
>  
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
>  		if (!match_address(server, addr,
>  				   (struct sockaddr *)&vol->srcaddr))
> @@ -1534,11 +1534,11 @@ cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol)
>  			continue;
>  
>  		++server->srv_count;
> -		write_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		cFYI(1, "Existing tcp session with server found");
>  		return server;
>  	}
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  	return NULL;
>  }
>  
> @@ -1547,14 +1547,14 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
>  {
>  	struct task_struct *task;
>  
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	if (--server->srv_count > 0) {
> -		write_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		return;
>  	}
>  
>  	list_del_init(&server->tcp_ses_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	spin_lock(&GlobalMid_Lock);
>  	server->tcpStatus = CifsExiting;
> @@ -1679,9 +1679,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
>  	}
>  
>  	/* thread spawned, put it on the list */
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	cifs_fscache_get_client_cookie(tcp_ses);
>  
> @@ -1703,7 +1703,7 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
>  {
>  	struct cifsSesInfo *ses;
>  
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
>  		switch (server->secType) {
>  		case Kerberos:
> @@ -1723,10 +1723,10 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
>  				continue;
>  		}
>  		++ses->ses_count;
> -		write_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		return ses;
>  	}
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  	return NULL;
>  }
>  
> @@ -1737,14 +1737,14 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
>  	struct TCP_Server_Info *server = ses->server;
>  
>  	cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count);
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	if (--ses->ses_count > 0) {
> -		write_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		return;
>  	}
>  
>  	list_del_init(&ses->smb_ses_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	if (ses->status == CifsGood) {
>  		xid = GetXid();
> @@ -1841,9 +1841,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
>  		goto get_ses_fail;
>  
>  	/* success, put it on the list */
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_add(&ses->smb_ses_list, &server->smb_ses_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	FreeXid(xid);
>  	return ses;
> @@ -1860,7 +1860,7 @@ cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
>  	struct list_head *tmp;
>  	struct cifsTconInfo *tcon;
>  
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each(tmp, &ses->tcon_list) {
>  		tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
>  		if (tcon->tidStatus == CifsExiting)
> @@ -1869,10 +1869,10 @@ cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
>  			continue;
>  
>  		++tcon->tc_count;
> -		write_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		return tcon;
>  	}
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  	return NULL;
>  }
>  
> @@ -1883,14 +1883,14 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
>  	struct cifsSesInfo *ses = tcon->ses;
>  
>  	cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count);
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	if (--tcon->tc_count > 0) {
> -		write_unlock(&cifs_tcp_ses_lock);
> +		spin_unlock(&cifs_tcp_ses_lock);
>  		return;
>  	}
>  
>  	list_del_init(&tcon->tcon_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	xid = GetXid();
>  	CIFSSMBTDis(xid, tcon);
> @@ -1963,9 +1963,9 @@ cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info)
>  	tcon->nocase = volume_info->nocase;
>  	tcon->local_lease = volume_info->local_lease;
>  
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_add(&tcon->tcon_list, &ses->tcon_list);
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	cifs_fscache_get_super_cookie(tcon);
>  
> @@ -3225,9 +3225,9 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
>  	vol_info->secFlg = CIFSSEC_MUST_KRB5;
>  
>  	/* get a reference for the same TCP session */
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	++master_tcon->ses->server->srv_count;
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
>  	if (IS_ERR(ses)) {
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index de6073c..a7b492c 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -347,7 +347,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
>  				if (current_fsuid() != treeCon->ses->linux_uid) {
>  					cFYI(1, "Multiuser mode and UID "
>  						 "did not match tcon uid");
> -					read_lock(&cifs_tcp_ses_lock);
> +					spin_lock(&cifs_tcp_ses_lock);
>  					list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) {
>  						ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list);
>  						if (ses->linux_uid == current_fsuid()) {
> @@ -361,7 +361,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
>  							}
>  						}
>  					}
> -					read_unlock(&cifs_tcp_ses_lock);
> +					spin_unlock(&cifs_tcp_ses_lock);
>  				}
>  			}
>  		}
> @@ -551,7 +551,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
>  		return false;
>  
>  	/* look up tcon based on tid & uid */
> -	read_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	list_for_each(tmp, &srv->smb_ses_list) {
>  		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
>  		list_for_each(tmp1, &ses->tcon_list) {
> @@ -573,7 +573,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
>  				 */
>  				if (netfile->closePend) {
>  					spin_unlock(&cifs_file_list_lock);
> -					read_unlock(&cifs_tcp_ses_lock);
> +					spin_unlock(&cifs_tcp_ses_lock);
>  					return true;
>  				}
>  
> @@ -595,16 +595,16 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
>  				netfile->oplock_break_cancelled = false;
>  
>  				spin_unlock(&cifs_file_list_lock);
> -				read_unlock(&cifs_tcp_ses_lock);
> +				spin_unlock(&cifs_tcp_ses_lock);
>  				return true;
>  			}
>  			spin_unlock(&cifs_file_list_lock);
> -			read_unlock(&cifs_tcp_ses_lock);
> +			spin_unlock(&cifs_tcp_ses_lock);
>  			cFYI(1, "No matching file for oplock break");
>  			return true;
>  		}
>  	}
> -	read_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  	cFYI(1, "Can not process oplock break for non-existent connection");
>  	return true;
>  }
> diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
> index 2111bed..933ed26 100644
> --- a/fs/cifs/sess.c
> +++ b/fs/cifs/sess.c
> @@ -80,7 +80,7 @@ static __le16 get_next_vcnum(struct cifsSesInfo *ses)
>  	if (max_vcs < 2)
>  		max_vcs = 0xFFFF;
>  
> -	write_lock(&cifs_tcp_ses_lock);
> +	spin_lock(&cifs_tcp_ses_lock);
>  	if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
>  			goto get_vc_num_exit;  /* vcnum will be zero */
>  	for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
> @@ -112,7 +112,7 @@ static __le16 get_next_vcnum(struct cifsSesInfo *ses)
>  		vcnum = i;
>  	ses->vcnum = vcnum;
>  get_vc_num_exit:
> -	write_unlock(&cifs_tcp_ses_lock);
> +	spin_unlock(&cifs_tcp_ses_lock);
>  
>  	return cpu_to_le16(vcnum);
>  }
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Looks reasonable. These codepaths aren't terribly "hot", so this lock
is fairly low-contention anyway.

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux