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 / p00002_pnfs_nfslayoutsupport.patch < prev    next >
Text File  |  2008-02-22  |  28KB  |  705 lines

  1.  
  2. Modify the NFS exported PVFS2 client to support the pNFS file-based layout driver.
  3. This is done by supporting the pNFS export operations that manage the pNFS
  4. data layout information.
  5.  
  6. The goal of this patch is to generate a pNFS file layout that matches the
  7. existing PVFS2 layout for a given file.  By creating a matching layout, the
  8. pNFS client can send NFSv4 I/O requests to the data server which contains
  9. the requested data.
  10.  
  11. A matching layout can be created if the PVFS2 layout is round-robin and
  12. the start server is always server 0 (this patch ensures this). 
  13.  
  14. When a pNFS client requests a file-based data layout for a file, the exported PVFS2
  15. client module retrieves the ordered listed of I/O servers rom the PVFS2 metadata server.
  16. The PVFS2 client then uses the I/O servers to create a file-based layout and
  17. returns the layout to the nfs server.
  18.  
  19. To retrieve the I/O servers,  a new upcall, getdevlist, has been created.  The
  20. getdevlist operation uses the PINT_cached_config_get_server_array function
  21. to retrieve the I/O servers from the metadata server.
  22.  
  23. To use this patch and generate a file-based layout based on the existing PVFS2
  24. I/O servers, the layouttype proc variable must be set to LAYOUT_NFSV4_FILES.
  25.  
  26. This patch compiles against a version of the 2.6.18.3 linux kernel.
  27.  
  28. ---
  29.  
  30.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/apps/kernel/linux/pvfs2-client-core.c |  120 ++++
  31.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/common/misc/pint-cached-config.c      |   17 
  32.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/downcall.h           |    7 
  33.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pnfs.c               |  278 ++++++++++
  34.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-dev-proto.h    |    1 
  35.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-kernel.h       |    3 
  36.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-mod.c          |    1 
  37.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-pnfs.h         |    1 
  38.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-proc.c         |    5 
  39.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/super.c              |    4 
  40.  pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/upcall.h             |    6 
  41.  11 files changed, 440 insertions(+), 3 deletions(-)
  42.  
  43. diff -puN src/kernel/linux-2.6/pvfs2-kernel.h~nfslayoutsupport src/kernel/linux-2.6/pvfs2-kernel.h
  44. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/pvfs2-kernel.h~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  45. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-kernel.h    2008-01-05 17:52:37.000000000 -0800
  46. @@ -454,6 +454,8 @@ typedef struct
  47.      struct super_block *sb;
  48.      int    mount_pending;
  49.      struct list_head list;
  50. +    int pnfs_devlist_size;
  51. +    char pnfs_devlist[PVFS2_MAX_DEVLIST_LEN];
  52.  } pvfs2_sb_info_t;
  53.  
  54.  /** a temporary structure used only for sb mount time that groups the
  55. @@ -992,6 +994,7 @@ int service_operation(pvfs2_kernel_op_t*
  56.      int flags);
  57.  
  58.  extern int layouttype;
  59. +extern int layout_stripesize;
  60.  
  61.  /** handles two possible error cases, depending on context.
  62.   *
  63. diff -puN src/kernel/linux-2.6/pvfs2-mod.c~nfslayoutsupport src/kernel/linux-2.6/pvfs2-mod.c
  64. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/pvfs2-mod.c~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  65. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-mod.c    2008-01-05 17:52:37.000000000 -0800
  66. @@ -30,6 +30,7 @@ int gossip_debug_mask = 0;
  67.  int op_timeout_secs = PVFS2_DEFAULT_OP_TIMEOUT_SECS;
  68.  
  69.  int layouttype = LAYOUT_PVFS2;
  70. +int layout_stripesize = 65536;
  71.  
  72.  MODULE_LICENSE("GPL");
  73.  MODULE_AUTHOR("PVFS2 Development Team");
  74. diff -puN src/kernel/linux-2.6/pvfs2-proc.c~nfslayoutsupport src/kernel/linux-2.6/pvfs2-proc.c
  75. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/pvfs2-proc.c~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  76. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-proc.c    2008-01-05 17:52:37.000000000 -0800
  77. @@ -264,6 +264,8 @@ static int min_debug[] = {0}, max_debug[
  78.  static int min_op_timeout_secs[] = {0}, max_op_timeout_secs[] = {INT_MAX};
  79.  /* DH: LAYOUT_NFSV4_FILES defined in the nfs header files */
  80.  static int min_layouttype[] = {LAYOUT_NFSV4_FILES}, max_layouttype[] = {5};
  81. +static int min_stripesize[] = {0}, max_stripesize[] = {INT_MAX};
  82. +
  83.  static ctl_table pvfs2_acache_table[] = {
  84.      /* controls acache timeout */
  85.      {1, "timeout-msecs", NULL, sizeof(int), 0644, NULL,
  86. @@ -331,6 +333,9 @@ static ctl_table pvfs2_table[] = {
  87.      {9, "layouttype", &layouttype, sizeof(int), 0644, NULL,
  88.          &proc_dointvec_minmax, &sysctl_intvec,
  89.          NULL, &min_layouttype, &max_layouttype},
  90. +    {9, "layout_stripesize", &layout_stripesize, sizeof(int), 0644, NULL,
  91. +        &proc_dointvec_minmax, &sysctl_intvec,
  92. +        NULL, &min_stripesize, &max_stripesize},
  93.      {0}
  94.  };
  95.  static ctl_table fs_table[] = {
  96. diff -puN src/apps/kernel/linux/pvfs2-client-core.c~nfslayoutsupport src/apps/kernel/linux/pvfs2-client-core.c
  97. --- pvfs-2.6.3-pnfsfilelayout/src/apps/kernel/linux/pvfs2-client-core.c~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  98. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/apps/kernel/linux/pvfs2-client-core.c    2008-01-05 17:52:37.000000000 -0800
  99. @@ -14,6 +14,10 @@
  100.  #include <pthread.h>
  101.  #include <signal.h>
  102.  #include <getopt.h>
  103. +#include <netdb.h>
  104. +#include <sys/socket.h>
  105. +#include <netinet/in.h>
  106. +#include <arpa/inet.h>
  107.  
  108.  #define __PINT_REQPROTO_ENCODE_FUNCS_C
  109.  #include "pvfs2.h"
  110. @@ -618,6 +622,118 @@ out_cleanup:
  111.       return ret;
  112.  }
  113.  
  114. +#define DFILE_KEY "system.pvfs2.datafile_handles"
  115. +
  116. +static PVFS_error service_pnfs_get_devlist(vfs_request_t *vfs_request)
  117. +{
  118. +    PVFS_error ret = -PVFS_EINVAL;
  119. +    struct server_configuration_s *server_config = NULL;
  120. +    int i, num_io, tmp;
  121. +    PVFS_BMI_addr_t* addr_array;
  122. +    struct hostent *hep;
  123. +    PVFS_fs_id fsid = vfs_request->in_upcall.req.getdevlist.refn.fs_id;
  124. +    struct sockaddr_in io_server;
  125. +    char* ip_addr;
  126. +    char* buffer_orig, *buffer;
  127. +
  128. +    gossip_debug(
  129. +    GOSSIP_CLIENTCORE_DEBUG,
  130. +    "service_pnfs_get_devlist: Start fsid %d | handle %llu\n",
  131. +    fsid,
  132. +    llu(vfs_request->in_upcall.req.getdevlist.refn.handle));
  133. +
  134. +    /* set output buffer */
  135. +    buffer_orig = buffer = vfs_request->out_downcall.resp.getdevlist.devlist;
  136. +
  137. +    /* Retrieve server configuration */
  138. +    server_config = PINT_get_server_config_struct(fsid);
  139. +    if (!server_config)
  140. +    {
  141. +    gossip_err("service_pnfs_get_devlist: Error retrieving server configuration!\n");
  142. +    ret = -PVFS_EINVAL;
  143. +    goto out_noput;
  144. +    }
  145. +
  146. +    /* Get number of io servers to create array */
  147. +    PINT_cached_config_get_num_io(fsid, &num_io);
  148. +    if (num_io <= 0)
  149. +    {
  150. +    gossip_err("service_pnfs_get_devlist: Zero I/O servers!\n");
  151. +    ret = -PVFS_EINVAL;
  152. +    goto out;
  153. +    }
  154. +    addr_array = (PVFS_BMI_addr_t *)malloc(num_io * sizeof(PVFS_BMI_addr_t));
  155. +    if (addr_array == NULL)
  156. +    {
  157. +    gossip_err("service_pnfs_get_devlist: Could not allocate address array\n");
  158. +    ret = -PVFS_ENOMEM;
  159. +    goto out;
  160. +    }
  161. +
  162. +    /* Get array of io servers */
  163. +    ret = PINT_cached_config_get_server_array(server_config,
  164. +                          fsid,
  165. +                          PVFS_MGMT_IO_SERVER,
  166. +                          addr_array,
  167. +                          &num_io);
  168. +    if (ret < 0)
  169. +    {
  170. +    gossip_err("service_pnfs_get_devlist: Could not retrieve server array\n");
  171. +    goto out_free;
  172. +    }
  173. +
  174. +    /* Set number of devices in downcall */
  175. +    encode_int32_t(&buffer, &num_io);
  176. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG,"service_pnfs_get_devlist: num io: %d\n",num_io);
  177. +    /* Loop through io servers for downcall */
  178. +    for (i = 0; i < num_io; i++)
  179. +    {
  180. +    /* get pvfs2 bmi type addr,e.g., tcp://host:3334 */
  181. +    const char* addr_string = PINT_cached_config_map_addr(server_config,
  182. +                                  fsid,
  183. +                                  addr_array[i],
  184. +                                  &tmp);
  185. +    /* strip out tcp and port bits */
  186. +    char* addr_string_alias = PINT_config_get_host_alias_ptr(server_config,
  187. +                                 (char*)addr_string);
  188. +    /* get ip address */
  189. +    if ((hep = gethostbyname(addr_string_alias)) == NULL)
  190. +    {
  191. +        gossip_err("service_pnfs_get_devlist: Could not retrieve server array\n");
  192. +        goto out_free;
  193. +    }
  194. +    memcpy(&(io_server.sin_addr.s_addr), hep->h_addr, hep->h_length);
  195. +    ip_addr = inet_ntoa(io_server.sin_addr);
  196. +    /* add ip addr to downcall result */
  197. +    encode_string(&buffer, &ip_addr);
  198. +
  199. +    /* print debug info */
  200. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG, "%s %d\n", hep->h_name, hep->h_length);
  201. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG, "Dev: %d - %lld - %s - %s - %s\n",
  202. +             i,
  203. +             addr_array[i],
  204. +             addr_string,
  205. +             addr_string_alias,
  206. +             inet_ntoa(io_server.sin_addr));
  207. +    }
  208. +    vfs_request->out_downcall.resp.getdevlist.devlist_size = buffer - buffer_orig;
  209. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG, "bufsize %d\n",
  210. +         vfs_request->out_downcall.resp.getdevlist.devlist_size);
  211. +    free(addr_array);
  212. +    ret = 0;
  213. +out:
  214. +    PINT_put_server_config_struct(server_config);
  215. +out_noput:
  216. +    vfs_request->out_downcall.type = vfs_request->in_upcall.type;
  217. +    vfs_request->out_downcall.status = ret;
  218. +    write_inlined_device_response(vfs_request);
  219. +    gossip_debug(GOSSIP_CLIENTCORE_DEBUG,"service_pnfs_get_devlist: End\n");
  220. +    return 0;
  221. +out_free:
  222. +    free(addr_array);
  223. +    goto out;
  224. +}
  225. +
  226.  static PVFS_error post_getattr_request(vfs_request_t *vfs_request)
  227.  {
  228.      PVFS_error ret = -PVFS_EINVAL;
  229. @@ -2871,6 +2987,9 @@ static inline PVFS_error handle_unexp_vf
  230.              posted_op = 1;
  231.              ret = post_iox_request(vfs_request);
  232.              break;
  233. +        case PVFS2_VFS_OP_GETDEVLIST:
  234. +        ret = service_pnfs_get_devlist(vfs_request);
  235. +            break;
  236.  #ifdef USE_MMAP_RA_CACHE
  237.              /*
  238.                if the mmap-readahead-cache is enabled, cache
  239. @@ -3798,6 +3917,7 @@ static char *get_vfs_op_name_str(int op_
  240.          { PVFS2_VFS_OP_PERF_COUNT, "PVFS2_VFS_OP_PERF_COUNT" },
  241.          { PVFS2_VFS_OP_FSKEY,  "PVFS2_VFS_OP_FSKEY" },
  242.          { PVFS2_VFS_OP_FILE_IOX, "PVFS2_VFS_OP_FILE_IOX" },
  243. +        { PVFS2_VFS_OP_GETDEVLIST,  "PVFS2_VFS_OP_GETDEVLIST" },
  244.          { 0, "UNKNOWN" }
  245.      };
  246.  
  247. diff -puN src/common/misc/pint-cached-config.c~nfslayoutsupport src/common/misc/pint-cached-config.c
  248. --- pvfs-2.6.3-pnfsfilelayout/src/common/misc/pint-cached-config.c~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  249. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/common/misc/pint-cached-config.c    2008-01-05 17:52:37.000000000 -0800
  250. @@ -106,7 +106,8 @@ static int cache_server_array(
  251.      struct server_configuration_s *config, PVFS_fs_id fsid);
  252.  
  253.  static int meta_randomized = 0;
  254. -static int io_randomized = 0;
  255. +/* DH: For now, since pNFS file layout drivers always start at 0 */
  256. +static int io_randomized = 1;
  257.  
  258.  /* PINT_cached_config_initialize()
  259.   *
  260. @@ -438,6 +439,7 @@ int PINT_cached_config_get_next_io(
  261.              {
  262.                  jitter = 0;
  263.              }
  264. +            gossip_debug(GOSSIP_CLIENT_DEBUG, "DH: jitter %d\n",jitter);
  265.              while(jitter-- > -1)
  266.              {
  267.                  cur_mapping = PINT_llist_head(
  268. @@ -450,10 +452,15 @@ int PINT_cached_config_get_next_io(
  269.                          cur_config_cache->data_server_cursor);
  270.                      assert(cur_mapping);
  271.                  }
  272. +        /* DH: Eliminate jitter for pNFS and just set it to the first
  273.                  cur_config_cache->data_server_cursor = PINT_llist_next(
  274.                      cur_config_cache->data_server_cursor);
  275. +        */
  276. +        cur_config_cache->data_server_cursor =
  277. +            cur_config_cache->fs->data_handle_ranges;
  278.              }
  279.              old_data_server_cursor = cur_config_cache->data_server_cursor;
  280. +            gossip_debug(GOSSIP_CLIENT_DEBUG, "DH: old_data_server_cursor %p\n",old_data_server_cursor);
  281.  
  282.              while(num_servers)
  283.              {
  284. @@ -467,11 +474,10 @@ int PINT_cached_config_get_next_io(
  285.                          cur_config_cache->fs->data_handle_ranges;
  286.                      continue;
  287.                  }
  288. -                cur_config_cache->data_server_cursor = PINT_llist_next(
  289. -                    cur_config_cache->data_server_cursor);
  290.  
  291.                  data_server_bmi_str = PINT_config_get_host_addr_ptr(
  292.                      config,cur_mapping->alias_mapping->host_alias);
  293. +                gossip_debug(GOSSIP_CLIENT_DEBUG, "DH: bmi: %s\n",data_server_bmi_str);
  294.  
  295.          if (io_addr_array != NULL)
  296.          {
  297. @@ -492,12 +498,17 @@ int PINT_cached_config_get_next_io(
  298.                  num_servers--;
  299.          if(io_addr_array != NULL)
  300.              io_addr_array++;
  301. +                cur_config_cache->data_server_cursor = PINT_llist_next(
  302. +                    cur_config_cache->data_server_cursor);
  303. +                gossip_debug(GOSSIP_CLIENT_DEBUG, "DH: next data_server_cursor %p\n",cur_config_cache->data_server_cursor);
  304. +
  305.              }
  306.              ret = ((num_servers == 0) ? 0 : ret);
  307.              /* reset data server cursor to point to the old cursor; the
  308.               * jitter on the next iteration will increment it by one
  309.               */
  310.              cur_config_cache->data_server_cursor = old_data_server_cursor;
  311. +            gossip_debug(GOSSIP_CLIENT_DEBUG, "DH: dsc: %p\n",cur_config_cache->data_server_cursor);
  312.          }
  313.      }
  314.      return ret;
  315. diff -puN src/kernel/linux-2.6/downcall.h~nfslayoutsupport src/kernel/linux-2.6/downcall.h
  316. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/downcall.h~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  317. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/downcall.h    2008-01-05 17:52:37.000000000 -0800
  318. @@ -54,6 +54,12 @@ typedef struct
  319.      char layout[PVFS2_MAX_LAYOUT_LEN];
  320.  } pvfs2_getattr_response_t;
  321.  
  322. +typedef struct
  323. +{
  324. +    int devlist_size;
  325. +    char devlist[PVFS2_MAX_DEVLIST_LEN];
  326. +} pvfs2_getdevlist_response_t;
  327. +
  328.  /* the setattr response is a blank downcall */
  329.  typedef struct
  330.  {
  331. @@ -225,6 +231,7 @@ typedef struct
  332.          pvfs2_param_response_t param;
  333.          pvfs2_perf_count_response_t perf_count;
  334.          pvfs2_fs_key_response_t fs_key;
  335. +        pvfs2_getdevlist_response_t getdevlist;
  336.      } resp;
  337.  } pvfs2_downcall_t;
  338.  
  339. diff -puN src/kernel/linux-2.6/pnfs.c~nfslayoutsupport src/kernel/linux-2.6/pnfs.c
  340. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/pnfs.c~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  341. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pnfs.c    2008-01-05 17:52:37.000000000 -0800
  342. @@ -17,10 +17,22 @@
  343.  
  344.  #include "nfsd/nfs4layoutxdr.h"
  345.  
  346. +#include "bmi-byteswap.h"
  347. +
  348.  /* used to protect the layout information for an inode */
  349.  spinlock_t pvfs2_layout_lock = SPIN_LOCK_UNLOCKED;
  350.  
  351.  /****** Common Functions ******/
  352. +#define pnfs_decode_int32_t(pptr,x) do {      \
  353. +        *(x) = bmitoh32(*(int32_t*) *(pptr)); \
  354. +        *(pptr) += 4;                  \
  355. +    } while (0)
  356. +#define pnfs_decode_string(pptr,pbuf) do {                \
  357. +    u_int32_t len = bmitoh32(*(u_int32_t *) *(pptr));    \
  358. +    *pbuf = *(pptr) + 4;                    \
  359. +    *(pptr) += roundup8(4 + len + 1);            \
  360. +    } while (0)
  361. +
  362.  static int
  363.  pvfs2_layout_type(void)
  364.  {
  365. @@ -185,6 +197,265 @@ pvfs2_layout_encode(u32 *p, u32 *end, vo
  366.      return lay_length;
  367.  }
  368.  
  369. +/****** NFSv4 File Layout Functions ******/
  370. +/* Encodes a nfs file pNFS layout.
  371. + * TODO: For now, always return the devices in order,e.g., 0,1,...
  372. + * At some point we need to re-enable randomizing the starting
  373. + * data server in pvfs2 (io_randomized) and then call
  374. + * PVFS_mgmt_get_dfile_array to get the in order list
  375. + * of servers for this data file (see descend and verify_datafiles
  376. + * in src/apps/admin/pvfs2-fs-dump.c)
  377. +*/
  378. +static int
  379. +nfs_build_layout(struct nfsd4_pnfs_layoutget* req, int num_devices)
  380. +{
  381. +    struct nfsd4_pnfs_filelayout* nfslayout;
  382. +    int i;
  383. +    static char buf[80];
  384. +    struct knfsd_fh *fh = (struct knfsd_fh*)req->lg_fh;
  385. +
  386. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Start\n",__FUNCTION__);
  387. +
  388. +    /* Free existing layout if it exists */
  389. +    if (req->lg_layout)
  390. +    {
  391. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Existing layout, freeing existing memory\n",__FUNCTION__);
  392. +    kfree(req->lg_layout);
  393. +    }
  394. +
  395. +    nfslayout = (struct nfsd4_pnfs_filelayout*)kmalloc(sizeof(struct nfsd4_pnfs_filelayout),
  396. +                           GFP_KERNEL);
  397. +
  398. +    /* Set nfs layout information */
  399. +    nfslayout->lg_commit_through_mds = 1;
  400. +    nfslayout->lg_stripe_type = 1; /* sparse */
  401. +    nfslayout->lg_file_size = 0ULL;
  402. +    nfslayout->lg_layout_type = LAYOUT_NFSV4_FILES;
  403. +    nfslayout->lg_indexlist = 0;
  404. +
  405. +    /* the stripe size is in the attributes of the pvfs2 layout,
  406. +     * but for now, just hardcode it to the value of the proc variable
  407. +     */
  408. +    nfslayout->lg_stripe_unit = layout_stripesize;
  409. +
  410. +    /* # dataservers == # dfiles
  411. +     * Note: This is pre-xdr'd by pvfs2 user land code
  412. +     */
  413. +    nfslayout->lg_llistlen = num_devices;
  414. +    gossip_debug(GOSSIP_PNFS_DEBUG,"# data servers:%d\n", nfslayout->lg_llistlen);
  415. +    if (nfslayout->lg_llistlen <= 0)
  416. +    {
  417. +    gossip_err("%s: No data servers!\n",__FUNCTION__);
  418. +    kfree(nfslayout);
  419. +    return -ENOSYS;
  420. +    }
  421. +
  422. +    nfslayout->lg_llist = (struct nfsd4_pnfs_layoutlist*)kmalloc(
  423. +    nfslayout->lg_llistlen * sizeof(struct nfsd4_pnfs_layoutlist), GFP_KERNEL);
  424. +    if (!nfslayout->lg_llist)
  425. +    {
  426. +    gossip_err("%s: Could not allocate nfs device list!\n",__FUNCTION__);
  427. +    kfree(nfslayout);
  428. +    return -ENOMEM;
  429. +    }
  430. +
  431. +    /* set data server and fh info */
  432. +    for (i = 0; i < nfslayout->lg_llistlen; i++) {
  433. +
  434. +    nfslayout->lg_llist[i].dev_id = i;
  435. +    nfslayout->lg_llist[i].dev_index = i;
  436. +    nfslayout->lg_llist[i].dev_fh = *fh;
  437. +
  438. +        /* To edit fh, edit req->lg_fh in place as follows:
  439. +     int SetFH(int *fhP, int sid)
  440. +     {
  441. +     struct knfsd_fh *fh = (struct knfsd_fh *)fhP;
  442. +
  443. +     if (fh->fh_size > 8) {
  444. +     fh->fh_size += 4; // fh_size + 4 for sid
  445. +     fh->fh_fsid_type += max_fsid_type;
  446. +     fhP[(fh->fh_size >> 2)] = sid;
  447. +     fh->fh_fileid_type = 7;
  448. +
  449. +     return 0;
  450. +     }
  451. +     return ENOENT;
  452. +     }
  453. +
  454. +    */
  455. +    }
  456. +
  457. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Printing fh\n", __FUNCTION__);
  458. +    sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x",
  459. +        fh->fh_size,
  460. +        fh->fh_base.fh_pad[0],
  461. +        fh->fh_base.fh_pad[1],
  462. +        fh->fh_base.fh_pad[2],
  463. +        fh->fh_base.fh_pad[3],
  464. +        fh->fh_base.fh_pad[4],
  465. +        fh->fh_base.fh_pad[5]);
  466. +
  467. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s:%s\n", __FUNCTION__, buf);
  468. +
  469. +    /* Set layout to be encoded later */
  470. +    req->lg_layout = (void*)nfslayout;
  471. +    return 0;
  472. +}
  473. +
  474. +/* Retrieves pvfs2 pNFS layout from mds
  475. + * PVFS2_VFS_OP_GETDEVLIST
  476. +*/
  477. +static int
  478. +nfs_getdevlist_upcall(pvfs2_sb_info_t* pvfs2_sb, pvfs2_inode_t* pvfs2_inode)
  479. +{
  480. +    int ret = -EINVAL;
  481. +    pvfs2_kernel_op_t *new_op = NULL;
  482. +
  483. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Start\n", __FUNCTION__);
  484. +
  485. +    /* Check if devlist has already been retrieve for this inode
  486. +     * TODO: need to make this thread aware
  487. +     */
  488. +    if (pvfs2_sb->pnfs_devlist_size <= 0)
  489. +    {
  490. +    /* perform upcall to retrieve layout */
  491. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Retrieving pNFS nfsv4 device list\n", __FUNCTION__);
  492. +
  493. +    new_op = op_alloc(PVFS2_VFS_OP_GETDEVLIST);
  494. +    if (!new_op)
  495. +    {
  496. +        ret = -ENOMEM;
  497. +        goto out;
  498. +    }
  499. +    new_op->upcall.type = PVFS2_VFS_OP_GETDEVLIST;
  500. +    new_op->upcall.req.getdevlist.refn = pvfs2_inode->refn;
  501. +    ret = service_operation(new_op,
  502. +                "pvfs2_getdevlist",
  503. +                get_interruptible_flag((&pvfs2_inode->vfs_inode)));
  504. +    gossip_debug(GOSSIP_PNFS_DEBUG,"pvfs2_getdevlist got return value of %d\n",ret);
  505. +    if (ret || new_op->downcall.resp.getdevlist.devlist_size <= 0)
  506. +    {
  507. +        gossip_err("%s: Error!  Could not retrieve device list (%d)\n",__FUNCTION__, ret);
  508. +        op_release(new_op);
  509. +        ret = -ENOSYS;
  510. +        goto out; /* failure */
  511. +    }
  512. +
  513. +    /* DH: Copy devlist blob for pNFS */
  514. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Server copy devicelist from userland size: %d\n",
  515. +            __FUNCTION__,new_op->downcall.resp.getdevlist.devlist_size);
  516. +    pvfs2_sb->pnfs_devlist_size = new_op->downcall.resp.getdevlist.devlist_size;
  517. +    memcpy(pvfs2_sb->pnfs_devlist, new_op->downcall.resp.getdevlist.devlist, pvfs2_sb->pnfs_devlist_size);
  518. +    op_release(new_op);
  519. +    } else {
  520. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Using cached pNFS nfsv4 device list\n", __FUNCTION__);
  521. +    ret = 0;
  522. +    }
  523. +out:
  524. +    return ret;
  525. +}
  526. +
  527. +/* Retrieves pvfs2 data layout information about the specified file.
  528. + * return- positive 0
  529. + * negative -ENOSYS or pvfs2_inode_getattr error
  530. + */
  531. +static int
  532. +nfs_layout_get(struct inode * inode, void* buf)
  533. +{
  534. +    int ret, devlist_len=0;
  535. +    struct nfsd4_pnfs_layoutget *layout_request = (struct nfsd4_pnfs_layoutget*)buf;
  536. +    pvfs2_inode_t* pvfs2_inode = PVFS2_I(inode);
  537. +    pvfs2_sb_info_t* pvfs2_sb = PVFS2_SB(inode->i_sb);
  538. +    char* buffer;
  539. +
  540. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: off:%Lu ex:%Lu macc:%d iomode:%d\n", __FUNCTION__,
  541. +        layout_request->lg_seg.offset,
  542. +        layout_request->lg_seg.length,
  543. +        layout_request->lg_mxcnt,
  544. +        layout_request->lg_seg.iomode);
  545. +    if ((ret = nfs_getdevlist_upcall(pvfs2_sb, pvfs2_inode)) < 0)
  546. +    return ret;
  547. +    buffer = pvfs2_sb->pnfs_devlist;
  548. +    pnfs_decode_int32_t(&buffer, &devlist_len);
  549. +    ret = nfs_build_layout(layout_request, devlist_len);
  550. +    if (ret)
  551. +    gossip_err("%s: Error!  Could not copy attributes (%d)\n",__FUNCTION__,ret);
  552. +
  553. +    return ret;
  554. +}
  555. +
  556. +/* Convert a encode char buffer into an array of devices.
  557. + * The devices are then freed as they are encoded by nfsd.
  558. +*/
  559. +struct nfsd4_pnfs_devlist*
  560. +nfs_create_devices(int devlist_len, char* buf)
  561. +{
  562. +    struct nfsd4_pnfs_devlist* devlist;
  563. +    int i;
  564. +    struct pnfs_filelayout_devaddr *fdev;
  565. +    char netid[] = "tcp";
  566. +    char nfsport[] = ".8.1";
  567. +    char* temp;
  568. +
  569. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Start Devs: %d\n", __FUNCTION__, devlist_len);
  570. +    devlist = (struct nfsd4_pnfs_devlist*)kmalloc(devlist_len * sizeof(struct nfsd4_pnfs_devlist), PVFS2_GFP_FLAGS);
  571. +    /* todo: ensure space alocated */
  572. +    for (i=0; i < devlist_len; i++)
  573. +    {
  574. +    devlist[i].dev_id = i;
  575. +
  576. +    fdev = (struct pnfs_filelayout_devaddr*)kmalloc(
  577. +        sizeof(struct pnfs_filelayout_devaddr), PVFS2_GFP_FLAGS);
  578. +    /* todo ensure space allocated */
  579. +    fdev->r_netid.len = 3;
  580. +    fdev->r_netid.data = (char*)kmalloc(3, PVFS2_GFP_FLAGS);
  581. +    memcpy(fdev->r_netid.data, netid, 3);
  582. +
  583. +    fdev->r_addr.len = bmitoh32(*(int32_t*)buf);
  584. +    fdev->r_addr.data = (char*)kmalloc(fdev->r_addr.len + 4, PVFS2_GFP_FLAGS);
  585. +    pnfs_decode_string(&buf, &temp);
  586. +    memcpy(fdev->r_addr.data, temp, fdev->r_addr.len);
  587. +
  588. +    /* add port */
  589. +    memcpy(fdev->r_addr.data + fdev->r_addr.len, nfsport, 4);
  590. +    /* Increase by 4 to add the nfs port 2049 */
  591. +    fdev->r_addr.len += 4;
  592. +
  593. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: raddrlen: %d raddr: %s\n",
  594. +            __FUNCTION__, fdev->r_addr.len, fdev->r_addr.data);
  595. +    devlist[i].dev_addr = (void*)fdev;
  596. +    }
  597. +
  598. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: End\n", __FUNCTION__);
  599. +    return devlist;
  600. +}
  601. +
  602. +static int
  603. +nfs_getdevicelist(struct super_block *sb, void *buf)
  604. +{
  605. +    int ret, devlist_len=0;
  606. +    pvfs2_sb_info_t* pvfs2_sb = PVFS2_SB(sb);
  607. +    struct inode* inode = sb->s_root->d_inode;
  608. +    pvfs2_inode_t* pvfs2_inode = PVFS2_I(inode);
  609. +    struct nfsd4_pnfs_getdevlist *gdevl = (struct nfsd4_pnfs_getdevlist*)buf;
  610. +    char* buffer;
  611. +
  612. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: Start\n", __FUNCTION__);
  613. +
  614. +    if ((ret = nfs_getdevlist_upcall(pvfs2_sb, pvfs2_inode)) < 0)
  615. +    return ret;
  616. +
  617. +    buffer = pvfs2_sb->pnfs_devlist;
  618. +    pnfs_decode_int32_t(&buffer, &devlist_len);
  619. +    gdevl->gd_devlist = nfs_create_devices(devlist_len, buffer);
  620. +    gdevl->gd_devlist_len = devlist_len;
  621. +    /* TODO: Not filling in gd_cookie, gd_verf */
  622. +
  623. +    gossip_debug(GOSSIP_PNFS_DEBUG,"%s: End (ret: %d) (len: %d)\n", __FUNCTION__, ret, devlist_len);
  624. +
  625. +    return ret;
  626. +}
  627. +
  628.  /* export ops for each layout type */
  629.  struct export_operations pvfs2layout_export_ops =
  630.  {
  631. @@ -194,6 +465,13 @@ struct export_operations pvfs2layout_exp
  632.      .layout_encode = pvfs2_layout_encode,
  633.  };
  634.  
  635. +struct export_operations nfslayout_export_ops =
  636. +{
  637. +    .layout_type    = pvfs2_layout_type,
  638. +    .layout_get     = nfs_layout_get,
  639. +    .get_devicelist = nfs_getdevicelist,
  640. +};
  641. +
  642.  /*
  643.   * Local variables:
  644.   *  c-indent-level: 4
  645. diff -puN src/kernel/linux-2.6/pvfs2-dev-proto.h~nfslayoutsupport src/kernel/linux-2.6/pvfs2-dev-proto.h
  646. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/pvfs2-dev-proto.h~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  647. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-dev-proto.h    2008-01-05 17:52:37.000000000 -0800
  648. @@ -37,6 +37,7 @@
  649.  #define PVFS2_VFS_OP_REMOVEXATTR       0xFF000013
  650.  #define PVFS2_VFS_OP_PARAM             0xFF000014
  651.  #define PVFS2_VFS_OP_PERF_COUNT        0xFF000015
  652. +#define PVFS2_VFS_OP_GETDEVLIST        0xFF000016
  653.  #define PVFS2_VFS_OP_CANCEL            0xFF00EE00
  654.  #define PVFS2_VFS_OP_FSYNC             0xFF00EE01
  655.  #define PVFS2_VFS_OP_FSKEY             0xFF00EE02
  656. diff -puN src/kernel/linux-2.6/pvfs2-pnfs.h~nfslayoutsupport src/kernel/linux-2.6/pvfs2-pnfs.h
  657. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/pvfs2-pnfs.h~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  658. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/pvfs2-pnfs.h    2008-01-05 17:52:37.000000000 -0800
  659. @@ -25,6 +25,7 @@ struct pvfs2_layout {
  660.  };
  661.  
  662.  extern struct export_operations pvfs2layout_export_ops;
  663. +extern struct export_operations nfslayout_export_ops;
  664.  
  665.  /* Structs need to be defined just to compile kernel module since they
  666.   * are used in include/linux/nfs4_pnfs.h.
  667. diff -puN src/kernel/linux-2.6/super.c~nfslayoutsupport src/kernel/linux-2.6/super.c
  668. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/super.c~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  669. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/super.c    2008-01-05 17:52:37.000000000 -0800
  670. @@ -1104,6 +1104,10 @@ int pvfs2_fill_sb(
  671.          gossip_debug(GOSSIP_PNFS_DEBUG,"Setting pvfs2 layout export ops\n");
  672.          sb->s_export_op = &pvfs2layout_export_ops;
  673.          break;
  674. +        case LAYOUT_NFSV4_FILES:
  675. +        gossip_debug(GOSSIP_PNFS_DEBUG,"Setting nfs layout export ops\n");
  676. +        sb->s_export_op = &nfslayout_export_ops;
  677. +        break;
  678.          default:
  679.          gossip_err("Invalid layouttype, no export ops to set! (%d)\n", layouttype);
  680.      }
  681. diff -puN src/kernel/linux-2.6/upcall.h~nfslayoutsupport src/kernel/linux-2.6/upcall.h
  682. --- pvfs-2.6.3-pnfsfilelayout/src/kernel/linux-2.6/upcall.h~nfslayoutsupport    2008-01-05 17:52:37.000000000 -0800
  683. +++ pvfs-2.6.3-pnfsfilelayout-dhildeb/src/kernel/linux-2.6/upcall.h    2008-01-05 17:52:37.000000000 -0800
  684. @@ -226,6 +226,11 @@ typedef struct
  685.  
  686.  typedef struct
  687.  {
  688. +    PVFS_object_ref refn;
  689. +} pvfs2_getdevlist_request_t;
  690. +
  691. +typedef struct
  692. +{
  693.      int32_t type;
  694.      int32_t __pad1;
  695.      PVFS_credentials credentials;
  696. @@ -261,6 +266,7 @@ typedef struct
  697.          pvfs2_param_request_t param;
  698.          pvfs2_perf_count_request_t perf_count;
  699.          pvfs2_fs_key_request_t fs_key;
  700. +    pvfs2_getdevlist_request_t getdevlist;
  701.      } req;
  702.  } pvfs2_upcall_t;
  703.  
  704. _
  705.