示例#1
0
int nfs3_commit(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	cache_inode_status_t cache_status;
	cache_entry_t *entry = NULL;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		sprint_fhandle3(str, &(arg->arg_commit3.file));
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_commit handle: %s",
			 str);
	}

	/* To avoid setting it on each error case */
	res->res_commit3.COMMIT3res_u.resfail.file_wcc.before.
	    attributes_follow = FALSE;
	res->res_commit3.COMMIT3res_u.resfail.file_wcc.after.attributes_follow =
	    FALSE;

	entry = nfs3_FhandleToCache(&arg->arg_commit3.file,
				    &res->res_commit3.status,
				    &rc);

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

	cache_status = cache_inode_commit(entry,
					  arg->arg_commit3.offset,
					  arg->arg_commit3.count);

	if (cache_status != CACHE_INODE_SUCCESS) {
		res->res_commit3.status = nfs3_Errno(cache_status);

		nfs_SetWccData(NULL, entry,
			       &(res->res_commit3.COMMIT3res_u.resfail.
				 file_wcc));

		rc = NFS_REQ_OK;
		goto out;
	}

	nfs_SetWccData(NULL, entry,
		       &(res->res_commit3.COMMIT3res_u.resok.file_wcc));

	/* Set the write verifier */
	memcpy(res->res_commit3.COMMIT3res_u.resok.verf, NFS3_write_verifier,
	       sizeof(writeverf3));
	res->res_commit3.status = NFS3_OK;

 out:

	if (entry)
		cache_inode_put(entry);

	return rc;
}				/* nfs3_commit */
示例#2
0
int nfs3_pathconf(nfs_arg_t *arg,
		  nfs_worker_data_t *worker,
		  struct svc_req *req, nfs_res_t *res)
{
	cache_entry_t *entry = NULL;
	int rc = NFS_REQ_OK;
	struct fsal_export *exp_hdl = op_ctx->fsal_export;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];
		sprint_fhandle3(str, &(arg->arg_pathconf3.object));
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_pathconf handle: "
			 "%s", str);
	}

	/* to avoid setting it on each error case */
	res->res_pathconf3.PATHCONF3res_u.resfail.obj_attributes.
	    attributes_follow = FALSE;

	/* Convert file handle into a fsal_handle */
	entry = nfs3_FhandleToCache(&arg->arg_pathconf3.object,
				    &res->res_pathconf3.status,
				    &rc);

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

	res->res_pathconf3.PATHCONF3res_u.resok.linkmax =
	    exp_hdl->ops->fs_maxlink(exp_hdl);
	res->res_pathconf3.PATHCONF3res_u.resok.name_max =
	    exp_hdl->ops->fs_maxnamelen(exp_hdl);
	res->res_pathconf3.PATHCONF3res_u.resok.no_trunc =
	    exp_hdl->ops->fs_supports(exp_hdl, fso_no_trunc);
	res->res_pathconf3.PATHCONF3res_u.resok.chown_restricted =
	    exp_hdl->ops->fs_supports(exp_hdl, fso_chown_restricted);
	res->res_pathconf3.PATHCONF3res_u.resok.case_insensitive =
	    exp_hdl->ops->fs_supports(exp_hdl, fso_case_insensitive);
	res->res_pathconf3.PATHCONF3res_u.resok.case_preserving =
	    exp_hdl->ops->fs_supports(exp_hdl, fso_case_preserving);

	/* Build post op file attributes */
	nfs_SetPostOpAttr(entry,
			  &(res->res_pathconf3.PATHCONF3res_u.resok.
			    obj_attributes));

 out:

	if (entry)
		cache_inode_put(entry);

	return rc;
}				/* nfs3_pathconf */
示例#3
0
int nfs3_getattr(nfs_arg_t *arg,
                 nfs_worker_data_t *worker,
                 struct svc_req *req, nfs_res_t *res)
{
    cache_entry_t *entry = NULL;
    int rc = NFS_REQ_OK;

    if (isDebug(COMPONENT_NFSPROTO)) {
        char str[LEN_FH_STR];
        nfs_FhandleToStr(req->rq_vers, &(arg->arg_getattr3.object),
                         NULL, str);
        LogDebug(COMPONENT_NFSPROTO,
                 "REQUEST PROCESSING: Calling nfs3_getattr handle: %s",
                 str);
    }

    entry = nfs3_FhandleToCache(&arg->arg_getattr3.object,
                                &res->res_getattr3.status,
                                &rc);

    if (entry == NULL) {
        /* Status and rc have been set by nfs3_FhandleToCache */
        LogFullDebug(COMPONENT_NFSPROTO,
                     "nfs_Getattr returning %d",
                     rc);
        goto out;
    }

    if (!cache_entry_to_nfs3_Fattr(
                entry,
                &res->res_getattr3.GETATTR3res_u.resok.obj_attributes)) {
        res->res_getattr3.status =
            nfs3_Errno(CACHE_INODE_INVALID_ARGUMENT);

        LogFullDebug(COMPONENT_NFSPROTO,
                     "nfs_Getattr set failed status v3");

        rc = NFS_REQ_OK;
        goto out;
    }

    res->res_getattr3.status = NFS3_OK;

