@@ -40,6 +40,7 @@
#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
#define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */
#define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */
+#define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */
struct cifs_sb_info {
struct rb_root tlink_tree;
@@ -61,6 +61,7 @@ extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
struct dentry *);
extern int cifs_revalidate_file(struct file *filp);
extern int cifs_revalidate_dentry(struct dentry *);
+extern void cifs_invalidate_mapping(struct inode *inode);
extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int cifs_setattr(struct dentry *, struct iattr *);
@@ -124,19 +124,11 @@ static inline int cifs_open_inode_helper(struct inode *inode,
temp = cifs_NTtimeToUnix(buf->LastWriteTime);
if (timespec_equal(&inode->i_mtime, &temp) &&
(inode->i_size ==
- (loff_t)le64_to_cpu(buf->EndOfFile))) {
+ (loff_t)le64_to_cpu(buf->EndOfFile)) &&
+ !pCifsInode->invalid_mapping) {
cFYI(1, "inode unchanged on server");
- } else {
- if (inode->i_mapping) {
- /* BB no need to lock inode until after invalidate
- since namei code should already have it locked? */
- rc = filemap_write_and_wait(inode->i_mapping);
- mapping_set_error(inode->i_mapping, rc);
- }
- cFYI(1, "invalidating remote inode since open detected it "
- "changed");
- invalidate_remote_inode(inode);
- }
+ } else
+ cifs_invalidate_mapping(inode);
client_can_cache:
if (pTcon->unix_ext)
@@ -250,6 +242,9 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file,
cifs_set_oplock_level(pCifsInode, oplock);
+ if (pCifsInode->invalid_mapping)
+ cifs_invalidate_mapping(inode);
+
file->private_data = pCifsFile;
return pCifsFile;
}
@@ -264,6 +259,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
struct inode *inode = cifs_file->dentry->d_inode;
struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink);
struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsLockInfo *li, *tmp;
spin_lock(&cifs_file_list_lock);
@@ -279,6 +275,13 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
if (list_empty(&cifsi->openFileList)) {
cFYI(1, "closing last open instance for inode %p",
cifs_file->dentry->d_inode);
+
+ /* in strict cache mode we need invalidate mapping on the last
+ close because it may cause a error when we open this file
+ again and get at least level II oplock */
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
+ CIFS_I(inode)->invalid_mapping = true;
+
cifs_set_oplock_level(cifsi, 0);
}
spin_unlock(&cifs_file_list_lock);
@@ -1671,8 +1671,7 @@ cifs_inode_needs_reval(struct inode *inode)
}
/* check invalid_mapping flag and zap the cache if it's set */
-static void
-cifs_invalidate_mapping(struct inode *inode)
+void cifs_invalidate_mapping(struct inode *inode)
{
int rc;
struct cifsInodeInfo *cifs_i = CIFS_I(inode);