[PATCH] CIFS: Consolidate error handling for cifs_invalidate_mapping

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Base of approach for splitting all calls that uses cifs_invalidate_mapping
(or cifs_revalidate_dentry, cifs_revalidate_file) into two groups:
1) aware about -EBUSY error code and report it back (cifs_d_revalidate,
cifs_strict_fsync, cifs_file_strict_mmap);
2) don't do it (cifs_getattrs, cifs_lseek).

Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
---
 fs/cifs/cifsfs.c |    8 +++++++-
 fs/cifs/cifsfs.h |    2 +-
 fs/cifs/file.c   |   18 ++++++++++++++----
 fs/cifs/inode.c  |   30 ++++++++++++++++++------------
 4 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index de49fbb..b275d76 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -634,7 +634,13 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 		CIFS_I(file->f_path.dentry->d_inode)->time = 0;
 
 		retval = cifs_revalidate_file(file);
-		if (retval < 0)
+		/*
+		 * We only need to get right file length and don't need to
+		 * aware about busy pages (-EBUSY error code).
+		 */
+		if (retval == -EBUSY)
+			retval = 0;
+		else if (retval < 0)
 			return (loff_t)retval;
 	}
 	return generic_file_llseek_unlocked(file, offset, origin);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index bb64313..f4391ff 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -61,7 +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_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 b9731c9..d99cf48 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1448,8 +1448,13 @@ int cifs_strict_fsync(struct file *file, int datasync)
 	cFYI(1, "Sync file - name: %s datasync: 0x%x",
 		file->f_path.dentry->d_name.name, datasync);
 
-	if (!CIFS_I(inode)->clientCanCacheRead)
-		cifs_invalidate_mapping(inode);
+	if (!CIFS_I(inode)->clientCanCacheRead) {
+		rc = cifs_invalidate_mapping(inode);
+		if (rc) {
+			FreeXid(xid);
+			return rc;
+		}
+	}
 
 	tcon = tlink_tcon(smbfile->tlink);
 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
@@ -1916,8 +1921,13 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
 
 	xid = GetXid();
 
-	if (!CIFS_I(inode)->clientCanCacheRead)
-		cifs_invalidate_mapping(inode);
+	if (!CIFS_I(inode)->clientCanCacheRead) {
+		rc = cifs_invalidate_mapping(inode);
+		if (rc) {
+			FreeXid(xid);
+			return rc;
+		}
+	}
 
 	rc = generic_file_mmap(file, vma);
 	FreeXid(xid);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index adb6324..d3abfc5 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1683,27 +1683,25 @@ cifs_inode_needs_reval(struct inode *inode)
 /*
  * Zap the cache. Called when invalid_mapping flag is set.
  */
-void
+int
 cifs_invalidate_mapping(struct inode *inode)
 {
-	int rc;
+	int rc = 0;
 	struct cifsInodeInfo *cifs_i = CIFS_I(inode);
 
-	cifs_i->invalid_mapping = false;
-
 	if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
 		/* write back any cached data */
 		rc = filemap_write_and_wait(inode->i_mapping);
 		mapping_set_error(inode->i_mapping, rc);
 		rc = invalidate_inode_pages2(inode->i_mapping);
-		if (rc) {
-			cERROR(1, "%s: could not invalidate inode %p", __func__,
-			       inode);
-			cifs_i->invalid_mapping = true;
-		}
+		if (rc)
+			cFYI(1, "%s: could not invalidate inode %p", __func__,
+			     inode);
+		cifs_i->invalid_mapping = (rc != 0) ? true : false;
 	}
 
 	cifs_fscache_reset_inode_cookie(inode);
+	return rc;
 }
 
 int cifs_revalidate_file(struct file *filp)
@@ -1722,7 +1720,7 @@ int cifs_revalidate_file(struct file *filp)
 
 check_inval:
 	if (CIFS_I(inode)->invalid_mapping)
-		cifs_invalidate_mapping(inode);
+		rc = cifs_invalidate_mapping(inode);
 
 	return rc;
 }
@@ -1764,7 +1762,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
 
 check_inval:
 	if (CIFS_I(inode)->invalid_mapping)
-		cifs_invalidate_mapping(inode);
+		rc = cifs_invalidate_mapping(inode);
 
 	kfree(full_path);
 	FreeXid(xid);
@@ -1776,7 +1774,15 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
 	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-	int err = cifs_revalidate_dentry(dentry);
+	int err;
+
+	err = cifs_revalidate_dentry(dentry);
+	/*
+	 * We only need to get file attributes and don't need to
+	 * aware about busy pages (-EBUSY error code).
+	 */
+	if (err == -EBUSY)
+		err = 0;
 
 	if (!err) {
 		generic_fillattr(dentry->d_inode, stat);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux