示例#1
0
文件: mds.c 项目: asias/nfs-ganesha
static void _stop_callback_thread(void *td)
{
	struct _recall_thread *_rt = td;
	void *tret;

	_rt->stop = true;
	panfs_um_cancel_recalls(_rt->fd, 0);
	pthread_join(_rt->thread, &tret);
	DBG_PRNT("_rt->thread => %ld\n", (long)tret);
	gsh_free(_rt);
}
示例#2
0
/**
 * @brief Release a DS handle
 *
 * @param[in] ds_pub The object to release
 */
static void
lustre_release(struct fsal_ds_handle *const ds_pub)
{
	/* The private 'full' DS handle */
	struct lustre_ds *ds = container_of(ds_pub,
					    struct lustre_ds,
					    ds);

	fsal_ds_handle_fini(&ds->ds);
	gsh_free(ds);
}
示例#3
0
void nsm_disconnect()
{
	if (nsm_count == 0 && nsm_clnt != NULL) {
		gsh_clnt_destroy(nsm_clnt);
		nsm_clnt = NULL;
		AUTH_DESTROY(nsm_auth);
		nsm_auth = NULL;
		gsh_free(nodename);
		nodename = NULL;
	}
}
示例#4
0
static int op_dsread(struct nfs_argop4 *op, compound_data_t *data,
		    struct nfs_resop4 *resp)
{
	READ4args * const arg_READ4 = &op->nfs_argop4_u.opread;
	READ4res * const res_READ4 = &resp->nfs_resop4_u.opread;
	/* NFSv4 return code */
	nfsstat4 nfs_status = 0;
	/* Buffer into which data is to be read */
	void *buffer = NULL;
	/* End of file flag */
	bool eof = false;

	/* Don't bother calling the FSAL if the read length is 0. */

	if (arg_READ4->count == 0) {
		res_READ4->READ4res_u.resok4.eof = FALSE;
		res_READ4->READ4res_u.resok4.data.data_len = 0;
		res_READ4->READ4res_u.resok4.data.data_val = NULL;
		res_READ4->status = NFS4_OK;
		return res_READ4->status;
	}

	/* Construct the FSAL file handle */

	buffer = gsh_malloc_aligned(4096, arg_READ4->count);

	res_READ4->READ4res_u.resok4.data.data_val = buffer;

	nfs_status = data->current_ds->dsh_ops.read(
				data->current_ds,
				op_ctx,
				&arg_READ4->stateid,
				arg_READ4->offset,
				arg_READ4->count,
				res_READ4->READ4res_u.resok4.data.data_val,
				&res_READ4->READ4res_u.resok4.data.data_len,
				&eof);

	if (nfs_status != NFS4_OK) {
		gsh_free(buffer);
		res_READ4->READ4res_u.resok4.data.data_val = NULL;
	}

	if (eof)
		res_READ4->READ4res_u.resok4.eof = TRUE;
	else
		res_READ4->READ4res_u.resok4.eof = FALSE;

	res_READ4->status = nfs_status;

	return res_READ4->status;
}
示例#5
0
static fsal_status_t readsymlink(struct fsal_obj_handle *obj_hdl,
				 struct gsh_buffdesc *link_content,
				 bool refresh)
{
	fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR;
	int retval = 0;
	struct gpfs_fsal_obj_handle *myself = NULL;
	fsal_status_t status;

	if (obj_hdl->type != SYMBOLIC_LINK) {
		fsal_error = ERR_FSAL_FAULT;
		goto out;
	}
	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle);
	if (refresh) {		/* lazy load or LRU'd storage */
		size_t retlink;
		char link_buff[PATH_MAX];

		retlink = PATH_MAX - 1;

		if (myself->u.symlink.link_content != NULL) {
			gsh_free(myself->u.symlink.link_content);
			myself->u.symlink.link_content = NULL;
			myself->u.symlink.link_size = 0;
		}

		status =
		    GPFSFSAL_readlink(obj_hdl, op_ctx, link_buff, &retlink);
		if (FSAL_IS_ERROR(status))
			return status;

		myself->u.symlink.link_content = gsh_malloc(retlink + 1);

		memcpy(myself->u.symlink.link_content, link_buff, retlink);
		myself->u.symlink.link_content[retlink] = '\0';
		myself->u.symlink.link_size = retlink + 1;
	}
	if (myself->u.symlink.link_content == NULL) {
		fsal_error = ERR_FSAL_FAULT;	/* probably a better error?? */
		goto out;
	}
	link_content->len = myself->u.symlink.link_size;
	link_content->addr = gsh_malloc(link_content->len);

	memcpy(link_content->addr, myself->u.symlink.link_content,
	       link_content->len);

 out:

	return fsalstat(fsal_error, retval);
}
示例#6
0
static fsal_status_t readsymlink(struct fsal_obj_handle *obj_hdl,
				 const struct req_op_context *opctx,
				 struct gsh_buffdesc *link_content,
				 bool refresh)
{
	int rc = 0;
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
	struct glusterfs_export *glfs_export =
	    container_of(obj_hdl->export, struct glusterfs_export, export);
	struct glusterfs_handle *objhandle =
	    container_of(obj_hdl, struct glusterfs_handle, handle);
#ifdef GLTIMING
	struct timespec s_time, e_time;

	now(&s_time);
#endif

	link_content->len = 1024;	// bad bad!!! need to determine size
	link_content->addr = gsh_malloc(link_content->len);
	if (link_content->addr == NULL) {
		status = gluster2fsal_error(rc);
		goto out;
	}

	rc = glfs_h_readlink(glfs_export->gl_fs, objhandle->glhandle,
			     link_content->addr, link_content->len);
	if (rc < 0) {
		status = gluster2fsal_error(errno);
		goto out;
	}

	/* Check if return buffer overflowed, it is still '\0' terminated */
	link_content->len = (strlen(link_content->addr) + 1);

 out:
	if (status.major != ERR_FSAL_NO_ERROR) {
		gsh_free(link_content->addr);
		link_content->addr = NULL;
		link_content->len = 0;
	}
#ifdef GLTIMING
	now(&e_time);
	latency_update(&s_time, &e_time, lat_readsymlink);
#endif

	return status;
}
示例#7
0
/* Allocate and fill in group_data structure */
static struct group_data *uid2grp_allocate_by_name(
		const struct gsh_buffdesc *name)
{
	struct passwd p;
	struct passwd *pp;
	char *namebuff = alloca(name->len + 1);
	struct group_data *gdata = NULL;
	char *buff;
	long buff_size;

	memcpy(namebuff, name->addr, name->len);
	*(namebuff + name->len) = '\0';

	buff_size = sysconf(_SC_GETPW_R_SIZE_MAX);
	if (buff_size == -1) {
		LogMajor(COMPONENT_IDMAPPER, "sysconf failure: %d", errno);
		return NULL;
	}

	buff = alloca(buff_size);
	if ((getpwnam_r(namebuff, &p, buff, buff_size, &pp) != 0)
	    || (pp == NULL)) {
		LogEvent(COMPONENT_IDMAPPER, "getpwnam_r %s failed", namebuff);
		return gdata;
	}

	gdata = gsh_malloc(sizeof(struct group_data) + strlen(p.pw_name));
	if (gdata == NULL) {
		LogEvent(COMPONENT_IDMAPPER, "failed to allocate group data");
		return gdata;
	}

	gdata->uname.len = strlen(p.pw_name);
	gdata->uname.addr = (char *)gdata + sizeof(struct group_data);
	memcpy(gdata->uname.addr, p.pw_name, gdata->uname.len);
	gdata->uid = p.pw_uid;
	gdata->gid = p.pw_gid;
	if (!my_getgrouplist_alloc(p.pw_name, p.pw_gid, gdata)) {
		gsh_free(gdata);
		return NULL;
	}

	PTHREAD_MUTEX_init(&gdata->lock, NULL);
	gdata->epoch = time(NULL);
	gdata->refcount = 0;
	return gdata;
}
示例#8
0
文件: ds.c 项目: hongjil5/nfs-ganesha
/**
 * @brief Release a DS object
 *
 * @param[in] obj_pub The object to release
 *
 * @return NFS Status codes.
 */
