int nfs4_op_savefh(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { int error; /* 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_SAVEFH; resp->nfs_resop4_u.opsavefh.status = NFS4_OK; /* If there is no currentFH, teh return an error */ if(nfs4_Is_Fh_Empty(&(data->currentFH))) { /* There is no current FH, return NFS4ERR_NOFILEHANDLE */ resp->nfs_resop4_u.opsavefh.status = NFS4ERR_NOFILEHANDLE; return NFS4ERR_NOFILEHANDLE; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(data->currentFH))) { resp->nfs_resop4_u.opgetfh.status = NFS4ERR_BADHANDLE; return NFS4ERR_BADHANDLE; } /* Tests if teh Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(data->currentFH))) { resp->nfs_resop4_u.opgetfh.status = NFS4ERR_FHEXPIRED; return NFS4ERR_FHEXPIRED; } /* If the savefh is not allocated, do it now */ if(data->savedFH.nfs_fh4_len == 0) { if((error = nfs4_AllocateFH(&(data->savedFH))) != NFS4_OK) { resp->nfs_resop4_u.opsavefh.status = error; return error; } } /* Copy the data from current FH to saved FH */ memcpy((char *)(data->savedFH.nfs_fh4_val), (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len); /* Keep the vnodep in mind */ data->saved_entry = data->current_entry; data->saved_filetype = data->current_filetype; if(isFullDebug(COMPONENT_NFS_V4)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->savedFH); LogFullDebug(COMPONENT_NFS_V4, "SAVE FH: Saved FH %s", str); } return NFS4_OK; } /* nfs4_op_savefh */
/** * * print_compound_fh * * This routine prints all the file handle within a compoud request's data structure. * * @param data [IN] compound's data to manage. * * @return nothing (void function). * */ void LogCompoundFH(compound_data_t * data) { if(isFullDebug(COMPONENT_FILEHANDLE)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->currentFH); LogFullDebug(COMPONENT_FILEHANDLE, "Current FH %s", str); sprint_fhandle4(str, &data->savedFH); LogFullDebug(COMPONENT_FILEHANDLE, "Saved FH %s", str); sprint_fhandle4(str, &data->publicFH); LogFullDebug(COMPONENT_FILEHANDLE, "Public FH %s", str); sprint_fhandle4(str, &data->rootFH); LogFullDebug(COMPONENT_FILEHANDLE, "Root FH %s", str); } } /* print_compoud_fh */
/** * * print_fhandle4 * * This routine prints a NFSv4 file handle (for debugging purpose) * * @param fh [IN] file handle to print. * * @return nothing (void function). * */ void print_fhandle4(log_components_t component, nfs_fh4 *fh) { if(isFullDebug(component)) { char str[LEN_FH_STR]; sprint_fhandle4(str, fh); LogFullDebug(component, "%s", str); } } /* print_fhandle4 */
/** * * nfs4_op_getattr: Gets attributes for an entry in the FSAL. * * Gets attributes for an entry in the FSAL. * * @param op [IN] pointer to nfs4_op arguments * @param data [INOUT] Pointer to the compound request's data * @param resp [IN] Pointer to nfs4_op results * * @return NFS4_OK * */ int nfs4_op_getattr(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { fsal_attrib_list_t attr; cache_inode_status_t cache_status; char __attribute__ ((__unused__)) funcname[] = "nfs4_op_getattr"; /* This is a NFS4_OP_GETTAR */ resp->resop = NFS4_OP_GETATTR; /* If there is no FH */ if(nfs4_Is_Fh_Empty(&(data->currentFH))) { res_GETATTR4.status = NFS4ERR_NOFILEHANDLE; return NFS4ERR_NOFILEHANDLE; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(data->currentFH))) { res_GETATTR4.status = NFS4ERR_BADHANDLE; return NFS4ERR_BADHANDLE; } /* Tests if teh Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(data->currentFH))) { res_GETATTR4.status = NFS4ERR_FHEXPIRED; return NFS4ERR_FHEXPIRED; } /* Pseudo Fs management */ if(nfs4_Is_Fh_Pseudo(&(data->currentFH))) return nfs4_op_getattr_pseudo(op, data, resp); /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */ if(nfs4_Is_Fh_Xattr(&(data->currentFH))) return nfs4_op_getattr_xattr(op, data, resp); if(isFullDebug(COMPONENT_NFS_V4)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->currentFH); LogFullDebug(COMPONENT_NFS_V4, "NFS4_OP_GETATTR: Current FH %s", str); } /* Sanity check: if no attributes are wanted, nothing is to be done. * In this case NFS4_OK is to be returned */ if(arg_GETATTR4.attr_request.bitmap4_len == 0) { res_GETATTR4.status = NFS4_OK; return res_GETATTR4.status; } /* Get only attributes that are allowed to be read */ if(!nfs4_Fattr_Check_Access_Bitmap(&arg_GETATTR4.attr_request, FATTR4_ATTR_READ)) { res_GETATTR4.status = NFS4ERR_INVAL; return res_GETATTR4.status; } if( !nfs4_bitmap4_Remove_Unsupported( &arg_GETATTR4.attr_request ) ) { res_GETATTR4.status = NFS4ERR_SERVERFAULT ; return res_GETATTR4.status; } /* * Get attributes. */ if(cache_inode_getattr(data->current_entry, &attr, data->ht, data->pclient, data->pcontext, &cache_status) == CACHE_INODE_SUCCESS) { if(nfs4_FSALattr_To_Fattr(data->pexport, &attr, &(res_GETATTR4.GETATTR4res_u.resok4.obj_attributes), data, &(data->currentFH), &(arg_GETATTR4.attr_request)) != 0) res_GETATTR4.status = NFS4ERR_SERVERFAULT; else res_GETATTR4.status = NFS4_OK; return res_GETATTR4.status; } res_GETATTR4.status = nfs4_Errno(cache_status); return res_GETATTR4.status; } /* nfs4_op_getattr */
int nfs4_op_savefh(struct nfs_argop4 *op, compound_data_t *data, struct nfs_resop4 *resp) { SAVEFH4res * const res_SAVEFH = &resp->nfs_resop4_u.opsavefh; /* 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_SAVEFH; res_SAVEFH->status = NFS4_OK; /* Do basic checks on a filehandle */ res_SAVEFH->status = nfs4_sanity_check_FH(data, NO_FILE_TYPE, true); if (res_SAVEFH->status != NFS4_OK) return res_SAVEFH->status; /* If the savefh is not allocated, do it now */ if (data->savedFH.nfs_fh4_val == NULL) nfs4_AllocateFH(&data->savedFH); /* Determine if we can get a new export reference. If there is * no op_ctx->ctx_export, don't get a reference. */ if (op_ctx->ctx_export != NULL) { if (!export_ready(op_ctx->ctx_export)) { /* The CurrentFH export has gone bad. */ res_SAVEFH->status = NFS4ERR_STALE; return res_SAVEFH->status; } get_gsh_export_ref(op_ctx->ctx_export); } /* Copy the data from current FH to saved FH */ memcpy(data->savedFH.nfs_fh4_val, data->currentFH.nfs_fh4_val, data->currentFH.nfs_fh4_len); data->savedFH.nfs_fh4_len = data->currentFH.nfs_fh4_len; /* If saved and current entry are equal, skip the following. */ if (data->saved_obj != data->current_obj) { set_saved_entry(data, data->current_obj); /* Make SAVEFH work right for DS handle */ if (data->current_ds != NULL) { data->saved_ds = data->current_ds; ds_handle_get_ref(data->saved_ds); } } /* Save the current stateid */ data->saved_stateid = data->current_stateid; data->saved_stateid_valid = data->current_stateid_valid; /* If old SavedFH had a related export, release reference. */ if (data->saved_export != NULL) put_gsh_export(data->saved_export); /* Save the export information (reference already taken above). */ data->saved_export = op_ctx->ctx_export; data->saved_export_perms = *op_ctx->export_perms; if (isFullDebug(COMPONENT_NFS_V4)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->savedFH); LogFullDebug(COMPONENT_NFS_V4, "SAVE FH: Saved FH %s", str); } res_SAVEFH->status = NFS4_OK; return NFS4_OK; } /* nfs4_op_savefh */
int nfs4_op_restorefh(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { char __attribute__ ((__unused__)) funcname[] = "nfs4_op_restorefh"; /* 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_RESTOREFH; res_RESTOREFH.status = NFS4_OK; /* If there is no currentFH, teh return an error */ if(nfs4_Is_Fh_Empty(&(data->savedFH))) { /* There is no current FH, return NFS4ERR_RESTOREFH (cg RFC3530, page 202) */ res_RESTOREFH.status = NFS4ERR_RESTOREFH; return res_RESTOREFH.status; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(data->savedFH))) { res_RESTOREFH.status = NFS4ERR_BADHANDLE; return res_RESTOREFH.status; } /* Tests if the Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(data->savedFH))) { res_RESTOREFH.status = NFS4ERR_FHEXPIRED; return res_RESTOREFH.status; } /* If data->exportp is null, a junction from pseudo fs was traversed, credp and exportp have to be updated */ if(data->pexport == NULL) { res_RESTOREFH.status = nfs4_SetCompoundExport(data); if(res_RESTOREFH.status != NFS4_OK) { LogCrit(COMPONENT_NFS_V4, "Error %d in nfs4_SetCompoundExport", res_RESTOREFH.status); return res_RESTOREFH.status; } } /* Copy the data from current FH to saved FH */ memcpy(data->currentFH.nfs_fh4_val, data->savedFH.nfs_fh4_val, data->savedFH.nfs_fh4_len); data->currentFH.nfs_fh4_len = data->savedFH.nfs_fh4_len; /* If current and saved entry are identical, get no references and make no changes. */ if (data->current_entry == data->saved_entry) { goto out; } if (data->current_entry) { cache_inode_put(data->current_entry); data->current_entry = NULL; } data->current_entry = data->saved_entry; data->current_filetype = data->saved_filetype; /* Take another reference. As of now the filehandle is both saved and current and both must be counted. Protect in case of pseudofs handle. */ if (data->current_entry) { if (cache_inode_lru_ref(data->current_entry, LRU_FLAG_NONE) != CACHE_INODE_SUCCESS) { resp->nfs_resop4_u.opgetfh.status = NFS4ERR_STALE; data->current_entry = NULL; return resp->nfs_resop4_u.opgetfh.status; } } out: if(isFullDebug(COMPONENT_NFS_V4)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->currentFH); LogFullDebug(COMPONENT_NFS_V4, "RESTORE FH: Current FH %s", str); } return NFS4_OK; } /* nfs4_op_restorefh */
int nfs4_op_restorefh(struct nfs_argop4 *op, compound_data_t *data, struct nfs_resop4 *resp) { RESTOREFH4res * const res_RESTOREFH = &resp->nfs_resop4_u.oprestorefh; /* 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_RESTOREFH; res_RESTOREFH->status = NFS4_OK; LogFullDebugOpaque(COMPONENT_FILEHANDLE, "Saved FH %s", LEN_FH_STR, data->savedFH.nfs_fh4_val, data->savedFH.nfs_fh4_len); /* If there is no savedFH, then return an error */ if (nfs4_Is_Fh_Empty(&(data->savedFH)) == NFS4ERR_NOFILEHANDLE) { /* There is no current FH, return NFS4ERR_RESTOREFH * (cg RFC3530, page 202) */ res_RESTOREFH->status = NFS4ERR_RESTOREFH; return res_RESTOREFH->status; } /* Do basic checks on saved filehandle */ res_RESTOREFH->status = nfs4_sanity_check_saved_FH(data, NO_FILE_TYPE, true); if (res_RESTOREFH->status != NFS4_OK) return res_RESTOREFH->status; /* Determine if we can get a new export reference. If there is * no saved export, don't get a reference to it. */ if (data->saved_export != NULL) { if (!export_ready(data->saved_export)) { /* The SavedFH export has gone bad. */ res_RESTOREFH->status = NFS4ERR_STALE; return res_RESTOREFH->status; } get_gsh_export_ref(data->saved_export); } /* Copy the data from saved FH to current FH */ memcpy(data->currentFH.nfs_fh4_val, data->savedFH.nfs_fh4_val, data->savedFH.nfs_fh4_len); data->currentFH.nfs_fh4_len = data->savedFH.nfs_fh4_len; if (op_ctx->ctx_export != NULL) put_gsh_export(op_ctx->ctx_export); /* Restore the export information */ op_ctx->ctx_export = data->saved_export; if (op_ctx->ctx_export != NULL) op_ctx->fsal_export = op_ctx->ctx_export->fsal_export; *op_ctx->export_perms = data->saved_export_perms; /* No need to call nfs4_SetCompoundExport or nfs4_MakeCred * because we are restoring saved information, and the * credential checking may be skipped. */ /* Update the current entry */ set_current_entry(data, data->saved_obj); /* Restore the saved stateid */ data->current_stateid = data->saved_stateid; data->current_stateid_valid = data->saved_stateid_valid; /* Make RESTOREFH work right for DS handle */ if (data->current_ds != NULL) { data->current_ds = data->saved_ds; data->current_filetype = data->saved_filetype; ds_handle_get_ref(data->current_ds); } if (isFullDebug(COMPONENT_NFS_V4)) { char str[LEN_FH_STR]; sprint_fhandle4(str, &data->currentFH); LogFullDebug(COMPONENT_NFS_V4, "RESTORE FH: Current FH %s", str); } return NFS4_OK; } /* nfs4_op_restorefh */