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

Revision 8596, 23.6 KB (checked in by shuangy, 3 years ago)

1. fix two memory leaks in fee_object_attr and decode_release. 2. clean sys-mkdir and acache.

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->getattr.attr.u.dir.dist_dir_attr,
427            sm_p->getattr.attr.u.dir.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->getattr.attr.u.dir.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->getattr.attr.u.dir.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->getattr.attr.u.dir.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    PINT_SET_OP_COMPLETE;
597    return SM_ACTION_TERMINATE;
598}
599
600/** looks at the attributes of the parent directory and decides if it impacts
601 *  the mkdir in any way
602 */
603static PINT_sm_action mkdir_parent_getattr_inspect(
604        struct PINT_smcb *smcb, job_status_s *js_p)
605{
606    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
607    PVFS_object_attr *attr = NULL;
608    int i;
609    int ret = -PVFS_EINVAL;
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    /* Determine the number of dirent files. For now just assume we will use
639     * all the metadata servers.
640     */
641    ret = PINT_cached_config_get_num_meta(sm_p->object_ref.fs_id,
642                                            &sm_p->u.mkdir.num_dirent_files);
643    if(ret < 0)
644    {
645        gossip_err("Error: failed to get number of metadata servers\n");
646        js_p->error_code = ret;
647        return SM_ACTION_COMPLETE;
648    }
649
650    return SM_ACTION_COMPLETE;
651}
652
653static PINT_sm_action mkdir_seteattr_setup_msgpair(
654        struct PINT_smcb *smcb, job_status_s *js_p)
655{
656    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
657    int eattr_count = 0;
658    int cur_index = 0;
659    PINT_sm_msgpair_state *msg_p = NULL;
660    int ret = -PVFS_EINVAL;
661
662    /* NOTE: any memory allocated here will be free'd in the cleanup function */
663
664    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: seteattr_setup_msgpair\n");
665   
666    /* don't set any hint attributes if the parent doesn't have them */
667    if(!(sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT))
668    {
669        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: skipping seteattr\n");
670        js_p->error_code = MKDIR_SKIP_EATTR;
671        return SM_ACTION_COMPLETE;
672    }
673
674    /* count how many hints we acquired */
675    if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
676        eattr_count++;
677    if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
678        eattr_count++;
679    if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
680        eattr_count++;
681
682    if(eattr_count == 0)
683    {
684        /* nothing to inherit */
685        js_p->error_code = MKDIR_SKIP_EATTR;
686        return SM_ACTION_COMPLETE;
687    }
688
689    sm_p->u.mkdir.key_array = (PVFS_ds_keyval*)calloc(eattr_count,
690        sizeof(PVFS_ds_keyval));
691    if(!sm_p->u.mkdir.key_array)
692    {
693        js_p->error_code = -PVFS_ENOMEM;
694        return SM_ACTION_COMPLETE;
695    }
696
697    sm_p->u.mkdir.val_array = (PVFS_ds_keyval*)calloc(eattr_count,
698        sizeof(PVFS_ds_keyval));
699    if(!sm_p->u.mkdir.val_array)
700    {
701        js_p->error_code = -PVFS_ENOMEM;
702        return SM_ACTION_COMPLETE;
703    }
704
705    if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
706    {
707        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting num_dfiles\n");
708        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.num_dfiles";
709        sm_p->u.mkdir.key_array[cur_index].buffer_sz =
710            strlen("user.pvfs2.num_dfiles") + 1;
711
712        sm_p->u.mkdir.val_array[cur_index].buffer = calloc(1, 16);
713        if(!sm_p->u.mkdir.val_array[cur_index].buffer)
714        {
715            js_p->error_code = -PVFS_ENOMEM;
716            return SM_ACTION_COMPLETE;
717        }
718        snprintf((char*)sm_p->u.mkdir.val_array[cur_index].buffer,
719            16, "%d", sm_p->getattr.attr.u.dir.hint.dfile_count);
720        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
721            strlen((char*)sm_p->u.mkdir.val_array[cur_index].buffer) + 1;
722
723        cur_index++;
724    }
725    if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
726    {
727        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_name\n");
728        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_name";
729        sm_p->u.mkdir.key_array[cur_index].buffer_sz =
730            strlen("user.pvfs2.dist_name") + 1;
731        sm_p->u.mkdir.val_array[cur_index].buffer =
732            sm_p->getattr.attr.u.dir.hint.dist_name;
733        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
734            sm_p->getattr.attr.u.dir.hint.dist_name_len;
735
736        cur_index++;
737    }
738    if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
739    {
740        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_params\n");
741        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_params";
742        sm_p->u.mkdir.key_array[cur_index].buffer_sz =
743            strlen("user.pvfs2.dist_params") + 1;
744
745        sm_p->u.mkdir.val_array[cur_index].buffer =
746            sm_p->getattr.attr.u.dir.hint.dist_params;
747        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
748            sm_p->getattr.attr.u.dir.hint.dist_params_len;
749
750        cur_index++;
751    }
752
753    PINT_msgpair_init(&sm_p->msgarray_op);
754    msg_p = &sm_p->msgarray_op.msgpair;
755
756    PINT_SERVREQ_SETEATTR_FILL(
757            msg_p->req,
758            (*sm_p->cred_p),
759            sm_p->object_ref.fs_id,
760            sm_p->u.mkdir.metafile_handle,
761            0,
762            eattr_count,
763            sm_p->u.mkdir.key_array,
764            sm_p->u.mkdir.val_array,
765            sm_p->hints);
766
767    msg_p->fs_id = sm_p->object_ref.fs_id;
768    msg_p->handle = sm_p->u.mkdir.metafile_handle;
769    msg_p->retry_flag = PVFS_MSGPAIR_RETRY;
770    /* NOTE: no comp_fn needed. */
771
772    ret = PINT_cached_config_map_to_server(
773            &msg_p->svr_addr,
774            msg_p->handle,
775            msg_p->fs_id);
776    if (ret)
777    {
778        gossip_err("Failed to map meta server address\n");
779        js_p->error_code = ret;
780    }
781    else
782    {
783        js_p->error_code = 0;
784    }
785
786    PINT_sm_push_frame(smcb, 0, &sm_p->msgarray_op);
787    return SM_ACTION_COMPLETE;
788}
789
790static PINT_sm_action mkdir_seteattr_failure(
791        struct PINT_smcb *smcb, job_status_s *js_p)
792{
793    struct PINT_client_sm *sm_p = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
794    sm_p->u.mkdir.stored_error_code = js_p->error_code;
795
796    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_seteattr_failure\n");
797
798    PVFS_perror_gossip("mkdir seteattr failed", js_p->error_code);
799    return SM_ACTION_COMPLETE;
800}
801
802/*
803 * Local variables:
804 *  mode: c
805 *  c-indent-level: 4
806 *  c-basic-offset: 4
807 * End:
808 *
809 * vim: ft=c ts=8 sts=4 sw=4 expandtab
810 */
Note: See TracBrowser for help on using the browser.