patch-2.1.61 linux/fs/nfs/file.c

Next file: linux/fs/nfs/inode.c
Previous file: linux/fs/nfs/dir.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.60/linux/fs/nfs/file.c linux/fs/nfs/file.c
@@ -83,53 +83,77 @@
 # define IS_SWAPFILE(inode)	(0)
 #endif
 
-
+/*
+ * Flush all dirty pages, and check for write errors.
+ *
+ * Note that since the file close operation is called only by the
+ * _last_ process to close the file, we need to flush _all_ dirty 
+ * pages. This also means that there is little sense in checking
+ * for errors for this specific process -- we should probably just
+ * clear all errors.
+ */
 static int
 nfs_file_close(struct inode *inode, struct file *file)
 {
-	int	status;
+	int	status, error;
 
 	dfprintk(VFS, "nfs: close(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
-	if ((status = nfs_flush_dirty_pages(inode, 0, 0)) < 0)
-		return status;
-	return nfs_write_error(inode);
+	status = nfs_flush_dirty_pages(inode, 0, 0, 0);
+	error = nfs_write_error(inode);
+	if (!status)
+		status = error;
+	return status;
 }
 
 static ssize_t
 nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
 {
 	struct inode * inode = file->f_dentry->d_inode;
-	int	status;
+	ssize_t result;
 
 	dfprintk(VFS, "nfs: read(%x/%ld, %lu@%lu)\n",
 			inode->i_dev, inode->i_ino, count,
 			(unsigned long) *ppos);
 
-	if ((status = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0)
-		return status;
-	return generic_file_read(file, buf, count, ppos);
+	result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (!result)
+		result = generic_file_read(file, buf, count, ppos);
+	return result;
 }
 
 static int
 nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
-	int	status;
 	struct inode *inode = file->f_dentry->d_inode;
+	int	status;
 
 	dfprintk(VFS, "nfs: mmap(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
-	if ((status = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0)
-		return status;
-	return generic_file_mmap(file, vma);
+	status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (!status)
+		status = generic_file_mmap(file, vma);
+	return status;
 }
 
-static int nfs_fsync(struct file *file, struct dentry *dentry)
+/*
+ * Flush any dirty pages for this process, and check for write errors.
+ * The return status from this call provides a reliable indication of
+ * whether any write errors occurred for this process.
+ */
+static int
+nfs_fsync(struct file *file, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
+	int status, error;
+
 	dfprintk(VFS, "nfs: fsync(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
-	return nfs_flush_dirty_pages(inode, 0, 0);
+	status = nfs_flush_dirty_pages(inode, current->pid, 0, 0);
+	error = nfs_write_error(inode);
+	if (!status)
+		status = error;
+	return status;
 }
 
 /* 
@@ -139,7 +163,7 @@
 nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
 	struct inode * inode = file->f_dentry->d_inode;
-	int	result;
+	ssize_t result;
 
 	dfprintk(VFS, "nfs: write(%x/%ld (%d), %lu@%lu)\n",
 			inode->i_dev, inode->i_ino, inode->i_count,
@@ -153,21 +177,26 @@
 		printk("NFS: attempt to write to active swap file!\n");
 		return -EBUSY;
 	}
-	if ((result = nfs_revalidate_inode(NFS_SERVER(inode), inode)) < 0)
-		return result;
+	result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (result)
+		goto out;
+
+	/* N.B. This should be impossible now -- inodes can't change mode */
 	if (!S_ISREG(inode->i_mode)) {
 		printk("nfs_file_write: write to non-file, mode %07o\n",
 			inode->i_mode);
 		return -EINVAL;
 	}
-	if (count <= 0)
-		return 0;
-
-	/* Return error from previous async call */
-	if ((result = nfs_write_error(inode)) < 0)
-		return result;
-
-	return generic_file_write(file, buf, count, ppos);
+	result = count;
+	if (!count)
+		goto out;
+
+	/* Check for an error from a previous async call */
+	result = nfs_write_error(inode);
+	if (!result)
+		result = generic_file_write(file, buf, count, ppos);
+out:
+	return result;
 }
 
 /*
@@ -176,15 +205,15 @@
 int
 nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
+	struct inode * inode = filp->f_dentry->d_inode;
 	int	status;
-	struct inode * inode;
 
 	dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%ld:%ld)\n",
-			filp->f_dentry->d_inode->i_dev, filp->f_dentry->d_inode->i_ino,
+			inode->i_dev, inode->i_ino,
 			fl->fl_type, fl->fl_flags,
 			fl->fl_start, fl->fl_end);
 
-	if (!(inode = filp->f_dentry->d_inode))
+	if (!inode)
 		return -EINVAL;
 
 	/* No mandatory locks over NFS */
@@ -209,7 +238,7 @@
 	 * been killed by a signal, that is). */
 	if (cmd == F_SETLK && fl->fl_type == F_UNLCK
 	    && !signal_pending(current)) {
-		status = nfs_flush_dirty_pages(inode,
+		status = nfs_flush_dirty_pages(inode, current->pid,
 			fl->fl_start, fl->fl_end == NLM_OFFSET_MAX? 0 :
 			fl->fl_end - fl->fl_start + 1);
 		if (status < 0)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov