[PVFS2-CVS] commit by slang in pvfs2/src/server: del-eattr.sm crdirent.sm create.sm final-response.sm get-attr.sm get-eattr.sm io.sm lookup.sm module.mk.in prelude.sm proto-error.sm pvfs2-server.c pvfs2-server.h rmdirent.sm set-eattr.sm setparam.sm get-eattr-list.sm set-eattr-list.sm

CVS commit program cvs at parl.clemson.edu
Wed Aug 10 16:38:09 EDT 2005


Update of /projects/cvsroot/pvfs2/src/server
In directory parlweb:/tmp/cvs-serv30967/src/server

Modified Files:
      Tag: slang-attr-cache-fixups-branch
	crdirent.sm create.sm final-response.sm get-attr.sm 
	get-eattr.sm io.sm lookup.sm module.mk.in prelude.sm 
	proto-error.sm pvfs2-server.c pvfs2-server.h rmdirent.sm 
	set-eattr.sm setparam.sm 
Added Files:
      Tag: slang-attr-cache-fixups-branch
	del-eattr.sm 
Removed Files:
      Tag: slang-attr-cache-fixups-branch
	get-eattr-list.sm set-eattr-list.sm 
Log Message:
merge changes from trunk since branch point into branch.  Effectively moves the branchpoint to the latest trunk.


--- /dev/null	2003-01-30 05:24:37.000000000 -0500
+++ del-eattr.sm	2005-08-10 15:38:09.000000000 -0400
@@ -0,0 +1,244 @@
+/* 
+ * (C) 2001 Clemson University and The University of Chicago 
+ *
+ * See COPYING in top-level directory.
+ */
+
+#include <string.h>
+#include <assert.h>
+
+#include "server-config.h"
+#include "pvfs2-server.h"
+#include "pvfs2-attr.h"
+
+static inline char *get_object_type(int objtype)
+{
+    static char *obj_types[] =
+    {
+         "NONE", "METAFILE", "DATAFILE",
+         "DIRECTORY", "SYMLINK", "DIRDATA", "UNKNOWN"
+    };
+    switch(objtype)
+    {
+    case PVFS_TYPE_NONE:
+         return obj_types[0];
+    case PVFS_TYPE_METAFILE:
+         return obj_types[1];
+    case PVFS_TYPE_DATAFILE:
+         return obj_types[2];
+    case PVFS_TYPE_DIRECTORY:
+         return obj_types[3];
+    case PVFS_TYPE_SYMLINK:
+         return obj_types[4];
+    case PVFS_TYPE_DIRDATA:
+         return obj_types[5];
+    }
+    return obj_types[6];
+}
+
+static int deleattr_cleanup(
+    PINT_server_op *s_op, job_status_s *js_p);
+static int deleattr_delobj_eattribs(
+    PINT_server_op *s_op, job_status_s *js_p);
+static int deleattr_verify_eattribs(
+    PINT_server_op *s_op, job_status_s *js_p);
+
+extern PINT_server_trove_keys_s Trove_Common_Keys[];
+
+%%
+
+machine pvfs2_del_eattr_sm(
+    prelude,
+    cleanup,
+    verify_eattribs,
+    delobj_eattrib,
+    final_response)
+{
+    state prelude
+    {
+        jump pvfs2_prelude_sm;
+        success => verify_eattribs;
+        default => final_response;
+    }
+
+    state verify_eattribs
+    {
+        run deleattr_verify_eattribs;
+        success => delobj_eattrib;
+        default => final_response;
+    }
+
+    state delobj_eattrib
+    {
+        run deleattr_delobj_eattribs;
+        default => final_response;
+    }
+
+    state final_response
+    {
+        jump pvfs2_final_response_sm;
+        default => cleanup;
+    }
+
+    state cleanup
+    {
+        run deleattr_cleanup;
+        default => terminate;
+    }
+}
+
+%%
+
+/*
+ * This routine really just does debugging - can print out info about
+ * the target of the operation.  There are few things to verify here
+ * be we'll try to verify what we can.  We can also disallow setting
+ * extended attributes on certain object types if we want.  We might
+ * want to prevent access to standard metadata keys.
+ */
+static int deleattr_verify_eattribs(
+    PINT_server_op *s_op, job_status_s *js_p)
+{
+    PVFS_object_attr *a_p = NULL;
+
+    PINT_STATE_DEBUG("verify_eattribs");
+
+    a_p = &s_op->attr;
+
+    js_p->error_code = 0;
+
+    gossip_debug(GOSSIP_DELEATTR_DEBUG,
+                 "  ext attr delete from handle %Lu refers to a %s\n\t"
+                 "[owner = %d, group = %d, perms = %o, type = %d]\n",
+                 Lu(s_op->req->u.deleattr.handle),
+                 get_object_type(a_p->objtype),
+                 a_p->owner, a_p->group, a_p->perms, a_p->objtype);
+
+    switch (a_p->objtype)
+    {
+    case PVFS_TYPE_METAFILE :
+        if (!strncmp(s_op->req->u.deleattr.key.buffer,
+                    Trove_Common_Keys[METAFILE_HANDLES_KEY].key,
+                    s_op->req->u.deleattr.key.buffer_sz) ||
+            !strncmp(s_op->req->u.deleattr.key.buffer,
+                    Trove_Common_Keys[METAFILE_DIST_KEY].key,
+                    s_op->req->u.deleattr.key.buffer_sz))
+        {
+            /* can't set these keys with this request */
+            js_p->error_code = -PVFS_EINVAL;
+            return -PVFS_EINVAL;
+        }
+    case PVFS_TYPE_SYMLINK :
+        if (!strncmp(s_op->req->u.deleattr.key.buffer,
+                    Trove_Common_Keys[SYMLINK_TARGET_KEY].key,
+                    s_op->req->u.deleattr.key.buffer_sz))
+        {
+            /* can't set these keys with this request */
+            js_p->error_code = -PVFS_EINVAL;
+            return -PVFS_EINVAL;
+        }
+    case PVFS_TYPE_DIRECTORY :
+        if (!strncmp(s_op->req->u.deleattr.key.buffer,
+                    Trove_Common_Keys[DIR_ENT_KEY].key,
+                    s_op->req->u.deleattr.key.buffer_sz))
+        {
+            /* can't set these keys with this request */
+            js_p->error_code = -PVFS_EINVAL;
+            return -PVFS_EINVAL;
+        }
+    default :
+        /* no holds barred for other types */
+        ;
+    }
+
+    /* no one is allowed to set standard attribs with this op */
+    if (!strncmp((void *)s_op->req->u.deleattr.key.buffer,
+                (void *)&s_op->req->u.deleattr.handle,
+                sizeof(s_op->req->u.deleattr.handle)))
+    {
+        /* can't set these keys with this request */
+        js_p->error_code = -PVFS_EINVAL;
+        return -PVFS_EINVAL;
+    }
+
+    return 1;
+}
+
+/*
+ * This is where the actual extended attrib gets written.
+ * Not much to this, its pretty straight-forward.
+ */
+static int deleattr_delobj_eattribs(PINT_server_op *s_op, job_status_s *js_p)
+{
+    int ret = 0;
+    job_id_t j_id;
+    struct server_configuration_s *user_opts = get_server_config_struct();
+
+    PINT_STATE_DEBUG("seteattr_setobj_eattribs");
+
+    /* set up key and value structure for keyval write */
+    s_op->key.buffer = s_op->req->u.deleattr.key.buffer;
+    s_op->key.buffer_sz = s_op->req->u.deleattr.key.buffer_sz;
+
+    gossip_debug(
+        GOSSIP_DELEATTR_DEBUG,
+        "  writing %s [%Lu,%d,len %d]\n",
+        (char *)s_op->key.buffer,
+        Lu(s_op->req->u.deleattr.handle),
+        s_op->req->u.deleattr.fs_id,
+        s_op->val.buffer_sz);
+
+    gossip_debug(
+        GOSSIP_DELEATTR_DEBUG,
+        "keybuf %p keylen %d\n",
+        s_op->req->u.deleattr.key.buffer, s_op->req->u.deleattr.key.buffer_sz);
+
+    ret = job_trove_keyval_remove(
+        s_op->req->u.deleattr.fs_id,
+        s_op->req->u.deleattr.handle,
+        &(s_op->key),
+        PINT_config_get_trove_sync_meta(
+            user_opts, s_op->req->u.deleattr.fs_id),
+        NULL,
+        s_op,
+        0,
+        js_p,
+        &j_id,
+        server_job_context);
+
+    return ret;
+}
+
+/*
+ * Function: delattr_cleanup
+ *
+ * Params:   server_op *b, 
+ *           job_status_s *js_p
+ *
+ * Returns:  int
+ *
+ * Synopsis: free memory and return
+ *           
+ */
+static int deleattr_cleanup(PINT_server_op *s_op, job_status_s *js_p)
+{
+    PINT_STATE_DEBUG("deleattr_cleanup");
+
+    gossip_debug(
+        GOSSIP_DELEATTR_DEBUG,
+        "keybuf %p keylen %d\n",
+        s_op->req->u.deleattr.key.buffer, s_op->req->u.deleattr.key.buffer_sz);
+
+    return(server_state_machine_complete(s_op));
+}
+
+/*
+ * Local variables:
+ *  mode: c
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ *
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ */
+

