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 / client / sysint / remove.sm < prev    next >
Text File  |  2009-10-07  |  9KB  |  323 lines

  1. /* 
  2.  * (C) 2003 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 "client-state-machine.h"
  11. #include "pvfs2-debug.h"
  12. #include "job.h"
  13. #include "gossip.h"
  14. #include "str-utils.h"
  15. #include "pint-cached-config.h"
  16. #include "PINT-reqproto-encode.h"
  17. #include "pint-util.h"
  18. #include "pvfs2-internal.h"
  19.  
  20. extern job_context_id pint_client_sm_context;
  21.  
  22. enum
  23. {
  24.     REMOVE_MUST_REMOVE_DATAFILES = 1,
  25. };
  26.  
  27. #define HANDLE_REMOVE_ERROR(state)                                     \
  28. do {                                                                   \
  29.     char buf[64] = {0};                                                \
  30.     gossip_debug(GOSSIP_CLIENT_DEBUG, "remove state: %s\n", state);    \
  31.     PVFS_strerror_r(js_p->error_code, buf, 64);                        \
  32.     gossip_err("WARNING: PVFS_sys_remove() encountered an error which "\
  33.                "may lead\n  to inconsistent state: %s\n", buf);        \
  34.     gossip_err("WARNING: PVFS2 fsck (if available) may be needed.\n"); \
  35.     sm_p->u.remove.stored_error_code = js_p->error_code;               \
  36.     js_p->error_code = 0;                                              \
  37. } while(0)
  38.  
  39. %%
  40.  
  41. nested machine pvfs2_client_remove_helper_sm
  42. {
  43.     state getattr_init
  44.     {
  45.         run remove_getattr_init;
  46.         default => getattr;
  47.     }
  48.  
  49.     state getattr
  50.     {
  51.         jump pvfs2_client_getattr_sm;
  52.         success => getattr_analyze_results;
  53.         default => remove_helper_cleanup;
  54.     }
  55.  
  56.     state getattr_analyze_results
  57.     {
  58.         run remove_getattr_analyze_results;
  59.         success => object_remove_setup_msgpair;
  60.         REMOVE_MUST_REMOVE_DATAFILES => datafile_remove_setup_msgpair;
  61.         default => remove_helper_cleanup;
  62.     }
  63.  
  64.     state datafile_remove_setup_msgpair
  65.     {
  66.         run remove_datafile_remove_setup_msgpair;
  67.         success => datafile_remove_xfer_msgpair;
  68.         default => datafile_remove_failure;
  69.     }
  70.  
  71.     state datafile_remove_xfer_msgpair
  72.     {
  73.         jump pvfs2_msgpairarray_sm;
  74.         success => object_remove_setup_msgpair;
  75.         default => datafile_remove_failure;
  76.     }
  77.  
  78.     state datafile_remove_failure
  79.     {
  80.         run remove_datafile_remove_failure;
  81.         default => remove_helper_cleanup;
  82.     }
  83.     
  84.     state object_remove_setup_msgpair
  85.     {
  86.         run remove_object_remove_setup_msgpair;
  87.         success => object_remove_xfer_msgpair;
  88.         default => object_remove_failure;
  89.     }
  90.  
  91.     state object_remove_xfer_msgpair
  92.     {
  93.         jump pvfs2_msgpairarray_sm;
  94.         success => remove_helper_cleanup;
  95.         default => object_remove_failure;
  96.     }
  97.  
  98.     state object_remove_failure
  99.     {
  100.         run remove_object_remove_failure;
  101.         default => remove_helper_cleanup;
  102.     }
  103.  
  104.     state remove_helper_cleanup
  105.     {
  106.         run remove_helper_cleanup;
  107.         default => return;
  108.     }
  109. }
  110.  
  111. %%
  112.  
  113. static PINT_sm_action remove_getattr_init(
  114.         struct PINT_smcb *smcb, job_status_s *js_p)
  115. {
  116.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  117.     PINT_SM_GETATTR_STATE_FILL(
  118.         sm_p->getattr,
  119.         sm_p->object_ref,
  120.         PVFS_ATTR_META_ALL|PVFS_ATTR_COMMON_TYPE,
  121.         PVFS_TYPE_NONE,
  122.         0);
  123.     return SM_ACTION_COMPLETE;
  124. }
  125.  
  126. static PINT_sm_action remove_getattr_analyze_results(
  127.         struct PINT_smcb *smcb, job_status_s *js_p)
  128. {
  129.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  130.     PVFS_object_attr *attr = NULL;
  131.     attr = &sm_p->getattr.attr;
  132.     assert(attr);
  133.  
  134.     switch(attr->objtype)
  135.     {
  136.     case PVFS_TYPE_METAFILE:
  137.         assert(attr->mask & PVFS_ATTR_META_DFILES);
  138.         assert(attr->u.meta.dfile_count > 0);
  139.  
  140.         gossip_debug(GOSSIP_CLIENT_DEBUG, "%s: must remove %d datafiles\n",
  141.                          __func__, attr->u.meta.dfile_count);
  142.  
  143.         js_p->error_code = REMOVE_MUST_REMOVE_DATAFILES;
  144.             break;
  145.     case PVFS_TYPE_DIRECTORY:
  146. #if 0
  147. /* NOTE: this check is not safe because it relies on cached attributes on the
  148.  * parent, which may be out of date.  The server will perform this check
  149.  * locally when we attempt to remove the directory itself.
  150.  */
  151.             if(attr->u.dir.dirent_count != 0)
  152.             {
  153.                 js_p->error_code = -PVFS_ENOTEMPTY;
  154.                 break;
  155.             }
  156. #endif
  157.     case PVFS_TYPE_SYMLINK:
  158.             js_p->error_code = 0;
  159.             break;
  160.     case PVFS_TYPE_DATAFILE:
  161.     case PVFS_TYPE_DIRDATA:
  162.     default:
  163.         gossip_err("%s: unhandled object type (%x)\n", __func__,
  164.                        attr->objtype);
  165.     }
  166.     return SM_ACTION_COMPLETE;
  167. }
  168.  
  169. static PINT_sm_action remove_datafile_remove_setup_msgpair(
  170.         struct PINT_smcb *smcb, job_status_s *js_p)
  171. {
  172.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  173.     PVFS_object_attr *attr = NULL;
  174.     int ret = -PVFS_EINVAL;
  175.     PINT_sm_msgpair_state *msg_p = NULL;
  176.  
  177.    /*
  178.     * NOTE: it's easier to clean up from a metafile with no datafiles
  179.     * than the other way around!  so we remove datafiles first.
  180.     */
  181.     js_p->error_code = 0;
  182.  
  183.     gossip_debug(GOSSIP_CLIENT_DEBUG,
  184.                  "remove state: datafile_remove_setup_msgpair\n");
  185.  
  186.     attr = &sm_p->getattr.attr;
  187.     assert(attr);
  188.  
  189.     /* post a send/recv pair for the remove to the
  190.        first server in the list of datafiles */
  191.     PINT_msgpair_init(&sm_p->msgarray_op);
  192.     msg_p = &sm_p->msgarray_op.msgpair;
  193.  
  194.     PINT_SERVREQ_TREE_REMOVE_FILL(
  195.         msg_p->req,
  196.         *sm_p->cred_p,
  197.         sm_p->object_ref.fs_id,
  198.         attr->u.meta.dfile_count,
  199.         attr->u.meta.dfile_array,
  200.         sm_p->hints);
  201.     
  202.     msg_p->fs_id = sm_p->object_ref.fs_id;
  203.     msg_p->handle = attr->u.meta.dfile_array[0];
  204.     msg_p->retry_flag = PVFS_MSGPAIR_RETRY;     /* TODO: Do we want retry? */
  205.     msg_p->comp_fn = NULL;
  206.  
  207.     ret = PINT_cached_config_map_to_server(
  208.         &msg_p->svr_addr, msg_p->handle, msg_p->fs_id);
  209.  
  210.     if (ret)
  211.     {
  212.         gossip_err("Failed to map meta server address\n");
  213.         js_p->error_code = ret;
  214.     }
  215.  
  216.     PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
  217.     return SM_ACTION_COMPLETE;
  218. }
  219.  
  220. static PINT_sm_action remove_object_remove_setup_msgpair(
  221.         struct PINT_smcb *smcb, job_status_s *js_p)
  222. {
  223.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  224.     int ret = -PVFS_EINVAL;
  225.     PINT_sm_msgpair_state *msg_p = NULL;
  226.  
  227.     gossip_debug(GOSSIP_CLIENT_DEBUG,
  228.                  "remove state: object_remove_setup_msgpair\n");
  229.  
  230.     js_p->error_code = 0;
  231.  
  232.     PINT_msgpair_init(&sm_p->msgarray_op);
  233.     msg_p = &sm_p->msgarray_op.msgpair;
  234.  
  235.     PINT_SERVREQ_REMOVE_FILL(
  236.         msg_p->req,
  237.         *sm_p->cred_p,
  238.         sm_p->object_ref.fs_id,
  239.         sm_p->object_ref.handle,
  240.         sm_p->hints);
  241.  
  242.     msg_p->fs_id = sm_p->object_ref.fs_id;
  243.     msg_p->handle = sm_p->object_ref.handle;
  244.     msg_p->retry_flag = PVFS_MSGPAIR_RETRY;
  245.     msg_p->comp_fn = NULL;
  246.  
  247.     ret = PINT_cached_config_map_to_server(
  248.         &msg_p->svr_addr, msg_p->handle, msg_p->fs_id);
  249.  
  250.     if (ret)
  251.     {
  252.         gossip_err("Failed to map meta server address\n");
  253.     js_p->error_code = ret;
  254.     }
  255.  
  256.     PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
  257.     return SM_ACTION_COMPLETE;
  258. }
  259.  
  260. static PINT_sm_action remove_datafile_remove_failure(
  261.         struct PINT_smcb *smcb, job_status_s *js_p)
  262. {
  263.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  264.     gossip_err("Error: failed removing one or more datafiles associated with the meta handle %llu\n", llu(sm_p->object_ref.handle));
  265.     HANDLE_REMOVE_ERROR("datafile_remove_failure");
  266.     return SM_ACTION_COMPLETE;
  267. }
  268.  
  269. static PINT_sm_action remove_object_remove_failure(
  270.         struct PINT_smcb *smcb, job_status_s *js_p)
  271. {
  272.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  273.     gossip_debug(GOSSIP_CLIENT_DEBUG, "remove state: "
  274.                  "object_remove_failure\n");
  275.     /*
  276.       catch and return acceptable errors here to avoid generic
  277.       post-remove-failure cleanup
  278.     */
  279.     if (js_p->error_code == -PVFS_ENOTEMPTY)
  280.     {
  281.         gossip_debug(GOSSIP_CLIENT_DEBUG, " directory not empty -- "
  282.                      "returning error\n");
  283.     }
  284.     else
  285.     {
  286.         gossip_err("Error: failed removing handle %llu\n", llu(sm_p->object_ref.handle));
  287.         HANDLE_REMOVE_ERROR("object_remove_failure");
  288.     }
  289.     return SM_ACTION_COMPLETE;
  290. }
  291.  
  292. static PINT_sm_action remove_helper_cleanup(
  293.         struct PINT_smcb *smcb, job_status_s *js_p)
  294. {
  295.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  296.     gossip_debug(GOSSIP_CLIENT_DEBUG, "remove state: helper cleanup\n");
  297.  
  298.     PINT_SM_GETATTR_STATE_CLEAR(sm_p->getattr);
  299.  
  300.     PINT_acache_invalidate(sm_p->object_ref);
  301.  
  302.     PINT_msgpairarray_destroy(&sm_p->msgarray_op);
  303.  
  304.     if (js_p->error_code)
  305.     {
  306.         char buf[64] = {0};
  307.         PVFS_strerror_r(js_p->error_code, buf, 64);
  308.         gossip_debug(GOSSIP_CLIENT_DEBUG,
  309.                      "remove_helper_cleanup error: %s\n", buf);
  310.     }
  311.     return SM_ACTION_COMPLETE;
  312. }
  313.  
  314. /*
  315.  * Local variables:
  316.  *  mode: c
  317.  *  c-indent-level: 4
  318.  *  c-basic-offset: 4
  319.  * End:
  320.  *
  321.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  322.  */
  323.