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 / src / server / readdir.sm < prev    next >
Text File  |  2008-11-19  |  7KB  |  279 lines

  1. /* 
  2.  * (C) 2001 Clemson University and The University of Chicago 
  3.  *
  4.  * See COPYING in top-level directory.
  5.  */
  6.  
  7. #include <stdlib.h>
  8. #ifdef HAVE_MALLOC_H
  9. #include <malloc.h>
  10. #endif
  11. #include <string.h>
  12. #include <assert.h>
  13.  
  14. #include "server-config.h"
  15. #include "pvfs2-server.h"
  16. #include "pvfs2-attr.h"
  17. #include "pvfs2-internal.h"
  18. #include "trove.h"
  19.  
  20. enum
  21. {
  22.     STATE_ENOTDIR = 7
  23. };
  24.  
  25. %%
  26.  
  27. machine pvfs2_readdir_sm
  28. {
  29.     state prelude
  30.     {
  31.     jump pvfs2_prelude_sm;
  32.     success => verify_directory_metadata;
  33.     default => final_response;
  34.     }
  35.  
  36.     state verify_directory_metadata
  37.     {
  38.     run readdir_verify_directory_metadata;
  39.     success => read_dirdata_handle;
  40.     default => setup_resp;
  41.     }
  42.  
  43.     state read_dirdata_handle
  44.     {
  45.     run readdir_read_dirdata_handle;
  46.     success => iterate_on_entries;
  47.     default => setup_resp;
  48.     }
  49.  
  50.     state iterate_on_entries
  51.     {
  52.     run readdir_iterate_on_entries;
  53.     default => setup_resp;
  54.     }
  55.  
  56.     state setup_resp
  57.     {
  58.     run readdir_setup_resp;
  59.     default => final_response;
  60.     }
  61.  
  62.     state final_response 
  63.     {
  64.     jump pvfs2_final_response_sm;
  65.     default => cleanup;
  66.     }
  67.  
  68.     state cleanup
  69.     {
  70.     run readdir_cleanup;
  71.     default => terminate;
  72.     }
  73. }
  74.  
  75. %%
  76.  
  77. static PINT_sm_action readdir_verify_directory_metadata(
  78.         struct PINT_smcb *smcb, job_status_s *js_p)
  79. {
  80.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  81.     PVFS_object_attr *attr = &s_op->attr;
  82.  
  83.     js_p->error_code = 0;
  84.  
  85.     gossip_debug(GOSSIP_READDIR_DEBUG, " - attrs: owner=%d, group=%d, "
  86.                  "perms=%d\n\ttype=%d, mtime=%llu\n", attr->owner,
  87.                  attr->group, attr->perms, attr->objtype,
  88.                  llu(attr->mtime));
  89.  
  90.     if (attr->objtype != PVFS_TYPE_DIRECTORY)
  91.     {
  92.     gossip_debug(GOSSIP_READDIR_DEBUG, "  object is not a directory; "
  93.                      "halting readdir and sending response\n");
  94.  
  95.     js_p->error_code = STATE_ENOTDIR;
  96.     }
  97.  
  98.     s_op->u.readdir.directory_version = (uint64_t)attr->mtime;
  99.     return SM_ACTION_COMPLETE;
  100. }
  101.  
  102. static PINT_sm_action readdir_read_dirdata_handle(
  103.         struct PINT_smcb *smcb, job_status_s *js_p)
  104. {
  105.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  106.     int ret = -PVFS_EINVAL;
  107.     job_id_t i;
  108.  
  109.     s_op->key.buffer = Trove_Common_Keys[DIR_ENT_KEY].key;
  110.     s_op->key.buffer_sz = Trove_Common_Keys[DIR_ENT_KEY].size;
  111.  
  112.     s_op->val.buffer = &s_op->u.readdir.dirent_handle;
  113.     s_op->val.buffer_sz = sizeof(PVFS_handle);
  114.  
  115.     gossip_debug(
  116.         GOSSIP_READDIR_DEBUG, " - reading metadata: [%llu,%d], "
  117.         "key=%s\n\t(sz=%d) val_buf=%p (sz=%d)\n",
  118.         llu(s_op->req->u.readdir.handle), s_op->req->u.readdir.fs_id,
  119.         (char *)s_op->key.buffer, s_op->key.buffer_sz,
  120.         s_op->val.buffer, s_op->val.buffer_sz);
  121.  
  122.     ret = job_trove_keyval_read(
  123.         s_op->req->u.readdir.fs_id, s_op->req->u.readdir.handle,
  124.         &s_op->key, &s_op->val, 
  125.         0, 
  126.         NULL, smcb, 0, js_p, &i,
  127.         server_job_context, s_op->req->hints);
  128.  
  129.     return ret;
  130. }
  131.  
  132. static PINT_sm_action readdir_iterate_on_entries(
  133.         struct PINT_smcb *smcb, job_status_s *js_p)
  134. {
  135.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  136.     int ret = -PVFS_EINVAL;
  137.     int j = 0, memory_size = 0, kv_array_size = 0;
  138.     char *memory_buffer = NULL;
  139.     job_id_t j_id;
  140.  
  141.     /*
  142.       if a client issues a readdir but asks for no entries, we can
  143.       skip doing anything here
  144.     */
  145.     if (s_op->req->u.readdir.dirent_count == 0)
  146.     {
  147.     js_p->error_code = 0;
  148.         return SM_ACTION_COMPLETE;
  149.     }
  150.  
  151.     if (s_op->req->u.readdir.dirent_count > PVFS_REQ_LIMIT_DIRENT_COUNT)
  152.     {
  153.         js_p->error_code = -PVFS_EINVAL;
  154.         return SM_ACTION_COMPLETE;
  155.     }
  156.  
  157.     /*
  158.       calculate total memory needed:
  159.       - 2 * dirent_count keyval structures to pass to iterate function
  160.       - dirent_count dirent structures to hold the results
  161.     */
  162.     kv_array_size = (s_op->req->u.readdir.dirent_count *
  163.                      sizeof(PVFS_ds_keyval));
  164.  
  165.     memory_size = (2 * kv_array_size +
  166.                    s_op->req->u.readdir.dirent_count *
  167.                    sizeof(PVFS_dirent));
  168.  
  169.     memory_buffer = malloc(memory_size);
  170.     if (!memory_buffer)
  171.     {
  172.         js_p->error_code = -PVFS_ENOMEM;
  173.         return SM_ACTION_COMPLETE;
  174.     }
  175.  
  176.     /* set up all the pointers into the one big buffer */
  177.     s_op->key_a = (PVFS_ds_keyval *)memory_buffer;
  178.     memory_buffer += kv_array_size;
  179.  
  180.     s_op->val_a = (PVFS_ds_keyval *)memory_buffer;
  181.     memory_buffer += kv_array_size;
  182.  
  183.     s_op->resp.u.readdir.dirent_array = (PVFS_dirent *)memory_buffer;
  184.  
  185.     for (j = 0; j < s_op->req->u.readdir.dirent_count; j++)
  186.     {
  187.     s_op->key_a[j].buffer =
  188.             s_op->resp.u.readdir.dirent_array[j].d_name;
  189.     s_op->key_a[j].buffer_sz = PVFS_NAME_MAX;
  190.     s_op->val_a[j].buffer =
  191.             &(s_op->resp.u.readdir.dirent_array[j].handle);
  192.     s_op->val_a[j].buffer_sz = sizeof(PVFS_handle);
  193.     }
  194.  
  195.     gossip_debug(
  196.         GOSSIP_READDIR_DEBUG, " - iterating keyvals: [%llu,%d], "
  197.         "\n\ttoken=%llu, count=%d\n",
  198.         llu(s_op->u.readdir.dirent_handle), s_op->req->u.readdir.fs_id,
  199.         llu(s_op->req->u.readdir.token),
  200.         s_op->req->u.readdir.dirent_count);
  201.  
  202.     ret = job_trove_keyval_iterate(
  203.         s_op->req->u.readdir.fs_id, s_op->u.readdir.dirent_handle,
  204.         s_op->req->u.readdir.token, s_op->key_a, s_op->val_a,
  205.         s_op->req->u.readdir.dirent_count, 
  206.         0, 
  207.         NULL, smcb, 0, js_p,
  208.         &j_id, server_job_context, s_op->req->hints);
  209.  
  210.     return ret;
  211. }
  212.  
  213. static PINT_sm_action readdir_setup_resp(
  214.         struct PINT_smcb *smcb, job_status_s *js_p)
  215. {
  216.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  217.     if (js_p->error_code == STATE_ENOTDIR)
  218.     {
  219.     gossip_debug(GOSSIP_READDIR_DEBUG,
  220.              "  handle didn't refer to a directory\n");
  221.  
  222.     js_p->error_code = -PVFS_EINVAL;
  223.     return SM_ACTION_COMPLETE;
  224.     }
  225.     else if(js_p->error_code != 0)
  226.     {
  227.         PVFS_perror_gossip("readdir_setup_resp failed: ", js_p->error_code);
  228.         return SM_ACTION_COMPLETE;
  229.     }
  230.  
  231.     s_op->resp.u.readdir.directory_version =
  232.         s_op->u.readdir.directory_version;
  233.     s_op->resp.u.readdir.dirent_count = js_p->count;
  234.  
  235.     /*
  236.      * Although, this is not as important to get ls
  237.      * to work through the VFS readdir, it is important
  238.      * to fill this and send it back because the system
  239.      * interface users could break because of this...
  240.      */
  241.     s_op->resp.u.readdir.token = js_p->position;
  242.     js_p->error_code = 0;
  243.     return SM_ACTION_COMPLETE;
  244. }
  245.  
  246. static PINT_sm_action readdir_cleanup(
  247.         struct PINT_smcb *smcb, job_status_s *js_p)
  248. {
  249.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  250.     if (s_op->key_a)
  251.     {
  252.         free(s_op->key_a);
  253.         s_op->key_a = NULL;
  254.         s_op->val_a = NULL;
  255.         s_op->resp.u.readdir.dirent_array = NULL;
  256.     }
  257.     return(server_state_machine_complete(smcb));
  258. }
  259.  
  260. PINT_GET_OBJECT_REF_DEFINE(readdir);
  261.  
  262. struct PINT_server_req_params pvfs2_readdir_params =
  263. {
  264.     .string_name = "readdir",
  265.     .perm = PINT_SERVER_CHECK_READ,
  266.     .get_object_ref = PINT_get_object_ref_readdir,
  267.     .state_machine = &pvfs2_readdir_sm
  268. };
  269.  
  270. /*
  271.  * Local variables:
  272.  *  mode: c
  273.  *  c-indent-level: 4
  274.  *  c-basic-offset: 4
  275.  * End:
  276.  *
  277.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  278.  */
  279.