static void release(struct fsal_ds_handle *const ds_pub)
{
	int    rc                 = 0;
	struct glfs_ds_handle *ds =
		container_of(ds_pub, struct glfs_ds_handle, ds);

	fsal_ds_handle_fini(&ds->ds);
	if (ds->glhandle) {
		rc = glfs_h_close(ds->glhandle);
		if (rc) {
			LogMajor(COMPONENT_PNFS,
				 "glfs_h_close returned error %s(%d)",
				 strerror(errno), errno);
		}
	}
	gsh_free(ds);
}
static int ChangeoverExports()
{

#if 0
  exportlist_t *pcurrent = NULL;

  /**
   * @@TODO@@ This is all totally bogus code now that exports are under the
   * control of the export manager. Left as unfinished business.
   */
  if (nfs_param.pexportlist)
    pcurrent = nfs_param.pexportlist->next;

  while(pcurrent != NULL)
    {
      /* Leave the head so that the list may be replaced later without
       * changing the reference pointer in worker threads. */

      if (pcurrent == nfs_param.pexportlist)
        break;

      nfs_param.pexportlist->next = RemoveExportEntry(pcurrent);
      pcurrent = nfs_param.pexportlist->next;
    }

  /* Allocate memory if needed, could have started with NULL exports */
  if (nfs_param.pexportlist == NULL)
    nfs_param.pexportlist = gsh_malloc(sizeof(exportlist_t));

  if (nfs_param.pexportlist == NULL)
    return ENOMEM;

  /* Changed the old export list head to the new export list head.
   * All references to the exports list should be up-to-date now. */
  memcpy(nfs_param.pexportlist, temp_pexportlist, sizeof(exportlist_t));

  /* We no longer need the head that was created for
   * the new list since the export list is built as a linked list. */
  gsh_free(temp_pexportlist);
  temp_pexportlist = NULL;
  return 0;
#else
  return ENOTSUP;
#endif
}
示例#10
0
void avl_unit_clear_tree(struct avltree *t)
{
	avl_unit_val_t *v;
	struct avltree_node *node, *next_node;

	if (avltree_size(t) < 1)
		return;

	node = avltree_first(t);
	while (node) {
		next_node = avltree_next(node);
		v = avltree_container_of(node, avl_unit_val_t, node_hk);
		avltree_remove(&v->node_hk, &avl_tree_1);
		gsh_free(v->name);
		avl_unit_free_val(v);
		node = next_node;
	}
}
示例#11
0
static fsal_status_t handle_release(struct fsal_obj_handle *obj_hdl)
{
	int rc = 0;
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
	struct glusterfs_handle *objhandle =
	    container_of(obj_hdl, struct glusterfs_handle, handle);
#ifdef GLTIMING
	struct timespec s_time, e_time;

	now(&s_time);
#endif

	rc = fsal_obj_handle_uninit(&objhandle->handle);
	if (rc != 0) {
		status = gluster2fsal_error(rc);
		goto out;
	}

	if (objhandle->glfd) {
		rc = glfs_close(objhandle->glfd);
		if (rc) {
			status = gluster2fsal_error(errno);
			/* cleanup as much as possible */
		}
	}

	if (objhandle->glhandle) {
		rc = glfs_h_close(objhandle->glhandle);
		if (rc) {
			status = gluster2fsal_error(errno);
			goto out;
		}
	}

	gsh_free(objhandle);

 out:
#ifdef GLTIMING
	now(&e_time);
	latency_update(&s_time, &e_time, lat_handle_release);
#endif

	return status;
}
示例#12
0
static void fridgethr_remove( fridge_entry_t * pfe ) 
{
   if( pfe == NULL )
	return ;

   P( fridge_mutex ) ;
 
   if( pfe->pprev != NULL ) pfe->pprev->pnext = pfe->pnext ;
   if( pfe->pnext != NULL ) pfe->pnext->pprev = pfe->pprev ;

   if( pfe->pnext == NULL && pfe->pprev == NULL ) /* Is the fridge empty ? */
     fridge_content = NULL ;

   V( fridge_mutex ) ;

   gsh_free(pfe) ;

   return ;
 } /* fridgethr_remove */
示例#13
0
FILE *open_memstream(char **cp, size_t *lenp)
{
    struct memstream *ms;
    int save_errno;
    FILE *fp;

    *cp = NULL;
    *lenp = 0;
    ms = gsh_malloc(sizeof(*ms));
    ms->cp = cp;
    ms->lenp = lenp;
    ms->offset = 0;
    fp = funopen(ms, memstream_read, memstream_write, memstream_seek,
                 memstream_close);
    if (fp == NULL) {
        save_errno = errno;
        gsh_free(ms);
        errno = save_errno;
    }
    return fp;
}
示例#14
0
bool pwentuid2grp(uid_t uid, struct gsh_buffdesc *name,
		  struct group_data *pgdata)
{
	char buff[1024];
	struct passwd p;
	struct passwd *pp;

	if ((getpwuid_r(uid, &p, buff, MAXPATHLEN, &pp) != 0) || (pp == NULL)) {
		LogEvent(COMPONENT_IDMAPPER, "getpwnam_r %u failed", uid);
		return false;
	}

	/** @todo Waste of memory here. To be fixed */
	pgdata->pgroups = (gid_t *) gsh_malloc(MAX_GRP * sizeof(gid_t));
	if (pgdata->pgroups == NULL)
		return false;

	pgdata->nbgroups = MAX_GRP;
	if (getgrouplist
	    (p.pw_name, p.pw_gid, pgdata->pgroups, &pgdata->nbgroups) == -1) {
		LogEvent(COMPONENT_IDMAPPER, "getgrouplist %s failed",
			 p.pw_name);
		gsh_free(pgdata->pgroups);
		return false;
	}

	/* Resize pgroups to what it should be */
	pgdata->pgroups =
	    gsh_realloc(pgdata->pgroups, pgdata->nbgroups * sizeof(gid_t));

	/* Set puid */
	name->addr = p.pw_name;
	name->len = strlen(p.pw_name);

	/* Set uid/gid */
	pgdata->uid = p.pw_uid;
	pgdata->gid = p.pw_gid;

	return true;
}
示例#15
0
/* Here and not static because proxy.c needs this function
 * but we also need access to pxy_exp_ops - I'd rather
 * keep the later static then the former */
