cifs: eliminate pfile pointer from cifsFileInfo
[pandora-kernel.git] / fs / cifs / file.c
index c302b9c..7935816 100644 (file)
@@ -60,34 +60,32 @@ static inline int cifs_convert_flags(unsigned int flags)
                FILE_READ_DATA);
 }
 
-static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
+static u32 cifs_posix_convert_flags(unsigned int flags)
 {
-       fmode_t posix_flags = 0;
+       u32 posix_flags = 0;
 
        if ((flags & O_ACCMODE) == O_RDONLY)
-               posix_flags = FMODE_READ;
+               posix_flags = SMB_O_RDONLY;
        else if ((flags & O_ACCMODE) == O_WRONLY)
-               posix_flags = FMODE_WRITE;
-       else if ((flags & O_ACCMODE) == O_RDWR) {
-               /* GENERIC_ALL is too much permission to request
-                  can cause unnecessary access denied on create */
-               /* return GENERIC_ALL; */
-               posix_flags = FMODE_READ | FMODE_WRITE;
-       }
-       /* can not map O_CREAT or O_EXCL or O_TRUNC flags when
-          reopening a file.  They had their effect on the original open */
-       if (flags & O_APPEND)
-               posix_flags |= (fmode_t)O_APPEND;
+               posix_flags = SMB_O_WRONLY;
+       else if ((flags & O_ACCMODE) == O_RDWR)
+               posix_flags = SMB_O_RDWR;
+
+       if (flags & O_CREAT)
+               posix_flags |= SMB_O_CREAT;
+       if (flags & O_EXCL)
+               posix_flags |= SMB_O_EXCL;
+       if (flags & O_TRUNC)
+               posix_flags |= SMB_O_TRUNC;
+       /* be safe and imply O_SYNC for O_DSYNC */
        if (flags & O_DSYNC)
-               posix_flags |= (fmode_t)O_DSYNC;
-       if (flags & __O_SYNC)
-               posix_flags |= (fmode_t)__O_SYNC;
+               posix_flags |= SMB_O_SYNC;
        if (flags & O_DIRECTORY)
-               posix_flags |= (fmode_t)O_DIRECTORY;
+               posix_flags |= SMB_O_DIRECTORY;
        if (flags & O_NOFOLLOW)
-               posix_flags |= (fmode_t)O_NOFOLLOW;
+               posix_flags |= SMB_O_NOFOLLOW;
        if (flags & O_DIRECT)
-               posix_flags |= (fmode_t)O_DIRECT;
+               posix_flags |= SMB_O_DIRECT;
 
        return posix_flags;
 }
@@ -106,64 +104,6 @@ static inline int cifs_get_disposition(unsigned int flags)
                return FILE_OPEN;
 }
 
-/* all arguments to this function must be checked for validity in caller */
-static inline int
-cifs_posix_open_inode_helper(struct inode *inode, struct file *file,
-                            struct cifsInodeInfo *pCifsInode, __u32 oplock,
-                            u16 netfid)
-{
-
-       write_lock(&GlobalSMBSeslock);
-
-       pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
-       if (pCifsInode == NULL) {
-               write_unlock(&GlobalSMBSeslock);
-               return -EINVAL;
-       }
-
-       if (pCifsInode->clientCanCacheRead) {
-               /* we have the inode open somewhere else
-                  no need to discard cache data */
-               goto psx_client_can_cache;
-       }
-
-       /* BB FIXME need to fix this check to move it earlier into posix_open
-          BB  fIX following section BB FIXME */
-
-       /* if not oplocked, invalidate inode pages if mtime or file
-          size changed */
-/*     temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
-       if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
-                          (file->f_path.dentry->d_inode->i_size ==
-                           (loff_t)le64_to_cpu(buf->EndOfFile))) {
-               cFYI(1, "inode unchanged on server");
-       } else {
-               if (file->f_path.dentry->d_inode->i_mapping) {
-                       rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
-                       if (rc != 0)
-                               CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc;
-               }
-               cFYI(1, "invalidating remote inode since open detected it "
-                        "changed");
-               invalidate_remote_inode(file->f_path.dentry->d_inode);
-       } */
-
-psx_client_can_cache:
-       if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-               pCifsInode->clientCanCacheAll = true;
-               pCifsInode->clientCanCacheRead = true;
-               cFYI(1, "Exclusive Oplock granted on inode %p",
-                        file->f_path.dentry->d_inode);
-       } else if ((oplock & 0xF) == OPLOCK_READ)
-               pCifsInode->clientCanCacheRead = true;
-
-       /* will have to change the unlock if we reenable the
-          filemap_fdatawrite (which does not seem necessary */
-       write_unlock(&GlobalSMBSeslock);
-       return 0;
-}
-
-/* all arguments to this function must be checked for validity in caller */
 static inline int cifs_open_inode_helper(struct inode *inode,
        struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf,
        char *full_path, int xid)