    LogFullDebug(COMPONENT_NFSPROTO, "nfs_Getattr succeeded");
    rc = NFS_REQ_OK;

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

    return rc;

}
示例#4
0
int nfs3_remove(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct fsal_obj_handle *parent_obj = NULL;
	struct fsal_obj_handle *child_obj = NULL;
	pre_op_attr pre_parent = {
		.attributes_follow = false
	};
	fsal_status_t fsal_status;
	const char *name = arg->arg_remove3.object.name;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_msg.cb_vers,
				 &arg->arg_create3.where.dir,
				 NULL,
				 str);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs_Remove handle: %s name: %s",
			 str, name);
	}

	/* Convert file handle into a pentry */
	/* to avoid setting it on each error case */
	res->res_remove3.REMOVE3res_u.resfail.dir_wcc.before.attributes_follow =
	    FALSE;
	res->res_remove3.REMOVE3res_u.resfail.dir_wcc.after.attributes_follow =
	    FALSE;

	parent_obj = nfs3_FhandleToCache(&arg->arg_remove3.object.dir,
					   &res->res_remove3.status,
					   &rc);

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

	nfs_SetPreOpAttr(parent_obj, &pre_parent);

	/* Sanity checks: file name must be non-null; parent must be a
	 * directory.
	 */
	if (parent_obj->type != DIRECTORY) {
		res->res_remove3.status = NFS3ERR_NOTDIR;
		rc = NFS_REQ_OK;
		goto out;
	}

	if (name == NULL || *name == '\0') {
		fsal_status = fsalstat(ERR_FSAL_INVAL, 0);
		goto out_fail;
	}

	/* Lookup the child entry to verify that it is not a directory */
	fsal_status = fsal_lookup(parent_obj, name, &child_obj, NULL);

	if (!FSAL_IS_ERROR(fsal_status)) {
		/* Sanity check: make sure we are not removing a
		 * directory
		 */
		if (child_obj->type == DIRECTORY) {
			res->res_remove3.status = NFS3ERR_ISDIR;
			rc = NFS_REQ_OK;
			goto out;
		}
	}

	LogFullDebug(COMPONENT_NFSPROTO, "Trying to remove file %s", name);

	/* Remove the entry. */
	fsal_status = fsal_remove(parent_obj, name);

	if (FSAL_IS_ERROR(fsal_status))
		goto out_fail;

	/* Build Weak Cache Coherency data */
	nfs_SetWccData(&pre_parent, parent_obj,
		       &res->res_remove3.REMOVE3res_u.resok.dir_wcc);

	res->res_remove3.status = NFS3_OK;
	rc = NFS_REQ_OK;

	goto out;

 out_fail:
	res->res_remove3.status = nfs3_Errno_status(fsal_status);
	nfs_SetWccData(&pre_parent, parent_obj,
		       &res->res_remove3.REMOVE3res_u.resfail.dir_wcc);

	if (nfs_RetryableError(fsal_status.major))
		rc = NFS_REQ_DROP;

 out:
	/* return references */
	if (child_obj)
		child_obj->obj_ops.put_ref(child_obj);

	if (parent_obj)
		parent_obj->obj_ops.put_ref(parent_obj);

	return rc;

}				/* nfs3_remove */

/**
 * @brief Free the result structure allocated for nfs3_remove.
 *
 * This function frees the result structure allocated for nfs3_remove.
 *
 * @param[in,out] res Result structure
 *
 */
void nfs3_remove_free(nfs_res_t *res)
{
	/* Nothing to do here */
}
示例#5
0
/**
 *
 * @brief The NFSPROC3_LINK
 *
 * The NFSPROC3_LINK.
 *
 * @param[in]  arg     NFS argument union
 * @param[in]  req     SVC request related to this call
 * @param[out] res     Structure to contain the result of the call
 *
 * @retval NFS_REQ_OK if successful
 * @retval NFS_REQ_DROP if failed but retryable
 * @retval NFS_REQ_FAILED if failed and not retryable
 *
 */