fsal_status_t pxy_create_export(struct fsal_module *fsal_hdl,
				void *parse_node,
				struct config_error_type *err_type,
				const struct fsal_up_vector *up_ops)
{
	struct pxy_export *exp = gsh_calloc(1, sizeof(*exp));
	struct pxy_fsal_module *pxy =
	    container_of(fsal_hdl, struct pxy_fsal_module, module);

	if (!exp)
		return fsalstat(ERR_FSAL_NOMEM, ENOMEM);
	if (fsal_export_init(&exp->exp) != 0) {
		gsh_free(exp);
		return fsalstat(ERR_FSAL_NOMEM, ENOMEM);
	}
	pxy_export_ops_init(&exp->exp.exp_ops);
	exp->exp.up_ops = up_ops;
	exp->info = &pxy->special;
	exp->exp.fsal = fsal_hdl;
	op_ctx->fsal_export = &exp->exp;
	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
示例#16
0
static void
nfs_read_ok(exportlist_t * pexport,
            struct svc_req *preq, 
            nfs_res_t * pres,
            char *data,
            fsal_size_t read_size,
            fsal_attrib_list_t *attr,
            int eof)
{
    if((read_size == 0) && (data != NULL)) {
        gsh_free(data);
        data = NULL;
    }
    switch (preq->rq_vers) {
    case NFS_V2:
        pres->res_read2.READ2res_u.readok.data.nfsdata2_val = data;
        pres->res_read2.READ2res_u.readok.data.nfsdata2_len = read_size;

        nfs2_FSALattr_To_Fattr(pexport, attr,
                               &(pres->res_read2.READ2res_u.readok.attributes));

        pres->res_attr2.status = NFS_OK;
        break;

    case NFS_V3:
        /* Build Post Op Attributes */
        nfs_SetPostOpAttr(pexport, attr,
                          &(pres->res_read3.READ3res_u.resok.file_attributes));

        pres->res_read3.READ3res_u.resok.eof = eof;
        pres->res_read3.READ3res_u.resok.count = read_size;
        pres->res_read3.READ3res_u.resok.data.data_val = data;
        pres->res_read3.READ3res_u.resok.data.data_len = read_size;

        pres->res_read3.status = NFS3_OK;
        break;
    }                   /* switch */
}
示例#17
0
int main(int argc, char **argv)
{
	int c;
	int port = 0;
	int state = 0, sflag = 0;
	char mon_client[STR_SIZE], mflag = 0;
	char remote_addr_s[STR_SIZE], rflag = 0;
	char local_addr_s[STR_SIZE], lflag = 0;
	notify arg;
	CLIENT *clnt;
	struct netbuf *buf;
	char port_str[20];

	struct sockaddr_in local_addr;

	int fd;

	while ((c = getopt(argc, argv, "p:r:m:l:s:")) != EOF)
		switch (c) {
		case 'p':
			port = atoi(optarg);
			break;
		case 's':
			state = atoi(optarg);
			sflag = 1;
			break;
		case 'm':
			if (strlen(optarg) >= STR_SIZE) {
				fprintf(stderr, ERR_MSG1, "monitor host");
				exit(1);
			}
			strcpy(mon_client, optarg);
			mflag = 1;
			break;
		case 'r':
			if (strlen(optarg) >= STR_SIZE) {
				fprintf(stderr, ERR_MSG1, "remote address");
				exit(1);
			}
			strcpy(remote_addr_s, optarg);
			rflag = 1;
			break;
		case 'l':
			if (strlen(optarg) >= STR_SIZE) {
				fprintf(stderr, ERR_MSG1, "local address");
				exit(1);
			}
			strcpy(local_addr_s, optarg);
			lflag = 1;
			break;
		case '?':
		default:
			fprintf(stderr, USAGE, argv[0]);
			exit(1);
			break;
	}

	if ((sflag + lflag + mflag + rflag) != 4) {
		fprintf(stderr, USAGE, argv[0]);
		exit(1);
	}


	/* create a udp socket */
	fd = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_UDP);
	if (fd < 0) {
		fprintf(stderr, "socket call failed. errno=%d\n", errno);
		exit(1);
	}

	/* set up the sockaddr for local endpoint */
	memset(&local_addr, 0, sizeof(struct sockaddr_in));
	local_addr.sin_family = PF_INET;
	local_addr.sin_port = htons(port);
	local_addr.sin_addr.s_addr = inet_addr(local_addr_s);

	if (bind(fd, (struct sockaddr *)&local_addr,
			sizeof(struct sockaddr)) < 0) {
		fprintf(stderr, "bind call failed. errno=%d\n", errno);
		exit(1);
	}

	/* find the port for SM service of the remote server */
	buf = rpcb_find_mapped_addr(
				"udp",
				SM_PROG, SM_VERS,
				remote_addr_s);

	/* handle error here, for example,
	 * client side blocking rpc call
	 */
	if (buf == NULL) {
		close(fd);
		exit(1);
	}

	/* convert port to string format */
	sprintf(port_str, "%d",
		htons(((struct sockaddr_in *)
		buf->buf)->sin_port));

	clnt = clnt_dg_ncreate(fd, buf, SM_PROG,
			SM_VERS, 0, 0);

	arg.my_name = mon_client;
	arg.state = state;
	nsm_notify_1(&arg, clnt);

	/* free resources */
	gsh_free(buf->buf);
	gsh_free(buf);
	clnt_destroy(clnt);

	close(fd);

	return 0;
}
示例#18
0
int nlm_process_parameters(struct svc_req        * preq,
                           bool_t                  exclusive,
                           nlm4_lock             * alock,
                           fsal_lock_param_t     * plock,
                           cache_entry_t        ** ppentry,
                           fsal_op_context_t     * pcontext,
                           care_t                  care,
                           state_nsm_client_t   ** ppnsm_client,
                           state_nlm_client_t   ** ppnlm_client,
                           state_owner_t        ** ppowner,
                           state_block_data_t   ** ppblock_data)
{
  cache_inode_fsal_data_t fsal_data;
  fsal_attrib_list_t      attr;
  cache_inode_status_t    cache_status;
  SVCXPRT                *ptr_svc = preq->rq_xprt;
  int                     rc;

  *ppnsm_client = NULL;
  *ppnlm_client = NULL;
  *ppowner      = NULL;

  /* Convert file handle into a cache entry */
  if(alock->fh.n_len > MAX_NETOBJ_SZ ||
     !nfs3_FhandleToFSAL((nfs_fh3 *) &alock->fh, &fsal_data.fh_desc, pcontext))
    {
      /* handle is not valid */
      return NLM4_STALE_FH;
    }

  /* Now get the cached inode attributes */
  *ppentry = cache_inode_get(&fsal_data,
                             &attr,
                             pcontext,
                             NULL,
                             &cache_status);
  if(*ppentry == NULL)
    {
      /* handle is not valid */
      return NLM4_STALE_FH;
    }

  *ppnsm_client = get_nsm_client(care, ptr_svc, alock->caller_name);

  if(*ppnsm_client == NULL)
    {
      /* If NSM Client is not found, and we don't care (such as unlock),
       * just return GRANTED (the unlock must succeed, there can't be
       * any locks).
       */
      if(care != CARE_NOT)
        rc = NLM4_DENIED_NOLOCKS;
      else
        rc = NLM4_GRANTED;

      goto out_put;
    }

  *ppnlm_client = get_nlm_client(care, ptr_svc, *ppnsm_client, alock->caller_name);

  if(*ppnlm_client == NULL)
    {
      /* If NLM Client is not found, and we don't care (such as unlock),
       * just return GRANTED (the unlock must succeed, there can't be
       * any locks).
       */
      dec_nsm_client_ref(*ppnsm_client);

      if(care != CARE_NOT)
        rc = NLM4_DENIED_NOLOCKS;
      else
        rc = NLM4_GRANTED;

      goto out_put;
    }

  *ppowner = get_nlm_owner(care, *ppnlm_client, &alock->oh, alock->svid);

  if(*ppowner == NULL)
    {
      LogDebug(COMPONENT_NLM,
               "Could not get NLM Owner");
      dec_nsm_client_ref(*ppnsm_client);
      dec_nlm_client_ref(*ppnlm_client);
      *ppnlm_client = NULL;

      /* If owner is not found, and we don't care (such as unlock),
       * just return GRANTED (the unlock must succeed, there can't be
       * any locks).
       */
      if(care != CARE_NOT)
        rc = NLM4_DENIED_NOLOCKS;
      else
        rc = NLM4_GRANTED;

      goto out_put;
    }

  if(ppblock_data != NULL)
    {
      *ppblock_data = gsh_calloc(1, sizeof(**ppblock_data));
      /* Fill in the block data, if we don't get one, we will just proceed
       * without (which will mean the lock doesn't block.
       */
      if(*ppblock_data != NULL)
        {
          if(copy_xprt_addr(&(*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_hostaddr, ptr_svc) == 0)
            {
              LogFullDebug(COMPONENT_NLM,
                           "copy_xprt_addr failed for Program %d, Version %d, Function %d",
                           (int)preq->rq_prog, (int)preq->rq_vers, (int)preq->rq_proc);
              gsh_free(*ppblock_data);
              *ppblock_data = NULL;
              rc = NLM4_FAILED;
              goto out_put;
            }
          (*ppblock_data)->sbd_granted_callback = nlm_granted_callback;
          (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_bytes =
            (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf;
          (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_len = alock->fh.n_len;
          memcpy((*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf,
                 alock->fh.n_bytes,
                 alock->fh.n_len);
          /* FSF TODO: Ultimately I think the following will go away, we won't need the context, just the export */
          /* Copy credentials from pcontext */
#ifdef _USE_HPSS
	  /** @todo : PhD: Think about removing hpsscred_t from FSAL */ 
          (*ppblock_data)->sbd_credential.user  =  pcontext->credential.hpss_usercred.Uid ;
          (*ppblock_data)->sbd_credential.group =  pcontext->credential.hpss_usercred.Gid ;
#else
          (*ppblock_data)->sbd_credential = pcontext->credential;

          /* Copy the alt groups list */
          if(pcontext->credential.nbgroups != 0)
            {
              (*ppblock_data)->sbd_credential.alt_groups =
                      gsh_malloc(sizeof(gid_t) * pcontext->credential.nbgroups);
              if((*ppblock_data)->sbd_credential.alt_groups == NULL)
                {
                  gsh_free(*ppblock_data);
                  *ppblock_data = NULL;
                  rc = NLM4_FAILED;
                  goto out_put;
                }
              memcpy((*ppblock_data)->sbd_credential.alt_groups,
                     pcontext->credential.alt_groups,
                     pcontext->credential.nbgroups);
            }
#endif
        }
    }
  /* Fill in plock */
  plock->lock_type   = exclusive ? FSAL_LOCK_W : FSAL_LOCK_R;
  plock->lock_start  = alock->l_offset;
  plock->lock_length = alock->l_len;

  LogFullDebug(COMPONENT_NLM,
               "Parameters Processed");

  return -1;

 out_put:

  cache_inode_put(*ppentry);
  *ppentry = NULL;
  return rc;
}
示例#19
0
void netobj_free(netobj * obj)
{
  if(obj->n_bytes)
    gsh_free(obj->n_bytes);
}
示例#20
0
int _9p_symlink(struct _9p_request_data *req9p, void *worker_data,
		u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u16 *name_len = NULL;
	char *name_str = NULL;
	u16 *linkcontent_len = NULL;
	char *linkcontent_str = NULL;
	u32 *gid = NULL;

	struct _9p_fid *pfid = NULL;
	struct _9p_qid qid_symlink;

	cache_entry_t *pentry_symlink = NULL;
	char symlink_name[MAXNAMLEN];
	uint64_t fileid;
	cache_inode_status_t cache_status;
	uint32_t mode = 0777;
	cache_inode_create_arg_t create_arg;

	memset(&create_arg, 0, sizeof(create_arg));

	/* Get data */
	_9p_getptr(cursor, msgtag, u16);

	_9p_getptr(cursor, fid, u32);
	_9p_getstr(cursor, name_len, name_str);
	_9p_getstr(cursor, linkcontent_len, linkcontent_str);
	_9p_getptr(cursor, gid, u32);

	LogDebug(COMPONENT_9P,
		 "TSYMLINK: tag=%u fid=%u name=%.*s linkcontent=%.*s gid=%u",
		 (u32) *msgtag, *fid, *name_len, name_str, *linkcontent_len,
		 linkcontent_str, *gid);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout,
				  preply);

	pfid = req9p->pconn->fids[*fid];

	/* Check that it is a valid fid */
	if (pfid == NULL || pfid->pentry == NULL) {
		LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid);
		return _9p_rerror(req9p, worker_data, msgtag, EIO, plenout,
				  preply);
	}

	if ((pfid->op_context.export_perms->options &
				 EXPORT_OPTION_WRITE_ACCESS) == 0)
		return _9p_rerror(req9p, worker_data, msgtag, EROFS, plenout,
				  preply);

	op_ctx = &pfid->op_context;
	snprintf(symlink_name, MAXNAMLEN, "%.*s", *name_len, name_str);

	create_arg.link_content = gsh_malloc(MAXPATHLEN);
	if (create_arg.link_content == NULL)
		return _9p_rerror(req9p, worker_data, msgtag, EFAULT, plenout,
				  preply);

	snprintf(create_arg.link_content, MAXPATHLEN, "%.*s", *linkcontent_len,
		 linkcontent_str);

	/* Let's do the job */
	/* BUGAZOMEU: @todo : the gid parameter is not used yet,
	 * flags is not yet used */
	cache_status =
	    cache_inode_create(pfid->pentry, symlink_name, SYMBOLIC_LINK, mode,
			       &create_arg, &pentry_symlink);

	if (create_arg.link_content != NULL)
		gsh_free(create_arg.link_content);
	if (pentry_symlink == NULL) {
		return _9p_rerror(req9p, worker_data, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);
	}

	/* This is not a TATTACH fid */
	pfid->from_attach = false;

	cache_status = cache_inode_fileid(pentry_symlink, &fileid);

	/* put the entry:
	 * we don't want to remember it even if cache_inode_fileid fails. */
	cache_inode_put(pentry_symlink);

	if (cache_status != CACHE_INODE_SUCCESS) {
		return _9p_rerror(req9p, worker_data, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);
	}

	/* Build the qid */
	qid_symlink.type = _9P_QTSYMLINK;
	qid_symlink.version = 0;
	qid_symlink.path = fileid;

	/* Build the reply */
	_9p_setinitptr(cursor, preply, _9P_RSYMLINK);
	_9p_setptr(cursor, msgtag, u16);

	_9p_setqid(cursor, qid_symlink);

	_9p_setendptr(cursor, preply);
	_9p_checkbound(cursor, preply, plenout);

	LogDebug(COMPONENT_9P,
		 "RSYMLINK: tag=%u fid=%u name=%.*s qid=(type=%u,version=%u,path=%llu)",
		 (u32) *msgtag, *fid, *name_len, name_str, qid_symlink.type,
		 qid_symlink.version, (unsigned long long)qid_symlink.path);

	return 1;
}
示例#21
0
int nfs_Create(nfs_arg_t *parg,
               exportlist_t *pexport,
               fsal_op_context_t *pcontext,
               nfs_worker_data_t *pworker,
               struct svc_req *preq,
               nfs_res_t *pres)
{
  char *str_file_name = NULL;
  fsal_name_t file_name;
  fsal_accessmode_t mode = 0;
  cache_entry_t *file_pentry = NULL;
  cache_entry_t *parent_pentry = NULL;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t attr;
  fsal_attrib_list_t attr_parent_after;
  fsal_attrib_list_t attr_newfile;
  fsal_attrib_list_t attributes_create;
  fsal_attrib_list_t *ppre_attr;
  cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
  cache_inode_status_t cache_status_lookup;
  cache_inode_file_type_t parent_filetype;
  int rc = NFS_REQ_OK;
#ifdef _USE_QUOTA
  fsal_status_t fsal_status ;
#endif

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

      switch (preq->rq_vers)
        {
        case NFS_V2:
          str_file_name = parg->arg_create2.where.name;
          break;
        case NFS_V3:
          str_file_name = parg->arg_create3.where.name;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_create2.where.dir),
                       &(parg->arg_create3.where.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Create handle: %s name: %s",
               str, str_file_name);
    }

  if((preq->rq_vers == NFS_V3) && (nfs3_Is_Fh_Xattr(&(parg->arg_create3.where.dir))))
    {
      rc = nfs3_Create_Xattr(parg, pexport, pcontext, preq, pres);
      goto out;
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_create3.CREATE3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_create3.CREATE3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_create2.where.dir),
                                         &(parg->arg_create3.where.dir),
                                         NULL,
                                         &(pres->res_dirop2.status),
                                         &(pres->res_create3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      goto out;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: new file name must be non-null; parent must be a
   * directory. 
   */
  if(parent_filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_dirop2.status = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_create3.status = NFS3ERR_NOTDIR;
          break;
        }

      rc = NFS_REQ_OK;
      goto out;
    }

  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_file_name = parg->arg_create2.where.name;

      if(parg->arg_create2.attributes.mode != (unsigned int)-1)
        {
          mode = unix2fsal_mode(parg->arg_create2.attributes.mode);
        }
      else
        {
          mode = 0;
        }

      break;

    case NFS_V3:
      str_file_name = parg->arg_create3.where.name;
      if(parg->arg_create3.how.mode == EXCLUSIVE)
        {
          /*
           * Client has not provided mode information.
           * If the create works, the client will issue
           * a separate setattr request to fix up the
           * file's mode, so pick arbitrary value for now.
           */

          mode = 0;
        }
      else if(parg->arg_create3.how.createhow3_u.obj_attributes.mode.set_it == TRUE)
        mode =
            unix2fsal_mode(parg->arg_create3.how.createhow3_u.obj_attributes.mode.
                           set_mode3_u.mode);
      else
        mode = 0;
      break;
    }

#ifdef _USE_QUOTA
    /* if quota support is active, then we should check is the FSAL allows inode creation or not */
    fsal_status = FSAL_check_quota( pexport->fullpath, 
                                    FSAL_QUOTA_INODES,
                                    FSAL_OP_CONTEXT_TO_UID( pcontext ) ) ;
    if( FSAL_IS_ERROR( fsal_status ) )
     {

       switch (preq->rq_vers)
         {
           case NFS_V2:
             pres->res_dirop2.status = NFSERR_DQUOT ;
             break;

           case NFS_V3:
             pres->res_create3.status = NFS3ERR_DQUOT;
             break;
         }

       rc = NFS_REQ_OK ;
       goto out;
     }
#endif /* _USE_QUOTA */

  // if(str_file_name == NULL || strlen(str_file_name) == 0)
  if(str_file_name == NULL || *str_file_name == '\0' )
    {
      if(preq->rq_vers == NFS_V2)
        pres->res_dirop2.status = NFSERR_IO;
      if(preq->rq_vers == NFS_V3)
        pres->res_create3.status = NFS3ERR_INVAL;
    }
  else
    {
      if((cache_status = cache_inode_error_convert(FSAL_str2name(str_file_name,
                                                                 FSAL_MAX_NAME_LEN,
                                                                 &file_name))) ==
         CACHE_INODE_SUCCESS)
        {
          /*
           * Lookup file to see if it exists.  If so, use it.  Otherwise
           * create a new one.
           */
          file_pentry = cache_inode_lookup(parent_pentry,
                                           &file_name,
                                           &attr,
                                           pcontext,
                                           &cache_status_lookup);

          if((cache_status_lookup == CACHE_INODE_NOT_FOUND) ||
             ((cache_status_lookup == CACHE_INODE_SUCCESS)
              && (parg->arg_create3.how.mode == UNCHECKED)))
            {
              /* Create the file */
              if((parg->arg_create3.how.mode == UNCHECKED)
                 && (cache_status_lookup == CACHE_INODE_SUCCESS))
                {
                  cache_status = CACHE_INODE_SUCCESS;
                  attr_newfile = attr;
                }
              else
                file_pentry = cache_inode_create(parent_pentry,
                                                 &file_name,
                                                 REGULAR_FILE,
                                                 mode,
                                                 NULL,
                                                 &attr_newfile,
                                                 pcontext, &cache_status);

              if(file_pentry != NULL)
                {
                  /*
                   * Look at sattr to see if some attributes are to be set at creation time 
                   */
                  attributes_create.asked_attributes = 0ULL;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:

                      if(nfs2_Sattr_To_FSALattr(&attributes_create,
                                                &parg->arg_create2.attributes) == 0)
                        {
                          pres->res_dirop2.status = NFSERR_IO;
                          rc = NFS_REQ_OK;
                          goto out;
                          break;
                        }
                      break;

                    case NFS_V3:

                      if(nfs3_Sattr_To_FSALattr(&attributes_create,
                                                &parg->arg_create3.how.createhow3_u.
                                                obj_attributes) == 0)
                        {
                          pres->res_create3.status = NFS3ERR_INVAL;
                          rc = NFS_REQ_OK;
                          goto out;
                        }
                      break;
                    }

                  /* Mode is managed above (in cache_inode_create), there is no need 
                   * to manage it */
                  if(attributes_create.asked_attributes & FSAL_ATTR_MODE)
                    attributes_create.asked_attributes &= ~FSAL_ATTR_MODE;

                  /* Some clients (like Solaris 10) try to set the size of the file to 0
                   * at creation time. The FSAL create empty file, so we ignore this */
                  if(attributes_create.asked_attributes & FSAL_ATTR_SIZE)
                    attributes_create.asked_attributes &= ~FSAL_ATTR_SIZE;

                  if(attributes_create.asked_attributes & FSAL_ATTR_SPACEUSED)
                    attributes_create.asked_attributes &= ~FSAL_ATTR_SPACEUSED;

                  /* Are there attributes to be set (additional to the mode) ? */
                  if(attributes_create.asked_attributes != 0ULL &&
                     attributes_create.asked_attributes != FSAL_ATTR_MODE)
                    {
                      /* A call to cache_inode_setattr is required */
                      if(cache_inode_setattr(file_pentry,
                                             &attributes_create,
                                             pcontext,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                        {
                          /* If we are here, there was an error */
                          nfs_SetFailedStatus(pcontext, pexport,
                                              preq->rq_vers,
                                              cache_status,
                                              &pres->res_dirop2.status,
                                              &pres->res_create3.status,
                                              NULL, NULL,
                                              parent_pentry,
                                              ppre_attr,
                                              &(pres->res_create3.CREATE3res_u.resfail.
                                                dir_wcc), NULL, NULL, NULL);

                          if(nfs_RetryableError(cache_status)) {
                              rc = NFS_REQ_DROP;
                              goto out;
                          }

                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Get the resulting attributes from the Cache Inode */
                      if(cache_inode_getattr(file_pentry,
                                             &attr_newfile,
                                             pcontext,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                        {
                          /* If we are here, there was an error */

                          nfs_SetFailedStatus(pcontext, pexport,
                                              preq->rq_vers,
                                              cache_status,
                                              &pres->res_dirop2.status,
                                              &pres->res_create3.status,
                                              NULL, NULL,
                                              parent_pentry,
                                              ppre_attr,
                                              &(pres->res_create3.CREATE3res_u.resfail.
                                                dir_wcc), NULL, NULL, NULL);

                          if(nfs_RetryableError(cache_status)) {
                            rc = NFS_REQ_DROP;
                            goto out;
                          }

                          rc = NFS_REQ_OK;
                          goto out;
                        }

                    }

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      /* Build file handle */
                      if(nfs2_FSALToFhandle(
                              &(pres->res_dirop2.DIROP2res_u.diropok.file),
                              &file_pentry->handle,
                              pexport) == 0)
                        pres->res_dirop2.status = NFSERR_IO;
                      else
                        {
                          if(!nfs2_FSALattr_To_Fattr(
                                  pexport, &attr_newfile,
                                  &(pres->res_dirop2.DIROP2res_u.
                                    diropok.attributes)))
                            pres->res_dirop2.status = NFSERR_IO;
                          else
                            pres->res_dirop2.status = NFS_OK;
                        }
                      break;

                    case NFS_V3:
                      /* Build file handle */
                      pres->res_create3.status =
                        nfs3_AllocateFH(&pres->res_create3.CREATE3res_u
                                        .resok.obj.post_op_fh3_u.handle);
                      if (pres->res_create3.status != NFS3_OK)
                        {
                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Set Post Op Fh3 structure */
                      if(nfs3_FSALToFhandle(
                              &(pres->res_create3.CREATE3res_u.resok
                                .obj.post_op_fh3_u.handle),
                              &file_pentry->handle, pexport) == 0)
                        {
                          gsh_free(pres->res_create3.CREATE3res_u.resok.obj.
                                   post_op_fh3_u.handle.data.data_val);

                          pres->res_create3.status = NFS3ERR_BADHANDLE;
                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Set Post Op Fh3 structure */
                      pres->res_create3.CREATE3res_u.resok.obj.handle_follows
                        = TRUE;

                      /* Get the attributes of the parent after the
                         operation */
                      attr_parent_after = parent_pentry->attributes;

                      /* Build entry attributes */
                      nfs_SetPostOpAttr(pexport,
                                        &attr_newfile,
                                        &(pres->res_create3.CREATE3res_u.resok.
                                          obj_attributes));

                      /*
                       * Build Weak Cache Coherency data
                       */
                      nfs_SetWccData(pexport,
                                     ppre_attr,
                                     &attr_parent_after,
                                     &(pres->res_create3.CREATE3res_u
                                       .resok.dir_wcc));

                      pres->res_create3.status = NFS3_OK;
                      break;
                    }       /* switch */
                  rc = NFS_REQ_OK;
                  goto out;
                }
            }
          else
            {
              if(cache_status_lookup == CACHE_INODE_SUCCESS)
                {
                  /* Trying to create a file that already exists */
                  cache_status = CACHE_INODE_ENTRY_EXISTS;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_EXIST;
                      break;

                    case NFS_V3:
                      pres->res_create3.status = NFS3ERR_EXIST;
                      break;
                    }
                }
              else
                {
                  /* Server fault */
                  cache_status = cache_status_lookup;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_IO;
                      break;

                    case NFS_V3:
                      pres->res_create3.status = NFS3ERR_INVAL;
                      break;
                    }
                }

              nfs_SetFailedStatus(pcontext, pexport,
                                  preq->rq_vers,
                                  cache_status,
                                  &pres->res_dirop2.status,
                                  &pres->res_create3.status,
                                  NULL, NULL,
                                  parent_pentry,
                                  ppre_attr,
                                  &(pres->res_create3.CREATE3res_u.resfail.dir_wcc),
                                  NULL, NULL, NULL);

              rc = NFS_REQ_OK;
              goto out;
            } /* if( cache_status_lookup == CACHE_INODE_NOT_FOUND ) */
        }
    }

  /* Set the exit status */
  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_dirop2.status,
                      &pres->res_create3.status,
                      NULL, NULL,
                      parent_pentry,
                      ppre_attr,
                      &(pres->res_create3.CREATE3res_u.resfail.dir_wcc),
                      NULL, NULL, NULL);

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

  rc = NFS_REQ_OK;

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

  if (parent_pentry)
      cache_inode_put(parent_pentry);

  return (rc);

}                               /* nfs_Create */
示例#22
0
struct hash_table *
hashtable_init(struct hash_param *hparam)
{
	/* The hash table being constructed */
	struct hash_table *ht = NULL;
	/* The index for initializing each partition */
	uint32_t index = 0;
	/* Read-Write Lock attributes, to prevent write starvation under
	   GLIBC */
	pthread_rwlockattr_t rwlockattr;
	/* Hash partition */
	struct hash_partition *partition = NULL;
	/* The number of fully initialized partitions */
	uint32_t completed = 0;

	if (pthread_rwlockattr_init(&rwlockattr) != 0)
		return NULL;

	/* At some point factor this out into the OS directory.  it is
	   necessary to prevent writer starvation under GLIBC. */
#ifdef GLIBC
	if ((pthread_rwlockattr_setkind_np
	     (&rwlockattrs,
	      PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) != 0) {
		LogCrit(COMPONENT_HASHTABLE,
			"Unable to set writer-preference on lock attribute.");
		goto deconstruct;
	}
#endif				/* GLIBC */

	ht = gsh_calloc(1, sizeof(struct hash_table) +
			(sizeof(struct hash_partition) *
			 hparam->index_size));

	/* Fixup entry size */
	if (hparam->flags & HT_FLAG_CACHE) {
		if (!hparam->cache_entry_count)
			/* works fine with a good hash algo */
			hparam->cache_entry_count = 32767;
	}

	/* We need to save copy of the parameters in the table. */
	ht->parameter = *hparam;
	for (index = 0; index < hparam->index_size; ++index) {
		partition = (&ht->partitions[index]);
		RBT_HEAD_INIT(&(partition->rbt));

		if (pthread_rwlock_init(&partition->lock, &rwlockattr) != 0) {
			LogCrit(COMPONENT_HASHTABLE,
				"Unable to initialize lock in hash table.");
			goto deconstruct;
		}

		/* Allocate a cache if requested */
		if (hparam->flags & HT_FLAG_CACHE)
			partition->cache = gsh_calloc(1, cache_page_size(ht));

		completed++;
	}

	ht->node_pool = pool_basic_init(NULL, sizeof(rbt_node_t));
	ht->data_pool = pool_basic_init(NULL, sizeof(struct hash_data));

	pthread_rwlockattr_destroy(&rwlockattr);
	return ht;

 deconstruct:

	while (completed != 0) {
		if (hparam->flags & HT_FLAG_CACHE)
			gsh_free(ht->partitions[completed - 1].cache);

		PTHREAD_RWLOCK_destroy(&(ht->partitions[completed - 1].lock));
		completed--;
	}
	if (ht->node_pool)
		pool_destroy(ht->node_pool);
	if (ht->data_pool)
		pool_destroy(ht->data_pool);

	gsh_free(ht);
	return ht = NULL;
}
示例#23
0
int _9p_xattrcreate(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	int create;

	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u64 *size;
	u32 *flag;
	u16 *name_len;
	char *name_str;

	struct _9p_fid *pfid = NULL;

	fsal_status_t fsal_status = { .major = ERR_FSAL_NO_ERROR, .minor = 0 };
	char name[MAXNAMLEN+1];

	/* Get data */
	_9p_getptr(cursor, msgtag, u16);
	_9p_getptr(cursor, fid, u32);
	_9p_getstr(cursor, name_len, name_str);
	_9p_getptr(cursor, size, u64);
	_9p_getptr(cursor, flag, u32);

	LogDebug(COMPONENT_9P,
		 "TXATTRCREATE: tag=%u fid=%u name=%.*s size=%llu flag=%u",
		 (u32) *msgtag, *fid, *name_len, name_str,
		 (unsigned long long)*size, *flag);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply);

	if (*size > _9P_XATTR_MAX_SIZE)
		return _9p_rerror(req9p, msgtag, ENOSPC, plenout, preply);

	pfid = req9p->pconn->fids[*fid];

	/* Check that it is a valid fid */
	if (pfid == NULL || pfid->pentry == NULL) {
		LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid);
		return _9p_rerror(req9p, msgtag, EIO, plenout, preply);
	}

	/* set op_ctx, it will be useful if FSAL is later called */
	_9p_init_opctx(pfid, req9p);

	if ((op_ctx->export_perms->options &
				 EXPORT_OPTION_WRITE_ACCESS) == 0)
		return _9p_rerror(req9p, msgtag, EROFS, plenout, preply);

	if (*name_len >= sizeof(name)) {
		LogDebug(COMPONENT_9P, "request with name too long (%u)",
			 *name_len);
		return _9p_rerror(req9p, msgtag, ENAMETOOLONG, plenout,
				  preply);
	}
	snprintf(name, sizeof(name), "%.*s", *name_len, name_str);

	if (*size == 0LL) {
		/* Size == 0 : this is in fact a call to removexattr */
		LogDebug(COMPONENT_9P,
			 "TXATTRCREATE: tag=%u fid=%u : will remove xattr %s",
			 (u32) *msgtag, *fid, name);

		fsal_status =
		    pfid->pentry->obj_ops.remove_extattr_by_name(pfid->pentry,
								 name);

		if (FSAL_IS_ERROR(fsal_status))
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno(fsal_status), plenout,
					  preply);
	} else {
		/* Size != 0 , this is a creation/replacement of xattr */

		/* Create the xattr at the FSAL level and cache result */
		pfid->xattr = gsh_malloc(sizeof(*pfid->xattr) + *size);
		pfid->xattr->xattr_size = *size;
		pfid->xattr->xattr_offset = 0LL;
		pfid->xattr->xattr_write = _9P_XATTR_CAN_WRITE;


		strncpy(pfid->xattr->xattr_name, name, MAXNAMLEN);

		/* /!\  POSIX_ACL RELATED HOOK
		 * Setting a POSIX ACL (using setfacl for example) means
		 * settings a xattr named system.posix_acl_access BUT this
		 * attribute is to be used and should not be created
		 * (it exists already since acl feature is on) */
		if (!strncmp(name, "system.posix_acl_access", MAXNAMLEN))
			goto skip_create;

		/* try to create if flag doesn't have REPLACE bit */
		if ((*flag & XATTR_REPLACE) == 0)
			create = true;
		else
			create = false;

		fsal_status =
		    pfid->pentry->obj_ops.setextattr_value(pfid->pentry, name,
				pfid->xattr->xattr_content,
				*size, create);

		/* Try again with create = false if flag was set to 0
		 * and create failed because attribute already exists */
		if (FSAL_IS_ERROR(fsal_status)
		    && fsal_status.major == ERR_FSAL_EXIST && (*flag == 0)) {
			fsal_status =
			    pfid->pentry->obj_ops.setextattr_value(pfid->pentry,
					     name,
					     pfid->xattr->xattr_content,
					     *size, false);
		}

		if (FSAL_IS_ERROR(fsal_status)) {
			gsh_free(pfid->xattr);
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno(fsal_status), plenout,
					  preply);
		}
	}

skip_create:
	/* Build the reply */
	_9p_setinitptr(cursor, preply, _9P_RXATTRCREATE);
	_9p_setptr(cursor, msgtag, u16);

	_9p_setendptr(cursor, preply);
	_9p_checkbound(cursor, preply, plenout);

	LogDebug(COMPONENT_9P,
		 "RXATTRCREATE: tag=%u fid=%u name=%.*s size=%llu flag=%u",
		 (u32) *msgtag, *fid, *name_len, name_str,
		 (unsigned long long)*size, *flag);

	return 1;
}				/* _9p_xattrcreate */
/**
 *
 * nfs_Add_MountList_Entry: Adds a client to the mount list.
 *
 * Adds a client to the mount list.
 *
 * @param hostname [IN] the hostname for the client
 * @param dirpath [IN] the mounted path 
 *
 * @return 1 if successful, 0 otherwise
 *
 */
