DESC pnfs-hooks EDESC --- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/inode.c | 58 ++++++++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c | 32 +++- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pagelist.c | 22 ++- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c | 85 +++++++++++- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.h | 3 linux-2.6.14-pnfs-current-dhildebz/fs/nfs/read.c | 24 ++- linux-2.6.14-pnfs-current-dhildebz/fs/nfs/write.c | 38 +++-- linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_page.h | 2 linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_xdr.h | 2 9 files changed, 241 insertions(+), 25 deletions(-) diff -puN fs/nfs/pnfs.c~client-pnfs-hooks fs/nfs/pnfs.c --- linux-2.6.14-pnfs-current/fs/nfs/pnfs.c~client-pnfs-hooks 2006-01-13 17:39:50.266533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.c 2006-01-18 19:58:05.151914000 -0500 @@ -46,6 +46,7 @@ #include #include #include +#include #include "nfs4_fs.h" #include "pnfs.h" @@ -60,6 +61,8 @@ extern int nfs_fsync(struct file *file, extern int nfs4_pnfs_getdevicelist(struct nfs_server *server, struct pnfs_devicelist* devlist); extern int nfs4_pnfs_getdeviceinfo(struct nfs_server *server, u32 dev_id, struct pnfs_device *res); +struct pnfs_client_operations pnfs_ops; + /* Locking: * * pnfs_spinlock: @@ -72,7 +75,6 @@ static spinlock_t pnfs_spinlock = SPIN_L */ static struct list_head pnfs_modules_tbl; static int is_pnfs_initialized = 0; -static struct pnfs_client_operations pnfs_ops; /* * struct pnfs_module - One per pNFS device module. @@ -887,5 +889,86 @@ pnfs_getdeviceinfo(struct super_block *s return rc; } +/* Callback operations for layout drivers. + */ +struct pnfs_client_operations pnfs_ops = { + .nfs_fsync = nfs_fsync, + .nfs_getdevicelist = pnfs_getdevicelist, + .nfs_getdeviceinfo = pnfs_getdeviceinfo, +}; + +unsigned int +pnfs_getboundary(struct inode* inode) +{ + struct pnfs_layout_type *laytype; + struct layoutdriver_policy_operations *policy_ops; + struct pnfs_layoutdriver_type *ld; + + laytype = NFS_I(inode)->current_layout; + ld = NFS_SERVER(inode)->pnfs_curr_ld; + if (!laytype || !ld) + return 0; + policy_ops = ld->ld_policy_ops; + + /* The default is to not gather across stripes */ + if (policy_ops && policy_ops->gather_across_stripes) + { + if (policy_ops->gather_across_stripes(laytype->mountid)) + { + return 0; + } + } + if (policy_ops && policy_ops->get_stripesize) + { + return policy_ops->get_stripesize(laytype, inode); + } + + return 0; /* Gather up to wsize/rsize */ +} + +/* Return number of pages the layout driver can handle + * in a single request. + * blocksize must be a multiple of the page cache size. + */ +unsigned int +pnfs_getpages(struct inode* inode, int iswrite) +{ + struct pnfs_mount_type *mounttype; + struct layoutdriver_policy_operations *policy_ops; + struct pnfs_layoutdriver_type *ld; + ssize_t bsize = 0; + unsigned int npages; + struct nfs_server *server = NFS_SERVER(inode); + + mounttype = server->pnfs_mountid; + ld = server->pnfs_curr_ld; + if (!mounttype || !ld) + goto outnfs; + policy_ops = ld->ld_policy_ops; + + if (policy_ops && policy_ops->get_blocksize) + { + bsize = policy_ops->get_blocksize(mounttype); + } + + if (bsize == 0) + { + goto outnfs; + } + + /* Convert the block size into a number of pages */ + npages = (bsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + +out: + return npages; +outnfs: + /* Return the number of NFS write or read pages */ + if (iswrite) + npages = server->wpages; + else + npages = server->rpages; + goto out; +} + EXPORT_SYMBOL(pnfs_unregister_layoutdriver); EXPORT_SYMBOL(pnfs_register_layoutdriver); diff -puN fs/nfs/inode.c~client-pnfs-hooks fs/nfs/inode.c --- linux-2.6.14-pnfs-current/fs/nfs/inode.c~client-pnfs-hooks 2006-01-13 17:39:50.277533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/inode.c 2006-01-13 17:39:50.346511000 -0500 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -125,6 +126,29 @@ struct rpc_program nfsacl_program = { }; #endif /* CONFIG_NFS_V3_ACL */ +struct rpc_clnt* +create_nfs_rpcclient(struct rpc_xprt *xprt, + char* server_name, + u32 version, + rpc_authflavor_t authflavor, + int *err) +{ + struct rpc_clnt* clnt = rpc_create_client(xprt, + server_name, + &nfs_program, + version, + authflavor); + if (IS_ERR(clnt)) { + *err = PTR_ERR(clnt); + printk("%s: error rpc_create_client\n", __FUNCTION__); + return NULL; + } + clnt->cl_intr = 1; + clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; + return clnt; +} + static inline unsigned long nfs_fattr_to_ino_t(struct nfs_fattr *fattr) { @@ -146,6 +170,7 @@ nfs_write_inode(struct inode *inode, int static void nfs_delete_inode(struct inode * inode) { + struct pnfs_layout_type* laytype; dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); truncate_inode_pages(&inode->i_data, 0); @@ -158,6 +183,16 @@ nfs_delete_inode(struct inode * inode) printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino); } +#if defined(CONFIG_NFS_V4) + /* TODO: I think we should be returning the layout at this point */ + laytype = NFS_I(inode)->current_layout; + if (laytype && NFS_SERVER(inode)->pnfs_curr_ld->ld_io_ops->free_layout) { + dprintk ("%s: removing layout\n", __FUNCTION__); + NFS_SERVER(inode)->pnfs_curr_ld->ld_io_ops->free_layout(laytype, inode); + NFS_I(inode)->current_layout = NULL; + } +#endif + clear_inode(inode); } @@ -1446,8 +1481,12 @@ static int nfs_update_inode(struct inode nfsi->last_updated = jiffies; /* Are we racing with known updates of the metadata on the server? */ +#if 1 //??? date change on DS makes it rewrite all data + data_unstable = 1; +#else data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); +#endif /* Check if our cached file size is stale */ new_isize = nfs_size_to_loff_t(fattr->size); @@ -1738,11 +1777,23 @@ static struct super_operations nfs4_sops static void nfs4_clear_inode(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); + struct pnfs_layout_type *laytype; /* If we are holding a delegation, return it! */ nfs_inode_return_delegation(inode); /* First call standard NFS clear_inode() code */ nfs_clear_inode(inode); + +#if defined(CONFIG_NFS_V4) + laytype = NFS_I(inode)->current_layout; + if (laytype && NFS_SERVER(inode)->pnfs_curr_ld->ld_io_ops->free_layout) { + /* TODO: I think we should be returning the layout at this point */ + dprintk ("%s: removing layout\n", __FUNCTION__); + NFS_SERVER(inode)->pnfs_curr_ld->ld_io_ops->free_layout(laytype, inode); + NFS_I(inode)->current_layout = NULL; + } +#endif + /* Now clear out any remaining state */ while (!list_empty(&nfsi->open_states)) { struct nfs4_state *state; @@ -2060,6 +2111,7 @@ static struct file_system_type nfs4_fs_t init_rwsem(&nfsi->rwsem); \ nfsi->pnfs_dirty = 0; \ nfsi->nfs_dirty = 0; \ + nfsi->current_layout = NULL; \ } while(0) #define register_nfs4fs() register_filesystem(&nfs4_fs_type) #define unregister_nfs4fs() unregister_filesystem(&nfs4_fs_type) @@ -2097,6 +2149,9 @@ static struct inode *nfs_alloc_inode(str #endif #ifdef CONFIG_NFS_V4 nfsi->nfs4_acl = NULL; + nfsi->current_layout = NULL; + nfsi->pnfs_dirty = 0; + nfsi->nfs_dirty = 0; #endif /* CONFIG_NFS_V4 */ return &nfsi->vfs_inode; } @@ -2217,6 +2272,9 @@ static void __exit exit_nfs_fs(void) unregister_nfs4fs(); } +/* Required for the pNFS file layout driver */ +EXPORT_SYMBOL(create_nfs_rpcclient); + /* Not quite true; I just maintain it */ MODULE_AUTHOR("Olaf Kirch "); MODULE_LICENSE("GPL"); diff -puN fs/nfs/nfs4proc.c~client-pnfs-hooks fs/nfs/nfs4proc.c --- linux-2.6.14-pnfs-current/fs/nfs/nfs4proc.c~client-pnfs-hooks 2006-01-13 17:39:50.290533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/nfs4proc.c 2006-01-13 17:39:50.360497000 -0500 @@ -1479,7 +1479,11 @@ static int _nfs4_proc_read(struct nfs_re (long long) rdata->args.offset); nfs_fattr_init(fattr); - status = rpc_call_sync(server->client, &msg, flags); + if (rdata->pnfs_client) + status = rpc_call_sync(rdata->pnfs_client, &msg, flags); + else + status = rpc_call_sync(server->client, &msg, flags); + if (!status) renew_lease(server, timestamp); dprintk("NFS reply read: %d\n", status); @@ -1610,7 +1614,10 @@ static int _nfs4_proc_write(struct nfs_w (long long) wdata->args.offset); nfs_fattr_init(fattr); - status = rpc_call_sync(server->client, &msg, rpcflags); + if (wdata->pnfs_client) + status = rpc_call_sync(wdata->pnfs_client, &msg, rpcflags); + else + status = rpc_call_sync(server->client, &msg, rpcflags); dprintk("NFS reply write: %d\n", status); return status; } @@ -2269,6 +2276,10 @@ nfs4_read_done(struct rpc_task *task) rpc_restart_call(task); return; } + + /* Reset rpc client. Is this necessary? */ + data->pnfs_client = NULL; + if (task->tk_status > 0) renew_lease(NFS_SERVER(inode), data->timestamp); /* Call back common NFS readpage processing */ @@ -2294,7 +2305,11 @@ nfs4_proc_read_setup(struct nfs_read_dat flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags); + /* Use the pNFS chosen rpc client if it exists */ + if (data->pnfs_client) + rpc_init_task(task, data->pnfs_client, nfs4_read_done, flags); + else + rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags); rpc_call_setup(task, &msg, 0); } @@ -2308,6 +2323,7 @@ nfs4_write_done(struct rpc_task *task) rpc_restart_call(task); return; } + if (task->tk_status >= 0) { renew_lease(NFS_SERVER(inode), data->timestamp); nfs_post_op_update_inode(inode, data->res.fattr); @@ -2348,7 +2364,11 @@ nfs4_proc_write_setup(struct nfs_write_d flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); + /* Use the pNFS chosen rpc client if it exists */ + if (data->pnfs_client) + rpc_init_task(task, data->pnfs_client, nfs4_write_done, flags); + else + rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); rpc_call_setup(task, &msg, 0); } @@ -2362,6 +2382,10 @@ nfs4_commit_done(struct rpc_task *task) rpc_restart_call(task); return; } + + /* Reset rpc client. Is this necessary? */ + data->pnfs_client = NULL; + if (task->tk_status >= 0) nfs_post_op_update_inode(inode, data->res.fattr); /* Call back common NFS writeback processing */ diff -puN fs/nfs/pagelist.c~client-pnfs-hooks fs/nfs/pagelist.c --- linux-2.6.14-pnfs-current/fs/nfs/pagelist.c~client-pnfs-hooks 2006-01-13 17:39:50.296533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pagelist.c 2006-01-13 17:39:50.408449000 -0500 @@ -19,6 +19,10 @@ #include #include +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? a : b) +#endif + #define NFS_PARANOIA 1 static kmem_cache_t *nfs_page_cachep; @@ -221,18 +225,32 @@ out: * @head: source list * @dst: destination list * @nmax: maximum number of requests to coalesce + * @boundary: byte boundary multiple that must not be crossed by this request * * Moves a maximum of 'nmax' elements from one list to another. * The elements are checked to ensure that they form a contiguous set * of pages, and that the RPC credentials are the same. */ int -nfs_coalesce_requests(struct list_head *head, struct list_head *dst, - unsigned int nmax) +nfs_coalesce_requests(struct list_head *head, + struct list_head *dst, + unsigned int nmax, + unsigned int boundary) { struct nfs_page *req = NULL; unsigned int npages = 0; + if (boundary && !list_empty(head)) { + /* Boundary can be thought of as a stripe unit, we don't want requests + * that span multiple stripes; boundary is given in bytes and is a + * multiple of the PAGE_CACHE_SIZE. + */ + req = nfs_list_entry(head->next); + nmax = MIN(nmax, ((boundary - ((req->wb_index << PAGE_CACHE_SHIFT) % + boundary)) >> PAGE_CACHE_SHIFT)); + req = NULL; + } + while (!list_empty(head)) { struct nfs_page *prev = req; diff -puN fs/nfs/read.c~client-pnfs-hooks fs/nfs/read.c --- linux-2.6.14-pnfs-current/fs/nfs/read.c~client-pnfs-hooks 2006-01-13 17:39:50.303533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/read.c 2006-01-18 20:09:24.756831000 -0500 @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -205,9 +206,9 @@ static void nfs_readpage_release(struct /* * Start an async read operation */ -static void nfs_execute_read(struct nfs_read_data *data) +void nfs_execute_read(struct nfs_read_data *data) { - struct rpc_clnt *clnt = NFS_CLIENT(data->inode); + struct rpc_clnt *clnt = data->task.tk_client; sigset_t oldset; rpc_clnt_sigmask(clnt, &oldset); @@ -387,15 +388,20 @@ out_bad: } static int -nfs_pagein_list(struct list_head *head, int rpages) +nfs_pagein_list(struct list_head *head, int rpages, struct inode *inode) { LIST_HEAD(one_request); struct nfs_page *req; int error = 0; unsigned int pages = 0; + unsigned int boundary = 0; + +#if defined(CONFIG_NFS_V4) + boundary = pnfs_getboundary(inode); +#endif while (!list_empty(head)) { - pages += nfs_coalesce_requests(head, &one_request, rpages); + pages += nfs_coalesce_requests(head, &one_request, rpages, boundary); req = nfs_list_entry(one_request.next); error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode); if (error < 0) @@ -600,7 +606,12 @@ int nfs_readpages(struct file *filp, str filp->private_data); ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); if (!list_empty(&head)) { - int err = nfs_pagein_list(&head, server->rpages); +#if defined(CONFIG_NFS_V4) + unsigned int rpages = pnfs_getpages(inode, 0); +#else + unsigned int rpages = server->rpages; +#endif + int err = nfs_pagein_list(&head, rpages, inode); if (!ret) ret = err; } @@ -633,3 +644,6 @@ void nfs_destroy_readpagecache(void) if (kmem_cache_destroy(nfs_rdata_cachep)) printk(KERN_INFO "nfs_read_data: not all structures were freed\n"); } + +EXPORT_SYMBOL(nfs_execute_read); +EXPORT_SYMBOL(nfs_readdata_release); diff -puN fs/nfs/write.c~client-pnfs-hooks fs/nfs/write.c --- linux-2.6.14-pnfs-current/fs/nfs/write.c~client-pnfs-hooks 2006-01-13 17:39:50.311534000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/write.c 2006-01-18 20:05:12.649483000 -0500 @@ -61,6 +61,7 @@ #include #include #include +#include #include "delegation.h" #include "pnfs.h" @@ -85,6 +86,7 @@ static int nfs_wait_on_requests(struct i static int nfs_flush_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how); extern int pnfs_commit(struct inode* inode, struct list_head *head, int sync, struct nfs_write_data *data); +extern unsigned int pnfs_getboundary(struct inode* inode); static kmem_cache_t *nfs_wdata_cachep; mempool_t *nfs_wdata_mempool; @@ -842,7 +844,7 @@ out: nfs_clear_page_writeback(req); } -static inline int flush_task_priority(int how) +inline int nfs_flush_task_priority(int how) { switch (how & (FLUSH_HIGHPRI|FLUSH_LOWPRI)) { case FLUSH_HIGHPRI: @@ -853,9 +855,9 @@ static inline int flush_task_priority(in return RPC_PRIORITY_NORMAL; } -static void nfs_execute_write(struct nfs_write_data *data) +void nfs_execute_write(struct nfs_write_data *data) { - struct rpc_clnt *clnt = NFS_CLIENT(data->inode); + struct rpc_clnt *clnt = data->task.tk_client; sigset_t oldset; rpc_clnt_sigmask(clnt, &oldset); lock_kernel(); @@ -897,7 +899,7 @@ void nfs_write_call(struct nfs_page *req if (!use_pnfs_io(inode, count)) { NFS_PROTO(inode)->write_setup(data, how); - data->task.tk_priority = flush_task_priority(how); + data->task.tk_priority = nfs_flush_task_priority(how); data->task.tk_cookie = (unsigned long)inode; data->task.tk_calldata = data; /* Release requests */ @@ -1041,15 +1043,19 @@ static int nfs_flush_one(struct list_hea } static int -nfs_flush_list(struct list_head *head, int wpages, int how) +nfs_flush_list(struct list_head *head, int wpages, int how, struct inode *inode) { LIST_HEAD(one_request); struct nfs_page *req; int error = 0; unsigned int pages = 0; + unsigned int boundary = 0; +#if defined(CONFIG_NFS_V4) + boundary = pnfs_getboundary(inode); +#endif while (!list_empty(head)) { - pages += nfs_coalesce_requests(head, &one_request, wpages); + pages += nfs_coalesce_requests(head, &one_request, wpages, boundary); req = nfs_list_entry(one_request.next); error = nfs_flush_one(&one_request, req->wb_context->dentry->d_inode, how); if (error < 0) @@ -1239,7 +1245,7 @@ static void nfs_commit_release(struct rp /* * Set up the argument/result storage required for the RPC call. */ -static void nfs_commit_rpcsetup(struct nfs_write_data *data, +void nfs_commit_rpcsetup(struct nfs_write_data *data, int how) { data->args.fh = NFS_FH(data->inode); @@ -1253,7 +1259,7 @@ static void nfs_commit_rpcsetup(struct n NFS_PROTO(data->inode)->commit_setup(data, how); - data->task.tk_priority = flush_task_priority(how); + data->task.tk_priority = nfs_flush_task_priority(how); data->task.tk_cookie = (unsigned long)data->inode; data->task.tk_calldata = data; /* Release requests */ @@ -1294,7 +1300,7 @@ static void pnfs_layoutcommit_rpcsetup(s NFS_PROTO(data->inode)->pnfs_layoutcommit_setup(data, how); - data->task.tk_priority = flush_task_priority(how); + data->task.tk_priority = nfs_flush_task_priority(how); data->task.tk_cookie = (unsigned long)data->inode; data->task.tk_calldata = data; /* Release requests */ @@ -1435,13 +1441,17 @@ static int nfs_flush_inode(struct inode spin_unlock(&nfsi->req_lock); if (res) { struct nfs_server *server = NFS_SERVER(inode); - +#if defined(CONFIG_NFS_V4) + unsigned int wpages = pnfs_getpages(inode, 1); +#else + unsigned int wpages = server->wpages; +#endif /* For single writes, FLUSH_STABLE is more efficient */ - if (res == nfsi->npages && nfsi->npages <= server->wpages) { + if (res == nfsi->npages && nfsi->npages <= wpages) { if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize) how |= FLUSH_STABLE; } - error = nfs_flush_list(&head, server->wpages, how); + error = nfs_flush_list(&head, wpages, how, inode); } if (error < 0) return error; @@ -1525,3 +1535,7 @@ void nfs_destroy_writepagecache(void) printk(KERN_INFO "nfs_write_data: not all structures were freed\n"); } +EXPORT_SYMBOL(nfs_execute_write); +EXPORT_SYMBOL(nfs_writedata_release); +EXPORT_SYMBOL(nfs_flush_task_priority); +EXPORT_SYMBOL(nfs_commit_rpcsetup); diff -puN include/linux/nfs_page.h~client-pnfs-hooks include/linux/nfs_page.h --- linux-2.6.14-pnfs-current/include/linux/nfs_page.h~client-pnfs-hooks 2006-01-13 17:39:50.315533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_page.h 2006-01-13 17:39:50.428429000 -0500 @@ -66,7 +66,7 @@ extern int nfs_scan_lock_dirty(struct n extern int nfs_scan_list(struct list_head *, struct list_head *, unsigned long, unsigned int); extern int nfs_coalesce_requests(struct list_head *, struct list_head *, - unsigned int); + unsigned int, unsigned int); extern int nfs_wait_on_request(struct nfs_page *); extern void nfs_unlock_request(struct nfs_page *req); extern int nfs_set_page_writeback_locked(struct nfs_page *req); diff -puN include/linux/nfs_xdr.h~client-pnfs-hooks include/linux/nfs_xdr.h --- linux-2.6.14-pnfs-current/include/linux/nfs_xdr.h~client-pnfs-hooks 2006-01-13 17:39:50.321533000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs_xdr.h 2006-01-13 17:39:50.434423000 -0500 @@ -693,6 +693,7 @@ struct nfs_read_data { struct nfs_readres res; #ifdef CONFIG_NFS_V4 unsigned long timestamp; /* For lease renewal */ + struct rpc_clnt *pnfs_client; /* Holds pNFS device across async calls */ #endif void (*complete) (struct nfs_read_data *, int); }; @@ -713,6 +714,7 @@ struct nfs_write_data { struct pnfs_layoutcommit_res lc_res; #ifdef CONFIG_NFS_V4 unsigned long timestamp; /* For lease renewal */ + struct rpc_clnt *pnfs_client; /* Holds pNFS device across async calls */ #endif void (*complete) (struct nfs_write_data *, int); unsigned int ispartial; diff -puN fs/nfs/pnfs.h~client-pnfs-hooks fs/nfs/pnfs.h --- linux-2.6.14-pnfs-current/fs/nfs/pnfs.h~client-pnfs-hooks 2006-01-13 17:39:50.326531000 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/fs/nfs/pnfs.h 2006-01-18 20:05:56.513667000 -0500 @@ -21,4 +21,7 @@ int pnfs_writepages(struct nfs_write_dat void pnfs_writeback_done(struct nfs_write_data *data, int status); int pnfs_readpages(struct nfs_read_data *rdata); int pnfs_fsync(struct file *file, struct dentry *dentry, int datasync); +unsigned int pnfs_getboundary(struct inode* inode); +unsigned int pnfs_getpages(struct inode* inode, int iswrite); + #endif /* FS_NFS_PNFS_H */ _