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

Revision 8508, 24.7 KB (checked in by elaine, 3 years ago)

Fixes to lookup.

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