@@ -217,6 +157,68 @@ client_can_cache:
        return rc;
 }
 
+int cifs_posix_open(char *full_path, struct inode **pinode,
+                       struct super_block *sb, int mode, unsigned int f_flags,
+                       __u32 *poplock, __u16 *pnetfid, int xid)
+{
+       int rc;
+       FILE_UNIX_BASIC_INFO *presp_data;
+       __u32 posix_flags = 0;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+       struct cifs_fattr fattr;
+       struct tcon_link *tlink;
+       struct cifsTconInfo *tcon;
+
+       cFYI(1, "posix open %s", full_path);
+
+       presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+       if (presp_data == NULL)
+               return -ENOMEM;
+
+       tlink = cifs_sb_tlink(cifs_sb);
+       if (IS_ERR(tlink)) {
+               rc = PTR_ERR(tlink);
+               goto posix_open_ret;
+       }
+
+       tcon = tlink_tcon(tlink);
+       mode &= ~current_umask();
+
+       posix_flags = cifs_posix_convert_flags(f_flags);
+       rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data,
+                            poplock, full_path, cifs_sb->local_nls,
+                            cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+       cifs_put_tlink(tlink);
+
+       if (rc)
+               goto posix_open_ret;
+
+       if (presp_data->Type == cpu_to_le32(-1))
+               goto posix_open_ret; /* open ok, caller does qpathinfo */
+
+       if (!pinode)
+               goto posix_open_ret; /* caller does not need info */
+
+       cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
+
+       /* get new inode and set it up */
+       if (*pinode == NULL) {
+               cifs_fill_uniqueid(sb, &fattr);
+               *pinode = cifs_iget(sb, &fattr);
+               if (!*pinode) {
+                       rc = -ENOMEM;
+                       goto posix_open_ret;
+               }
+       } else {
+               cifs_fattr_to_inode(*pinode, &fattr);
+       }
+
+posix_open_ret:
+       kfree(presp_data);
+       return rc;
+}
+
 int cifs_open(struct inode *inode, struct file *file)
 {
        int rc = -EACCES;
@@ -263,27 +265,15 @@ int cifs_open(struct inode *inode, struct file *file)
            (tcon->ses->capabilities & CAP_UNIX) &&
            (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-               int oflags = (int) cifs_posix_convert_flags(file->f_flags);
-               oflags |= SMB_O_CREAT;
                /* can not refresh inode info since size could be stale */
                rc = cifs_posix_open(full_path, &inode, inode->i_sb,
                                cifs_sb->mnt_file_mode /* ignored */,
-                               oflags, &oplock, &netfid, xid);
+                               file->f_flags, &oplock, &netfid, xid);
                if (rc == 0) {
                        cFYI(1, "posix open succeeded");
-                       /* no need for special case handling of setting mode
-                          on read only files needed here */
 
-                       rc = cifs_posix_open_inode_helper(inode, file,
-                                       pCifsInode, oplock, netfid);
-                       if (rc != 0) {
-                               CIFSSMBClose(xid, tcon, netfid);
-                               goto out;
-                       }
-
-                       pCifsFile = cifs_new_fileinfo(inode, netfid, file,
-                                                       file->f_path.mnt,
-                                                       tlink, oflags, oplock);
+                       pCifsFile = cifs_new_fileinfo(netfid, file, tlink,
+                                                     oplock);
                        if (pCifsFile == NULL) {
                                CIFSSMBClose(xid, tcon, netfid);
                                rc = -ENOMEM;
@@ -375,8 +365,7 @@ int cifs_open(struct inode *inode, struct file *file)
        if (rc != 0)
                goto out;
 
-       pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
-                                       tlink, file->f_flags, oplock);
+       pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock);
        if (pCifsFile == NULL) {
                rc = -ENOMEM;
                goto out;
@@ -423,14 +412,13 @@ static int cifs_relock_file(struct cifsFileInfo *cifsFile)
        return rc;
 }
 
-static int cifs_reopen_file(struct file *file, bool can_flush)
+static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush)
 {
        int rc = -EACCES;
        int xid;
        __u32 oplock;
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *tcon;
-       struct cifsFileInfo *pCifsFile;
        struct cifsInodeInfo *pCifsInode;
        struct inode *inode;
        char *full_path = NULL;
@@ -438,11 +426,6 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
        int disposition = FILE_OPEN;
        __u16 netfid;
 
-       if (file->private_data)
-               pCifsFile = file->private_data;
-       else
-               return -EBADF;
-
        xid = GetXid();
        mutex_lock(&pCifsFile->fh_mutex);
        if (!pCifsFile->invalidHandle) {
@@ -452,21 +435,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
                return rc;
        }
 
-       if (file->f_path.dentry == NULL) {
-               cERROR(1, "no valid name if dentry freed");
-               dump_stack();
-               rc = -EBADF;
-               goto reopen_error_exit;
-       }
-
-       inode = file->f_path.dentry->d_inode;
-       if (inode == NULL) {
-               cERROR(1, "inode not valid");
-               dump_stack();
-               rc = -EBADF;
-               goto reopen_error_exit;
-       }
-
+       inode = pCifsFile->dentry->d_inode;
        cifs_sb = CIFS_SB(inode->i_sb);
        tcon = tlink_tcon(pCifsFile->tlink);
 
@@ -474,17 +443,16 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
    those that already have the rename sem can end up causing writepage
    to get called and if the server was down that means we end up here,
    and we can never tell if the caller already has the rename_sem */
-       full_path = build_path_from_dentry(file->f_path.dentry);
+       full_path = build_path_from_dentry(pCifsFile->dentry);
        if (full_path == NULL) {
                rc = -ENOMEM;
-reopen_error_exit:
                mutex_unlock(&pCifsFile->fh_mutex);
                FreeXid(xid);
                return rc;
        }
 
        cFYI(1, "inode = 0x%p file flags 0x%x for %s",
-                inode, file->f_flags, full_path);
+                inode, pCifsFile->f_flags, full_path);
 
        if (oplockEnabled)
                oplock = REQ_OPLOCK;
