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

Revision 8480, 23.9 KB (checked in by shuangy, 3 years ago)

incorporate dist-dir-struct to the source tree. It's compilable but not runnable. still have a lot to change and add. Commit as a touch base.

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_DIRENT_FILES),
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\n");
359
360    PINT_msgpair_init(&sm_p->msgarray_op);
361    msg_p = &sm_p->msgarray_op.msgpair;
362
363    ret = PINT_cached_config_get_next_meta(
364        sm_p->object_ref.fs_id,
365        &msg_p->svr_addr, &meta_handle_extent_array);
366
367    if (ret)
368    {
369        gossip_err("Failed to map meta server address\n");
370        js_p->error_code = ret;
371        return SM_ACTION_COMPLETE;
372    }
373
374    PINT_SERVREQ_MKDIR_FILL(
375        msg_p->req,
376        *sm_p->cred_p,
377        sm_p->object_ref.fs_id,
378        meta_handle_extent_array,
379        sm_p->u.mkdir.sys_attr,
380        sm_p->u.mkdir.num_dirent_files,
381        sm_p->u.mkdir.layout,
382        sm_p->hints);
383
384    msg_p->fs_id = sm_p->object_ref.fs_id;
385    msg_p->handle = meta_handle_extent_array.extent_array[0].first;
386    msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
387    msg_p->comp_fn = mkdir_msg_comp_fn;
388
389    PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
390    return SM_ACTION_COMPLETE;
391}
392
393static PINT_sm_action mkdir_msg_failure(
394        struct PINT_smcb *smcb, job_status_s *js_p)
395{
396    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
397    sm_p->u.mkdir.stored_error_code = js_p->error_code;
398
399    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_msg_failure\n");
400    return SM_ACTION_COMPLETE;
401}
402
403static PINT_sm_action mkdir_crdirent_setup_msgpair(
404        struct PINT_smcb *smcb, job_status_s *js_p)
405{
406    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
407    int ret = -PVFS_EINVAL;
408    PINT_sm_msgpair_state *msg_p = NULL;
409
410    gossip_debug(GOSSIP_CLIENT_DEBUG,
411                 "mkdir state: crdirent_setup_msgpair\n");
412
413    js_p->error_code = 0;
414
415    gossip_debug(GOSSIP_CLIENT_DEBUG," mkdir: posting crdirent req\n");
416
417    /* TODO: Need to find the correct dirent_handle */
418    /* !!! change later */
419    gossip_debug(GOSSIP_CLIENT_DEBUG, "hooking dirent %s (%llu) under "
420                 "parent handle %llu, dirent_handle %llu\n",
421                 sm_p->u.mkdir.object_name,
422                 llu(sm_p->u.mkdir.metafile_handle),
423                 llu(sm_p->object_ref.handle),
424                 llu(sm_p->u.mkdir.dirdata_handles[0]));
425
426    PINT_msgpair_init(&sm_p->msgarray_op);
427    msg_p = &sm_p->msgarray_op.msgpair;
428
429    PINT_SERVREQ_CRDIRENT_FILL(
430        msg_p->req,
431        *sm_p->cred_p,
432        sm_p->u.mkdir.object_name,
433        sm_p->u.mkdir.metafile_handle,
434        sm_p->object_ref.handle,
435        sm_p->u.mkdir.dirdata_handles[0],
436        sm_p->object_ref.fs_id,
437        sm_p->hints);
438
439    msg_p->fs_id = sm_p->object_ref.fs_id;
440    msg_p->handle = sm_p->object_ref.handle;
441    msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
442    msg_p->comp_fn = mkdir_crdirent_comp_fn;
443
444    ret = PINT_cached_config_map_to_server(
445        &msg_p->svr_addr, sm_p->object_ref.handle,
446        sm_p->object_ref.fs_id);
447
448    if (ret)
449    {
450        gossip_err("Failed to map meta server address\n");
451        js_p->error_code = ret;
452    }
453
454    PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
455    return SM_ACTION_COMPLETE;
456}
457
458static PINT_sm_action mkdir_crdirent_failure(
459        struct PINT_smcb *smcb, job_status_s *js_p)
460{
461    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
462    sm_p->u.mkdir.stored_error_code = js_p->error_code;
463
464    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: crdirent_failure\n");
465
466    PVFS_perror_gossip("mkdir crdirent failed", js_p->error_code);
467    return SM_ACTION_COMPLETE;
468}
469
470static PINT_sm_action mkdir_delete_handle_setup_msgpair(
471        struct PINT_smcb *smcb, job_status_s *js_p)
472{
473    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
474    int ret = -PVFS_EINVAL;
475    PVFS_BMI_addr_t metafile_server_addr;
476    PINT_sm_msgpair_state *msg_p = NULL;
477
478    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: "
479                 "delete_handle_setup_msgpair_array\n");
480
481    js_p->error_code = 0;
482
483    PINT_msgpair_init(&sm_p->msgarray_op);
484    msg_p = &sm_p->msgarray_op.msgpair;
485
486    ret = PINT_cached_config_map_to_server(
487        &metafile_server_addr, sm_p->u.mkdir.metafile_handle,
488        sm_p->object_ref.fs_id);
489
490    if (ret)
491    {
492        gossip_err("Failed to map meta server address\n");
493        js_p->error_code = ret;
494        return SM_ACTION_COMPLETE;
495    }
496
497    PINT_SERVREQ_REMOVE_FILL(
498        msg_p->req,
499        *sm_p->cred_p,
500        sm_p->object_ref.fs_id,
501        sm_p->u.mkdir.metafile_handle,
502        sm_p->hints);
503
504    msg_p->fs_id = sm_p->object_ref.fs_id;
505    msg_p->handle = sm_p->u.mkdir.metafile_handle;
506    msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
507    msg_p->comp_fn = mkdir_delete_handle_comp_fn;
508    msg_p->svr_addr = metafile_server_addr;
509
510    gossip_debug(GOSSIP_CLIENT_DEBUG, " Preparing to remove "
511                 "directory handle %llu\n", llu(msg_p->handle));
512
513    PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
514    return SM_ACTION_COMPLETE;
515}
516
517static PINT_sm_action mkdir_cleanup(
518        struct PINT_smcb *smcb, job_status_s *js_p)
519{
520    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
521    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: cleanup\n");
522
523    if(sm_p->u.mkdir.val_array)
524    {
525        if((sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT) &&
526            (sm_p->getattr.attr.u.dir.hint.dfile_count > 0))
527        {
528            free(sm_p->u.mkdir.val_array[0].buffer);
529        }
530        free(sm_p->u.mkdir.val_array);
531    }
532    if(sm_p->u.mkdir.key_array)
533    {
534        free(sm_p->u.mkdir.key_array);
535    }
536
537    PVFS_util_release_sys_attr(&sm_p->u.mkdir.sys_attr);
538    PINT_free_object_attr(&sm_p->getattr.attr);
539
540    PINT_SM_GETATTR_STATE_CLEAR(sm_p->getattr);
541
542    sm_p->error_code = (sm_p->u.mkdir.stored_error_code ?
543                        sm_p->u.mkdir.stored_error_code :
544                        js_p->error_code);
545
546    if (sm_p->error_code == 0)
547    {
548        PVFS_object_ref directory_ref;
549
550        directory_ref.handle = sm_p->u.mkdir.metafile_handle;
551        directory_ref.fs_id = sm_p->object_ref.fs_id;
552
553        sm_p->u.mkdir.mkdir_resp->ref.handle = directory_ref.handle;
554        sm_p->u.mkdir.mkdir_resp->ref.fs_id = directory_ref.fs_id;
555
556        /* insert newly created directory handle into the ncache */
557        PINT_ncache_update((const char*) sm_p->u.mkdir.object_name,
558                           (const PVFS_object_ref*) &directory_ref,
559                           (const PVFS_object_ref*) &(sm_p->object_ref));
560    }
561    else if ((PVFS_ERROR_CLASS(-sm_p->error_code) == PVFS_ERROR_BMI) &&
562             (sm_p->u.mkdir.retry_count < sm_p->msgarray_op.params.retry_limit))
563    {
564        sm_p->u.mkdir.stored_error_code = 0;
565        sm_p->u.mkdir.retry_count++;
566
567        gossip_debug(GOSSIP_CLIENT_DEBUG, "Retrying mkdir operation "
568                     "(attempt number %d)\n", sm_p->u.mkdir.retry_count);
569
570        js_p->error_code = MKDIR_RETRY;
571        return SM_ACTION_COMPLETE;
572    }
573    else
574    {
575        PINT_acache_invalidate(sm_p->object_ref);
576        PVFS_perror_gossip("mkdir failed with error", sm_p->error_code);
577    }
578
579    if(sm_p->u.mkdir.dist_dir_bitmap)
580    {
581        free(sm_p->u.mkdir.dist_dir_bitmap);
582        sm_p->u.mkdir.dist_dir_bitmap = NULL;
583    }
584
585    if(sm_p->u.mkdir.dirdata_handles)
586    {
587        free(sm_p->u.mkdir.dirdata_handles);
588        sm_p->u.mkdir.dirdata_handles = NULL;
589    }
590
591    PINT_SET_OP_COMPLETE;
592    return SM_ACTION_TERMINATE;
593}
594
595/** looks at the attributes of the parent directory and decides if it impacts
596 *  the mkdir in any way
597 */
598static PINT_sm_action mkdir_parent_getattr_inspect(
599        struct PINT_smcb *smcb, job_status_s *js_p)
600{
601    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
602    PVFS_object_attr *attr = NULL;
603    int i;
604    int ret = -PVFS_EINVAL;
605
606    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: parent_getattr_inspect\n");
607
608    attr = &sm_p->getattr.attr;
609    assert(attr);
610
611    /* !!! change later */
612    gossip_debug(GOSSIP_CLIENT_DEBUG,
613        "parent owner: %d, group: %d, perms: %d, dirdata_server_count: %d\n",
614        (int)attr->owner, (int)attr->group, (int)attr->perms,
615        attr->u.dir.dist_dir_attr.num_servers);
616    for (i = 0; i < attr->u.dir.dist_dir_attr.num_servers; i++)
617    {
618        gossip_debug(GOSSIP_CLIENT_DEBUG,
619                     "                           dirdata_handle[%d] = %llu\n",
620                     i, llu(attr->u.dir.dirdata_handles[i]));
621    }
622
623    /* do we have a setgid bit? */
624    if(attr->perms & PVFS_G_SGID)
625    {
626        gossip_debug(GOSSIP_CLIENT_DEBUG, "parent has setgid bit set.\n");
627        gossip_debug(GOSSIP_CLIENT_DEBUG, " - modifying requested attr for new file.\n");
628        sm_p->u.mkdir.sys_attr.group = attr->group;
629        sm_p->u.mkdir.sys_attr.perms |= PVFS_G_SGID;
630        /* note that permission checking is left to server even in this case */
631    }
632
633    PINT_dist_dir_attr_copyto(sm_p->u.mkdir.dist_dir_attr, attr->u.dir.dist_dir_attr);
634
635    sm_p->u.mkdir.dist_dir_bitmap = malloc(
636        sizeof(PVFS_dist_dir_bitmap_basetype) * attr->u.dir.dist_dir_attr.bitmap_size);
637    sm_p->u.mkdir.dirdata_handles = malloc(
638        sizeof(*attr->u.dir.dirdata_handles) * attr->u.dir.dist_dir_attr.num_servers);
639    if (!sm_p->u.mkdir.dist_dir_bitmap ||
640            !sm_p->u.mkdir.dirdata_handles)
641    {
642        return -PVFS_ENOMEM;
643    }
644    memcpy(sm_p->u.mkdir.dist_dir_bitmap,
645            attr->u.dir.dist_dir_bitmap,
646            sizeof(PVFS_dist_dir_bitmap_basetype) * attr->u.dir.dist_dir_attr.bitmap_size);
647    memcpy(sm_p->u.mkdir.dirdata_handles,
648           attr->u.dir.dirdata_handles,
649           sizeof(*attr->u.dir.dirdata_handles) * attr->u.dir.dist_dir_attr.num_servers);
650
651    /* Determine the number of dirent files. For now just assume we will use
652     * all the metadata servers.
653     */
654    ret = PINT_cached_config_get_num_meta(sm_p->object_ref.fs_id,
655                                            &sm_p->u.mkdir.num_dirent_files);
656    if(ret < 0)
657    {
658        gossip_err("Error: failed to get number of metadata servers\n");
659        js_p->error_code = ret;
660        return SM_ACTION_COMPLETE;
661    }
662
663    return SM_ACTION_COMPLETE;
664}
665
666static PINT_sm_action mkdir_seteattr_setup_msgpair(
667        struct PINT_smcb *smcb, job_status_s *js_p)
668{
669    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
670    int eattr_count = 0;
671    int cur_index = 0;
672    PINT_sm_msgpair_state *msg_p = NULL;
673    int ret = -PVFS_EINVAL;
674
675    /* NOTE: any memory allocated here will be free'd in the cleanup function */
676
677    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: seteattr_setup_msgpair\n");
678   
679    /* don't set any hint attributes if the parent doesn't have them */
680    if(!(sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT))
681    {
682        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: skipping seteattr\n");
683        js_p->error_code = MKDIR_SKIP_EATTR;
684        return SM_ACTION_COMPLETE;
685    }
686
687    /* count how many hints we acquired */
688    if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
689        eattr_count++;
690    if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
691        eattr_count++;
692    if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
693        eattr_count++;
694
695    if(eattr_count == 0)
696    {
697        /* nothing to inherit */
698        js_p->error_code = MKDIR_SKIP_EATTR;
699        return SM_ACTION_COMPLETE;
700    }
701
702    sm_p->u.mkdir.key_array = (PVFS_ds_keyval*)calloc(eattr_count,
703        sizeof(PVFS_ds_keyval));
704    if(!sm_p->u.mkdir.key_array)
705    {
706        js_p->error_code = -PVFS_ENOMEM;
707        return SM_ACTION_COMPLETE;
708    }
709
710    sm_p->u.mkdir.val_array = (PVFS_ds_keyval*)calloc(eattr_count,
711        sizeof(PVFS_ds_keyval));
712    if(!sm_p->u.mkdir.val_array)
713    {
714        js_p->error_code = -PVFS_ENOMEM;
715        return SM_ACTION_COMPLETE;
716    }
717
718    if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
719    {
720        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting num_dfiles\n");
721        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.num_dfiles";
722        sm_p->u.mkdir.key_array[cur_index].buffer_sz =
723            strlen("user.pvfs2.num_dfiles") + 1;
724
725        sm_p->u.mkdir.val_array[cur_index].buffer = calloc(1, 16);
726        if(!sm_p->u.mkdir.val_array[cur_index].buffer)
727        {
728            js_p->error_code = -PVFS_ENOMEM;
729            return SM_ACTION_COMPLETE;
730        }
731        snprintf((char*)sm_p->u.mkdir.val_array[cur_index].buffer,
732            16, "%d", sm_p->getattr.attr.u.dir.hint.dfile_count);
733        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
734            strlen((char*)sm_p->u.mkdir.val_array[cur_index].buffer) + 1;
735
736        cur_index++;
737    }
738    if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
739    {
740        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_name\n");
741        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_name";
742        sm_p->u.mkdir.key_array[cur_index].buffer_sz =
743            strlen("user.pvfs2.dist_name") + 1;
744        sm_p->u.mkdir.val_array[cur_index].buffer =
745            sm_p->getattr.attr.u.dir.hint.dist_name;
746        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
747            sm_p->getattr.attr.u.dir.hint.dist_name_len;
748
749        cur_index++;
750    }
751    if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
752    {
753        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_params\n");
754        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_params";
755        sm_p->u.mkdir.key_array[cur_index].buffer_sz =
756            strlen("user.pvfs2.dist_params") + 1;
757
758        sm_p->u.mkdir.val_array[cur_index].buffer =
759            sm_p->getattr.attr.u.dir.hint.dist_params;
760        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
761            sm_p->getattr.attr.u.dir.hint.dist_params_len;
762
763        cur_index++;
764    }
765
766    PINT_msgpair_init(&sm_p->msgarray_op);
767    msg_p = &sm_p->msgarray_op.msgpair;
768
769    PINT_SERVREQ_SETEATTR_FILL(
770            msg_p->req,
771            (*sm_p->cred_p),
772            sm_p->object_ref.fs_id,
773            sm_p->u.mkdir.metafile_handle,
774            0,
775            eattr_count,
776            sm_p->u.mkdir.key_array,
777            sm_p->u.mkdir.val_array,
778            sm_p->hints);
779
780    msg_p->fs_id = sm_p->object_ref.fs_id;
781    msg_p->handle = sm_p->u.mkdir.metafile_handle;
782    msg_p->retry_flag = PVFS_MSGPAIR_RETRY;
783    /* NOTE: no comp_fn needed. */
784
785    ret = PINT_cached_config_map_to_server(
786            &msg_p->svr_addr,
787            msg_p->handle,
788            msg_p->fs_id);
789    if (ret)
790    {
791        gossip_err("Failed to map meta server address\n");
792        js_p->error_code = ret;
793    }
794    else
795    {
796        js_p->error_code = 0;
797    }
798
799    PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
800    return SM_ACTION_COMPLETE;
801}
802
803static PINT_sm_action mkdir_seteattr_failure(
804        struct PINT_smcb *smcb, job_status_s *js_p)
805{
806    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
807    sm_p->u.mkdir.stored_error_code = js_p->error_code;
808
809    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_seteattr_failure\n");
810
811    PVFS_perror_gossip("mkdir seteattr failed", js_p->error_code);
812    return SM_ACTION_COMPLETE;
813}
814
815/*
816 * Local variables:
817 *  mode: c
818 *  c-indent-level: 4
819 *  c-basic-offset: 4
820 * End:
821 *
822 * vim: ft=c ts=8 sts=4 sw=4 expandtab
823 */
Note: See TracBrowser for help on using the browser.