diff mbox

[1/6] CIFS: Make cifsFileInfo_put work with strict cache mode

Message ID 1289459222-8210-1-git-send-email-piastryyy@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pavel Shilovsky Nov. 11, 2010, 7:07 a.m. UTC
None
diff mbox

Patch

diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index e9a393c..be7b159 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -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;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 897b2b2..b8d783c 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -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 *);
 
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 06c3e83..d604e09 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -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);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ef3a55b..518514e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -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);