@@ -494,8 +462,14 @@ reopen_error_exit:
        if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
            (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
-               int oflags = (int) cifs_posix_convert_flags(file->f_flags);
-               /* can not refresh inode info since size could be stale */
+
+               /*
+                * O_CREAT, O_EXCL and O_TRUNC already had their effect on the
+                * original open. Must mask them off for a reopen.
+                */
+               unsigned int oflags = pCifsFile->f_flags &
+                                               ~(O_CREAT | O_EXCL | O_TRUNC);
+
                rc = cifs_posix_open(full_path, NULL, inode->i_sb,
                                cifs_sb->mnt_file_mode /* ignored */,
                                oflags, &oplock, &netfid, xid);
@@ -507,7 +481,7 @@ reopen_error_exit:
                   in the reconnect path it is important to retry hard */
        }
 
-       desiredAccess = cifs_convert_flags(file->f_flags);
+       desiredAccess = cifs_convert_flags(pCifsFile->f_flags);
 
        /* Can not refresh inode by passing in file_info buf to be returned
           by SMBOpen and then calling get_inode_info with returned buf
@@ -523,49 +497,50 @@ reopen_error_exit:
                mutex_unlock(&pCifsFile->fh_mutex);
                cFYI(1, "cifs_open returned 0x%x", rc);
                cFYI(1, "oplock: %d", oplock);
-       } else {
+               goto reopen_error_exit;
+       }
+
 reopen_success:
-               pCifsFile->netfid = netfid;
-               pCifsFile->invalidHandle = false;
-               mutex_unlock(&pCifsFile->fh_mutex);
-               pCifsInode = CIFS_I(inode);
-               if (pCifsInode) {
-                       if (can_flush) {
-                               rc = filemap_write_and_wait(inode->i_mapping);
-                               if (rc != 0)
-                                       CIFS_I(inode)->write_behind_rc = rc;
-                       /* temporarily disable caching while we
-                          go to server to get inode info */
-                               pCifsInode->clientCanCacheAll = false;
-                               pCifsInode->clientCanCacheRead = false;
-                               if (tcon->unix_ext)
-                                       rc = cifs_get_inode_info_unix(&inode,
-                                               full_path, inode->i_sb, xid);
-                               else
-                                       rc = cifs_get_inode_info(&inode,
-                                               full_path, NULL, inode->i_sb,
-                                               xid, NULL);
-                       } /* else we are writing out data to server already
-                            and could deadlock if we tried to flush data, and
-                            since we do not know if we have data that would
-                            invalidate the current end of file on the server
-                            we can not go to the server to get the new inod
-                            info */
-                       if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
-                               pCifsInode->clientCanCacheAll = true;
-                               pCifsInode->clientCanCacheRead = true;
-                               cFYI(1, "Exclusive Oplock granted on inode %p",
-                                        file->f_path.dentry->d_inode);
-                       } else if ((oplock & 0xF) == OPLOCK_READ) {
-                               pCifsInode->clientCanCacheRead = true;
-                               pCifsInode->clientCanCacheAll = false;
-                       } else {
-                               pCifsInode->clientCanCacheRead = false;
-                               pCifsInode->clientCanCacheAll = false;
-                       }
-                       cifs_relock_file(pCifsFile);
-               }
+       pCifsFile->netfid = netfid;
+       pCifsFile->invalidHandle = false;
+       mutex_unlock(&pCifsFile->fh_mutex);
+       pCifsInode = CIFS_I(inode);
+
+       if (can_flush) {
+               rc = filemap_write_and_wait(inode->i_mapping);
+               if (rc != 0)
+                       CIFS_I(inode)->write_behind_rc = rc;
+
+               pCifsInode->clientCanCacheAll = false;
+               pCifsInode->clientCanCacheRead = false;
+               if (tcon->unix_ext)
+                       rc = cifs_get_inode_info_unix(&inode,
+                               full_path, inode->i_sb, xid);
+               else
+                       rc = cifs_get_inode_info(&inode,
+                               full_path, NULL, inode->i_sb,
+                               xid, NULL);
+       } /* else we are writing out data to server already
+            and could deadlock if we tried to flush data, and
+            since we do not know if we have data that would
+            invalidate the current end of file on the server
+            we can not go to the server to get the new inod
+            info */
+       if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+               pCifsInode->clientCanCacheAll = true;
+               pCifsInode->clientCanCacheRead = true;
+               cFYI(1, "Exclusive Oplock granted on inode %p",
+                        pCifsFile->dentry->d_inode);
+       } else if ((oplock & 0xF) == OPLOCK_READ) {
+               pCifsInode->clientCanCacheRead = true;
+               pCifsInode->clientCanCacheAll = false;
+       } else {
+               pCifsInode->clientCanCacheRead = false;
+               pCifsInode->clientCanCacheAll = false;
        }
