/** * fsal_internal_proxy_create_fh : * * * @param pnfs4_handle [IN] the NFSv4 Handle * @param type [IN] the type of object for this entry * @param fileid [IN] the file id for this entry * @param pfsal_handle [OUT] the resulting FSAL Handle * * @return TRUE if OK, FALSE otherwise * */ int fsal_internal_proxy_create_fh(nfs_fh4 * pnfs4_handle, fsal_nodetype_t type, fsal_u64_t fileid, fsal_handle_t * fsal_handle) { proxyfsal_handle_t * pfsal_handle = (proxyfsal_handle_t *) fsal_handle; if(pnfs4_handle == NULL || pfsal_handle == NULL) return FALSE; if(isFullDebug(COMPONENT_FSAL)) { char outstr[1024]; nfs4_sprint_fhandle(pnfs4_handle, outstr); LogFullDebug(COMPONENT_FSAL, "fsal_internal_proxy_create_fh: input nfsv4 server handle=%s", outstr); } memset( (char *)pfsal_handle, 0, sizeof( proxyfsal_handle_t ) ) ; pfsal_handle->data.object_type_reminder = type; pfsal_handle->data.fileid4 = fileid; pfsal_handle->data.timestamp = /** @todo fh should be volatile ? ServerBootTime ; */ 0; pfsal_handle->data.srv_handle_len = pnfs4_handle->nfs_fh4_len; memset(pfsal_handle->data.srv_handle_val, 0, FSAL_PROXY_FILEHANDLE_MAX_LEN); memcpy(pfsal_handle->data.srv_handle_val, pnfs4_handle->nfs_fh4_val, pnfs4_handle->nfs_fh4_len); if(isFullDebug(COMPONENT_FSAL)) { char outstr[1024]; if(type == FSAL_TYPE_FILE) { nfs_fh4 tmpfh; tmpfh.nfs_fh4_len = pfsal_handle->data.srv_handle_len; tmpfh.nfs_fh4_val = pfsal_handle->data.srv_handle_val; nfs4_sprint_fhandle(&tmpfh, outstr); LogFullDebug(COMPONENT_FSAL, "fsal_internal_proxy_create_fh: output nfsv4 server handle= %s fileid=%llu", outstr, fileid); } if(memcmp (pfsal_handle->data.srv_handle_val, pnfs4_handle->nfs_fh4_val, pnfs4_handle->nfs_fh4_len)) LogFullDebug(COMPONENT_FSAL, "CRITICAL ERROR: ==========> Filehandle mismatch n ifsal_internal_proxy_create"); } return TRUE; } /* fsal_internal_proxy_create_fh */
/** * fsal_internal_proxy_extract_fh : * Do the FSAL -> NFSv4 FH conversion * * * @param pnfs4_handle [OUT] the NFSv4 Handle * @param pfsal_handle [IN] the resulting FSAL Handle * * @return TRUE if OK, FALSE otherwise * */ int fsal_internal_proxy_extract_fh(nfs_fh4 * pnfs4_handle, proxyfsal_handle_t * pfsal_handle) { if(pnfs4_handle == NULL || pfsal_handle == NULL) return FALSE; pnfs4_handle->nfs_fh4_len = pfsal_handle->data.srv_handle_len; pnfs4_handle->nfs_fh4_val = pfsal_handle->data.srv_handle_val; if(isFullDebug(COMPONENT_FSAL)) { char outstr[1024]; nfs4_sprint_fhandle(pnfs4_handle, outstr); LogFullDebug(COMPONENT_FSAL, "fsal_internal_proxy_extract_fh: input nfsv4 server handle=%s\n", outstr); } return TRUE; } /* fsal_internal_proxy_extract_fh */
int CreateROOTFH4(nfs_fh4 * fh, compound_data_t * data) { pseudofs_entry_t psfsentry; int status = 0; char fhstr[LEN_FH_STR]; psfsentry = *(data->pseudofs->reverse_tab[0]); if((status = nfs4_AllocateFH(&(data->rootFH))) != NFS4_OK) return status; if(!nfs4_PseudoToFhandle(&(data->rootFH), &psfsentry)) { return NFS4ERR_BADHANDLE; } /* Test */ nfs4_sprint_fhandle(&data->rootFH, fhstr); LogDebug(COMPONENT_NFS_V4, "CREATE ROOTFH: %s", fhstr); return NFS4_OK; } /* CreateROOTFH4 */
int nfs4_op_putfh(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { int rc; int error; fsal_attrib_list_t attr; char outstr[1024]; char __attribute__ ((__unused__)) funcname[] = "nfs4_op_putfh"; resp->resop = NFS4_OP_PUTFH; res_PUTFH4.status = NFS4_OK; /* If there is no FH */ if(nfs4_Is_Fh_Empty(&(arg_PUTFH4.object))) { res_PUTFH4.status = NFS4ERR_NOFILEHANDLE; return res_PUTFH4.status; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(arg_PUTFH4.object))) { res_PUTFH4.status = NFS4ERR_BADHANDLE; return res_PUTFH4.status; } /* Tests if teh Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(arg_PUTFH4.object))) { res_PUTFH4.status = NFS4ERR_FHEXPIRED; return res_PUTFH4.status; } /* If no currentFH were set, allocate one */ if(data->currentFH.nfs_fh4_len == 0) { if((error = nfs4_AllocateFH(&(data->currentFH))) != NFS4_OK) { res_PUTFH4.status = error; return res_PUTFH4.status; } } /* The same is to be done with mounted_on_FH */ if(data->mounted_on_FH.nfs_fh4_len == 0) { if((error = nfs4_AllocateFH(&(data->mounted_on_FH))) != NFS4_OK) { res_PUTFH4.status = error; return res_PUTFH4.status; } } /* Copy the filehandle from the reply structure */ data->currentFH.nfs_fh4_len = arg_PUTFH4.object.nfs_fh4_len; data->mounted_on_FH.nfs_fh4_len = arg_PUTFH4.object.nfs_fh4_len; /* Put the data in place */ memcpy(data->currentFH.nfs_fh4_val, arg_PUTFH4.object.nfs_fh4_val, arg_PUTFH4.object.nfs_fh4_len); memcpy(data->mounted_on_FH.nfs_fh4_val, arg_PUTFH4.object.nfs_fh4_val, arg_PUTFH4.object.nfs_fh4_len); nfs4_sprint_fhandle(&arg_PUTFH4.object, outstr); LogDebug(COMPONENT_NFS_V4, "NFS4_OP_PUTFH CURRENTFH BEFORE: File handle = %s", outstr); /* If the filehandle is not pseudo hs file handle, get the entry related to it, otherwise use fake values */ if(nfs4_Is_Fh_Pseudo(&(data->currentFH))) { data->current_entry = NULL; data->current_filetype = DIR_BEGINNING; data->pexport = NULL; /* No exportlist is related to pseudo fs */ } else { /* If data->exportp is null, a junction from pseudo fs was traversed, credp and exportp have to be updated */ if(data->pexport == NULL) { if((error = nfs4_SetCompoundExport(data)) != NFS4_OK) { res_PUTFH4.status = error; return res_PUTFH4.status; } } /* Build the pentry */ if((data->current_entry = nfs_FhandleToCache(NFS_V4, NULL, NULL, &(data->currentFH), NULL, NULL, &(res_PUTFH4.status), &attr, data->pcontext, data->pclient, data->ht, &rc)) == NULL) { res_PUTFH4.status = NFS4ERR_BADHANDLE; return res_PUTFH4.status; } /* Extract the filetype */ data->current_filetype = cache_inode_fsal_type_convert(attr.type); } /* Trace */ return NFS4_OK; } /* nfs4_op_putfh */
int nfs4_op_putrootfh(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { int error; char __attribute__ ((__unused__)) funcname[] = "nfs4_op_putrootfh"; char fhstr[LEN_FH_STR]; /* This NFS4 Operation has no argument, it just get then ROOTFH (replace MOUNTPROC3_MNT) */ /* First of all, set the reply to zero to make sure it contains no parasite information */ memset(resp, 0, sizeof(struct nfs_resop4)); resp->resop = NFS4_OP_PUTROOTFH; resp->nfs_resop4_u.opputrootfh.status = NFS4_OK; if((error = CreateROOTFH4(&(data->rootFH), data)) != NFS4_OK) { res_PUTROOTFH4.status = error; return res_PUTROOTFH4.status; } data->current_entry = NULL; /* No cache inode entry for the directory within pseudo fs */ data->current_filetype = DIR_BEGINNING; /* Only directory in the pseudo fs */ /* I copy the root FH to the currentFH and, if not already done, to the publicFH */ /* For the moment, I choose to have rootFH = publicFH */ /* For initial mounted_on_FH, I'll use the rootFH, this will change at junction traversal */ if(data->currentFH.nfs_fh4_len == 0) { if((error = nfs4_AllocateFH(&(data->currentFH))) != NFS4_OK) { resp->nfs_resop4_u.opputrootfh.status = error; return error; } } memcpy((char *)(data->currentFH.nfs_fh4_val), (char *)(data->rootFH.nfs_fh4_val), data->rootFH.nfs_fh4_len); data->currentFH.nfs_fh4_len = data->rootFH.nfs_fh4_len; if(data->mounted_on_FH.nfs_fh4_len == 0) { if((error = nfs4_AllocateFH(&(data->mounted_on_FH))) != NFS4_OK) { resp->nfs_resop4_u.opputrootfh.status = error; return error; } } memcpy((char *)(data->mounted_on_FH.nfs_fh4_val), (char *)(data->rootFH.nfs_fh4_val), data->rootFH.nfs_fh4_len); data->mounted_on_FH.nfs_fh4_len = data->rootFH.nfs_fh4_len; if(data->publicFH.nfs_fh4_len == 0) { if((error = nfs4_AllocateFH(&(data->publicFH))) != NFS4_OK) { resp->nfs_resop4_u.opputrootfh.status = error; return error; } } /* Copy the data where they are supposed to be */ memcpy((char *)(data->publicFH.nfs_fh4_val), (char *)(data->rootFH.nfs_fh4_val), data->rootFH.nfs_fh4_len); data->publicFH.nfs_fh4_len = data->rootFH.nfs_fh4_len; /* Test */ nfs4_sprint_fhandle(&data->rootFH, fhstr); LogDebug(COMPONENT_NFS_V4, "NFS4 PUTROOTFH: rootFH=%s", fhstr); nfs4_sprint_fhandle(&data->currentFH, fhstr); LogDebug(COMPONENT_NFS_V4, "NFS4 PUTROOTFH: currentFH=%s", fhstr); LogFullDebug(COMPONENT_NFS_V4, "NFS4 PUTROOTFH: Ending on status %d", resp->nfs_resop4_u.opputrootfh.status); return resp->nfs_resop4_u.opputrootfh.status; } /* nfs4_op_putrootfh */
/** * FSAL_create: * Create a regular file. * * \param parent_directory_handle (input): * Handle of the parent directory where the file is to be created. * \param p_filename (input): * Pointer to the name of the file to be created. * \param cred (input): * Authentication context for the operation (user, export...). * \param accessmode (input): * Mode for the file to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param object_handle (output): * Pointer to the handle of the created file. * \param object_attributes (optionnal input/output): * The postop attributes of the created file. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * Can be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_STALE (parent_directory_handle does not address an existing object) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ... * * NB: if getting postop attributes failed, * the function does not return an error * but the FSAL_ATTR_RDATTR_ERR bit is set in * the object_attributes->asked_attributes field. */ fsal_status_t PROXYFSAL_create(proxyfsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_filename, /* IN */ proxyfsal_op_context_t * p_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ proxyfsal_handle_t * object_handle, /* OUT */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; COMPOUND4args argnfs4; COMPOUND4res resnfs4; nfs_fh4 nfs4fh; bitmap4 bitmap; uint32_t bitmap_val[2]; uint32_t bitmap_res[2]; uint32_t bitmap_conv_val[2]; uint32_t bitmap_create[2]; uint32_t bitmap_getattr_res[2]; fattr4 input_attr; bitmap4 convert_bitmap; component4 name; char nameval[MAXNAMLEN]; char padfilehandle[FSAL_PROXY_FILEHANDLE_MAX_LEN]; fsal_status_t fsal_status; proxyfsal_file_t fd; #define FSAL_CREATE_NB_OP_ALLOC 4 #define FSAL_CREATE_VAL_BUFFER 1024 fsal_proxy_internal_fattr_t fattr_internal; fsal_attrib_list_t create_mode_attr; fsal_attrib_list_t attributes; nfs_argop4 argoparray[FSAL_CREATE_NB_OP_ALLOC]; nfs_resop4 resoparray[FSAL_CREATE_NB_OP_ALLOC]; char fattr_val[FSAL_CREATE_VAL_BUFFER]; struct timeval timeout = { 25, 0 }; char owner_val[FSAL_PROXY_OWNER_LEN]; unsigned int owner_len = 0; /* sanity checks. * note : object_attributes is optional. */ if(!parent_directory_handle || !p_context || !object_handle || !p_filename) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); PRINT_HANDLE("FSAL_create", parent_directory_handle); /* Create the owner */ snprintf(owner_val, FSAL_PROXY_OWNER_LEN, "GANESHA/PROXY: pid=%u ctx=%p file=%llu", getpid(), p_context, (unsigned long long int)p_context->file_counter); owner_len = strnlen(owner_val, FSAL_PROXY_OWNER_LEN); p_context->file_counter += 1; /* Setup results structures */ argnfs4.argarray.argarray_val = argoparray; resnfs4.resarray.resarray_val = resoparray; argnfs4.minorversion = 0; /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Mkdir" ; */ argnfs4.tag.utf8string_val = NULL; argnfs4.tag.utf8string_len = 0; argnfs4.argarray.argarray_len = 0; input_attr.attrmask.bitmap4_val = bitmap_val; input_attr.attrmask.bitmap4_len = 2; input_attr.attr_vals.attrlist4_val = fattr_val; input_attr.attr_vals.attrlist4_len = FSAL_CREATE_VAL_BUFFER; fsal_internal_proxy_setup_fattr(&fattr_internal); convert_bitmap.bitmap4_val = bitmap_conv_val; convert_bitmap.bitmap4_len = 2; memset((char *)&name, 0, sizeof(component4)); name.utf8string_val = nameval; if(fsal_internal_proxy_fsal_name_2_utf8(p_filename, &name) == FALSE) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); /* Get NFSv4 File handle */ if(fsal_internal_proxy_extract_fh(&nfs4fh, parent_directory_handle) == FALSE) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); if(isFullDebug(COMPONENT_FSAL)) { char outstr[1024]; nfs4_sprint_fhandle(&nfs4fh, outstr); LogFullDebug(COMPONENT_FSAL, "FSAL_CREATE: extracted server (as client) parent handle=%s\n", outstr); } bitmap.bitmap4_val = bitmap_create; bitmap.bitmap4_len = 2; fsal_internal_proxy_create_fattr_bitmap(&bitmap); create_mode_attr.asked_attributes = FSAL_ATTR_MODE; create_mode_attr.mode = accessmode; fsal_interval_proxy_fsalattr2bitmap4(&create_mode_attr, &convert_bitmap); if(nfs4_FSALattr_To_Fattr(NULL, /* no exportlist required here */ &create_mode_attr, &input_attr, NULL, /* no compound data required here */ NULL, /* No fh here, filehandle is not a settable attribute */ &convert_bitmap) == -1) Return(ERR_FSAL_INVAL, -1, INDEX_FSAL_create); #define FSAL_CREATE_IDX_OP_PUTFH 0 #define FSAL_CREATE_IDX_OP_OPEN_CREATE 1 #define FSAL_CREATE_IDX_OP_GETFH 2 #define FSAL_CREATE_IDX_OP_GETATTR 3 COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh); COMPOUNDV4_ARG_ADD_OP_OPEN_CREATE(argnfs4, name, input_attr, p_context->clientid, owner_val, owner_len); COMPOUNDV4_ARG_ADD_OP_GETFH(argnfs4); COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, bitmap); resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen. OPEN4res_u.resok4.attrset.bitmap4_val = bitmap_res; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen. OPEN4res_u.resok4.attrset.bitmap4_len = 2; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh. GETFH4res_u.resok4.object.nfs_fh4_val = (char *)padfilehandle; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh. GETFH4res_u.resok4.object.nfs_fh4_len = FSAL_PROXY_FILEHANDLE_MAX_LEN; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_getattr_res; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val = (char *)&fattr_internal; resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len = sizeof(fattr_internal); TakeTokenFSCall(); /* Call the NFSv4 function */ COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc); if(rc != RPC_SUCCESS) { ReleaseTokenFSCall(); Return(ERR_FSAL_IO, rc, INDEX_FSAL_create); } ReleaseTokenFSCall(); /* >> convert error code, and return on error << */ if(resnfs4.status != NFS4_OK) return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_create); /* Use NFSv4 service function to build the FSAL_attr */ if(nfs4_Fattr_To_FSAL_attr(&attributes, &resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETATTR]. nfs_resop4_u.opgetattr.GETATTR4res_u.resok4. obj_attributes) != 1) { FSAL_CLEAR_MASK(attributes.asked_attributes); FSAL_SET_MASK(attributes.asked_attributes, FSAL_ATTR_RDATTR_ERR); Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_create); } /* Return attributes if asked */ if(object_attributes) { memcpy(object_attributes, &attributes, sizeof(attributes)); } if(isFullDebug(COMPONENT_FSAL)) { char outstr[1024]; nfs4_sprint_fhandle(&nfs4fh, outstr); LogFullDebug(COMPONENT_FSAL, "FSAL_CREATE: extracted server (as client) created file handle=%s\n", outstr); } if(fsal_internal_proxy_create_fh (& (resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_GETFH].nfs_resop4_u.opgetfh. GETFH4res_u.resok4.object), FSAL_TYPE_FILE, attributes.fileid, object_handle) == FALSE) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); /* Keep the information into the file descriptor as well */ memcpy((char *)&fd.fhandle, (char *)object_handle, sizeof(fd.fhandle)); fd.openflags = FSAL_O_RDWR; fd.current_offset = 0; fd.pcontext = p_context; /* Keep the returned stateid for later use */ fd.stateid.seqid = resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen. OPEN4res_u.resok4.stateid.seqid; memcpy((char *)fd.stateid.other, resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u. opopen.OPEN4res_u.resok4.stateid.other, 12); /* See if a OPEN_CONFIRM is required */ if(resnfs4.resarray.resarray_val[FSAL_CREATE_IDX_OP_OPEN_CREATE].nfs_resop4_u.opopen. OPEN4res_u.resok4.rflags & OPEN4_RESULT_CONFIRM) { fsal_status = FSAL_proxy_open_confirm(&fd); if(FSAL_IS_ERROR(fsal_status)) Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_create); } #ifdef _FSAL_CREATE_CLOSE_FILE /* The craeted file is still opened, to preserve the correct seqid for later use, we close it */ fsal_status = FSAL_close(&fd); if(FSAL_IS_ERROR(fsal_status)) Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_create); #endif /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create); } /* FSAL_create */