Loading fs/cifs/file.c +111 −13 Original line number Diff line number Diff line Loading @@ -124,6 +124,80 @@ 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, struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) { struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); /* struct timespec temp; */ /* BB REMOVEME BB */ 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); list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode == NULL) { write_unlock(&GlobalSMBSeslock); return -EINVAL; } /* want handles we can use to read with first in the list so we do not have to walk the list to search for one in write_begin */ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); } else { list_add(&pCifsFile->flist, &pCifsInode->openFileList); } 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 file *file, struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, Loading Loading @@ -195,7 +269,7 @@ int cifs_open(struct inode *inode, struct file *file) int rc = -EACCES; int xid, oplock; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; struct cifsTconInfo *tcon; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; struct list_head *tmp; Loading @@ -208,7 +282,7 @@ int cifs_open(struct inode *inode, struct file *file) xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; tcon = cifs_sb->tcon; if (file->f_flags & O_CREAT) { /* search inode for this file and fill in file->private_data */ Loading Loading @@ -248,6 +322,35 @@ int cifs_open(struct inode *inode, struct file *file) cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags, full_path)); if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; 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 */ rc = cifs_posix_open(full_path, &inode, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, oflags, &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 */ cifs_posix_open_inode_helper(inode, file, pCifsInode, pCifsFile, oplock, netfid); goto out; } else if ((rc != -EIO) && (rc != -EREMOTE) && (rc != -EOPNOTSUPP)) /* path not found or net err */ goto out; /* fallthrough to retry open the old way on operation not supported or DFS errors */ } desiredAccess = cifs_convert_flags(file->f_flags); /********************************************************************* Loading Loading @@ -276,11 +379,6 @@ int cifs_open(struct inode *inode, struct file *file) disposition = cifs_get_disposition(file->f_flags); if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; /* BB pass O_SYNC flag through on file attributes .. BB */ /* Also refresh inode by passing in file_info buf returned by SMBOpen Loading @@ -297,7 +395,7 @@ int cifs_open(struct inode *inode, struct file *file) } if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -306,7 +404,7 @@ int cifs_open(struct inode *inode, struct file *file) if (rc == -EIO) { /* Old server, try legacy style OpenX */ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, rc = SMBLegacyOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -323,12 +421,12 @@ int cifs_open(struct inode *inode, struct file *file) } pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); write_lock(&GlobalSMBSeslock); list_add(&pCifsFile->tlist, &pTcon->openFileList); list_add(&pCifsFile->tlist, &tcon->openFileList); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode) { rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, pTcon, pCifsFile, tcon, &oplock, buf, full_path, xid); } else { write_unlock(&GlobalSMBSeslock); Loading @@ -337,7 +435,7 @@ int cifs_open(struct inode *inode, struct file *file) if (oplock & CIFS_CREATE_ACTION) { /* time to set mode which we can not set earlier due to problems creating new read-only files */ if (pTcon->unix_ext) { if (tcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = inode->i_mode, .uid = NO_CHANGE_64, Loading @@ -347,7 +445,7 @@ int cifs_open(struct inode *inode, struct file *file) .mtime = NO_CHANGE_64, .device = 0, }; CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading Loading
fs/cifs/file.c +111 −13 Original line number Diff line number Diff line Loading @@ -124,6 +124,80 @@ 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, struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) { struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); /* struct timespec temp; */ /* BB REMOVEME BB */ 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); list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode == NULL) { write_unlock(&GlobalSMBSeslock); return -EINVAL; } /* want handles we can use to read with first in the list so we do not have to walk the list to search for one in write_begin */ if ((file->f_flags & O_ACCMODE) == O_WRONLY) { list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); } else { list_add(&pCifsFile->flist, &pCifsInode->openFileList); } 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 file *file, struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, Loading Loading @@ -195,7 +269,7 @@ int cifs_open(struct inode *inode, struct file *file) int rc = -EACCES; int xid, oplock; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; struct cifsTconInfo *tcon; struct cifsFileInfo *pCifsFile; struct cifsInodeInfo *pCifsInode; struct list_head *tmp; Loading @@ -208,7 +282,7 @@ int cifs_open(struct inode *inode, struct file *file) xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; tcon = cifs_sb->tcon; if (file->f_flags & O_CREAT) { /* search inode for this file and fill in file->private_data */ Loading Loading @@ -248,6 +322,35 @@ int cifs_open(struct inode *inode, struct file *file) cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags, full_path)); if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; 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 */ rc = cifs_posix_open(full_path, &inode, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, oflags, &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 */ cifs_posix_open_inode_helper(inode, file, pCifsInode, pCifsFile, oplock, netfid); goto out; } else if ((rc != -EIO) && (rc != -EREMOTE) && (rc != -EOPNOTSUPP)) /* path not found or net err */ goto out; /* fallthrough to retry open the old way on operation not supported or DFS errors */ } desiredAccess = cifs_convert_flags(file->f_flags); /********************************************************************* Loading Loading @@ -276,11 +379,6 @@ int cifs_open(struct inode *inode, struct file *file) disposition = cifs_get_disposition(file->f_flags); if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; /* BB pass O_SYNC flag through on file attributes .. BB */ /* Also refresh inode by passing in file_info buf returned by SMBOpen Loading @@ -297,7 +395,7 @@ int cifs_open(struct inode *inode, struct file *file) } if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -306,7 +404,7 @@ int cifs_open(struct inode *inode, struct file *file) if (rc == -EIO) { /* Old server, try legacy style OpenX */ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, rc = SMBLegacyOpen(xid, tcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading @@ -323,12 +421,12 @@ int cifs_open(struct inode *inode, struct file *file) } pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); write_lock(&GlobalSMBSeslock); list_add(&pCifsFile->tlist, &pTcon->openFileList); list_add(&pCifsFile->tlist, &tcon->openFileList); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode) { rc = cifs_open_inode_helper(inode, file, pCifsInode, pCifsFile, pTcon, pCifsFile, tcon, &oplock, buf, full_path, xid); } else { write_unlock(&GlobalSMBSeslock); Loading @@ -337,7 +435,7 @@ int cifs_open(struct inode *inode, struct file *file) if (oplock & CIFS_CREATE_ACTION) { /* time to set mode which we can not set earlier due to problems creating new read-only files */ if (pTcon->unix_ext) { if (tcon->unix_ext) { struct cifs_unix_set_info_args args = { .mode = inode->i_mode, .uid = NO_CHANGE_64, Loading @@ -347,7 +445,7 @@ int cifs_open(struct inode *inode, struct file *file) .mtime = NO_CHANGE_64, .device = 0, }; CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, CIFSSMBUnixSetInfo(xid, tcon, full_path, &args, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); Loading