Defines the layout driver I/O, Policy operations interface. This interface will evolve as we add additional layout drivers. Also specifies layout driver register and unregister opreations. --- linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4_pnfs.h | 139 +++++++++++ 1 files changed, 139 insertions(+) diff -puN /dev/null include/linux/nfs4_pnfs.h --- /dev/null 2006-01-09 05:56:56.224752500 -0500 +++ linux-2.6.14-pnfs-current-dhildebz/include/linux/nfs4_pnfs.h 2006-01-11 14:21:28.426990000 -0500 @@ -0,0 +1,139 @@ +/* + * include/linux/nfs4_pnfs.h + * + * Common data structures needed by the pnfs client and pnfs layout driver. + * + * Copyright (c) 2002 The Regents of the University of Michigan. + * All rights reserved. + * + * Dean Hildebrand + */ + +#ifndef LINUX_NFS4_PNFS_H +#define LINUX_NFS4_PNFS_H + +#define NFS4_PNFS_DEV_MAXCOUNT 16 +#define NFS4_PNFS_DEV_MAXSIZE 128 + +/* Layout driver specific identifier for a mount point. For each mountpoint + * a reference is stored in the nfs_server structure. + */ +struct pnfs_mount_type { + void* mountid; +}; + +/* Layout driver specific identifier for layout information for a file. + * Each inode has a specific layout type structure. + * A reference is stored in the nfs_inode structure. + */ +struct pnfs_layout_type { + struct pnfs_mount_type* mountid; + void* layoutid; +}; + +/* Layout driver I/O operations. + * Either the pagecache or non-pagecache read/write operations must be implemented + */ +struct layoutdriver_io_operations { + /* Functions that use the pagecache. + * If use_pagecache == 1, then these functions must be implemented. + */ + ssize_t (*read_pagelist) (struct pnfs_layout_type * layoutid, struct inode *, struct page **pages, unsigned int pgbase, unsigned nr_pages, loff_t offset, size_t count, void* private); + ssize_t (*write_pagelist) (struct pnfs_layout_type * layoutid, struct inode *, struct page **pages, unsigned int pgbase, unsigned nr_pages, loff_t offset, size_t count, int sync, void* private); + + /* Functions that do not use the pagecache. + * If use_pagecache == 0, then these functions must be implemented. + */ + ssize_t (*read) (struct pnfs_layout_type * layoutid, struct file *, char __user *, size_t, loff_t *); + ssize_t (*write) (struct pnfs_layout_type * layoutid, struct file *, const char __user *, size_t, loff_t *); + ssize_t (*readv) (struct pnfs_layout_type * layoutid, struct file *, const struct iovec *, unsigned long, loff_t *); + ssize_t (*writev) (struct pnfs_layout_type * layoutid, struct file *, const struct iovec *, unsigned long, loff_t *); + + /* Consistency ops */ + int (*fsync) (struct pnfs_layout_type * layoutid, struct file *, struct dentry *, int); + /* 2 problems: + * 1) the page list contains nfs_pages, NOT pages + * 2) currently the NFS code doesn't create a page array (as it does with read/write) + */ + int (*commit) (struct pnfs_layout_type * layoutid, struct inode *, struct list_head *, int sync, void* private); + + /* Layout information. For each inode, alloc_layout is executed once to retrieve an + * inode specific layout structure. Each subsequent layoutget operation results in + * a set_layout call to set the opaque layout in the layout driver.*/ + struct pnfs_layout_type* (*alloc_layout) (struct pnfs_mount_type * mountid, struct inode * inode); + void (*free_layout) (struct pnfs_layout_type * layoutid, struct inode * inode); + struct pnfs_layout_type* (*set_layout) (struct pnfs_layout_type * layoutid, struct inode * inode, void* layout); + + /* Registration information for a new mounted file system + */ + struct pnfs_mount_type* (*initialize_mountpoint) (struct super_block *); + int (*uninitialize_mountpoint) (struct pnfs_mount_type* mountid); + + /* Other ops... */ + int (*ioctl) (struct pnfs_layout_type *, struct inode *, struct file *, unsigned int, unsigned long); +}; + +struct layoutdriver_policy_operations { + /* The stripe size of the file system */ + ssize_t (*get_stripesize) (struct pnfs_layout_type * layoutid, struct inode *); + + /* Should the NFS req. gather algorithm cross stripe boundaries? */ + int (*gather_across_stripes) (struct pnfs_mount_type * mountid); + + /* Retreive the block size of the file system. If gather_across_stripes == 1, + * then the file system will gather requests into the block size. + * TODO: Where will the layout driver get this info? It is hard coded in PVFS2. + */ + ssize_t (*get_blocksize) (struct pnfs_mount_type *); + + /* I/O requests under this value are sent to the NFSv4 server */ + int (*get_io_threshold) (struct pnfs_layout_type *, struct inode *); + + /* Use the linux page cache prior to calling layout driver + * read/write functions + */ + int (*use_pagecache) (struct pnfs_layout_type *, struct inode *); + + /* Should the pNFS client issue a layoutget call in the + * same compound as the OPEN operation? + */ + int (*layoutget_on_open) (struct pnfs_mount_type *); +}; + +/* Per-layout driver specific registration structure */ +struct pnfs_layoutdriver_type { + const int id; + const char *name; + struct layoutdriver_io_operations *ld_io_ops; + struct layoutdriver_policy_operations *ld_policy_ops; +}; + +struct pnfs_device +{ + unsigned int layoutclass; + int dev_id; + unsigned int dev_addr_len; + char dev_addr_buf[NFS4_PNFS_DEV_MAXSIZE]; +}; + +struct pnfs_devicelist { + unsigned int num_devs; + unsigned int devs_len; + struct pnfs_device devs[NFS4_PNFS_DEV_MAXCOUNT]; +}; + +/* pNFS client callback functions. + * These operations allow the layout driver to access pNFS client + * specific information or call pNFS client->server operations. + * E.g., getdeviceinfo, I/O callbacks, etc + */ +struct pnfs_client_operations { + int (*nfs_fsync) (struct file * file, struct dentry * dentry, int datasync); + int (*nfs_getdevicelist) (struct super_block * sb, struct pnfs_devicelist* devlist); + int (*nfs_getdeviceinfo) (struct super_block * sb, u32 dev_id, struct pnfs_device * dev); +}; + +struct pnfs_client_operations* pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); +void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); + +#endif /* LINUX_NFS4_PNFS_H */ _