patch-2.4.15 linux/fs/nfs/read.c
Next file: linux/fs/nfs/write.c
Previous file: linux/fs/nfs/pagelist.c
Back to the patch index
Back to the overall index
- Lines: 263
- Date:
Fri Nov 9 14:28:15 2001
- Orig file:
v2.4.14/linux/fs/nfs/read.c
- Orig date:
Tue Oct 23 22:48:53 2001
diff -u --recursive --new-file v2.4.14/linux/fs/nfs/read.c linux/fs/nfs/read.c
@@ -148,34 +148,6 @@
return result;
}
-static inline struct nfs_page *
-_nfs_find_read(struct inode *inode, struct page *page)
-{
- struct list_head *head, *next;
-
- head = &inode->u.nfs_i.read;
- next = head->next;
- while (next != head) {
- struct nfs_page *req = nfs_list_entry(next);
- next = next->next;
- if (page_index(req->wb_page) != page_index(page))
- continue;
- req->wb_count++;
- return req;
- }
- return NULL;
-}
-
-static struct nfs_page *
-nfs_find_read(struct inode *inode, struct page *page)
-{
- struct nfs_page *req;
- spin_lock(&nfs_wreq_lock);
- req = _nfs_find_read(inode, page);
- spin_unlock(&nfs_wreq_lock);
- return req;
-}
-
/*
* Add a request to the inode's asynchronous read list.
*/
@@ -185,61 +157,26 @@
struct inode *inode = req->wb_inode;
spin_lock(&nfs_wreq_lock);
- if (list_empty(&req->wb_list)) {
- nfs_list_add_request(req, &inode->u.nfs_i.read);
- inode->u.nfs_i.nread++;
- }
+ nfs_list_add_request(req, &inode->u.nfs_i.read);
+ inode->u.nfs_i.nread++;
+ __nfs_add_lru(&NFS_SERVER(inode)->lru_read, req);
spin_unlock(&nfs_wreq_lock);
- /*
- * NB: the call to inode_schedule_scan() must lie outside the
- * spinlock since it can run flushd().
- */
- inode_schedule_scan(inode, req->wb_timeout);
}
static int
nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
{
- struct nfs_page *req, *new = NULL;
- int result;
-
- for (;;) {
- result = 0;
- if (Page_Uptodate(page))
- break;
+ struct nfs_page *new;
- req = nfs_find_read(inode, page);
- if (req) {
- if (page != req->wb_page) {
- nfs_release_request(req);
- nfs_pagein_inode(inode, page_index(page), 0);
- continue;
- }
- nfs_release_request(req);
- break;
- }
-
- if (new) {
- nfs_lock_request(new);
- new->wb_timeout = jiffies + NFS_READ_DELAY;
- nfs_mark_request_read(new);
- nfs_unlock_request(new);
- new = NULL;
- break;
- }
-
- result = -ENOMEM;
- new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE);
- if (!new)
- break;
- }
+ new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+ nfs_mark_request_read(new);
if (inode->u.nfs_i.nread >= NFS_SERVER(inode)->rpages ||
page_index(page) == (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
nfs_pagein_inode(inode, 0, 0);
- if (new)
- nfs_release_request(new);
- return result;
+ return 0;
}
/*
@@ -345,14 +282,13 @@
return -ENOMEM;
}
-static int
-nfs_pagein_list(struct inode *inode, struct list_head *head)
+int
+nfs_pagein_list(struct list_head *head, int rpages)
{
LIST_HEAD(one_request);
struct nfs_page *req;
int error = 0;
- unsigned int pages = 0,
- rpages = NFS_SERVER(inode)->rpages;
+ unsigned int pages = 0;
while (!list_empty(head)) {
pages += nfs_coalesce_requests(head, &one_request, rpages);
@@ -368,29 +304,70 @@
return error;
}
-static int
-nfs_scan_read_timeout(struct inode *inode, struct list_head *dst)
+/**
+ * nfs_scan_lru_read_timeout - Scan LRU list for timed out read requests
+ * @server: NFS superblock data
+ * @dst: destination list
+ *
+ * Moves a maximum of 'rpages' timed out requests from the NFS read LRU list.
+ * The elements are checked to ensure that they form a contiguous set
+ * of pages, and that they originated from the same file.
+ */
+int
+nfs_scan_lru_read_timeout(struct nfs_server *server, struct list_head *dst)
{
- int pages;
- spin_lock(&nfs_wreq_lock);
- pages = nfs_scan_list_timeout(&inode->u.nfs_i.read, dst, inode);
- inode->u.nfs_i.nread -= pages;
- if ((inode->u.nfs_i.nread == 0) != list_empty(&inode->u.nfs_i.read))
- printk(KERN_ERR "NFS: desynchronized value of nfs_i.nread.\n");
- spin_unlock(&nfs_wreq_lock);
- return pages;
+ struct inode *inode;
+ int npages;
+
+ npages = nfs_scan_lru_timeout(&server->lru_read, dst, server->rpages);
+ if (npages) {
+ inode = nfs_list_entry(dst->next)->wb_inode;
+ inode->u.nfs_i.nread -= npages;
+ }
+ return npages;
}
+/**
+ * nfs_scan_lru_read - Scan LRU list for read requests
+ * @server: NFS superblock data
+ * @dst: destination list
+ *
+ * Moves a maximum of 'rpages' requests from the NFS read LRU list.
+ * The elements are checked to ensure that they form a contiguous set
+ * of pages, and that they originated from the same file.
+ */
+int
+nfs_scan_lru_read(struct nfs_server *server, struct list_head *dst)
+{
+ struct inode *inode;
+ int npages;
+
+ npages = nfs_scan_lru(&server->lru_read, dst, server->rpages);
+ if (npages) {
+ inode = nfs_list_entry(dst->next)->wb_inode;
+ inode->u.nfs_i.nread -= npages;
+ }
+ return npages;
+}
+
+/*
+ * nfs_scan_read - Scan an inode for read requests
+ * @inode: NFS inode to scan
+ * @dst: destination list
+ * @idx_start: lower bound of page->index to scan
+ * @npages: idx_start + npages sets the upper bound to scan
+ *
+ * Moves requests from the inode's read list.
+ * The requests are *not* checked to ensure that they form a contiguous set.
+ */
static int
nfs_scan_read(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
{
int res;
- spin_lock(&nfs_wreq_lock);
res = nfs_scan_list(&inode->u.nfs_i.read, dst, NULL, idx_start, npages);
inode->u.nfs_i.nread -= res;
if ((inode->u.nfs_i.nread == 0) != list_empty(&inode->u.nfs_i.read))
printk(KERN_ERR "NFS: desynchronized value of nfs_i.nread.\n");
- spin_unlock(&nfs_wreq_lock);
return res;
}
@@ -401,28 +378,16 @@
int res,
error = 0;
+ spin_lock(&nfs_wreq_lock);
res = nfs_scan_read(inode, &head, idx_start, npages);
+ spin_unlock(&nfs_wreq_lock);
if (res)
- error = nfs_pagein_list(inode, &head);
+ error = nfs_pagein_list(&head, NFS_SERVER(inode)->rpages);
if (error < 0)
return error;
return res;
}
-int nfs_pagein_timeout(struct inode *inode)
-{
- LIST_HEAD(head);
- int pages,
- error = 0;
-
- pages = nfs_scan_read_timeout(inode, &head);
- if (pages)
- error = nfs_pagein_list(inode, &head);
- if (error < 0)
- return error;
- return pages;
-}
-
/*
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
@@ -457,8 +422,8 @@
(long long)NFS_FILEID(req->wb_inode),
req->wb_bytes,
(long long)(page_offset(page) + req->wb_offset));
- nfs_unlock_request(req);
nfs_release_request(req);
+ nfs_unlock_request(req);
}
}
@@ -500,11 +465,10 @@
if (error)
goto out_error;
- error = -1;
- if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
+ if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
error = nfs_readpage_async(file, inode, page);
- if (error >= 0)
goto out;
+ }
error = nfs_readpage_sync(file, inode, page);
if (error < 0 && IS_SWAPFILE(inode))
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)