int nfs3_link(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct LINK3args *l3_arg = &arg->arg_link3;
	struct LINK3res *l3_res = &res->res_link3;
	const char *link_name = l3_arg->link.name;
	struct fsal_obj_handle *target_obj = NULL;
	struct fsal_obj_handle *parent_obj = NULL;
	pre_op_attr pre_parent = {0};
	fsal_status_t fsal_status = {0, 0};
	int rc = NFS_REQ_OK;

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

		nfs_FhandleToStr(req->rq_msg.cb_vers, &l3_arg->file,
				 NULL, strfrom);
		nfs_FhandleToStr(req->rq_msg.cb_vers, &l3_arg->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 */
	l3_res->LINK3res_u.resfail.file_attributes.attributes_follow = FALSE;
	l3_res->LINK3res_u.resfail.linkdir_wcc.before.attributes_follow = FALSE;
	l3_res->LINK3res_u.resfail.linkdir_wcc.after.attributes_follow = FALSE;

	l3_res->status = nfs3_verify_exportid(l3_arg, req);
	if (l3_res->status != NFS3_OK)
		return rc;

	parent_obj = nfs3_FhandleToCache(&l3_arg->link.dir, &l3_res->status,
					 &rc);
	if (parent_obj == NULL)
		return rc;  /* Status and rc are set by nfs3_FhandleToCache */

	nfs_SetPreOpAttr(parent_obj, &pre_parent);

	target_obj = nfs3_FhandleToCache(&l3_arg->file, &l3_res->status, &rc);
	if (target_obj == NULL) {
		parent_obj->obj_ops.put_ref(parent_obj);
		return rc;  /* Status and rc are set by nfs3_FhandleToCache */
	}

	if (parent_obj->type != DIRECTORY) {
		l3_res->status = NFS3ERR_NOTDIR;
		goto out;
	}

	if (link_name == NULL || *link_name == '\0') {
		l3_res->status = NFS3ERR_INVAL;
		goto out;
	}

	fsal_status = fsal_link(target_obj, parent_obj, link_name);

	if (FSAL_IS_ERROR(fsal_status)) {
		/* If we are here, there was an error */
		LogFullDebug(COMPONENT_NFSPROTO,
			     "failed link: fsal_status=%s",
			     fsal_err_txt(fsal_status));

		if (nfs_RetryableError(fsal_status.major)) {
			rc = NFS_REQ_DROP;
			goto out;
		}

		l3_res->status = nfs3_Errno_status(fsal_status);
		nfs_SetPostOpAttr(target_obj,
				  &l3_res->LINK3res_u.resfail.file_attributes,
				  NULL);

		nfs_SetWccData(&pre_parent, parent_obj,
			       &l3_res->LINK3res_u.resfail.linkdir_wcc);
	} else {
		nfs_SetPostOpAttr(target_obj,
				  &l3_res->LINK3res_u.resok.file_attributes,
				  NULL);

		nfs_SetWccData(&pre_parent, parent_obj,
			       &l3_res->LINK3res_u.resok.linkdir_wcc);
		l3_res->status = NFS3_OK;
	}

 out:
	/* return references */
	target_obj->obj_ops.put_ref(target_obj);
	parent_obj->obj_ops.put_ref(parent_obj);

	return rc;
}				/* nfs3_link */
示例#6
0
int nfs3_access(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	cache_inode_status_t cache_status;
	cache_entry_t *entry = NULL;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		sprint_fhandle3(str, &(arg->arg_access3.object));
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_access handle: %s",
			 str);
	}

	/* to avoid setting it on each error case */
	res->res_access3.ACCESS3res_u.resfail.obj_attributes.attributes_follow =
	    FALSE;

	/* Convert file handle into a vnode */
	entry = nfs3_FhandleToCache(&(arg->arg_access3.object),
				    &(res->res_access3.status),
				    &rc);

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

	/* Perform the 'access' call */
	cache_status =
	    nfs_access_op(entry, arg->arg_access3.access,
			  &res->res_access3.ACCESS3res_u.resok.access, NULL);

	if (cache_status == CACHE_INODE_SUCCESS
	    || cache_status == CACHE_INODE_FSAL_EACCESS) {
		/* Build Post Op Attributes */
		nfs_SetPostOpAttr(entry,
				  &(res->res_access3.ACCESS3res_u.resok.
				    obj_attributes));

		res->res_access3.status = NFS3_OK;
		rc = NFS_REQ_OK;
		goto out;
	}

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

	res->res_access3.status = nfs3_Errno(cache_status);
	nfs_SetPostOpAttr(entry,
			  &(res->res_access3.ACCESS3res_u.resfail.
			    obj_attributes));
 out:

	if (entry)
		cache_inode_put(entry);

	return rc;
}				/* nfs3_access */
示例#7
0
int nfs3_readdir(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct fsal_obj_handle *dir_obj = NULL;
	struct fsal_obj_handle *parent_dir_obj = NULL;
	unsigned long count = 0;
	uint64_t cookie = 0;
	uint64_t fsal_cookie = 0;
	cookieverf3 cookie_verifier;
	unsigned int num_entries = 0;
	unsigned long estimated_num_entries = 0;
	object_file_type_t dir_filetype = 0;
	bool eod_met = false;
	fsal_status_t fsal_status = {0, 0};
	fsal_status_t fsal_status_gethandle = {0, 0};
	int rc = NFS_REQ_OK;
	struct nfs3_readdir_cb_data tracker = { NULL };
	bool use_cookie_verifier = op_ctx_export_has_option(
					EXPORT_OPTION_USE_COOKIE_VERIFIER);

	if (isDebug(COMPONENT_NFSPROTO) || isDebug(COMPONENT_NFS_READDIR)) {
		char str[LEN_FH_STR];
		log_components_t component;

		nfs_FhandleToStr(req->rq_vers,
				 &(arg->arg_readdir3.dir),
				 NULL,
				 str);

		if (isDebug(COMPONENT_NFSPROTO))
			component = COMPONENT_NFSPROTO;
		else
			component = COMPONENT_NFS_READDIR;

		LogDebug(component,
			 "REQUEST PROCESSING: Calling nfs_Readdir handle: %s",
			 str);
	}

	READDIR3resok * const RES_READDIR3_OK =
	    &res->res_readdir3.READDIR3res_u.resok;

	/* to avoid setting it on each error case */
	res->res_readdir3.READDIR3res_u.resfail.dir_attributes.
	    attributes_follow = FALSE;

	/* Look up object for filehandle */
	dir_obj = nfs3_FhandleToCache(&(arg->arg_readdir3.dir),
					&(res->res_readdir3.status),
					&rc);
	if (dir_obj == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	/* Extract the filetype */
	dir_filetype = dir_obj->type;
	/* Sanity checks -- must be a directory */
	if (dir_filetype != DIRECTORY) {
		res->res_readdir3.status = NFS3ERR_NOTDIR;

		rc = NFS_REQ_OK;
		goto out;
	}

	/* Parse out request arguments and decide how many entries we
	 * want.  For NFSv3, deal with the cookie verifier.
	 */

	count = arg->arg_readdir3.count;
	cookie = arg->arg_readdir3.cookie;
	estimated_num_entries =
	    MIN(count / (sizeof(entry3) - sizeof(char *)), 120);
	LogFullDebug(COMPONENT_NFS_READDIR,
		     "---> nfs3_readdir: count=%lu  cookie=%" PRIu64
		     " estimated_num_entries=%lu",
		     count, cookie, estimated_num_entries);
	if (estimated_num_entries == 0) {
		res->res_readdir3.status = NFS3ERR_TOOSMALL;
		rc = NFS_REQ_OK;
		goto out;
	}

	/* To make or check the cookie verifier */
	memset(cookie_verifier, 0, sizeof(cookieverf3));

	/* If cookie verifier is used, then a
	 * non-trivial value is returned to the
	 * client.
	 *
	 * This value is the ctime of the directory. If verifier is
	 * unused (as in many NFS Servers) then only a set of zeros
	 * is returned (trivial value).
	 */
	if (use_cookie_verifier) {
		struct attrlist attrs;

		fsal_prepare_attrs(&attrs, ATTR_CTIME);

		fsal_status = dir_obj->obj_ops.getattrs(dir_obj, &attrs);

		if (FSAL_IS_ERROR(fsal_status)) {
			res->res_readdir3.status =
						nfs3_Errno_status(fsal_status);
			LogFullDebug(COMPONENT_NFS_READDIR,
				     "getattrs returned %s",
				     msg_fsal_err(fsal_status.major));
			goto out;
		}

		memcpy(cookie_verifier,
		       &attrs.ctime.tv_sec,
		       sizeof(attrs.ctime.tv_sec));

		/* Done with the attrs */
		fsal_release_attrs(&attrs);
	}

	if (cookie != 0 && use_cookie_verifier) {
		/* Not the first call, so we have to check the cookie
		 * verifier
		 */
		if (memcmp(cookie_verifier,
			   arg->arg_readdir3.cookieverf,
			   NFS3_COOKIEVERFSIZE) != 0) {
			res->res_readdir3.status = NFS3ERR_BAD_COOKIE;
			rc = NFS_REQ_OK;
			goto out;
		}
	}

	tracker.entries = gsh_calloc(estimated_num_entries, sizeof(entry3));
	tracker.total_entries = estimated_num_entries;
	tracker.mem_left = count - sizeof(READDIR3resok);
	tracker.count = 0;
	tracker.error = NFS3_OK;

	/* Adjust the cookie we supply to fsal */
	if (cookie > 2) {	/* it is not the cookie for "." nor ".." */
		fsal_cookie = cookie;
	} else {
		fsal_cookie = 0;
	}

	/* Fills "."  */
	if (cookie == 0) {
		res->res_readdir3.status = nfs_readdir_dot_entry(dir_obj, ".",
					 1, nfs3_readdir_callback, &tracker);

		if (res->res_readdir3.status != NFS3_OK) {
			rc = NFS_REQ_OK;
			goto out;
		}
	}

	/* Fills ".." */
	if ((cookie <= 1) && (estimated_num_entries > 1)) {
		/* Get parent pentry */
		fsal_status_gethandle = fsal_lookupp(dir_obj,
						     &parent_dir_obj,
						     NULL);

		if (parent_dir_obj == NULL) {
			res->res_readdir3.status =
			    nfs3_Errno_status(fsal_status_gethandle);
			rc = NFS_REQ_OK;
			goto out;
		}

		res->res_readdir3.status = nfs_readdir_dot_entry(parent_dir_obj,
				"..", 2, nfs3_readdir_callback, &tracker);

		if (res->res_readdir3.status != NFS3_OK) {
			rc = NFS_REQ_OK;
			goto out;
		}

		parent_dir_obj->obj_ops.put_ref(parent_dir_obj);
		parent_dir_obj = NULL;
	}

	/* Call readdir */
	fsal_status = fsal_readdir(dir_obj, fsal_cookie, &num_entries, &eod_met,
				   0,	/* no attr */
				   nfs3_readdir_callback, &tracker);

	if (FSAL_IS_ERROR(fsal_status)) {
		if (nfs_RetryableError(fsal_status.major)) {
			rc = NFS_REQ_DROP;
			goto out;
		}

		res->res_readdir3.status = nfs3_Errno_status(fsal_status);
		nfs_SetPostOpAttr(dir_obj,
				  &res->res_readdir3.READDIR3res_u.resfail.
					dir_attributes,
				  NULL);
		goto out;
	}

	if (tracker.error != NFS3_OK) {
		res->res_readdir3.status = tracker.error;
		nfs_SetPostOpAttr(dir_obj,
				  &res->res_readdir3.READDIR3res_u.resfail.
					dir_attributes,
				  NULL);
		goto out;
	}

	LogFullDebug(COMPONENT_NFS_READDIR,
		     "-- Readdir -> Call to fsal_readdir(cookie=%"
		     PRIu64 ")",
		     fsal_cookie);

	if ((num_entries == 0) && (cookie > 1)) {
		RES_READDIR3_OK->reply.entries = NULL;
		RES_READDIR3_OK->reply.eof = TRUE;
	} else {
		RES_READDIR3_OK->reply.entries = tracker.entries;
		RES_READDIR3_OK->reply.eof = eod_met;
	}
	nfs_SetPostOpAttr(dir_obj, &RES_READDIR3_OK->dir_attributes, NULL);
	memcpy(RES_READDIR3_OK->cookieverf, cookie_verifier,
	       sizeof(cookieverf3));
	res->res_readdir3.status = NFS3_OK;

	rc = NFS_REQ_OK;

 out:
	/* return references */
	if (dir_obj)
		dir_obj->obj_ops.put_ref(dir_obj);

	if (parent_dir_obj)
		parent_dir_obj->obj_ops.put_ref(parent_dir_obj);

	/* Deallocate memory in the event of an error */
	if (((res->res_readdir3.status != NFS3_OK) || (rc != NFS_REQ_OK) ||
	    ((num_entries == 0) && (cookie > 1))) &&
	    (tracker.entries != NULL)) {
		free_entry3s(tracker.entries);
		RES_READDIR3_OK->reply.entries = NULL;
	}

	return rc;
}				/* nfs3_readdir */
示例#8
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;
}
示例#9
0
int nfs3_rmdir(nfs_arg_t *arg,
	       nfs_worker_data_t *worker,
	       struct svc_req *req, nfs_res_t *res)
{
	cache_entry_t *parent_entry = NULL;
	cache_entry_t *child_entry = NULL;
	pre_op_attr pre_parent = {
		.attributes_follow = false
	};
	cache_inode_status_t cache_status;
	const char *name = arg->arg_rmdir3.object.name;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_vers,
				 &arg->arg_rmdir3.object.dir,
				 NULL,
				 str);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_rmdir handle: %s "
			 "name: %s", str, name);
	}

	/* Convert file handle into a pentry */
	/* to avoid setting it on each error case */
	res->res_rmdir3.RMDIR3res_u.resfail.dir_wcc.before.attributes_follow =
	    FALSE;
	res->res_rmdir3.RMDIR3res_u.resfail.dir_wcc.after.attributes_follow =
	    FALSE;

	parent_entry = nfs3_FhandleToCache(&arg->arg_rmdir3.object.dir,
					   &res->res_rmdir3.status,
					   &rc);

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

	nfs_SetPreOpAttr(parent_entry, &pre_parent);

	/* Sanity checks: directory name must be non-null; parent
	 * must be a directory.
	 */
	if (parent_entry->type != DIRECTORY) {
		res->res_rmdir3.status = NFS3ERR_NOTDIR;
		rc = NFS_REQ_OK;
		goto out;
	}

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

	/* Lookup to the entry to be removed to check that it is a
	 * directory
	 */
	cache_status = cache_inode_lookup(parent_entry,
					  name,
					  &child_entry);

	if (child_entry != NULL) {
		/* Sanity check: make sure we are about to remove a
		 * directory
		 */
		if (child_entry->type != DIRECTORY) {
			res->res_rmdir3.status = NFS3ERR_NOTDIR;
			rc = NFS_REQ_OK;
			goto out;
		}
	}

	cache_status = cache_inode_remove(parent_entry, name);

	if (cache_status != CACHE_INODE_SUCCESS)
		goto out_fail;

	nfs_SetWccData(&pre_parent, parent_entry,
		       &res->res_rmdir3.RMDIR3res_u.resok.dir_wcc);

	res->res_rmdir3.status = NFS3_OK;

	rc = NFS_REQ_OK;

	goto out;

 out_fail:
	res->res_rmdir3.status = nfs3_Errno(cache_status);
	nfs_SetWccData(&pre_parent, parent_entry,
		       &res->res_rmdir3.RMDIR3res_u.resfail.dir_wcc);

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

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

	if (parent_entry)
		cache_inode_put(parent_entry);

	return rc;
}				/* nfs3_rmdir */

