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 / sys-mkdir.sm < prev    next >
Text File  |  2008-11-26  |  22KB  |  758 lines

  1. /* 
  2.  * (C) 2003 Clemson University and The University of Chicago 
  3.  *
  4.  * Changes by Acxiom Corporation to add setgid support
  5.  * Copyright ⌐ Acxiom Corporation, 2005.
  6.  *
  7.  * See COPYING in top-level directory.
  8.  */
  9.  
  10. /** \file
  11.  *  \ingroup sysint
  12.  *
  13.  *  PVFS2 system interface routines for creating a new directory.
  14.  */
  15.  
  16. #include <string.h>
  17. #include <assert.h>
  18.  
  19. #include "client-state-machine.h"
  20. #include "pvfs2-debug.h"
  21. #include "job.h"
  22. #include "gossip.h"
  23. #include "str-utils.h"
  24. #include "pint-cached-config.h"
  25. #include "PINT-reqproto-encode.h"
  26. #include "pint-util.h"
  27. #include "ncache.h"
  28. #include "pvfs2-internal.h"
  29.  
  30. extern job_context_id pint_client_sm_context;
  31.  
  32. enum
  33. {
  34.     MKDIR_RETRY = 180,
  35.     MKDIR_SKIP_EATTR = 181
  36. };
  37.  
  38. static int mkdir_msg_comp_fn(
  39.     void *v_p, struct PVFS_server_resp *resp_p, int index);
  40. static int mkdir_crdirent_comp_fn(
  41.     void *v_p, struct PVFS_server_resp *resp_p, int index);
  42. static int mkdir_delete_handle_comp_fn(
  43.     void *v_p, struct PVFS_server_resp *resp_p, int index);
  44.  
  45. %%
  46.  
  47. machine pvfs2_client_mkdir_sm
  48. {
  49.     state init
  50.     {
  51.         run mkdir_init;
  52.         default => parent_getattr;
  53.     }
  54.  
  55.     state parent_getattr
  56.     {
  57.         jump pvfs2_client_getattr_sm;
  58.         success => parent_getattr_inspect;
  59.         default => cleanup;
  60.     }
  61.  
  62.     state parent_getattr_inspect
  63.     {
  64.         run mkdir_parent_getattr_inspect;
  65.         success => mkdir_msg_setup_msgpair;
  66.         default => cleanup;
  67.     }
  68.  
  69.     state mkdir_msg_setup_msgpair
  70.     {
  71.         run mkdir_msg_setup_msgpair;
  72.         success => mkdir_msg_xfer_msgpair;
  73.         default => mkdir_msg_failure;
  74.     }
  75.  
  76.     state mkdir_msg_xfer_msgpair
  77.     {
  78.         jump pvfs2_msgpairarray_sm;
  79.         success => mkdir_seteattr_setup_msgpair;
  80.         default => mkdir_msg_failure;
  81.     }
  82.  
  83.     state mkdir_msg_failure
  84.     {
  85.         run mkdir_msg_failure;
  86.         default => cleanup;
  87.     }
  88.  
  89.     state mkdir_seteattr_setup_msgpair
  90.     {
  91.         run mkdir_seteattr_setup_msgpair;
  92.         MKDIR_SKIP_EATTR => mkdir_crdirent_setup_msgpair;
  93.         success => mkdir_seteattr_xfer_msgpair;
  94.         default => mkdir_seteattr_failure;
  95.     }
  96.  
  97.     state mkdir_seteattr_xfer_msgpair
  98.     {
  99.         jump pvfs2_msgpairarray_sm;
  100.         success => mkdir_crdirent_setup_msgpair;
  101.         default => mkdir_seteattr_failure;
  102.     }
  103.  
  104.     state mkdir_seteattr_failure
  105.     {
  106.         run mkdir_seteattr_failure;
  107.         default => delete_handle_setup_msgpair;
  108.     }
  109.  
  110.     state mkdir_crdirent_setup_msgpair
  111.     {
  112.         run mkdir_crdirent_setup_msgpair;
  113.         success => mkdir_crdirent_xfer_msgpair;
  114.         default => mkdir_crdirent_failure;
  115.     }
  116.  
  117.     state mkdir_crdirent_xfer_msgpair
  118.     {
  119.         jump pvfs2_msgpairarray_sm;
  120.         success => cleanup;
  121.         default => mkdir_crdirent_failure;
  122.     }
  123.  
  124.     state mkdir_crdirent_failure
  125.     {
  126.         run mkdir_crdirent_failure;
  127.         default => delete_handle_setup_msgpair;
  128.     }
  129.  
  130.     state delete_handle_setup_msgpair
  131.     {
  132.         run mkdir_delete_handle_setup_msgpair;
  133.         success => delete_handle_xfer_msgpair;
  134.         default => cleanup;
  135.     }
  136.  
  137.     state delete_handle_xfer_msgpair
  138.     {
  139.         jump pvfs2_msgpairarray_sm;
  140.         default => cleanup;
  141.     }
  142.  
  143.     state cleanup
  144.     {
  145.         run mkdir_cleanup;
  146.         MKDIR_RETRY => init;
  147.         default => terminate;
  148.     }
  149. }
  150.  
  151. %%
  152.  
  153. /** Initiate creation of a new directory.
  154.  */
  155. PVFS_error PVFS_isys_mkdir(
  156.     char *object_name,
  157.     PVFS_object_ref parent_ref,
  158.     PVFS_sys_attr attr,
  159.     const PVFS_credentials *credentials,
  160.     PVFS_sysresp_mkdir *resp,
  161.     PVFS_sys_op_id *op_id,
  162.     PVFS_hint hints,
  163.     void *user_ptr)
  164. {
  165.     PVFS_error ret = -PVFS_EINVAL;
  166.     PINT_smcb *smcb = NULL;
  167.     PINT_client_sm *sm_p = NULL;
  168.  
  169.     gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_isys_mkdir entered\n");
  170.  
  171.     if ((parent_ref.handle == PVFS_HANDLE_NULL) ||
  172.         (parent_ref.fs_id == PVFS_FS_ID_NULL) ||
  173.         (object_name == NULL) || (resp == NULL))
  174.     {
  175.         gossip_err("invalid (NULL) required argument\n");
  176.         return ret;
  177.     }
  178.  
  179.     if ((attr.mask & PVFS_ATTR_SYS_ALL_SETABLE) !=
  180.         PVFS_ATTR_SYS_ALL_SETABLE)
  181.     {
  182.         gossip_lerr("PVFS_isys_mkdir() failure: invalid attributes "
  183.                     "specified\n");
  184.         return ret;
  185.     }
  186.  
  187.     if ((strlen(object_name) + 1) > PVFS_REQ_LIMIT_SEGMENT_BYTES)
  188.     {
  189.         return -PVFS_ENAMETOOLONG;
  190.     }
  191.  
  192.     PINT_smcb_alloc(&smcb, PVFS_SYS_MKDIR,
  193.              sizeof(struct PINT_client_sm),
  194.              client_op_state_get_machine,
  195.              client_state_machine_terminate,
  196.              pint_client_sm_context);
  197.     if (smcb == NULL)
  198.     {
  199.         return -PVFS_ENOMEM;
  200.     }
  201.     sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  202.  
  203.     PINT_init_msgarray_params(sm_p, parent_ref.fs_id);
  204.     PINT_init_sysint_credentials(sm_p->cred_p, credentials);
  205.     sm_p->u.mkdir.object_name = object_name;
  206.     PVFS_util_copy_sys_attr(&sm_p->u.mkdir.sys_attr, &attr);
  207.     sm_p->u.mkdir.mkdir_resp = resp;
  208.     sm_p->u.mkdir.stored_error_code = 0;
  209.     sm_p->object_ref = parent_ref;
  210.     PVFS_hint_copy(hints, &sm_p->hints);
  211.     PVFS_hint_add(&sm_p->hints, PVFS_HINT_HANDLE_NAME, sizeof(PVFS_handle), &parent_ref.handle);
  212.  
  213.     gossip_debug(GOSSIP_CLIENT_DEBUG, "Creating directory named %s "
  214.                  "under parent handle %llu on fs %d\n", object_name,
  215.                  llu(parent_ref.handle), parent_ref.fs_id);
  216.  
  217.     return PINT_client_state_machine_post(
  218.         smcb,  op_id, user_ptr);
  219. }
  220.  
  221. /** Create a new directory.
  222.  */
  223. PVFS_error PVFS_sys_mkdir(
  224.     char *object_name,
  225.     PVFS_object_ref parent_ref,
  226.     PVFS_sys_attr attr,
  227.     const PVFS_credentials *credentials,
  228.     PVFS_sysresp_mkdir *resp,
  229.     PVFS_hint hints)
  230. {
  231.     PVFS_error ret = -PVFS_EINVAL, error = 0;
  232.     PVFS_sys_op_id op_id;
  233.  
  234.     gossip_debug(GOSSIP_CLIENT_DEBUG, "PVFS_sys_mkdir entered\n");
  235.  
  236.     ret = PVFS_isys_mkdir(object_name, parent_ref, attr,
  237.                           credentials, resp, &op_id, hints, NULL);
  238.     if (ret)
  239.     {
  240.         PVFS_perror_gossip("PVFS_isys_mkdir call", ret);
  241.         error = ret;
  242.     }
  243.     else
  244.     {
  245.         ret = PVFS_sys_wait(op_id, "mkdir", &error);
  246.         if (ret)
  247.         {
  248.             PVFS_perror_gossip("PVFS_sys_wait call", ret);
  249.             error = ret;
  250.         }
  251.     }
  252.  
  253.     PINT_sys_release(op_id);
  254.     return error;
  255. }
  256.  
  257. /****************************************************************/
  258.  
  259. static PINT_sm_action mkdir_init(
  260.         struct PINT_smcb *smcb, job_status_s *js_p)
  261. {
  262.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  263.     job_id_t tmp_id;
  264.  
  265.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: init\n");
  266.  
  267.     assert((js_p->error_code == 0) ||
  268.            (js_p->error_code == MKDIR_RETRY));
  269.  
  270.     PINT_SM_GETATTR_STATE_FILL(
  271.         sm_p->getattr,
  272.         sm_p->object_ref,
  273.         (PVFS_ATTR_COMMON_ALL|PVFS_ATTR_DIR_HINT),
  274.         PVFS_TYPE_DIRECTORY,
  275.         0);
  276.  
  277.     if (js_p->error_code == MKDIR_RETRY)
  278.     {
  279.         js_p->error_code = 0;
  280.  
  281.         return job_req_sched_post_timer(
  282.             sm_p->msgarray_op.params.retry_delay, smcb, 0, js_p, &tmp_id,
  283.             pint_client_sm_context);
  284.     }
  285.  
  286.     return SM_ACTION_COMPLETE;
  287. }
  288.  
  289. static int mkdir_msg_comp_fn(void *v_p,
  290.                              struct PVFS_server_resp *resp_p,
  291.                              int index)
  292. {
  293.     PINT_smcb *smcb = v_p;
  294.     PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_MSGPAIR_PARENT_SM);
  295.     PVFS_object_attr attr;
  296.     
  297.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir_msg_comp_fn\n");
  298.  
  299.     assert(resp_p->op == PVFS_SERV_MKDIR);
  300.  
  301.     if (resp_p->status != 0)
  302.     {
  303.     return resp_p->status;
  304.     }
  305.  
  306.     /* otherwise, just stash the newly created meta handle */
  307.     sm_p->u.mkdir.metafile_handle = resp_p->u.mkdir.handle;
  308.  
  309.     /* also insert entry into attr cache */
  310.     PINT_CONVERT_ATTR(&attr, &sm_p->u.mkdir.sys_attr, 0);
  311.     PINT_acache_update(sm_p->object_ref, &attr, NULL);
  312.  
  313.     gossip_debug(
  314.         GOSSIP_CLIENT_DEBUG, "*** Got newly created dir handle %llu\n",
  315.         llu(sm_p->u.mkdir.metafile_handle));
  316.  
  317.     return 0;
  318. }
  319.  
  320. static int mkdir_crdirent_comp_fn(void *v_p,
  321.                                   struct PVFS_server_resp *resp_p,
  322.                                   int index)
  323. {
  324.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir_crdirent_comp_fn\n");
  325.  
  326.     assert(resp_p->op == PVFS_SERV_CRDIRENT);
  327.     return resp_p->status;
  328. }
  329.  
  330. static int mkdir_delete_handle_comp_fn(void *v_p,
  331.                                        struct PVFS_server_resp *resp_p,
  332.                                        int index)
  333. {
  334.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir_delete_handle_comp_fn\n");
  335.  
  336.     assert(resp_p->op == PVFS_SERV_REMOVE);
  337.     return resp_p->status;
  338. }
  339.  
  340. static PINT_sm_action mkdir_msg_setup_msgpair(
  341.         struct PINT_smcb *smcb, job_status_s *js_p)
  342. {
  343.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  344.     int ret = -PVFS_EINVAL;
  345.     PVFS_handle_extent_array meta_handle_extent_array;
  346.     PINT_sm_msgpair_state *msg_p = NULL;
  347.  
  348.     gossip_debug(GOSSIP_CLIENT_DEBUG,
  349.                  "mkdir state: mkdir_msg_setup_msgpair\n");
  350.  
  351.     js_p->error_code = 0;
  352.  
  353.     gossip_debug(GOSSIP_CLIENT_DEBUG," mkdir: posting mkdir req\n");
  354.  
  355.     PINT_msgpair_init(&sm_p->msgarray_op);
  356.     msg_p = &sm_p->msgarray_op.msgpair;
  357.  
  358.     ret = PINT_cached_config_get_next_meta(
  359.         sm_p->object_ref.fs_id,
  360.         &msg_p->svr_addr, &meta_handle_extent_array);
  361.  
  362.     if (ret)
  363.     {
  364.         gossip_err("Failed to map meta server address\n");
  365.         js_p->error_code = ret;
  366.         return SM_ACTION_COMPLETE;
  367.     }
  368.  
  369.     PINT_SERVREQ_MKDIR_FILL(
  370.         msg_p->req,
  371.         *sm_p->cred_p,
  372.         sm_p->object_ref.fs_id,
  373.         meta_handle_extent_array,
  374.         sm_p->u.mkdir.sys_attr,
  375.         sm_p->hints);
  376.  
  377.     msg_p->fs_id = sm_p->object_ref.fs_id;
  378.     msg_p->handle = meta_handle_extent_array.extent_array[0].first;
  379.     msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
  380.     msg_p->comp_fn = mkdir_msg_comp_fn;
  381.  
  382.     PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
  383.     return SM_ACTION_COMPLETE;
  384. }
  385.  
  386. static PINT_sm_action mkdir_msg_failure(
  387.         struct PINT_smcb *smcb, job_status_s *js_p)
  388. {
  389.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  390.     sm_p->u.mkdir.stored_error_code = js_p->error_code;
  391.  
  392.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_msg_failure\n");
  393.     return SM_ACTION_COMPLETE;
  394. }
  395.  
  396. static PINT_sm_action mkdir_crdirent_setup_msgpair(
  397.         struct PINT_smcb *smcb, job_status_s *js_p)
  398. {
  399.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  400.     int ret = -PVFS_EINVAL;
  401.     PINT_sm_msgpair_state *msg_p = NULL;
  402.  
  403.     gossip_debug(GOSSIP_CLIENT_DEBUG,
  404.                  "mkdir state: crdirent_setup_msgpair\n");
  405.  
  406.     js_p->error_code = 0;
  407.  
  408.     gossip_debug(GOSSIP_CLIENT_DEBUG," mkdir: posting crdirent req\n");
  409.  
  410.     gossip_debug(GOSSIP_CLIENT_DEBUG, "hooking dirent %s (%llu) under "
  411.                  "parent handle %llu\n", sm_p->u.mkdir.object_name,
  412.                  llu(sm_p->u.mkdir.metafile_handle),
  413.                  llu(sm_p->object_ref.handle));
  414.  
  415.     PINT_msgpair_init(&sm_p->msgarray_op);
  416.     msg_p = &sm_p->msgarray_op.msgpair;
  417.  
  418.     PINT_SERVREQ_CRDIRENT_FILL(
  419.         msg_p->req,
  420.         *sm_p->cred_p,
  421.         sm_p->u.mkdir.object_name,
  422.         sm_p->u.mkdir.metafile_handle,
  423.         sm_p->object_ref.handle,
  424.         sm_p->object_ref.fs_id,
  425.         sm_p->hints);
  426.  
  427.     msg_p->fs_id = sm_p->object_ref.fs_id;
  428.     msg_p->handle = sm_p->object_ref.handle;
  429.     msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
  430.     msg_p->comp_fn = mkdir_crdirent_comp_fn;
  431.  
  432.     ret = PINT_cached_config_map_to_server(
  433.         &msg_p->svr_addr, sm_p->object_ref.handle,
  434.         sm_p->object_ref.fs_id);
  435.  
  436.     if (ret)
  437.     {
  438.         gossip_err("Failed to map meta server address\n");
  439.         js_p->error_code = ret;
  440.     }
  441.  
  442.     PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
  443.     return SM_ACTION_COMPLETE;
  444. }
  445.  
  446. static PINT_sm_action mkdir_crdirent_failure(
  447.         struct PINT_smcb *smcb, job_status_s *js_p)
  448. {
  449.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  450.     sm_p->u.mkdir.stored_error_code = js_p->error_code;
  451.  
  452.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: crdirent_failure\n");
  453.  
  454.     PVFS_perror_gossip("mkdir crdirent failed", js_p->error_code);
  455.     return SM_ACTION_COMPLETE;
  456. }
  457.  
  458. static PINT_sm_action mkdir_delete_handle_setup_msgpair(
  459.         struct PINT_smcb *smcb, job_status_s *js_p)
  460. {
  461.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  462.     int ret = -PVFS_EINVAL;
  463.     PVFS_BMI_addr_t metafile_server_addr;
  464.     PINT_sm_msgpair_state *msg_p = NULL;
  465.  
  466.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: "
  467.                  "delete_handle_setup_msgpair_array\n");
  468.  
  469.     js_p->error_code = 0;
  470.  
  471.     PINT_msgpair_init(&sm_p->msgarray_op);
  472.     msg_p = &sm_p->msgarray_op.msgpair;
  473.  
  474.     ret = PINT_cached_config_map_to_server(
  475.         &metafile_server_addr, sm_p->u.mkdir.metafile_handle,
  476.         sm_p->object_ref.fs_id);
  477.  
  478.     if (ret)
  479.     {
  480.         gossip_err("Failed to map meta server address\n");
  481.         js_p->error_code = ret;
  482.         return SM_ACTION_COMPLETE;
  483.     }
  484.  
  485.     PINT_SERVREQ_REMOVE_FILL(
  486.         msg_p->req,
  487.         *sm_p->cred_p,
  488.         sm_p->object_ref.fs_id,
  489.         sm_p->u.mkdir.metafile_handle,
  490.         sm_p->hints);
  491.  
  492.     msg_p->fs_id = sm_p->object_ref.fs_id;
  493.     msg_p->handle = sm_p->u.mkdir.metafile_handle;
  494.     msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
  495.     msg_p->comp_fn = mkdir_delete_handle_comp_fn;
  496.     msg_p->svr_addr = metafile_server_addr;
  497.  
  498.     gossip_debug(GOSSIP_CLIENT_DEBUG, " Preparing to remove "
  499.                  "directory handle %llu\n", llu(msg_p->handle));
  500.  
  501.     PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
  502.     return SM_ACTION_COMPLETE;
  503. }
  504.  
  505. static PINT_sm_action mkdir_cleanup(
  506.         struct PINT_smcb *smcb, job_status_s *js_p)
  507. {
  508.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  509.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: cleanup\n");
  510.  
  511.     if(sm_p->u.mkdir.val_array)
  512.     {
  513.         if((sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT) &&
  514.             (sm_p->getattr.attr.u.dir.hint.dfile_count > 0))
  515.         {
  516.             free(sm_p->u.mkdir.val_array[0].buffer);
  517.         }
  518.         free(sm_p->u.mkdir.val_array);
  519.     }
  520.     if(sm_p->u.mkdir.key_array)
  521.     {
  522.         free(sm_p->u.mkdir.key_array);
  523.     }
  524.  
  525.     PVFS_util_release_sys_attr(&sm_p->u.mkdir.sys_attr);
  526.  
  527.     PINT_SM_GETATTR_STATE_CLEAR(sm_p->getattr);
  528.  
  529.     sm_p->error_code = (sm_p->u.mkdir.stored_error_code ?
  530.                         sm_p->u.mkdir.stored_error_code :
  531.                         js_p->error_code);
  532.  
  533.     if (sm_p->error_code == 0)
  534.     {
  535.         PVFS_object_ref directory_ref;
  536.  
  537.         directory_ref.handle = sm_p->u.mkdir.metafile_handle;
  538.         directory_ref.fs_id = sm_p->object_ref.fs_id;
  539.  
  540.         sm_p->u.mkdir.mkdir_resp->ref.handle = directory_ref.handle;
  541.         sm_p->u.mkdir.mkdir_resp->ref.fs_id = directory_ref.fs_id;
  542.  
  543.         /* insert newly created directory handle into the ncache */
  544.         PINT_ncache_update((const char*) sm_p->u.mkdir.object_name, 
  545.                            (const PVFS_object_ref*) &directory_ref, 
  546.                            (const PVFS_object_ref*) &(sm_p->object_ref));
  547.     }
  548.     else if ((PVFS_ERROR_CLASS(-sm_p->error_code) == PVFS_ERROR_BMI) &&
  549.              (sm_p->u.mkdir.retry_count < sm_p->msgarray_op.params.retry_limit))
  550.     {
  551.         sm_p->u.mkdir.stored_error_code = 0;
  552.         sm_p->u.mkdir.retry_count++;
  553.  
  554.         gossip_debug(GOSSIP_CLIENT_DEBUG, "Retrying mkdir operation "
  555.                      "(attempt number %d)\n", sm_p->u.mkdir.retry_count);
  556.  
  557.         js_p->error_code = MKDIR_RETRY;
  558.         return SM_ACTION_COMPLETE;
  559.     }
  560.     else
  561.     {
  562.         PINT_acache_invalidate(sm_p->object_ref);
  563.         PVFS_perror_gossip("mkdir failed with error", sm_p->error_code);
  564.     }
  565.  
  566.     PINT_SET_OP_COMPLETE;
  567.     return SM_ACTION_TERMINATE;
  568. }
  569.  
  570. /** looks at the attributes of the parent directory and decides if it impacts
  571.  *  the mkdir in any way
  572.  */
  573. static PINT_sm_action mkdir_parent_getattr_inspect(
  574.         struct PINT_smcb *smcb, job_status_s *js_p)
  575. {
  576.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  577.     PVFS_object_attr *attr = NULL;
  578.  
  579.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: parent_getattr_inspect\n");
  580.  
  581.     attr = &sm_p->getattr.attr;
  582.     assert(attr);
  583.  
  584.     gossip_debug(GOSSIP_CLIENT_DEBUG, "parent owner: %d, group: %d, perms: %d\n",
  585.         (int)attr->owner, (int)attr->group, (int)attr->perms);
  586.  
  587.     /* do we have a setgid bit? */
  588.     if(attr->perms & PVFS_G_SGID)
  589.     {
  590.         gossip_debug(GOSSIP_CLIENT_DEBUG, "parent has setgid bit set.\n");
  591.         gossip_debug(GOSSIP_CLIENT_DEBUG, " - modifying requested attr for new file.\n");
  592.         sm_p->u.mkdir.sys_attr.group = attr->group;
  593.         sm_p->u.mkdir.sys_attr.perms |= PVFS_G_SGID;
  594.         /* note that permission checking is left to server even in this case */
  595.     }
  596.  
  597.     return SM_ACTION_COMPLETE;
  598. }
  599.  
  600. static PINT_sm_action mkdir_seteattr_setup_msgpair(
  601.         struct PINT_smcb *smcb, job_status_s *js_p)
  602. {
  603.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  604.     int eattr_count = 0;
  605.     int cur_index = 0;
  606.     PINT_sm_msgpair_state *msg_p = NULL;
  607.     int ret = -PVFS_EINVAL;
  608.  
  609.     /* NOTE: any memory allocated here will be free'd in the cleanup function */
  610.  
  611.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: seteattr_setup_msgpair\n");
  612.     
  613.     /* don't set any hint attributes if the parent doesn't have them */
  614.     if(!(sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT))
  615.     {
  616.         gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: skipping seteattr\n");
  617.         js_p->error_code = MKDIR_SKIP_EATTR;
  618.         return SM_ACTION_COMPLETE;
  619.     }
  620.  
  621.     /* count how many hints we acquired */
  622.     if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
  623.         eattr_count++;
  624.     if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
  625.         eattr_count++;
  626.     if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
  627.         eattr_count++;
  628.  
  629.     if(eattr_count == 0)
  630.     {
  631.         /* nothing to inherit */
  632.         js_p->error_code = MKDIR_SKIP_EATTR;
  633.         return SM_ACTION_COMPLETE;
  634.     }
  635.  
  636.     sm_p->u.mkdir.key_array = (PVFS_ds_keyval*)calloc(eattr_count,
  637.         sizeof(PVFS_ds_keyval));
  638.     if(!sm_p->u.mkdir.key_array)
  639.     {
  640.         js_p->error_code = -PVFS_ENOMEM;
  641.         return SM_ACTION_COMPLETE;
  642.     }
  643.  
  644.     sm_p->u.mkdir.val_array = (PVFS_ds_keyval*)calloc(eattr_count,
  645.         sizeof(PVFS_ds_keyval));
  646.     if(!sm_p->u.mkdir.val_array)
  647.     {
  648.         js_p->error_code = -PVFS_ENOMEM;
  649.         return SM_ACTION_COMPLETE;
  650.     }
  651.  
  652.     if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
  653.     {
  654.         gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting num_dfiles\n");
  655.         sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.num_dfiles";
  656.         sm_p->u.mkdir.key_array[cur_index].buffer_sz = 
  657.             strlen("user.pvfs2.num_dfiles") + 1;
  658.  
  659.         sm_p->u.mkdir.val_array[cur_index].buffer = calloc(1, 16);
  660.         if(!sm_p->u.mkdir.val_array[cur_index].buffer)
  661.         {
  662.             js_p->error_code = -PVFS_ENOMEM;
  663.             return SM_ACTION_COMPLETE;
  664.         }
  665.         snprintf((char*)sm_p->u.mkdir.val_array[cur_index].buffer,
  666.             16, "%d", sm_p->getattr.attr.u.dir.hint.dfile_count);
  667.         sm_p->u.mkdir.val_array[cur_index].buffer_sz = 
  668.             strlen((char*)sm_p->u.mkdir.val_array[cur_index].buffer) + 1;
  669.  
  670.         cur_index++;
  671.     }
  672.     if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
  673.     {
  674.         gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_name\n");
  675.         sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_name";
  676.         sm_p->u.mkdir.key_array[cur_index].buffer_sz = 
  677.             strlen("user.pvfs2.dist_name") + 1;
  678.         sm_p->u.mkdir.val_array[cur_index].buffer =
  679.             sm_p->getattr.attr.u.dir.hint.dist_name;
  680.         sm_p->u.mkdir.val_array[cur_index].buffer_sz =
  681.             sm_p->getattr.attr.u.dir.hint.dist_name_len;
  682.  
  683.         cur_index++;
  684.     }
  685.     if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
  686.     {
  687.         gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_params\n");
  688.         sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_params";
  689.         sm_p->u.mkdir.key_array[cur_index].buffer_sz = 
  690.             strlen("user.pvfs2.dist_params") + 1;
  691.  
  692.         sm_p->u.mkdir.val_array[cur_index].buffer = 
  693.             sm_p->getattr.attr.u.dir.hint.dist_params;
  694.         sm_p->u.mkdir.val_array[cur_index].buffer_sz = 
  695.             sm_p->getattr.attr.u.dir.hint.dist_params_len;
  696.  
  697.         cur_index++;
  698.     }
  699.  
  700.     PINT_msgpair_init(&sm_p->msgarray_op);
  701.     msg_p = &sm_p->msgarray_op.msgpair;
  702.  
  703.     PINT_SERVREQ_SETEATTR_FILL(
  704.             msg_p->req,
  705.             (*sm_p->cred_p),
  706.             sm_p->object_ref.fs_id,
  707.             sm_p->u.mkdir.metafile_handle,
  708.             0,
  709.             eattr_count,
  710.             sm_p->u.mkdir.key_array,
  711.             sm_p->u.mkdir.val_array,
  712.             sm_p->hints);
  713.  
  714.     msg_p->fs_id = sm_p->object_ref.fs_id;
  715.     msg_p->handle = sm_p->u.mkdir.metafile_handle;
  716.     msg_p->retry_flag = PVFS_MSGPAIR_RETRY;
  717.     /* NOTE: no comp_fn needed. */
  718.  
  719.     ret = PINT_cached_config_map_to_server(
  720.             &msg_p->svr_addr,
  721.             msg_p->handle,
  722.             msg_p->fs_id);
  723.     if (ret)
  724.     {
  725.         gossip_err("Failed to map meta server address\n");
  726.         js_p->error_code = ret;
  727.     }
  728.     else
  729.     {
  730.         js_p->error_code = 0;
  731.     }
  732.  
  733.     PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
  734.     return SM_ACTION_COMPLETE;
  735. }
  736.  
  737. static PINT_sm_action mkdir_seteattr_failure(
  738.         struct PINT_smcb *smcb, job_status_s *js_p)
  739. {
  740.     struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  741.     sm_p->u.mkdir.stored_error_code = js_p->error_code;
  742.  
  743.     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_seteattr_failure\n");
  744.  
  745.     PVFS_perror_gossip("mkdir seteattr failed", js_p->error_code);
  746.     return SM_ACTION_COMPLETE;
  747. }
  748.  
  749. /*
  750.  * Local variables:
  751.  *  mode: c
  752.  *  c-indent-level: 4
  753.  *  c-basic-offset: 4
  754.  * End:
  755.  *
  756.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  757.  */
  758.