[linux-cifs-client][patch] utilize lookup intents to open in lookup

Jeff Layton jlayton at redhat.com
Thu Apr 9 12:55:54 GMT 2009


On Wed, 1 Apr 2009 14:33:23 -0500
Shirish Pargaonkar <shirishpargaonkar at gmail.com> wrote:

Sorry I'm late. I know Steve has already committed this, but here are
some comments. Maybe we can fix them in a later patch...

> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 9fbf4df..9a8368f 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -350,7 +350,7 @@ struct cifsFileInfo {
>  	bool invalidHandle:1;	/* file closed via session abend */
>  	bool messageMode:1;	/* for pipes: message vs byte mode */
>  	atomic_t wrtPending;   /* handle in use - defer close */
> -	struct semaphore fh_sem; /* prevents reopen race after dead ses*/
> +	struct mutex fh_mutex; /* prevents reopen race after dead ses*/
>  	struct cifs_search_info srch_inf;
>  };
>  
> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
> index f9b6f68..f473c73 100644
> --- a/fs/cifs/dir.c
> +++ b/fs/cifs/dir.c
> @@ -129,12 +129,64 @@ cifs_bp_rename_retry:
>  	return full_path;
>  }
>  
> +static void
> +cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
> +			struct cifsTconInfo *tcon, bool write_only)
> +{
> +	int oplock = 0;
> +	struct cifsFileInfo *pCifsFile;
> +	struct cifsInodeInfo *pCifsInode;
> +
> +	pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
> +
> +	if (pCifsFile == NULL)
> +		return;
> +
> +	if (oplockEnabled)
> +		oplock = REQ_OPLOCK;
> +
> +	pCifsFile->netfid = fileHandle;
> +	pCifsFile->pid = current->tgid;
> +	pCifsFile->pInode = newinode;
> +	pCifsFile->invalidHandle = false;
> +	pCifsFile->closePend     = false;
			^^^^^^^
None of the other '=' are lined up. Why here?

> +	mutex_init(&pCifsFile->fh_mutex);
> +	mutex_init(&pCifsFile->lock_mutex);
> +	INIT_LIST_HEAD(&pCifsFile->llist);
> +	atomic_set(&pCifsFile->wrtPending, 0);
> +
> +	/* set the following in open now
> +			pCifsFile->pfile = file; */
> +	write_lock(&GlobalSMBSeslock);
> +	list_add(&pCifsFile->tlist, &tcon->openFileList);
> +	pCifsInode = CIFS_I(newinode);
> +	if (pCifsInode) {
> +		/* if readable file instance put first in list*/
> +		if (write_only) {
> +			list_add_tail(&pCifsFile->flist,
> +				      &pCifsInode->openFileList);
> +		} else {
> +			list_add(&pCifsFile->flist,
> +				 &pCifsInode->openFileList);
> +		}
		^^^^^^^^
Are these brackets needed?

> +		if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
> +			pCifsInode->clientCanCacheAll = true;
> +			pCifsInode->clientCanCacheRead = true;
> +			cFYI(1, ("Exclusive Oplock inode %p",
> +				newinode));
> +		} else if ((oplock & 0xF) == OPLOCK_READ)
> +			pCifsInode->clientCanCacheRead = true;
> +	}