int nfs_Add_MountList_Entry(char *hostname, char *dirpath)
{
#ifndef _NO_MOUNT_LIST
  mountlist pnew_mnt_list_entry;
#endif

  /* Sanity check */
  if(hostname == NULL || dirpath == NULL)
    return 0;

#ifndef _NO_MOUNT_LIST

  /* Allocate the new entry */
  if((pnew_mnt_list_entry = gsh_calloc(1, sizeof(struct mountbody))) == NULL)
    return 0;

  if((pnew_mnt_list_entry->ml_hostname
      = gsh_calloc(1, MAXHOSTNAMELEN + 1)) == NULL)
    {
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }

  if((pnew_mnt_list_entry->ml_directory
      = gsh_calloc(1, MAXPATHLEN + 1)) == NULL)
    {
      gsh_free(pnew_mnt_list_entry->ml_hostname);
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }
  /* Copy the data */
  if (strmaxcpy(pnew_mnt_list_entry->ml_hostname, hostname,
		MAXHOSTNAMELEN) == -1)
    {
      gsh_free(pnew_mnt_list_entry->ml_directory);
      gsh_free(pnew_mnt_list_entry->ml_hostname);
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }
  if (strmaxcpy(pnew_mnt_list_entry->ml_directory, dirpath,
		MAXPATHLEN) == -1)
    {
      gsh_free(pnew_mnt_list_entry->ml_directory);
      gsh_free(pnew_mnt_list_entry->ml_hostname);
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }

  /* initialize next pointer */
  pnew_mnt_list_entry->ml_next = NULL;

  /* This should occur only for the first mount */
  if(MNT_List_head == NULL)
    {
      MNT_List_head = pnew_mnt_list_entry;
    }

  /* Append to the tail of the list */
  if(MNT_List_tail == NULL)
    MNT_List_tail = pnew_mnt_list_entry;
  else
    {
      MNT_List_tail->ml_next = pnew_mnt_list_entry;
      MNT_List_tail = pnew_mnt_list_entry;
    }

  if(isFullDebug(COMPONENT_NFSPROTO))
    nfs_Print_MountList();

#endif

  return 1;
}
示例#25
0
void *LUSTREFSAL_UP_Thread(void *Arg)
{
	const struct fsal_up_vector *event_func;
	struct lustre_filesystem *lustre_fs = Arg;
	struct lcap_cl_ctx *ctx = NULL;
	struct changelog_rec *rec;
	struct changelog_ext_jobid *jid;
	struct changelog_ext_rename *rnm;
	int flags = LCAP_CL_DIRECT|LCAP_CL_JOBID;
	int rc;
	long long last_idx = 0LL;
	long long managed_idx = 0LL;
	unsigned int req_count = 0;
	/* For wanting of a llapi call to get this information */
	/* @todo: use information form fsal_filesystem here */
	const char mdtname[] = "lustre-MDT0000";
	const char chlg_reader[] = "cl1";
	char my_jobid[JOBID_LEN];

	/* Compute my jobid */
	snprintf(my_jobid, JOBID_LEN, "%s.%d", exec_name, getuid());

	/* get the FSAL_UP vector */
	event_func = lustre_fs->up_ops;

	if (event_func == NULL) {
		LogFatal(COMPONENT_FSAL_UP,
			 "FSAL up vector does not exist. Can not continue.");
		gsh_free(Arg);
		return NULL;
	}
	LogFullDebug(COMPONENT_FSAL_UP,
		     "Initializing callback thread for %s MDT=%s my_jobid=%s",
		     lustre_fs->fsname, mdtname, my_jobid);


	/* Wait for 2 seconds, until the rest of the server starts */
	sleep(2);

	/* Main loop */
	last_idx = 0LL;
	managed_idx = 0LL;
	while (true) {
		/* open changelog reading channel in lcap */
		rc = lcap_changelog_start(&ctx, flags, mdtname, last_idx);
		if (rc) {
			LogFatal(COMPONENT_FSAL_UP,
				 "could not read changelog, "
				 "lcap_changelog_start:(%d,%s)",
				 rc, strerror(-rc));
			return NULL;
		}

		while ((rc = lcap_changelog_recv(ctx, &rec)) == 0) {

			if (rec->cr_flags & CLF_JOBID)
				jid = changelog_rec_jobid(rec);
			else
				break;
			if (rec->cr_index > managed_idx) {
				managed_idx = rec->cr_index;
				last_idx = rec->cr_index;
				req_count += 1;

				/* If jobid is an empty string, skip it */
				if (jid->cr_jid[0] == '\0') {
					rc = lcap_changelog_free(ctx, &rec);
					if (rc)
						LogFatal(COMPONENT_FSAL_UP,
							 "lcap_changelog_free: "
							 "%d,%s\n",
							 rc, strerror(-rc));
					continue;
				}
				/* Do not care for records generated
				 * by Ganesha's activity */
				if (!strcmp(jid->cr_jobid, my_jobid)) {
					rc = lcap_changelog_free(ctx, &rec);
					if (rc)
						LogFatal(COMPONENT_FSAL_UP,
							 "lcap_changelog_free: "
							 "%d,%s\n",
							 rc, strerror(-rc));
					continue;
				}

				rc = lustre_changelog_upcall(lustre_fs,
							     event_func,
							     rec);
				if (rc)
					LogMajor(COMPONENT_FSAL,
						   "error occured when dealing"
						   " with a changelog record");

				rc = lcap_changelog_free(ctx, &rec);
				if (rc)
					LogFatal(COMPONENT_FSAL_UP,
						 "lcap_changelog_free: %d,%s\n",
						 rc, strerror(-rc));
				}
			}

		if (req_count > FLUSH_REQ_COUNT) {
				rc = lcap_changelog_clear(ctx,
							  mdtname,
							  chlg_reader,
							  last_idx);
				if (rc)
					LogDebug(COMPONENT_FSAL_UP,
					 "lcap_changelog_clear() exited"
					 " with status %d, %s",
					 rc, strerror(-rc));
				else
					LogDebug(COMPONENT_FSAL_UP,
						 "changelog records cleared");
				req_count = 0;
		}

		/* clear si req_count > 0 et eof sans avoir vu de records */

		if (rc < 0)
			LogDebug(COMPONENT_FSAL_UP,
				 "lcap_changelog_recv() loop exited"
				 " with status %d, %s",
				 rc, strerror(-rc));

		/* Close changelog file */
		rc = lcap_changelog_fini(ctx);
		if (rc)
			LogFatal(COMPONENT_FSAL_UP,
				 "lcap_changelog_fini: %d,%s\n",
				 rc, strerror(-rc));
		last_idx = 0LL;

		/* Sleep for one second to avoid too aggressive polling
		 * on LUSTRE changelogs */
		sleep(1);
	}
	return NULL;
}
示例#26
0
static struct pt_fsal_obj_handle *alloc_handle(ptfsal_handle_t *fh,
					       struct attrlist *attributes,
					       const char *link_content,
					       ptfsal_handle_t *dir_fh,
					       const char *unopenable_name,
					       struct fsal_export *exp_hdl)
{
	struct pt_fsal_obj_handle *hdl;

