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 / set-attr.sm < prev    next >
Text File  |  2010-04-30  |  17KB  |  513 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 "pvfs2-util.h"
  14. #include "pvfs2-internal.h"
  15. #include "pint-util.h"
  16.  
  17. enum
  18. {
  19.     STATE_METAFILE = 7,
  20.     STATE_SYMLINK = 8
  21. };
  22.  
  23. %%
  24.  
  25. machine pvfs2_set_attr_sm
  26. {
  27.     state prelude
  28.     {
  29.         jump pvfs2_prelude_sm;
  30.         success => verify_attribs;
  31.         default => final_response;
  32.     }
  33.  
  34.     state verify_attribs
  35.     {
  36.         run setattr_verify_attribs;
  37.         STATE_METAFILE => write_metafile_datafile_handles_if_required;
  38.         STATE_SYMLINK => write_symlink_target_if_required;
  39.         success => setobj_attrib;
  40.         default => final_response;
  41.     }
  42.  
  43.     state write_metafile_datafile_handles_if_required
  44.     {
  45.         run setattr_write_metafile_datafile_handles_if_required;
  46.         success => write_metafile_distribution_if_required;
  47.         default => final_response;
  48.     }
  49.  
  50.     state write_metafile_distribution_if_required
  51.     {
  52.         run setattr_write_metafile_distribution_if_required;
  53.         success => setobj_attrib;
  54.         default => final_response;
  55.     }
  56.  
  57.     state write_symlink_target_if_required
  58.     {
  59.         run setattr_write_symlink_target_if_required;
  60.         success => setobj_attrib;
  61.         default => final_response;
  62.     }
  63.  
  64.     state setobj_attrib
  65.     {
  66.         run setattr_setobj_attribs;
  67.         default => final_response;
  68.     }
  69.  
  70.     state final_response
  71.     {
  72.         jump pvfs2_final_response_sm;
  73.         default => cleanup;
  74.     }
  75.  
  76.     state cleanup
  77.     {
  78.         run setattr_cleanup;
  79.         default => terminate;
  80.     }
  81. }
  82.  
  83. %%
  84.  
  85. static PINT_sm_action setattr_verify_attribs(
  86.         struct PINT_smcb *smcb, job_status_s *js_p)
  87. {
  88.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  89.     PVFS_object_attr *a_p = NULL, *req_a_p = NULL;
  90.  
  91.     a_p = &s_op->attr;
  92.     req_a_p = &s_op->req->u.setattr.attr;
  93.  
  94.     gossip_debug(GOSSIP_SETATTR_DEBUG, "  attrs read from dspace:\n\t"
  95.                  "[owner = %d, group = %d, perms = %o, type = %d]\n",
  96.                  a_p->owner, a_p->group, a_p->perms, a_p->objtype);
  97.  
  98.     gossip_debug(GOSSIP_SETATTR_DEBUG, "  attrs read from request:\n\t"
  99.                  "[owner = %d, group = %d, perms = %o, type = %d]\n",
  100.                  (req_a_p->mask & PVFS_ATTR_COMMON_UID)  ? req_a_p->owner : -1,
  101.                  (req_a_p->mask & PVFS_ATTR_COMMON_GID)  ? req_a_p->group : -1,
  102.                  (req_a_p->mask & PVFS_ATTR_COMMON_PERM) ? req_a_p->perms : -1,
  103.                  (req_a_p->mask & PVFS_ATTR_COMMON_TYPE) ? req_a_p->objtype : -1);
  104.     /*
  105.       here we're enforcing that no one can change the type of the
  106.       handle/object already stored once it's been set to a non-zero
  107.       value.  (zero is not a valid object type meaning that it hasn't
  108.       been assigned yet)
  109.     */
  110.     if (a_p->objtype && req_a_p->objtype &&
  111.         (a_p->objtype != req_a_p->objtype))
  112.     {
  113.         gossip_debug(GOSSIP_SETATTR_DEBUG, "  handle %llu is of type %d "
  114.                      "and cannot be changed to type %d\n",
  115.                      llu(s_op->req->u.setattr.handle),
  116.                      a_p->objtype, s_op->req->u.setattr.attr.objtype);
  117.  
  118.         /* set an error to bail out of set-attr processing */
  119.         js_p->error_code = -PVFS_EACCES;
  120.         return SM_ACTION_COMPLETE;
  121.     }
  122.     else if (req_a_p->objtype == PVFS_TYPE_NONE)
  123.     {
  124.         /* if the requested object type is PVFS_TYPE_NONE, then the
  125.          * setattr is only on the common attributes, so we use the
  126.          * actual object type
  127.          */
  128.         req_a_p->objtype = a_p->objtype;
  129.     }
  130.  
  131.     js_p->error_code = 0;
  132.  
  133.     if ((req_a_p->objtype == PVFS_TYPE_METAFILE) ||
  134.         (a_p->objtype == PVFS_TYPE_METAFILE))
  135.     {
  136.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  137.                      "  handle %llu refers to a metafile\n",
  138.                      llu(s_op->req->u.setattr.handle));
  139.  
  140.         gossip_debug(
  141.             GOSSIP_SETATTR_DEBUG, " *** dspace has dfile count %d and "
  142.             "req has dfile count %d\n",
  143.             a_p->u.meta.dfile_count, req_a_p->u.meta.dfile_count);
  144.         gossip_debug(
  145.             GOSSIP_SETATTR_DEBUG, " *** dspace has dist size %d and "
  146.             "req has dist size %d\n",
  147.             a_p->u.meta.dist_size, req_a_p->u.meta.dist_size);
  148.  
  149.         /* copy the dfile count before writing this object */
  150.         if (req_a_p->mask & PVFS_ATTR_META_DFILES)
  151.         {
  152.             gossip_debug(
  153.                 GOSSIP_SETATTR_DEBUG," *** using dfile_count of %d\n",
  154.                 req_a_p->u.meta.dfile_count);
  155.             a_p->u.meta.dfile_count = req_a_p->u.meta.dfile_count;
  156.             js_p->error_code = STATE_METAFILE;
  157.         }
  158.         else
  159.         {
  160.             gossip_debug(GOSSIP_SETATTR_DEBUG,
  161.                          " *** ignoring dfile_count of %d\n",
  162.                          req_a_p->u.meta.dfile_count);
  163.         }
  164.  
  165.         /* copy the dist size before writing this object */
  166.         if (req_a_p->mask & PVFS_ATTR_META_DIST)
  167.         {
  168.             gossip_debug(GOSSIP_SETATTR_DEBUG,
  169.                          " *** using dist_size of %d\n",
  170.                          req_a_p->u.meta.dist_size);
  171.             a_p->u.meta.dist_size = req_a_p->u.meta.dist_size;
  172.             js_p->error_code = STATE_METAFILE;
  173.         }
  174.         else
  175.         {
  176.             gossip_debug(GOSSIP_SETATTR_DEBUG,
  177.                          " *** ignoring dist_size of %d\n",
  178.                          req_a_p->u.meta.dist_size);
  179.         }
  180.     }
  181.     else if ((req_a_p->objtype == PVFS_TYPE_DATAFILE) ||
  182.              (a_p->objtype == PVFS_TYPE_DATAFILE))
  183.     {
  184.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  185.                      "  handle %llu refers to a datafile\n",
  186.                      llu(s_op->req->u.setattr.handle));
  187.     }
  188.     else if ((req_a_p->objtype == PVFS_TYPE_DIRECTORY) ||
  189.              (a_p->objtype == PVFS_TYPE_DIRECTORY))
  190.     {
  191.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  192.                      "  handle %llu refers to a directory\n",
  193.                      llu(s_op->req->u.setattr.handle));
  194.     }
  195.     else if ((req_a_p->objtype == PVFS_TYPE_SYMLINK) ||
  196.              (a_p->objtype == PVFS_TYPE_SYMLINK))
  197.     {
  198.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  199.                      "  handle %llu refers to a symlink\n",
  200.                      llu(s_op->req->u.setattr.handle));
  201.  
  202.         if (req_a_p->mask & PVFS_ATTR_SYMLNK_ALL)
  203.         {
  204.             assert(req_a_p->u.sym.target_path_len > 0);
  205.             assert(req_a_p->u.sym.target_path);
  206.  
  207.             gossip_debug(GOSSIP_SETATTR_DEBUG,
  208.                          " symlink links handle %llu to %s\n",
  209.                          llu(s_op->req->u.setattr.handle),
  210.                          req_a_p->u.sym.target_path);
  211.  
  212.             a_p->u.sym.target_path_len = req_a_p->u.sym.target_path_len;
  213.             a_p->u.sym.target_path = req_a_p->u.sym.target_path;
  214.         }
  215.         js_p->error_code = STATE_SYMLINK;
  216.     }
  217.     else if ((req_a_p->objtype == PVFS_TYPE_DIRDATA) ||
  218.              (a_p->objtype == PVFS_TYPE_DIRDATA))
  219.     {
  220.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  221.                      "  handle %llu refers to a dirdata object\n",
  222.                      llu(s_op->req->u.setattr.handle));
  223.     }
  224.     else
  225.     {
  226.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  227.                      "  handle %llu refers to something unknown\n",
  228.                      llu(s_op->req->u.setattr.handle));
  229.  
  230.         js_p->error_code = -PVFS_EACCES;
  231.     }
  232.     return SM_ACTION_COMPLETE;
  233. }
  234.  
  235. static PINT_sm_action setattr_setobj_attribs(
  236.         struct PINT_smcb *smcb, job_status_s *js_p)
  237. {
  238.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  239.     int ret = -1;
  240.     job_id_t j_id;
  241.     PVFS_object_attr *a_p = NULL;
  242.     PVFS_object_attr *dspace_a_p = NULL;
  243.     PVFS_ds_attributes *ds_attr = NULL;
  244.  
  245.     dspace_a_p = &s_op->attr;
  246.     a_p = &s_op->req->u.setattr.attr;
  247.  
  248.     if (a_p->mask & PVFS_ATTR_META_DFILES)
  249.     {
  250.         gossip_debug(GOSSIP_SETATTR_DEBUG, " request has dfile_count of "
  251.                      "%d | dspace has %d\n",
  252.                      s_op->req->u.setattr.attr.u.meta.dfile_count,
  253.                      s_op->attr.u.meta.dfile_count);
  254.  
  255.         gossip_debug(GOSSIP_SETATTR_DEBUG, " writing count of %d to "
  256.                      "disk\n", dspace_a_p->u.meta.dfile_count);
  257.     }
  258.     /* 
  259.      * Remember that mtime is versioned on disk! so convert it here..
  260.      * It is better to do it here than change the PVFS_object_attr_overwrite_setable
  261.      * macro, since there are many more users of it, I think.
  262.      */
  263.      if (a_p->mask & PVFS_ATTR_COMMON_MTIME_SET)
  264.      {
  265.          PVFS_time orig_mtime = a_p->mtime;
  266.          a_p->mtime = PINT_util_mktime_version(orig_mtime);
  267.          gossip_debug(GOSSIP_SETATTR_DEBUG, "setting version "
  268.                  "to %llu\n\tmtime is %llu\n",
  269.                  llu(a_p->mtime), llu(orig_mtime));
  270.      }
  271.  
  272.     /* if the object is a symbolic link, check to make sure that the request
  273.      * is not attempting to change the permissions 
  274.      */
  275.     if(dspace_a_p->objtype == PVFS_TYPE_SYMLINK)
  276.     {
  277.         if (dspace_a_p->perms != 0 && ((a_p->mask & PVFS_ATTR_COMMON_PERM) && (dspace_a_p->perms != a_p->perms)))
  278.         {
  279.             gossip_debug(GOSSIP_SETATTR_DEBUG, "Cannot change perms of symlink: Permission denied\n");
  280.             js_p->error_code = -PVFS_EPERM;
  281.             return SM_ACTION_COMPLETE;
  282.         }
  283.     }
  284.  
  285.     /*
  286.       we have the attribs stored in the dspace, as well as the
  287.       requested attribs to store.  overwrite the ones that are setable
  288.       and specified by the mask value in the request; macro defined in
  289.       pvfs2-storage.h
  290.     */
  291.     PVFS_object_attr_overwrite_setable(dspace_a_p, a_p);
  292.  
  293.     gossip_debug(
  294.         GOSSIP_SETATTR_DEBUG,
  295.         "  WRITING attrs: [owner = %d, group = %d\n\t"
  296.         "perms = %o, type = %d, atime = %llu, mtime = %llu\n\t"
  297.         "ctime = %llu | dfile_count = %d | dist_size = %d\n\t"
  298.         "handle = %llu | S = %p | mask = %d]\n",
  299.         dspace_a_p->owner, dspace_a_p->group, dspace_a_p->perms,
  300.         dspace_a_p->objtype, llu(dspace_a_p->atime),
  301.         llu(PINT_util_mkversion_time(dspace_a_p->mtime)), llu(dspace_a_p->ctime),
  302.         (int)dspace_a_p->u.meta.dfile_count,
  303.         (int)dspace_a_p->u.meta.dist_size,
  304.         llu(s_op->req->u.setattr.handle), s_op, a_p->mask);
  305.  
  306.     /* translate attrs to storage attr format */
  307.     ds_attr = &(s_op->ds_attr);
  308.     PVFS_object_attr_to_ds_attr(dspace_a_p, ds_attr);
  309.  
  310.     ret = job_trove_dspace_setattr(
  311.         s_op->req->u.setattr.fs_id, s_op->req->u.setattr.handle,
  312.         ds_attr, 
  313.         TROVE_SYNC,
  314.         smcb, 0, js_p, &j_id, server_job_context, s_op->req->hints);
  315.  
  316.     return ret;
  317. }
  318.  
  319. static PINT_sm_action setattr_write_metafile_datafile_handles_if_required(
  320.         struct PINT_smcb *smcb, job_status_s *js_p)
  321. {
  322.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  323.     int ret = 0, dfile_count = 0;
  324.     job_id_t j_id;
  325.  
  326.     /* reset from jump to here with STATE_METAFILE */
  327.     js_p->error_code = 0;
  328.  
  329.     gossip_debug(GOSSIP_SETATTR_DEBUG,
  330.                  " request has dfile_count of %d | dspace has %d\n",
  331.                  s_op->req->u.setattr.attr.u.meta.dfile_count,
  332.                  s_op->attr.u.meta.dfile_count);
  333.  
  334.     /* verify that the requested dfile count is sane */
  335.     dfile_count = s_op->req->u.setattr.attr.u.meta.dfile_count;
  336.     if ((dfile_count < 1) || (dfile_count > PVFS_REQ_LIMIT_DFILE_COUNT))
  337.     {
  338.         gossip_err("The requested dfile count of %d is invalid; "
  339.                    "aborting operation.\n", dfile_count);
  340.         js_p->error_code = -PVFS_EOVERFLOW;
  341.         return SM_ACTION_COMPLETE;
  342.     }
  343.  
  344.     /* set up key and value structure for keyval write */
  345.     s_op->key.buffer = Trove_Common_Keys[METAFILE_HANDLES_KEY].key;
  346.     s_op->key.buffer_sz = Trove_Common_Keys[METAFILE_HANDLES_KEY].size;
  347.  
  348.     gossip_debug(GOSSIP_SETATTR_DEBUG,
  349.                  "  metafile has %d datafiles associated with it\n",
  350.                  s_op->req->u.setattr.attr.u.meta.dfile_count);
  351.  
  352.     s_op->val.buffer = s_op->req->u.setattr.attr.u.meta.dfile_array;
  353.     s_op->val.buffer_sz = dfile_count * sizeof(PVFS_handle);
  354.  
  355.     gossip_debug(
  356.         GOSSIP_SETATTR_DEBUG, "  writing %s [%llu,%d,"
  357.         "len %d]\n", (char *)s_op->key.buffer,
  358.         llu(s_op->req->u.setattr.handle), s_op->req->u.setattr.fs_id,
  359.         s_op->val.buffer_sz);
  360.  
  361.     /* we don't sync here since we're going to do it anyway in
  362.      * write_metafile_distribution
  363.      */
  364.     ret = job_trove_keyval_write(
  365.         s_op->req->u.setattr.fs_id, s_op->req->u.setattr.handle,
  366.         &(s_op->key), &(s_op->val),
  367.         0,
  368.         NULL, smcb, 0, js_p, &j_id, server_job_context, s_op->req->hints);
  369.  
  370.     return ret;
  371. }
  372.  
  373. static PINT_sm_action setattr_write_metafile_distribution_if_required(
  374.         struct PINT_smcb *smcb, job_status_s *js_p)
  375. {
  376.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  377.     int ret = 0;
  378.     job_id_t j_id;
  379.  
  380.     /* if we don't need to fill in the distribution, skip it */
  381.     if (!(s_op->req->u.setattr.attr.mask & PVFS_ATTR_META_DIST))
  382.     {
  383.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  384.                      "skipping distribution write\n");
  385.         js_p->error_code = 0;
  386.         return SM_ACTION_COMPLETE;
  387.     }
  388.  
  389.     /* set up key and value structure for keyval write */
  390.     s_op->key.buffer = Trove_Common_Keys[METAFILE_DIST_KEY].key;
  391.     s_op->key.buffer_sz = Trove_Common_Keys[METAFILE_DIST_KEY].size;
  392.  
  393.     gossip_debug(GOSSIP_SETATTR_DEBUG,
  394.                  "  metafile distribution size = %d\n",
  395.                  (int)s_op->req->u.setattr.attr.u.meta.dist_size);
  396.  
  397.     s_op->val.buffer_sz = s_op->req->u.setattr.attr.u.meta.dist_size;
  398.  
  399.     s_op->val.buffer = malloc(s_op->val.buffer_sz);
  400.     if(!s_op->val.buffer)
  401.     {
  402.         js_p->error_code = -PVFS_ENOMEM;
  403.         return SM_ACTION_COMPLETE;
  404.     }
  405.     s_op->free_val = 1;
  406.     
  407.     PINT_dist_encode(s_op->val.buffer, 
  408.                      s_op->req->u.setattr.attr.u.meta.dist);
  409.     gossip_debug(
  410.         GOSSIP_SERVER_DEBUG, "  writing %s [%llu,%d,"
  411.         "len %d]\n", (char *)s_op->key.buffer,
  412.         llu(s_op->req->u.setattr.handle), s_op->req->u.setattr.fs_id,
  413.         s_op->val.buffer_sz);
  414.  
  415.     ret = job_trove_keyval_write(
  416.         s_op->req->u.setattr.fs_id, s_op->req->u.setattr.handle,
  417.         &(s_op->key), &(s_op->val),
  418.         TROVE_SYNC,
  419.         NULL, smcb, 0, js_p, &j_id, server_job_context, s_op->req->hints);
  420.  
  421.     return ret;
  422. }
  423.  
  424. static PINT_sm_action setattr_write_symlink_target_if_required(
  425.         struct PINT_smcb *smcb, job_status_s *js_p)
  426. {
  427.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  428.     int ret = 0;
  429.     job_id_t j_id;
  430.  
  431.     /* if we don't need to fill in the symlink target, skip it */
  432.     if (!(s_op->req->u.setattr.attr.mask & PVFS_ATTR_SYMLNK_TARGET))
  433.     {
  434.         gossip_debug(GOSSIP_SETATTR_DEBUG,
  435.                      "skipping symlink target write\n");
  436.         js_p->error_code = 0;
  437.         return SM_ACTION_COMPLETE;
  438.     }
  439.  
  440.     assert(s_op->req->u.setattr.attr.u.sym.target_path_len > 0);
  441.     assert(s_op->req->u.setattr.attr.u.sym.target_path);
  442.  
  443.     /* set up key and value structure for keyval write */
  444.     s_op->key.buffer = Trove_Common_Keys[SYMLINK_TARGET_KEY].key;
  445.     s_op->key.buffer_sz = Trove_Common_Keys[SYMLINK_TARGET_KEY].size;
  446.  
  447.     gossip_debug(GOSSIP_SETATTR_DEBUG,
  448.                  "  symlink target_path_len = %d\n",
  449.                  s_op->req->u.setattr.attr.u.sym.target_path_len);
  450.  
  451.     s_op->val.buffer = s_op->req->u.setattr.attr.u.sym.target_path;
  452.     s_op->val.buffer_sz = s_op->req->u.setattr.attr.u.sym.target_path_len;
  453.  
  454.     gossip_debug(GOSSIP_SETATTR_DEBUG, "  writing %s [%llu,%d,"
  455.                  "len %d]\n", (char *)s_op->key.buffer,
  456.                  llu(s_op->req->u.setattr.handle),
  457.                  s_op->req->u.setattr.fs_id,
  458.                  s_op->val.buffer_sz);
  459.  
  460.     ret = job_trove_keyval_write(
  461.         s_op->req->u.setattr.fs_id, s_op->req->u.setattr.handle,
  462.         &(s_op->key), &(s_op->val),
  463.         TROVE_SYNC,
  464.         NULL, smcb, 0, js_p, &j_id, server_job_context, s_op->req->hints);
  465.  
  466.     return ret;
  467. }
  468.  
  469. /*
  470.  * Function: setattr_cleanup
  471.  *
  472.  * Params:   server_op *b, 
  473.  *           job_status_s *js_p
  474.  *
  475.  * Returns:  int
  476.  *
  477.  * Synopsis: free memory and return
  478.  *           
  479.  */
  480. static PINT_sm_action setattr_cleanup(
  481.         struct PINT_smcb *smcb, job_status_s *js_p)
  482. {
  483.     struct PINT_server_op *s_op = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
  484.     if(s_op->free_val)
  485.     {
  486.         free(s_op->val.buffer);
  487.     }
  488.     return(server_state_machine_complete(smcb));
  489. }
  490.  
  491. PINT_GET_OBJECT_REF_DEFINE(setattr);
  492.  
  493. struct PINT_server_req_params pvfs2_set_attr_params =
  494. {
  495.     .string_name = "setattr",
  496.     .perm = PINT_SERVER_CHECK_ATTR,
  497.     .access_type = PINT_server_req_modify,
  498.     .sched_policy = PINT_SERVER_REQ_SCHEDULE,
  499.     .get_object_ref = PINT_get_object_ref_setattr,
  500.     .state_machine = &pvfs2_set_attr_sm
  501. };
  502.  
  503. /*
  504.  * Local variables:
  505.  *  mode: c
  506.  *  c-indent-level: 4
  507.  *  c-basic-offset: 4
  508.  * End:
  509.  *
  510.  * vim: ft=c ts=8 sts=4 sw=4 expandtab
  511.  */
  512.  
  513.