Beispiel #1
0
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 */
Beispiel #4
0
/**
 *
 * 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 */
Beispiel #5
0
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 */