Index: crdirent.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/crdirent.sm,v
diff -p -u -r1.52 -r1.52.2.1
--- crdirent.sm	14 Jun 2005 19:23:32 -0000	1.52
+++ crdirent.sm	10 Aug 2005 19:38:07 -0000	1.52.2.1
@@ -659,6 +659,8 @@ static int crdirent_setup_op(
     PINT_server_op *s_op, job_status_s *js_p)
 {
     PINT_STATE_DEBUG("setup_op");
+    PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "crdirent entry: %s points to %Lu\n",
+        s_op->req->u.crdirent.name, Lu(s_op->req->u.crdirent.new_handle));
 
     s_op->u.crdirent.name = s_op->req->u.crdirent.name;
     s_op->u.crdirent.new_handle = s_op->req->u.crdirent.new_handle;

Index: create.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/create.sm,v
diff -p -u -r1.36 -r1.36.14.1
--- create.sm	12 Aug 2004 19:53:41 -0000	1.36
+++ create.sm	10 Aug 2005 19:38:07 -0000	1.36.14.1
@@ -114,6 +114,33 @@ static int create_setup_resp(PINT_server
 	gossip_debug(GOSSIP_SERVER_DEBUG, "Handle created: %Lu\n",
                      Lu(js_p->handle));
 	s_op->resp.u.create.handle = js_p->handle;
+        switch(s_op->req->u.create.object_type)
+        {
+            case PVFS_TYPE_NONE:
+                PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, 
+                    "new handle: %Lu, type unknown.\n");
+                break;
+            case PVFS_TYPE_METAFILE:
+                PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, 
+                    "new handle: %Lu, type metafile.\n");
+                break;
+            case PVFS_TYPE_DATAFILE:
+                PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG,    
+                    "new handle: %Lu, type datafile.\n");
+                break;
+            case PVFS_TYPE_DIRECTORY:
+                PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, 
+                    "new handle: %Lu, type directory.\n");
+                break;
+            case PVFS_TYPE_SYMLINK:
+                PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG,    
+                    "new handle: %Lu, type symlink.\n");
+                break;
+            case PVFS_TYPE_DIRDATA:
+                PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG,    
+                    "new handle: %Lu, type dirdata.\n");
+                break;
+        }
     }
 
     /* NOTE: we _deliberately_ leave the error_code unchanged so that it

Index: final-response.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/final-response.sm,v
diff -p -u -r1.20 -r1.20.12.1
--- final-response.sm	20 Jan 2005 14:51:02 -0000	1.20
+++ final-response.sm	10 Aug 2005 19:38:07 -0000	1.20.12.1
@@ -110,6 +110,7 @@ static int final_response_send_resp(
 {
     int ret = -1;
     job_id_t tmp_id;
+    struct server_configuration_s *user_opts = get_server_config_struct();
     
     gossip_debug(
         GOSSIP_SERVER_DEBUG, 
@@ -139,7 +140,7 @@ static int final_response_send_resp(
         s_op->addr, s_op->encoded.buffer_list, s_op->encoded.size_list,
         s_op->encoded.list_count, s_op->encoded.total_size, s_op->tag,
         s_op->encoded.buffer_type, 0, s_op, 0, js_p, &tmp_id,
-        server_job_context, PVFS2_SERVER_RESPONSE_TIMEOUT);
+        server_job_context, user_opts->server_job_bmi_timeout);
 
     return ret;
 }
@@ -152,10 +153,15 @@ static int final_response_send_resp(
  */
 static int final_response_cleanup(PINT_server_op *s_op, job_status_s *js_p)
 {
+    char status_string[64] = {0};
+
     gossip_debug(GOSSIP_SERVER_DEBUG, 
                  "(%p) %s (FR sm) state: cleanup\n",
                  s_op, PINT_map_server_op_to_string(s_op->req->op));
 
+    PVFS_strerror_r(s_op->resp.status, status_string, 64);
+    PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "finish (%s)\n", status_string);
+
     PINT_encode_release(&s_op->encoded, PINT_ENCODE_RESP);
 
     /* decrement reference count for this bmi address */
@@ -199,6 +205,9 @@ static __req_resp_type_desc_t s_req_resp
       "PVFS_SERV_MGMT_GET_DIRDATA_HANDLE" },
     { PVFS_SERV_JOB_TIMER, "PVFS_SERV_JOB_TIMER" },
     { PVFS_SERV_PROTO_ERROR, "PVFS_SERV_PROTO_ERROR" },
+    { PVFS_SERV_GETEATTR, "PVFS_SERV_GETEATTR" },
+    { PVFS_SERV_SETEATTR, "PVFS_SERV_SETEATTR" },
+    { PVFS_SERV_DELEATTR, "PVFS_SERV_DELEATTR" },
 };
 
 static void PINT_gossip_err_server_resp(

Index: get-attr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/get-attr.sm,v
diff -p -u -r1.68 -r1.68.2.1
--- get-attr.sm	11 Jul 2005 20:06:24 -0000	1.68
+++ get-attr.sm	10 Aug 2005 19:38:07 -0000	1.68.2.1
@@ -274,6 +274,7 @@ static int getattr_verify_attribs(
     */
     if (resp_attr->objtype == PVFS_TYPE_METAFILE)
     {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "type: metafile\n");
         gossip_debug(GOSSIP_GETATTR_DEBUG,
                      "  Req handle %Lu refers to a metafile\n",
                      Lu(s_op->u.getattr.handle));
@@ -323,6 +324,7 @@ static int getattr_verify_attribs(
     }
     else if (resp_attr->objtype == PVFS_TYPE_DATAFILE)
     {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "type: datafile\n");
         /*
           note: the prelude already retrieved the size for us, so
           there's no special action that needs to be taken if we have
@@ -340,6 +342,7 @@ static int getattr_verify_attribs(
     }
     else if (resp_attr->objtype == PVFS_TYPE_DIRECTORY)
     {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "type: directory\n");
         if (s_op->u.getattr.attrmask & PVFS_ATTR_DIR_DIRENT_COUNT)
         {
             gossip_debug(GOSSIP_GETATTR_DEBUG,
@@ -358,6 +361,7 @@ static int getattr_verify_attribs(
     }
     else if (resp_attr->objtype == PVFS_TYPE_DIRDATA)
     {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "type: dirdata\n");
 	gossip_debug(
             GOSSIP_GETATTR_DEBUG, "  handle %Lu refers to "
             "a dirdata object. doing nothing special\n",
@@ -366,6 +370,7 @@ static int getattr_verify_attribs(
     }
     else if (resp_attr->objtype == PVFS_TYPE_SYMLINK)
     {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "type: symlink\n");
 	gossip_debug(
             GOSSIP_GETATTR_DEBUG, "  handle %Lu refers to a symlink.\n",
             Lu(s_op->u.getattr.handle));

Index: get-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/get-eattr.sm,v
diff -p -u -r1.1 -r1.1.4.1
--- get-eattr.sm	16 Jun 2005 23:45:46 -0000	1.1
+++ get-eattr.sm	10 Aug 2005 19:38:08 -0000	1.1.4.1
@@ -119,10 +119,34 @@ machine pvfs2_get_eattr_sm(
  */
 static int geteattr_setup_resp(PINT_server_op *s_op, job_status_s *js_p)
 {
+    int i, tsz;
     PINT_STATE_DEBUG("setup_resp");
-    s_op->resp.u.geteattr.val.buffer = malloc(s_op->req->u.geteattr.valsz);
-    if (!s_op->resp.u.geteattr.val.buffer)
+    gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr requesting %d keys\n",
+            s_op->req->u.geteattr.nkey);
+    s_op->resp.u.geteattr.val =
+        malloc(s_op->req->u.geteattr.nkey*sizeof(PVFS_ds_keyval));
+    if (!s_op->resp.u.geteattr.val)
         return -PVFS_ENOMEM;
+    s_op->resp.u.geteattr.nkey = s_op->req->u.geteattr.nkey;
+    for (i = 0, tsz = 0; i < s_op->req->u.geteattr.nkey; i++)
+        tsz += s_op->req->u.geteattr.valsz[i];
+    s_op->u.eattr.buffer = malloc(tsz);
+    if (!s_op->u.eattr.buffer)
+    {
+        s_op->resp.u.geteattr.nkey = 0;
+        free (s_op->resp.u.geteattr.val);
+        return -PVFS_ENOMEM;
+    }
+    gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr buffer size %d bytes\n",
+            tsz);
+    for (i = 0, tsz = 0; i < s_op->req->u.geteattr.nkey; i++)
+    {
+        s_op->resp.u.geteattr.val[i].buffer_sz =
+            s_op->req->u.geteattr.valsz[i];
+        s_op->resp.u.geteattr.val[i].buffer =
+            s_op->u.eattr.buffer + tsz;
+        tsz += s_op->req->u.geteattr.valsz[i];
+    }
     return 1;
 }
 
