patch-2.4.20 linux-2.4.20/fs/nfs/read.c

Next file: linux-2.4.20/fs/nfs/symlink.c
Previous file: linux-2.4.20/fs/nfs/proc.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/fs/nfs/read.c linux-2.4.20/fs/nfs/read.c
@@ -42,6 +42,7 @@
 	struct nfs_readres	res;	/* ... and result struct */
 	struct nfs_fattr	fattr;	/* fattr storage */
 	struct list_head	pages;	/* Coalesced read requests */
+	struct page		*pagevec[NFS_READ_MAXIOV];
 };
 
 /*
@@ -63,6 +64,7 @@
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
+		p->args.pages = p->pagevec;
 	}
 	return p;
 }
@@ -86,8 +88,7 @@
 {
 	struct rpc_cred	*cred = NULL;
 	struct nfs_fattr fattr;
-	loff_t		offset = page_offset(page);
-	char		*buffer;
+	unsigned int	offset = 0;
 	int		rsize = NFS_SERVER(inode)->rsize;
 	int		result;
 	int		count = PAGE_CACHE_SIZE;
@@ -103,19 +104,18 @@
 	 * This works now because the socket layer never tries to DMA
 	 * into this buffer directly.
 	 */
-	buffer = kmap(page);
 	do {
 		if (count < rsize)
 			rsize = count;
 
-		dprintk("NFS: nfs_proc_read(%s, (%x/%Ld), %Ld, %d, %p)\n",
+		dprintk("NFS: nfs_proc_read(%s, (%x/%Ld), %u, %u, %p)\n",
 			NFS_SERVER(inode)->hostname,
 			inode->i_dev, (long long)NFS_FILEID(inode),
-			(long long)offset, rsize, buffer);
+			offset, rsize, page);
 
 		lock_kernel();
 		result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags,
-						offset, rsize, buffer, &eof);
+						offset, rsize, page, &eof);
 		nfs_refresh_inode(inode, &fattr);
 		unlock_kernel();
 
@@ -130,12 +130,15 @@
 		}
 		count  -= result;
 		offset += result;
-		buffer += result;
 		if (result < rsize)	/* NFSv2ism */
 			break;
 	} while (count);
 
-	memset(buffer, 0, count);
+	if (count) {
+		char *kaddr = kmap(page);
+		memset(kaddr + offset, 0, count);
+		kunmap(page);
+	}
 	flush_dcache_page(page);
 	SetPageUptodate(page);
 	if (PageError(page))
@@ -143,7 +146,6 @@
 	result = 0;
 
 io_error:
-	kunmap(page);
 	UnlockPage(page);
 	return result;
 }
@@ -186,26 +188,24 @@
 nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
 {
 	struct nfs_page		*req;
-	struct iovec		*iov;
+	struct page		**pages;
 	unsigned int		count;
 
-	iov = data->args.iov;
+	pages = data->args.pages;
 	count = 0;
 	while (!list_empty(head)) {
 		struct nfs_page *req = nfs_list_entry(head->next);
 		nfs_list_remove_request(req);
 		nfs_list_add_request(req, &data->pages);
-		iov->iov_base = kmap(req->wb_page) + req->wb_offset;
-		iov->iov_len = req->wb_bytes;
+		*pages++ = req->wb_page;
 		count += req->wb_bytes;
-		iov++;
-		data->args.nriov++;
 	}
 	req = nfs_list_entry(data->pages.next);
 	data->inode	  = req->wb_inode;
 	data->cred	  = req->wb_cred;
 	data->args.fh     = NFS_FH(req->wb_inode);
 	data->args.offset = page_offset(req->wb_page) + req->wb_offset;
+	data->args.pgbase = req->wb_offset;
 	data->args.count  = count;
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
@@ -266,10 +266,10 @@
 	msg.rpc_cred = data->cred;
 
 	/* Start the async call */
-	dprintk("NFS: %4d initiated read call (req %x/%Ld count %d nriov %d.\n",
+	dprintk("NFS: %4d initiated read call (req %x/%Ld count %u.\n",
 		task->tk_pid,
 		inode->i_dev, (long long)NFS_FILEID(inode),
-		data->args.count, data->args.nriov);
+		data->args.count);
 
 	rpc_clnt_sigmask(clnt, &oldset);
 	rpc_call_setup(task, &msg, 0);
@@ -418,13 +418,17 @@
 				memset(p + count, 0, PAGE_CACHE_SIZE - count);
 				kunmap(page);
 				count = 0;
-			} else
+				if (data->res.eof)
+					SetPageUptodate(page);
+				else
+					SetPageError(page);
+			} else {
 				count -= PAGE_CACHE_SIZE;
-			SetPageUptodate(page);
+				SetPageUptodate(page);
+			}
 		} else
 			SetPageError(page);
 		flush_dcache_page(page);
-		kunmap(page);
 		UnlockPage(page);
 
 		dprintk("NFS: read (%x/%Ld %d@%Ld)\n",

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)