	hdl = gsh_malloc(sizeof(struct pt_fsal_obj_handle)
			 + sizeof(ptfsal_handle_t));
	if (hdl == NULL)
		return NULL;
	memset(hdl, 0,
	       (sizeof(struct pt_fsal_obj_handle) + sizeof(ptfsal_handle_t)));
	hdl->handle = (ptfsal_handle_t *) &hdl[1];
	memcpy(hdl->handle, fh, sizeof(ptfsal_handle_t));
	hdl->obj_handle.type = attributes->type;
	hdl->obj_handle.fs = &pt_filesystem;
	if (hdl->obj_handle.type == REGULAR_FILE) {
		hdl->u.file.fd = -1;	/* no open on this yet */
		hdl->u.file.openflags = FSAL_O_CLOSED;
	} else if (hdl->obj_handle.type == SYMBOLIC_LINK
		   && link_content != NULL) {
		size_t len = strlen(link_content) + 1;

		hdl->u.symlink.link_content = gsh_malloc(len);
		if (hdl->u.symlink.link_content == NULL)
			goto spcerr;
		memcpy(hdl->u.symlink.link_content, link_content, len);
		hdl->u.symlink.link_size = len;
	} else if (pt_unopenable_type(hdl->obj_handle.type)
		   && dir_fh != NULL && unopenable_name != NULL) {
		hdl->u.unopenable.dir = gsh_malloc(sizeof(ptfsal_handle_t));
		if (hdl->u.unopenable.dir == NULL)
			goto spcerr;
		memcpy(hdl->u.unopenable.dir, dir_fh, sizeof(ptfsal_handle_t));
		hdl->u.unopenable.name =
		    gsh_malloc(strlen(unopenable_name) + 1);
		if (hdl->u.unopenable.name == NULL)
			goto spcerr;
		strcpy(hdl->u.unopenable.name, unopenable_name);
	}
	hdl->obj_handle.attributes.mask =
	    exp_hdl->ops->fs_supported_attrs(exp_hdl);
	memcpy(&hdl->obj_handle.attributes, attributes,
	       sizeof(struct attrlist));

