These patches are based on part of the functionality Murali originally
contributed in this email thread:
http://www.beowulf-underground.org/pipermail/pvfs2-developers/2005-November/001624.html
Thanks for the patches!
No, thank you - you did all of the hard work!
Examples:
[EMAIL PROTECTED] setfattr -n "user.pvfs2.num_dfiles" -v "1"
/mnt/pvfs2/directory
[EMAIL PROTECTED] setfattr -n "user.pvfs2.dist_name" -v "basic_dist"
/mnt/pvfs2/directory
[EMAIL PROTECTED] setfattr -n "user.pvfs2.dist_params" -v "strip_size:4096"
/mnt/pvfs2/directory
Can you also add an entry in the FAQ for these if you haven't done it
already?
I have attached an updated version of the patch that adds some faq
entries for the examples above.
-Phil
diff -Naur pvfs2-old/include/pvfs2-sysint.h pvfs2/include/pvfs2-sysint.h
--- pvfs2-old/include/pvfs2-sysint.h 2006-05-22 23:50:11.000000000 +0200
+++ pvfs2/include/pvfs2-sysint.h 2006-06-07 03:48:46.000000000 +0200
@@ -36,8 +36,10 @@
PVFS_time mtime;
PVFS_time ctime;
PVFS_size size;
- PVFS2_ALIGN_VAR(char *, link_target); /* NOTE: caller must free this */
+ PVFS2_ALIGN_VAR(char *, link_target);/* NOTE: caller must free if valid */
PVFS2_ALIGN_VAR(int32_t, dfile_count); /* Changed to int32_t so that size of structure does not change */
+ PVFS2_ALIGN_VAR(char*, dist_name); /* NOTE: caller must free if valid */
+ PVFS2_ALIGN_VAR(char*, dist_params); /* NOTE: caller must free if valid */
PVFS_size dirent_count;
PVFS_ds_type objtype;
uint32_t mask;
diff -Naur pvfs2-old/include/pvfs2-types.h pvfs2/include/pvfs2-types.h
--- pvfs2-old/include/pvfs2-types.h 2006-05-29 18:21:10.000000000 +0200
+++ pvfs2/include/pvfs2-types.h 2006-06-07 03:48:46.000000000 +0200
@@ -245,6 +245,7 @@
#define PVFS_ATTR_SYS_LNK_TARGET (1 << 24)
#define PVFS_ATTR_SYS_DFILE_COUNT (1 << 25)
#define PVFS_ATTR_SYS_DIRENT_COUNT (1 << 26)
+#define PVFS_ATTR_SYS_DIR_HINT (1 << 27)
#define PVFS_ATTR_SYS_UID (1 << 0)
#define PVFS_ATTR_SYS_GID (1 << 1)
#define PVFS_ATTR_SYS_PERM (1 << 2)
@@ -261,10 +262,14 @@
#define PVFS_ATTR_SYS_ALL \
(PVFS_ATTR_SYS_COMMON_ALL | PVFS_ATTR_SYS_SIZE | \
PVFS_ATTR_SYS_LNK_TARGET | PVFS_ATTR_SYS_DFILE_COUNT | \
+ PVFS_ATTR_SYS_DIRENT_COUNT | PVFS_ATTR_SYS_DIR_HINT)
+#define PVFS_ATTR_SYS_ALL_NOHINT \
+(PVFS_ATTR_SYS_COMMON_ALL | PVFS_ATTR_SYS_SIZE | \
+ PVFS_ATTR_SYS_LNK_TARGET | PVFS_ATTR_SYS_DFILE_COUNT | \
PVFS_ATTR_SYS_DIRENT_COUNT)
#define PVFS_ATTR_SYS_ALL_NOSIZE \
(PVFS_ATTR_SYS_COMMON_ALL | PVFS_ATTR_SYS_LNK_TARGET | \
- PVFS_ATTR_SYS_DFILE_COUNT | PVFS_ATTR_SYS_DIRENT_COUNT)
+ PVFS_ATTR_SYS_DFILE_COUNT | PVFS_ATTR_SYS_DIRENT_COUNT | PVFS_ATTR_SYS_DIR_HINT)
#define PVFS_ATTR_SYS_ALL_SETABLE \
(PVFS_ATTR_SYS_COMMON_ALL-PVFS_ATTR_SYS_TYPE)
diff -Naur pvfs2-old/src/apps/admin/pvfs2-cp.c pvfs2/src/apps/admin/pvfs2-cp.c
--- pvfs2-old/src/apps/admin/pvfs2-cp.c 2006-05-29 18:16:36.000000000 +0200
+++ pvfs2/src/apps/admin/pvfs2-cp.c 2006-06-07 03:48:46.000000000 +0200
@@ -558,7 +558,7 @@
if ((ret == 0) && (open_type == OPEN_SRC))
{
memset(&resp_getattr, 0, sizeof(PVFS_sysresp_getattr));
- ret = PVFS_sys_getattr(resp_lookup.ref, PVFS_ATTR_SYS_ALL,
+ ret = PVFS_sys_getattr(resp_lookup.ref, PVFS_ATTR_SYS_ALL_NOHINT,
credentials, &resp_getattr);
if (ret)
{
diff -Naur pvfs2-old/src/apps/admin/pvfs2-fs-dump.c pvfs2/src/apps/admin/pvfs2-fs-dump.c
--- pvfs2-old/src/apps/admin/pvfs2-fs-dump.c 2006-05-29 18:16:36.000000000 +0200
+++ pvfs2/src/apps/admin/pvfs2-fs-dump.c 2006-06-07 03:49:37.000000000 +0200
@@ -439,7 +439,7 @@
pref = lookup_resp.ref;
PVFS_sys_getattr(pref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp);
@@ -505,7 +505,7 @@
entry_ref.fs_id = cur_fs;
if ((ret = PVFS_sys_getattr(entry_ref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp)) != 0)
{
diff -Naur pvfs2-old/src/apps/admin/pvfs2-fsck.c pvfs2/src/apps/admin/pvfs2-fsck.c
--- pvfs2-old/src/apps/admin/pvfs2-fsck.c 2006-05-29 18:16:36.000000000 +0200
+++ pvfs2/src/apps/admin/pvfs2-fsck.c 2006-06-07 03:50:11.000000000 +0200
@@ -449,7 +449,7 @@
pref = lookup_resp.ref;
PVFS_sys_getattr(pref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp);
@@ -565,7 +565,7 @@
}
ret = PVFS_sys_getattr(entry_ref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp);
if (ret != 0) {
@@ -795,7 +795,7 @@
handle_ref.fs_id = cur_fs;
ret = PVFS_sys_getattr(handle_ref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp);
if (ret) {
@@ -876,7 +876,7 @@
handle_ref.fs_id = cur_fs;
ret = PVFS_sys_getattr(handle_ref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp);
if (ret) {
@@ -987,7 +987,7 @@
handle_ref.fs_id = cur_fs;
ret = PVFS_sys_getattr(handle_ref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
creds,
&getattr_resp);
if (ret) {
diff -Naur pvfs2-old/src/apps/admin/pvfs2-ls.c pvfs2/src/apps/admin/pvfs2-ls.c
--- pvfs2-old/src/apps/admin/pvfs2-ls.c 2006-05-27 20:55:43.000000000 +0200
+++ pvfs2/src/apps/admin/pvfs2-ls.c 2006-06-07 03:48:46.000000000 +0200
@@ -367,7 +367,7 @@
memset(&getattr_response,0, sizeof(PVFS_sysresp_getattr));
PVFS_util_gen_credentials(&credentials);
- ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL,
+ ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL_NOHINT,
&credentials, &getattr_response);
if (ret)
{
@@ -415,7 +415,7 @@
pvfs_dirent_incount = MAX_NUM_DIRENTS;
memset(&getattr_response,0,sizeof(PVFS_sysresp_getattr));
- if (PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL,
+ if (PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL_NOHINT,
&credentials, &getattr_response) == 0)
{
if ((getattr_response.attr.objtype == PVFS_TYPE_METAFILE) ||
diff -Naur pvfs2-old/src/apps/admin/pvfs2-stat.c pvfs2/src/apps/admin/pvfs2-stat.c
--- pvfs2-old/src/apps/admin/pvfs2-stat.c 2006-03-09 22:17:48.000000000 +0100
+++ pvfs2/src/apps/admin/pvfs2-stat.c 2006-06-07 03:48:46.000000000 +0200
@@ -225,7 +225,7 @@
ref.fs_id = fs_id;
ret = PVFS_sys_getattr(ref,
- PVFS_ATTR_SYS_ALL,
+ PVFS_ATTR_SYS_ALL_NOHINT,
(PVFS_credentials *) credentials,
&getattr_response);
diff -Naur pvfs2-old/src/apps/admin/pvfs2-viewdist.c pvfs2/src/apps/admin/pvfs2-viewdist.c
--- pvfs2-old/src/apps/admin/pvfs2-viewdist.c 2006-05-29 18:16:36.000000000 +0200
+++ pvfs2/src/apps/admin/pvfs2-viewdist.c 2006-06-07 03:48:46.000000000 +0200
@@ -404,7 +404,7 @@
ref.fs_id = resp_lookup.ref.fs_id;
memset(&resp_getattr, 0, sizeof(PVFS_sysresp_getattr));
- ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL,
+ ret = PVFS_sys_getattr(ref, PVFS_ATTR_SYS_ALL_NOHINT,
credentials, &resp_getattr);
if (ret)
{
diff -Naur pvfs2-old/src/client/sysint/client-state-machine.h pvfs2/src/client/sysint/client-state-machine.h
--- pvfs2-old/src/client/sysint/client-state-machine.h 2006-05-29 18:21:10.000000000 +0200
+++ pvfs2/src/client/sysint/client-state-machine.h 2006-06-07 03:48:46.000000000 +0200
@@ -95,6 +95,8 @@
PVFS_sysresp_mkdir *mkdir_resp; /* in/out parameter */
PVFS_sys_attr sys_attr; /* input parameter */
+ PVFS_ds_keyval *key_array;
+ PVFS_ds_keyval *val_array;
int retry_count;
int stored_error_code;
PVFS_handle metafile_handle;
diff -Naur pvfs2-old/src/client/sysint/sys-create.sm pvfs2/src/client/sysint/sys-create.sm
--- pvfs2-old/src/client/sysint/sys-create.sm 2006-05-22 23:50:13.000000000 +0200
+++ pvfs2/src/client/sysint/sys-create.sm 2006-06-07 03:48:46.000000000 +0200
@@ -24,6 +24,7 @@
#include "pint-distribution.h"
#include "PINT-reqproto-encode.h"
#include "pint-util.h"
+#include "pint-dist-utils.h"
#include "ncache.h"
#include "pvfs2-internal.h"
@@ -417,7 +418,7 @@
PINT_SM_GETATTR_STATE_FILL(
sm_p->getattr,
sm_p->object_ref,
- PVFS_ATTR_COMMON_ALL,
+ PVFS_ATTR_COMMON_ALL|PVFS_ATTR_DIR_HINT,
PVFS_TYPE_DIRECTORY,
0);
@@ -1042,6 +1043,9 @@
PINT_client_sm *sm_p, job_status_s *js_p)
{
PVFS_object_attr *attr = NULL;
+ int num_dfiles_requested_override = 0;
+ PINT_dist *current_dist;
+ int ret = 0;
gossip_debug(GOSSIP_CLIENT_DEBUG, "create state: parent_getattr_inspect\n");
@@ -1060,7 +1064,108 @@
sm_p->u.create.sys_attr.group = attr->group;
/* note that permission checking is left to server even in this case */
}
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "create_parent_getattr: [%p] "
+ "dfile_count = %d "
+ "dist_name_len = %d "
+ "dist_params_len = %d\n",
+ attr,
+ attr->u.dir.hint.dfile_count,
+ attr->u.dir.hint.dist_name_len,
+ attr->u.dir.hint.dist_params_len);
+
+ num_dfiles_requested_override = attr->u.dir.hint.dfile_count;
+ /* override the # of data files for this create */
+ if (num_dfiles_requested_override > 0)
+ {
+ /* Determine the number of dfiles */
+ PINT_cached_config_get_num_dfiles(sm_p->object_ref.fs_id,
+ sm_p->u.create.dist,
+ num_dfiles_requested_override,
+ &sm_p->u.create.num_data_files);
+ }
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "Setting number of datafiles to %d [requested %d]\n",
+ sm_p->u.create.num_data_files, num_dfiles_requested_override);
+ current_dist = sm_p->u.create.dist;
+ /* We have an overriding distribution name for this directory.. honor that */
+ if (attr->u.dir.hint.dist_name_len > 0)
+ {
+ /* switch it only if it is different! */
+ if (strcmp(attr->u.dir.hint.dist_name, current_dist->dist_name))
+ {
+ PINT_dist *new_dist = NULL;
+ new_dist = PINT_dist_create(attr->u.dir.hint.dist_name);
+ if (new_dist)
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "Overridding distribution name to %s instead of %s\n",
+ attr->u.dir.hint.dist_name,
+ current_dist->dist_name);
+ PINT_dist_free(current_dist);
+ sm_p->u.create.dist = new_dist;
+ current_dist = new_dist;
+ }
+ else
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "Could not override distribution name with %s instead of %s\n",
+ attr->u.dir.hint.dist_name,
+ current_dist->dist_name);
+ }
+ }
+ else {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "retaining current distribution name %s\n",
+ current_dist->dist_name);
+ }
+ }
+ /* okay, we might need to override some dist params as well */
+ if (attr->u.dir.hint.dist_params_len > 0)
+ {
+ /* We have a series of comma separated key:val strings */
+ char **key, **val;
+ int64_t tmp_val;
+ int nparams = 0;
+
+ /* ignore parse errors! */
+ if (PINT_split_keyvals(attr->u.dir.hint.dist_params,
+ &nparams, &key, &val) == 0)
+ {
+ int i;
+ for (i = 0; i < nparams; i++)
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "distribution parameter %s, value %s\n",
+ key[i], val[i]);
+ /* NOTE: just as in server-config.c when parsing "Param" and
+ * "Value" fields, we will assume that all values are 64 bit
+ * integers. The only difference here is that we scan
+ * directly into a 64 bit integer, rather than converting
+ * from the int format that dotconf supports.
+ */
+ ret = sscanf(val[i], SCANF_lld, &tmp_val);
+ if(ret != 1)
+ {
+ gossip_err("Error: unsupported type for distribution parameter %s, value %s found in directory hints.\n",
+ key[i], val[i]);
+ gossip_err("Error: continuing anyway.\n");
+ }
+ else
+ {
+ if(current_dist->methods->set_param(current_dist->dist_name,
+ current_dist->params,
+ key[i],
+ &tmp_val))
+ {
+
+ gossip_err("Error: could not override hinted distribution parameter %s, value %s found in directory hints\n",
+ key[i],
+ val[i]);
+ }
+ }
+ free(key[i]);
+ free(val[i]);
+ }
+ free(key);
+ free(val);
+ }
+ }
return(1);
}
diff -Naur pvfs2-old/src/client/sysint/sys-getattr.sm pvfs2/src/client/sysint/sys-getattr.sm
--- pvfs2-old/src/client/sysint/sys-getattr.sm 2006-05-22 23:50:13.000000000 +0200
+++ pvfs2/src/client/sysint/sys-getattr.sm 2006-06-07 03:48:46.000000000 +0200
@@ -539,7 +539,6 @@
&resp_p->u.getattr.attr);
attr = &sm_p->getattr.attr;
- assert(attr);
/* if the ref_type mask is set to a non-zero value (!PVFS_TYPE_NONE)
* a -PVFS_error will be triggered if the
@@ -618,7 +617,18 @@
}
return 0;
case PVFS_TYPE_DIRECTORY:
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG,
+ "getattr comp_fn [%p] "
+ "dfile_count = %d "
+ "dist_name_len = %d "
+ "dist_params_len = %d\n",
+ attr,
+ attr->u.dir.hint.dfile_count,
+ attr->u.dir.hint.dist_name_len,
+ attr->u.dir.hint.dist_params_len);
return 0;
+ }
case PVFS_TYPE_SYMLINK:
return 0;
case PVFS_TYPE_DATAFILE:
@@ -845,6 +855,42 @@
{
sysresp->attr.dfile_count = attr->u.meta.dfile_count;
}
+ if (attr->objtype == PVFS_TYPE_DIRECTORY)
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "dfile_count: %d\n",
+ attr->u.dir.hint.dfile_count);
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "dist_name_len = %d, dist_params_len = %d\n",
+ attr->u.dir.hint.dist_name_len, attr->u.dir.hint.dist_params_len);
+ sysresp->attr.dfile_count = attr->u.dir.hint.dfile_count;
+ /*
+ * If we retrieved any extended attributes for the directory
+ * in question, the caller's responsibility to free it up
+ */
+ if (attr->u.dir.hint.dist_name_len > 0 &&
+ (sm_p->getattr.req_attrmask & PVFS_ATTR_DIR_HINT))
+ {
+ sysresp->attr.dist_name = strdup(attr->u.dir.hint.dist_name);
+ if (!sysresp->attr.dist_name)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 0;
+ }
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "dist_name_hint: %s\n", sysresp->attr.dist_name);
+ }
+ if (attr->u.dir.hint.dist_params_len > 0 &&
+ (sm_p->getattr.req_attrmask & PVFS_ATTR_DIR_HINT))
+ {
+ sysresp->attr.dist_params = strdup(attr->u.dir.hint.dist_params);
+ if (!sysresp->attr.dist_params)
+ {
+ free(sysresp->attr.dist_name);
+ sysresp->attr.dist_name = NULL;
+ js_p->error_code = -PVFS_ENOMEM;
+ return 0;
+ }
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "dist_name_params: %s\n", sysresp->attr.dist_params);
+ }
+ }
/* copy outgoing sys_attr fields from returned object_attr */
sysresp->attr.owner = attr->owner;
diff -Naur pvfs2-old/src/client/sysint/sys-mkdir.sm pvfs2/src/client/sysint/sys-mkdir.sm
--- pvfs2-old/src/client/sysint/sys-mkdir.sm 2006-05-22 23:50:13.000000000 +0200
+++ pvfs2/src/client/sysint/sys-mkdir.sm 2006-06-07 03:48:46.000000000 +0200
@@ -32,7 +32,8 @@
enum
{
- MKDIR_RETRY = 180
+ MKDIR_RETRY = 180,
+ MKDIR_SKIP_EATTR = 181
};
static int mkdir_init(
@@ -45,6 +46,10 @@
PINT_client_sm *sm_p, job_status_s *js_p);
static int mkdir_crdirent_failure(
PINT_client_sm *sm_p, job_status_s *js_p);
+static int mkdir_seteattr_setup_msgpair(
+ PINT_client_sm *sm_p, job_status_s *js_p);
+static int mkdir_seteattr_failure(
+ PINT_client_sm *sm_p, job_status_s *js_p);
static int mkdir_delete_handle_setup_msgpair(
PINT_client_sm *sm_p, job_status_s *js_p);
static int mkdir_cleanup(
@@ -68,6 +73,9 @@
mkdir_msg_setup_msgpair,
mkdir_msg_xfer_msgpair,
mkdir_msg_failure,
+ mkdir_seteattr_setup_msgpair,
+ mkdir_seteattr_xfer_msgpair,
+ mkdir_seteattr_failure,
mkdir_crdirent_setup_msgpair,
mkdir_crdirent_xfer_msgpair,
mkdir_crdirent_failure,
@@ -105,7 +113,7 @@
state mkdir_msg_xfer_msgpair
{
jump pvfs2_msgpairarray_sm;
- success => mkdir_crdirent_setup_msgpair;
+ success => mkdir_seteattr_setup_msgpair;
default => mkdir_msg_failure;
}
@@ -115,6 +123,27 @@
default => cleanup;
}
+ state mkdir_seteattr_setup_msgpair
+ {
+ run mkdir_seteattr_setup_msgpair;
+ MKDIR_SKIP_EATTR => mkdir_crdirent_setup_msgpair;
+ success => mkdir_seteattr_xfer_msgpair;
+ default => mkdir_seteattr_failure;
+ }
+
+ state mkdir_seteattr_xfer_msgpair
+ {
+ jump pvfs2_msgpairarray_sm;
+ success => mkdir_crdirent_setup_msgpair;
+ default => mkdir_seteattr_failure;
+ }
+
+ state mkdir_seteattr_failure
+ {
+ run mkdir_seteattr_failure;
+ default => delete_handle_setup_msgpair;
+ }
+
state mkdir_crdirent_setup_msgpair
{
run mkdir_crdirent_setup_msgpair;
@@ -277,7 +306,7 @@
PINT_SM_GETATTR_STATE_FILL(
sm_p->getattr,
sm_p->object_ref,
- PVFS_ATTR_COMMON_ALL,
+ (PVFS_ATTR_COMMON_ALL|PVFS_ATTR_DIR_HINT),
PVFS_TYPE_DIRECTORY,
0);
@@ -498,6 +527,20 @@
{
gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: cleanup\n");
+ if(sm_p->u.mkdir.val_array)
+ {
+ if((sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT) &&
+ (sm_p->getattr.attr.u.dir.hint.dfile_count > 0))
+ {
+ free(sm_p->u.mkdir.val_array[0].buffer);
+ }
+ free(sm_p->u.mkdir.val_array);
+ }
+ if(sm_p->u.mkdir.key_array)
+ {
+ free(sm_p->u.mkdir.key_array);
+ }
+
PVFS_util_release_sys_attr(&sm_p->u.mkdir.sys_attr);
PINT_SM_GETATTR_STATE_CLEAR(sm_p->getattr);
@@ -572,6 +615,152 @@
return(1);
}
+static int mkdir_seteattr_setup_msgpair(
+ PINT_client_sm *sm_p, job_status_s *js_p)
+{
+ int eattr_count = 0;
+ int cur_index = 0;
+ PINT_sm_msgpair_state *msg_p = NULL;
+ int ret = -PVFS_EINVAL;
+
+ /* NOTE: any memory allocated here will be free'd in the cleanup function */
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: seteattr_setup_msgpair\n");
+
+ /* don't set any hint attributes if the parent doesn't have them */
+ if(!(sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT))
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: skipping seteattr\n");
+ js_p->error_code = MKDIR_SKIP_EATTR;
+ return(1);
+ }
+
+ /* count how many hints we acquired */
+ if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
+ eattr_count++;
+ if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
+ eattr_count++;
+ if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
+ eattr_count++;
+
+ if(eattr_count == 0)
+ {
+ /* nothing to inherit */
+ js_p->error_code = MKDIR_SKIP_EATTR;
+ return(1);
+ }
+
+ sm_p->u.mkdir.key_array = (PVFS_ds_keyval*)calloc(eattr_count,
+ sizeof(PVFS_ds_keyval));
+ if(!sm_p->u.mkdir.key_array)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return(1);
+ }
+
+ sm_p->u.mkdir.val_array = (PVFS_ds_keyval*)calloc(eattr_count,
+ sizeof(PVFS_ds_keyval));
+ if(!sm_p->u.mkdir.val_array)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return(1);
+ }
+
+ if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting num_dfiles\n");
+ sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.num_dfiles";
+ sm_p->u.mkdir.key_array[cur_index].buffer_sz =
+ strlen("user.pvfs2.num_dfiles") + 1;
+
+ sm_p->u.mkdir.val_array[cur_index].buffer = calloc(1, 16);
+ if(!sm_p->u.mkdir.val_array[cur_index].buffer)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return(1);
+ }
+ snprintf((char*)sm_p->u.mkdir.val_array[cur_index].buffer,
+ 16, "%d", sm_p->getattr.attr.u.dir.hint.dfile_count);
+ sm_p->u.mkdir.val_array[cur_index].buffer_sz =
+ strlen((char*)sm_p->u.mkdir.val_array[cur_index].buffer) + 1;
+
+ cur_index++;
+ }
+ if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_name\n");
+ sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_name";
+ sm_p->u.mkdir.key_array[cur_index].buffer_sz =
+ strlen("user.pvfs2.dist_name") + 1;
+ sm_p->u.mkdir.val_array[cur_index].buffer =
+ sm_p->getattr.attr.u.dir.hint.dist_name;
+ sm_p->u.mkdir.val_array[cur_index].buffer_sz =
+ sm_p->getattr.attr.u.dir.hint.dist_name_len;
+
+ cur_index++;
+ }
+ if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
+ {
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_params\n");
+ sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_params";
+ sm_p->u.mkdir.key_array[cur_index].buffer_sz =
+ strlen("user.pvfs2.dist_params") + 1;
+
+ sm_p->u.mkdir.val_array[cur_index].buffer =
+ sm_p->getattr.attr.u.dir.hint.dist_params;
+ sm_p->u.mkdir.val_array[cur_index].buffer_sz =
+ sm_p->getattr.attr.u.dir.hint.dist_params_len;
+
+ cur_index++;
+ }
+
+ PINT_init_msgpair(sm_p, msg_p);
+
+ PINT_SERVREQ_SETEATTR_FILL(
+ sm_p->msgpair.req,
+ (*sm_p->cred_p),
+ sm_p->object_ref.fs_id,
+ sm_p->u.mkdir.metafile_handle,
+ 0,
+ eattr_count,
+ sm_p->u.mkdir.key_array,
+ sm_p->u.mkdir.val_array
+ );
+
+ sm_p->msgarray = &(sm_p->msgpair);
+ sm_p->msgarray_count = 1;
+ sm_p->msgpair.fs_id = sm_p->object_ref.fs_id;
+ sm_p->msgpair.handle = sm_p->u.mkdir.metafile_handle;
+ sm_p->msgpair.retry_flag = PVFS_MSGPAIR_RETRY;
+ /* NOTE: no comp_fn needed. */
+
+ ret = PINT_cached_config_map_to_server(
+ &sm_p->msgpair.svr_addr,
+ sm_p->msgpair.handle,
+ sm_p->msgpair.fs_id);
+ if (ret)
+ {
+ gossip_err("Failed to map meta server address\n");
+ js_p->error_code = ret;
+ }
+ else
+ {
+ js_p->error_code = 0;
+ }
+ return(1);
+}
+
+static int mkdir_seteattr_failure(
+ PINT_client_sm *sm_p, job_status_s *js_p)
+{
+ sm_p->u.mkdir.stored_error_code = js_p->error_code;
+
+ gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_seteattr_failure\n");
+
+ PVFS_perror_gossip("mkdir seteattr failed", js_p->error_code);
+ return 1;
+}
+
/*
* Local variables:
* mode: c
diff -Naur pvfs2-old/src/common/misc/pint-util.c pvfs2/src/common/misc/pint-util.c
--- pvfs2-old/src/common/misc/pint-util.c 2005-08-23 20:44:17.000000000 +0200
+++ pvfs2/src/common/misc/pint-util.c 2006-06-07 03:48:46.000000000 +0200
@@ -133,6 +133,33 @@
src->u.dir.dirent_count;
}
+ if (src->mask & PVFS_ATTR_DIR_HINT)
+ {
+ dest->u.dir.hint.dfile_count =
+ src->u.dir.hint.dfile_count;
+ dest->u.dir.hint.dist_name_len =
+ src->u.dir.hint.dist_name_len;
+ if (dest->u.dir.hint.dist_name_len > 0)
+ {
+ dest->u.dir.hint.dist_name = strdup(src->u.dir.hint.dist_name);
+ if (dest->u.dir.hint.dist_name == NULL)
+ {
+ return ret;
+ }
+ }
+ dest->u.dir.hint.dist_params_len =
+ src->u.dir.hint.dist_params_len;
+ if (dest->u.dir.hint.dist_params_len > 0)
+ {
+ dest->u.dir.hint.dist_params = strdup(src->u.dir.hint.dist_params);
+ if (dest->u.dir.hint.dist_params == NULL)
+ {
+ free(dest->u.dir.hint.dist_name);
+ return ret;
+ }
+ }
+ }
+
/*
NOTE:
we only copy the size out if we're actually a
@@ -253,6 +280,20 @@
}
}
}
+ else if (attr->objtype == PVFS_TYPE_DIRECTORY)
+ {
+ if ((attr->mask & PVFS_ATTR_DIR_HINT) || (attr->mask & PVFS_ATTR_DIR_DIRENT_COUNT))
+ {
+ if (attr->u.dir.hint.dist_name)
+ {
+ free(attr->u.dir.hint.dist_name);
+ }
+ if (attr->u.dir.hint.dist_params)
+ {
+ free(attr->u.dir.hint.dist_params);
+ }
+ }
+ }
}
}
diff -Naur pvfs2-old/src/common/misc/pvfs2-util.c pvfs2/src/common/misc/pvfs2-util.c
--- pvfs2-old/src/common/misc/pvfs2-util.c 2006-05-31 00:18:42.000000000 +0200
+++ pvfs2/src/common/misc/pvfs2-util.c 2006-06-07 03:48:46.000000000 +0200
@@ -175,6 +175,28 @@
return ret;
}
}
+ else if ((src_attr->mask & PVFS_ATTR_SYS_DIR_HINT))
+ {
+ if (src_attr->dist_name)
+ {
+ dest_attr->dist_name = strdup(src_attr->dist_name);
+ if (dest_attr->dist_name == NULL)
+ {
+ ret = -PVFS_ENOMEM;
+ return ret;
+ }
+ }
+ if (src_attr->dist_params)
+ {
+ dest_attr->dist_params = strdup(src_attr->dist_params);
+ if (dest_attr->dist_params == NULL)
+ {
+ free(dest_attr->dist_name);
+ ret = -PVFS_ENOMEM;
+ return ret;
+ }
+ }
+ }
ret = 0;
}
return ret;
@@ -190,6 +212,16 @@
free(attr->link_target);
attr->link_target = NULL;
}
+ else if ((attr->mask & PVFS_ATTR_SYS_DIR_HINT) &&
+ (attr->objtype == PVFS_TYPE_DIRECTORY))
+ {
+ if (attr->dist_name)
+ free(attr->dist_name);
+ if (attr->dist_params)
+ free(attr->dist_params);
+ attr->dist_name = NULL;
+ attr->dist_params = NULL;
+ }
}
}
@@ -1471,6 +1503,11 @@
attrmask |= PVFS_ATTR_DIR_DIRENT_COUNT;
}
+ if (sys_attrmask & PVFS_ATTR_SYS_DIR_HINT)
+ {
+ attrmask |= PVFS_ATTR_DIR_HINT;
+ }
+
if (sys_attrmask & PVFS_ATTR_SYS_LNK_TARGET)
{
attrmask |= PVFS_ATTR_SYMLNK_TARGET;
@@ -1532,6 +1569,10 @@
{
sys_mask |= PVFS_ATTR_SYS_DFILE_COUNT;
}
+ if (obj_mask & PVFS_ATTR_DIR_HINT)
+ {
+ sys_mask |= PVFS_ATTR_SYS_DIR_HINT;
+ }
return sys_mask;
}
diff -Naur pvfs2-old/src/common/misc/str-utils.c pvfs2/src/common/misc/str-utils.c
--- pvfs2-old/src/common/misc/str-utils.c 2005-08-23 20:44:17.000000000 +0200
+++ pvfs2/src/common/misc/str-utils.c 2006-06-07 03:48:46.000000000 +0200
@@ -680,6 +680,134 @@
#endif
/*
+ * PINT_split_keyvals()
+ *
+ * Splits a given string into a number of key:val strings.
+ *
+ * Parameters:
+ * The given string must be comma separated, and each
+ * segment within the comma regions must be of of
+ * the form key:val.
+ * Return the number of such keyval pairs and a
+ * pointer to a double dimensional array of keys and values.
+ * In case of errors, a -ve PVFS error is returned.
+ *
+ * Example inputs and return values:
+ *
+ * NULL - return -PVFS_EINVAL
+ * ab:23 - return nkey as 1, pkey <"ab">, pval <"23">
+ * ab:23,bc:34 - returns nkey as 2, pkey <"ab", "bc">, pval<"23", "34">
+ *
+ */
+int PINT_split_keyvals(char *string, int *nkey,
+ char ***pkey, char ***pval)
+{
+ char **key, **val, *ptr, *params;
+ int nparams = 0, i;
+
+ if (string == NULL || nkey == NULL
+ || pkey == NULL || pval == NULL)
+ {
+ return -PVFS_EINVAL;
+ }
+ params = strdup(string);
+ if (params == NULL)
+ {
+ return -PVFS_ENOMEM;
+ }
+ ptr = params;
+ while (ptr)
+ {
+ if (*ptr != ',' || *ptr != '\0')
+ nparams++;
+ ptr++;
+ ptr = strchr(ptr, ',');
+ }
+ if (nparams == 0)
+ {
+ free(params);
+ return -PVFS_EINVAL;
+ }
+ ptr = params;
+ key = (char **) calloc(nparams, sizeof(char *));
+ val = (char **) calloc(nparams, sizeof(char *));
+ if (key == NULL || val == NULL)
+ {
+ free(key);
+ free(val);
+ free(params);
+ return -PVFS_ENOMEM;
+ }
+ for (i = 0; i < nparams; i++)
+ {
+ char *ptr2;
+ if (i > 0 && ptr)
+ {
+ *ptr = '\0';
+ ptr++;
+ }
+ else if (ptr == NULL)
+ {
+ break;
+ }
+ ptr2 = strchr(ptr, ':');
+ if (ptr2 == NULL)
+ {
+ break;
+ }
+ key[i] = ptr;
+ ptr = strchr(ptr, ',');
+ if (ptr != NULL && ptr < ptr2)
+ {
+ break;
+ }
+ *ptr2 = '\0';
+ val[i] = ptr2 + 1;
+ }
+ if (i != nparams)
+ {
+ free(key);
+ free(val);
+ free(params);
+ return -PVFS_EINVAL;
+ }
+ else
+ {
+ for (i = 0; i < nparams; i++)
+ {
+ char *ptr1, *ptr2;
+ ptr1 = strdup(key[i]);
+ ptr2 = strdup(val[i]);
+ if (ptr1 == NULL || ptr2 == NULL)
+ break;
+ if (strchr(ptr1, ':') || strchr(ptr2, ':'))
+ break;
+ key[i] = ptr1;
+ val[i] = ptr2;
+ }
+ if (i != nparams)
+ {
+ int j;
+ for (j = 0; j < i; j++)
+ {
+ if (key[j]) free(key[j]);
+ if (val[j]) free(val[j]);
+ }
+ free(key);
+ free(val);
+ free(params);
+ return -PVFS_EINVAL;
+ }
+ free(params);
+ *nkey = nparams;
+ *pkey = key;
+ *pval = val;
+ return 0;
+ }
+}
+
+
+/*
* Local variables:
* c-indent-level: 4
* c-basic-offset: 4
diff -Naur pvfs2-old/src/common/misc/str-utils.h pvfs2/src/common/misc/str-utils.h
--- pvfs2-old/src/common/misc/str-utils.h 2005-08-23 20:44:17.000000000 +0200
+++ pvfs2/src/common/misc/str-utils.h 2006-06-07 03:48:46.000000000 +0200
@@ -60,6 +60,8 @@
char *strstr(const char *haystack, const char *needle);
#endif
+int PINT_split_keyvals(char *string, int *nkey,
+ char ***pkey, char ***pval);
#endif
/*
* Local variables:
diff -Naur pvfs2-old/src/kernel/linux-2.6/inode.c pvfs2/src/kernel/linux-2.6/inode.c
--- pvfs2-old/src/kernel/linux-2.6/inode.c 2006-01-07 04:08:59.000000000 +0100
+++ pvfs2/src/kernel/linux-2.6/inode.c 2006-06-07 03:48:46.000000000 +0200
@@ -341,7 +341,7 @@
* A revalidate expects that all fields of the inode would be refreshed
* So we have no choice but to refresh all attributes.
*/
- ret = pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL);
+ ret = pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL_NOHINT);
if (ret)
{
/* assume an I/O error and flag inode as bad */
@@ -367,7 +367,7 @@
* of the inode would be refreshed. So again, we dont have too much of a choice
* but refresh all the attributes.
*/
- ret = pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL);
+ ret = pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL_NOHINT);
if (ret == 0)
{
generic_fillattr(inode, kstat);
diff -Naur pvfs2-old/src/kernel/linux-2.6/pvfs2-kernel.h pvfs2/src/kernel/linux-2.6/pvfs2-kernel.h
--- pvfs2-old/src/kernel/linux-2.6/pvfs2-kernel.h 2006-05-30 06:53:27.000000000 +0200
+++ pvfs2/src/kernel/linux-2.6/pvfs2-kernel.h 2006-06-07 03:48:46.000000000 +0200
@@ -930,7 +930,7 @@
* The dentry revalidating function expects that all fields of the inode
* would be refreshed, so we dont have much of a choice here too.
*/
- ret = ((pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL) == 0) ? 1 : 0);
+ ret = ((pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL_NOHINT) == 0) ? 1 : 0);
#if 0
/* Calling make_bad_inode() here results in a bad reference count on the
* inode. It therefore gets cached until the module is unloaded, when we get
diff -Naur pvfs2-old/src/kernel/linux-2.6/super.c pvfs2/src/kernel/linux-2.6/super.c
--- pvfs2-old/src/kernel/linux-2.6/super.c 2006-05-05 02:48:00.000000000 +0200
+++ pvfs2/src/kernel/linux-2.6/super.c 2006-06-07 03:51:10.000000000 +0200
@@ -213,7 +213,7 @@
called after a successful dentry lookup if the inode is not
present in the inode cache already. so this is our chance.
*/
- if (pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL) != 0)
+ if (pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL_NOHINT) != 0)
{
/* assume an I/O error and mark the inode as bad */
pvfs2_make_bad_inode(inode);
@@ -245,7 +245,7 @@
pvfs2_print("pvfs2: pvfs2_read_inode: allocated %p (inode = %lu | "
"ct = %d)\n", pvfs2_inode, inode->i_ino,
(int)atomic_read(&inode->i_count));
- if (pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL) != 0)
+ if (pvfs2_inode_getattr(inode, PVFS_ATTR_SYS_ALL_NOHINT) != 0)
{
pvfs2_make_bad_inode(inode);
}
diff -Naur pvfs2-old/src/proto/PINT-le-bytefield.c pvfs2/src/proto/PINT-le-bytefield.c
--- pvfs2-old/src/proto/PINT-le-bytefield.c 2005-12-23 23:22:14.000000000 +0100
+++ pvfs2/src/proto/PINT-le-bytefield.c 2006-06-07 03:48:46.000000000 +0200
@@ -657,7 +657,8 @@
#undef CASE
if (ptr != (char *)input_buffer + input_size) {
- gossip_lerr("%s: improper input buffer size", __func__);
+ gossip_lerr("%s: improper input buffer size [%p + %d != %p]\n", __func__,
+ input_buffer, input_size, ptr);
ret = -PVFS_EPROTO;
}
diff -Naur pvfs2-old/src/proto/endecode-funcs.h pvfs2/src/proto/endecode-funcs.h
--- pvfs2-old/src/proto/endecode-funcs.h 2006-06-05 21:57:27.000000000 +0200
+++ pvfs2/src/proto/endecode-funcs.h 2006-06-07 03:48:46.000000000 +0200
@@ -229,6 +229,26 @@
#define endecode_fields_5_struct(name, t1, x1, t2, x2, t3, x3, t4, x4, t5, x5) \
endecode_fields_5_generic(name, struct name, t1, x1, t2, x2, t3, x3, t4, x4, t5, x5)
+#define endecode_fields_7(name,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7) \
+static inline void encode_##name(char **pptr, const name *x) { \
+ encode_##t1(pptr, &x->x1); \
+ encode_##t2(pptr, &x->x2); \
+ encode_##t3(pptr, &x->x3); \
+ encode_##t4(pptr, &x->x4); \
+ encode_##t5(pptr, &x->x5); \
+ encode_##t6(pptr, &x->x6); \
+ encode_##t7(pptr, &x->x7); \
+} \
+static inline void decode_##name(char **pptr, name *x) { \
+ decode_##t1(pptr, &x->x1); \
+ decode_##t2(pptr, &x->x2); \
+ decode_##t3(pptr, &x->x3); \
+ decode_##t4(pptr, &x->x4); \
+ decode_##t5(pptr, &x->x5); \
+ decode_##t6(pptr, &x->x6); \
+ decode_##t7(pptr, &x->x7); \
+}
+
#define endecode_fields_7_struct(name,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7) \
static inline void encode_##name(char **pptr, const struct name *x) { \
encode_##t1(pptr, &x->x1); \
diff -Naur pvfs2-old/src/proto/pvfs2-attr.h pvfs2/src/proto/pvfs2-attr.h
--- pvfs2-old/src/proto/pvfs2-attr.h 2005-10-06 15:43:04.000000000 +0200
+++ pvfs2/src/proto/pvfs2-attr.h 2006-06-07 03:48:46.000000000 +0200
@@ -44,7 +44,9 @@
/* internal attribute masks for directory objects */
#define PVFS_ATTR_DIR_DIRENT_COUNT (1 << 19)
-#define PVFS_ATTR_DIR_ALL PVFS_ATTR_DIR_DIRENT_COUNT
+#define PVFS_ATTR_DIR_HINT (1 << 20)
+#define PVFS_ATTR_DIR_ALL \
+(PVFS_ATTR_DIR_DIRENT_COUNT | PVFS_ATTR_DIR_HINT)
/* attributes specific to metadata objects */
struct PVFS_metafile_attr_s
@@ -90,13 +92,49 @@
typedef struct PVFS_datafile_attr_s PVFS_datafile_attr;
endecode_fields_1(PVFS_datafile_attr, PVFS_size, size)
+/* extended hint attributes for a directory object */
+struct PVFS_directory_hint_s
+{
+ uint32_t dist_name_len;
+ /* what is the distribution name? */
+ char *dist_name;
+ /* what are the distribution parameters? */
+ uint32_t dist_params_len;
+ char *dist_params;
+ /* how many dfiles ought to be used */
+ uint32_t dfile_count;
+};
+typedef struct PVFS_directory_hint_s PVFS_directory_hint;
+
+#ifdef __PINT_REQPROTO_ENCODE_FUNCS_C
+endecode_fields_7(PVFS_directory_hint,
+ uint32_t, dist_name_len,
+ skip4,,
+ string, dist_name,
+ uint32_t, dist_params_len,
+ skip4,,
+ string, dist_params,
+ uint32_t, dfile_count)
+#endif
+
/* attributes specific to directory objects */
struct PVFS_directory_attr_s
{
PVFS_size dirent_count;
+ PVFS_directory_hint hint;
};
typedef struct PVFS_directory_attr_s PVFS_directory_attr;
-endecode_fields_1(PVFS_directory_attr, PVFS_size, dirent_count)
+
+#ifdef __PINT_REQPROTO_ENCODE_FUNCS_C
+#define encode_PVFS_directory_attr(pptr, x) do { \
+ encode_PVFS_size(pptr, &(x)->dirent_count);\
+ encode_PVFS_directory_hint(pptr, &(x)->hint);\
+} while(0)
+#define decode_PVFS_directory_attr(pptr, x) do { \
+ decode_PVFS_size(pptr, &(x)->dirent_count);\
+ decode_PVFS_directory_hint(pptr, &(x)->hint);\
+} while(0)
+#endif
/* attributes specific to symlinks */
struct PVFS_symlink_attr_s
@@ -151,7 +189,7 @@
encode_PVFS_datafile_attr(pptr, &(x)->u.data); \
if ((x)->mask & PVFS_ATTR_SYMLNK_TARGET) \
encode_PVFS_symlink_attr(pptr, &(x)->u.sym); \
- if ((x)->mask & PVFS_ATTR_DIR_DIRENT_COUNT) \
+ if (((x)->mask & PVFS_ATTR_DIR_DIRENT_COUNT) || ((x)->mask & PVFS_ATTR_DIR_HINT)) \
encode_PVFS_directory_attr(pptr, &(x)->u.dir); \
} while (0)
#define decode_PVFS_object_attr(pptr,x) do { \
@@ -172,18 +210,26 @@
decode_PVFS_datafile_attr(pptr, &(x)->u.data); \
if ((x)->mask & PVFS_ATTR_SYMLNK_TARGET) \
decode_PVFS_symlink_attr(pptr, &(x)->u.sym); \
- if ((x)->mask & PVFS_ATTR_DIR_DIRENT_COUNT) \
+ if (((x)->mask & PVFS_ATTR_DIR_DIRENT_COUNT) || ((x)->mask & PVFS_ATTR_DIR_HINT)) \
decode_PVFS_directory_attr(pptr, &(x)->u.dir); \
} while (0)
#endif
-/* attr buffer needs room for larger of symlink path or meta fields: an attrib
- * structure can never hold information for both a symlink and a metafile */
+/* attr buffer needs room for larger of symlink path, meta fields or dir hints: an attrib
+ * structure can never hold information for not more than a symlink or a metafile or a dir object */
+#define extra_size_PVFS_object_attr_dir (PVFS_REQ_LIMIT_DIST_BYTES + \
+ PVFS_REQ_LIMIT_DIST_NAME + roundup8(sizeof(PVFS_directory_attr)))
+
#define extra_size_PVFS_object_attr_meta (PVFS_REQ_LIMIT_DIST_BYTES + \
PVFS_REQ_LIMIT_DFILE_COUNT * sizeof(PVFS_handle))
+
#define extra_size_PVFS_object_attr_symlink (PVFS_REQ_LIMIT_PATH_NAME_BYTES)
-#define extra_size_PVFS_object_attr ((extra_size_PVFS_object_attr_meta > \
- extra_size_PVFS_object_attr_symlink) ? extra_size_PVFS_object_attr_meta : \
- extra_size_PVFS_object_attr_symlink)
+
+#ifndef max3
+#define max3(a, b, c) (a) < (b) ? (b) < (c) ? (c) : (b) : (a) < (c) ? (c) : (a)
+#endif
+
+#define extra_size_PVFS_object_attr \
+ max3(extra_size_PVFS_object_attr_meta, extra_size_PVFS_object_attr_symlink, extra_size_PVFS_object_attr_dir)
#endif /* __PVFS2_ATTR_H */
diff -Naur pvfs2-old/src/proto/pvfs2-req-proto.h pvfs2/src/proto/pvfs2-req-proto.h
--- pvfs2-old/src/proto/pvfs2-req-proto.h 2006-05-19 03:03:59.000000000 +0200
+++ pvfs2/src/proto/pvfs2-req-proto.h 2006-06-07 03:48:46.000000000 +0200
@@ -108,6 +108,8 @@
#define PVFS_REQ_LIMIT_SEGMENT_BYTES PVFS_SEGMENT_MAX
/* max total size of I/O request descriptions */
#define PVFS_REQ_LIMIT_IOREQ_BYTES 8192
+/* maximum size of distribution name used for the hints */
+#define PVFS_REQ_LIMIT_DIST_NAME 128
/* max count of segments allowed per path lookup (note that this governs
* the number of handles and attributes returned in lookup_path responses)
*/
diff -Naur pvfs2-old/src/server/get-attr.sm pvfs2/src/server/get-attr.sm
--- pvfs2-old/src/server/get-attr.sm 2006-06-05 21:57:28.000000000 +0200
+++ pvfs2/src/server/get-attr.sm 2006-06-07 03:52:25.000000000 +0200
@@ -29,6 +29,21 @@
#include "pint-util.h"
#include "pvfs2-internal.h"
+enum
+{
+ DIST_NAME_KEY = 0,
+ DIST_PARAMS_KEY = 1,
+ NUM_DFILES_KEY = 2,
+ NUM_SPECIAL_KEYS = 3,
+};
+
+PINT_server_trove_keys_s Trove_Special_Keys[] =
+{
+ {"user.pvfs2.dist_name", 21},
+ {"user.pvfs2.dist_params", 23},
+ {"user.pvfs2.num_dfiles", 22},
+};
+
enum
{
STATE_METAFILE = 7,
@@ -46,6 +61,10 @@
PINT_server_op *s_op, job_status_s *js_p);
static int getattr_interpret_dirent_count(
PINT_server_op *s_op, job_status_s *js_p);
+static int getattr_get_dir_hint(
+ PINT_server_op *s_op, job_status_s *js_p);
+static int getattr_interpret_dir_hint(
+ PINT_server_op *s_op, job_status_s *js_p);
static int getattr_read_metafile_datafile_handles_if_required(
PINT_server_op *s_op, job_status_s *js_p);
static int getattr_read_metafile_distribution_if_required(
@@ -66,6 +85,8 @@
read_metafile_distribution_if_required,
get_dirent_count,
interpret_dirent_count,
+ get_dir_hint,
+ interpret_dir_hint,
setup_resp)
{
state verify_attribs
@@ -106,6 +127,18 @@
state interpret_dirent_count
{
run getattr_interpret_dirent_count;
+ default => get_dir_hint;
+ }
+
+ state get_dir_hint
+ {
+ run getattr_get_dir_hint;
+ default => interpret_dir_hint;
+ }
+
+ state interpret_dir_hint
+ {
+ run getattr_interpret_dir_hint;
default => setup_resp;
}
@@ -321,6 +354,20 @@
js_p->error_code = 0;
assert(resp_attr->mask & PVFS_ATTR_COMMON_ALL);
}
+ if (s_op->u.getattr.attrmask & PVFS_ATTR_DIR_HINT)
+ {
+ gossip_debug(GOSSIP_GETATTR_DEBUG,
+ " getattr: dfile_count needed.\n");
+ assert(resp_attr->mask & PVFS_ATTR_COMMON_ALL);
+ resp_attr->mask |= PVFS_ATTR_DIR_HINT;
+ js_p->error_code = STATE_DIR;
+ }
+ else
+ {
+ gossip_debug(GOSSIP_GETATTR_DEBUG,
+ " getattr: dfile_count not needed\n");
+ assert(resp_attr->mask & PVFS_ATTR_COMMON_ALL);
+ }
}
else if (resp_attr->objtype == PVFS_TYPE_DIRDATA)
{
@@ -639,6 +686,17 @@
return 1;
}
}
+ else if ((resp_attr->objtype == PVFS_TYPE_DIRECTORY) &&
+ (resp_attr->mask & PVFS_ATTR_DIR_HINT))
+ {
+ gossip_debug(GOSSIP_GETATTR_DEBUG, " server returning "
+ "dfile_count = %d "
+ "dist_name_len = %d "
+ "dist_params_len = %d\n",
+ resp_attr->u.dir.hint.dfile_count,
+ resp_attr->u.dir.hint.dist_name_len,
+ resp_attr->u.dir.hint.dist_params_len);
+ }
gossip_debug(GOSSIP_GETATTR_DEBUG,"@ End %s attributes: sending "
"status %d (error = %d)\n",
@@ -656,6 +714,27 @@
static int getattr_cleanup(PINT_server_op *s_op, job_status_s *js_p)
{
+
+ if(s_op->val_a)
+ {
+ if(s_op->val_a[NUM_DFILES_KEY].buffer)
+ {
+ free(s_op->val_a[NUM_DFILES_KEY].buffer);
+ }
+ free(s_op->val_a);
+ s_op->val_a = NULL;
+ }
+ if(s_op->key_a)
+ {
+ free(s_op->key_a);
+ s_op->key_a = NULL;
+ }
+ if(s_op->u.getattr.err_array)
+ {
+ free(s_op->u.getattr.err_array);
+ s_op->u.getattr.err_array = NULL;
+ }
+
PINT_free_object_attr(&s_op->resp.u.getattr.attr);
return(server_state_machine_complete(s_op));
}
@@ -712,6 +791,177 @@
return 1;
}
+static int getattr_get_dir_hint(
+ PINT_server_op *s_op, job_status_s *js_p)
+{
+ int ret, i;
+ job_id_t tmp_id;
+
+ /* NOTE: memory allocations are released in the getattr_cleanup()
+ * function
+ */
+
+ PINT_STATE_DEBUG("get_dir_hint");
+
+ gossip_debug(GOSSIP_SERVER_DEBUG, " trying to getxattr of %s,%s,%s "
+ "of dir handle (coll_id = %d, handle = %llu\n",
+ Trove_Special_Keys[DIST_NAME_KEY].key,
+ Trove_Special_Keys[DIST_PARAMS_KEY].key,
+ Trove_Special_Keys[NUM_DFILES_KEY].key,
+ s_op->u.getattr.fs_id, llu(s_op->u.getattr.handle));
+
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_params =
+ (char *) calloc(1, PVFS_REQ_LIMIT_DIST_BYTES);
+ if (!s_op->resp.u.getattr.attr.u.dir.hint.dist_params)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 1;
+ }
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_params_len =
+ PVFS_REQ_LIMIT_DIST_BYTES;
+
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_name =
+ (char *) calloc(1, PVFS_REQ_LIMIT_DIST_NAME);
+ if (!s_op->resp.u.getattr.attr.u.dir.hint.dist_name)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 1;
+ }
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_name_len =
+ PVFS_REQ_LIMIT_DIST_NAME;
+
+ s_op->key_a =
+ (PVFS_ds_keyval *) calloc(NUM_SPECIAL_KEYS, sizeof(PVFS_ds_keyval));
+ if (s_op->key_a == NULL)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 1;
+ }
+ s_op->val_a = (PVFS_ds_keyval *) calloc(NUM_SPECIAL_KEYS, sizeof(PVFS_ds_keyval));
+ if (s_op->val_a == NULL)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 1;
+ }
+ s_op->u.getattr.err_array = (PVFS_error*)calloc(NUM_SPECIAL_KEYS,
+ sizeof(PVFS_error));
+ if(s_op->u.getattr.err_array == NULL)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 1;
+
+ }
+ for (i = 0; i < NUM_SPECIAL_KEYS; i++)
+ {
+ s_op->key_a[i].buffer = Trove_Special_Keys[i].key;
+ s_op->key_a[i].buffer_sz = Trove_Special_Keys[i].size;
+ if (i == NUM_DFILES_KEY)
+ {
+ s_op->val_a[i].buffer = (char *) calloc(1, 16);
+ if(s_op->val_a[i].buffer == NULL)
+ {
+ js_p->error_code = -PVFS_ENOMEM;
+ return 1;
+ }
+ s_op->val_a[i].buffer_sz = 16;
+ }
+ else if (i == DIST_PARAMS_KEY) {
+ s_op->val_a[i].buffer = s_op->resp.u.getattr.attr.u.dir.hint.dist_params;
+ s_op->val_a[i].buffer_sz = s_op->resp.u.getattr.attr.u.dir.hint.dist_params_len;
+ }
+ else if (i == DIST_NAME_KEY) {
+ s_op->val_a[i].buffer = s_op->resp.u.getattr.attr.u.dir.hint.dist_name;
+ s_op->val_a[i].buffer_sz = s_op->resp.u.getattr.attr.u.dir.hint.dist_name_len;
+ }
+ }
+
+ js_p->error_code = 0;
+ ret = job_trove_keyval_read_list(
+ s_op->req->u.getattr.fs_id,
+ s_op->req->u.getattr.handle,
+ s_op->key_a, s_op->val_a, s_op->u.getattr.err_array, NUM_SPECIAL_KEYS,
+ 0, NULL, s_op, 0, js_p, &tmp_id,
+ server_job_context);
+
+ return ret;
+}
+
+static int getattr_interpret_dir_hint(
+ PINT_server_op *s_op, job_status_s *js_p)
+{
+ PINT_STATE_DEBUG("interpret_dfile_count");
+
+ if(js_p->error_code != 0 && js_p->error_code != -TROVE_ENOENT)
+ {
+ /* if we failed to get any of the keys, and the error code is due to
+ * something other than the keys simply not being present, then
+ * propigate the error.
+ */
+ return(1);
+ }
+
+ gossip_debug(GOSSIP_SERVER_DEBUG,
+ "getattr: job status code = %d\n", js_p->error_code);
+ if (s_op->val_a && s_op->key_a)
+ {
+ long int dfile_count = 0;
+
+ if (s_op->u.getattr.err_array[DIST_NAME_KEY] == 0)
+ {
+ gossip_debug(GOSSIP_SERVER_DEBUG,
+ "val_a[DIST_NAME_KEY] %p read_sz = %d dist_name = %s\n",
+ s_op->val_a[DIST_NAME_KEY].buffer,
+ s_op->val_a[DIST_NAME_KEY].read_sz,
+ (char *)s_op->val_a[DIST_NAME_KEY].buffer);
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_name_len =
+ s_op->val_a[DIST_NAME_KEY].read_sz;
+ }
+ else
+ {
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_name_len = 0;
+ }
+
+ if (s_op->u.getattr.err_array[DIST_PARAMS_KEY] == 0)
+ {
+ gossip_debug(GOSSIP_SERVER_DEBUG,
+ "val_a[DIST_PARAMS_KEY] %p read_sz = %d dist_params = %s\n",
+ s_op->val_a[DIST_PARAMS_KEY].buffer,
+ s_op->val_a[DIST_PARAMS_KEY].read_sz,
+ (char *)s_op->val_a[DIST_PARAMS_KEY].buffer);
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_params_len =
+ s_op->val_a[DIST_PARAMS_KEY].read_sz;
+ }
+ else
+ {
+ s_op->resp.u.getattr.attr.u.dir.hint.dist_params_len = 0;
+ }
+
+ if (s_op->u.getattr.err_array[NUM_DFILES_KEY] == 0)
+ {
+ char *endptr = NULL;
+ gossip_debug(GOSSIP_SERVER_DEBUG, "val_a[NUM_DFILES_KEY] %p read_sz = %d\n",
+ s_op->val_a[NUM_DFILES_KEY].buffer,
+ s_op->val_a[NUM_DFILES_KEY].read_sz);
+ dfile_count = strtol(s_op->val_a[NUM_DFILES_KEY].buffer, &endptr, 10);
+ if (*endptr != '\0' || dfile_count < 0)
+ {
+ dfile_count = 0;
+ }
+ free(s_op->val_a[NUM_DFILES_KEY].buffer);
+ s_op->val_a[NUM_DFILES_KEY].buffer = NULL;
+ s_op->val_a[NUM_DFILES_KEY].buffer_sz = 0;
+ }
+
+ s_op->resp.u.getattr.attr.u.dir.hint.dfile_count = dfile_count;
+
+ gossip_debug(GOSSIP_SERVER_DEBUG, "getattr: dfile_count: %d\n",
+ s_op->resp.u.getattr.attr.u.dir.hint.dfile_count);
+
+ js_p->error_code = 0;
+ }
+ return 1;
+}
+
/*
* Local variables:
* mode: c
diff -Naur pvfs2-old/src/server/pvfs2-server.h pvfs2/src/server/pvfs2-server.h
--- pvfs2-old/src/server/pvfs2-server.h 2006-06-05 21:57:28.000000000 +0200
+++ pvfs2/src/server/pvfs2-server.h 2006-06-07 03:48:46.000000000 +0200
@@ -311,6 +311,7 @@
PVFS_fs_id fs_id;
PVFS_ds_attributes dirdata_ds_attr;
uint32_t attrmask;
+ PVFS_error* err_array;
};
/* this is used in both set_eattr, get_eattr and list_eattr */
Index: pvfs2_src/doc/pvfs2-faq.tex
===================================================================
--- pvfs2_src/doc/pvfs2-faq.tex (revision 2098)
+++ pvfs2_src/doc/pvfs2-faq.tex (revision 2099)
@@ -759,6 +759,52 @@
to use, we suggest ext3 with ``journal data writeback'' option as a
reasonable choice.
+\subsection{Is there any way to tune particular directories for different
+workloads?}
+
+Yes. This can be done by using extended attributes to set directory
+hints. Three hints are currently supported, and they allow you to specify
+the distribution, distribution parameters, and number of datafiles to
+stripe across. They will not change the characteristics of existing
+files, but they will take effect for any newly created files within the
+directory. These hints will also be inherited by any new
+subdirectories.
+
+\subsubsection{Distribution}
+
+The distribution can be set as follows:
+
+\begin{verbatim}
+prompt# setfattr -n "user.pvfs2.dist_name" -v "basic_dist" /mnt/pvfs2/directory
+\end{verbatim}
+
+Supported distribution names can be found by looking in the pvfs2-dist-*
+header files.
+
+\subsubsection{Distribution parameters}
+
+Some distributions allow you to set parameters that impact how the
+distribution behaves. These parameters can be set as follows:
+
+\begin{verbatim}
+prompt# setfattr -n "user.pvfs2.dist_params" -v "strip_size:4096" /mnt/pvfs2/directory
+\end{verbatim}
+
+You can specify more than one "parameter:value" pair by seperating them with
+commas.
+
+\subsubsection{Number of datafiles}
+
+You can also specify the number of datafiles to stripe across:
+
+\begin{verbatim}
+prompt# setfattr -n "user.pvfs2.num_dfiles" -v "1" /mnt/pvfs2/directory
+\end{verbatim}
+
+PVFS2 defaults to striping files across each server in the file system.
+However, you may find that for small files it is advantages to limit each
+file to only a subset of servers (or even just one).
+
\subsection{My app still runs more slowly than I would like. What can I do?}
\label{sec:tuning}
_______________________________________________
Pvfs2-developers mailing list
Pvfs2-developers@beowulf-underground.org
http://www.beowulf-underground.org/mailman/listinfo/pvfs2-developers