@@ -140,13 +164,12 @@ static int geteattr_read_eattrib(
 
     js_p->error_code = 0;
 
-    s_op->resp.u.geteattr.val.buffer_sz = s_op->req->u.geteattr.valsz;
-
-    ret = job_trove_keyval_read(
+    ret = job_trove_keyval_read_list(
         s_op->req->u.geteattr.fs_id,
         s_op->req->u.geteattr.handle,
-        &(s_op->req->u.geteattr.key),
-        &(s_op->resp.u.geteattr.val),
+        s_op->req->u.geteattr.key,
+        s_op->resp.u.geteattr.val,
+        s_op->req->u.geteattr.nkey,
         0,
         NULL,
         s_op,
@@ -164,10 +187,26 @@ static int geteattr_read_eattrib(
  */
 static int geteattr_check_resp(PINT_server_op *s_op, job_status_s *js_p)
 {
+    int k;
     PINT_STATE_DEBUG("check_resp");
+    gossip_debug(GOSSIP_GETEATTR_DEBUG,"geteattr returning %d values\n",
+            s_op->resp.u.geteattr.nkey);
     /* put the returned read buffer size in buffer_sz */
+    gossip_debug(GOSSIP_GETEATTR_DEBUG,"status %d error_code %d nkeys %d\n",
+            s_op->resp.status, js_p->error_code, s_op->resp.u.geteattr.nkey);
     /* it is the only thing returned across the wire */
-    s_op->resp.u.geteattr.val.buffer_sz = s_op->resp.u.geteattr.val.read_sz;
+    for (k = 0; k < s_op->resp.u.geteattr.nkey; k++)
+    {
+        if (js_p->error_code == 0)
+        {
+            s_op->resp.u.geteattr.val[k].buffer_sz =
+                s_op->resp.u.geteattr.val[k].read_sz;
+        }
+        /* in case of any errors, we initialize it to 0 */
+        else {
+            s_op->resp.u.geteattr.val[k].buffer_sz = 0;
+        }
+    }
     return 1;
 }
 
@@ -177,8 +216,10 @@ static int geteattr_check_resp(PINT_serv
 static int geteattr_cleanup(PINT_server_op *s_op, job_status_s *js_p)
 {
     PINT_STATE_DEBUG("geteattr_cleanup");
-    if (s_op->resp.u.geteattr.val.buffer)
-        free(s_op->resp.u.geteattr.val.buffer);
+    if (s_op->resp.u.geteattr.val)
+        free(s_op->resp.u.geteattr.val);
+    if (s_op->u.eattr.buffer)
+        free(s_op->u.eattr.buffer);
     return(server_state_machine_complete(s_op));
 }
 

Index: io.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/io.sm,v
diff -p -u -r1.55 -r1.55.14.1
--- io.sm	21 Dec 2004 14:54:52 -0000	1.55
+++ io.sm	10 Aug 2005 19:38:08 -0000	1.55.14.1
@@ -111,6 +111,7 @@ static int io_send_ack(PINT_server_op *s
 {
     int err = -PVFS_EIO;
     job_id_t tmp_id;
+    struct server_configuration_s *user_opts = get_server_config_struct();
         
     PINT_STATE_DEBUG("send_ack");
 
@@ -134,7 +135,7 @@ static int io_send_ack(PINT_server_op *s
         s_op->addr, s_op->encoded.buffer_list, s_op->encoded.size_list,
         s_op->encoded.list_count, s_op->encoded.total_size,
         s_op->tag, s_op->encoded.buffer_type, 0, s_op, 0, js_p,
-        &tmp_id, server_job_context, PVFS2_SERVER_RESPONSE_TIMEOUT);
+        &tmp_id, server_job_context, user_opts->server_job_bmi_timeout);
 
     return err;
 }
@@ -161,6 +162,7 @@ static int io_start_flow(PINT_server_op 
 {
     int err = -PVFS_EIO;
     job_id_t tmp_id;
+    struct server_configuration_s *user_opts = get_server_config_struct();
         
     PINT_STATE_DEBUG("start_flow");
 
@@ -239,7 +241,7 @@ static int io_start_flow(PINT_server_op 
     }
 
     err = job_flow(s_op->u.io.flow_d, s_op, 0, js_p, &tmp_id,
-                   server_job_context, PVFS2_SERVER_FLOW_TIMEOUT);
+                   server_job_context, user_opts->server_job_flow_timeout);
 
     return err;
 }
@@ -295,8 +297,13 @@ static int io_release(PINT_server_op *s_
  */
 static int io_cleanup(PINT_server_op *s_op, job_status_s *js_p)
 {
+    char status_string[64] = {0};
+
     PINT_STATE_DEBUG("cleanup");
 
+    PVFS_strerror_r(s_op->resp.status, status_string, 64);
+    PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "finish (%s)\n", status_string);
+
     if (s_op->u.io.flow_d)
     {
         PINT_flow_free(s_op->u.io.flow_d);
@@ -343,6 +350,7 @@ static int io_send_completion_ack(
 {
     int err = -PVFS_EIO;
     job_id_t tmp_id;
+    struct server_configuration_s *user_opts = get_server_config_struct();
         
     PINT_STATE_DEBUG("send_completion_ack");
 
@@ -385,7 +393,7 @@ static int io_send_completion_ack(
         s_op->addr, s_op->encoded.buffer_list, s_op->encoded.size_list,
         s_op->encoded.list_count, s_op->encoded.total_size, s_op->tag,
         s_op->encoded.buffer_type, 0, s_op, 0, js_p, &tmp_id,
-        server_job_context, PVFS2_SERVER_RESPONSE_TIMEOUT);
+        server_job_context, user_opts->server_job_bmi_timeout);
 
     return err;
 }

Index: lookup.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/lookup.sm,v
diff -p -u -r1.40 -r1.40.2.1
--- lookup.sm	7 Jul 2005 21:43:46 -0000	1.40
+++ lookup.sm	10 Aug 2005 19:38:08 -0000	1.40.2.1
@@ -472,6 +472,18 @@ static int lookup_setup_resp(PINT_server
                  s_op->resp.u.lookup_path.handle_count,
                  s_op->resp.u.lookup_path.attr_count);
 
+    if(js_p->error_code == 0)
+    {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "path: %s, handle: %Lu\n",
+            s_op->req->u.lookup_path.path,
+            Lu(s_op->resp.u.lookup_path.handle_array[s_op->resp.u.lookup_path.handle_count-1]));
+    }
+    else
+    {
+        PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "path: %s, lookup failed\n",
+            s_op->req->u.lookup_path.path);
+    }
+
     return 1;
 }
 

Index: module.mk.in
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/module.mk.in,v
diff -p -u -r1.43 -r1.43.12.1
--- module.mk.in	9 Feb 2005 18:46:30 -0000	1.43
+++ module.mk.in	10 Aug 2005 19:38:08 -0000	1.43.12.1
@@ -32,7 +32,10 @@ ifdef BUILD_SERVER
 		$(DIR)/proto-error.c \
 		$(DIR)/mgmt-remove-object.c \
 		$(DIR)/mgmt-remove-dirent.c \
-		$(DIR)/mgmt-get-dirdata-handle.c
+		$(DIR)/mgmt-get-dirdata-handle.c \
+		$(DIR)/get-eattr.c \
+		$(DIR)/set-eattr.c \
+		$(DIR)/del-eattr.c
 
 	# c files that should be added to server library
 	SERVERSRC += \

Index: prelude.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/prelude.sm,v
diff -p -u -r1.52 -r1.52.2.1
--- prelude.sm	8 Jun 2005 19:30:30 -0000	1.52
+++ prelude.sm	10 Aug 2005 19:38:08 -0000	1.52.2.1
@@ -72,6 +72,8 @@ static int prelude_req_sched(
         "(%p) %s (prelude sm) state: req_sched\n", s_op,
         PINT_map_server_op_to_string(s_op->req->op));
 
+    PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DETAIL_DEBUG, "request\n");
+
     /* this is the first state for every normal pvfs2 server state
      * machine, so we get to do some housekeeping here.  In
      * particular, bump up the reference count on the bmi address that
@@ -106,6 +108,8 @@ static int prelude_getattr_if_needed(
     PVFS_fs_id target_fs_id = PVFS_FS_ID_NULL;
     job_id_t tmp_id;
 
+    PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DETAIL_DEBUG, "start\n");
+
     gossip_debug(GOSSIP_SERVER_DEBUG,
                  "(%p) %s (prelude sm) state: getattr_if_needed\n", s_op,
                  PINT_map_server_op_to_string(s_op->req->op));
@@ -236,14 +240,18 @@ static int prelude_perm_check(
             {
                 js_p->error_code = 0;
             }
-	    else if (s_op->req->op == PVFS_SERV_GETATTR)
+            /* for now we'll assume extended attribs are treated
+             * the same as regular attribs as far as permissions
+             */
+	    else if (s_op->req->op == PVFS_SERV_GETATTR ||
+                    s_op->req->op == PVFS_SERV_GETEATTR)
 	    {
 		/* getting attributes is always ok -- permission
 		 * is checked on the parent directory at read time
 		 */
 		js_p->error_code = 0;
 	    }
-            else /* setattr */
+            else /* setattr, seteattr, seteattr_list */
             {
                 /*
                   NOTE: on other file systems, setattr doesn't

Index: proto-error.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/proto-error.sm,v
diff -p -u -r1.2 -r1.2.14.1
--- proto-error.sm	28 Jul 2004 14:32:56 -0000	1.2
+++ proto-error.sm	10 Aug 2005 19:38:08 -0000	1.2.14.1
@@ -11,6 +11,7 @@
 #include <fcntl.h>
 
 #include "pvfs2-server.h"
+#include "server-config.h"
 
 static int proto_error_cleanup(PINT_server_op *s_op, job_status_s* js_p);
 static int proto_error_init(PINT_server_op *s_op, job_status_s* js_p);
@@ -42,6 +43,7 @@ static int proto_error_init(PINT_server_
 {
     int ret;
     job_id_t tmp_id;
+    struct server_configuration_s *user_opts = get_server_config_struct();
 
     PINT_STATE_DEBUG("init");
 
@@ -80,7 +82,7 @@ static int proto_error_init(PINT_server_
 			    js_p,
 			    &tmp_id,
 			    server_job_context,
-			    PVFS2_SERVER_RESPONSE_TIMEOUT);
+			    user_opts->server_job_bmi_timeout);
 
     return ret;
 }

Index: pvfs2-server.c
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/pvfs2-server.c,v
diff -p -u -r1.181 -r1.181.2.1
--- pvfs2-server.c	29 Jun 2005 14:58:49 -0000	1.181
+++ pvfs2-server.c	10 Aug 2005 19:38:08 -0000	1.181.2.1
@@ -178,7 +178,8 @@ int main(int argc, char **argv)
     fs_conf = ((argc >= optind) ? argv[optind] : NULL);
     server_conf = ((argc >= (optind + 1)) ? argv[optind + 1] : NULL);
 
-    if (PINT_parse_config(&server_config, fs_conf, server_conf))
+    ret = PINT_parse_config(&server_config, fs_conf, server_conf);
+    if (ret < 0)
     {
         gossip_err("Error: Please check your config files.\n");  
         gossip_err("Error: Server aborting.\n");
@@ -190,6 +191,7 @@ int main(int argc, char **argv)
     if (!PINT_config_is_valid_configuration(&server_config))
     {
         gossip_err("Error: Invalid configuration; aborting.\n");
+        ret = -PVFS_EINVAL;
         goto server_shutdown;
     }
 
@@ -204,14 +206,22 @@ int main(int argc, char **argv)
     if (s_server_options.server_remove_storage_space)
     {
         ret = PINT_config_pvfs2_rmspace(&server_config);
-        exit(ret);
+        if(ret < 0)
+        {
+            goto server_shutdown;
+        }
+        return(0);
     }
 
     /* create storage space and exit if requested */
     if (s_server_options.server_create_storage_space)
     {
         ret = PINT_config_pvfs2_mkspace(&server_config);
-        exit(ret);
+        if(ret < 0)
+        {
+            goto server_shutdown;
+        }
+        return(0);
     }
 
     server_job_id_array = (job_id_t *)
@@ -305,7 +315,7 @@ int main(int argc, char **argv)
         if (ret < 0)
         {
             gossip_lerr("pvfs2-server panic; main loop aborting\n");
-            exit(-1);
+            goto server_shutdown;
         }
 
         /*
@@ -381,8 +391,8 @@ int main(int argc, char **argv)
                      * put something here to make it exit for the
                      * moment.  -Phil
                      */
-                    gossip_lerr("Error: NOT HANDLED.\n");
-                    exit(1);
+                    gossip_lerr("Error: post unexpected failure not handled.\n");
+                    goto server_shutdown;
                 }
             }
         }
@@ -390,6 +400,9 @@ int main(int argc, char **argv)
 
   server_shutdown:
     server_shutdown(server_status_flag, ret, siglevel);
+    /* NOTE: the server_shutdown() function does not return; it always ends
+     * by calling exit.  This point in the code should never be reached.
+     */
     return -1;
 }
 
