[linux-cifs-client] Re: lookup intent patch
Shirish Pargaonkar
shirishpargaonkar at gmail.com
Mon Mar 30 15:57:32 GMT 2009
On Fri, Mar 27, 2009 at 1:13 PM, Jeff Layton <jlayton at redhat.com> wrote:
> On Fri, 27 Mar 2009 10:15:21 -0500
> Shirish Pargaonkar <shirishpargaonkar at gmail.com> wrote:
>
> Please run this through checkpatch.pl, there is a lot of bad whitespace
> in this patch:
>
>> diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
>> index f9b6f68..011d0ac 100644
>> --- a/fs/cifs/dir.c
>> +++ b/fs/cifs/dir.c
>> @@ -129,12 +129,67 @@ 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;
>> +
>> + cERROR(1, ("cifs_fill_fileinfo enter\n"));
>> +
>> + 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;
>> + init_MUTEX(&pCifsFile->fh_sem);
> ^^^^
> Can you convert this to a mutex while you're at it? Might not hurt to make
> that a separate patch though.
>
>> + 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);
>> + cERROR(1, ("cifs_fill_fileinfo exit\n"));
>> +}
>> +
>> 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 +227,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 +255,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 +298,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 +468,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,13 +602,16 @@ 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;
>> @@ -632,12 +657,26 @@ 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);
>> + posix_open = true;
>> + }
>> + }
>> + if (!posix_open || ((rc == -EINVAL) || (rc == -EOPNOTSUPP)))
>> + 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);
>>
>
> Ok, so you're opening the file on lookup now. Aren't you supposed to use
> lookup_instantiate_filp() to pass an instantiated file pointer back to the
> caller? If you don't do this, then I think you're susceptible to leaking
> this open file if an error occurs between the lookup and the open.
>
> nfs4 does something very similar to what you're trying to do here. You
> might want to look carefully at it as an example. nfs4_atomic_open()
> is a good place to start.
>
>> if ((rc == 0) && (newInode != NULL)) {
>> if (pTcon->nocase)
>> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> index 81747ac..4a7c886 100644
>> --- a/fs/cifs/file.c
>> +++ b/fs/cifs/file.c
>> @@ -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))
>> + 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) {
>
>
> --
> Jeff Layton <jlayton at redhat.com>
>
Jeff,
Thanks. Looking into it. I am trying to figure out the need/necessity
for cifs_lookup to call lookup_instanitate_flip.
lookup_instantiate_filp does call dentry_open and if cifs_lookup does
not call lookup_instantiate_flip,
nameidata_to_filp will call dentry_open.
So I am not sure what we loose if dentry_open does not get called
between lookup_hash and nameidata_to_flip
because of an error between those two calls, specifically how will the
cause of open file getting closed on the
server will be served if there was an in-betwen error by calling
lookup_instantiate_filp.
Regards,
Shirish
More information about the linux-cifs-client
mailing list