Ditto		^^^^^^^^^
> +	write_unlock(&GlobalSMBSeslock);
> +}
> +
>  int cifs_posix_open(char *full_path, struct inode **pinode,
>  		    struct super_block *sb, int mode, int oflags,
>  		    int *poplock, __u16 *pnetfid, int xid)
>  {
>  	int rc;
>  	__u32 oplock;
> +	bool write_only = false;
>  	FILE_UNIX_BASIC_INFO *presp_data;
>  	__u32 posix_flags = 0;
>  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
> @@ -172,6 +224,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
>  	if (oflags & O_DIRECT)
>  		posix_flags |= SMB_O_DIRECT;
>  
> +	if (!(oflags & FMODE_READ))
> +		write_only = true;
>  
>  	rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
>  			pnetfid, presp_data, &oplock, full_path,
> @@ -198,6 +252,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
>  
>  	posix_fill_in_inode(*pinode, presp_data, 1);
>  
> +	cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
> +
>  posix_open_ret:
>  	kfree(presp_data);
>  	return rc;
> @@ -239,7 +295,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
>  	char *full_path = NULL;
>  	FILE_ALL_INFO *buf = NULL;
>  	struct inode *newinode = NULL;
> -	struct cifsInodeInfo *pCifsInode;
>  	int disposition = FILE_OVERWRITE_IF;
>  	bool write_only = false;
>  
> @@ -410,44 +465,8 @@ cifs_create_set_dentry:
>  		/* mknod case - do not leave file open */
>  		CIFSSMBClose(xid, tcon, fileHandle);
>  	} else if (newinode) {
> -		struct cifsFileInfo *pCifsFile =
> -			kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
> -
> -		if (pCifsFile == NULL)
> -			goto cifs_create_out;
> -		pCifsFile->netfid = fileHandle;
> -		pCifsFile->pid = current->tgid;
> -		pCifsFile->pInode = newinode;
> -		pCifsFile->invalidHandle = false;
> -		pCifsFile->closePend     = false;
> -		init_MUTEX(&pCifsFile->fh_sem);
> -		mutex_init(&pCifsFile->lock_mutex);
> -		INIT_LIST_HEAD(&pCifsFile->llist);
> -		atomic_set(&pCifsFile->wrtPending, 0);
> -
> -		/* set the following in open now
> -				pCifsFile->pfile = file; */
> -		write_lock(&GlobalSMBSeslock);
> -		list_add(&pCifsFile->tlist, &tcon->openFileList);
> -		pCifsInode = CIFS_I(newinode);
> -		if (pCifsInode) {
> -			/* if readable file instance put first in list*/
> -			if (write_only) {
> -				list_add_tail(&pCifsFile->flist,
> -					      &pCifsInode->openFileList);
> -			} else {
> -				list_add(&pCifsFile->flist,
> -					 &pCifsInode->openFileList);
> -			}
> -			if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
> -				pCifsInode->clientCanCacheAll = true;
> -				pCifsInode->clientCanCacheRead = true;
> -				cFYI(1, ("Exclusive Oplock inode %p",
> -					newinode));
> -			} else if ((oplock & 0xF) == OPLOCK_READ)
> -				pCifsInode->clientCanCacheRead = true;
> -		}
> -		write_unlock(&GlobalSMBSeslock);
> +			cifs_fill_fileinfo(newinode, fileHandle,
> +					cifs_sb->tcon, write_only);
>  	}
>  cifs_create_out:
>  	kfree(buf);
> @@ -580,17 +599,21 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
>  	return rc;
>  }
>  
> -
>  struct dentry *
>  cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
>  	    struct nameidata *nd)
>  {
>  	int xid;
>  	int rc = 0; /* to get around spurious gcc warning, set to zero here */
> +	int oplock = 0;
> +	int mode;
> +	__u16 fileHandle = 0;
> +	bool posix_open = false;
>  	struct cifs_sb_info *cifs_sb;
>  	struct cifsTconInfo *pTcon;
>  	struct inode *newInode = NULL;
>  	char *full_path = NULL;
> +	struct file *filp;
>  
>  	xid = GetXid();
>  
> @@ -632,12 +655,27 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
>  	}
>  	cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode));
>  
> -	if (pTcon->unix_ext)
> -		rc = cifs_get_inode_info_unix(&newInode, full_path,
> -					      parent_dir_inode->i_sb, xid);
> -	else
> +	if (pTcon->unix_ext) {
> +		if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
> +				(nd->flags & LOOKUP_OPEN)) {
> +			if (!((nd->intent.open.flags & O_CREAT) &&
> +					(nd->intent.open.flags & O_EXCL))) {
> +				mode = nd->intent.open.create_mode &
> +						~current->fs->umask;
> +				rc = cifs_posix_open(full_path, &newInode,
> +					parent_dir_inode->i_sb, mode,
> +					nd->intent.open.flags, &oplock,
> +					&fileHandle, xid);
> +				if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
					^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This looks wrong to me.  It's possible that you'd get a different
return code here on an unsuccessful open call? Why would we want to
instantiate the filp on any error from cifs_posix_open? For instance,
that function can return -ENOMEM. I don't think we want to instantiate
the filp in that case.

Maybe that should just be: "if (!rc)" ?

> +					posix_open = true;
> +			}
> +		}
> +		if (!posix_open)
> +			rc = cifs_get_inode_info_unix(&newInode, full_path,
> +						parent_dir_inode->i_sb, xid);
> +	} else
>  		rc = cifs_get_inode_info(&newInode, full_path, NULL,
> -					 parent_dir_inode->i_sb, xid, NULL);
> +				parent_dir_inode->i_sb, xid, NULL);
>  
>  	if ((rc == 0) && (newInode != NULL)) {
>  		if (pTcon->nocase)
> @@ -645,7 +683,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
>  		else
>  			direntry->d_op = &cifs_dentry_ops;
>  		d_add(direntry, newInode);
> -
> +		if (posix_open)
> +			filp = lookup_instantiate_filp(nd, direntry, NULL);
>  		/* since paths are not looked up by component - the parent
>  		   directories are presumed to be good here */
>  		renew_parental_timestamps(direntry);
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 81747ac..c3f51de 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -46,7 +46,7 @@ static inline struct cifsFileInfo *cifs_init_private(
>  	memset(private_data, 0, sizeof(struct cifsFileInfo));
>  	private_data->netfid = netfid;
>  	private_data->pid = current->tgid;
> -	init_MUTEX(&private_data->fh_sem);
> +	mutex_init(&private_data->fh_mutex);
>  	mutex_init(&private_data->lock_mutex);
>  	INIT_LIST_HEAD(&private_data->llist);
>  	private_data->pfile = file; /* needed for writepage */
> @@ -284,35 +284,34 @@ int cifs_open(struct inode *inode, struct file *file)
>  	cifs_sb = CIFS_SB(inode->i_sb);
>  	tcon = cifs_sb->tcon;
>  
> -	if (file->f_flags & O_CREAT) {
> -		/* search inode for this file and fill in file->private_data */
> -		pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
> -		read_lock(&GlobalSMBSeslock);
> -		list_for_each(tmp, &pCifsInode->openFileList) {
> -			pCifsFile = list_entry(tmp, struct cifsFileInfo,
> -					       flist);
> -			if ((pCifsFile->pfile == NULL) &&
> -			    (pCifsFile->pid == current->tgid)) {
> -				/* mode set in cifs_create */
> -
> -				/* needed for writepage */
> -				pCifsFile->pfile = file;
> -
> -				file->private_data = pCifsFile;
> -				break;
> -			}
> -		}
> -		read_unlock(&GlobalSMBSeslock);
> -		if (file->private_data != NULL) {
> -			rc = 0;
> -			FreeXid(xid);
> -			return rc;
> -		} else {
> -			if (file->f_flags & O_EXCL)
> -				cERROR(1, ("could not find file instance for "
> -					   "new file %p", file));
> +	/* search inode for this file and fill in file->private_data */
> +	pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
> +	read_lock(&GlobalSMBSeslock);
> +	list_for_each(tmp, &pCifsInode->openFileList) {
> +		pCifsFile = list_entry(tmp, struct cifsFileInfo,
> +				       flist);
> +		if ((pCifsFile->pfile == NULL) &&
> +		    (pCifsFile->pid == current->tgid)) {
> +			/* mode set in cifs_create */
> +
> +			/* needed for writepage */
> +			pCifsFile->pfile = file;
> +
> +			file->private_data = pCifsFile;
> +			break;
>  		}
>  	}
> +	read_unlock(&GlobalSMBSeslock);
> +
> +	if (file->private_data != NULL) {
> +		rc = 0;
> +		FreeXid(xid);
> +		return rc;
> +	} else {
> +		if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))

	^^^^^ how about "else if" here and reduce the indentation below?

> +			cERROR(1, ("could not find file instance for "
> +				   "new file %p", file));
> +	}
>  
>  	full_path = build_path_from_dentry(file->f_path.dentry);
>  	if (full_path == NULL) {
> @@ -500,9 +499,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
>  		return -EBADF;
>  
>  	xid = GetXid();
> -	down(&pCifsFile->fh_sem);
> +	mutex_unlock(&pCifsFile->fh_mutex);
>  	if (!pCifsFile->invalidHandle) {
> -		up(&pCifsFile->fh_sem);
> +		mutex_lock(&pCifsFile->fh_mutex);
>  		FreeXid(xid);
>  		return 0;
>  	}
> @@ -533,7 +532,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
>  	if (full_path == NULL) {
>  		rc = -ENOMEM;
>  reopen_error_exit:
> -		up(&pCifsFile->fh_sem);
> +		mutex_lock(&pCifsFile->fh_mutex);
>  		FreeXid(xid);
>  		return rc;
>  	}
> @@ -575,14 +574,14 @@ reopen_error_exit:
>  			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
>  				CIFS_MOUNT_MAP_SPECIAL_CHR);
>  	if (rc) {
> -		up(&pCifsFile->fh_sem);
> +		mutex_lock(&pCifsFile->fh_mutex);
>  		cFYI(1, ("cifs_open returned 0x%x", rc));
>  		cFYI(1, ("oplock: %d", oplock));
>  	} else {
>  reopen_success:
>  		pCifsFile->netfid = netfid;
>  		pCifsFile->invalidHandle = false;
> -		up(&pCifsFile->fh_sem);
> +		mutex_lock(&pCifsFile->fh_mutex);
>  		pCifsInode = CIFS_I(inode);
>  		if (pCifsInode) {
>  			if (can_flush) {


-- 
Jeff Layton <jlayton at redhat.com>


More information about the linux-cifs-client mailing list