/**
 * @brief Free the result structure allocated for nfs3_rmdir
 *
 * This function frees the result structure allocated for nfs3_rmdir.
 *
 * @param[in,out] res Result structure
 *
 */
void nfs3_rmdir_free(nfs_res_t *res)
{
	return;
}
示例#10
0
int nfs3_lookup(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct fsal_obj_handle *obj_dir = NULL;
	struct fsal_obj_handle *obj_file = NULL;
	fsal_status_t fsal_status;
	char *name = NULL;
	int rc = NFS_REQ_OK;
	struct attrlist attrs;

	/* We have the option of not sending attributes, so set ATTR_RDATTR_ERR.
	 */
	fsal_prepare_attrs(&attrs, ATTRS_NFS3 | ATTR_RDATTR_ERR);

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		name = arg->arg_lookup3.what.name;

		nfs_FhandleToStr(req->rq_msg.cb_vers,
				 &(arg->arg_lookup3.what.dir),
				 NULL, str);
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs_Lookup handle: %s name: %s",
			 str, name);
	}

	/* to avoid setting it on each error case */
	res->res_lookup3.LOOKUP3res_u.resfail.dir_attributes.attributes_follow =
	    FALSE;

	obj_dir = nfs3_FhandleToCache(&arg->arg_lookup3.what.dir,
					&res->res_lookup3.status,
					&rc);

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

	name = arg->arg_lookup3.what.name;

	fsal_status = fsal_lookup(obj_dir, name, &obj_file, &attrs);

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

		res->res_lookup3.status = nfs3_Errno_status(fsal_status);
		nfs_SetPostOpAttr(obj_dir,
				  &res->res_lookup3.LOOKUP3res_u.resfail.
					dir_attributes,
				  NULL);
	} else {
		/* Build FH */
		if (nfs3_FSALToFhandle(
			    true,
			    &res->res_lookup3.LOOKUP3res_u.resok.object,
			    obj_file,
			    op_ctx->ctx_export)) {
			/* Build entry attributes */
			nfs_SetPostOpAttr(obj_file,
					  &res->res_lookup3.LOOKUP3res_u.
						resok.obj_attributes,
					  &attrs);

			/* Build directory attributes */
			nfs_SetPostOpAttr(obj_dir,
					  &res->res_lookup3.
					     LOOKUP3res_u.resok.dir_attributes,
					  NULL);
			res->res_lookup3.status = NFS3_OK;
		} else {
			res->res_lookup3.status = NFS3ERR_BADHANDLE;
		}
	}

	rc = NFS_REQ_OK;

 out:

	/* Release the attributes. */
	fsal_release_attrs(&attrs);

	/* return references */
	if (obj_dir)
		obj_dir->obj_ops.put_ref(obj_dir);

	if (obj_file)
		obj_file->obj_ops.put_ref(obj_file);

	return rc;
}				/* nfs3_lookup */
示例#11
0
int nfs3_fsstat(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	fsal_dynamicfsinfo_t dynamicinfo;
	cache_inode_status_t cache_status;
	cache_entry_t *entry = NULL;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_vers, &(arg->arg_fsstat3.fsroot), NULL,
				 str);
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_fsstat handle: %s",
			 str);
	}

	/* to avoid setting it on each error case */
	res->res_fsstat3.FSSTAT3res_u.resfail.obj_attributes.attributes_follow =
	    FALSE;

	entry = nfs3_FhandleToCache(&arg->arg_fsstat3.fsroot,
				    &res->res_fsstat3.status,
				    &rc);

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

	/* Get statistics and convert from cache */
	cache_status = cache_inode_statfs(entry,
					  &dynamicinfo);

	if (cache_status == CACHE_INODE_SUCCESS) {
		LogFullDebug(COMPONENT_NFSPROTO,
			     "nfs_Fsstat --> dynamicinfo.total_bytes=%" PRIu64
			     " dynamicinfo.free_bytes=%" PRIu64
			     " dynamicinfo.avail_bytes=%" PRIu64,
			     dynamicinfo.total_bytes, dynamicinfo.free_bytes,
			     dynamicinfo.avail_bytes);
		LogFullDebug(COMPONENT_NFSPROTO,
			     "nfs_Fsstat --> dynamicinfo.total_files=%" PRIu64
			     " dynamicinfo.free_files=%" PRIu64
			     " dynamicinfo.avail_files=%" PRIu64,
			     dynamicinfo.total_files, dynamicinfo.free_files,
			     dynamicinfo.avail_files);

		nfs_SetPostOpAttr(entry,
				  &(res->res_fsstat3.FSSTAT3res_u.resok.
				    obj_attributes));

		res->res_fsstat3.FSSTAT3res_u.resok.tbytes =
		    dynamicinfo.total_bytes;
		res->res_fsstat3.FSSTAT3res_u.resok.fbytes =
		    dynamicinfo.free_bytes;
		res->res_fsstat3.FSSTAT3res_u.resok.abytes =
		    dynamicinfo.avail_bytes;
		res->res_fsstat3.FSSTAT3res_u.resok.tfiles =
		    dynamicinfo.total_files;
		res->res_fsstat3.FSSTAT3res_u.resok.ffiles =
		    dynamicinfo.free_files;
		res->res_fsstat3.FSSTAT3res_u.resok.afiles =
		    dynamicinfo.avail_files;
		/* volatile FS */
		res->res_fsstat3.FSSTAT3res_u.resok.invarsec = 0;

		res->res_fsstat3.status = NFS3_OK;

		LogFullDebug(COMPONENT_NFSPROTO,
			     "nfs_Fsstat --> tbytes=%llu fbytes=%llu abytes=%llu",
			     res->res_fsstat3.FSSTAT3res_u.resok.tbytes,
			     res->res_fsstat3.FSSTAT3res_u.resok.fbytes,
			     res->res_fsstat3.FSSTAT3res_u.resok.abytes);

		LogFullDebug(COMPONENT_NFSPROTO,
			     "nfs_Fsstat --> tfiles=%llu fffiles=%llu afiles=%llu",
			     res->res_fsstat3.FSSTAT3res_u.resok.tfiles,
			     res->res_fsstat3.FSSTAT3res_u.resok.ffiles,
			     res->res_fsstat3.FSSTAT3res_u.resok.afiles);

		rc = NFS_REQ_OK;
		goto out;
	}

	/* At this point we met an error */
	if (nfs_RetryableError(cache_status)) {
		rc = NFS_REQ_DROP;
		goto out;
	}

	res->res_fsstat3.status = nfs3_Errno(cache_status);
	rc = NFS_REQ_OK;

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

	return rc;
}				/* nfs3_fsstat */
示例#12
0
int nfs3_readlink(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	cache_entry_t *entry = NULL;
	cache_inode_status_t cache_status;
	struct gsh_buffdesc link_buffer = {
		.addr = NULL,
		.len = 0
	};
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_vers,
				 &(arg->arg_readlink3.symlink),
				 NULL, str);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs_Readlink handle: %s",
			 str);
	}

	/* to avoid setting it on each error case */
	res->res_readlink3.READLINK3res_u.resfail.symlink_attributes.
	    attributes_follow = false;

	entry = nfs3_FhandleToCache(&arg->arg_readlink3.symlink,
				    &res->res_readlink3.status,
				    &rc);

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

	/* Sanity Check: the entry must be a link */
	if (entry->type != SYMBOLIC_LINK) {
		res->res_readlink3.status = NFS3ERR_INVAL;
		rc = NFS_REQ_OK;
		goto out;
	}

	cache_status = cache_inode_readlink(entry, &link_buffer);

	if (cache_status != CACHE_INODE_SUCCESS) {
		res->res_readlink3.status = nfs3_Errno(cache_status);
		nfs_SetPostOpAttr(entry,
				  &res->res_readlink3.READLINK3res_u.resfail.
				  symlink_attributes);

		if (nfs_RetryableError(cache_status))
			rc = NFS_REQ_DROP;

		goto out;
	}

	/* Reply to the client */
	res->res_readlink3.READLINK3res_u.resok.data = link_buffer.addr;

	nfs_SetPostOpAttr(entry,
			  &res->res_readlink3.READLINK3res_u.
			  resok.symlink_attributes);
	res->res_readlink3.status = NFS3_OK;

	rc = NFS_REQ_OK;

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

	return rc;
}				/* nfs3_readlink */

