/** * * nfs3_FSALToFhandle: converts a FSAL file handle to a nfs3 file handle. * * Converts a nfs3 file handle to a FSAL file handle. * * @param pfh3 [OUT] pointer to the extracted file handle * @param pfsalhandle [IN] pointer to the FSAL handle to be converted * @param pexport [IN] pointer to the export list entry the FH belongs to * * @return 1 if successful, 0 otherwise * */ int nfs3_FSALToFhandle(nfs_fh3 * pfh3, fsal_handle_t * pfsalhandle, exportlist_t * pexport) { fsal_status_t fsal_status; file_handle_v3_t file_handle; print_buff(COMPONENT_FILEHANDLE, (char *)pfsalhandle, sizeof(fsal_handle_t)); /* zero-ification of the buffer to be used as handle */ memset(pfh3->data.data_val, 0, NFS3_FHSIZE); memset((caddr_t) &file_handle, 0, sizeof(file_handle_v3_t)); /* Fill in the fs opaque part */ fsal_status = FSAL_DigestHandle(&pexport->FS_export_context, FSAL_DIGEST_NFSV3, pfsalhandle, (caddr_t) & file_handle.fsopaque); if(FSAL_IS_ERROR(fsal_status)) return 0; /* keep track of the export id */ file_handle.exportid = pexport->id; /* Set the last byte */ file_handle.xattr_pos = 0; /* Set the len */ pfh3->data.data_len = sizeof(file_handle_v3_t); /* Set the data */ memcpy(pfh3->data.data_val, &file_handle, sizeof(file_handle_v3_t)); print_fhandle3(COMPONENT_FILEHANDLE, pfh3); return 1; } /* nfs3_FSALToFhandle */
/** * * nfs4_FSALToFhandle: converts a FSAL file handle to a nfs4 file handle. * * Converts a nfs4 file handle to a FSAL file handle. * * @param pfh4 [OUT] pointer to the extracted file handle * @param pfsalhandle [IN] pointer to the FSAL handle to be converted * @param data [IN] pointer to NFSv4 compound data structure. * * @return 1 if successful, 0 otherwise * */ int nfs4_FSALToFhandle(nfs_fh4 * pfh4, fsal_handle_t * pfsalhandle, compound_data_t * data) { fsal_status_t fsal_status; file_handle_v4_t file_handle; /* zero-ification of the buffer to be used as handle */ memset(pfh4->nfs_fh4_val, 0, sizeof(file_handle_v4_t)); memset((caddr_t) &file_handle, 0, sizeof(file_handle_v4_t)); /* Fill in the fs opaque part */ fsal_status = FSAL_DigestHandle(&data->pexport->FS_export_context, FSAL_DIGEST_NFSV4, pfsalhandle, (caddr_t) & file_handle.fsopaque); if(FSAL_IS_ERROR(fsal_status)) return 0; /* keep track of the export id */ file_handle.exportid = data->pexport->id; /* No Pseudo fs here */ file_handle.pseudofs_id = 0; file_handle.pseudofs_flag = FALSE; file_handle.ds_flag = 0; file_handle.refid = 0; /* if FH expires, set it there */ if(nfs_param.nfsv4_param.fh_expire == TRUE) { LogFullDebug(COMPONENT_NFS_V4, "An expireable file handle was created."); file_handle.srvboot_time = ServerBootTime; } else { /* Non expirable FH */ file_handle.srvboot_time = 0; } /* Set the last byte */ file_handle.xattr_pos = 0; /* Set the len */ pfh4->nfs_fh4_len = sizeof(file_handle_v4_t); /* Set the data */ memcpy(pfh4->nfs_fh4_val, &file_handle, sizeof(file_handle_v4_t)); return 1; } /* nfs4_FSALToFhandle */
/** * * nfs2_FSALToFhandle: converts a FSAL file handle to a nfs2 file handle. * * Converts a nfs2 file handle to a FSAL file handle. * * @param pfh2 [OUT] pointer to the extracted file handle * @param pfsalhandle [IN] pointer to the FSAL handle to be converted * @param pfsalhandle [IN] pointer to the FSAL handle to be converted * * @return 1 if successful, 0 otherwise * */ int nfs2_FSALToFhandle(fhandle2 * pfh2, fsal_handle_t * pfsalhandle, exportlist_t * pexport) { fsal_status_t fsal_status; file_handle_v2_t file_handle; print_buff(COMPONENT_FILEHANDLE, (char *)pfsalhandle, sizeof(fsal_handle_t)); /* zero-ification of the buffer to be used as handle */ memset(pfh2, 0, NFS2_FHSIZE); memset((caddr_t) &file_handle, 0, sizeof(file_handle_v2_t)); /* Fill in the fs opaque part */ fsal_status = FSAL_DigestHandle(&pexport->FS_export_context, FSAL_DIGEST_NFSV2, pfsalhandle, (caddr_t) & file_handle.fsopaque); if(FSAL_IS_ERROR(fsal_status)) { if( fsal_status.major == ERR_FSAL_TOOSMALL ) LogCrit( COMPONENT_FILEHANDLE, "NFSv2 file handle is too small to manage this fsal" ) ; else LogCrit( COMPONENT_FILEHANDLE, "FSAL_DigestHandle return (%u,%u) when called from %s", fsal_status.major, fsal_status.minor, __func__ ) ; return 0; } /* keep track of the export id */ file_handle.exportid = pexport->id; /* Set the last byte */ file_handle.xattr_pos = 0; /* Set the data */ memcpy((caddr_t) pfh2, &file_handle, sizeof(file_handle_v2_t)); print_fhandle2(COMPONENT_FILEHANDLE, pfh2); return 1; } /* nfs2_FSALToFhandle */
fsal_status_t PROXYFSAL_truncate(proxyfsal_handle_t * filehandle, /* IN */ proxyfsal_op_context_t * p_context, /* IN */ fsal_size_t length, /* IN */ fsal_file_t * file_descriptor, /* [IN|OUT] */ fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ ) { int rc; COMPOUND4args argnfs4; COMPOUND4res resnfs4; nfs_fh4 nfs4fh; uint64_t fileid; fsal_status_t fsal_status; fsal_attrib_list_t open_attrs; bitmap4 inbitmap; bitmap4 convert_bitmap; uint32_t inbitmap_val[2]; uint32_t bitmap_res[2]; uint32_t bitmap_set[2]; uint32_t bitmap_conv_val[2]; #define FSAL_TRUNCATE_NB_OP_ALLOC 3 nfs_argop4 argoparray[FSAL_TRUNCATE_NB_OP_ALLOC]; nfs_resop4 resoparray[FSAL_TRUNCATE_NB_OP_ALLOC]; fsal_attrib_list_t fsal_attr_set; fattr4 fattr_set; fsal_proxy_internal_fattr_t fattr_internal; struct timeval timeout = { 25, 0 }; /* sanity checks. * note : object_attributes is optional. */ if(!filehandle || !p_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate); if(filehandle->data.object_type_reminder != FSAL_TYPE_FILE) { Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate); } if(file_descriptor == NULL) { /* Use the stateless version */ fsal_status = FSAL_proxy_truncate_stateless(filehandle, p_context, length, object_attributes); Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* First, we need to get the fileid on a filehandle base */ fsal_status = FSAL_DigestHandle(p_context->export_context, FSAL_DIGEST_FILEID4, filehandle, (caddr_t) & fileid); if(FSAL_IS_ERROR(fsal_status)) { Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* Then we have of open the file by fileid */ open_attrs.asked_attributes = FSAL_ATTRS_POSIX; fsal_status = FSAL_open_by_fileid(filehandle, fileid, p_context, FSAL_O_RDWR, file_descriptor, &open_attrs); if(FSAL_IS_ERROR(fsal_status)) { Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* Setup results structures */ argnfs4.argarray.argarray_val = argoparray; resnfs4.resarray.resarray_val = resoparray; fsal_internal_proxy_setup_fattr(&fattr_internal); argnfs4.minorversion = 0; /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Truncate" ; */ argnfs4.tag.utf8string_val = NULL; argnfs4.tag.utf8string_len = 0; argnfs4.argarray.argarray_len = 0; /* Get NFSv4 File handle */ if(fsal_internal_proxy_extract_fh(&nfs4fh, filehandle) == FALSE) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_truncate); /* Get prepared for truncate */ fsal_attr_set.asked_attributes = FSAL_ATTR_SIZE; fsal_attr_set.filesize = length; convert_bitmap.bitmap4_val = bitmap_conv_val; convert_bitmap.bitmap4_len = 2; fsal_interval_proxy_fsalattr2bitmap4(&fsal_attr_set, &convert_bitmap); if(nfs4_FSALattr_To_Fattr(NULL, /* no exportlist required here */ &fsal_attr_set, &fattr_set, 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_truncate); inbitmap.bitmap4_val = inbitmap_val; inbitmap.bitmap4_len = 2; fsal_internal_proxy_create_fattr_bitmap(&inbitmap); #define FSAL_TRUNCATE_IDX_OP_PUTFH 0 #define FSAL_TRUNCATE_IDX_OP_SETATTR 1 #define FSAL_TRUNCATE_IDX_OP_GETATTR 2 COMPOUNDV4_ARG_ADD_OP_PUTFH(argnfs4, nfs4fh); COMPOUNDV4_ARG_ADD_OP_SETATTR(argnfs4, fattr_set); COMPOUNDV4_ARG_ADD_OP_GETATTR(argnfs4, inbitmap); /* For ATTR_SIZE, stateid is needed */ argnfs4.argarray.argarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_argop4_u.opsetattr. stateid.seqid = file_descriptor->stateid.seqid; memcpy(argnfs4.argarray.argarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_argop4_u. opsetattr.stateid.other, file_descriptor->stateid.other, 12); resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_val = bitmap_res; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attrmask.bitmap4_len = 2; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_val = (char *)&fattr_internal; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u.opgetattr. GETATTR4res_u.resok4.obj_attributes.attr_vals.attrlist4_len = sizeof(fattr_internal); resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_resop4_u.opsetattr. attrsset.bitmap4_val = bitmap_set; resnfs4.resarray.resarray_val[FSAL_TRUNCATE_IDX_OP_SETATTR].nfs_resop4_u.opsetattr. attrsset.bitmap4_len = 2; TakeTokenFSCall(); COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc); if(rc != RPC_SUCCESS) { ReleaseTokenFSCall(); Return(ERR_FSAL_IO, 0, INDEX_FSAL_truncate); } ReleaseTokenFSCall(); if(resnfs4.status != NFS4_OK) return fsal_internal_proxy_error_convert(resnfs4.status, INDEX_FSAL_truncate); /* >> interpret error code << */ /* >> Optionnaly retrieve post op attributes * If your filesystem truncate call can't return them, * you can proceed like this : << */ if(object_attributes) { if(nfs4_Fattr_To_FSAL_attr(object_attributes, &resnfs4.resarray. resarray_val[FSAL_TRUNCATE_IDX_OP_GETATTR].nfs_resop4_u. opgetattr.GETATTR4res_u.resok4.obj_attributes) != 1) { FSAL_CLEAR_MASK(object_attributes->asked_attributes); FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_truncate); } } /* Close the previously opened filedescriptor */ fsal_status = FSAL_close_by_fileid(file_descriptor, fileid); if(FSAL_IS_ERROR(fsal_status)) { Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_truncate); } /* No error occured */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_truncate); }
int main(int argc, char **argv) { char localmachine[256]; char *test; fsal_parameter_t init_param; fsal_status_t st; uid_t uid; fsal_export_context_t export_ctx; fsal_op_context_t op_ctx; fsal_handle_t root_handle, handle; fsal_name_t name; fsal_path_t path; fsal_attrib_list_t attribs; fsal_attrib_mask_t mask; char tracebuff[256]; if(argc < 2) { usage(); exit(-1); } test = argv[1]; /* retrieving params */ #ifndef _NO_BUDDY_SYSTEM BuddyInit(NULL); #endif /* init debug */ SetNamePgm("test_fsal"); SetDefaultLogging("TEST"); SetNameFunction("main"); InitLogging(); /* Obtention du nom de la machine */ if(gethostname(localmachine, sizeof(localmachine)) != 0) { LogError(COMPONENT_STDOUT,ERR_SYS, ERR_GETHOSTNAME, errno); exit(1); } else SetNameHost(localmachine); AddFamilyError(ERR_FSAL, "FSAL related Errors", tab_errstatus_FSAL); /* prepare fsal_init */ /* 1 - fs specific info */ #ifdef _USE_HPSS_51 init_param.fs_specific_info.behaviors.PrincipalName = FSAL_INIT_FORCE_VALUE; strcpy(init_param.fs_specific_info.hpss_config.PrincipalName, "hpss_nfs"); init_param.fs_specific_info.behaviors.KeytabPath = FSAL_INIT_FORCE_VALUE; strcpy(init_param.fs_specific_info.hpss_config.KeytabPath, "/krb5/hpssserver.keytab"); #elif defined _USE_HPSS_62 init_param.fs_specific_info.behaviors.AuthnMech = FSAL_INIT_FORCE_VALUE; init_param.fs_specific_info.hpss_config.AuthnMech = hpss_authn_mech_krb5; init_param.fs_specific_info.behaviors.Principal = FSAL_INIT_FORCE_VALUE; strcpy(init_param.fs_specific_info.Principal, "hpssfs"); init_param.fs_specific_info.behaviors.KeytabPath = FSAL_INIT_FORCE_VALUE; strcpy(init_param.fs_specific_info.KeytabPath, "/var/hpss/etc/hpss.keytab"); #endif /* 2-common info (default) */ FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxfilesize); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxlink); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxnamelen); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxpathlen); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, no_trunc); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, chown_restricted); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, case_insensitive); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, case_preserving); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, fh_expire_type); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, link_support); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, symlink_support); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, named_attr); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, unique_handles); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, lease_time); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, acl_support); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, cansettime); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, homogenous); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, supported_attrs); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxread); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, maxwrite); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, umask); FSAL_SET_INIT_DEFAULT(init_param.fs_common_info, auth_exportpath_xdev); /* 3- fsal info */ init_param.fsal_info.max_fs_calls = 0; /* Init */ if(FSAL_IS_ERROR(st = FSAL_Init(&init_param))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } /* getting creds */ uid = getuid(); LogTest("uid = %d", uid); st = FSAL_BuildExportContext(&export_ctx, NULL, NULL); if(FSAL_IS_ERROR(st)) LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); st = FSAL_InitClientContext(&op_ctx); if(FSAL_IS_ERROR(st)) LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); st = FSAL_GetClientContext(&op_ctx, &export_ctx, uid, -1, NULL, 0); if(FSAL_IS_ERROR(st)) LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); /* getting root handle */ if(FSAL_IS_ERROR(st = FSAL_lookup(NULL, NULL, &op_ctx, &root_handle, NULL))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &root_handle); LogTest("Root handle = %s", tracebuff); /* getting what are the supported attributes */ attribs.asked_attributes = 0; FSAL_SET_MASK(attribs.asked_attributes, FSAL_ATTR_SUPPATTR); LogTest("asked attributes :"); printmask(attribs.asked_attributes); if(FSAL_IS_ERROR(st = ZFSFSAL_getattrs(&root_handle, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } LogTest("supported attributes :"); printmask(attribs.supported_attributes); mask = attribs.supported_attributes; /* TEST 1 */ if(test[0] == '1') { attribs.asked_attributes = 0; FSAL_SET_MASK(attribs.asked_attributes, FSAL_ATTR_SUPPATTR); LogTest("asked attributes :"); printmask(attribs.asked_attributes); if(FSAL_IS_ERROR(st = ZFSFSAL_getattrs(&root_handle, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } LogTest("supported attributes :"); /* getting all spported attributes of root */ attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = ZFSFSAL_getattrs(&root_handle, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } printattributes(attribs); } else /* TEST 2 */ if(test[0] == '2') { /* getting handle and attributes for subdirectory "OSF1_V5" */ if(FSAL_IS_ERROR(st = FSAL_str2name("cea", 4, &name))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookup(&root_handle, &name, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea handle = %s", tracebuff); /* displaying attributes */ printattributes(attribs); /* getting handle and attributes for subdirectory "bin" */ if(FSAL_IS_ERROR(st = FSAL_str2name("prot", 5, &name))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } root_handle = handle; attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookup(&root_handle, &name, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot handle = %s", tracebuff); /* displaying attributes */ printattributes(attribs); /* getting handle and attributes for symlink "AglaePwrSW" */ if(FSAL_IS_ERROR(st = FSAL_str2name("lama", 5, &name))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } root_handle = handle; attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookup(&root_handle, &name, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot/lama handle = %s", tracebuff); /* displaying attributes */ printattributes(attribs); } else /* TEST 3 */ if(test[0] == '3') { /* lookup root */ if(FSAL_IS_ERROR(st = FSAL_str2path("/", 30, &path))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookupPath(&path, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/ handle = %s", tracebuff); /* displaying attributes */ printattributes(attribs); /* lookup path */ if(FSAL_IS_ERROR(st = FSAL_str2path("/cea/prot/lama", 15, &path))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookupPath(&path, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot/lama handle = %s", tracebuff); /* displaying attributes */ printattributes(attribs); } else /* TEST 4 */ if(test[0] == '4') { /* readdir on root */ fsal_dir_t dir; fsal_cookie_t from, to; fsal_dirent_t entries[READDIR_SIZE]; fsal_count_t number; fsal_boolean_t eod = FALSE; int error = FALSE; attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_opendir(&root_handle, &op_ctx, &dir, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } LogTest("'/' attributes :"); /* displaying attributes */ printattributes(attribs); from = FSAL_READDIR_FROM_BEGINNING; while(!error && !eod) { unsigned int i; char cookiebuff[256]; snprintCookie(cookiebuff, 256, &from); LogTest("\nReaddir cookie = %s", cookiebuff); if(FSAL_IS_ERROR(st = FSAL_readdir(&dir, from, mask, READDIR_SIZE * sizeof(fsal_dirent_t), entries, &to, &number, &eod))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); error = TRUE; } for(i = 0; (!error) && (i < number); i++) { snprintHandle(tracebuff, 256, &entries[i].handle); snprintCookie(cookiebuff, 256, &entries[i].cookie); LogTest("\t%s : %s (cookie %s)", tracebuff, entries[i].name.name, cookiebuff); } /* preparing next call */ from = to; } LogTest("Fin de boucle : error=%d ; eod=%d", error, eod); } else /* TEST 5 */ if(test[0] == '5') { /* readdir on root */ fsal_dir_t dir; fsal_cookie_t from, to; fsal_dirent_t entries[READDIR_SIZE]; fsal_count_t number; fsal_boolean_t eod = FALSE; int error = FALSE; attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_opendir(&root_handle, &op_ctx, &dir, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } LogTest("'/' attributes :"); /* displaying attributes */ printattributes(attribs); from = FSAL_READDIR_FROM_BEGINNING; while(!error && !eod) { fsal_dirent_t *curr; char cookiebuff[256]; snprintCookie(cookiebuff, 256, &from); LogTest("\nReaddir cookie = %s", cookiebuff); if(FSAL_IS_ERROR(st = FSAL_readdir(&dir, from, mask, READDIR_SIZE * sizeof(fsal_dirent_t), entries, &to, &number, &eod))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); error = TRUE; } if(number > 0) { curr = entries; do { snprintHandle(tracebuff, 256, &curr->handle); snprintCookie(cookiebuff, 256, &curr->cookie); LogTest("\t%s : %s (cookie %s)", tracebuff, curr->name.name, cookiebuff); } while(curr = curr->nextentry); } /* preparing next call */ from = to; } LogTest("Fin de boucle : error=%d ; eod=%d", error, eod); } else /* TEST 6 */ if(test[0] == '6') { /* readdir on root */ fsal_dir_t dir; fsal_cookie_t from, to; fsal_dirent_t entries[READDIR_SIZE]; fsal_count_t number; fsal_boolean_t eod = FALSE; int error = FALSE; attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_opendir(&root_handle, &op_ctx, &dir, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } LogTest("'/' attributes :"); /* displaying attributes */ printattributes(attribs); from = FSAL_READDIR_FROM_BEGINNING; while(!error && !eod) { unsigned int i; snprintCookie(tracebuff, 256, &from); LogTest("\nReaddir cookie = %s", tracebuff); st = FSAL_readdir(&dir, from, mask, READDIR_SIZE * sizeof(fsal_dirent_t), entries, &to, &number, &eod); if(FSAL_IS_ERROR(st)) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); error = TRUE; } /* for each entry, we compare the result of FSAL_access * to FSAL_test_access. */ for(i = 0; (!error) && (i < number); i++) { fsal_status_t st1, st2; char cookiebuff[256]; snprintHandle(tracebuff, 256, &entries[i].handle); snprintCookie(cookiebuff, 256, &entries[i].cookie); LogTest("\t%s : %s (cookie %s)", tracebuff, entries[i].name.name, cookiebuff); if(FSAL_IS_ERROR(st = ZFSFSAL_getattrs(&entries[i].handle, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } /* 1 - test R access */ st1 = FSAL_access(&entries[i].handle, &op_ctx, FSAL_R_OK, NULL); st2 = FSAL_test_access(&op_ctx, FSAL_R_OK, &attribs); LogError(COMPONENT_STDOUT, ERR_FSAL, st1.major, st1.minor); LogError(COMPONENT_STDOUT, ERR_FSAL, st2.major, st2.minor); if(st1.major != st2.major) { LogTest ("Error : different access permissions given by FSAL_access and FSAL_test_access : %d <>%d", st1.major, st2.major); } /* 2 - test W access */ st1 = FSAL_access(&entries[i].handle, &op_ctx, FSAL_W_OK, NULL); st2 = FSAL_test_access(&op_ctx, FSAL_W_OK, &attribs); LogError(COMPONENT_STDOUT, ERR_FSAL, st1.major, st1.minor); LogError(COMPONENT_STDOUT, ERR_FSAL, st2.major, st2.minor); if(st1.major != st2.major) { LogTest ("Error : different access permissions given by FSAL_access and FSAL_test_access : %d <>%d", st1.major, st2.major); } /* 3 - test X access */ st1 = FSAL_access(&entries[i].handle, &op_ctx, FSAL_X_OK, NULL); st2 = FSAL_test_access(&op_ctx, FSAL_X_OK, &attribs); LogError(COMPONENT_STDOUT, ERR_FSAL, st1.major, st1.minor); LogError(COMPONENT_STDOUT, ERR_FSAL, st2.major, st2.minor); if(st1.major != st2.major) { LogTest ("Error : different access permissions given by FSAL_access and FSAL_test_access : %d <>%d", st1.major, st2.major); } } /* preparing next call */ from = to; } LogTest("Fin de boucle : error=%d ; eod=%d", error, eod); } else /* TEST 7 */ if(test[0] == '7') { /* test snprintmem and sscanmem */ char test_string[] = "Ceci est une chaine d'essai.\nLes chiffres : 0123456789\nLes lettres : ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char buffer[256]; char string[200]; /* 200 suffit car test_string fait <100 */ int size1, size2, size3, i; /* we put bad values in string, to see if it is correctly set. */ for(i = 0; i < 200; i++) string[i] = (char)i; LogTest("Initial data (%d Bytes) = <<%s>>", strlen(test_string), test_string); /* Write test_string to a buffer. */ /* We don't give the final '\0'. */ snprintmem(buffer, 256, test_string, strlen(test_string)); LogTest("Dest_Buffer (%d Bytes) = <<%s>>", strlen(buffer), buffer); /* read the value from the buffer */ sscanmem(string, strlen(test_string), buffer); /* sets the final 0 to print the content of the buffer */ LogTest("Retrieved string : following byte = %d", (int)string[strlen(test_string)]); string[strlen(test_string)] = '\0'; LogTest("Retrieved string (%d Bytes) = <<%s>>", strlen(string), string); /* Automatic tests : */ size1 = strlen(test_string); size2 = strlen(buffer); size3 = strlen(string); LogTest("-------------------------------------"); if(size1 <= 0) LogTest("***** ERROR: source size=0 !!!"); if(size1 != size3) LogTest("***** ERROR: source size <> target size"); else LogTest("OK: source size = target size"); if((size1 * 2) != size2) LogTest("***** ERROR: hexa size <> 2 * source size"); else LogTest("OK: hexa size = 2 * source size"); if(strcmp(test_string, string)) LogTest("***** ERROR: source string <> target string"); else LogTest("OK: source string = target string"); } else /* TEST 8 */ if(test[0] == '8') { fsal_handle_t dir_hdl, subdir_hdl; fsal_name_t subdir_name; /* lookup on /cea/prot/S/lama/s8/leibovic */ if(FSAL_IS_ERROR(st = FSAL_str2path("/cea/prot/S/lama/s8/leibovic", 40, &path))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookupPath(&path, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot/S/lama/s8/leibovic: handle = %s", tracebuff); sleep(1); /* creates a directory */ LogTest("------- Create a directory -------"); if(FSAL_IS_ERROR(st = FSAL_str2name("tests_GANESHA", 30, &name))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_mkdir(&handle, &name, &op_ctx, FSAL_MODE_RUSR | FSAL_MODE_WUSR | FSAL_MODE_XUSR | FSAL_MODE_RGRP | FSAL_MODE_WGRP, &dir_hdl, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { snprintHandle(tracebuff, 256, &dir_hdl); LogTest("newly created dir handle = %s", tracebuff); printattributes(attribs); } sleep(1); /* Try to create it again */ LogTest("------- Try to create it again -------"); if(FSAL_IS_ERROR(st = FSAL_mkdir(&handle, &name, &op_ctx, FSAL_MODE_RUSR | FSAL_MODE_WUSR | FSAL_MODE_XUSR | FSAL_MODE_RGRP | FSAL_MODE_WGRP, &dir_hdl, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { LogTest("**** Error: FSAL should have returned ERR_FSAL_EXIST"); } sleep(1); /* creates a subdirectory */ LogTest("------- Create a subdirectory -------"); if(FSAL_IS_ERROR(st = FSAL_str2name("subdir_GANESHA", 30, &subdir_name))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } if(FSAL_IS_ERROR(st = FSAL_mkdir(&dir_hdl, &subdir_name, &op_ctx, FSAL_MODE_RUSR | FSAL_MODE_WUSR | FSAL_MODE_XUSR | FSAL_MODE_RGRP | FSAL_MODE_WGRP, &subdir_hdl, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { snprintHandle(tracebuff, 256, &subdir_hdl); LogTest("newly created subdir handle = %s", tracebuff); printattributes(attribs); } /* try to removes the parent directory */ LogTest("------- Try to removes the parent directory -------"); if(FSAL_IS_ERROR(st = FSAL_unlink(&handle, &name, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { LogTest("FSAL should not have unlinked %s because it is not empty", name.name); } sleep(1); /* removes the subdirectory */ LogTest("------- Removes the subdirectory -------"); if(FSAL_IS_ERROR(st = FSAL_unlink(&dir_hdl, &subdir_name, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { LogTest("New attributes for parent directory:"); printattributes(attribs); } /* removes the parent directory */ LogTest("------- Removes the parent directory -------"); if(FSAL_IS_ERROR(st = FSAL_unlink(&handle, &name, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { LogTest("Unlink %s OK", name.name); } } /* TEST 9 */ else if(test[0] == '9') { fsal_handle_t dir_hdl, subdir_hdl; fsal_name_t subdir_name; fsal_attrib_list_t attr_set; fsal_fsid_t set_fsid = { 1LL, 2LL }; #ifdef _LINUX struct tm jour_heure = { 56, 34, 12, 31, 12, 110, 0, 0, 0, 0, 0 }; #else struct tm jour_heure = { 56, 34, 12, 31, 12, 110, 0, 0, 0 }; #endif /* lookup on /cea/prot/S/lama/s8/leibovic */ if(FSAL_IS_ERROR(st = FSAL_str2path("/cea/prot/S/lama/s8/leibovic", 40, &path))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookupPath(&path, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot/S/lama/s8/leibovic: handle = %s", tracebuff); sleep(1); /* creates a file */ LogTest("------- Create a file -------"); if(FSAL_IS_ERROR(st = FSAL_str2name("tests_GANESHA_setattrs", 30, &name))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_create(&handle, &name, &op_ctx, FSAL_MODE_RUSR | FSAL_MODE_WUSR | FSAL_MODE_XUSR | FSAL_MODE_RGRP | FSAL_MODE_WGRP, &dir_hdl, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { snprintHandle(tracebuff, 256, &dir_hdl); LogTest("newly created file handle = %s", tracebuff); printattributes(attribs); } sleep(1); LogTest("------- Try to change its attributes -------"); /* Macro that try to change the value for an attribute */ #define CHANGE_ATTRS( str_nom, nom, flag, new_val ) do {\ memset(&attr_set, 0, sizeof(fsal_attrib_list_t) ); \ LogTest("\nTry to change '%s' :",str_nom); \ FSAL_SET_MASK( attr_set.asked_attributes , flag ); \ attr_set.nom = new_val; \ attribs.asked_attributes = attr_set.asked_attributes; \ /* attribs.asked_attributes = mask; */\ st = FSAL_setattrs( &dir_hdl, &op_ctx, &attr_set, &attribs );\ if ( FSAL_IS_ERROR(st) ) \ LogError(COMPONENT_STDOUT,ERR_FSAL,st.major,st.minor);\ else \ printattributes( attribs ); \ } while(0) CHANGE_ATTRS("supported_attributes", supported_attributes, FSAL_ATTR_SUPPATTR, FSAL_ATTRS_MANDATORY); CHANGE_ATTRS("type", type, FSAL_ATTR_TYPE, FSAL_TYPE_LNK); sleep(1); /* to see mtime modification by truncate */ CHANGE_ATTRS("filesize", filesize, FSAL_ATTR_SIZE, (fsal_size_t) 12); sleep(1); /* to see mtime modification by truncate */ CHANGE_ATTRS("fsid", fsid, FSAL_ATTR_FSID, set_fsid); /* @todo : ACLs */ CHANGE_ATTRS("fileid", fileid, FSAL_ATTR_FILEID, (fsal_u64_t) 1234); CHANGE_ATTRS("mode", mode, FSAL_ATTR_MODE, (FSAL_MODE_RUSR | FSAL_MODE_WUSR | FSAL_MODE_RGRP)); CHANGE_ATTRS("numlinks", numlinks, FSAL_ATTR_NUMLINKS, 7); /* FSAL_ATTR_RAWDEV */ CHANGE_ATTRS("atime", atime.seconds, FSAL_ATTR_ATIME, mktime(&jour_heure)); jour_heure.tm_min++; CHANGE_ATTRS("creation", creation.seconds, FSAL_ATTR_CREATION, mktime(&jour_heure)); jour_heure.tm_min++; CHANGE_ATTRS("mtime", mtime.seconds, FSAL_ATTR_MTIME, mktime(&jour_heure)); jour_heure.tm_min++; CHANGE_ATTRS("ctime", ctime.seconds, FSAL_ATTR_CTIME, mktime(&jour_heure)); CHANGE_ATTRS("spaceused", spaceused, FSAL_ATTR_SPACEUSED, (fsal_size_t) 12345); CHANGE_ATTRS("mounted_on_fileid", mounted_on_fileid, FSAL_ATTR_MOUNTFILEID, (fsal_u64_t) 3210); CHANGE_ATTRS("owner", owner, FSAL_ATTR_OWNER, 3051); /* deniel */ CHANGE_ATTRS("group", group, FSAL_ATTR_GROUP, 5953); /* sr */ sleep(1); /* removes the parent directory */ LogTest("------- Removes the directory -------"); if(FSAL_IS_ERROR(st = FSAL_unlink(&handle, &name, &op_ctx, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { LogTest("Unlink %s OK", name.name); } } else if(test[0] == 'A') { char digest_buff[FSAL_DIGEST_SIZE_HDLV3]; /* lookup on /cea/prot/S/lama/s8/leibovic */ if(FSAL_IS_ERROR(st = FSAL_str2path("/cea/prot/S/lama/s8/leibovic", 40, &path))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } attribs.asked_attributes = mask; if(FSAL_IS_ERROR(st = FSAL_lookupPath(&path, &op_ctx, &handle, &attribs))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot/S/lama/s8/leibovic: handle = %s", tracebuff); /* building digest */ st = FSAL_DigestHandle(&export_ctx, FSAL_DIGEST_NFSV3, &handle, digest_buff); if(FSAL_IS_ERROR(st)) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { /* print digest */ snprintmem(tracebuff, 256, digest_buff, FSAL_DIGEST_SIZE_HDLV3); LogTest("/cea/prot/S/lama/s8/leibovic: handle_digest = %s", tracebuff); } memset(&handle, 0, sizeof(fsal_handle_t)); /* expend digest */ st = FSAL_ExpandHandle(&export_ctx, FSAL_DIGEST_NFSV3, digest_buff, &handle); if(FSAL_IS_ERROR(st)) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); } else { /* print expended handle */ snprintHandle(tracebuff, 256, &handle); LogTest("/cea/prot/S/lama/s8/leibovic: handle expended = %s", tracebuff); } } else if(test[0] == 'B') { fsal_dynamicfsinfo_t dyninfo; if(FSAL_IS_ERROR(st = FSAL_dynamic_fsinfo(&root_handle, &op_ctx, &dyninfo))) { LogError(COMPONENT_STDOUT, ERR_FSAL, st.major, st.minor); exit(st.major); } LogTest("total_bytes = %llu", dyninfo.total_bytes); LogTest("free_bytes = %llu", dyninfo.free_bytes); LogTest("avail_bytes = %llu", dyninfo.avail_bytes); LogTest("total_files = %llu", dyninfo.total_files); LogTest("free_files = %llu", dyninfo.free_files); LogTest("avail_files = %llu", dyninfo.avail_files); LogTest("time_delta = %u.%u", dyninfo.time_delta.seconds, dyninfo.time_delta.nseconds); } else LogTest("%s : test inconnu", test); return 0; }
int main(int argc, char *argv[]) { int c; int exportid = 0; char buffer[CMD_BUFFER_SIZE]; char str[2 * CMD_BUFFER_SIZE]; fhandle2 filehandle_v2; struct nfs_fh3 filehandle_v3; nfs_fh4 filehandle_v4; int flag_i = FALSE; char exec_name[MAXPATHLEN]; char *tempo_exec_name = NULL; cache_inode_fsal_data_t fsal_data; fsal_op_context_t fsal_op_context; fsal_export_context_t fsal_export_context; exportlist_t *pexportlist = NULL; exportlist_t *pexport = NULL; nfs_start_info_t nfs_start_info; fsal_status_t fsal_status; unsigned int nfs_version = 3; path_str_t fsal_path_lib[NB_AVAILABLE_FSAL]; #ifdef _USE_SHARED_FSAL int lentab = NB_AVAILABLE_FSAL ; #endif short cache_content_hash; char entry_path[MAXPATHLEN]; int i, nb_char; fsal_path_t export_path = FSAL_PATH_INITIALIZER; unsigned int cookie; fsal_xattrent_t xattr_array[256]; unsigned int nb_returned; int eol; char attr_buffer[4096]; size_t sz_returned; fsal_u64_t objid; char options[] = "h@f:v:i:"; char usage[] = "%s [-h][-f <cfg_path>] {-v 2|3|4 <NFS_FileHandle> | -i <inum>}\n" " -h : prints this help\n" " -f <config_file> : sets the ganesha configuration file to be used\n" " -v <nfs_version> : sets the NFS version the file handle passed as argument\n" " -i <inum> : get datacache path for the given inode number (decimal)\n"; ServerBootTime = time(NULL); SetDefaultLogging("STDERR"); /* What is the executable file's name */ if((tempo_exec_name = strrchr(argv[0], '/')) != NULL) strcpy((char *)exec_name, tempo_exec_name + 1); strncpy(config_path, DEFAULT_CONFIG_FILE, MAXPATHLEN); /* now parsing options with getopt */ while((c = getopt(argc, argv, options)) != EOF) { switch (c) { case '@': printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); exit(0); break; case 'h': printf(usage, exec_name); exit(0); break; case 'f': strncpy(config_path, optarg, MAXPATHLEN); break; case 'i': if(sscanf(optarg, "%llu", &objid) != 1) { fprintf(stderr, "Invalid object_id %s (base-10 integer expected)\n", optarg); exit(1); } flag_i = TRUE; break; case 'v': nfs_version = atoi(optarg); if((nfs_version < 2) || (nfs_version > 4)) { fprintf(stderr, "Invalid nfs version %u\n", nfs_version); exit(1); } break; case '?': printf("Unknown option: %c\n", optopt); printf(usage, exec_name); exit(1); } } if(!flag_i && (optind != argc - 1)) { printf("Missing argument: <NFS_FileHandle>\n"); printf(usage, exec_name); exit(1); } /* initialize memory and logging */ nfs_prereq_init("convert_fh", "localhost", NIV_MAJ, "/dev/tty"); #ifdef _USE_SHARED_FSAL if(nfs_get_fsalpathlib_conf(config_path, fsal_path_lib, &lentab)) { fprintf(stderr, "NFS MAIN: Error parsing configuration file."); exit(1); } #endif /* _USE_SHARED_FSAL */ /* Load the FSAL library (if needed) */ if(!FSAL_LoadLibrary((char *)fsal_path_lib)) /** @todo: this part of the code and this utility has to be checked */ { fprintf(stderr, "NFS MAIN: Could not load FSAL dynamic library %s", (char *)fsal_path_lib[0]); exit(1); } /* Get the FSAL functions */ FSAL_LoadFunctions(); /* Get the FSAL consts */ FSAL_LoadConsts(); /* initialize default parameters */ nfs_set_param_default(); /* parse configuration file */ if(nfs_set_param_from_conf(&nfs_start_info)) { fprintf(stderr, "Error parsing configuration file '%s'", config_path); exit(1); } /* check parameters consitency */ if(nfs_check_param_consistency()) { fprintf(stderr, "Inconsistent parameters found"); exit(1); } if(!nfs_param.pexportlist) { fprintf(stderr, "No export entries found in configuration file !!!\n"); return -1; } pexportlist = nfs_param.pexportlist; /* not initialization is needed for converting fileid to path in datacache */ if(!flag_i) { #ifdef _USE_SHARED_FSAL fsal_status = FSAL_Init(&nfs_param.fsal_param[0]); #else fsal_status = FSAL_Init(&nfs_param.fsal_param); #endif if(FSAL_IS_ERROR(fsal_status)) { /* Failed init */ fprintf(stderr, "FSAL library could not be initialized, major=%d minor=%d\n", fsal_status.major, fsal_status.minor); exit(1); } strncpy(str, argv[optind], 2 * CMD_BUFFER_SIZE); switch (nfs_version) { case 2: if(sscanmem(filehandle_v2, sizeof(file_handle_v2_t), (char *)str) == -1) { fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n", (unsigned long)sizeof(file_handle_v2_t)); exit(1); } exportid = nfs2_FhandleToExportId(&filehandle_v2); break; case 3: if(sscanmem(buffer, sizeof(file_handle_v3_t), (char *)str) == -1) { fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n", (unsigned long)sizeof(file_handle_v3_t)); exit(1); } filehandle_v3.data.data_val = (char *)buffer; filehandle_v3.data.data_len = sizeof(file_handle_v3_t); exportid = nfs3_FhandleToExportId(&filehandle_v3); break; case 4: if(sscanmem(buffer, sizeof(file_handle_v4_t), (char *)str) == -1) { fprintf(stderr, "Bad FH as input (expected size: %lu bytes)\n", (unsigned long)sizeof(file_handle_v4_t)); exit(1); } filehandle_v4.nfs_fh4_val = (char *)buffer; filehandle_v4.nfs_fh4_len = sizeof(file_handle_v4_t); exportid = nfs4_FhandleToExportId(&filehandle_v4); break; } if((pexport = nfs_Get_export_by_id(pexportlist, exportid)) == NULL) { fprintf(stderr, "NFS FH has exportid %u which is invalid....\n", exportid); exit(1); } /* INITIALIZING A CLIENT CONTEXT FOR FSAL */ FSAL_str2path(pexport->fullpath, MAXPATHLEN, &export_path); if(FSAL_IS_ERROR (fsal_status = FSAL_BuildExportContext(&fsal_export_context, &export_path, pexport->FS_specific))) { fprintf(stderr, "Error in FSAL_BuildExportContext, major=%u, minor=%u\n", fsal_status.major, fsal_status.minor); exit(1); } fsal_status = FSAL_InitClientContext(&fsal_op_context); if(FSAL_IS_ERROR(fsal_status)) { /* Failed init */ fprintf(stderr, "Could not init client context... major=%d minor=%d\n", fsal_status.major, fsal_status.minor); exit(1); } fsal_status = FSAL_GetClientContext(&fsal_op_context, &fsal_export_context, 0, 0, NULL, 0); if(FSAL_IS_ERROR(fsal_status)) { /* Failed init */ fprintf(stderr, "Could not get cred for uid=%d gid=%d, major=%d minor=%d\n", getuid(), getgid(), fsal_status.major, fsal_status.minor); exit(1); } /* now, can use the fsal_op_context */ switch (nfs_version) { case 2: if(!nfs2_FhandleToFSAL(&filehandle_v2, &fsal_data.handle, &fsal_op_context)) { fprintf(stderr, "Cannot convert Fhandle to FSAL\n"); exit(1); } break; case 3: if(!nfs3_FhandleToFSAL(&filehandle_v3, &fsal_data.handle, &fsal_op_context)) { fprintf(stderr, "Cannot convert Fhandle to FSAL\n"); exit(1); } break; case 4: if(!nfs4_FhandleToFSAL(&filehandle_v4, &fsal_data.handle, &fsal_op_context)) { fprintf(stderr, "Cannot convert Fhandle to FSAL\n"); exit(1); } break; } printf("\n"); snprintmem((caddr_t) str, 2 * CMD_BUFFER_SIZE, (caddr_t) & fsal_data.handle, sizeof(fsal_data.handle)); printf("%-18s = %s\n", "FSAL Handle", str); /* Now, list FSAL extended attributes */ cookie = XATTRS_READLIST_FROM_BEGINNING; eol = FALSE; while(!eol) { unsigned int index; fsal_status = FSAL_ListXAttrs(&fsal_data.handle, cookie, &fsal_op_context, xattr_array, 256, &nb_returned, &eol); if(FSAL_IS_ERROR(fsal_status)) { fprintf(stderr, "Error executing FSAL_ListXAttrs\n"); exit(1); } /* list attributes and get their value */ for(index = 0; index < nb_returned; index++) { cookie = xattr_array[index].xattr_cookie; printf("%-18s = ", xattr_array[index].xattr_name.name); fsal_status = FSAL_GetXAttrValueByName(&fsal_data.handle, &xattr_array[index].xattr_name, &fsal_op_context, attr_buffer, 4096, &sz_returned); if(FSAL_IS_ERROR(fsal_status)) { fprintf(stderr, "Error executing FSAL_GetXAttrValueByName\n"); } /* Display it */ print_buffer(attr_buffer, sz_returned); } } /* get object ID */ fsal_status = FSAL_DigestHandle(&fsal_export_context, FSAL_DIGEST_FILEID4, &fsal_data.handle, (caddr_t) & objid); if(FSAL_IS_ERROR(fsal_status)) { fprintf(stderr, "Error retrieving fileid from handle\n"); } else { printf("%-18s = %llu\n", "FileId", objid); } } /* end of retrieval of objid */ /* build the path in the datacache */ cache_content_hash = HashFileID4(objid); /* for limiting the number of entries into each datacache directory * we create 256 subdirectories on 2 levels, depending on the entry's fileid. */ nb_char = snprintf(entry_path, MAXPATHLEN, "export_id=%d", 0); for(i = 0; i <= 8; i += 8) { /* concatenation of hashval */ nb_char += snprintf((char *)(entry_path + nb_char), MAXPATHLEN - nb_char, "/%02hhX", (char)((cache_content_hash >> i) & 0xFF)); } /* displays the node name */ printf("%-18s = %s/%s/node=%llx*\n", "DataCache path", nfs_param.cache_layers_param.cache_content_client_param.cache_dir, entry_path, objid); exit(0); }
int nfs3_Readdirplus(nfs_arg_t * parg, exportlist_t * pexport, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres) { static char __attribute__ ((__unused__)) funcName[] = "nfs3_Readdirplus"; typedef char entry_name_array_item_t[FSAL_MAX_NAME_LEN]; typedef char fh3_buffer_item_t[NFS3_FHSIZE]; unsigned int delta = 0; cache_entry_t *dir_pentry = NULL; cache_entry_t *pentry_dot_dot = NULL; unsigned long dircount; unsigned long maxcount; fsal_attrib_list_t dir_attr; fsal_attrib_list_t entry_attr; uint64_t begin_cookie; uint64_t end_cookie; uint64_t cache_inode_cookie; cache_inode_dir_entry_t **dirent_array = NULL; cookieverf3 cookie_verifier; int rc; unsigned int i = 0; unsigned int num_entries; unsigned long space_used; unsigned long estimated_num_entries; unsigned long asked_num_entries; cache_inode_file_type_t dir_filetype; cache_inode_endofdir_t eod_met = UNASSIGNED_EOD; cache_inode_status_t cache_status; cache_inode_status_t cache_status_gethandle; fsal_handle_t *pfsal_handle = NULL; entry_name_array_item_t *entry_name_array = NULL; fh3_buffer_item_t *fh3_array = NULL; entryplus3 reference_entry; READDIRPLUS3resok reference_reply; int dir_pentry_unlock = FALSE; if(isDebug(COMPONENT_NFSPROTO) || isDebug(COMPONENT_NFS_READDIR)) { char str[LEN_FH_STR]; log_components_t component; sprint_fhandle3(str, &(parg->arg_readdirplus3.dir)); if(isDebug(COMPONENT_NFSPROTO)) component = COMPONENT_NFSPROTO; else component = COMPONENT_NFS_READDIR; LogDebug(component, "REQUEST PROCESSING: Calling nfs3_Readdirplus handle: %s", str); } /* to avoid setting it on each error case */ pres->res_readdir3.READDIR3res_u.resfail.dir_attributes.attributes_follow = FALSE; dircount = parg->arg_readdirplus3.dircount; maxcount = parg->arg_readdirplus3.maxcount; begin_cookie = (unsigned int)parg->arg_readdirplus3.cookie; /* FIXME: This calculation over estimates the number of bytes that * READDIRPLUS3resok will use on the wire by 4 bytes on x86_64. */ space_used = sizeof(reference_reply.dir_attributes.attributes_follow) + sizeof(reference_reply.dir_attributes.post_op_attr_u.attributes) + sizeof(reference_reply.cookieverf) + sizeof(reference_reply.reply.eof); estimated_num_entries = (dircount - space_used + sizeof(entry3 *)) / (sizeof(entry3) - sizeof(char *)*2); // estimated_num_entries *= 4; LogFullDebug(COMPONENT_NFS_READDIR, "nfs3_Readdirplus: dircount=%lu maxcount=%lu begin_cookie=%" PRIu64" space_used=%lu estimated_num_entries=%lu", dircount, maxcount, begin_cookie, space_used, estimated_num_entries); /* Is this a xattr FH ? */ if(nfs3_Is_Fh_Xattr(&(parg->arg_readdirplus3.dir))) return nfs3_Readdirplus_Xattr(parg, pexport, pcontext, pclient, ht, preq, pres); /* Convert file handle into a vnode */ if((dir_pentry = nfs_FhandleToCache(preq->rq_vers, NULL, &(parg->arg_readdirplus3.dir), NULL, NULL, &(pres->res_readdirplus3.status), NULL, &dir_attr, pcontext, pclient, ht, &rc)) == NULL) { /* return NFS_REQ_DROP ; */ return rc; } /* Extract the filetype */ dir_filetype = cache_inode_fsal_type_convert(dir_attr.type); /* Sanity checks -- must be a directory */ if(dir_filetype != DIRECTORY) { pres->res_readdirplus3.status = NFS3ERR_NOTDIR; return NFS_REQ_OK; } /* switch */ memset(cookie_verifier, 0, sizeof(cookieverf3)); /* * If cookie verifier is used, then an non-trivial value is * returned to the client This value is the mtime of * the directory. If verifier is unused (as in many NFS * Servers) then only a set of zeros is returned (trivial * value) */ if(pexport->UseCookieVerifier) memcpy(cookie_verifier, &(dir_attr.mtime), sizeof(dir_attr.mtime)); /* * nothing to do if != 0 because the area is already full of * zero */ if(pexport->UseCookieVerifier && (begin_cookie != 0)) { /* * Not the first call, so we have to check the cookie * verifier */ if(memcmp(cookie_verifier, parg->arg_readdirplus3.cookieverf, NFS3_COOKIEVERFSIZE) != 0) { pres->res_readdirplus3.status = NFS3ERR_BAD_COOKIE; return NFS_REQ_OK; } } if((dirent_array = (cache_inode_dir_entry_t **) Mem_Alloc_Label( estimated_num_entries * sizeof(cache_inode_dir_entry_t*), "cache_inode_dir_entry_t in nfs3_Readdirplus")) == NULL) { pres->res_readdirplus3.status = NFS3ERR_IO; return NFS_REQ_DROP; } pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries = NULL; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = FALSE; /** @todo XXXX fix this--compare nfs4_op_readdir */ /* How many entries will we retry from cache_inode ? */ if(begin_cookie > 1) { asked_num_entries = estimated_num_entries; cache_inode_cookie = begin_cookie; } else { asked_num_entries = ((estimated_num_entries > 2) ? estimated_num_entries - 2 : 0); /* Keep space for '.' and '..' */ cache_inode_cookie = 0; } /* A definition that will be very useful to avoid very long names for variables */ #define RES_READDIRPLUS_REPLY pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply /* Call readdir */ if(cache_inode_readdir(dir_pentry, pexport->cache_inode_policy, cache_inode_cookie, asked_num_entries, &num_entries, &end_cookie, &eod_met, dirent_array, ht, &dir_pentry_unlock, pclient, pcontext, &cache_status) == CACHE_INODE_SUCCESS) { LogFullDebug(COMPONENT_NFS_READDIR, "Readdirplus3 -> Call to cache_inode_readdir( cookie=%" PRIu64", asked=%lu ) -> num_entries = %u", cache_inode_cookie, asked_num_entries, num_entries); if(eod_met == END_OF_DIR) { LogFullDebug(COMPONENT_NFS_READDIR, "+++++++++++++++++++++++++++++++++++++++++> EOD MET "); } /* If nothing was found, return nothing, but if cookie=0, we should return . and .. */ if((num_entries == 0) && (asked_num_entries != 0) && (begin_cookie > 1)) { pres->res_readdirplus3.status = NFS3_OK; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries = NULL; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = TRUE; nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, NULL, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok. dir_attributes)); memcpy(pres->res_readdirplus3.READDIRPLUS3res_u.resok.cookieverf, cookie_verifier, sizeof(cookieverf3)); } else { /* Allocation of the structure for reply */ entry_name_array = (entry_name_array_item_t *) Mem_Alloc_Label(estimated_num_entries * (FSAL_MAX_NAME_LEN + 1), "entry_name_array in nfs3_Readdirplus"); if(entry_name_array == NULL) { /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); return NFS_REQ_DROP; } pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries = (entryplus3 *) Mem_Alloc_Label(estimated_num_entries * sizeof(entryplus3), "READDIRPLUS3res_u.resok.reply.entries"); if(pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries == NULL) { /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); return NFS_REQ_DROP; } /* Allocation of the file handles */ fh3_array = (fh3_buffer_item_t *) Mem_Alloc_Label(estimated_num_entries * NFS3_FHSIZE, "Filehandle V3 in nfs3_Readdirplus"); if(fh3_array == NULL) { /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); return NFS_REQ_DROP; } delta = 0; /* manage . and .. */ if(begin_cookie == 0) { /* Fill in '.' */ if(estimated_num_entries > 0) { if((pfsal_handle = cache_inode_get_fsal_handle(dir_pentry, &cache_status_gethandle)) == NULL) { /* after successful cache_inode_readdir, dir_pentry * may be read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } FSAL_DigestHandle(FSAL_GET_EXP_CTX(pcontext), FSAL_DIGEST_FILEID3, pfsal_handle, (caddr_t) & (RES_READDIRPLUS_REPLY.entries[0]. fileid)); RES_READDIRPLUS_REPLY.entries[0].name = entry_name_array[0]; strcpy(RES_READDIRPLUS_REPLY.entries[0].name, "."); RES_READDIRPLUS_REPLY.entries[0].cookie = 1; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle.data.data_val = (char *)fh3_array[0]; if(nfs3_FSALToFhandle (&pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle, pfsal_handle, pexport) == 0) { /* after successful cache_inode_readdir, dir_pentry may * be read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_BADHANDLE; return NFS_REQ_OK; } RES_READDIRPLUS_REPLY.entries[0].name_attributes.attributes_follow = FALSE; RES_READDIRPLUS_REPLY.entries[0].name_handle.handle_follows = FALSE; entry_attr = dir_pentry->attributes; /* Set PostPoFh3 structure */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.handle_follows = TRUE; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle.data.data_len = sizeof(file_handle_v3_t); nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, &entry_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok. reply.entries[0].name_attributes)); LogFullDebug(COMPONENT_NFS_READDIR, "Readdirplus3 -> i=0 num_entries=%d space_used=%lu maxcount=%lu Name=. FileId=%016llx Cookie=%llu", num_entries, space_used, maxcount, RES_READDIRPLUS_REPLY.entries[0].fileid, RES_READDIRPLUS_REPLY.entries[0].cookie); delta += 1; } } /* Fill in '..' */ if(begin_cookie <= 1) { if(estimated_num_entries > delta) { if((pentry_dot_dot = cache_inode_lookupp_sw(dir_pentry, ht, pclient, pcontext, &cache_status_gethandle, !dir_pentry_unlock)) == NULL) { /* after successful cache_inode_readdir, dir_pentry may * be read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } if((pfsal_handle = cache_inode_get_fsal_handle(pentry_dot_dot, &cache_status_gethandle)) == NULL) { /* after successful cache_inode_readdir, dir_pentry may * be read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } FSAL_DigestHandle(FSAL_GET_EXP_CTX(pcontext), FSAL_DIGEST_FILEID3, pfsal_handle, (caddr_t) & (RES_READDIRPLUS_REPLY.entries[delta]. fileid)); RES_READDIRPLUS_REPLY.entries[delta].name = entry_name_array[delta]; strcpy(RES_READDIRPLUS_REPLY.entries[delta].name, ".."); /* Getting a file handle */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.post_op_fh3_u.handle.data.data_val = (char *)fh3_array[delta]; if(nfs3_FSALToFhandle (&pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.post_op_fh3_u.handle, pfsal_handle, pexport) == 0) { /* after successful cache_inode_readdir, dir_pentry may * be read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_BADHANDLE; return NFS_REQ_OK; } RES_READDIRPLUS_REPLY.entries[delta].cookie = 2; RES_READDIRPLUS_REPLY.entries[delta].name_attributes.attributes_follow = FALSE; RES_READDIRPLUS_REPLY.entries[delta].name_handle.handle_follows = FALSE; entry_attr = pentry_dot_dot->attributes; /* Set PostPoFh3 structure */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.handle_follows = TRUE; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.post_op_fh3_u.handle.data.data_len = sizeof(file_handle_v3_t); nfs_SetPostOpAttr(pcontext, pexport, pentry_dot_dot, &entry_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok. reply.entries[delta].name_attributes)); LogFullDebug(COMPONENT_NFS_READDIR, "Readdirplus3 -> i=%d num_entries=%d space_used=%lu maxcount=%lu Name=.. FileId=%016llx Cookie=%llu", delta, num_entries, space_used, maxcount, RES_READDIRPLUS_REPLY.entries[delta].fileid, RES_READDIRPLUS_REPLY.entries[delta].cookie); } RES_READDIRPLUS_REPLY.entries[0].nextentry = &(RES_READDIRPLUS_REPLY.entries[delta]); if(num_entries > delta + 1) /* not 0 ??? */ RES_READDIRPLUS_REPLY.entries[delta].nextentry = &(RES_READDIRPLUS_REPLY.entries[delta + 1]); else RES_READDIRPLUS_REPLY.entries[delta].nextentry = NULL; delta += 1; } /* if( begin_cookie == 0 ) */ for(i = delta; i < num_entries + delta; i++) { unsigned long needed; /* maxcount is the size with the FH and attributes overhead, * so entryplus3 is used instead of entry3. The data structures * in nfs23.h have funny padding depending on the arch (32 or 64). * We can't get an accurate estimate by simply using * sizeof(entryplus3). */ /* FIXME: There is still a 4 byte over estimate here on x86_64. */ /** @todo Remove cookie offset calculation in readdir and readdirplus (obsoleted) */ needed = sizeof(reference_entry) + NFS3_FHSIZE + ((strlen(dirent_array[i - delta]->name.name) + 3) & ~3); /* if delta == 1 or 2, then "." and ".." have already been added * to the readdirplus reply. */ if (i == delta) { needed += needed*delta /* size of a dir entry in reply */ - ((strlen(dirent_array[i - delta]->name.name) + 3) & ~3)*delta /* size of filename for current entry */ + 4*delta; /* size of "." and ".." filenames in reply */ } if((space_used += needed) > maxcount) { /* If delta != 0, then we already added "." or ".." to the reply. */ if(i == delta && delta == 0) { /* Not enough room to make even a single reply */ /* after successful cache_inode_readdir, dir_pentry may * be read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_TOOSMALL; return NFS_REQ_OK; } break; /* Make post traitement */ } /* * Get information specific to this entry */ if((pfsal_handle = cache_inode_get_fsal_handle(dirent_array[i - delta]->pentry, &cache_status_gethandle)) == NULL) { /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } /* Now fill in the replyed entryplus3 list */ FSAL_DigestHandle(FSAL_GET_EXP_CTX(pcontext), FSAL_DIGEST_FILEID3, pfsal_handle, (caddr_t) & (RES_READDIRPLUS_REPLY.entries[i].fileid)); FSAL_name2str(&dirent_array[i - delta]->name, entry_name_array[i], FSAL_MAX_NAME_LEN); RES_READDIRPLUS_REPLY.entries[i].name = entry_name_array[i]; LogFullDebug(COMPONENT_NFS_READDIR, "Readdirplus3 -> i=%u num_entries=%u delta=%u " "num_entries + delta - 1=%u end_cookie=%"PRIu64, i, num_entries, delta, num_entries + delta - 1, end_cookie); if(i != num_entries + delta - 1) RES_READDIRPLUS_REPLY.entries[i].cookie = dirent_array[i - delta]->cookie; else RES_READDIRPLUS_REPLY.entries[i].cookie = end_cookie; RES_READDIRPLUS_REPLY.entries[i].name_attributes.attributes_follow = FALSE; RES_READDIRPLUS_REPLY.entries[i].name_handle.handle_follows = FALSE; entry_attr = dirent_array[i - delta]->pentry->attributes; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_handle.post_op_fh3_u.handle.data.data_val = (char *)fh3_array[i]; /* Compute the NFSv3 file handle */ if(nfs3_FSALToFhandle (&pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i]. name_handle.post_op_fh3_u.handle, pfsal_handle, pexport) == 0) { /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_BADHANDLE; return NFS_REQ_OK; } /* Set PostPoFh3 structure */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_handle.handle_follows = TRUE; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_handle.post_op_fh3_u.handle.data.data_len = sizeof(file_handle_v3_t); nfs_SetPostOpAttr(pcontext, pexport, dirent_array[i - delta]->pentry, &entry_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_attributes)); LogFullDebug(COMPONENT_NFS_READDIR, "Readdirplus3 -> i=%d, num_entries=%d needed=%lu space_used=%lu maxcount=%lu Name=%s FileId=%016llx Cookie=%llu", i, num_entries, needed, space_used, maxcount, dirent_array[i - delta]->name.name, RES_READDIRPLUS_REPLY.entries[i].fileid, RES_READDIRPLUS_REPLY.entries[i].cookie); RES_READDIRPLUS_REPLY.entries[i].nextentry = NULL; if(i != 0) RES_READDIRPLUS_REPLY.entries[i - 1].nextentry = &(RES_READDIRPLUS_REPLY.entries[i]); } pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = FALSE; } nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, &dir_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok.dir_attributes)); memcpy(pres->res_readdirplus3.READDIRPLUS3res_u.resok.cookieverf, cookie_verifier, sizeof(cookieverf3)); pres->res_readdirplus3.status = NFS3_OK; if((eod_met == END_OF_DIR) && (i == num_entries + delta)) { /* End of directory */ LogFullDebug(COMPONENT_NFS_READDIR, "============================================================> EOD MET !!!!!!"); pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = TRUE; } else pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = FALSE; nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, &dir_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok.dir_attributes)); memcpy(pres->res_readdirplus3.READDIRPLUS3res_u.resok.cookieverf, cookie_verifier, sizeof(cookieverf3)); LogFullDebug(COMPONENT_NFS_READDIR, "============================================================"); /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); /* Free the memory */ if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); return NFS_REQ_OK; } /* If we are here, there was an error */ /* after successful cache_inode_readdir, dir_pentry may be * read locked */ if (dir_pentry_unlock) V_r(&dir_pentry->lock); /* Free the memory */ if( !CACHE_INODE_KEEP_CONTENT( dir_pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, pclient ) ; Mem_Free((char *)dirent_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); /* Is this a retryable error */ if(nfs_RetryableError(cache_status)) return NFS_REQ_DROP; /* Set failed status */ nfs_SetFailedStatus(pcontext, pexport, NFS_V3, cache_status, NULL, &pres->res_readdirplus3.status, dir_pentry, &(pres->res_readdirplus3.READDIRPLUS3res_u.resfail.dir_attributes), NULL, NULL, NULL, NULL, NULL, NULL); return NFS_REQ_OK; } /* nfs3_Readdirplus */
int nfs3_Readdirplus(nfs_arg_t * parg, exportlist_t * pexport, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres) { static char __attribute__ ((__unused__)) funcName[] = "nfs3_Readdirplus"; typedef char entry_name_array_item_t[FSAL_MAX_NAME_LEN]; typedef char fh3_buffer_item_t[NFS3_FHSIZE]; unsigned int delta = 0; cache_entry_t *dir_pentry = NULL; cache_entry_t *pentry_dot_dot = NULL; unsigned long dircount; unsigned long maxcount; fsal_attrib_list_t dir_attr; fsal_attrib_list_t entry_attr; unsigned int begin_cookie; unsigned int end_cookie; unsigned int cache_inode_cookie; cache_inode_dir_entry_t *dirent_array = NULL; unsigned int *cookie_array = NULL; cookieverf3 cookie_verifier; int rc; unsigned int i = 0; unsigned int num_entries; unsigned long space_used; unsigned long estimated_num_entries; unsigned long asked_num_entries; cache_inode_file_type_t dir_filetype; cache_inode_endofdir_t eod_met = UNASSIGNED_EOD; cache_inode_status_t cache_status; cache_inode_status_t cache_status_gethandle; fsal_handle_t *pfsal_handle = NULL; entry_name_array_item_t *entry_name_array = NULL; fh3_buffer_item_t *fh3_array = NULL; /* to avoid setting it on each error case */ pres->res_readdir3.READDIR3res_u.resfail.dir_attributes.attributes_follow = FALSE; dircount = parg->arg_readdirplus3.dircount; maxcount = parg->arg_readdirplus3.maxcount; begin_cookie = (unsigned int)parg->arg_readdirplus3.cookie; space_used = sizeof(READDIRPLUS3resok); estimated_num_entries = dircount / sizeof(entryplus3); LogFullDebug(COMPONENT_NFS_READDIR, "---> nfs3_Readdirplus: dircount=%d maxcount=%d begin_cookie=%d space_used=%d estimated_num_entries=%d\n", dircount, maxcount, begin_cookie, space_used, estimated_num_entries); /* Is this a xattr FH ? */ if(nfs3_Is_Fh_Xattr(&(parg->arg_readdirplus3.dir))) return nfs3_Readdirplus_Xattr(parg, pexport, pcontext, pclient, ht, preq, pres); /* Convert file handle into a vnode */ /* BUGAZOMEU : rajouter acces direct au DIR_CONTINUE */ if((dir_pentry = nfs_FhandleToCache(preq->rq_vers, NULL, &(parg->arg_readdirplus3.dir), NULL, NULL, &(pres->res_readdirplus3.status), NULL, &dir_attr, pcontext, pclient, ht, &rc)) == NULL) { /* return NFS_REQ_DROP ; */ return rc; } /* Extract the filetype */ dir_filetype = cache_inode_fsal_type_convert(dir_attr.type); /* Sanity checks -- must be a directory */ if((dir_filetype != DIR_BEGINNING) && (dir_filetype != DIR_CONTINUE)) { pres->res_readdirplus3.status = NFS3ERR_NOTDIR; return NFS_REQ_OK; } /* switch */ memset(cookie_verifier, 0, sizeof(cookieverf3)); /* * If cookie verifier is used, then an non-trivial value is * returned to the client This value is the mtime of * the directory. If verifier is unused (as in many NFS * Servers) then only a set of zeros is returned (trivial * value) */ if(pexport->UseCookieVerifier) memcpy(cookie_verifier, &(dir_attr.mtime), sizeof(dir_attr.mtime)); /* * nothing to do if != 0 because the area is already full of * zero */ if(pexport->UseCookieVerifier && (begin_cookie != 0)) { /* * Not the first call, so we have to check the cookie * verifier */ if(memcmp(cookie_verifier, parg->arg_readdirplus3.cookieverf, NFS3_COOKIEVERFSIZE) != 0) { pres->res_readdirplus3.status = NFS3ERR_BAD_COOKIE; return NFS_REQ_OK; } } #ifdef _DEBUG_MEMLEAKS /* For debugging memory leaks */ BuddySetDebugLabel("cache_inode_dir_entry_t in nfs3_Readdirplus"); #endif if((dirent_array = (cache_inode_dir_entry_t *) Mem_Alloc(estimated_num_entries * sizeof(cache_inode_dir_entry_t))) == NULL) { pres->res_readdirplus3.status = NFS3ERR_IO; return NFS_REQ_DROP; } #ifdef _DEBUG_MEMLEAKS /* For debugging memory leaks */ BuddySetDebugLabel("cookie array in nfs3_Readdirplus"); #endif if((cookie_array = (unsigned int *)Mem_Alloc(estimated_num_entries * sizeof(unsigned int))) == NULL) { Mem_Free((char *)dirent_array); pres->res_readdirplus3.status = NFS3ERR_IO; return NFS_REQ_DROP; } pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries = NULL; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = FALSE; /* How many entries will we retry from cache_inode ? */ if(begin_cookie > 1) { asked_num_entries = estimated_num_entries; cache_inode_cookie = begin_cookie - 2; } else { asked_num_entries = ((estimated_num_entries > 2) ? estimated_num_entries - 2 : 0); /* Keep space for '.' and '..' */ cache_inode_cookie = 0; } /* A definition that will be very useful to avoid very long names for variables */ #define RES_READDIRPLUS_REPLY pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply /* Call readdir */ if(cache_inode_readdir(dir_pentry, cache_inode_cookie, asked_num_entries, &num_entries, &end_cookie, &eod_met, dirent_array, cookie_array, ht, pclient, pcontext, &cache_status) == CACHE_INODE_SUCCESS) { LogFullDebug(COMPONENT_NFS_READDIR, "-- Readdirplus3 -> Call to cache_inode_readdir( cookie=%d, asked=%d ) -> num_entries = %d\n", cache_inode_cookie, asked_num_entries, num_entries); if(eod_met == END_OF_DIR) { LogFullDebug(COMPONENT_NFS_READDIR, "+++++++++++++++++++++++++++++++++++++++++> EOD MET \n"); } /* If nothing was found, return nothing, but if cookie=0, we should return . and .. */ if((num_entries == 0) && (asked_num_entries != 0) && (begin_cookie > 1)) { pres->res_readdirplus3.status = NFS3_OK; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries = NULL; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = TRUE; nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, NULL, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok. dir_attributes)); memcpy(pres->res_readdirplus3.READDIRPLUS3res_u.resok.cookieverf, cookie_verifier, sizeof(cookieverf3)); } else { #ifdef _DEBUG_MEMLEAKS /* For debugging memory leaks */ BuddySetDebugLabel("entry_name_array in nfs3_Readdirplus"); #endif /* Allocation of the structure for reply */ entry_name_array = (entry_name_array_item_t *) Mem_Alloc(estimated_num_entries * (FSAL_MAX_NAME_LEN + 1)); if(entry_name_array == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); return NFS_REQ_DROP; } #ifdef _DEBUG_MEMLEAKS /* For debugging memory leaks */ BuddySetDebugLabel("READDIRPLUS3res_u.resok.reply.entries"); #endif pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries = (entryplus3 *) Mem_Alloc(estimated_num_entries * sizeof(entryplus3)); if(pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); return NFS_REQ_DROP; } /* Allocation of the file handles */ #ifdef _DEBUG_MEMLEAKS /* For debugging memory leaks */ BuddySetDebugLabel("Filehandle V3 in nfs3_Readdirplus"); #endif fh3_array = (fh3_buffer_item_t *) Mem_Alloc(estimated_num_entries * NFS3_FHSIZE); #ifdef _DEBUG_MEMLEAKS /* For debugging memory leaks */ BuddySetDebugLabel("N/A"); #endif if(fh3_array == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); return NFS_REQ_DROP; } delta = 0; /* manage . and .. */ if(begin_cookie == 0) { /* Fill in '.' */ if(estimated_num_entries > 0) { if((pfsal_handle = cache_inode_get_fsal_handle(dir_pentry, &cache_status_gethandle)) == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } FSAL_DigestHandle(FSAL_GET_EXP_CTX(pcontext), FSAL_DIGEST_FILEID3, pfsal_handle, (caddr_t) & (RES_READDIRPLUS_REPLY.entries[0]. fileid)); RES_READDIRPLUS_REPLY.entries[0].name = entry_name_array[0]; strcpy(RES_READDIRPLUS_REPLY.entries[0].name, "."); RES_READDIRPLUS_REPLY.entries[0].cookie = 1; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle.data.data_val = (char *)fh3_array[0]; if(nfs3_FSALToFhandle (&pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle, pfsal_handle, pexport) == 0) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_BADHANDLE; return NFS_REQ_OK; } RES_READDIRPLUS_REPLY.entries[0].name_attributes.attributes_follow = FALSE; RES_READDIRPLUS_REPLY.entries[0].name_handle.handle_follows = FALSE; cache_inode_get_attributes(dir_pentry, &entry_attr); /* Set PostPoFh3 structure */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.handle_follows = TRUE; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle.data.data_len = sizeof(file_handle_v3_t); nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, &entry_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok. reply.entries[0].name_attributes)); delta += 1; } } /* Fill in '..' */ if(begin_cookie <= 1) { if(estimated_num_entries > delta) { if((pentry_dot_dot = cache_inode_lookupp(dir_pentry, ht, pclient, pcontext, &cache_status_gethandle)) == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } if((pfsal_handle = cache_inode_get_fsal_handle(pentry_dot_dot, &cache_status_gethandle)) == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } FSAL_DigestHandle(FSAL_GET_EXP_CTX(pcontext), FSAL_DIGEST_FILEID3, pfsal_handle, (caddr_t) & (RES_READDIRPLUS_REPLY.entries[delta]. fileid)); RES_READDIRPLUS_REPLY.entries[delta].name = entry_name_array[delta]; strcpy(RES_READDIRPLUS_REPLY.entries[delta].name, ".."); /* Getting a file handle */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.post_op_fh3_u.handle.data.data_val = (char *)fh3_array[delta]; if(nfs3_FSALToFhandle (&pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[0]. name_handle.post_op_fh3_u.handle, pfsal_handle, pexport) == 0) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_BADHANDLE; return NFS_REQ_OK; } RES_READDIRPLUS_REPLY.entries[delta].cookie = 2; RES_READDIRPLUS_REPLY.entries[delta].name_attributes.attributes_follow = FALSE; RES_READDIRPLUS_REPLY.entries[delta].name_handle.handle_follows = FALSE; cache_inode_get_attributes(pentry_dot_dot, &entry_attr); /* Set PostPoFh3 structure */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.handle_follows = TRUE; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[delta]. name_handle.post_op_fh3_u.handle.data.data_len = sizeof(file_handle_v3_t); nfs_SetPostOpAttr(pcontext, pexport, pentry_dot_dot, &entry_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok. reply.entries[delta].name_attributes)); } RES_READDIRPLUS_REPLY.entries[0].nextentry = &(RES_READDIRPLUS_REPLY.entries[delta]); if(num_entries > delta + 1) /* not 0 ??? */ RES_READDIRPLUS_REPLY.entries[delta].nextentry = &(RES_READDIRPLUS_REPLY.entries[delta + 1]); else RES_READDIRPLUS_REPLY.entries[delta].nextentry = NULL; delta += 1; } /* if( begin_cookie == 0 ) */ for(i = delta; i < num_entries + delta; i++) { unsigned long needed; /* dircount is the size without the FH and attributes overhead, so entry3 is used intead of entryplus3 */ needed = sizeof(entry3) + ((strlen(dirent_array[i - delta].name.name) + 3) & ~3); /* LogFullDebug(COMPONENT_NFS_READDIR, "==============> i=%d sizeof(entryplus3)=%d needed=%d space_used=%d maxcount=%d num_entries=%d asked_num_entries=%d\n", i, sizeof( entryplus3 ), needed, space_used, maxcount, num_entries, asked_num_entries ) ; */ if((space_used += needed) > maxcount) { if(i == delta) { /* * Not enough room to make even a single reply */ Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_TOOSMALL; return NFS_REQ_OK; } break; /* Make post traitement */ } /* * Get information specific to this entry */ if((pfsal_handle = cache_inode_get_fsal_handle(dirent_array[i - delta].pentry, &cache_status_gethandle)) == NULL) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = nfs3_Errno(cache_status_gethandle); return NFS_REQ_OK; } /* Now fill in the replyed entryplus3 list */ FSAL_DigestHandle(FSAL_GET_EXP_CTX(pcontext), FSAL_DIGEST_FILEID3, pfsal_handle, (caddr_t) & (RES_READDIRPLUS_REPLY.entries[i].fileid)); FSAL_name2str(&dirent_array[i - delta].name, entry_name_array[i], FSAL_MAX_NAME_LEN); RES_READDIRPLUS_REPLY.entries[i].name = entry_name_array[i]; if(i != num_entries + delta - 1) RES_READDIRPLUS_REPLY.entries[i].cookie = cookie_array[i + 1 - delta] + 2; else RES_READDIRPLUS_REPLY.entries[i].cookie = end_cookie + 2; RES_READDIRPLUS_REPLY.entries[i].name_attributes.attributes_follow = FALSE; RES_READDIRPLUS_REPLY.entries[i].name_handle.handle_follows = FALSE; cache_inode_get_attributes(dirent_array[i - delta].pentry, &entry_attr); pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_handle. post_op_fh3_u.handle.data.data_val = (char *)fh3_array[i]; /* Compute the NFSv3 file handle */ if(nfs3_FSALToFhandle (&pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i]. name_handle.post_op_fh3_u.handle, pfsal_handle, pexport) == 0) { Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); pres->res_readdirplus3.status = NFS3ERR_BADHANDLE; return NFS_REQ_OK; } LogFullDebug(COMPONENT_NFS_READDIR, "-- Readdirplus3 -> i=%d num_entries=%d needed=%d space_used=%lu maxcount=%lu Name=%s FileId=%llu Cookie=%llu\n", i, num_entries, needed, space_used, maxcount, dirent_array[i - delta].name.name, RES_READDIRPLUS_REPLY.entries[i].fileid, RES_READDIRPLUS_REPLY.entries[i].cookie); /* Set PostPoFh3 structure */ pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_handle. handle_follows = TRUE; pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.entries[i].name_handle. post_op_fh3_u.handle.data.data_len = sizeof(file_handle_v3_t); nfs_SetPostOpAttr(pcontext, pexport, dirent_array[i - delta].pentry, &entry_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply. entries[i].name_attributes)); RES_READDIRPLUS_REPLY.entries[i].nextentry = NULL; if(i != 0) RES_READDIRPLUS_REPLY.entries[i - 1].nextentry = &(RES_READDIRPLUS_REPLY.entries[i]); } pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = FALSE; } nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, &dir_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok.dir_attributes)); memcpy(pres->res_readdirplus3.READDIRPLUS3res_u.resok.cookieverf, cookie_verifier, sizeof(cookieverf3)); pres->res_readdirplus3.status = NFS3_OK; if((eod_met == END_OF_DIR) && (i == num_entries + delta)) { /* End of directory */ LogFullDebug(COMPONENT_NFS_READDIR, "============================================================> EOD MET !!!!!!\n"); pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = TRUE; } else pres->res_readdirplus3.READDIRPLUS3res_u.resok.reply.eof = FALSE; nfs_SetPostOpAttr(pcontext, pexport, dir_pentry, &dir_attr, &(pres->res_readdirplus3.READDIRPLUS3res_u.resok.dir_attributes)); memcpy(pres->res_readdirplus3.READDIRPLUS3res_u.resok.cookieverf, cookie_verifier, sizeof(cookieverf3)); LogFullDebug(COMPONENT_NFS_READDIR,"============================================================\n"); /* Free the memory */ Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); return NFS_REQ_OK; } /* If we are here, there was an error */ /* Free the memory */ Mem_Free((char *)dirent_array); Mem_Free((char *)cookie_array); Mem_Free((char *)entry_name_array); Mem_Free((char *)fh3_array); /* Is this a retryable error */ if(nfs_RetryableError(cache_status)) return NFS_REQ_DROP; /* Set failed status */ nfs_SetFailedStatus(pcontext, pexport, NFS_V3, cache_status, NULL, &pres->res_readdirplus3.status, dir_pentry, &(pres->res_readdirplus3.READDIRPLUS3res_u.resfail.dir_attributes), NULL, NULL, NULL, NULL, NULL, NULL); return NFS_REQ_OK; } /* nfs3_Readdirplus */