+       cifs_relock_file(pCifsFile);
+
+reopen_error_exit:
        kfree(full_path);
        FreeXid(xid);
        return rc;
@@ -1004,7 +979,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
                                   filemap_fdatawait from here so tell
                                   reopen_file not to flush data to server
                                   now */
-                               rc = cifs_reopen_file(file, false);
+                               rc = cifs_reopen_file(open_file, false);
                                if (rc != 0)
                                        break;
                        }
@@ -1052,8 +1027,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
        return total_written;
 }
 
-static ssize_t cifs_write(struct file *file, const char *write_data,
-                         size_t write_size, loff_t *poffset)
+static ssize_t cifs_write(struct cifsFileInfo *open_file,
+                         const char *write_data, size_t write_size,
+                         loff_t *poffset)
 {
        int rc = 0;
        unsigned int bytes_written = 0;
@@ -1061,17 +1037,14 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *pTcon;
        int xid, long_op;
-       struct cifsFileInfo *open_file;
-       struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);
+       struct dentry *dentry = open_file->dentry;
+       struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
 
-       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+       cifs_sb = CIFS_SB(dentry->d_sb);
 
        cFYI(1, "write %zd bytes to offset %lld of %s", write_size,
-          *poffset, file->f_path.dentry->d_name.name);
+          *poffset, dentry->d_name.name);
 
-       if (file->private_data == NULL)
-               return -EBADF;
-       open_file = file->private_data;
        pTcon = tlink_tcon(open_file->tlink);
 
        xid = GetXid();
