home *** CD-ROM | disk | FTP | other *** search
/ ftp.parl.clemson.edu / 2015-02-07.ftp.parl.clemson.edu.tar / ftp.parl.clemson.edu / pub / pvfs2 / orangefs-2.8.3-20110323.tar.gz / orangefs-2.8.3-20110323.tar / orangefs / patches / pnfs / p00001_pnfs_pvfs2layoutdriver.patch next >
Text File  |  2008-01-07  |  60KB  |  1,760 lines

  1.  
  2.  
  3. Transform pvfs2 client into the pvfs2 layout driver.
  4.  
  5. The pNFS client handles all metadata operations, relying
  6. only on the layout driver to perform I/O to the data servers.
  7. Essentially the pvfs2 layout driver is a subset of the full
  8. pvfs2 client, it only requires the read and write operations.
  9.  
  10. The interface between the pNFS client and the layout driver
  11. is the functions listed in the pvfs2layout_io_operations and
  12. pvfs2layout_policy_operations operation structures.  The former
  13. controls all I/O to the data servers, while the former
  14. provides policy information to the pNFS client.
  15.  
  16. Before the pNFS client can perform I/O, it must retrieve
  17. the data layout from the pNFS server.  Once this is done,
  18. it passes an opaque buffer to the layout driver, which
  19. parses the layout in pvfs2layout_set_layout.  A new
  20. upcall then moves the layout to the user level. A new
  21. state machine in sys-pnfs.c places the layout information
  22. (a set of servers and their handles) into the pvfs2 client
  23. cache.  Normally this cache would expire, but this patch
  24. disables this, allowing the pNFS client to control the
  25. expiration of the layout information.
  26.  
  27. There is 2 possible I/O paths into the pvfs2 layout driver.
  28. 1. The first does not use the page cache (which is unusual
  29. for the nfs client), passing memory buffers directly to
  30. the pvfs2layout_file_read/write functions.
  31.  
  32. 2. In the second I/O path, the nfs client uses the page cache
  33. and passes a list of pages to the pvfs2 layout driver using the
  34. pvfs2layout_read_pagelist and pvfs2layout_write_pagelist
  35. functions. 
  36.  
  37. Other details:
  38. 1. Renames op cache to pvfs2_pnfs_op_cache
  39. 2. Renames device request cache to pvfs2_pnfs_devreqcache
  40. 3. Renames inode cache to pvfs2_pnfs_inode_cache
  41. 4. Renames device name to pvfs2-pnfs (will be in /dev)
  42. 5. Initializes (at the user level) the /dev/pvfs2-pnfs module.
  43. 6. Uses /dev/pvfs2-pnfs to allow a standard pvfs2 client and
  44. a pNFS client to run on the same machine.
  45.  
  46.  
  47.  
  48. ---
  49.  
  50.  pvfs2-1.5.1-ld-dhildeb/Makefile.in                               |    2 
  51.  pvfs2-1.5.1-ld-dhildeb/include/pvfs2-sysint.h                    |   12 
  52.  pvfs2-1.5.1-ld-dhildeb/src/apps/kernel/linux/pvfs2-client-core.c |   45 
  53.  pvfs2-1.5.1-ld-dhildeb/src/client/sysint/acache.c                |   24 
  54.  pvfs2-1.5.1-ld-dhildeb/src/client/sysint/module.mk.in            |    3 
  55.  pvfs2-1.5.1-ld-dhildeb/src/client/sysint/sys-getattr.sm          |   23 
  56.  pvfs2-1.5.1-ld-dhildeb/src/client/sysint/sys-pnfs.c              |  135 ++
  57.  pvfs2-1.5.1-ld-dhildeb/src/io/dev/pint-dev.c                     |    2 
  58.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/Makefile.in          |   17 
  59.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/file.c               |  629 +++++++++-
  60.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-bufmap.c       |   72 +
  61.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-bufmap.h       |   10 
  62.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-cache.c        |   16 
  63.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-dev-proto.h    |    1 
  64.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-kernel.h       |   24 
  65.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-mod.c          |   42 
  66.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-pnfs.h         |   14 
  67.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-proc.c         |   13 
  68.  pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/upcall.h             |    8 
  69.  19 files changed, 1021 insertions(+), 71 deletions(-)
  70.  
  71. diff -puN include/pvfs2-sysint.h~pvfs2layoutdriver include/pvfs2-sysint.h
  72. --- pvfs2-1.5.1-ld/include/pvfs2-sysint.h~pvfs2layoutdriver    2008-01-05 18:08:55.000000000 -0800
  73. +++ pvfs2-1.5.1-ld-dhildeb/include/pvfs2-sysint.h    2008-01-05 18:08:55.000000000 -0800
  74. @@ -270,6 +270,18 @@ PVFS_error PVFS_isys_setattr(
  75.      PVFS_sys_op_id *op_id,
  76.      void *user_ptr);
  77.  
  78. +PVFS_error PVFS_isys_setlayout(
  79. +     PVFS_object_ref ref,
  80. +     void* layout,
  81. +     PVFS_credentials *credentials,
  82. +     PVFS_sys_op_id *op_id,
  83. +     void *user_ptr);
  84. +
  85. +PVFS_error PVFS_sys_setlayout(
  86. +     PVFS_object_ref ref,
  87. +     void* layout,
  88. +     PVFS_credentials *credentials);
  89. +
  90.  PVFS_error PVFS_sys_setattr(
  91.      PVFS_object_ref ref,
  92.      PVFS_sys_attr attr,
  93. diff -puN Makefile.in~pvfs2layoutdriver Makefile.in
  94. --- pvfs2-1.5.1-ld/Makefile.in~pvfs2layoutdriver    2008-01-05 18:08:55.000000000 -0800
  95. +++ pvfs2-1.5.1-ld-dhildeb/Makefile.in    2008-01-05 18:08:55.000000000 -0800
  96. @@ -865,7 +865,7 @@ KMOD_DIR ?= $(kmod_prefix)/lib/modules/$
  97.  .PHONY: just_kmod_install
  98.  just_kmod_install: just_kmod
  99.      install -d $(KMOD_DIR)
  100. -    install -m 755 src/kernel/linux-2.6/pvfs2.ko $(KMOD_DIR)
  101. +    install -m 755 src/kernel/linux-2.6/pvfs2-pnfs.ko $(KMOD_DIR)
  102.  
  103.  .PHONY: kmod_install
  104.  kmod_install: kmod kernapps just_kmod_install
  105. diff -puN src/kernel/linux-2.6/Makefile.in~pvfs2layoutdriver src/kernel/linux-2.6/Makefile.in
  106. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/Makefile.in~pvfs2layoutdriver    2008-01-05 18:08:55.000000000 -0800
  107. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/Makefile.in    2008-01-05 18:08:55.000000000 -0800
  108. @@ -56,16 +56,24 @@ hsrc = \
  109.      pvfs2-bufmap.h \
  110.      upcall.h \
  111.      downcall.h \
  112. -    pvfs2-proc.h
  113. +    pvfs2-proc.h \
  114. +    downcall.h \
  115. +    pvfs2-pnfs.h
  116.  
  117.  objs = $(csrc:.c=.o)
  118. -othergen = pvfs2.o pvfs2.ko pvfs2.mod.c pvfs2.mod.o
  119. +othergen = pvfs2-pnfs.o pvfs2-pnfs.ko pvfs2.mod.c pvfs2.mod.o
  120.  othergendir = .tmp_versions  # around 2.6.6 this is generated locally
  121.  cmds = $(patsubst %,.%.cmd,$(objs) $(othergen))
  122.  
  123. +KDIR    := @LINUX_KERNEL_SRC@
  124.  ifneq ($(KERNELRELEASE),)
  125.  
  126.  EXTRA_CFLAGS = \
  127. +    -I$(KDIR)/include/linux \
  128. +    -I$(KDIR)/arch/um/os-Linux/include \
  129. +    -I$(KDIR)/arch/um/kernel/skas \
  130. +    -I$(KDIR)/arch/um/kernel/skas/include \
  131. +    -I$(KDIR)/arch/um/include \
  132.      -I$(absolute_src_dir)/ \
  133.      -I$(absolute_build_dir)/ \
  134.      -I$(absolute_src_dir)/include \
  135. @@ -81,14 +89,13 @@ EXTRA_CFLAGS += -DPVFS2_VERSION="\"@PVFS
  136.  # debugging output or features
  137.  #EXTRA_CFLAGS += -DPVFS2_KERNEL_DEBUG
  138.  
  139. -obj-m += pvfs2.o
  140. -pvfs2-objs := $(objs)
  141. +obj-m += pvfs2-pnfs.o
  142. +pvfs2-pnfs-objs := $(objs)
  143.  
  144.  else
  145.  
  146.  #KDIR    := /lib/modules/$(shell uname -r)/build
  147.  #KDIR    := /usr/src/linux-$(shell uname -r)
  148. -KDIR    := @LINUX_KERNEL_SRC@
  149.  PWD    := $(shell pwd)
  150.  
  151.  default: links
  152. diff -puN src/kernel/linux-2.6/pvfs2-dev-proto.h~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-dev-proto.h
  153. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-dev-proto.h~pvfs2layoutdriver    2008-01-05 18:08:55.000000000 -0800
  154. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-dev-proto.h    2008-01-05 18:08:55.000000000 -0800
  155. @@ -33,6 +33,7 @@
  156.  #define PVFS2_VFS_OP_REMOVEXATTR       0xFF000013
  157.  #define PVFS2_VFS_OP_PARAM             0xFF000014
  158.  #define PVFS2_VFS_OP_PERF_COUNT        0xFF000015
  159. +#define PVFS2_VFS_OP_SET_LAYOUT        0xFF000016
  160.  #define PVFS2_VFS_OP_CANCEL            0xFF00EE00
  161.  #define PVFS2_VFS_OP_FSYNC             0xFF00EE01
  162.  
  163. diff -puN /dev/null src/kernel/linux-2.6/pvfs2-pnfs.h
  164. --- /dev/null    2007-11-26 10:11:24.475597181 -0800
  165. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-pnfs.h    2008-01-05 18:49:19.000000000 -0800
  166. @@ -0,0 +1,14 @@
  167. +/*
  168. + * (C) 2001 Clemson University and The University of Chicago
  169. + *
  170. + * See COPYING in top-level directory.
  171. + */
  172. +
  173. +#ifndef __PVFS2_PNFS_H
  174. +#define __PVFS2_PNFS_H
  175. +
  176. +#define GET_DATA_LAYOUT_MAXSIZE 1024
  177. +#define IO_THRESHOLD 65536
  178. +#define LAYOUT_PVFS2 4
  179. +
  180. +#endif
  181. diff -puN src/kernel/linux-2.6/upcall.h~pvfs2layoutdriver src/kernel/linux-2.6/upcall.h
  182. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/upcall.h~pvfs2layoutdriver    2008-01-05 18:08:55.000000000 -0800
  183. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/upcall.h    2008-01-05 18:08:55.000000000 -0800
  184. @@ -8,6 +8,7 @@
  185.  #define __UPCALL_H
  186.  
  187.  #include "pvfs2-sysint.h"
  188. +#include "pvfs2-pnfs.h"
  189.  
  190.  /* Sanitized this header file to fix
  191.   * 32-64 bit interaction issues between
  192. @@ -195,6 +196,12 @@ typedef struct
  193.  
  194.  typedef struct
  195.  {
  196. +    PVFS_object_ref refn;
  197. +    char layout[GET_DATA_LAYOUT_MAXSIZE];
  198. +} pvfs2_setlayout_request_t;
  199. +
  200. +typedef struct
  201. +{
  202.      int32_t type;
  203.      int32_t __pad1;
  204.      PVFS_credentials credentials;
  205. @@ -224,6 +231,7 @@ typedef struct
  206.          pvfs2_fsync_request_t fsync;
  207.          pvfs2_param_request_t param;
  208.          pvfs2_perf_count_request_t perf_count;
  209. +        pvfs2_setlayout_request_t setlayout;
  210.      } req;
  211.  } pvfs2_upcall_t;
  212.  
  213. diff -puN src/apps/kernel/linux/pvfs2-client-core.c~pvfs2layoutdriver src/apps/kernel/linux/pvfs2-client-core.c
  214. --- pvfs2-1.5.1-ld/src/apps/kernel/linux/pvfs2-client-core.c~pvfs2layoutdriver    2008-01-05 18:09:48.000000000 -0800
  215. +++ pvfs2-1.5.1-ld-dhildeb/src/apps/kernel/linux/pvfs2-client-core.c    2008-01-05 18:11:31.000000000 -0800
  216. @@ -78,7 +78,7 @@
  217.  #include "pvfs2-internal.h"
  218.  #endif
  219.  
  220. -#define DEFAULT_LOGFILE "/tmp/pvfs2-client.log"
  221. +#define DEFAULT_LOGFILE "/tmp/pnfs-client.log"
  222.  
  223.  typedef struct
  224.  {
  225. @@ -1560,6 +1560,35 @@ static PVFS_object_ref perform_lookup_on
  226.      return refn;
  227.  }
  228.  
  229. +/* DH: Initiate set layout fsm
  230. + */
  231. +static PVFS_error service_setlayout_request(vfs_request_t *vfs_request)
  232. +{
  233. +    PVFS_error ret = -PVFS_EINVAL;
  234. +
  235. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG,
  236. +         "got a setlayout request for fsid %d | handle %llu\n",
  237. +         vfs_request->in_upcall.req.setattr.refn.fs_id,
  238. +         llu(vfs_request->in_upcall.req.setattr.refn.handle));
  239. +
  240. +    ret = PVFS_sys_setlayout(vfs_request->in_upcall.req.setlayout.refn,
  241. +                 vfs_request->in_upcall.req.setlayout.layout,
  242. +                 &vfs_request->in_upcall.credentials);
  243. +    if (ret < 0)
  244. +    {
  245. +    gossip_err("failed to setlayout handle %llu on fsid %d ret %d!\n",
  246. +           llu(vfs_request->in_upcall.req.setattr.refn.handle),
  247. +           vfs_request->in_upcall.req.setattr.refn.fs_id,ret);
  248. +    }
  249. +
  250. +    vfs_request->out_downcall.type = PVFS2_VFS_OP_SET_LAYOUT;
  251. +    vfs_request->out_downcall.status = ret;
  252. +
  253. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG, "setlayout ok\n");
  254. +    write_inlined_device_response(vfs_request);
  255. +    return 0;
  256. +}
  257. +
  258.  PVFS_error write_device_response(
  259.      void *buffer_list,
  260.      int *size_list,
  261. @@ -2072,6 +2101,8 @@ static inline void package_downcall_memb
  262.              }
  263.              break;
  264.          }
  265. +        case PVFS2_VFS_OP_SET_LAYOUT:
  266. +         break;
  267.          default:
  268.              gossip_err("Completed upcall of unknown type %x!\n",
  269.                         vfs_request->in_upcall.type);
  270. @@ -2286,6 +2317,9 @@ static inline PVFS_error handle_unexp_vf
  271.              posted_op = 1;
  272.              ret = post_fsync_request(vfs_request);
  273.              break;
  274. +        case PVFS2_VFS_OP_SET_LAYOUT:
  275. +         ret = service_setlayout_request(vfs_request);
  276. +            break;
  277.          case PVFS2_VFS_OP_INVALID:
  278.          default:
  279.              gossip_err(
  280. @@ -2573,12 +2607,13 @@ int main(int argc, char **argv)
  281.        (re)configure the acache at that time since it's based on the
  282.        dynamic server configurations)
  283.      */
  284. -    ret = PVFS_sys_initialize(debug_mask);
  285. +    /* DH: load default pvfs2tab file*/
  286. +    ret = PVFS_util_init_defaults();
  287.      if (ret < 0)
  288.      {
  289. -        return ret;
  290. +     PVFS_perror("PVFS_util_init_defaults", ret);
  291. +    return ret;
  292.      }
  293. -
  294.      ret = gossip_enable_file(s_opts.logfile, "a");
  295.      if(ret < 0)
  296.      {
  297. @@ -2654,7 +2689,7 @@ int main(int argc, char **argv)
  298.          return ret;
  299.      }   
  300.  
  301. -    ret = PINT_dev_initialize("/dev/pvfs2-req", 0);
  302. +    ret = PINT_dev_initialize("/dev/pvfs2-pnfs", 0);
  303.      if (ret < 0)
  304.      {
  305.      PVFS_perror("PINT_dev_initialize", ret);
  306. diff -puN src/io/dev/pint-dev.c~pvfs2layoutdriver src/io/dev/pint-dev.c
  307. --- pvfs2-1.5.1-ld/src/io/dev/pint-dev.c~pvfs2layoutdriver    2008-01-05 18:09:48.000000000 -0800
  308. +++ pvfs2-1.5.1-ld-dhildeb/src/io/dev/pint-dev.c    2008-01-05 18:09:48.000000000 -0800
  309. @@ -527,7 +527,7 @@ static int setup_dev_entry(const char *d
  310.      int ret = -1;
  311.      struct stat dev_stat;
  312.  
  313. -    ret = parse_devices("/proc/devices", "pvfs2-req", &majornum);
  314. +    ret = parse_devices("/proc/devices", "pvfs2-pnfs", &majornum);
  315.      if (ret < 0)
  316.      {
  317.          gossip_err("Error: unable to parse device file.\n");
  318. diff -puN src/kernel/linux-2.6/pvfs2-cache.c~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-cache.c
  319. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-cache.c~pvfs2layoutdriver    2008-01-05 18:09:48.000000000 -0800
  320. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-cache.c    2008-01-05 18:09:48.000000000 -0800
  321. @@ -33,7 +33,7 @@ extern int pvfs2_gen_credentials(
  322.  int op_cache_initialize(void)
  323.  {
  324.      op_cache = kmem_cache_create(
  325. -        "pvfs2_op_cache", sizeof(pvfs2_kernel_op_t),
  326. +        "pvfs2_pnfs_op_cache", sizeof(pvfs2_kernel_op_t),
  327.          0, PVFS2_CACHE_CREATE_FLAGS, NULL, NULL);
  328.  
  329.      if (!op_cache)
  330. @@ -53,7 +53,7 @@ int op_cache_finalize(void)
  331.  {
  332.      if (kmem_cache_destroy(op_cache) != 0)
  333.      {
  334. -        pvfs2_panic("Failed to destroy pvfs2_op_cache\n");
  335. +        pvfs2_panic("Failed to destroy pvfs2_pnfs_op_cache\n");
  336.          return -EINVAL;
  337.      }
  338.      return 0;
  339. @@ -126,7 +126,7 @@ static void dev_req_cache_ctor(
  340.  int dev_req_cache_initialize(void)
  341.  {
  342.      dev_req_cache = kmem_cache_create(
  343. -        "pvfs2_devreqcache", MAX_ALIGNED_DEV_REQ_DOWNSIZE, 0,
  344. +        "pvfs2_pnfs_devreqcache", MAX_ALIGNED_DEV_REQ_DOWNSIZE, 0,
  345.          PVFS2_CACHE_CREATE_FLAGS, dev_req_cache_ctor, NULL);
  346.  
  347.      if (!dev_req_cache)
  348. @@ -141,7 +141,7 @@ int dev_req_cache_finalize(void)
  349.  {
  350.      if (kmem_cache_destroy(dev_req_cache) != 0)
  351.      {
  352. -        pvfs2_panic("Failed to destroy pvfs2_devreqcache\n");
  353. +        pvfs2_panic("Failed to destroy pvfs2_pnfs_devreqcache\n");
  354.          return -EINVAL;
  355.      }
  356.      return 0;
  357. @@ -238,13 +238,13 @@ static inline void del_from_pinode_list(
  358.  int pvfs2_inode_cache_initialize(void)
  359.  {
  360.      pvfs2_inode_cache = kmem_cache_create(
  361. -        "pvfs2_inode_cache", sizeof(pvfs2_inode_t), 0,
  362. +        "pvfs2_pnfs_inode_cache", sizeof(pvfs2_inode_t), 0,
  363.          PVFS2_CACHE_CREATE_FLAGS, pvfs2_inode_cache_ctor,
  364.          pvfs2_inode_cache_dtor);
  365.  
  366.      if (!pvfs2_inode_cache)
  367.      {
  368. -        pvfs2_panic("Cannot create pvfs2_inode_cache\n");
  369. +        pvfs2_panic("Cannot create pvfs2_pnfs_inode_cache\n");
  370.          return -ENOMEM;
  371.      }
  372.      return 0;
  373. @@ -264,7 +264,7 @@ int pvfs2_inode_cache_finalize(void)
  374.      }
  375.      if (kmem_cache_destroy(pvfs2_inode_cache) != 0)
  376.      {
  377. -        pvfs2_panic("Failed to destroy pvfs2_inode_cache\n");
  378. +        pvfs2_panic("Failed to destroy pvfs2_pnfs_inode_cache\n");
  379.          return -EINVAL;
  380.      }
  381.      return 0;
  382. @@ -326,7 +326,7 @@ static void kiocb_ctor(
  383.  int kiocb_cache_initialize(void)
  384.  {
  385.      pvfs2_kiocb_cache = kmem_cache_create(
  386. -        "pvfs2_kiocbcache", sizeof(pvfs2_kiocb), 0,
  387. +        "pnfs_kiocbcache", sizeof(pvfs2_kiocb), 0,
  388.          PVFS2_CACHE_CREATE_FLAGS, kiocb_ctor, NULL);
  389.  
  390.      if (!pvfs2_kiocb_cache)
  391. diff -puN src/kernel/linux-2.6/pvfs2-kernel.h~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-kernel.h
  392. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-kernel.h~pvfs2layoutdriver    2008-01-05 18:09:48.000000000 -0800
  393. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-kernel.h    2008-01-05 18:13:54.000000000 -0800
  394. @@ -151,11 +151,17 @@ do {                                    
  395.  #define PVFS2_DEFAULT_OP_TIMEOUT_SECS       60
  396.  #endif
  397.  
  398. -#define PVFS2_REQDEVICE_NAME          "pvfs2-req"
  399. + /* DH: Change device for pnfs client in UML */
  400. +#define PVFS2_REQDEVICE_NAME          "pvfs2-pnfs"
  401. +
  402. +struct nfs_write_data;
  403. +struct nfs_read_data;
  404. +struct pnfs_layoutcommit_arg;
  405. +struct pnfs_layoutcommit_res;
  406.  
  407.  #define PVFS2_DEVREQ_MAGIC             0x20030529
  408.  #define PVFS2_LINK_MAX                 0x000000FF
  409. -#define PVFS2_OP_RETRY_COUNT           0x00000005
  410. +#define PVFS2_OP_RETRY_COUNT           0x00000001
  411.  #define PVFS2_SEEK_END                 0x00000002
  412.  #define PVFS2_MAX_NUM_OPTIONS          0x00000004
  413.  #define PVFS2_MAX_MOUNT_OPT_LEN        0x00000080
  414. @@ -759,6 +765,20 @@ do {                                    
  415.      buffer_index = -1;                                    \
  416.  } while(0)
  417.  
  418. +#define pnfs_io_error()                                 \
  419. +do {                                                      \
  420. +    if(new_op->op_state != PVFS2_VFS_STATE_SERVICED)      \
  421. +    {                                                     \
  422. +        pvfs2_cancel_op_in_progress(new_op->tag);         \
  423. +        op_release(new_op);                               \
  424. +    }                                                     \
  425. +    else                                                  \
  426. +    {                                                     \
  427. +        wake_up_device_for_return(new_op);                \
  428. +    }                                                     \
  429. +    pvfs_bufmap_put(buffer_index);                        \
  430. +} while(0)
  431. +
  432.  #ifdef HAVE_AIO_VFS_SUPPORT
  433.  /* 
  434.   * This macro differs from the above only in that it does not
  435. diff -puN src/kernel/linux-2.6/pvfs2-mod.c~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-mod.c
  436. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-mod.c~pvfs2layoutdriver    2008-01-05 18:09:48.000000000 -0800
  437. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-mod.c    2008-01-05 18:18:08.000000000 -0800
  438. @@ -5,10 +5,14 @@
  439.   * parameters, Copyright ⌐ Acxiom Corporation, 2005.
  440.   *
  441.   * See COPYING in top-level directory.
  442. + *
  443. + * Initializes kernel for pNFS PVFS2 device driver support.
  444. + * Registers pNFS ops with pNFS client.
  445.   */
  446.  
  447.  #include "pvfs2-kernel.h"
  448.  #include "pvfs2-proc.h"
  449. +#include "nfs4_pnfs.h"
  450.  
  451.  #ifndef PVFS2_VERSION
  452.  #define PVFS2_VERSION "Unknown"
  453. @@ -23,6 +27,8 @@ extern wait_queue_head_t pvfs2_request_l
  454.  static int hash_func(void *key, int table_size);
  455.  static int hash_compare(void *key, struct qhash_head *link);
  456.  
  457. +extern struct pnfs_layoutdriver_type pvfs2layout_type;
  458. +
  459.  /*************************************
  460.   * global variables declared here
  461.   *************************************/
  462. @@ -31,6 +37,12 @@ static int hash_compare(void *key, struc
  463.  static int hash_table_size = 509;
  464.  int debug = 0;
  465.  int op_timeout_secs = PVFS2_DEFAULT_OP_TIMEOUT_SECS;
  466. +int read_threshold = -1;
  467. +int write_threshold = -1;
  468. +int use_pagecache = 0;
  469. +
  470. +/* Callback operations to the pNFS client */
  471. +struct pnfs_client_operations * pnfs_callback_ops;
  472.  
  473.  MODULE_LICENSE("GPL");
  474.  MODULE_AUTHOR("PVFS2 Development Team");
  475. @@ -99,10 +111,10 @@ spinlock_t pvfs2_request_list_lock = SPI
  476.  DECLARE_WAIT_QUEUE_HEAD(pvfs2_request_list_waitq);
  477.  
  478.  
  479. -static int __init pvfs2_init(void)
  480. +static int __init pnfs_init(void)
  481.  {
  482.      int ret = -1;
  483. -    pvfs2_print("pvfs2: pvfs2_init called\n");
  484. +    pvfs2_print("%s: start\n",__FUNCTION__);
  485.  
  486.      if(debug)
  487.      {
  488. @@ -164,14 +176,20 @@ static int __init pvfs2_init(void)
  489.          ret = -ENOMEM;
  490.          goto cleanup_device;
  491.      }
  492. -    pvfs2_proc_initialize();
  493. -    ret = register_filesystem(&pvfs2_fs_type);
  494.  
  495. -    if(ret == 0)
  496. +    if (ret == 0)
  497.      {
  498. -        printk("pvfs2: module version %s loaded\n", PVFS2_VERSION);
  499. -        return 0;
  500. +    pvfs2_proc_initialize();
  501. +    /* DH:
  502. +     * Need to register file_operations struct with global list to indicate
  503. +     * that PVFS2 is a possible pNFS I/O module
  504. +     */
  505. +    pnfs_callback_ops = pnfs_register_layoutdriver(&pvfs2layout_type);
  506. +
  507. +    printk("pvfs2: module version %s loaded\n", PVFS2_VERSION);
  508. +    return 0;
  509.      }
  510. +
  511.      pvfs2_proc_finalize();
  512.      qhash_finalize(htable_ops_in_progress);
  513.  cleanup_device:
  514. @@ -190,7 +208,7 @@ err:
  515.      return ret;
  516.  }
  517.  
  518. -static void __exit pvfs2_exit(void)
  519. +static void __exit pnfs_exit(void)
  520.  {
  521.      int i = 0;
  522.      pvfs2_kernel_op_t *cur_op = NULL;
  523. @@ -243,7 +261,9 @@ static void __exit pvfs2_exit(void)
  524.      op_cache_finalize();
  525.  
  526.      qhash_finalize(htable_ops_in_progress);
  527. -    
  528. +
  529. +    pnfs_unregister_layoutdriver(&pvfs2layout_type);
  530. +
  531.      printk("pvfs2: module version %s unloaded\n", PVFS2_VERSION);
  532.  }
  533.  
  534. @@ -265,8 +285,8 @@ static int hash_compare(void *key, struc
  535.      return (op->tag == *real_tag);
  536.  }
  537.  
  538. -module_init(pvfs2_init);
  539. -module_exit(pvfs2_exit);
  540. +module_init(pnfs_init);
  541. +module_exit(pnfs_exit);
  542.  
  543.  /*
  544.   * Local variables:
  545. diff -puN src/kernel/linux-2.6/pvfs2-proc.c~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-proc.c
  546. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-proc.c~pvfs2layoutdriver    2008-01-05 18:09:48.000000000 -0800
  547. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-proc.c    2008-01-05 18:18:08.000000000 -0800
  548. @@ -22,6 +22,9 @@ extern int op_timeout_secs;
  549.  extern spinlock_t pvfs2_request_list_lock;
  550.  extern struct list_head pvfs2_request_list;
  551.  extern wait_queue_head_t pvfs2_request_list_waitq;
  552. +extern int read_threshold;
  553. +extern int write_threshold;
  554. +extern int use_pagecache;
  555.  
  556.  #ifdef CONFIG_SYSCTL
  557.  #include <linux/sysctl.h>
  558. @@ -248,6 +251,8 @@ static struct pvfs2_param_extra perf_res
  559.  };
  560.  static int min_debug[] = {0}, max_debug[] = {1};
  561.  static int min_op_timeout_secs[] = {0}, max_op_timeout_secs[] = {INT_MAX};
  562. +static int min_io_threshold[] = {-1}, max_io_threshold[] = {1073741824};
  563. +static int min_pc[] = {0}, max_pc[] = {1};
  564.  static ctl_table pvfs2_acache_table[] = {
  565.      /* controls acache timeout */
  566.      {1, "timeout-msecs", NULL, sizeof(int), 0644, NULL,
  567. @@ -291,10 +296,16 @@ static ctl_table pvfs2_table[] = {
  568.      /* subdir for acache control */
  569.      {6, "acache", NULL, 0, 0555, pvfs2_acache_table},
  570.      {7, "perf-counters", NULL, 0, 0555, pvfs2_pc_table},
  571. +    {8, "read_threshold", &read_threshold, sizeof(int), 0644, NULL,
  572. +     &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_io_threshold, &max_io_threshold},
  573. +    {9, "write_threshold", &write_threshold, sizeof(int), 0644, NULL,
  574. +     &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_io_threshold, &max_io_threshold},
  575. +    {10, "use_pagecache", &use_pagecache, sizeof(int), 0644, NULL,
  576. +     &proc_dointvec_minmax, &sysctl_intvec, NULL, &min_pc, &max_pc},
  577.      {0}
  578.  };
  579.  static ctl_table fs_table[] = {
  580. -    {1, "pvfs2", NULL, 0, 0555, pvfs2_table},
  581. +    {1, "pvfs2-pnfs", NULL, 0, 0555, pvfs2_table},
  582.      {0}
  583.  };
  584.  #endif
  585. diff -puN src/client/sysint/acache.c~pvfs2layoutdriver src/client/sysint/acache.c
  586. --- pvfs2-1.5.1-ld/src/client/sysint/acache.c~pvfs2layoutdriver    2008-01-05 18:11:31.000000000 -0800
  587. +++ pvfs2-1.5.1-ld-dhildeb/src/client/sysint/acache.c    2008-01-05 18:11:31.000000000 -0800
  588. @@ -137,7 +137,17 @@ int PINT_acache_initialize(void)
  589.          gen_mutex_unlock(&acache_mutex);
  590.          return(ret);
  591.      }
  592. -  
  593. +
  594. +    /* DH: Disable the cache expiration for pNFS */
  595. +    ret = PINT_tcache_set_info(acache, TCACHE_ENABLE_EXPIRATION, 0);
  596. +    if(ret < 0)
  597. +    {
  598. +        gossip_debug(GOSSIP_ACACHE_DEBUG, "Could not disable expiration\n");
  599. +    PINT_tcache_finalize(acache);
  600. +        gen_mutex_unlock(&acache_mutex);
  601. +        return(ret);
  602. +    }
  603. +
  604.      gen_mutex_unlock(&acache_mutex);
  605.      return(0);
  606.  }
  607. @@ -201,7 +211,7 @@ int PINT_acache_set_info(
  608.  
  609.      return(ret);
  610.  }
  611. -  
  612. +
  613.  /** 
  614.   * Retrieves a _copy_ of a cached attributes structure.  Also retrieves the
  615.   * logical file size (if the object in question is a file) and reports the
  616. @@ -290,6 +300,8 @@ int PINT_acache_get_cached_entry(
  617.  void PINT_acache_invalidate(
  618.      PVFS_object_ref refn)
  619.  {
  620. +/* We can't invalidate anything for pNFS */
  621. +#if 0
  622.      int ret = -1;
  623.      struct PINT_tcache_entry* tmp_entry;
  624.      int tmp_status;
  625. @@ -316,6 +328,7 @@ void PINT_acache_invalidate(
  626.                      acache->num_entries, PINT_PERF_SET);
  627.  
  628.      gen_mutex_unlock(&acache_mutex);
  629. +#endif
  630.      return;
  631.  }
  632.    
  633. @@ -326,6 +339,8 @@ void PINT_acache_invalidate(
  634.  void PINT_acache_invalidate_size(
  635.      PVFS_object_ref refn)
  636.  {
  637. +/* We can't invalidate anything for pNFS */
  638. +#if 0
  639.      int ret = -1;
  640.      struct PINT_tcache_entry* tmp_entry;
  641.      struct acache_payload* tmp_payload;
  642. @@ -352,6 +367,7 @@ void PINT_acache_invalidate_size(
  643.                      acache->num_entries, PINT_PERF_SET);
  644.  
  645.      gen_mutex_unlock(&acache_mutex);
  646. +#endif
  647.      return;
  648.  }
  649.    
  650. @@ -403,7 +419,8 @@ int PINT_acache_update(
  651.      /* fill in attributes */
  652.      if(attr)
  653.      {
  654. -        ret = PINT_copy_object_attr(&(tmp_payload->attr), attr);
  655. +      gossip_debug(GOSSIP_ACACHE_DEBUG, "acache: setting attrs\n");
  656. +    ret = PINT_copy_object_attr(&(tmp_payload->attr), attr);
  657.          if(ret < 0)
  658.          {
  659.              free(tmp_payload);
  660. @@ -415,6 +432,7 @@ int PINT_acache_update(
  661.      /* fill in size */
  662.      if(size)
  663.      {
  664. +    gossip_debug(GOSSIP_ACACHE_DEBUG, "acache: setting size\n");
  665.          tmp_payload->size = *size;
  666.          tmp_payload->size_status = 0;
  667.      }
  668. diff -puN src/client/sysint/module.mk.in~pvfs2layoutdriver src/client/sysint/module.mk.in
  669. --- pvfs2-1.5.1-ld/src/client/sysint/module.mk.in~pvfs2layoutdriver    2008-01-05 18:11:31.000000000 -0800
  670. +++ pvfs2-1.5.1-ld-dhildeb/src/client/sysint/module.mk.in    2008-01-05 18:11:31.000000000 -0800
  671. @@ -10,7 +10,8 @@ CSRC := \
  672.      $(DIR)/client-state-machine.c \
  673.      $(DIR)/mgmt-misc.c \
  674.      $(DIR)/sys-dist.c \
  675. -    $(DIR)/error-details.c
  676. +    $(DIR)/error-details.c \
  677. +    $(DIR)/sys-pnfs.c
  678.  
  679.  CLIENT_SMCGEN := \
  680.      $(DIR)/remove.c \
  681. diff -puN src/client/sysint/sys-getattr.sm~pvfs2layoutdriver src/client/sysint/sys-getattr.sm
  682. --- pvfs2-1.5.1-ld/src/client/sysint/sys-getattr.sm~pvfs2layoutdriver    2008-01-05 18:11:31.000000000 -0800
  683. +++ pvfs2-1.5.1-ld-dhildeb/src/client/sysint/sys-getattr.sm    2008-01-05 18:11:31.000000000 -0800
  684. @@ -359,11 +359,13 @@ static int getattr_acache_lookup(PINT_cl
  685.          &size_status);
  686.      if(ret < 0 || attr_status < 0)
  687.      {
  688. -        gossip_debug(GOSSIP_ACACHE_DEBUG, "acache: clean acache miss: "
  689. -                    " [%llu]\n",
  690. -                      llu(object_ref.handle));
  691. -  
  692. -        js_p->error_code = GETATTR_ACACHE_MISS;
  693. +    /* DH: It is now a fatal error for pnfs.
  694. +     */
  695. +    gossip_debug(GOSSIP_ACACHE_DEBUG, "acache: clean acache miss: "
  696. +             " [%llu]\n",
  697. +             llu(object_ref.handle));
  698. +    gossip_err("acache: Error-Cache Object not found!!!\n");
  699. +        js_p->error_code = -1;
  700.          return 1;
  701.      }
  702.    
  703. @@ -448,11 +450,14 @@ static int getattr_acache_lookup(PINT_cl
  704.       * overwritten when we request updated information from the server
  705.       */
  706.      PINT_free_object_attr(&sm_p->getattr.attr);
  707. -    gossip_debug(GOSSIP_ACACHE_DEBUG, "acache: acache miss due to mask: "
  708. -        " [%llu]\n",
  709. -          llu(object_ref.handle));
  710.  
  711. -    js_p->error_code = GETATTR_ACACHE_MISS;
  712. +    /* DH: It is now a fatal error for pnfs.
  713. +     */
  714. +    gossip_debug(GOSSIP_ACACHE_DEBUG, "acache: acache miss due to mask: "
  715. +         " [%llu]\n",
  716. +         llu(object_ref.handle));
  717. +    gossip_err("acache: Error-Cache Object not found!!!\n");
  718. +    js_p->error_code = -1;
  719.      return 1;
  720.  }
  721.  
  722. diff -puN /dev/null src/client/sysint/sys-pnfs.c
  723. --- /dev/null    2007-11-26 10:11:24.475597181 -0800
  724. +++ pvfs2-1.5.1-ld-dhildeb/src/client/sysint/sys-pnfs.c    2008-01-05 18:11:31.000000000 -0800
  725. @@ -0,0 +1,135 @@
  726. +/*
  727. + * Dean Hildebrand
  728. + *
  729. + * This state machine injects the required information into the PVFS2
  730. + * client cache to perform I/O for pNFS.
  731. + */
  732. +
  733. +#include <stdlib.h>
  734. +#include <stdio.h>
  735. +#include <string.h>
  736. +#include <assert.h>
  737. +
  738. +#define __PINT_REQPROTO_ENCODE_FUNCS_C
  739. +#include "gossip.h"
  740. +#include "pvfs2-debug.h"
  741. +#include "job.h"
  742. +#include "str-utils.h"
  743. +#include "pint-servreq.h"
  744. +#include "pvfs2-attr.h"
  745. +#include "acache.h"
  746. +#include "pvfs2-internal.h"
  747. +
  748. +extern void PINT_free_object_attr(PVFS_object_attr *attr);
  749. +static int setlayout_inject(PVFS_object_ref refn, void* layout);
  750. +
  751. +/* DH: This is the entry function for the state machine */
  752. +PVFS_error PVFS_sys_setlayout(
  753. +    PVFS_object_ref ref,
  754. +    void* layout,
  755. +    PVFS_credentials *credentials)
  756. +{
  757. +    int ret = -PVFS_EINVAL;
  758. +
  759. +    gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_sys_setlayout entered\n");
  760. +
  761. +    if ((ref.handle == PVFS_HANDLE_NULL) ||
  762. +    (ref.fs_id == PVFS_FS_ID_NULL)) {
  763. +    gossip_err("PVFS_sys_setlayout: invalid (NULL) required argument\n");
  764. +    return ret;
  765. +    }
  766. +
  767. +    gossip_debug(GOSSIP_CLIENT_DEBUG,
  768. +         "Doing setlayout on handle %llu on fs %d\n",
  769. +         ref.handle, ref.fs_id);
  770. +
  771. +    ret = setlayout_inject(ref, layout);
  772. +
  773. +    return ret;
  774. +}
  775. +
  776. +/****************************************************************/
  777. +
  778. +/* Deserialize the layout (dfiles and dist) and set in the
  779. + * cache attribute struct
  780. +*/
  781. +static int deserialize_layout(char* layout, PVFS_metafile_attr* meta)
  782. +{
  783. +    int blob_size=0, fs_id=0;
  784. +
  785. +    gossip_debug(GOSSIP_CLIENT_DEBUG, "deserialize_layout: Begin\n");
  786. +
  787. +    /* Size of entire opaque object */
  788. +    decode_int32_t(&layout, &blob_size);
  789. +    /* Size of entire opaque object */
  790. +    decode_int32_t(&layout, &fs_id);
  791. +    gossip_debug(GOSSIP_CLIENT_DEBUG,
  792. +         "deserialize_layout: #bs:%d fsid:%d\n",
  793. +         blob_size, fs_id);
  794. +
  795. +    /* Deserialize dfile array */
  796. +    decode_PVFS_metafile_attr_dfiles(&layout, meta);
  797. +    gossip_debug(GOSSIP_CLIENT_DEBUG,
  798. +         "deserialize_layout: #dfiles: %d dfile #0: %llu \n",
  799. +         meta->dfile_count, llu(meta->dfile_array[0]));
  800. +
  801. +    /* Deserialize distribution struct */
  802. +    decode_PVFS_metafile_attr_dist(&layout, meta);
  803. +    gossip_debug(GOSSIP_CLIENT_DEBUG,
  804. +         "deserialize_layout: #ds: %d\n",
  805. +         meta->dist_size);
  806. +    PINT_dist_dump(meta->dist);
  807. +
  808. +    gossip_debug(GOSSIP_CLIENT_DEBUG, "deserialize_layout: End\n");
  809. +    return 0;
  810. +}
  811. +
  812. +/* DH: Place layout in cache */
  813. +static int setlayout_inject(PVFS_object_ref refn, void* layout)
  814. +{
  815. +    int ret = -PVFS_EINVAL;
  816. +    PVFS_object_attr attr;
  817. +    PVFS_size tempsz = 0;
  818. +
  819. +    gossip_debug(GOSSIP_CLIENT_DEBUG, "setlayout_inject: Begin\n");
  820. +
  821. +    if (layout == NULL)
  822. +    {
  823. +    gossip_err("setlayout_inject: Layout is NULL!\n");
  824. +    ret = -EIO;
  825. +    goto out;
  826. +    }
  827. +
  828. +    /* Set (mostly false) attributes on the cached inode */
  829. +    attr.mask = (PVFS_ATTR_META_ALL | PVFS_ATTR_COMMON_ALL);
  830. +    /*    attr.mask &= !(PVFS_ATTR_SYMLNK_TARGET); */
  831. +    attr.objtype = PVFS_TYPE_METAFILE;
  832. +
  833. +    /* Decode the blob layout */
  834. +    if ((ret = deserialize_layout((char*)layout, &attr.u.meta)))
  835. +    {
  836. +    gossip_err("setlayout_inject: Could not deserialize layout %d!\n",ret);
  837. +    goto out;
  838. +    }
  839. +
  840. +    ret = PINT_acache_update(refn, &attr, &tempsz);
  841. +    if (ret)
  842. +    {
  843. +    gossip_err("setlayout_inject: Could not set layout in cache %d!\n",ret);
  844. +    }
  845. +
  846. +    PINT_free_object_attr(&attr);
  847. +out:
  848. +    gossip_debug(GOSSIP_CLIENT_DEBUG, "setlayout_inject: End\n");
  849. +    return ret;
  850. +}
  851. +
  852. +/*
  853. + * Local variables:
  854. + *  mode: c
  855. + *  c-indent-level: 4
  856. + *  c-basic-offset: 4
  857. + * End:
  858. + *
  859. + * vim: ft=c ts=8 sts=4 sw=4 noexpandtab
  860. + */
  861. diff -puN src/kernel/linux-2.6/file.c~pvfs2layoutdriver src/kernel/linux-2.6/file.c
  862. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/file.c~pvfs2layoutdriver    2008-01-05 18:13:54.000000000 -0800
  863. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/file.c    2008-01-05 18:13:54.000000000 -0800
  864. @@ -16,6 +16,11 @@
  865.  #include "pvfs2-internal.h"
  866.  #include <linux/fs.h>
  867.  #include <linux/pagemap.h>
  868. +#include "bmi-byteswap.h"
  869. +
  870. +#include "nfs4_pnfs.h"
  871. +
  872. +int pvfs2layout_fsync_inode(struct inode* inode, struct dentry *dentry, int datasync, struct pnfs_layout_type * layoutid);
  873.  
  874.  enum {
  875.      IO_READ = 0,
  876. @@ -33,6 +38,17 @@ extern int op_timeout_secs;
  877.  extern struct address_space_operations pvfs2_address_operations;
  878.  extern struct backing_dev_info pvfs2_backing_dev_info;
  879.  
  880. +extern struct pnfs_client_operations * pnfs_callback_ops;
  881. +
  882. +struct pvfs2layout_mount_type {
  883. +    struct super_block* fl_sb;
  884. +    int pnfs_fs_id;
  885. +};
  886. +
  887. +struct pvfs2layout_layout_type {
  888. +    int junk;
  889. +};
  890. +
  891.  #ifdef PVFS2_LINUX_KERNEL_2_4
  892.  static int pvfs2_precheck_file_write(struct file *file, struct inode *inode,
  893.      size_t *count, loff_t *ppos);
  894. @@ -46,6 +62,14 @@ do {                                    
  895.    wake_up_interruptible(&op->io_completion_waitq);\
  896.  } while(0)
  897.  
  898. +#define pnfs_decode_int32_t(pptr,x) do { \
  899. +        *(x) = bmitoh32(*(int32_t*) *(pptr)); \
  900. +        *(pptr) += 4; \
  901. +} while (0)
  902. +
  903. +extern int read_threshold;
  904. +extern int write_threshold;
  905. +extern int use_pagecache;
  906.  
  907.  /** Called when a process requests to open a file.
  908.   */
  909. @@ -126,12 +150,27 @@ struct rw_options {
  910.      } io;
  911.  };
  912.  
  913. -static ssize_t do_read_write(struct rw_options *rw)
  914. +/* Set file handle for upcall.
  915. + */
  916. +void
  917. +set_pvfs2_file_id(PVFS_object_ref* refn, struct inode *inode, struct pnfs_mount_type* mountid)
  918. +{
  919. +    struct pvfs2layout_mount_type* mount_type = (struct pvfs2layout_mount_type*)mountid->mountid;
  920. +
  921. +    /* DH: Since the file reference handle is a hash of the
  922. +     * ino, calculate it
  923. +     */
  924. +    refn->handle = pvfs2_ino_to_handle(inode->i_ino);
  925. +    refn->fs_id = mount_type->pnfs_fs_id;
  926. +    pvfs2_print("%s: handle:%llu fs_id:%d\n",__FUNCTION__,llu(refn->handle),refn->fs_id);
  927. +}
  928. +
  929. +static ssize_t do_read_write(struct rw_options *rw,
  930. +                 struct pnfs_mount_type *mountid)
  931.  {
  932.      pvfs2_kernel_op_t *new_op = NULL;
  933.      int buffer_index = -1;
  934.      struct inode *inode;
  935. -    pvfs2_inode_t *pvfs2_inode = NULL;
  936.      char *current_buf = NULL;
  937.      size_t count;
  938.      loff_t *offset;
  939. @@ -202,7 +241,6 @@ static ssize_t do_read_write(struct rw_o
  940.          pvfs2_print("%s: proceeding with offset : %ld, size %ld\n",
  941.                  fnstr, (unsigned long) *offset, (unsigned long) count);
  942.      }
  943. -    pvfs2_inode = PVFS2_I(inode);
  944.  
  945.      while(total_count < count)
  946.      {
  947. @@ -220,7 +258,9 @@ static ssize_t do_read_write(struct rw_o
  948.          new_op->upcall.req.io.readahead_size = readahead_size;
  949.          new_op->upcall.req.io.io_type = 
  950.              (rw->type == IO_READ) ? PVFS_IO_READ : PVFS_IO_WRITE;
  951. -        new_op->upcall.req.io.refn = pvfs2_inode->refn;
  952. +    /* DH - Set the file handle */
  953. +    set_pvfs2_file_id(&new_op->upcall.req.io.refn, inode, mountid);
  954. +
  955.  
  956.          ret = pvfs_bufmap_get(&buffer_index);
  957.          if (ret < 0)
  958. @@ -348,13 +388,14 @@ out:
  959.  /** Read data from a specified offset in a file (referenced by inode).
  960.   *  Data may be placed either in a user or kernel buffer.
  961.   */
  962. -ssize_t pvfs2_inode_read(
  963. +ssize_t pvfs2layout_inode_read(
  964.      struct inode *inode,
  965.      char __user *buf,
  966.      size_t count,
  967.      loff_t *offset,
  968.      int copy_to_user,
  969. -    loff_t readahead_size)
  970. +    loff_t readahead_size,
  971. +    struct pnfs_mount_type *mountid)
  972.  {
  973.      struct rw_options rw;
  974.      rw.type = IO_READ;
  975. @@ -364,12 +405,24 @@ ssize_t pvfs2_inode_read(
  976.      rw.io.read.inode = inode;
  977.      rw.io.read.copy_to_user = copy_to_user;
  978.      rw.io.read.readahead_size = readahead_size;
  979. -    return do_read_write(&rw); 
  980. +    return do_read_write(&rw, mountid);
  981. +}
  982. +
  983. +size_t pvfs2_inode_read(
  984. +    struct inode *inode,
  985. +    char __user *buf,
  986. +    size_t count,
  987. +    loff_t *offset,
  988. +    int copy_to_user,
  989. +    loff_t readahead_size)
  990. +{
  991. +    return pvfs2layout_inode_read(inode, buf, count, offset, copy_to_user, readahead_size, NULL);
  992.  }
  993.  
  994.  /** Read data from a specified offset in a file into a user buffer.
  995.   */
  996. -ssize_t pvfs2_file_read(
  997. +ssize_t pvfs2layout_file_read(
  998. +    struct pnfs_layout_type * layoutid,
  999.      struct file *file,
  1000.      char __user *buf,
  1001.      size_t count,
  1002. @@ -380,14 +433,15 @@ ssize_t pvfs2_file_read(
  1003.                   (char *)file->f_dentry->d_name.name : "UNKNOWN"),
  1004.                  (unsigned long) *offset, (unsigned long) count);
  1005.  
  1006. -    return pvfs2_inode_read(
  1007. -        file->f_dentry->d_inode, buf, count, offset, 1, 0);
  1008. +    return pvfs2layout_inode_read(
  1009. +        file->f_dentry->d_inode, buf, count, offset, 1, 0, layoutid->mountid);
  1010.  }
  1011.  
  1012.  /** Write data from a contiguous user buffer into a file at a specified
  1013.   *  offset.
  1014.   */
  1015. -static ssize_t pvfs2_file_write(
  1016. +static ssize_t pvfs2layout_file_write(
  1017. +    struct pnfs_layout_type * layoutid,
  1018.      struct file *file,
  1019.      const char __user *buf,
  1020.      size_t count,
  1021. @@ -399,7 +453,7 @@ static ssize_t pvfs2_file_write(
  1022.      rw.count = count;
  1023.      rw.offset = offset;
  1024.      rw.io.write.file = file;
  1025. -    return do_read_write(&rw);
  1026. +    return do_read_write(&rw, layoutid->mountid);
  1027.  }
  1028.  
  1029.  /*
  1030. @@ -830,7 +884,6 @@ static ssize_t pvfs2_file_readv(
  1031.      return do_readv_writev(IO_READV, file, iov, nr_segs, offset);
  1032.  }
  1033.  
  1034. -
  1035.  /** Write data from a several contiguous user buffers (an iovec) into a file at
  1036.   * a specified offset.
  1037.   */
  1038. @@ -843,6 +896,274 @@ static ssize_t pvfs2_file_writev(
  1039.      return do_readv_writev(IO_WRITEV, file, iov, nr_segs, offset);
  1040.  }
  1041.  
  1042. +static ssize_t
  1043. +pvfs2layout_read_pagelist(
  1044. +    struct pnfs_layout_type *layoutid,
  1045. +    struct inode * inode,
  1046. +    struct page **pages,
  1047. +    unsigned int pgbase,
  1048. +    unsigned nr_pages,
  1049. +    loff_t offset,
  1050. +    size_t count,
  1051. +    struct nfs_read_data * nfs_data)
  1052. +{
  1053. +    int ret = -1;
  1054. +    pvfs2_kernel_op_t *new_op = NULL;
  1055. +    int buffer_index = -1;
  1056. +    size_t amt_complete = 0;
  1057. +    size_t total_count = 0, each_count = 0;
  1058. +
  1059. +    pvfs2_print("%s: Reading ino:%lu pgbase:%d baseshift %d %u@%llu\n", __FUNCTION__, inode->i_ino, pgbase, (pgbase >> PAGE_CACHE_SHIFT) , count, offset);
  1060. +
  1061. +    while (total_count < count)
  1062. +    {
  1063. +        new_op = op_alloc();
  1064. +        if (!new_op)
  1065. +        {
  1066. +            ret = -ENOMEM;
  1067. +        goto pnfs_out;
  1068. +        }
  1069. +
  1070. +        new_op->upcall.type = PVFS2_VFS_OP_FILE_IO;
  1071. +        /* disable read-ahead */
  1072. +        new_op->upcall.req.io.readahead_size = 0;
  1073. +        new_op->upcall.req.io.io_type = PVFS_IO_READ;
  1074. +
  1075. +        /* DH - Set the file handle */
  1076. +    set_pvfs2_file_id(&new_op->upcall.req.io.refn, inode, layoutid->mountid);
  1077. +
  1078. +        ret = pvfs_bufmap_get(&buffer_index);
  1079. +        if (ret < 0)
  1080. +        {
  1081. +            pvfs2_error("%s: pvfs_bufmap_get() failure (%d)\n", __FUNCTION__, ret);
  1082. +            op_release(new_op);
  1083. +            goto pnfs_out;
  1084. +        }
  1085. +
  1086. +        /* how much to transfer in this loop iteration */
  1087. +        each_count = (((count - total_count) > pvfs_bufmap_size_query()) ?
  1088. +                      pvfs_bufmap_size_query() : (count - total_count));
  1089. +
  1090. +        new_op->upcall.req.io.buf_index = buffer_index;
  1091. +        new_op->upcall.req.io.count = each_count;
  1092. +        new_op->upcall.req.io.offset = offset;
  1093. +
  1094. +        ret = service_operation(new_op, "pvfs2layout_read_pagelist", PVFS2_OP_RETRY_COUNT,
  1095. +                get_interruptible_flag(inode));
  1096. +
  1097. +        if (ret < 0)
  1098. +        {
  1099. +            /* this macro is defined in pvfs2-kernel.h */
  1100. +            pnfs_io_error();
  1101. +
  1102. +            /*
  1103. +          don't write an error to syslog on signaled operation
  1104. +              termination unless we've got debugging turned on, as
  1105. +              this can happen regularly (i.e. ctrl-c)
  1106. +            */
  1107. +            if(ret == -EINTR)
  1108. +            {
  1109. +                pvfs2_print("%s: returning error %d\n", __FUNCTION__, ret);
  1110. +            }
  1111. +            else
  1112. +            {
  1113. +        pvfs2_error("%s: error reading from handle %llu -- returning %d \n",
  1114. +                __FUNCTION__,
  1115. +                llu(pvfs2_ino_to_handle(inode->i_ino)), ret);
  1116. +            }
  1117. +        goto pnfs_out;
  1118. +        }
  1119. +        /*
  1120. +         * copy data to application by pushing it out to the iovec.
  1121. +         * Number of segments to copy so that we don't
  1122. +         * overflow the block-size is set in seg_array[], and
  1123. +         * ptr points to the appropriate beginning of the
  1124. +         * iovec from where data needs to be copied to, and
  1125. +         * new_op->downcall.resp.io.amt_complete indicates
  1126. +         * the size in bytes that needs to be pushed out
  1127. +         */
  1128. +        if (new_op->downcall.resp.io.amt_complete)
  1129. +        {
  1130. +        ret = pvfs_copy_from_bufmap_to_pages(buffer_index, pages, nr_pages);
  1131. +        if (ret < 0)
  1132. +            {
  1133. +                pvfs2_error("%s: Failed to copy user buffer.  Please make sure "
  1134. +                            "that the pvfs2-client is running.\n", __FUNCTION__);
  1135. +                /* put error codes in downcall so that handle_io_error()
  1136. +                 * preserves it properly */
  1137. +                new_op->downcall.status = ret;
  1138. +                pnfs_io_error();
  1139. +        goto pnfs_out;
  1140. +            }
  1141. +        }
  1142. +        offset += new_op->downcall.resp.io.amt_complete;
  1143. +        total_count += new_op->downcall.resp.io.amt_complete;
  1144. +        amt_complete = new_op->downcall.resp.io.amt_complete;
  1145. +
  1146. +        /*
  1147. +          tell the device file owner waiting on I/O that this read has
  1148. +          completed and it can return now.  in this exact case, on
  1149. +          wakeup the device will free the op, so we *cannot* touch it
  1150. +          after this.
  1151. +        */
  1152. +        wake_up_device_for_return(new_op);
  1153. +        pvfs_bufmap_put(buffer_index);
  1154. +
  1155. +        /* if we got a short write, fall out and return what we got so far.
  1156. +         */
  1157. +        if (amt_complete < each_count)
  1158. +        {
  1159. +            break;
  1160. +        }
  1161. +    }
  1162. +
  1163. +    /* success of at least some data! */
  1164. +    ret = total_count;
  1165. +
  1166. +pnfs_out:
  1167. +    /* Call back into the nfs client to clean up the committed pages */
  1168. +    pnfs_callback_ops->nfs_readlist_complete(nfs_data, ret, 1);
  1169. +
  1170. +    return ret;
  1171. +}
  1172. +
  1173. +/* Write data from a several contiguous user buffers (an iovec)
  1174. + * into a file at a specified offset.
  1175. + */
  1176. +static ssize_t pvfs2layout_write_pagelist(
  1177. +    struct pnfs_layout_type * layoutid,
  1178. +    struct inode * inode,
  1179. +    struct page **pages,
  1180. +    unsigned int pgbase,
  1181. +    unsigned nr_pages,
  1182. +    loff_t offset,
  1183. +    size_t count,
  1184. +    int sync,
  1185. +    struct nfs_write_data* nfs_data)
  1186. +{
  1187. +    int ret = -1;
  1188. +    pvfs2_kernel_op_t *new_op = NULL;
  1189. +    int buffer_index = -1;
  1190. +    size_t amt_complete = 0;
  1191. +    size_t total_count = 0, each_count = 0;
  1192. +
  1193. +    pvfs2_print("%s: Writing ino:%lu pgbase:%d baseshift %d %u@%llu\n", __FUNCTION__, inode->i_ino, pgbase, (pgbase >> PAGE_CACHE_SHIFT) , count, offset);
  1194. +
  1195. +    while (total_count < count)
  1196. +    {
  1197. +        new_op = op_alloc();
  1198. +        if (!new_op)
  1199. +        {
  1200. +            ret = -ENOMEM;
  1201. +        goto pnfs_out;
  1202. +        }
  1203. +
  1204. +        new_op->upcall.type = PVFS2_VFS_OP_FILE_IO;
  1205. +        new_op->upcall.req.io.io_type = PVFS_IO_WRITE;
  1206. +        /* DH - Set the file handle */
  1207. +    set_pvfs2_file_id(&new_op->upcall.req.io.refn, inode, layoutid->mountid);
  1208. +
  1209. +        ret = pvfs_bufmap_get(&buffer_index);
  1210. +        if (ret < 0)
  1211. +        {
  1212. +            pvfs2_error("%s: pvfs_bufmap_get() failure (%d)\n", __FUNCTION__, ret);
  1213. +            op_release(new_op);
  1214. +        goto pnfs_out;
  1215. +        }
  1216. +
  1217. +        /* how much to transfer in this loop iteration */
  1218. +        each_count = (((count - total_count) > pvfs_bufmap_size_query()) ?
  1219. +                      pvfs_bufmap_size_query() : (count - total_count));
  1220. +
  1221. +        new_op->upcall.req.io.buf_index = buffer_index;
  1222. +        new_op->upcall.req.io.count = each_count;
  1223. +        new_op->upcall.req.io.offset = offset;
  1224. +        pvfs2_print("%s: nr_pages %u, offset: %llu each_count: %d\n", __FUNCTION__, nr_pages, offset, each_count);
  1225. +
  1226. +        /*
  1227. +         * copy data from application by pulling it out  of the iovec.
  1228. +         * Number of segments to copy so that we don't overflow the block-size
  1229. +         * is set in seg_array[], and ptr points to the appropriate
  1230. +         * beginning of the iovec from where data needs to be copied out,
  1231. +         * and each_count indicates the size in bytes that needs to be pulled
  1232. +         * out.  */
  1233. +        ret = pvfs_copy_from_pages_to_bufmap(buffer_index, pages, nr_pages);
  1234. +
  1235. +        if (ret < 0)
  1236. +        {
  1237. +            pvfs2_error("%s: Failed to copy user buffer.  Please make sure "
  1238. +                        "that the pvfs2-client is running. %d\n", __FUNCTION__, ret);
  1239. +            op_release(new_op);
  1240. +            pvfs_bufmap_put(buffer_index);
  1241. +        goto pnfs_out;
  1242. +        }
  1243. +        ret = service_operation(new_op, "pvfs2layout_write_pagelist", PVFS2_OP_RETRY_COUNT,
  1244. +                get_interruptible_flag(inode));
  1245. +
  1246. +        if (ret < 0)
  1247. +        {
  1248. +        pvfs2_error("%s: io downcall status error\n", __FUNCTION__);
  1249. +            /* this macro is defined in pvfs2-kernel.h */
  1250. +            pnfs_io_error();
  1251. +            /*
  1252. +          don't write an error to syslog on signaled operation
  1253. +              termination unless we've got debugging turned on, as
  1254. +              this can happen regularly (i.e. ctrl-c)
  1255. +            */
  1256. +            if(ret == -EINTR)
  1257. +            {
  1258. +                pvfs2_print("%s: returning error %d\n", __FUNCTION__, ret);
  1259. +            }
  1260. +            else
  1261. +            {
  1262. +        pvfs2_error("%s: error reading from handle %llu -- returning %d \n",
  1263. +                __FUNCTION__,
  1264. +                llu(pvfs2_ino_to_handle(inode->i_ino)), ret);
  1265. +            }
  1266. +        goto pnfs_out;
  1267. +        }
  1268. +
  1269. +        offset += new_op->downcall.resp.io.amt_complete;
  1270. +        total_count += new_op->downcall.resp.io.amt_complete;
  1271. +        amt_complete = new_op->downcall.resp.io.amt_complete;
  1272. +
  1273. +        /*
  1274. +          tell the device file owner waiting on I/O that this read has
  1275. +          completed and it can return now.  in this exact case, on
  1276. +          wakeup the device will free the op, so we *cannot* touch it
  1277. +          after this.
  1278. +        */
  1279. +        wake_up_device_for_return(new_op);
  1280. +        pvfs_bufmap_put(buffer_index);
  1281. +
  1282. +        /* if we got a short write, fall out and return what we got so
  1283. +         * far TODO: define semantics here- kind of depends on pvfs2
  1284. +         * semantics that don't really exist yet
  1285. +         */
  1286. +        if (amt_complete < each_count)
  1287. +        {
  1288. +            break;
  1289. +        }
  1290. +    }
  1291. +
  1292. +    /* 'sync' is 4 if it the write is stable (nfs.h FLUSH_STABLE) */
  1293. +    if (sync == 4)
  1294. +    {
  1295. +    ret = pvfs2layout_fsync_inode(inode, NULL, sync, layoutid);
  1296. +    if (ret)
  1297. +        goto pnfs_out;
  1298. +    }
  1299. +
  1300. +    /* success of at least some data! */
  1301. +    ret = total_count;
  1302. +
  1303. +pnfs_out:
  1304. +    /* Call back into the nfs client to clean up the committed pages */
  1305. +    pnfs_callback_ops->nfs_writelist_complete(nfs_data, ret);
  1306. +
  1307. +    return ret;
  1308. +}
  1309. +
  1310.  #ifdef HAVE_AIO_VFS_SUPPORT
  1311.  /*
  1312.   * NOTES on the aio implementation.
  1313. @@ -1688,7 +2009,8 @@ out_error:
  1314.  
  1315.  /** Perform a miscellaneous operation on a file.
  1316.   */
  1317. -int pvfs2_ioctl(
  1318. +int pvfs2layout_ioctl(
  1319. +    struct pnfs_layout_type *layoutid,
  1320.      struct inode *inode,
  1321.      struct file *file,
  1322.      unsigned int cmd,
  1323. @@ -1700,6 +2022,114 @@ int pvfs2_ioctl(
  1324.      return ret;
  1325.  }
  1326.  
  1327. +/* Create a filelayout layout structure and return it
  1328. + * TODO: Require a destroy_layout function in the main interface.
  1329. + */
  1330. +struct pnfs_layout_type*
  1331. +pvfs2layout_alloc_layout(struct pnfs_mount_type * mountid, struct inode * inode)
  1332. +{
  1333. +    struct pnfs_layout_type* pnfslay = NULL;
  1334. +    struct pvfs2layout_layout_type* nfslay = NULL;
  1335. +
  1336. +    pnfslay = kmalloc(sizeof(struct pnfs_layout_type), GFP_KERNEL);
  1337. +    if (!pnfslay)
  1338. +    return NULL;
  1339. +    nfslay = kmalloc(sizeof(struct pvfs2layout_layout_type), GFP_KERNEL);
  1340. +    if (!nfslay)
  1341. +    return NULL;
  1342. +
  1343. +    pnfslay->layoutid = (void*)nfslay;
  1344. +    pnfslay->mountid = mountid;
  1345. +    return pnfslay;
  1346. +}
  1347. +
  1348. +/* Free a filelayout layout structure
  1349. + */
  1350. +void
  1351. +pvfs2layout_free_layout(struct pnfs_layout_type * layoutid, struct inode * inode, loff_t offset, size_t count)
  1352. +{
  1353. +    struct pvfs2layout_layout_type* pvfs2lay = NULL;
  1354. +    if (layoutid)
  1355. +    pvfs2lay = (struct pvfs2layout_layout_type*)layoutid->layoutid;
  1356. +    if (pvfs2lay != NULL)
  1357. +    kfree(pvfs2lay);
  1358. +    kfree(layoutid);
  1359. +}
  1360. +
  1361. +/* Decode layout and store in layoutid.  Overwrite any existing layout
  1362. + * information for this file.
  1363. + * I'm currently storing nothing in layoutid;
  1364. + */
  1365. +struct pnfs_layout_type*
  1366. +pvfs2layout_set_layout(struct pnfs_layout_type* layoutid,
  1367. +              struct inode* inode,
  1368. +              void* layout)
  1369. +{
  1370. +    pvfs2_kernel_op_t *new_op = NULL;
  1371. +    int ret = -ENOTTY, layoutsize = 0, dfilecount = 0;
  1372. +    struct pnfs_mount_type * mountid;
  1373. +    struct pvfs2layout_mount_type* pvfs2mount;
  1374. +    void* layout_ptr = layout;
  1375. +
  1376. +    pvfs2_print("%s: Begin\n",__FUNCTION__);
  1377. +
  1378. +    if (!layout) {
  1379. +        pvfs2_error("%s: layout null!\n",__FUNCTION__);
  1380. +        return NULL;
  1381. +    }
  1382. +
  1383. +    if (!layoutid) {
  1384. +        pvfs2_error("%s: layoutid null!\n",__FUNCTION__);
  1385. +        return NULL;
  1386. +    }
  1387. +    mountid = layoutid->mountid;
  1388. +
  1389. +    if (!mountid) {
  1390. +    pvfs2_error("%s: mountid null!\n",__FUNCTION__);
  1391. +    return NULL;
  1392. +    }
  1393. +
  1394. +    pvfs2mount = (struct pvfs2layout_mount_type*)mountid->mountid;
  1395. +
  1396. +    if (!pvfs2mount) {
  1397. +    pvfs2_error("%s: pvfs2mount struct null!\n",__FUNCTION__);
  1398. +    return NULL;
  1399. +    }
  1400. +
  1401. +    new_op = op_alloc();
  1402. +    if (!new_op)
  1403. +    {
  1404. +    pvfs2_error("%s: kmem_cache_alloc failed!\n",__FUNCTION__);
  1405. +    return NULL;
  1406. +    }
  1407. +    new_op->upcall.type = PVFS2_VFS_OP_SET_LAYOUT;
  1408. +
  1409. +    /* Set the global fs id.  Current I only handle 1 fs.  I would
  1410. +     * need to create a hash of ino to fs_id to handle more */
  1411. +    pnfs_decode_int32_t(&layout, &layoutsize);
  1412. +    pnfs_decode_int32_t(&layout, &pvfs2mount->pnfs_fs_id);
  1413. +
  1414. +    /* For debugging, see how many data handles we have */
  1415. +    pnfs_decode_int32_t(&layout, &dfilecount);
  1416. +    pvfs2_print("%s LAYOUT: bytes: %d fsid: %d, #dfiles: %d\n",__FUNCTION__, layoutsize, pvfs2mount->pnfs_fs_id, dfilecount);
  1417. +
  1418. +    /* DH - Set the file handle */
  1419. +    set_pvfs2_file_id(&new_op->upcall.req.setlayout.refn, inode, layoutid->mountid);
  1420. +
  1421. +    memcpy(new_op->upcall.req.setlayout.layout, layout_ptr, layoutsize);
  1422. +    ret = service_operation(
  1423. +    new_op, "pvfs2_file_set_layout", PVFS2_OP_RETRY_COUNT,
  1424. +    get_interruptible_flag(inode));
  1425. +
  1426. +    op_release(new_op);
  1427. +
  1428. +    if (ret < 0) {
  1429. +        pvfs2_error("%s: returning error %d\n", __FUNCTION__, ret);
  1430. +        return NULL;
  1431. +    }
  1432. +    return layoutid;
  1433. +}
  1434. +
  1435.  /** Memory map a region of a file.
  1436.   */
  1437.  static int pvfs2_file_mmap(struct file *file, struct vm_area_struct *vma)
  1438. @@ -1778,14 +2208,15 @@ int pvfs2_file_release(
  1439.  
  1440.  /** Push all data for a specific file onto permanent storage.
  1441.   */
  1442. -int pvfs2_fsync(
  1443. -    struct file *file,
  1444. +int pvfs2layout_fsync_inode(
  1445. +    struct inode* inode,
  1446.      struct dentry *dentry,
  1447. -    int datasync)
  1448. +    int datasync,
  1449. +    struct pnfs_layout_type * layoutid)
  1450.  {
  1451.      int ret = -EINVAL;
  1452. -    pvfs2_inode_t *pvfs2_inode = PVFS2_I(file->f_dentry->d_inode);
  1453.      pvfs2_kernel_op_t *new_op = NULL;
  1454. +    /* DH: There is no longer a PVFS2 inode */
  1455.  
  1456.      new_op = op_alloc();
  1457.      if (!new_op)
  1458. @@ -1793,10 +2224,12 @@ int pvfs2_fsync(
  1459.          return -ENOMEM;
  1460.      }
  1461.      new_op->upcall.type = PVFS2_VFS_OP_FSYNC;
  1462. -    new_op->upcall.req.fsync.refn = pvfs2_inode->refn;
  1463. +
  1464. +    /* DH - Set the file handle */
  1465. +    set_pvfs2_file_id(&new_op->upcall.req.fsync.refn, inode, layoutid->mountid);
  1466.  
  1467.      ret = service_operation(new_op, "pvfs2_fsync", 0,
  1468. -                      get_interruptible_flag(file->f_dentry->d_inode));
  1469. +                      get_interruptible_flag(inode));
  1470.  
  1471.      pvfs2_print("pvfs2_fsync got return value of %d\n",ret);
  1472.  
  1473. @@ -1804,11 +2237,163 @@ int pvfs2_fsync(
  1474.      return ret;
  1475.  }
  1476.  
  1477. +int pvfs2layout_fsync(
  1478. +    struct pnfs_layout_type * layoutid,
  1479. +    struct file *file,
  1480. +    struct dentry *dentry,
  1481. +    int datasync)
  1482. +{
  1483. +    return pvfs2layout_fsync_inode(file->f_dentry->d_inode, dentry, datasync, layoutid);
  1484. +}
  1485. +
  1486. +/* The pNFS client calls this function after flushing pages to the server.
  1487. + * Since pvfs2 doesn't have a way to sync to disk only specific regions of
  1488. + * a file, we just fsync the whole thing
  1489. + */
  1490. +int pvfs2layout_commit(struct pnfs_layout_type * layoutid,
  1491. +               struct inode* ino,
  1492. +               struct list_head *pages,
  1493. +               int sync,
  1494. +               struct nfs_write_data *nfs_data)
  1495. +{
  1496. +    int status;
  1497. +    status = pvfs2layout_fsync_inode(ino, NULL, 1, layoutid);
  1498. +
  1499. +    /* Call back into the nfs client to clean up the committed pages */
  1500. +    pnfs_callback_ops->nfs_commit_complete(nfs_data, status);
  1501. +
  1502. +    return status;
  1503. +}
  1504. +
  1505.  /** Change the file pointer position for an instance of an open file.
  1506.   *
  1507.   *  \note If .llseek is overriden, we must acquire lock as described in
  1508.   *        Documentation/filesystems/Locking.
  1509.   */
  1510. +
  1511. +/* Split wsize/rsize chunks so they do not span multiple data servers
  1512. + */
  1513. +int
  1514. +pvfs2layout_gather_across_stripes(struct pnfs_mount_type* mountid)
  1515. +{
  1516. +    return 1;
  1517. +}
  1518. +
  1519. +/* Retrieve the blocksize of the file system and return.
  1520. + * TODO: Do other layout drivers require access to a file's layout in order to
  1521. + * determine this value?
  1522. + */
  1523. +ssize_t
  1524. +pvfs2layout_get_blocksize(struct pnfs_mount_type* mountid)
  1525. +{
  1526. +    return pvfs_bufmap_size_query();
  1527. +}
  1528. +
  1529. +/* Use the NFSv4 page cache
  1530. +*/
  1531. +int
  1532. +pvfs2layout_use_pagecache(struct pnfs_layout_type* layoutid, struct inode* inode)
  1533. +{
  1534. +    return use_pagecache;
  1535. +}
  1536. +
  1537. +/* Issue a layoutget in the same compound as OPEN
  1538. + */
  1539. +int
  1540. +pvfs2layout_layoutget_on_open(struct pnfs_mount_type* mountid)
  1541. +{
  1542. +    return 0;
  1543. +}
  1544. +
  1545. +/* Below the Write threshold, the pNFS client will use standard NFSv4 write */
  1546. +ssize_t
  1547. +pvfs2layout_get_write_threshold(struct pnfs_layout_type* layoutid, struct inode* inode)
  1548. +{
  1549. +    return write_threshold;
  1550. +}
  1551. +
  1552. +/* Below the Read threshold, the pNFS client will use standard NFSv4 read */
  1553. +ssize_t
  1554. +pvfs2layout_get_read_threshold(struct pnfs_layout_type* layoutid, struct inode* inode)
  1555. +{
  1556. +    return read_threshold;
  1557. +}
  1558. +
  1559. +struct pnfs_mount_type*
  1560. +pvfs2layout_initialize_mountpoint(struct super_block* sb)
  1561. +{
  1562. +    struct pvfs2layout_mount_type* fl_mt;
  1563. +    struct pnfs_mount_type* mt;
  1564. +
  1565. +    pvfs2_print("%s: Begin\n",__FUNCTION__);
  1566. +
  1567. +    fl_mt = kmalloc(sizeof(struct pvfs2layout_mount_type), GFP_KERNEL);
  1568. +    if (!fl_mt)
  1569. +    return NULL;
  1570. +    mt = kmalloc(sizeof(struct pnfs_mount_type), GFP_KERNEL);
  1571. +    if (!mt)
  1572. +    return NULL;
  1573. +
  1574. +    fl_mt->fl_sb = sb;
  1575. +    fl_mt->pnfs_fs_id = -1;
  1576. +    mt->mountid = (void*)fl_mt;
  1577. +    return mt;
  1578. +}
  1579. +
  1580. +int
  1581. +pvfs2layout_uninitialize_mountpoint(struct pnfs_mount_type* mountid)
  1582. +{
  1583. +    struct filelayout_mount_type* fl_mt = NULL;
  1584. +
  1585. +    pvfs2_print("%s: Begin\n",__FUNCTION__);
  1586. +
  1587. +    if (mountid)
  1588. +    fl_mt = (struct filelayout_mount_type*)mountid->mountid;
  1589. +    if (fl_mt != NULL)
  1590. +    kfree(fl_mt);
  1591. +    kfree(mountid);
  1592. +    return 0;
  1593. +}
  1594. +
  1595. +/* TODO: All over the code I'm returning error values without calling
  1596. + * the pNFS callback functions.  Is this bad when using the
  1597. + * page_cache?  I think so.
  1598. + */
  1599. +struct layoutdriver_io_operations pvfs2layout_io_operations =
  1600. +{
  1601. +    .fsync                   = pvfs2layout_fsync,
  1602. +    .commit                  = pvfs2layout_commit,
  1603. +    .read_pagelist           = pvfs2layout_read_pagelist,
  1604. +    .write_pagelist          = pvfs2layout_write_pagelist,
  1605. +    .read                    = pvfs2layout_file_read,
  1606. +    .write                   = pvfs2layout_file_write,
  1607. +    .set_layout              = pvfs2layout_set_layout,
  1608. +    .alloc_layout            = pvfs2layout_alloc_layout,
  1609. +    .free_layout             = pvfs2layout_free_layout,
  1610. +    .initialize_mountpoint   = pvfs2layout_initialize_mountpoint,
  1611. +    .uninitialize_mountpoint = pvfs2layout_uninitialize_mountpoint,
  1612. +    .ioctl                   = pvfs2layout_ioctl,
  1613. +};
  1614. +
  1615. +struct layoutdriver_policy_operations pvfs2layout_policy_operations =
  1616. +{
  1617. +    .gather_across_stripes = pvfs2layout_gather_across_stripes,
  1618. +    .get_blocksize         = pvfs2layout_get_blocksize,
  1619. +    .use_pagecache         = pvfs2layout_use_pagecache,
  1620. +    .layoutget_on_open     = pvfs2layout_layoutget_on_open,
  1621. +    .get_read_threshold    = pvfs2layout_get_read_threshold,
  1622. +    .get_write_threshold   = pvfs2layout_get_write_threshold,
  1623. +};
  1624. +
  1625. +struct pnfs_layoutdriver_type pvfs2layout_type =
  1626. +{
  1627. +    .id = LAYOUT_PVFS2,
  1628. +    .name = "LAYOUT_PVFS2",
  1629. +    .ld_io_ops = &pvfs2layout_io_operations,
  1630. +    .ld_policy_ops = &pvfs2layout_policy_operations,
  1631. +};
  1632. +
  1633. +/* CODE NO LONGER USED BEYOND THIS POINT */
  1634.  loff_t pvfs2_file_llseek(struct file *file, loff_t offset, int origin)
  1635.  {
  1636.      int ret = -EINVAL;
  1637. @@ -2013,19 +2598,15 @@ struct file_operations pvfs2_file_operat
  1638.      fsync : pvfs2_fsync
  1639.  #else
  1640.      .llseek = pvfs2_file_llseek,
  1641. -    .read = pvfs2_file_read,
  1642. -    .write = pvfs2_file_write,
  1643.      .readv = pvfs2_file_readv,
  1644.      .writev = pvfs2_file_writev,
  1645.  #ifdef HAVE_AIO_VFS_SUPPORT
  1646.      .aio_read = pvfs2_file_aio_read,
  1647.      .aio_write = pvfs2_file_aio_write,
  1648.  #endif
  1649. -    .ioctl = pvfs2_ioctl,
  1650.      .mmap = pvfs2_file_mmap,
  1651.      .open = pvfs2_file_open,
  1652.      .release = pvfs2_file_release,
  1653. -    .fsync = pvfs2_fsync,
  1654.  #ifdef HAVE_SENDFILE_VFS_SUPPORT
  1655.      .sendfile = pvfs2_sendfile,
  1656.  #endif
  1657. diff -puN src/kernel/linux-2.6/pvfs2-bufmap.c~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-bufmap.c
  1658. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-bufmap.c~pvfs2layoutdriver    2008-01-05 18:13:54.000000000 -0800
  1659. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-bufmap.c    2008-01-05 18:13:54.000000000 -0800
  1660. @@ -770,6 +770,78 @@ int pvfs_bufmap_copy_to_user_task(
  1661.  
  1662.  #endif
  1663.  
  1664. +int pvfs_copy_from_pages_to_bufmap(
  1665. +    int buffer_index,
  1666. +    struct page **pages,
  1667. +    unsigned nr_pages)
  1668. +{
  1669. +    void *to_kaddr = NULL, *respointer = NULL, *from_kaddr = NULL;
  1670. +    struct pvfs_bufmap_desc *to = &desc_array[buffer_index];
  1671. +    int i;
  1672. +
  1673. +    pvfs2_print("%s: index %d nr_pages %d\n", __FUNCTION__, buffer_index, nr_pages);
  1674. +
  1675. +    if (bufmap_init == 0)
  1676. +    {
  1677. +        pvfs2_print("%s: not yet initialized; returning\n", __FUNCTION__);
  1678. +        return 1;
  1679. +    }
  1680. +
  1681. +    for (i = 0; i < nr_pages; i++)
  1682. +    {
  1683. +    from_kaddr = pvfs2_kmap(pages[i]);
  1684. +        to_kaddr = pvfs2_kmap(to->page_array[i]);
  1685. +    respointer = memcpy(to_kaddr, from_kaddr, PAGE_SIZE);
  1686. +    if (respointer == NULL)
  1687. +    {
  1688. +        pvfs2_error("%s: Failed to copy data from kernel space\n", __FUNCTION__);
  1689. +        return -EFAULT;
  1690. +    }
  1691. +
  1692. +        pvfs2_kunmap(to->page_array[i]);
  1693. +        pvfs2_kunmap(pages[i]);
  1694. +    }
  1695. +
  1696. +    return 0;
  1697. +}
  1698. +
  1699. +int pvfs_copy_from_bufmap_to_pages(
  1700. +    int buffer_index,
  1701. +    struct page **pages,
  1702. +    unsigned nr_pages)
  1703. +{
  1704. +    void *to_kaddr = NULL, *respointer = NULL, *from_kaddr = NULL;
  1705. +    struct pvfs_bufmap_desc *to = &desc_array[buffer_index];
  1706. +    int i;
  1707. +
  1708. +    pvfs2_print("%s: index %d nr_pages %d\n", __FUNCTION__, buffer_index, nr_pages);
  1709. +
  1710. +    if (bufmap_init == 0)
  1711. +    {
  1712. +        pvfs2_print("%s: not yet initialized; returning\n", __FUNCTION__);
  1713. +        return 1;
  1714. +    }
  1715. +
  1716. +    for (i = 0; i < nr_pages; i++)
  1717. +    {
  1718. +    to_kaddr = pvfs2_kmap(pages[i]);
  1719. +        from_kaddr = pvfs2_kmap(to->page_array[i]);
  1720. +    respointer = memcpy(to_kaddr, from_kaddr, PAGE_SIZE);
  1721. +    if (respointer == NULL)
  1722. +    {
  1723. +        pvfs2_error("%s: Failed to copy data from kernel space\n", __FUNCTION__);
  1724. +        return -EFAULT;
  1725. +    }
  1726. +
  1727. +        pvfs2_kunmap(to->page_array[i]);
  1728. +        pvfs2_kunmap(pages[i]);
  1729. +    }
  1730. +
  1731. +    return 0;
  1732. +}
  1733. +
  1734. +
  1735. +
  1736.  /*
  1737.   * Local variables:
  1738.   *  c-indent-level: 4
  1739. diff -puN src/kernel/linux-2.6/pvfs2-bufmap.h~pvfs2layoutdriver src/kernel/linux-2.6/pvfs2-bufmap.h
  1740. --- pvfs2-1.5.1-ld/src/kernel/linux-2.6/pvfs2-bufmap.h~pvfs2layoutdriver    2008-01-05 18:13:54.000000000 -0800
  1741. +++ pvfs2-1.5.1-ld-dhildeb/src/kernel/linux-2.6/pvfs2-bufmap.h    2008-01-05 18:13:54.000000000 -0800
  1742. @@ -67,6 +67,16 @@ int pvfs_bufmap_copy_to_user_task(
  1743.          int size);
  1744.  #endif
  1745.  
  1746. +int pvfs_copy_from_bufmap_to_pages(
  1747. +    int buffer_index,
  1748. +    struct page **pages,
  1749. +    unsigned nr_pages);
  1750. +
  1751. +int pvfs_copy_from_pages_to_bufmap(
  1752. +    int buffer_index,
  1753. +    struct page **pages,
  1754. +    unsigned nr_pages);
  1755. +
  1756.  #endif /* __PVFS2_BUFMAP_H */
  1757.  
  1758.  /*
  1759. _
  1760.