Exemple #1
0
/**
 *  @brief Helper to verify validity of export ID's
 *
 *  @l3_arg  NFS argument
 *  @req     SVC request
 *
 *  @return nfsstat3
 */
static enum nfsstat3
nfs3_verify_exportid(struct LINK3args *l3_arg, struct svc_req *req)
{
	const short to_exportid = nfs3_FhandleToExportId(&l3_arg->link.dir);
	const short from_exportid = nfs3_FhandleToExportId(&l3_arg->file);

	if (to_exportid < 0 || from_exportid < 0) {
		LogInfo(COMPONENT_DISPATCH,
			"NFS%d LINK Request from client %s has badly formed handle for link dir",
			req->rq_msg.cb_vers,
			op_ctx->client ?
					op_ctx->client->hostaddr_str :
					"unknown client");
		return NFS3ERR_BADHANDLE;
	}

	/* Both objects have to be in the same filesystem */
	if (to_exportid != from_exportid)
		return NFS3ERR_XDEV;

	return NFS3_OK;
}
Exemple #2
0
int nfs3_link(nfs_arg_t *arg,
	      nfs_worker_data_t *worker,
	      struct svc_req *req, nfs_res_t *res)
{
	const char *link_name = arg->arg_link3.link.name;
	cache_entry_t *target_entry = NULL;
	cache_entry_t *parent_entry = NULL;
	pre_op_attr pre_parent = {
		.attributes_follow = false
	};
	cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
	short to_exportid = 0;
	short from_exportid = 0;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char strto[LEN_FH_STR], strfrom[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_vers,
				 &(arg->arg_link3.file),
				 NULL,
				 strfrom);