/**
 * @brief Free the result structure allocated for nfs3_readlink.
 *
 * This function frees the result structure allocated for
 * nfs3_readlink.
 *
 * @param[in,out] res Result structure
 *
 */
void nfs3_readlink_free(nfs_res_t *res)
{
	if (res->res_readlink3.status == NFS3_OK)
		gsh_free(res->res_readlink3.READLINK3res_u.resok.data);
}
示例#13
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 */
}
示例#14
0
int nfs3_fsinfo(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct fsal_obj_handle *obj = NULL;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		sprint_fhandle3(str, &(arg->arg_fsinfo3.fsroot));
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_fsinfo handle: %s",
			 str);
	}

	/* To avoid setting it on each error case */
	res->res_fsinfo3.FSINFO3res_u.resfail.obj_attributes.attributes_follow =
	    FALSE;

	obj = nfs3_FhandleToCache(&arg->arg_fsinfo3.fsroot,
				    &res->res_fsinfo3.status,
				    &rc);

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

	/* New fields were added to nfs_config_t to handle this
	   value. We use them */

	FSINFO3resok * const FSINFO_FIELD =
		&res->res_fsinfo3.FSINFO3res_u.resok;

	FSINFO_FIELD->rtmax =
		atomic_fetch_uint64_t(&op_ctx->ctx_export->MaxRead);
	FSINFO_FIELD->rtpref =
		atomic_fetch_uint64_t(&op_ctx->ctx_export->PrefRead);
	/* This field is generally unused, it will be removed in V4 */
	FSINFO_FIELD->rtmult = DEV_BSIZE;

	FSINFO_FIELD->wtmax =
		atomic_fetch_uint64_t(&op_ctx->ctx_export->MaxWrite);
	FSINFO_FIELD->wtpref =
		atomic_fetch_uint64_t(&op_ctx->ctx_export->PrefWrite);
	/* This field is generally unused, it will be removed in V4 */
	FSINFO_FIELD->wtmult = DEV_BSIZE;

	FSINFO_FIELD->dtpref =
		atomic_fetch_uint64_t(&op_ctx->ctx_export->PrefReaddir);
	FSINFO_FIELD->maxfilesize =
	    op_ctx->fsal_export->exp_ops.fs_maxfilesize(op_ctx->fsal_export);
	FSINFO_FIELD->time_delta.tv_sec = 1;
	FSINFO_FIELD->time_delta.tv_nsec = 0;

	LogFullDebug(COMPONENT_NFSPROTO,
		     "rtmax = %d | rtpref = %d | trmult = %d",
		     FSINFO_FIELD->rtmax, FSINFO_FIELD->rtpref,
		     FSINFO_FIELD->rtmult);
	LogFullDebug(COMPONENT_NFSPROTO,
		     "wtmax = %d | wtpref = %d | wrmult = %d",
		     FSINFO_FIELD->wtmax, FSINFO_FIELD->wtpref,
		     FSINFO_FIELD->wtmult);
	LogFullDebug(COMPONENT_NFSPROTO, "dtpref = %d | maxfilesize = %llu ",
		     FSINFO_FIELD->dtpref, FSINFO_FIELD->maxfilesize);

	/* Allow all kinds of operations to be performed on the server
	   through NFS v3 */
	FSINFO_FIELD->properties =
	    FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS | FSF3_CANSETTIME;

	nfs_SetPostOpAttr(obj,
			  &res->res_fsinfo3.FSINFO3res_u.resok.
			    obj_attributes,
			  NULL);
	res->res_fsinfo3.status = NFS3_OK;

 out:

	if (obj)
		obj->obj_ops.put_ref(obj);

	return rc;
}				/* nfs3_fsinfo */
示例#15
0
int nfs3_fsstat(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	fsal_dynamicfsinfo_t dynamicinfo;
	fsal_status_t fsal_status;
	struct fsal_obj_handle *obj = NULL;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_msg.cb_vers,
				 &(arg->arg_fsstat3.fsroot),
				 NULL, str);
		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs3_fsstat handle: %s",
			 str);
	}

	/* to avoid setting it on each error case */
	res->res_fsstat3.FSSTAT3res_u.resfail.obj_attributes.attributes_follow =
	    FALSE;

	obj = nfs3_FhandleToCache(&arg->arg_fsstat3.fsroot,
				    &res->res_fsstat3.status,
				    &rc);

	if (obj == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		return rc;
	}

	/* Get statistics and convert from FSAL */
	fsal_status = fsal_statfs(obj, &dynamicinfo);

	if (FSAL_IS_ERROR(fsal_status)) {
		/* At this point we met an error */
		LogFullDebug(COMPONENT_NFSPROTO,
			     "failed statfs: fsal_status=%s",
			     fsal_err_txt(fsal_status));

		if (nfs_RetryableError(fsal_status.major)) {
			/* Drop retryable errors. */
			rc = NFS_REQ_DROP;
		} else {
			res->res_fsstat3.status =
						nfs3_Errno_status(fsal_status);
			rc = NFS_REQ_OK;
		}

		goto out;
	}

	LogFullDebug(COMPONENT_NFSPROTO,
		     "nfs_Fsstat --> dynamicinfo.total_bytes=%" PRIu64
		     " dynamicinfo.free_bytes=%" PRIu64
		     " dynamicinfo.avail_bytes=%" PRIu64,
		     dynamicinfo.total_bytes, dynamicinfo.free_bytes,
		     dynamicinfo.avail_bytes);
	LogFullDebug(COMPONENT_NFSPROTO,
		     "nfs_Fsstat --> dynamicinfo.total_files=%" PRIu64
		     " dynamicinfo.free_files=%" PRIu64
		     " dynamicinfo.avail_files=%" PRIu64,
		     dynamicinfo.total_files, dynamicinfo.free_files,
		     dynamicinfo.avail_files);

	nfs_SetPostOpAttr(obj,
			  &res->res_fsstat3.FSSTAT3res_u.resok.obj_attributes,
			  NULL);

	res->res_fsstat3.FSSTAT3res_u.resok.tbytes = dynamicinfo.total_bytes;
	res->res_fsstat3.FSSTAT3res_u.resok.fbytes = dynamicinfo.free_bytes;
	res->res_fsstat3.FSSTAT3res_u.resok.abytes = dynamicinfo.avail_bytes;
	res->res_fsstat3.FSSTAT3res_u.resok.tfiles = dynamicinfo.total_files;
	res->res_fsstat3.FSSTAT3res_u.resok.ffiles = dynamicinfo.free_files;
	res->res_fsstat3.FSSTAT3res_u.resok.afiles = dynamicinfo.avail_files;
	/* volatile FS */
	res->res_fsstat3.FSSTAT3res_u.resok.invarsec = 0;

	res->res_fsstat3.status = NFS3_OK;

	LogFullDebug(COMPONENT_NFSPROTO,
		     "nfs_Fsstat --> tbytes=%llu fbytes=%llu abytes=%llu",
		     res->res_fsstat3.FSSTAT3res_u.resok.tbytes,
		     res->res_fsstat3.FSSTAT3res_u.resok.fbytes,
		     res->res_fsstat3.FSSTAT3res_u.resok.abytes);

	LogFullDebug(COMPONENT_NFSPROTO,
		     "nfs_Fsstat --> tfiles=%llu fffiles=%llu afiles=%llu",
		     res->res_fsstat3.FSSTAT3res_u.resok.tfiles,
		     res->res_fsstat3.FSSTAT3res_u.resok.ffiles,
		     res->res_fsstat3.FSSTAT3res_u.resok.afiles);

	rc = NFS_REQ_OK;

 out:
	/* return references */
	obj->obj_ops.put_ref(obj);

	return rc;
}				/* nfs3_fsstat */