Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 May 2009 14:38:28 +0000 (07:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 22 May 2009 14:38:28 +0000 (07:38 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] fix posix open regression

fs/cifs/dir.c
fs/cifs/file.c

index 11431ed..f49d684 100644 (file)
@@ -225,6 +225,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
        if (!(oflags & FMODE_READ))
                write_only = true;
 
+       mode &= ~current_umask();
        rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
                        pnetfid, presp_data, &oplock, full_path,
                        cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -310,7 +311,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                return -ENOMEM;
        }
 
-       mode &= ~current_umask();
        if (oplockEnabled)
                oplock = REQ_OPLOCK;
 
@@ -336,7 +336,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        else /* success, no need to query */
                                goto cifs_create_set_dentry;
                } else if ((rc != -EIO) && (rc != -EREMOTE) &&
-                        (rc != -EOPNOTSUPP)) /* path not found or net err */
+                        (rc != -EOPNOTSUPP) && (rc != -EINVAL))
                        goto cifs_create_out;
                /* else fallthrough to retry, using older open call, this is
                   case where server does not support this SMB level, and
@@ -609,7 +609,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        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;
@@ -660,13 +659,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 
        if (pTcon->unix_ext) {
                if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
-                               (nd->flags & LOOKUP_OPEN)) {
+                    (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open) {
                        if (!((nd->intent.open.flags & O_CREAT) &&
                                        (nd->intent.open.flags & O_EXCL))) {
-                               mode = nd->intent.open.create_mode &
-                                               ~current_umask();
                                rc = cifs_posix_open(full_path, &newInode,
-                                       parent_dir_inode->i_sb, mode,
+                                       parent_dir_inode->i_sb,
+                                       nd->intent.open.create_mode,
                                        nd->intent.open.flags, &oplock,
                                        &fileHandle, xid);
                                /*
@@ -681,6 +679,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                                 */
                                if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
                                        posix_open = true;
+                               else
+                                       pTcon->broken_posix_open = true;
                        }
                }
                if (!posix_open)
index 38c06f8..302ea15 100644 (file)
@@ -130,10 +130,6 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
                        struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
 {
 
-       file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-       if (file->private_data == NULL)
-               return -ENOMEM;
-       pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
        write_lock(&GlobalSMBSeslock);
 
        pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
@@ -184,6 +180,38 @@ psx_client_can_cache:
        return 0;
 }
 
+static struct cifsFileInfo *
+cifs_fill_filedata(struct file *file)
+{
+       struct list_head *tmp;
+       struct cifsFileInfo *pCifsFile = NULL;
+       struct cifsInodeInfo *pCifsInode = NULL;
+
+       /* 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) {
+               return pCifsFile;
+       } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
+                       cERROR(1, ("could not find file instance for "
+                                  "new file %p", file));
+       return NULL;
+}
+
 /* all arguments to this function must be checked for validity in caller */
 static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
        struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
@@ -258,7 +286,6 @@ int cifs_open(struct inode *inode, struct file *file)
        struct cifsTconInfo *tcon;
        struct cifsFileInfo *pCifsFile;
        struct cifsInodeInfo *pCifsInode;
-       struct list_head *tmp;
        char *full_path = NULL;
        int desiredAccess;
        int disposition;
@@ -270,32 +297,12 @@ int cifs_open(struct inode *inode, struct file *file)
        cifs_sb = CIFS_SB(inode->i_sb);
        tcon = cifs_sb->tcon;
 
-       /* 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;
+       pCifsFile = cifs_fill_filedata(file);
+       if (pCifsFile) {
                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));
+               return 0;
+       }
 
        full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
@@ -325,6 +332,7 @@ int cifs_open(struct inode *inode, struct file *file)
                        /* no need for special case handling of setting mode
                           on read only files needed here */
 
+                       pCifsFile = cifs_fill_filedata(file);
                        cifs_posix_open_inode_helper(inode, file, pCifsInode,
                                                     pCifsFile, oplock, netfid);
                        goto out;