		nfs_FhandleToStr(req->rq_vers,
				 &(arg->arg_link3.link.dir),
				 NULL,
				 strto);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_link handle: %s to "
			 "handle: %s name: %s", strfrom, strto, link_name);
	}

	/* to avoid setting it on each error case */
	res->res_link3.LINK3res_u.resfail.file_attributes.attributes_follow =
	    FALSE;
	res->res_link3.LINK3res_u.resfail.linkdir_wcc.before.attributes_follow =
	    FALSE;
	res->res_link3.LINK3res_u.resfail.linkdir_wcc.after.attributes_follow =
	    FALSE;

	/* Get the exportids for the two handles. */
	to_exportid = nfs3_FhandleToExportId(&(arg->arg_link3.link.dir));
	from_exportid = nfs3_FhandleToExportId(&(arg->arg_link3.file));

	/* Validate the to_exportid */
	if (to_exportid < 0 || from_exportid < 0) {
		LogInfo(COMPONENT_DISPATCH,
			"NFS%d LINK Request from client %s has badly formed handle for link dir",
			req->rq_vers,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");

		/* Bad handle, report to client */
		res->res_link3.status = NFS3ERR_BADHANDLE;
		goto out;
	}

	/* Both objects have to be in the same filesystem */
	if (to_exportid != from_exportid) {
		res->res_link3.status = NFS3ERR_XDEV;
		goto out;
	}

	/* Get entry for parent directory */
	parent_entry = nfs3_FhandleToCache(&arg->arg_link3.link.dir,
					   &res->res_link3.status,
					   &rc);

	if (parent_entry == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	nfs_SetPreOpAttr(parent_entry, &pre_parent);

	target_entry = nfs3_FhandleToCache(&arg->arg_link3.file,
					   &res->res_link3.status,
					   &rc);

	if (target_entry == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	/* Sanity checks: */
	if (parent_entry->type != DIRECTORY) {
		res->res_link3.status = NFS3ERR_NOTDIR;
		rc = NFS_REQ_OK;
		goto out;
	}

	if (link_name == NULL || *link_name == '\0')
		res->res_link3.status = NFS3ERR_INVAL;
	else {
		/* Both objects have to be in the same filesystem */
		if (to_exportid != from_exportid)
			res->res_link3.status = NFS3ERR_XDEV;
		else {
			cache_status = cache_inode_link(target_entry,
							parent_entry,
							link_name);

			if (cache_status == CACHE_INODE_SUCCESS) {
				nfs_SetPostOpAttr(target_entry,
						  &(res->res_link3.LINK3res_u.
						    resok.file_attributes));

				nfs_SetWccData(&pre_parent,
					       parent_entry,
					       &(res->res_link3.LINK3res_u.
						 resok.linkdir_wcc));
				res->res_link3.status = NFS3_OK;
				rc = NFS_REQ_OK;
				goto out;
			}
		}		/* else */
	}

	/* If we are here, there was an error */
	if (nfs_RetryableError(cache_status)) {
		rc = NFS_REQ_DROP;
		goto out;
	}

	res->res_link3.status = nfs3_Errno(cache_status);
	nfs_SetPostOpAttr(target_entry,
			  &(res->res_link3.LINK3res_u.resfail.file_attributes));

	nfs_SetWccData(&pre_parent, parent_entry,
		       &res->res_link3.LINK3res_u.resfail.linkdir_wcc);

	rc = NFS_REQ_OK;

 out:
	/* return references */
	if (target_entry)
		cache_inode_put(target_entry);

	if (parent_entry)
		cache_inode_put(parent_entry);

	return rc;

}				/* nfs3_link */

/**
 * @brief Free the result structure allocated for nfs3_link
 *
 * This function frees the result structure allocated for nfs3_link.
 *
 * @param[in,out] resp Result structure
 *
 */
void nfs3_link_free(nfs_res_t *resp)
{
	return;
}
Exemple #3
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_rename(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	const char *entry_name = arg->arg_rename3.from.name;
	const char *new_entry_name = arg->arg_rename3.to.name;
	cache_entry_t *parent_entry = NULL;
	cache_entry_t *new_parent_entry = NULL;
	cache_inode_status_t cache_status;
	short to_exportid = 0;
	short from_exportid = 0;
	int rc = NFS_REQ_OK;

	pre_op_attr pre_parent = {
		.attributes_follow = false
	};
	pre_op_attr pre_new_parent = {
		.attributes_follow = false
	};

	if (isDebug(COMPONENT_NFSPROTO)) {
		char strto[LEN_FH_STR], strfrom[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_vers,
				 &arg->arg_rename3.from.dir,
				 NULL,
				 strfrom);

		nfs_FhandleToStr(req->rq_vers,
				 &arg->arg_rename3.to.dir,
				 NULL,
				 strto);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs_Rename from handle: %s name %s to handle: %s name: %s",
			 strfrom, entry_name, strto, new_entry_name);
	}

	/* to avoid setting it on each error case */
	res->res_rename3.RENAME3res_u.resfail.fromdir_wcc.before.
	    attributes_follow = FALSE;
	res->res_rename3.RENAME3res_u.resfail.fromdir_wcc.after.
	    attributes_follow = FALSE;
	res->res_rename3.RENAME3res_u.resfail.todir_wcc.before.
	    attributes_follow = FALSE;
	res->res_rename3.RENAME3res_u.resfail.todir_wcc.after.
	    attributes_follow = FALSE;

	/* Get the exportids for the two handles. */
	to_exportid = nfs3_FhandleToExportId(&(arg->arg_rename3.to.dir));
	from_exportid = nfs3_FhandleToExportId(&(arg->arg_rename3.from.dir));

	/* Validate the to_exportid */
	if (to_exportid < 0 || from_exportid < 0) {
		LogInfo(COMPONENT_DISPATCH,
			"NFS%d RENAME Request from client %s has badly formed handle for to dir",
			req->rq_vers,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");

		/* Bad handle, report to client */
		res->res_rename3.status = NFS3ERR_BADHANDLE;
		goto out;
	}

	/* Both objects have to be in the same filesystem */
	if (to_exportid != from_exportid) {
		res->res_rename3.status = NFS3ERR_XDEV;
		goto out;
	}

	/* Convert fromdir file handle into a cache_entry */
	parent_entry = nfs3_FhandleToCache(&arg->arg_rename3.from.dir,
					   &res->res_create3.status,
					   &rc);

	if (parent_entry == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	nfs_SetPreOpAttr(parent_entry, &pre_parent);

	/* Convert todir file handle into a cache_entry */
	new_parent_entry = nfs3_FhandleToCache(&arg->arg_rename3.to.dir,
					       &res->res_create3.status,
					       &rc);

	if (new_parent_entry == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	nfs_SetPreOpAttr(new_parent_entry, &pre_new_parent);

	if (entry_name == NULL || *entry_name == '\0' || new_entry_name == NULL
	    || *new_entry_name == '\0') {
		cache_status = CACHE_INODE_INVALID_ARGUMENT;
		goto out_fail;
	}

	cache_status = cache_inode_rename(parent_entry,
					  entry_name,
					  new_parent_entry,
					  new_entry_name);

	if (cache_status != CACHE_INODE_SUCCESS)
		goto out_fail;

	res->res_rename3.status = NFS3_OK;

	nfs_SetWccData(&pre_parent, parent_entry,
		       &res->res_rename3.RENAME3res_u.resok.fromdir_wcc);

	nfs_SetWccData(&pre_new_parent, new_parent_entry,
		       &res->res_rename3.RENAME3res_u.resok.todir_wcc);

	rc = NFS_REQ_OK;

	goto out;

 out_fail:
	res->res_rename3.status = nfs3_Errno(cache_status);

	nfs_SetWccData(&pre_parent, parent_entry,
		       &res->res_rename3.RENAME3res_u.resfail.fromdir_wcc);

	nfs_SetWccData(&pre_new_parent, new_parent_entry,
		       &res->res_rename3.RENAME3res_u.resfail.todir_wcc);

	/* If we are here, there was an error */
	if (nfs_RetryableError(cache_status))
		rc = NFS_REQ_DROP;

 out:
	if (parent_entry)
		cache_inode_put(parent_entry);

	if (new_parent_entry)
		cache_inode_put(new_parent_entry);

	return rc;
}

/**
 * @brief Free the result structure allocated for nfs3_rename.
 *
 * This function frees the result structure allocated for nfs3_rename.
 *
 * @param[in,out] res Result structure
 *
 */
void nfs3_rename_free(nfs_res_t *res)
{
	/* Nothing to do here */
}