[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