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 / rmdirent.sm < prev    next >
Text File  |  2010-04-30  |  9KB  |  315 lines

  1. /* 
  2.  * (C) 2001 Clemson University and The University of Chicago 
  3.  *
  4.  * See COPYING in top-level directory.
  5.  */
  6.  
  7. #include <string.h>
  8. #include <assert.h>
  9.  
  10. #include "server-config.h"
  11. #include "pvfs2-server.h"
  12. #include "pvfs2-attr.h"
  13. #include "gossip.h"
  14. #include "pvfs2-util.h"
  15. #include "pvfs2-internal.h"
  16. #include "pint-util.h"
  17.  
  18. enum
  19. {
  20.     UPDATE_DIR_ATTR_REQUIRED = 133
  21. };
  22.  
  23. %%
  24.  
  25. machine pvfs2_rmdirent_sm
  26. {
  27.     state prelude
  28.     {
  29.         jump pvfs2_prelude_sm;
  30.         success => verify_parent_metadata_and_read_directory_entry_handle;
  31.         default => final_response;
  32.     }
  33.  
  34.     state verify_parent_metadata_and_read_directory_entry_handle
  35.     {
  36.         run rmdirent_verify_parent_metadata_and_read_directory_entry_handle;
  37.         success => remove_directory_entry;
  38.         default => setup_resp;
  39.     }
  40.  
  41.     state remove_directory_entry
  42.     {
  43.         run rmdirent_remove_directory_entry;
  44.         success => check_for_req_dir_update;
  45.         default => remove_directory_entry_failure;
  46.     }
  47.  
  48.     state remove_directory_entry_failure
  49.     {
  50.         run rmdirent_remove_directory_entry_failure;
  51.         default => setup_resp;
  52.     }
  53.  
  54.     state check_for_req_dir_update
  55.     {
  56.         run rmdirent_check_for_req_dir_update;
  57.         UPDATE_DIR_ATTR_REQUIRED => update_directory_attr;
  58.         default => setup_resp;
  59.     }
  60.  
  61.     state update_directory_attr
  62.     {
  63.         run rmdirent_update_directory_attr;
  64.         default => setup_resp;
  65.     }
  66.  
  67.     state setup_resp
  68.     {
  69.         run rmdirent_setup_resp;
  70.         default => final_response;
  71.     }
  72.  
  73.     state final_response
  74.     {
  75.         jump pvfs2_final_response_sm;
  76.         default => cleanup;
  77.     }
  78.  
  79.     state cleanup
  80.     {
  81.         run rmdirent_cleanup;
  82.         default => terminate;
  83.     }
  84. }
  85.  
  86. %%
  87.  
  88. static int rmdirent_verify_parent_metadata_and_read_directory_entry_handle(
  89.         struct PINT_smcb *smcb, job_status_s *js_p)
  90. {
  91.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  92.     int ret = -PVFS_EINVAL;
  93.     job_id_t i;
  94.  
  95.     PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "rmdirent entry: %s\n",
  96.         s_op->req->u.rmdirent.entry);
  97.  
  98.     /* set up key and value structures to read directory entry */
  99.     s_op->key.buffer = Trove_Common_Keys[DIR_ENT_KEY].key;
  100.     s_op->key.buffer_sz = Trove_Common_Keys[DIR_ENT_KEY].size;
  101.  
  102.     /* we will read the dirdata handle from the entry into the
  103.      * rmdirent scratch space */
  104.     s_op->val.buffer = &s_op->u.rmdirent.dirdata_handle;
  105.     s_op->val.buffer_sz = sizeof(PVFS_handle);
  106.  
  107.     gossip_debug(
  108.         GOSSIP_SERVER_DEBUG,
  109.         "  reading dirdata handle (coll_id = 0x%x, handle = %llu, "
  110.         "key = %s (%d), val_buf = %p (%d))\n",
  111.         s_op->req->u.rmdirent.fs_id,
  112.         llu(s_op->req->u.rmdirent.handle),
  113.         (char *)s_op->key.buffer,
  114.         s_op->key.buffer_sz,
  115.         s_op->val.buffer,
  116.         s_op->val.buffer_sz);
  117.  
  118.     ret = job_trove_keyval_read(
  119.         s_op->req->u.rmdirent.fs_id,
  120.         s_op->req->u.rmdirent.handle,
  121.         &s_op->key,
  122.         &s_op->val,
  123.         0,
  124.         NULL,
  125.         smcb,
  126.         0,
  127.         js_p,
  128.         &i,
  129.         server_job_context, s_op->req->hints);
  130.  
  131.     return ret;
  132. }
  133.  
  134. /*
  135.  * Function: rmdirent_remove_directory_entry
  136.  *
  137.  * Synopsis: posts a trove keyval remove to remove the directory entry
  138.  * from the dirdata object.
  139.  *           
  140.  */
  141. static int rmdirent_remove_directory_entry(
  142.         struct PINT_smcb *smcb, job_status_s *js_p)
  143. {
  144.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  145.     int ret = -PVFS_EINVAL;
  146.     job_id_t j_id;
  147.     TROVE_ds_flags flags;
  148.  
  149.     /* set up key and structure for keyval remove */
  150.     s_op->key.buffer = s_op->req->u.rmdirent.entry;
  151.     s_op->key.buffer_sz = strlen(s_op->req->u.rmdirent.entry) + 1;
  152.  
  153.     s_op->val.buffer = &s_op->u.rmdirent.entry_handle;
  154.     s_op->val.buffer_sz = sizeof(PVFS_handle);
  155.  
  156.     gossip_debug(GOSSIP_SERVER_DEBUG, "  removing entry %s from dirdata "
  157.                  "object (handle = %llu)\n", s_op->req->u.rmdirent.entry,
  158.                  llu(s_op->u.rmdirent.dirdata_handle));
  159.  
  160.     /* set the sync flag */
  161.     flags = TROVE_SYNC;
  162.  
  163.     /* Also keep track of the keyval entries removed on this handle.  Because
  164.      * we're doing a remove, this should decrement the count.
  165.      */
  166.     flags |= TROVE_KEYVAL_HANDLE_COUNT;
  167.  
  168.     ret = job_trove_keyval_remove(
  169.         s_op->req->u.rmdirent.fs_id, s_op->u.rmdirent.dirdata_handle,
  170.         &s_op->key, 
  171.         &s_op->val,
  172.         flags,
  173.         NULL, smcb, 0, js_p, &j_id, server_job_context, s_op->req->hints);
  174.  
  175.     /* 
  176.      * Removing an entry causes an update of directory timestamps
  177.      */
  178.     s_op->u.rmdirent.dir_attr_update_required = 1;
  179.     return ret;
  180. }
  181.  
  182. static PINT_sm_action rmdirent_check_for_req_dir_update(
  183.         struct PINT_smcb *smcb, job_status_s *js_p)
  184. {
  185.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  186.     if ((js_p->error_code == 0) &&
  187.         (s_op->u.rmdirent.dir_attr_update_required))
  188.     {
  189.         js_p->error_code = UPDATE_DIR_ATTR_REQUIRED;
  190.     }
  191.     return SM_ACTION_COMPLETE;
  192. }
  193.  
  194. static PINT_sm_action rmdirent_update_directory_attr(
  195.         struct PINT_smcb *smcb, job_status_s *js_p)
  196. {
  197.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  198.     int ret = -1;
  199.     job_id_t j_id;
  200.     PVFS_object_attr tmp_attr, *tmp_attr_ptr = &tmp_attr;
  201.     PVFS_object_attr *dspace_attr = NULL;
  202.     PVFS_ds_attributes *ds_attr = NULL;
  203.  
  204.     if (js_p->error_code != UPDATE_DIR_ATTR_REQUIRED)
  205.     {
  206.         PVFS_perror_gossip("previous keyval remove failed",
  207.                            js_p->error_code);
  208.         return SM_ACTION_COMPLETE;
  209.     }
  210.  
  211.     memset(&tmp_attr, 0, sizeof(PVFS_object_attr));
  212.     dspace_attr = &s_op->attr;
  213.     dspace_attr->mask |= (PVFS_ATTR_COMMON_ATIME | PVFS_ATTR_COMMON_MTIME | PVFS_ATTR_COMMON_CTIME);
  214.  
  215.     PVFS_object_attr_overwrite_setable(tmp_attr_ptr, dspace_attr);
  216.     ds_attr = &(s_op->ds_attr);
  217.     PVFS_object_attr_to_ds_attr(tmp_attr_ptr, ds_attr);
  218.  
  219.     ret = job_trove_dspace_setattr(
  220.         s_op->req->u.rmdirent.fs_id, s_op->req->u.rmdirent.handle,
  221.         ds_attr, 
  222.         TROVE_SYNC,
  223.         smcb, 0, js_p, &j_id, server_job_context, s_op->req->hints);
  224.  
  225.     return ret;
  226. }
  227.  
  228. /* Function: rmdirent_read_directory_entry_failure
  229.  *
  230.  * The purpose of this state is simply to parse the error value from a
  231.  * failed direntry remove operation (trove_keyval_remove), convert it
  232.  * into an error to return to the user if possible, and print an error
  233.  * if something unexpected has occurred.
  234.  *
  235.  * NOTE: we shouldn't ever actually hit this state, because nothing
  236.  * else should be modifying trove in such a way that the keyval isn't
  237.  * there at this point, because the keyval read has to have succeeded
  238.  * for us to get this far.
  239.  *
  240.  * This state always returns 1, and it allows another function to
  241.  * handle actually returning the error value.
  242.  */
  243. static PINT_sm_action rmdirent_remove_directory_entry_failure(
  244.         struct PINT_smcb *smcb, job_status_s *js_p)
  245. {
  246.     switch (js_p->error_code)
  247.     {
  248.     case -TROVE_ENOENT:
  249.         js_p->error_code = -PVFS_ENOENT;
  250.         break;
  251.     default:
  252.             gossip_lerr("unexpected error %d\n", js_p->error_code);
  253.         break;
  254.     }
  255.  
  256.     return SM_ACTION_COMPLETE;
  257. }
  258.  
  259. static PINT_sm_action rmdirent_setup_resp(
  260.         struct PINT_smcb *smcb, job_status_s *js_p)
  261. {
  262.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  263.     /* Set the handle if it was removed */
  264.     if(js_p->error_code == 0)
  265.     {
  266.     /*
  267.           we return the handle from the directory entry in the
  268.           response
  269.         */
  270.     s_op->resp.u.rmdirent.entry_handle =
  271.             s_op->u.rmdirent.entry_handle;
  272.     gossip_debug(GOSSIP_SERVER_DEBUG,
  273.              "  succeeded; returning handle %llu in response\n",
  274.              llu(s_op->resp.u.rmdirent.entry_handle));
  275.     }
  276.     else
  277.     {
  278.     gossip_debug(GOSSIP_SERVER_DEBUG, "  sending error response\n");
  279.     }
  280.  
  281.     /* NOTE: we _intentionally_ leave the error_code field the way that
  282.      * we found it, so that later states can use it to set the resp.status
  283.      * field.
  284.      */
  285.     return SM_ACTION_COMPLETE;
  286. }
  287.  
  288. static PINT_sm_action rmdirent_cleanup(
  289.         struct PINT_smcb *smcb, job_status_s *js_p)
  290. {
  291.     return(server_state_machine_complete(smcb));
  292. }
  293.  
  294. PINT_GET_OBJECT_REF_DEFINE(rmdirent);
  295.  
  296. struct PINT_server_req_params pvfs2_rmdirent_params =
  297. {
  298.     .string_name = "rmdirent",
  299.     .perm = PINT_SERVER_CHECK_WRITE,
  300.     .access_type = PINT_server_req_modify,
  301.     .sched_policy = PINT_SERVER_REQ_SCHEDULE,
  302.     .get_object_ref = PINT_get_object_ref_rmdirent,
  303.     .state_machine = &pvfs2_rmdirent_sm
  304. };
  305.  
  306. /*
  307.  * Local variables:
  308.  *  mode: c
  309.  *  c-indent-level: 4
  310.  *  c-basic-offset: 4
  311.  * End:
  312.  *
  313.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  314.  */
  315.