	fsal_obj_handle_init(&hdl->obj_handle, exp_hdl, attributes->type);
	return hdl;

 spcerr:
	if (hdl->obj_handle.type == SYMBOLIC_LINK) {
		if (hdl->u.symlink.link_content != NULL)
			gsh_free(hdl->u.symlink.link_content);
	} else if (pt_unopenable_type(hdl->obj_handle.type)) {
		if (hdl->u.unopenable.name != NULL)
			gsh_free(hdl->u.unopenable.name);
		if (hdl->u.unopenable.dir != NULL)
			gsh_free(hdl->u.unopenable.dir);
	}
	gsh_free(hdl);		/* elvis has left the building */
	return NULL;
}
示例#27
0
void Release_nfs4_denied(LOCK4denied * denied)
{
  if(denied->owner.owner.owner_val != unknown_owner.so_owner_val &&
     denied->owner.owner.owner_val != NULL)
    gsh_free(denied->owner.owner.owner_val);
}
示例#28
0
int _9p_walk(struct _9p_request_data *req9p, void *worker_data,
	     u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	unsigned int i = 0;

	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u32 *newfid = NULL;
	u16 *nwname = NULL;
	u16 *wnames_len;
	char *wnames_str;
	uint64_t fileid;
	cache_inode_status_t cache_status;
	cache_entry_t *pentry = NULL;
	char name[MAXNAMLEN];

	u16 *nwqid;

	struct _9p_fid *pfid = NULL;
	struct _9p_fid *pnewfid = NULL;

	/* Now Get data */
	_9p_getptr(cursor, msgtag, u16);
	_9p_getptr(cursor, fid, u32);
	_9p_getptr(cursor, newfid, u32);
	_9p_getptr(cursor, nwname, u16);

	LogDebug(COMPONENT_9P, "TWALK: tag=%u fid=%u newfid=%u nwname=%u",
		 (u32) *msgtag, *fid, *newfid, *nwname);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout,
				  preply);

	if (*newfid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout,
				  preply);

	pfid = req9p->pconn->fids[*fid];
	/* Check that it is a valid fid */
	if (pfid == NULL || pfid->pentry == NULL) {
		LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid);
		return _9p_rerror(req9p, worker_data, msgtag, EIO, plenout,
				  preply);
	}
	op_ctx = &pfid->op_context;
	pnewfid = gsh_calloc(1, sizeof(struct _9p_fid));
	if (pnewfid == NULL)
		return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout,
				  preply);

	/* Is this a lookup or a fid cloning operation ? */
	if (*nwname == 0) {
		/* Cloning operation */
		memcpy((char *)pnewfid, (char *)pfid, sizeof(struct _9p_fid));

		/* Set the new fid id */
		pnewfid->fid = *newfid;

		/* This is not a TATTACH fid */
		pnewfid->from_attach = false;

		/* Increments refcount */
		(void) cache_inode_lru_ref(pnewfid->pentry, LRU_REQ_STALE_OK);
	} else {
		/* the walk is in fact a lookup */
		pentry = pfid->pentry;

		for (i = 0; i < *nwname; i++) {
			_9p_getstr(cursor, wnames_len, wnames_str);
			snprintf(name, MAXNAMLEN, "%.*s", *wnames_len,
				 wnames_str);

			LogDebug(COMPONENT_9P,
				 "TWALK (lookup): tag=%u fid=%u newfid=%u (component %u/%u :%s)",
				 (u32) *msgtag, *fid, *newfid, i + 1, *nwname,
				 name);

			if (pnewfid->pentry == pentry)
				pnewfid->pentry = NULL;

			/* refcount +1 */
			cache_status =
			    cache_inode_lookup(pentry, name, &pnewfid->pentry);

			if (pnewfid->pentry == NULL) {
				gsh_free(pnewfid);
				return _9p_rerror(req9p, worker_data, msgtag,
						  _9p_tools_errno(cache_status),
						  plenout, preply);
			}

			if (pentry != pfid->pentry)
				cache_inode_put(pentry);

			pentry = pnewfid->pentry;
		}

		pnewfid->fid = *newfid;
		pnewfid->op_context = pfid->op_context;
		pnewfid->ppentry = pfid->pentry;
		strncpy(pnewfid->name, name, MAXNAMLEN-1);

		/* gdata ref is not hold : the pfid, which use same gdata */
		/*  will be clunked after pnewfid */
		/* This clunk release the gdata */
		pnewfid->gdata = pfid->gdata;

		/* This is not a TATTACH fid */
		pnewfid->from_attach = false;

		cache_status = cache_inode_fileid(pnewfid->pentry, &fileid);
		if (cache_status != CACHE_INODE_SUCCESS) {
			gsh_free(pnewfid);
			return _9p_rerror(req9p, worker_data, msgtag,
					  _9p_tools_errno(cache_status),
					  plenout, preply);
		}

		/* Build the qid */
		/* No cache, we want the client to stay synchronous
		 * with the server */
		pnewfid->qid.version = 0;
		pnewfid->qid.path = fileid;

		pnewfid->specdata.xattr.xattr_id = 0;
		pnewfid->specdata.xattr.xattr_content = NULL;

		switch (pnewfid->pentry->type) {
		case REGULAR_FILE:
		case CHARACTER_FILE:
		case BLOCK_FILE:
		case SOCKET_FILE:
		case FIFO_FILE:
			pnewfid->qid.type = _9P_QTFILE;
			break;

		case SYMBOLIC_LINK:
			pnewfid->qid.type = _9P_QTSYMLINK;
			break;

		case DIRECTORY:
			pnewfid->qid.type = _9P_QTDIR;
			break;

		default:
			LogMajor(COMPONENT_9P,
				 "implementation error, you should not see this message !!!!!!");
			gsh_free(pnewfid);
			return _9p_rerror(req9p, worker_data, msgtag, EINVAL,
					  plenout, preply);
			break;
		}

	}

	/* keep info on new fid */
	req9p->pconn->fids[*newfid] = pnewfid;

	/* As much qid as requested fid */
	nwqid = nwname;

	/* Hold refcount on gdata */
	uid2grp_hold_group_data(pnewfid->gdata);

	/* Build the reply */
	_9p_setinitptr(cursor, preply, _9P_RWALK);
	_9p_setptr(cursor, msgtag, u16);

	_9p_setptr(cursor, nwqid, u16);
	for (i = 0; i < *nwqid; i++) {
		/** @todo: should be different qids
		 * for each directory walked through */
		_9p_setqid(cursor, pnewfid->qid);
	}

	_9p_setendptr(cursor, preply);
	_9p_checkbound(cursor, preply, plenout);

	LogDebug(COMPONENT_9P,
		 "RWALK: tag=%u fid=%u newfid=%u nwqid=%u fileid=%llu pentry=%p refcount=%i",
		 (u32) *msgtag, *fid, *newfid, *nwqid,
		 (unsigned long long)pnewfid->qid.path, pnewfid->pentry,
		 pnewfid->pentry->lru.refcnt);

	return 1;
}
示例#29
0
static int xattr_format_value(caddr_t buffer, size_t *datalen, size_t maxlen)
{
	size_t size_in = *datalen;
	size_t len = strnlen((char *)buffer, size_in);
	int i;

	if (len == size_in - 1 || len == size_in) {
		int ascii = true;
		char *str = buffer;
		int i;

		for (i = 0; i < len; i++) {
			if (!isprint(str[i]) && !isspace(str[i])) {
				ascii = false;
				break;
			}
		}

		if (ascii) {
			*datalen = size_in;
			/* add additional '\n', if missing */
			if ((size_in + 1 < maxlen) && (str[len - 1] != '\n')) {
				str[len] = '\n';
				str[len + 1] = '\0';
				(*datalen) += 2;
			}
			return ERR_FSAL_NO_ERROR;
		}
	}

	/* byte, word, 32 or 64 bits */
	if (size_in == 1) {
		unsigned char val = *((unsigned char *)buffer);
		*datalen = 1 + snprintf((char *)buffer, maxlen, "%hhu\n", val);
		return ERR_FSAL_NO_ERROR;
	} else if (size_in == 2) {
		unsigned short val = *((unsigned short *)buffer);
		*datalen = 1 + snprintf((char *)buffer, maxlen, "%hu\n", val);
		return ERR_FSAL_NO_ERROR;
	} else if (size_in == 4) {
		unsigned int val = *((unsigned int *)buffer);
		*datalen = 1 + snprintf((char *)buffer, maxlen, "%u\n", val);
		return ERR_FSAL_NO_ERROR;
	} else if (size_in == 8) {
		unsigned long long val = *((unsigned long long *)buffer);
		*datalen = 1 + snprintf((char *)buffer, maxlen, "%llu\n", val);
		return ERR_FSAL_NO_ERROR;
	} else {
		/* 2 bytes per initial byte +'0x' +\n +\0 */
		char *curr_out;
		char *tmp_buf = (char *)gsh_malloc(3 * size_in + 4);
		if (!tmp_buf)
			return ERR_FSAL_NOMEM;
		curr_out = tmp_buf;
		curr_out += sprintf(curr_out, "0x");
		/* hexa representation */
		for (i = 0; i < size_in; i++) {
			unsigned char *p8 = (unsigned char *)(buffer + i);
			if ((i % 4 == 3) && (i != size_in - 1))
				curr_out += sprintf(curr_out, "%02hhX.", *p8);
			else
				curr_out += sprintf(curr_out, "%02hhX", *p8);
		}
		*curr_out = '\n';
		curr_out++;
		*curr_out = '\0';
		curr_out++;
		strncpy((char *)buffer, tmp_buf, maxlen);
		*datalen = strlen(tmp_buf) + 1;
		if (*datalen > maxlen)
			*datalen = maxlen;
		gsh_free(tmp_buf);
		return ERR_FSAL_NO_ERROR;
	}
}
int nfs4_op_getdevicelist(struct nfs_argop4 *op, compound_data_t *data,
			  struct nfs_resop4 *resp)
{
	/* Convenience alias for arguments */
	GETDEVICELIST4args * const arg_GETDEVICELIST4 =
	    &op->nfs_argop4_u.opgetdevicelist;
	/* Convenience alias for response */
	GETDEVICELIST4res * const res_GETDEVICELIST4 =
	    &resp->nfs_resop4_u.opgetdevicelist;
	/* NFS4 return code */
	nfsstat4 nfs_status = 0;
	/* Input/output and output parameters of FSAL function */
	struct fsal_getdevicelist_res res;
	/* Structure for callback */
	struct cb_data cb_opaque;

