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 / remove.sm < prev    next >
Text File  |  2009-10-07  |  10KB  |  402 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-storage.h"
  12. #include "pvfs2-server.h"
  13. #include "pvfs2-attr.h"
  14. #include "gossip.h"
  15. #include "pvfs2-internal.h"
  16.  
  17. /* Implementation notes
  18.  *
  19.  * This is a complicated machine.  It is capable of removing the three
  20.  * externally visible PVFS2 object types: datafiles, metafiles, and
  21.  * directories.
  22.  *
  23.  * For a datafile, the path through the state machine looks like:
  24.  * 1) prelude
  25.  * 2) check_object_type
  26.  * 3) verify_object_metadata
  27.  * 4) remove_dspace
  28.  * 5) final_response
  29.  * 6) cleanup
  30.  *
  31.  * For metafiles and symlinks, the path is:
  32.  * 1) prelude
  33.  * 2) check_object_type
  34.  * 3) verify_object_metadata
  35.  * 4) remove_dspace
  36.  * 5) final_response
  37.  * 6) cleanup
  38.  *
  39.  * For a directory that has (or at one time had) entries, the path is:
  40.  * 1) prelude
  41.  * 2) check_object_type
  42.  * 3) verify_object_metadata
  43.  * 4) try_to_read_dirdata_handle
  44.  * 5) remove_dirdata_keyvals
  45.  * 6) remove_dirdata_dspace
  46.  * 7) remove_dspace
  47.  * 8) final_response
  48.  * 9) cleanup
  49.  *
  50.  * A directory that never had entries will skip step (5), as there
  51.  * would be no dirdata dspace.
  52.  */
  53.  
  54. #define PVFS_REMOVE_ITERATE_MAXCOUNT 100
  55.  
  56. enum
  57. {
  58.     STATE_TYPE_DIRECTORY = 1,
  59.     STATE_TYPE_DATAFILE = 2,
  60. };
  61.  
  62. %%
  63.  
  64. nested machine pvfs2_remove_work_sm
  65. {
  66.  
  67.     state check_object_type
  68.     {
  69.         run remove_check_object_type;
  70.         success => verify_object_metadata;
  71.         STATE_TYPE_DATAFILE => remove_dspace;
  72.         default => return;
  73.     }
  74.  
  75.     state verify_object_metadata
  76.     {
  77.         run remove_verify_object_metadata;
  78.         STATE_TYPE_DIRECTORY => read_dirdata_handle;
  79.         success => remove_dspace;
  80.         default => return;
  81.     }
  82.  
  83.     state remove_dspace
  84.     {
  85.         run remove_remove_dspace;
  86.         default => return;
  87.     }
  88.  
  89.     state read_dirdata_handle
  90.     {
  91.         run remove_read_dirdata_handle;
  92.         success => getattr_of_dirdata_handle;
  93.         default => remove_dspace;
  94.     }
  95.  
  96.     state getattr_of_dirdata_handle
  97.     {
  98.         run remove_get_dirent_count;
  99.         default => check_dirdata_entries;
  100.     }
  101.  
  102.     state check_dirdata_entries
  103.     {
  104.         run remove_check_dirdata_entries;
  105.         success => remove_dirdata_dspace;
  106.         default => return;
  107.     }
  108.  
  109.     state remove_dirdata_dspace
  110.     {
  111.         run remove_remove_dirdata_dspace;
  112.         success => remove_dspace;
  113.         default => return;
  114.     }
  115.  
  116. }
  117.  
  118. nested machine pvfs2_remove_with_prelude_sm
  119. {
  120.     state prelude
  121.     {
  122.         jump pvfs2_prelude_sm;
  123.         success => do_work;
  124.         default => return;
  125.     }
  126.  
  127.     state do_work
  128.     {
  129.         jump pvfs2_remove_work_sm;
  130.         default => return;
  131.     }
  132. }
  133.  
  134. machine pvfs2_remove_sm
  135. {
  136.     state work
  137.     {
  138.         jump pvfs2_remove_with_prelude_sm;
  139.         default => final_response;
  140.     }
  141.  
  142.     state final_response
  143.     {
  144.         jump pvfs2_final_response_sm;
  145.         default => cleanup;
  146.     }
  147.  
  148.     state cleanup
  149.     {
  150.         run remove_cleanup;
  151.         default => terminate;
  152.     }
  153. }
  154.  
  155. %%
  156.  
  157. /*
  158.  * Function: remove_check_object_type
  159.  *
  160.  * decides whether to follow the path for datafile removal or
  161.  * non-datafile removal, based on whether we were able to successfully
  162.  * retrive object attributes earlier
  163.  *
  164.  */
  165. static PINT_sm_action remove_check_object_type(
  166.         struct PINT_smcb *smcb, job_status_s *js_p)
  167. {
  168.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  169.     if(s_op->attr.objtype == PVFS_TYPE_DATAFILE)
  170.     {
  171.     /* it must be a datafile, transition to try reading datafile 
  172.      * attribs with dspace_getattr()
  173.      */
  174.     js_p->error_code = STATE_TYPE_DATAFILE;
  175.     return SM_ACTION_COMPLETE;
  176.     }
  177.  
  178.     js_p->error_code = 0;
  179.     return SM_ACTION_COMPLETE;
  180. }
  181.  
  182. /*
  183.  * Function: remove_verify_object_metadata
  184.  *
  185.  * Verifies that the user has permission to access the file (not yet
  186.  * implemented).  Also directs removal of dirdata dspace in the case
  187.  * of a directory.
  188.  *
  189.  * This state has changed some over time; it might need a new name.
  190.  *
  191.  * Note: errors from the previous state are redirected elsewhere, so
  192.  * we know that we have metadata if we make it here.
  193.  */
  194. static PINT_sm_action remove_verify_object_metadata(
  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.     PVFS_object_attr *a_p;
  199.  
  200.     a_p = &s_op->attr;
  201.  
  202.     js_p->error_code = 0;
  203.     
  204.     gossip_debug(GOSSIP_SERVER_DEBUG,
  205.          "  attrs read from keyval = (owner = %d, "
  206.                  "group = %d, perms = %o, type = %d)\n",
  207.          a_p->owner,
  208.          a_p->group,
  209.          a_p->perms,
  210.          a_p->objtype);
  211.  
  212.     if (a_p->objtype == PVFS_TYPE_DIRECTORY)
  213.     {
  214.     js_p->error_code = STATE_TYPE_DIRECTORY;
  215.  
  216.     gossip_debug(
  217.             GOSSIP_SERVER_DEBUG, "  type is directory; removing "
  218.             "dirdata object before removing directory itself.\n");
  219.     }
  220.  
  221.     return SM_ACTION_COMPLETE;
  222. }
  223.  
  224. static PINT_sm_action remove_read_dirdata_handle(
  225.         struct PINT_smcb *smcb, job_status_s *js_p)
  226. {
  227.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  228.     int ret;
  229.     job_id_t j_id;
  230.  
  231.     /* set up key and value structures for reading the dirdata handle */
  232.     s_op->key.buffer = Trove_Common_Keys[DIR_ENT_KEY].key;
  233.     s_op->key.buffer_sz = Trove_Common_Keys[DIR_ENT_KEY].size;
  234.  
  235.     s_op->val.buffer = &s_op->u.remove.dirdata_handle;
  236.     s_op->val.buffer_sz = sizeof(PVFS_handle);
  237.  
  238.     gossip_debug(GOSSIP_SERVER_DEBUG,
  239.          "  trying to read dirdata handle (coll_id = %d, "
  240.                  "handle = %llu, key = %s (%d), val_buf = %p (%d))\n",
  241.          s_op->req->u.remove.fs_id, llu(s_op->req->u.remove.handle),
  242.          (char *)s_op->key.buffer, s_op->key.buffer_sz,
  243.          s_op->val.buffer, s_op->val.buffer_sz);
  244.  
  245.     ret = job_trove_keyval_read(
  246.         s_op->req->u.remove.fs_id, s_op->req->u.remove.handle,
  247.         &s_op->key, &s_op->val,
  248.         0,
  249.         NULL, smcb, 0, js_p,
  250.         &j_id, server_job_context, s_op->req->hints);
  251.  
  252.     return ret;
  253. }
  254.  
  255. static PINT_sm_action remove_get_dirent_count(
  256.         struct PINT_smcb *smcb, job_status_s *js_p)
  257. {
  258.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  259.     int ret;
  260.     job_id_t tmp_id;
  261.  
  262.     if (js_p->error_code)
  263.     {
  264.         return SM_ACTION_COMPLETE;
  265.     }
  266.     js_p->error_code = 0;
  267.  
  268.  
  269.     ret = job_trove_keyval_iterate_keys(
  270.         s_op->req->u.remove.fs_id,
  271.         s_op->u.remove.dirdata_handle,
  272.         PVFS_ITERATE_START,
  273.         &s_op->u.remove.key,
  274.         1,
  275.         0,
  276.         NULL,
  277.         smcb,
  278.         0,
  279.         js_p,
  280.         &tmp_id,
  281.         server_job_context, s_op->req->hints);
  282.  
  283.     return ret;
  284. }
  285.  
  286. static PINT_sm_action remove_check_dirdata_entries(
  287.         struct PINT_smcb *smcb, job_status_s *js_p)
  288. {
  289.     struct PINT_server_op *s_op __attribute__((unused)) =
  290.         PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  291.     if (js_p->error_code == 0)
  292.     {
  293.         if(js_p->count > 0)
  294.         {
  295.             gossip_debug(GOSSIP_SERVER_DEBUG, 
  296.                          " detected non-empty "
  297.                          "directory (fsid: %u, handle: %llu) "
  298.                          "-- returning error\n",
  299.                          s_op->req->u.remove.fs_id,
  300.                          llu(s_op->req->u.remove.handle));
  301.             js_p->error_code = -PVFS_ENOTEMPTY;
  302.         }
  303.     }
  304.     else if(js_p->error_code == -TROVE_ENOENT)
  305.     {
  306.         /* no entries because count is 0 */
  307.         js_p->error_code = 0;
  308.     }
  309.  
  310.     /* setup position for next state (remove[_dirdata]_keyvals) */
  311.     return SM_ACTION_COMPLETE;
  312. }
  313.  
  314. /*
  315.  * Function: remove_remove_dirdata_dspace
  316.  *
  317.  * Remove the dirdata dspace using the handle that we ready in the
  318.  * read_dirdata_handle state.
  319.  */
  320. static PINT_sm_action remove_remove_dirdata_dspace(
  321.         struct PINT_smcb *smcb, job_status_s *js_p)
  322. {
  323.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  324.     int ret;
  325.     job_id_t j_id;
  326.     gossip_debug(GOSSIP_SERVER_DEBUG,
  327.          "  removing dirdata dspace %llu\n",
  328.          llu(s_op->u.remove.dirdata_handle));
  329.  
  330.     ret = job_trove_dspace_remove(
  331.         s_op->req->u.remove.fs_id,
  332.         s_op->u.remove.dirdata_handle,
  333.         0,  /* don't sync here, we do a dspace remove on the dir handle next */
  334.         smcb,
  335.         0,
  336.         js_p,
  337.         &j_id,
  338.         server_job_context, s_op->req->hints);
  339.  
  340.     return ret;
  341. }
  342.  
  343. /*
  344.  * Function: remove_remove_dspace
  345.  *
  346.  * Remove the dspace using the handle from the incoming request
  347.  * (which was verified in previous states).
  348.  */
  349. static PINT_sm_action remove_remove_dspace(
  350.         struct PINT_smcb *smcb, job_status_s *js_p)
  351. {
  352.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  353.     int ret = -PVFS_EINVAL;
  354.     job_id_t j_id;
  355.     gossip_debug(GOSSIP_SERVER_DEBUG, "(%p) remove: removing dspace "
  356.                  "object %llu,%d\n", s_op, llu(s_op->req->u.remove.handle),
  357.                  s_op->req->u.remove.fs_id);
  358.  
  359.     ret = job_trove_dspace_remove(
  360.         s_op->req->u.remove.fs_id, s_op->req->u.remove.handle,
  361.         TROVE_SYNC,
  362.         smcb, 0, js_p,
  363.         &j_id, server_job_context, s_op->req->hints);
  364.  
  365.     return ret;
  366. }
  367.  
  368. /*
  369.  * Function: remove_cleanup
  370.  *
  371.  * Free all memory associated with this request and return 0, indicating
  372.  * we're done processing.
  373.  */
  374. static PINT_sm_action remove_cleanup(
  375.         struct PINT_smcb *smcb, job_status_s *js_p)
  376. {
  377.     return(server_state_machine_complete(smcb));
  378. }
  379.  
  380. PINT_GET_OBJECT_REF_DEFINE(remove);
  381.  
  382. struct PINT_server_req_params pvfs2_remove_params =
  383. {
  384.     .string_name = "remove",
  385.     .get_object_ref = PINT_get_object_ref_remove,
  386.     .perm = PINT_SERVER_CHECK_NONE,
  387.     .access_type = PINT_server_req_modify,
  388.     .sched_policy = PINT_SERVER_REQ_SCHEDULE,
  389.     .state_machine = &pvfs2_remove_sm
  390. };
  391.  
  392.  
  393. /*
  394.  * Local variables:
  395.  *  mode: c
  396.  *  c-indent-level: 4
  397.  *  c-basic-offset: 4
  398.  * End:
  399.  *
  400.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  401.  */
  402.