@@ -1081,15 +1054,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
             total_written += bytes_written) {
                rc = -EAGAIN;
                while (rc == -EAGAIN) {
-                       if (file->private_data == NULL) {
-                               /* file has been closed on us */
-                               FreeXid(xid);
-                       /* if we have gotten here we have written some data
-                          and blocked, and the file has been freed on us
-                          while we blocked so return what we managed to
-                          write */
-                               return total_written;
-                       }
                        if (open_file->closePend) {
                                FreeXid(xid);
                                if (total_written)
@@ -1102,7 +1066,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
                                   filemap_fdatawait from here so tell
                                   reopen_file not to flush data to
                                   server now */
-                               rc = cifs_reopen_file(file, false);
+                               rc = cifs_reopen_file(open_file, false);
                                if (rc != 0)
                                        break;
                        }
@@ -1149,20 +1113,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
 
        cifs_stats_bytes_written(pTcon, total_written);
 
-       /* since the write may have blocked check these pointers again */
-       if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
-/*BB We could make this contingent on superblock ATIME flag too */
-/*             file->f_path.dentry->d_inode->i_ctime =
-               file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/
-               if (total_written > 0) {
-                       spin_lock(&file->f_path.dentry->d_inode->i_lock);
-                       if (*poffset > file->f_path.dentry->d_inode->i_size)
-                               i_size_write(file->f_path.dentry->d_inode,
-                                            *poffset);
-                       spin_unlock(&file->f_path.dentry->d_inode->i_lock);
-               }
-               mark_inode_dirty_sync(file->f_path.dentry->d_inode);
+       if (total_written > 0) {
+               spin_lock(&dentry->d_inode->i_lock);
+               if (*poffset > dentry->d_inode->i_size)
+                       i_size_write(dentry->d_inode, *poffset);
+               spin_unlock(&dentry->d_inode->i_lock);
        }
+       mark_inode_dirty_sync(dentry->d_inode);
        FreeXid(xid);
        return total_written;
 }
@@ -1187,8 +1144,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                        continue;
                if (fsuid_only && open_file->uid != current_fsuid())
                        continue;
-               if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
-                   (open_file->pfile->f_flags & O_RDONLY))) {
+               if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
                        if (!open_file->invalidHandle) {
                                /* found a good file */
                                /* lock it so it will not be closed on us */
@@ -1237,9 +1193,7 @@ refind_writable:
                        continue;
                if (fsuid_only && open_file->uid != current_fsuid())
                        continue;
-               if (open_file->pfile &&
-                   ((open_file->pfile->f_flags & O_RDWR) ||
-                    (open_file->pfile->f_flags & O_WRONLY))) {
+               if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
                        cifsFileInfo_get(open_file);
 
                        if (!open_file->invalidHandle) {
@@ -1250,7 +1204,7 @@ refind_writable:
 
                        read_unlock(&GlobalSMBSeslock);
                        /* Had to unlock since following call can block */
-                       rc = cifs_reopen_file(open_file->pfile, false);
+                       rc = cifs_reopen_file(open_file, false);
                        if (!rc) {
                                if (!open_file->closePend)
                                        return open_file;
@@ -1333,8 +1287,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
 
        open_file = find_writable_file(CIFS_I(mapping->host), false);
        if (open_file) {
-               bytes_written = cifs_write(open_file->pfile, write_data,
-                                          to-from, &offset);
+               bytes_written = cifs_write(open_file, write_data,
+                                          to - from, &offset);
                cifsFileInfo_put(open_file);
                /* Does mm or vfs already set times? */
                inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
@@ -1649,7 +1603,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
                /* BB check if anything else missing out of ppw
                   such as updating last write time */
                page_data = kmap(page);
-               rc = cifs_write(file, page_data + offset, copied, &pos);
+               rc = cifs_write(file->private_data, page_data + offset,
+                               copied, &pos);
                /* if (rc < 0) should we set writebehind rc? */
                kunmap(page);
 
@@ -1798,7 +1753,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
                        int buf_type = CIFS_NO_BUFFER;
                        if ((open_file->invalidHandle) &&
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file, true);
+                               rc = cifs_reopen_file(open_file, true);
                                if (rc != 0)
                                        break;
                        }
@@ -1884,7 +1839,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
                while (rc == -EAGAIN) {
                        if ((open_file->invalidHandle) &&
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file, true);
+                               rc = cifs_reopen_file(open_file, true);
                                if (rc != 0)
                                        break;
                        }
@@ -2049,7 +2004,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                while (rc == -EAGAIN) {
                        if ((open_file->invalidHandle) &&
                            (!open_file->closePend)) {
-                               rc = cifs_reopen_file(file, true);
+                               rc = cifs_reopen_file(open_file, true);
                                if (rc != 0)
                                        break;
                        }
@@ -2202,9 +2157,7 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
        list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
                if (open_file->closePend)
                        continue;
-               if (open_file->pfile &&
-                   ((open_file->pfile->f_flags & O_RDWR) ||
-                    (open_file->pfile->f_flags & O_WRONLY))) {
+               if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
                        read_unlock(&GlobalSMBSeslock);
                        return 1;
                }
@@ -2381,14 +2334,14 @@ void cifs_oplock_break(struct work_struct *work)
 
 void cifs_oplock_break_get(struct cifsFileInfo *cfile)
 {
-       mntget(cfile->mnt);
+       cifs_sb_active(cfile->dentry->d_sb);
        cifsFileInfo_get(cfile);
 }
 
 void cifs_oplock_break_put(struct cifsFileInfo *cfile)
 {
-       mntput(cfile->mnt);
        cifsFileInfo_put(cfile);
+       cifs_sb_deactive(cfile->dentry->d_sb);
 }
 
 const struct address_space_operations cifs_addr_ops = {