	resp->resop = NFS4_OP_GETDEVICELIST;

	if (data->minorversion == 0)
		return res_GETDEVICELIST4->gdlr_status = NFS4ERR_INVAL;

	nfs_status = nfs4_sanity_check_FH(data, NO_FILE_TYPE, false);

	if (nfs_status != NFS4_OK)
		goto out;

	memset(&res, 0, sizeof(struct fsal_getdevicelist_res));

	res.cookie = arg_GETDEVICELIST4->gdla_cookie;
	memcpy(&res.cookieverf,
	       arg_GETDEVICELIST4->gdla_cookieverf,
	       NFS4_VERIFIER_SIZE);

	cb_opaque.count = 0;
	cb_opaque.max = 32;
	cb_opaque.swexport = nfs_htonl64(op_ctx->export->export_id);

	res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.
	     gdlr_deviceid_list.gdlr_deviceid_list_val =
	     gsh_malloc(cb_opaque.max * sizeof(deviceid4));

	if (res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.
	     gdlr_deviceid_list.gdlr_deviceid_list_val == NULL) {
		nfs_status = NFS4ERR_SERVERFAULT;
		goto out;
	}

	cb_opaque.buffer =
	    res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.
	    gdlr_deviceid_list.gdlr_deviceid_list_val;

	nfs_status = op_ctx->fsal_export->ops->getdevicelist(
					op_ctx->fsal_export,
					arg_GETDEVICELIST4->gdla_layout_type,
					&cb_opaque, cb,
					&res);

	if (nfs_status != NFS4_OK) {
		gsh_free(cb_opaque.buffer);
		goto out;
	}

	res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.gdlr_cookie =
	    res.cookie;

	memcpy(res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.
	       gdlr_cookieverf, &res.cookieverf,
	       NFS4_VERIFIER_SIZE);

	res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.gdlr_deviceid_list.
	    gdlr_deviceid_list_len = cb_opaque.count;

	res_GETDEVICELIST4->GETDEVICELIST4res_u.gdlr_resok4.gdlr_eof = res.eof;

	nfs_status = NFS4_OK;

 out:
	res_GETDEVICELIST4->gdlr_status = nfs_status;

	return res_GETDEVICELIST4->gdlr_status;
}