@@ -483,16 +496,29 @@ static int server_initialize(
         freopen("/dev/null", "w", stderr);
 
         assert(server_config.logfile != NULL);
-        if (gossip_enable_file(server_config.logfile, "w") < 0)
+        ret = gossip_enable_file(server_config.logfile, "w");
+        if (ret < 0)
         {
             gossip_lerr("error opening log file %s\n",
                         server_config.logfile);
-            exit(3);
+            return ret;
         }
+        /* log starting message again so it appears in log file, not just
+         * console
+         */
+        gossip_debug(GOSSIP_SERVER_DEBUG,
+           "PVFS2 Server version %s starting.\n", PVFS2_VERSION);
     }
     return ret;
 }
 
+/* server_setup_process_environment()
+ *
+ * performs normal daemon initialization steps
+ *
+ * returns 0 on success, -PVFS_EINVAL on failure (details will be logged to
+ * gossip)
+ */
 static int server_setup_process_environment(int background)
 {
     pid_t new_pid = 0;
@@ -510,6 +536,7 @@ static int server_setup_process_environm
         {
             gossip_err("Failed to create pid file %s: %s\n",
                        s_server_options.pidfile, strerror(errno));
+            return(-PVFS_EINVAL);
         }
     }
 
@@ -517,7 +544,7 @@ static int server_setup_process_environm
     {
         gossip_lerr("cannot change working directory to \"/\" "
                     "(errno = %x). aborting.\n", errno);
-        exit(1);
+        return(-PVFS_EINVAL);
     }
 
     umask(0077);
@@ -529,7 +556,7 @@ static int server_setup_process_environm
         {
             gossip_lerr("error in fork() system call (errno = %x). "
                         "aborting.\n", errno);
-            exit(1);
+            return(-PVFS_EINVAL);
         }
         else if (new_pid > 0)
         {
@@ -541,7 +568,7 @@ static int server_setup_process_environm
         if (new_pid < 0)
         {
             gossip_lerr("error in setsid() system call.  aborting.\n");
-            exit(2);
+            return(-PVFS_EINVAL);
         }
     }
     if (pid_fd >= 0)
