root/branches/Orange-Elaine-Distr-Dir-Branch/src/client/sysint/sys-mkdir.sm @ 8648

Revision 8648, 23.7 KB (checked in by shuangy, 2 years ago)

1. add >InitNumDirdataHandles?< field to fs_config and default value set to 2. 2. add command line options >-n, --init-num-dirdata< to pvfs2-mkdir to set initial number of dirdata handles for a directory. (not yet applied to kernel module.)

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