@@ -963,7 +990,7 @@ static int server_shutdown(
     if (siglevel == SIGSEGV)
     {
         gossip_err("SIGSEGV: skipping cleanup; exit now!\n");
-        exit(-1);
+        exit(EXIT_FAILURE);
     }
 
     gossip_debug(GOSSIP_SERVER_DEBUG,
@@ -1092,7 +1119,11 @@ static int server_shutdown(
         free(server_job_status_array);
     }
 
-    exit((siglevel == 0) ? -ret : 0);
+    if(siglevel == 0 && ret != 0)
+    {
+        exit(EXIT_FAILURE);
+    }
+    exit(EXIT_SUCCESS);
 }
 
 static void server_sig_handler(int sig)
@@ -1211,6 +1242,11 @@ static int server_parse_cmd_line_args(in
             case 'p':
           do_pidfile:
                 s_server_options.pidfile = optarg;
+                if(optarg[0] != '/')
+                {
+                    gossip_err("Error: pidfile must be specified with an absolute path.\n");
+                    goto parse_cmd_line_args_failure;
+                }
                 break;
             case '?':
             case 'h':
@@ -1569,6 +1605,15 @@ static void init_req_table(void)
             OP_CASE(PVFS_SERV_MGMT_EVENT_MON, "mgmt_event_mon", 
                     PINT_SERVER_CHECK_NONE,
                     PINT_SERVER_ATTRIBS_REQUIRED, &pvfs2_event_mon_sm);
+            OP_CASE(PVFS_SERV_GETEATTR, "geteattr",
+                    PINT_SERVER_CHECK_ATTR,
+                    PINT_SERVER_ATTRIBS_NOT_REQUIRED, &pvfs2_get_eattr_sm);
+            OP_CASE(PVFS_SERV_SETEATTR, "seteattr",
+                    PINT_SERVER_CHECK_ATTR,
+                    PINT_SERVER_ATTRIBS_NOT_REQUIRED, &pvfs2_set_eattr_sm);
+            OP_CASE(PVFS_SERV_DELEATTR, "deleattr",
+                    PINT_SERVER_CHECK_ATTR,
+                    PINT_SERVER_ATTRIBS_NOT_REQUIRED, &pvfs2_del_eattr_sm);
             OP_CASE(PVFS_SERV_JOB_TIMER, "job_timer",
                     PINT_SERVER_CHECK_INVALID,
                     PINT_SERVER_ATTRIBS_REQUIRED, &pvfs2_job_timer_sm);

Index: pvfs2-server.h
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/pvfs2-server.h,v
diff -p -u -r1.117 -r1.117.2.1
--- pvfs2-server.h	11 Jul 2005 20:06:24 -0000	1.117
+++ pvfs2-server.h	10 Aug 2005 19:38:08 -0000	1.117.2.1
@@ -16,9 +16,14 @@
  */
 
 #include <stdint.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
 #include "pvfs2-debug.h"
 #include "pvfs2-storage.h"
 #include "job.h"
+#include "bmi.h"
+#include "src/server/request-scheduler/request-scheduler.h"
 #include "trove.h"
 #include "gossip.h"
 #include "PINT-reqproto-encode.h"
@@ -38,18 +43,23 @@ extern job_context_id server_job_context
 #define PVFS2_SERVER_DEFAULT_TIMEOUT_MS      100
 #define BMI_UNEXPECTED_OP                    999
 
-/* the server will give up on sending a response if the send does not
- * complete in PVFS2_SERVER_RESPONSE_TIMEOUT seconds
+/* BMI operation timeout if not specified in config file */
+#define PVFS2_SERVER_JOB_BMI_TIMEOUT_DEFAULT         30
+/* Flow operation timeout if not specified in config file */
+#define PVFS2_SERVER_JOB_FLOW_TIMEOUT_DEFAULT        30
+/* BMI client side operation timeout if not specified in config file */
+/* NOTE: the default for this timeout is set higher to allow the client to
+ * overcome syncing and queueing delays on the server
  */
-/* TODO: this should be read from a config file */
-#define PVFS2_SERVER_RESPONSE_TIMEOUT         30
-
-/* the server will give up on a flow if more than
- * PVFS2_SERVER_FLOW_TIMEOUT seconds pass without any progress being
- * made on it
+#define PVFS2_CLIENT_JOB_BMI_TIMEOUT_DEFAULT         300
+/* Flow client side operation timeout if not specified in config file */
+#define PVFS2_CLIENT_JOB_FLOW_TIMEOUT_DEFAULT        300
+/* maximum number of times for client to retry restartable operations;
+ * use INT_MAX to approximate infinity (187 years with 2 sec delay)
  */
-/* TODO: this should be read from a config file */
-#define PVFS2_SERVER_FLOW_TIMEOUT             30
+#define PVFS2_CLIENT_RETRY_LIMIT_DEFAULT     (5)
+/* number of milliseconds that clients will delay between retries */
+#define PVFS2_CLIENT_RETRY_DELAY_MS_DEFAULT  2000
 
 /* types of permission checking that a server may need to perform for
  * incoming requests
@@ -260,6 +270,12 @@ struct PINT_server_getattr_op
     PVFS_ds_attributes dirdata_ds_attr;
     uint32_t attrmask;
 };
+
+/* this is used in both set_eattr and get_eattr */
+struct PINT_server_eattr_op
+{
+    void *buffer;
+};
     
 /* This structure is passed into the void *ptr 
  * within the job interface.  Used to tell us where
@@ -317,6 +333,7 @@ typedef struct PINT_server_op
     union
     {
 	/* request-specific scratch spaces for use during processing */
+        struct PINT_server_eattr_op eattr;
         struct PINT_server_getattr_op getattr;
 	struct PINT_server_getconfig_op getconfig;
 	struct PINT_server_lookup_op lookup;
@@ -346,6 +363,42 @@ typedef struct PINT_server_op
     gossip_debug(GOSSIP_SERVER_DEBUG, "(%p) %s state: %s\n", s_op,\
     PINT_map_server_op_to_string(s_op->op), fn_name);
 
+/* PINT_ACCESS_DEBUG()
+ *
+ * macro for consistent printing of access records
+ *
+ * no return value
+ */
+#define PINT_ACCESS_DEBUG(__s_op, __mask, format, f...)                     \
+do {                                                                        \
+    PVFS_handle __handle;                                                   \
+    PVFS_fs_id __fsid;                                                      \
+    int __flag;                                                             \
+    static char __pint_access_buffer[GOSSIP_BUF_SIZE];                      \
+    struct passwd* __pw;                                                    \
+    struct group* __gr;                                                     \
+                                                                            \
+    if ((gossip_debug_on) &&                                                \
+        (gossip_debug_mask & __mask) &&                                     \
+        (gossip_facility))                                                  \
+    {                                                                       \
+        PINT_req_sched_target_handle(__s_op->req, 0, &__handle,             \
+            &__fsid, &__flag);                                              \
+        __pw = getpwuid(__s_op->req->credentials.uid);                      \
+        __gr = getgrgid(__s_op->req->credentials.gid);                      \
+        snprintf(__pint_access_buffer, GOSSIP_BUF_SIZE,                     \
+            "%s.%s@%s H=%Lu S=%p: %s: %s",                                  \
+            ((__pw) ? __pw->pw_name : "UNKNOWN"),                           \
+            ((__gr) ? __gr->gr_name : "UNKNOWN"),                           \
+            BMI_addr_rev_lookup_unexpected(__s_op->addr),                   \
+            Lu(__handle),                                                   \
+            __s_op,                                                         \
+            PINT_map_server_op_to_string(__s_op->req->op),                  \
+            format);                                                        \
+        __gossip_debug(__mask, 'A', __pint_access_buffer, ##f);             \
+    }                                                                       \
+} while(0);
+
 /* server operation state machines */
 extern struct PINT_state_machine_s pvfs2_get_config_sm;
 extern struct PINT_state_machine_s pvfs2_get_attr_sm;
@@ -373,6 +426,11 @@ extern struct PINT_state_machine_s pvfs2
 extern struct PINT_state_machine_s pvfs2_perf_mon_sm;
 extern struct PINT_state_machine_s pvfs2_event_mon_sm;
 extern struct PINT_state_machine_s pvfs2_iterate_handles_sm;
+extern struct PINT_state_machine_s pvfs2_get_eattr_sm;
+extern struct PINT_state_machine_s pvfs2_get_eattr_list_sm;
+extern struct PINT_state_machine_s pvfs2_set_eattr_sm;
+extern struct PINT_state_machine_s pvfs2_set_eattr_list_sm;
+extern struct PINT_state_machine_s pvfs2_del_eattr_sm;
 
 /* nested state machines */
 extern struct PINT_state_machine_s pvfs2_get_attr_work_sm;

Index: rmdirent.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/rmdirent.sm,v
diff -p -u -r1.38 -r1.38.14.1
--- rmdirent.sm	15 Sep 2004 18:46:22 -0000	1.38
+++ rmdirent.sm	10 Aug 2005 19:38:08 -0000	1.38.14.1
@@ -135,6 +135,8 @@ static int rmdirent_verify_parent_metada
 
     PINT_STATE_DEBUG("verify_parent_metadata_and_"
                      "read_directory_entry_handle");
+    PINT_ACCESS_DEBUG(s_op, GOSSIP_ACCESS_DEBUG, "rmdirent entry: %s\n",
+        s_op->req->u.rmdirent.entry);
 
     /* set up key and value structures to read directory entry */
     s_op->key.buffer = Trove_Common_Keys[DIR_ENT_KEY].key;

Index: set-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/set-eattr.sm,v
diff -p -u -r1.1 -r1.1.4.1
--- set-eattr.sm	16 Jun 2005 23:45:46 -0000	1.1
+++ set-eattr.sm	10 Aug 2005 19:38:09 -0000	1.1.4.1
@@ -36,32 +36,32 @@ static inline char *get_object_type(int 
     return obj_types[6];
 }
 
-static int seteattr_cleanup(
+extern PINT_server_trove_keys_s Trove_Common_Keys[];
+
+static int seteattr_verify_eattribs(
     PINT_server_op *s_op, job_status_s *js_p);
 static int seteattr_setobj_eattribs(
     PINT_server_op *s_op, job_status_s *js_p);
-static int seteattr_verify_eattribs(
+static int seteattr_cleanup(
     PINT_server_op *s_op, job_status_s *js_p);
 
-extern PINT_server_trove_keys_s Trove_Common_Keys[];
-
 %%
 
 machine pvfs2_set_eattr_sm(
     prelude,
-    cleanup,
-    verify_eattribs,
+    verify_eattrib,
     setobj_eattrib,
+    cleanup,
     final_response)
 {
     state prelude
     {
         jump pvfs2_prelude_sm;
-        success => verify_eattribs;
+        success => verify_eattrib;
         default => final_response;
     }
 
-    state verify_eattribs
+    state verify_eattrib
     {
         run seteattr_verify_eattribs;
         success => setobj_eattrib;
@@ -95,11 +95,13 @@ machine pvfs2_set_eattr_sm(
  * be we'll try to verify what we can.  We can also disallow setting
  * extended attributes on certain object types if we want.  We might
  * want to prevent access to standard metadata keys.
+ *
  */
 static int seteattr_verify_eattribs(
     PINT_server_op *s_op, job_status_s *js_p)
 {
     PVFS_object_attr *a_p = NULL;
+    int i;
 
     PINT_STATE_DEBUG("verify_eattribs");
 
@@ -108,57 +110,61 @@ static int seteattr_verify_eattribs(
     js_p->error_code = 0;
 
     gossip_debug(GOSSIP_SETEATTR_DEBUG,
-                 "  ext attr read from handle %Lu refers to a %s\n\t"
+                 "  ext attr list write to handle %Lu refers to a %s\n\t"
                  "[owner = %d, group = %d, perms = %o, type = %d]\n",
                  Lu(s_op->req->u.seteattr.handle),
                  get_object_type(a_p->objtype),
                  a_p->owner, a_p->group, a_p->perms, a_p->objtype);
 
-    switch (a_p->objtype)
+    /* if any key is bad, we reject the whole list */
+    for (i = 0; i < s_op->req->u.seteattr.nkey; i++)
     {
-    case PVFS_TYPE_METAFILE :
-        if (!strncmp(s_op->req->u.seteattr.key.buffer,
-                    Trove_Common_Keys[METAFILE_HANDLES_KEY].key,
-                    s_op->req->u.seteattr.key.buffer_sz) ||
-            !strncmp(s_op->req->u.seteattr.key.buffer,
-                    Trove_Common_Keys[METAFILE_DIST_KEY].key,
-                    s_op->req->u.seteattr.key.buffer_sz))
+        switch (a_p->objtype)
         {
-            /* can't set these keys with this request */
-            js_p->error_code = -PVFS_EINVAL;
-            return -PVFS_EINVAL;
+        case PVFS_TYPE_METAFILE :
+            if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
+                        Trove_Common_Keys[METAFILE_HANDLES_KEY].key,
+                        s_op->req->u.seteattr.key[i].buffer_sz) ||
+                !strncmp(s_op->req->u.seteattr.key[i].buffer,
+                        Trove_Common_Keys[METAFILE_DIST_KEY].key,
+                        s_op->req->u.seteattr.key[i].buffer_sz))
+            {
+                /* can't set these keys with this request */
+                js_p->error_code = -PVFS_EINVAL;
+                return -PVFS_EINVAL;
+            }
+        case PVFS_TYPE_SYMLINK :
+            if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
+                        Trove_Common_Keys[SYMLINK_TARGET_KEY].key,
+                        s_op->req->u.seteattr.key[i].buffer_sz))
+            {
+                /* can't set these keys with this request */
+                js_p->error_code = -PVFS_EINVAL;
+                return -PVFS_EINVAL;
+            }
+        case PVFS_TYPE_DIRECTORY :
+            if (!strncmp(s_op->req->u.seteattr.key[i].buffer,
+                        Trove_Common_Keys[DIR_ENT_KEY].key,
+                        s_op->req->u.seteattr.key[i].buffer_sz))
+            {
+                /* can't set these keys with this request */
+                js_p->error_code = -PVFS_EINVAL;
+                return -PVFS_EINVAL;
+            }
+        default :
+            /* no holds barred for other types */
+            ;
         }
-    case PVFS_TYPE_SYMLINK :
-        if (!strncmp(s_op->req->u.seteattr.key.buffer,
-                    Trove_Common_Keys[SYMLINK_TARGET_KEY].key,
-                    s_op->req->u.seteattr.key.buffer_sz))
-        {
-            /* can't set these keys with this request */
-            js_p->error_code = -PVFS_EINVAL;
-            return -PVFS_EINVAL;
-        }
-    case PVFS_TYPE_DIRECTORY :
-        if (!strncmp(s_op->req->u.seteattr.key.buffer,
-                    Trove_Common_Keys[DIR_ENT_KEY].key,
-                    s_op->req->u.seteattr.key.buffer_sz))
+
+        /* no one is allowed to set standard attribs with this op */
+        if (!strncmp((void *)s_op->req->u.seteattr.key[i].buffer,
+                    (void *)&s_op->req->u.seteattr.handle,
+                    sizeof(s_op->req->u.seteattr.handle)))
         {
             /* can't set these keys with this request */
             js_p->error_code = -PVFS_EINVAL;
             return -PVFS_EINVAL;
         }
-    default :
-        /* no holds barred for other types */
-        ;
-    }
-
-    /* no one is allowed to set standard attribs with this op */
-    if (!strncmp((void *)s_op->req->u.seteattr.key.buffer,
-                (void *)&s_op->req->u.seteattr.handle,
-                sizeof(s_op->req->u.seteattr.handle)))
-    {
-        /* can't set these keys with this request */
-        js_p->error_code = -PVFS_EINVAL;
-        return -PVFS_EINVAL;
     }
 
     return 1;
@@ -167,41 +173,52 @@ static int seteattr_verify_eattribs(
 /*
  * This is where the actual extended attrib gets written.
  * Not much to this, its pretty straight-forward.
+ * 
+ * NOTE: we need to check the value of s_op->req->u.seteattr.flags to determine
+ * the following:
+ *
+ * if (flags & PVFS_XATTR_CREATE)
+ *  we need to make sure that the attribute does not exist. (pure create)
+ * else if (flags & PVFS_XATTR_REPLACE)
+ *  we need to make sure that the attribute does exist. (pure replace)
+ * else it is default operation as before.
+ * We translate this to an internal trove flag 
+ *  (TROVE_NOOVERWRITE, TROVE_ONLYOVERWRITE)
  */
-static int seteattr_setobj_eattribs(PINT_server_op *s_op, job_status_s *js_p)
+static int seteattr_setobj_eattribs(
+        PINT_server_op *s_op, job_status_s *js_p)
 {
     int ret = 0;
+    PVFS_ds_flags trove_flags = 0;
     job_id_t j_id;
     struct server_configuration_s *user_opts = get_server_config_struct();
 
     PINT_STATE_DEBUG("seteattr_setobj_eattribs");
 
-    /* set up key and value structure for keyval write */
-    s_op->key.buffer = s_op->req->u.seteattr.key.buffer;
-    s_op->key.buffer_sz = s_op->req->u.seteattr.key.buffer_sz;
-
-    s_op->val.buffer = s_op->req->u.seteattr.val.buffer;
-    s_op->val.buffer_sz = s_op->req->u.seteattr.val.buffer_sz;
-
     gossip_debug(
-        GOSSIP_SETATTR_DEBUG,
-        "  writing %s [%Lu,%d,len %d]\n",
-        (char *)s_op->key.buffer,
+        GOSSIP_SETEATTR_DEBUG,
+        "  writing keylist [%Lu,%d,len %d flags %d]\n",
         Lu(s_op->req->u.seteattr.handle),
         s_op->req->u.seteattr.fs_id,
-        s_op->val.buffer_sz);
-
-    printf("keybuf %x keylex %d valbuf %x vallen %d\n",
-            s_op->key.buffer, s_op->key.buffer_sz,
-            s_op->val.buffer, s_op->val.buffer_sz);
+        s_op->req->u.seteattr.nkey, s_op->req->u.seteattr.flags);
 
-    ret = job_trove_keyval_write(
+    if (s_op->req->u.seteattr.flags & PVFS_XATTR_CREATE)
+    {
+        trove_flags = TROVE_NOOVERWRITE;
+    }
+    else if (s_op->req->u.seteattr.flags & PVFS_XATTR_REPLACE)
+    {
+        trove_flags = TROVE_ONLYOVERWRITE;
+    }
+    trove_flags |= PINT_config_get_trove_sync_meta(user_opts, 
+            s_op->req->u.seteattr.fs_id);
+    ret = job_trove_keyval_write_list(
         s_op->req->u.seteattr.fs_id,
         s_op->req->u.seteattr.handle,
-        &(s_op->key),
-        &(s_op->val),
-        PINT_config_get_trove_sync_meta(
-            user_opts, s_op->req->u.seteattr.fs_id),
+        s_op->req->u.seteattr.key,
+        s_op->req->u.seteattr.val,
+        s_op->req->u.seteattr.nkey,
+        trove_flags,
         NULL,
         s_op,
         0,
@@ -226,11 +243,7 @@ static int seteattr_setobj_eattribs(PINT
 static int seteattr_cleanup(PINT_server_op *s_op, job_status_s *js_p)
 {
     PINT_STATE_DEBUG("seteattr_cleanup");
-
-    printf("keybuf %x keylex %d valbuf %x vallen %d\n",
-            s_op->key.buffer, s_op->key.buffer_sz,
-            s_op->val.buffer, s_op->val.buffer_sz);
-
+    /* do I need to free memory from decoding key and val?*/
     return(server_state_machine_complete(s_op));
 }
 

Index: setparam.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2/src/server/setparam.sm,v
diff -p -u -r1.22 -r1.22.14.1
--- setparam.sm	7 Dec 2004 13:53:45 -0000	1.22
+++ setparam.sm	10 Aug 2005 19:38:09 -0000	1.22.14.1
@@ -69,7 +69,10 @@ static int setparam_work(PINT_server_op 
     uint64_t tmp_mask = 0;
     int32_t old_api_mask = 0, old_op_mask = 0;
     PVFS_handle tmp_handle = PVFS_HANDLE_NULL;
-
+    struct server_configuration_s *user_opts;
+    struct filesystem_configuration_s *fs_conf;
+    char buf[16] = {0};
+ 
     PINT_STATE_DEBUG("work");
 
     switch(s_op->req->u.mgmt_setparam.param)
@@ -119,6 +122,42 @@ static int setparam_work(PINT_server_op 
                 (int32_t)(s_op->req->u.mgmt_setparam.value >> 32));
             s_op->resp.u.mgmt_setparam.old_value = old_api_mask +
                 ((int64_t)old_op_mask << 32);
+            js_p->error_code = 0;
+            return(1);
+        case PVFS_SERV_PARAM_SYNC_META:
+            user_opts = get_server_config_struct();
+            fs_conf = PINT_config_find_fs_id(user_opts, 
+                s_op->req->u.mgmt_setparam.fs_id);
+            if(fs_conf)
+            {
+                if(s_op->req->u.mgmt_setparam.value)
+                    fs_conf->trove_sync_meta = TROVE_SYNC;
+                else
+                    fs_conf->trove_sync_meta = 0;
+            }
+            js_p->error_code = 0;
+            return(1);
+        case PVFS_SERV_PARAM_SYNC_DATA:
+            user_opts = get_server_config_struct();
+            fs_conf = PINT_config_find_fs_id(user_opts, 
+                s_op->req->u.mgmt_setparam.fs_id);
+            if(fs_conf)
+            {
+                if(s_op->req->u.mgmt_setparam.value)
+                {
+                    snprintf(buf, 16, "%d,%d", s_op->req->u.mgmt_setparam.fs_id,
+                             TROVE_SYNC);
+                    PINT_flow_setinfo(NULL, FLOWPROTO_DATA_SYNC_MODE, buf);
+                    fs_conf->trove_sync_data = TROVE_SYNC;
+                }
+                else
+                {
+                    snprintf(buf, 16, "%d,%d", s_op->req->u.mgmt_setparam.fs_id,
+                             0);
+                    PINT_flow_setinfo(NULL, FLOWPROTO_DATA_SYNC_MODE, buf);
+                    fs_conf->trove_sync_data = 0;
+                }
+            }
             js_p->error_code = 0;
             return(1);
         case PVFS_SERV_PARAM_MODE:

--- get-eattr-list.sm	2005-08-10 15:38:09.000000000 -0400
+++ /dev/null	2003-01-30 05:24:37.000000000 -0500
@@ -1,210 +0,0 @@
-/* 
- * (C) 2001 Clemson University and The University of Chicago 
- *
- * See COPYING in top-level directory.
- */
-
-/* pvfs2_get_eattr_sm
- *
- * This state machine handles incoming server getattr operations.  These
- * are the operations sent by PVFS_sys_getattr() among others.
- *
- * The pvfs2_prelude_sm is responsible for reading the actual metadata
- * to begin with, because it does this as part of the permission checking
- * process.
- */
-
-#include <string.h>
-#include <assert.h>
-
-#include "server-config.h"
-#include "pvfs2-server.h"
-#include "pvfs2-attr.h"
-#include "pvfs2-types.h"
-#include "pvfs2-types-debug.h"
-#include "pvfs2-util.h"
-#include "pint-util.h"
-
-static inline char *get_object_type(int objtype)
-{
-    static char *obj_types[] =
-    {
-        "NONE", "METAFILE", "DATAFILE",
-        "DIRECTORY", "SYMLINK", "DIRDATA", "UNKNOWN"
-    };
-
-    switch(objtype)
-    {
-        case PVFS_TYPE_NONE:
-            return obj_types[0];
-        case PVFS_TYPE_METAFILE:
-            return obj_types[1];
-        case PVFS_TYPE_DATAFILE:
-            return obj_types[2];
-        case PVFS_TYPE_DIRECTORY:
-            return obj_types[3];
-        case PVFS_TYPE_SYMLINK:
-            return obj_types[4];
-        case PVFS_TYPE_DIRDATA:
-            return obj_types[5];
-    }
-    return obj_types[6];
-}
-
-static int geteattr_list_setup_resp(
-    PINT_server_op *s_op, job_status_s *js_p);
-static int geteattr_list_read_eattrib(
-    PINT_server_op *s_op, job_status_s *js_p);
-static int geteattr_list_check_resp(
-    PINT_server_op *s_op, job_status_s *js_p);
-static int geteattr_list_cleanup(
-    PINT_server_op *s_op, job_status_s *js_p);
-
-extern PINT_server_trove_keys_s Trove_Common_Keys[];
-
-%%
-
-machine pvfs2_get_eattr_list_sm(
-    prelude,
-    setup_resp,
-    read_eattrib,
-    check_resp,
-    final_response,
-    cleanup)
-{
-    state prelude
-    {
-        jump pvfs2_prelude_sm;
-        success => setup_resp;
-        default => final_response;
-    }
-
-    state setup_resp
-    {
-        run geteattr_list_setup_resp;
-        success => read_eattrib;
-        default => final_response;
-    }
-
-    state read_eattrib
-    {
-        run geteattr_list_read_eattrib;
-        default => check_resp;
-    }
-
-    state check_resp
-    {
-        run geteattr_list_check_resp;
-        default => final_response;
-    }
-
-    state final_response
-    {
-        jump pvfs2_final_response_sm;
-        default => cleanup;
-    }
-
-    state cleanup
-    {
-        run geteattr_list_cleanup;
-        default => terminate;
-    }
-}
-
-%%
-
-/*
- * geteattr_list_setup_resp()
- * Set up the response - allocate needed resources
- */
-static int geteattr_list_setup_resp(PINT_server_op *s_op, job_status_s *js_p)
-{
-    int i, tsz;
-    PINT_STATE_DEBUG("setup_resp");
-    s_op->resp.u.geteattr_list.val =
-        malloc(s_op->req->u.geteattr_list.nkey*sizeof(PVFS_ds_keyval));
-    if (!s_op->resp.u.geteattr_list.val)
-        return -PVFS_ENOMEM;
-    for (i = 0, tsz = 0; i < s_op->req->u.geteattr_list.nkey; i++)
-        tsz += s_op->req->u.geteattr_list.valsz[i];
-    s_op->u.eattr_list.buffer = malloc(tsz);
-    if (!s_op->u.eattr_list.buffer)
-    {
-        free (s_op->resp.u.geteattr_list.val);
-        return -PVFS_ENOMEM;
-    }
-    for (i = 0, tsz = 0; i < s_op->req->u.geteattr_list.nkey; i++)
-    {
-        s_op->resp.u.geteattr_list.val[i].buffer_sz =
-            s_op->req->u.geteattr_list.valsz[i];
-        s_op->resp.u.geteattr_list.val[i].buffer =
-            s_op->u.eattr_list.buffer + tsz;
-        tsz += s_op->req->u.geteattr_list.valsz[i];
-    }
-    return 1;
-}
-
-/*
- * geteattr_list_read_eattrib()
- * Here is where the eattrib get read.  Not much to this.
- */
-static int geteattr_list_read_eattrib(
-    PINT_server_op *s_op, job_status_s *js_p)
-{
-    int ret = -PVFS_EINVAL;
-    job_id_t i;
-
-    PINT_STATE_DEBUG("read_eattrib");
-
-    js_p->error_code = 0;
-
-    ret = job_trove_keyval_read_list(
-        s_op->req->u.geteattr_list.fs_id,
-        s_op->req->u.geteattr_list.handle,
-        s_op->req->u.geteattr_list.key,
-        s_op->resp.u.geteattr_list.val,
-        s_op->req->u.geteattr_list.nkey,
-        0,
-        NULL,
-        s_op,
-        0,
-        js_p,
-        &i,
-        server_job_context);
-
-    return ret;
-}
-
-/*
- * geteattr_list_check_resp()
- * Check the response - handle any errors
- */
-static int geteattr_list_check_resp(PINT_server_op *s_op, job_status_s *js_p)
-{
-    PINT_STATE_DEBUG("check_resp");
-    return 1;
-}
-
-/* geteattr_list_cleanup()
- * free resources alloc'd by state machine
- */
-static int geteattr_list_cleanup(PINT_server_op *s_op, job_status_s *js_p)
-{
-    PINT_STATE_DEBUG("geteattr_list_cleanup");
-    if (s_op->resp.u.geteattr_list.val)
-        free(s_op->resp.u.geteattr_list.val);
-    if (s_op->u.eattr_list.buffer)
-        free(s_op->u.eattr_list.buffer);
-    return(server_state_machine_complete(s_op));
-}
-
-/*
- * Local variables:
- *  mode: c
- *  c-indent-level: 4
- *  c-basic-offset: 4
- * End:
- *
- * vim: ft=c ts=8 sts=4 sw=4 expandtab
- */
-

--- set-eattr-list.sm	2005-08-10 15:38:09.000000000 -0400
+++ /dev/null	2003-01-30 05:24:37.000000000 -0500
@@ -1,237 +0,0 @@
-/* 
- * (C) 2001 Clemson University and The University of Chicago 
- *
- * See COPYING in top-level directory.
- */
-
-#include <string.h>
-#include <assert.h>
-
-#include "server-config.h"
-#include "pvfs2-server.h"
-#include "pvfs2-attr.h"
-
-static inline char *get_object_type(int objtype)
-{
-    static char *obj_types[] =
-    {
-         "NONE", "METAFILE", "DATAFILE",
-         "DIRECTORY", "SYMLINK", "DIRDATA", "UNKNOWN"
-    };
-    switch(objtype)
-    {
-    case PVFS_TYPE_NONE:
-         return obj_types[0];
-    case PVFS_TYPE_METAFILE:
-         return obj_types[1];
-    case PVFS_TYPE_DATAFILE:
-         return obj_types[2];
-    case PVFS_TYPE_DIRECTORY:
-         return obj_types[3];
-    case PVFS_TYPE_SYMLINK:
-         return obj_types[4];
-    case PVFS_TYPE_DIRDATA:
-         return obj_types[5];
-    }
-    return obj_types[6];
-}
-
-extern PINT_server_trove_keys_s Trove_Common_Keys[];
-
-static int seteattr_list_verify_eattribs(
-    PINT_server_op *s_op, job_status_s *js_p);
-static int seteattr_list_setobj_eattribs(
-    PINT_server_op *s_op, job_status_s *js_p);
-static int seteattr_list_cleanup(
-    PINT_server_op *s_op, job_status_s *js_p);
-
-%%
-
-machine pvfs2_set_eattr_list_sm(
-    prelude,
-    verify_eattrib,
-    setobj_eattrib,
-    cleanup,
-    final_response)
-{
-    state prelude
-    {
-        jump pvfs2_prelude_sm;
-        success => verify_eattrib;
-        default => final_response;
-    }
-
-    state verify_eattrib
-    {
-        run seteattr_list_verify_eattribs;
-        success => setobj_eattrib;
-        default => final_response;
-    }
-
-    state setobj_eattrib
-    {
-        run seteattr_list_setobj_eattribs;
-        default => final_response;
-    }
-
-    state final_response
-    {
-        jump pvfs2_final_response_sm;
-        default => cleanup;
-    }
-
-    state cleanup
-    {
-        run seteattr_list_cleanup;
-        default => terminate;
-    }
-}
-
-%%
-
-/*
- * This routine really just does debugging - can print out info about
- * the target of the operation.  There are few things to verify here
- * be we'll try to verify what we can.  We can also disallow setting
- * extended attributes on certain object types if we want.  We might
- * want to prevent access to standard metadata keys.
- */
-static int seteattr_list_verify_eattribs(
-    PINT_server_op *s_op, job_status_s *js_p)
-{
-    PVFS_object_attr *a_p = NULL;
-    int i;
-
-    PINT_STATE_DEBUG("verify_eattribs");
-
-    a_p = &s_op->attr;
-
-    js_p->error_code = 0;
-
-    gossip_debug(GOSSIP_SETEATTR_DEBUG,
-                 "  ext attr list write to handle %Lu refers to a %s\n\t"
-                 "[owner = %d, group = %d, perms = %o, type = %d]\n",
-                 Lu(s_op->req->u.seteattr.handle),
-                 get_object_type(a_p->objtype),
-                 a_p->owner, a_p->group, a_p->perms, a_p->objtype);
-
-    /* if any key is bad, we reject the whole list */
-    for (i = 0; i < s_op->req->u.seteattr_list.nkey; i++)
-    {
-        switch (a_p->objtype)
-        {
-        case PVFS_TYPE_METAFILE :
-            if (!strncmp(s_op->req->u.seteattr_list.key[i].buffer,
-                        Trove_Common_Keys[METAFILE_HANDLES_KEY].key,
-                        s_op->req->u.seteattr_list.key[i].buffer_sz) ||
-                !strncmp(s_op->req->u.seteattr_list.key[i].buffer,
-                        Trove_Common_Keys[METAFILE_DIST_KEY].key,
-                        s_op->req->u.seteattr_list.key[i].buffer_sz))
-            {
-                /* can't set these keys with this request */
-                js_p->error_code = -PVFS_EINVAL;
-                return -PVFS_EINVAL;
-            }
-        case PVFS_TYPE_SYMLINK :
-            if (!strncmp(s_op->req->u.seteattr_list.key[i].buffer,
-                        Trove_Common_Keys[SYMLINK_TARGET_KEY].key,
-                        s_op->req->u.seteattr_list.key[i].buffer_sz))
-            {
-                /* can't set these keys with this request */
-                js_p->error_code = -PVFS_EINVAL;
-                return -PVFS_EINVAL;
-            }
-        case PVFS_TYPE_DIRECTORY :
-            if (!strncmp(s_op->req->u.seteattr_list.key[i].buffer,
-                        Trove_Common_Keys[DIR_ENT_KEY].key,
-                        s_op->req->u.seteattr_list.key[i].buffer_sz))
-            {
-                /* can't set these keys with this request */
-                js_p->error_code = -PVFS_EINVAL;
-                return -PVFS_EINVAL;
-            }
-        default :
-            /* no holds barred for other types */
-            ;
-        }
-
-        /* no one is allowed to set standard attribs with this op */
-        if (!strncmp((void *)s_op->req->u.seteattr_list.key[i].buffer,
-                    (void *)&s_op->req->u.seteattr_list.handle,
-                    sizeof(s_op->req->u.seteattr_list.handle)))
-        {
-            /* can't set these keys with this request */
-            js_p->error_code = -PVFS_EINVAL;
-            return -PVFS_EINVAL;
-        }
-    }
-
-    return 1;
-}
-
-/*
- * This is where the actual extended attrib gets written.
- * Not much to this, its pretty straight-forward.
- */
-static int seteattr_list_setobj_eattribs(
-        PINT_server_op *s_op, job_status_s *js_p)
-{
-    int ret = 0;
-    job_id_t j_id;
-    struct server_configuration_s *user_opts = get_server_config_struct();
-
-    PINT_STATE_DEBUG("seteattr_list_setobj_eattribs");
-
-    gossip_debug(
-        GOSSIP_SETEATTR_DEBUG,
-        "  writing keylist [%Lu,%d,len %d]\n",
-        Lu(s_op->req->u.seteattr_list.handle),
-        s_op->req->u.seteattr_list.fs_id,
-        s_op->req->u.seteattr_list.nkey);
-
-    ret = job_trove_keyval_write_list(
-        s_op->req->u.seteattr_list.fs_id,
-        s_op->req->u.seteattr_list.handle,
-        s_op->req->u.seteattr_list.key,
-        s_op->req->u.seteattr_list.val,
-        s_op->req->u.seteattr_list.nkey,
-        PINT_config_get_trove_sync_meta(
-            user_opts, s_op->req->u.seteattr_list.fs_id),
-        NULL,
-        s_op,
-        0,
-        js_p,
-        &j_id,
-        server_job_context);
-
-    return ret;
-}
-
-/*
- * Function: setattr_cleanup
- *
- * Params:   server_op *b, 
- *           job_status_s *js_p
- *
- * Returns:  int
- *
- * Synopsis: free memory and return
- *           
- */
-static int seteattr_list_cleanup(PINT_server_op *s_op, job_status_s *js_p)
-{
-    PINT_STATE_DEBUG("seteattr_list_cleanup");
-    /* do I need to free memory from decoding key and val?*/
-    return(server_state_machine_complete(s_op));
-}
-
-/*
- * Local variables:
- *  mode: c
- *  c-indent-level: 4
- *  c-basic-offset: 4
- * End:
- *
- * vim: ft=c ts=8 sts=4 sw=4 expandtab
- */
-



More information about the PVFS2-CVS mailing list