bool uid2grp( uid_t uid, struct group_data ** pgdata ) 
{
  bool success;
   
  struct gsh_buffdesc name;
  struct gsh_buffdesc * pname = &name ;

  pthread_rwlock_rdlock(&uid2grp_user_lock);

  success = uid2grp_lookup_by_uid( uid, &pname, pgdata );

  pthread_rwlock_unlock(&uid2grp_user_lock);

  if (success)
    return true;
  else
    {
      if( pwentuid2grp( uid, &name, *pgdata ) )
       {
         pthread_rwlock_wrlock(&uid2grp_user_lock);

         success = uid2grp_add_user(&name, uid, *pgdata ) ;

         pthread_rwlock_unlock(&uid2grp_user_lock);

         if (!success)
	   LogMajor(COMPONENT_IDMAPPER, "uid2grp %u", uid ) ;
         return true;
       }
      else
	return false ;
    }
}
Beispiel #2
0
bool name2grp(const struct gsh_buffdesc *name, struct group_data **pgdata)
{
	bool success;
	uid_t uid = -1;

	pthread_rwlock_rdlock(&uid2grp_user_lock);

	success = uid2grp_lookup_by_uname(name, &uid, pgdata);

	pthread_rwlock_unlock(&uid2grp_user_lock);

	if (success)
		return true;
	else {
		/* Something we can mutate and count on as terminated */
		char *namebuff = alloca(name->len + 1);

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

		if (pwentname2grp(namebuff, &uid, *pgdata)) {
			pthread_rwlock_wrlock(&uid2grp_user_lock);

			success = uid2grp_add_user(name, uid, *pgdata);

			pthread_rwlock_unlock(&uid2grp_user_lock);

			if (!success)
				LogMajor(COMPONENT_IDMAPPER, "name2grp %s",
					 namebuff);
			return true;
		} else
			return false;
	}
}
/*
 *  Process NFSv4 ACLs passed in setattr call
 */
fsal_status_t glusterfs_process_acl(struct glfs *fs,
				    struct glfs_object *object,
				    struct attrlist *attrs,
				    glusterfs_fsal_xstat_t *buffxstat)
{
	if (attrs->acl) {
		LogDebug(COMPONENT_FSAL, "setattr acl = %p",
			 attrs->acl);

		/* Convert FSAL ACL to POSIX ACL */
		buffxstat->e_acl = fsal_acl_2_posix_acl(attrs->acl,
						ACL_TYPE_ACCESS);
		if (!buffxstat->e_acl) {
			LogMajor(COMPONENT_FSAL,
				 "failed to set access type posix acl");
			return fsalstat(ERR_FSAL_FAULT, 0);
		}
		/* For directories consider inherited acl too */
		if (buffxstat->is_dir) {
			buffxstat->i_acl = fsal_acl_2_posix_acl(attrs->acl,
							ACL_TYPE_DEFAULT);
			if (!buffxstat->i_acl)
				LogDebug(COMPONENT_FSAL,
				"inherited acl is not defined for directory");
		}

	} else {
		LogCrit(COMPONENT_FSAL, "setattr acl is NULL");
		return fsalstat(ERR_FSAL_FAULT, 0);
	}
	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #4
0
/**
 * @brief Read from a data-server handle.
 *
 * NFSv4.1 data server handles are disjount from normal
 * filehandles (in Ganesha, there is a ds_flag in the filehandle_v4_t
 * structure) and do not get loaded into cache_inode or processed the
 * normal way.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  requested_length Length of read requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[out] supplied_length  Length of data read
 * @param[out] eof              True on end of file
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4 ds_read(struct fsal_ds_handle *const ds_pub,
			struct req_op_context *const req_ctx,
			const stateid4 *stateid, const offset4 offset,
			const count4 requested_length, void *const buffer,
			count4 * const supplied_length,
			bool * const end_of_file)
{
	/* The private DS handle */
	struct glfs_ds_handle *ds =
		container_of(ds_pub, struct glfs_ds_handle, ds);
	int    rc = 0;
	struct glusterfs_export *glfs_export =
	container_of(ds_pub->pds->mds_fsal_export,
		     struct glusterfs_export, export);

	if (ds->glhandle == NULL)
		LogDebug(COMPONENT_PNFS, "ds_read glhandle NULL");

	rc = glfs_h_anonymous_read(glfs_export->gl_fs->fs, ds->glhandle,
				   buffer, requested_length, offset);
	if (rc < 0) {
		LogMajor(COMPONENT_PNFS, "Read failed on DS");
		return posix2nfs4_error(-rc);
	}

	*supplied_length = rc;
	if (rc == 0 || rc < requested_length)
		*end_of_file = true;


	return NFS4_OK;
}
Beispiel #5
0
/**
 * FSAL_DigestHandle :
 *  Convert an posixfsal_handle_t to a buffer
 *  to be included into NFS handles,
 *  or another digest.
 *
 * \param output_type (input):
 *        Indicates the type of digest to do.
 * \param in_fsal_handle (input):
 *        The handle to be converted to digest.
 * \param fh_desc (input/output):
 *        The buffer where the digest is to be stored.
 *
 * \return The major code is ERR_FSAL_NO_ERROR is no error occured.
 *         Else, it is a non null value.
 */
fsal_status_t POSIXFSAL_DigestHandle(fsal_export_context_t * expcontext, /* IN */
                                     fsal_digesttype_t output_type,     /* IN */
                                     fsal_handle_t * in_fsal_handle,     /* IN */
                                     struct fsal_handle_desc *fh_desc     /* IN/OUT */
    )
{
  posixfsal_export_context_t * p_expcontext
    = (posixfsal_export_context_t *) expcontext;
  posixfsal_handle_t * p_in_fsal_handle = (posixfsal_handle_t *) in_fsal_handle;
  size_t fh_size;
  caddr_t fh_data;

  /* sanity checks */
  if(!p_in_fsal_handle || !fh_desc || !fh_desc->start || !p_expcontext)
    ReturnCode(ERR_FSAL_FAULT, 0);

  switch (output_type)
    {
    /* NFS handle digest */
    case FSAL_DIGEST_NFSV2:
    case FSAL_DIGEST_NFSV3:
    case FSAL_DIGEST_NFSV4:
      fh_size = sizeof(p_in_fsal_handle->data.id) + sizeof(p_in_fsal_handle->data.ts);
      fh_data = (caddr_t) p_in_fsal_handle;
      break;

    /* FileId digest */
    case FSAL_DIGEST_FILEID2:
    case FSAL_DIGEST_FILEID3:
    case FSAL_DIGEST_FILEID4:
      /* XXX: does fh_desc need to be padded to FSAL_DIGEST_SIZE_FILEID{2,3,4} ?
       *      or is setting fh_size = sizeof(ino_t) sufficient? */
      fh_size = sizeof(p_in_fsal_handle->data.info.inode);
      fh_data = (caddr_t) &p_in_fsal_handle->data.info.inode;
      break;

    /* Nodetype digest. */
    case FSAL_DIGEST_NODETYPE:
      /* XXX: should fh_desc be padded to FSAL_DIGEST_SIZE_NODETYPE ? */
      fh_size = sizeof(p_in_fsal_handle->data.info.ftype);
      fh_data = (caddr_t) &p_in_fsal_handle->data.info.ftype;
      break;

    default:
      ReturnCode(ERR_FSAL_SERVERFAULT, 0);
    }

  if(fh_desc->len < fh_size)
    {
      LogMajor( COMPONENT_FSAL, "POSIX DigestHandle: too small for handle.  need %lu, have %lu",
                fh_size, fh_desc->len);
      ReturnCode(ERR_FSAL_TOOSMALL, 0);
    }

  memcpy(fh_desc->start, fh_data, fh_size);
  fh_desc->len = fh_size;

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #6
0
/**
 * @brief Initialize asynchronous request system
 *
 * @return State status.
 */
state_status_t state_async_init(void)
{
	int rc = 0;
	struct fridgethr_params frp;

	memset(&frp, 0, sizeof(struct fridgethr_params));
	frp.thr_max = 1;
	frp.deferment = fridgethr_defer_queue;

	rc = fridgethr_init(&state_async_fridge, "State_Async", &frp);

	if (rc != 0) {
		LogMajor(COMPONENT_STATE,
			 "Unable to initialize state async thread fridge: %d",
			 rc);
		return STATE_INIT_ENTRY_FAILED;
	}

	memset(&frp, 0, sizeof(struct fridgethr_params));
	frp.thr_max = 1;
	frp.thr_min = 1;
	frp.thread_delay = nfs_param.core_param.blocked_lock_poller_interval;
	frp.flavor = fridgethr_flavor_looper;

	rc = fridgethr_init(&state_poll_fridge, "state_poll", &frp);

	if (rc != 0) {
		LogMajor(COMPONENT_STATE,
			 "Unable to initialize state blocked lock polling thread fridge: %d",
			 rc);
		return STATE_INIT_ENTRY_FAILED;
	}

	rc = fridgethr_submit(state_poll_fridge, blocked_lock_polling, NULL);

	if (rc != 0) {
		LogMajor(COMPONENT_STATE,
			 "Unable to start blocked lock polling thread, error code %d.",
			 rc);
		return STATE_INIT_ENTRY_FAILED;
	}

	return STATE_SUCCESS;
}
Beispiel #7
0
void _9p_tcp_process_request(struct _9p_request_data *req9p)
{
	u32 outdatalen = 0;
	int rc = 0;
	char replydata[_9P_MSG_SIZE];

	rc = _9p_process_buffer(req9p, replydata, &outdatalen);
	if (rc != 1) {
		LogMajor(COMPONENT_9P,
			 "Could not process 9P buffer on socket #%lu",
			 req9p->pconn->trans_data.sockfd);
	} else {
		if (tcp_conn_send(req9p->pconn, replydata, outdatalen, 0) !=
		    outdatalen)
			LogMajor(COMPONENT_9P,
				 "Could not send 9P/TCP reply correclty on socket #%lu",
				 req9p->pconn->trans_data.sockfd);
	}
	_9p_DiscardFlushHook(req9p);
}				/* _9p_process_request */
Beispiel #8
0
int FSAL_LoadLibrary(char *path)
{
  void *handle;
  char *error;

  LogEvent(COMPONENT_FSAL, "Load shared FSAL : %s", path);

  if((handle = dlopen(path, RTLD_LAZY)) == NULL)
    {
      LogMajor(COMPONENT_FSAL,
               "FSAL_LoadLibrary: could not load fsal: %s",
               dlerror());
      return 0;
    }

  /* Clear any existing error : dlerror will be used to check if dlsym succeeded or not */
  dlerror();

  /* Map FSAL_GetFunctions */
  *(void **)(&getfunctions) = dlsym(handle, "FSAL_GetFunctions");
  if((error = dlerror()) != NULL)
    {
      LogMajor(COMPONENT_FSAL,
               "FSAL_LoadLibrary: Could not map symbol FSAL_GetFunctions:%s",
               error);
      return 0;
    }
  /* Map FSAL_GetConsts */
  *(void **)(&getconsts) = dlsym(handle, "FSAL_GetConsts");
  if((error = dlerror()) != NULL)
    {
      LogMajor(COMPONENT_FSAL,
               "FSAL_LoadLibrary: Could not map symbol FSAL_GetConsts:%s",
               error);
      return 0;
    }

  return 1;
}                               /* FSAL_LoadLibrary */
Beispiel #9
0
/*
 * The data server address will be send from here
 *
 * The information about the first server present
 * in the PATH_INFO_KEY will be returned, since
 * entire file is consistent over the servers
 * (Striped volumes are not considered right now)
 *
 * On success, returns zero with ip address of
 * the server will be send
 */
int
glfs_get_ds_addr(struct glfs *fs, struct glfs_object *object, uint32_t *ds_addr)
{
	int             ret                  = 0;
	char            pathinfo[1024]       = {0, };
	char            hostname[1024]       = {0, };
	struct addrinfo hints, *res;
	struct in_addr  addr                 = {0, };
	const char      *pathinfokey         = "trusted.glusterfs.pathinfo";

	ret = glfs_h_getxattrs(fs, object, pathinfokey, pathinfo, 1024);

	LogDebug(COMPONENT_PNFS, "pathinfo %s", pathinfo);

	ret = select_ds(object, pathinfo, hostname, sizeof(hostname));
	if (ret) {
		LogMajor(COMPONENT_PNFS, "No DS found");
		goto out;
	}

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_family = AF_INET;
	ret = getaddrinfo(hostname, NULL, &hints, &res);
	if (ret != 0) {
		LogMajor(COMPONENT_PNFS, "error %d\n", ret);
		goto out;
	}

	addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;

	LogDebug(COMPONENT_PNFS, "ip address : %s", inet_ntoa(addr));

	freeaddrinfo(res);
out:

	*ds_addr = addr.s_addr;
	return ret;
}
Beispiel #10
0
/**
 *
 * fsal_internal_ClientReconnect: Redo a previously lost connection to the server.
 *
 * edo a previously lost connection to the server.
 *
 * @param p_thr_context [INOUT]  pointer to the FSAL thread context.
 *
 * @return 0 if successful, -1 if failed
 *
 */
int fsal_internal_ClientReconnect(proxyfsal_op_context_t * p_thr_context)
{
  int rc;
  struct timeval timeout = TIMEOUTRPC;
  struct sockaddr_in addr_rpc;
  fsal_status_t fsal_status;


  memset(&addr_rpc, 0, sizeof(addr_rpc));
  addr_rpc.sin_port = p_thr_context->srv_port;
  addr_rpc.sin_family = AF_INET;
  addr_rpc.sin_addr.s_addr = p_thr_context->srv_addr;
  int priv_port = 0 ;

  LogEvent( COMPONENT_FSAL, "Remote server lost, trying to reconnect to remote server" ) ;

  /* First of all, close the formerly opened socket that is now useless */
  if( close( p_thr_context->socket ) == -1 )
    LogMajor( COMPONENT_FSAL,
              "FSAL RECONNECT : got POSIX error %u while closing socket in fsal_internal_ClientReconnect", errno ) ;
  
  // clnt_destroy(p_thr_context->rpc_client);
  // clnt_destroy makes the server segfaults if no server exists on the other side

  if(!strcmp(p_thr_context->srv_proto, "udp"))
    {
      if( ( p_thr_context->socket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) < 0)
        return -1;

      if((p_thr_context->rpc_client = clntudp_bufcreate(&addr_rpc,
                                                        p_thr_context->srv_prognum,
                                                        FSAL_PROXY_NFS_V4,
                                                        (struct timeval)
                                                        {
                                                        25, 0},
                                                        &p_thr_context->socket,
                                                        p_thr_context->srv_sendsize,
                                                        p_thr_context->srv_recvsize)) == NULL )
        {

          LogCrit(COMPONENT_FSAL,
               "FSAL RECONNECT : Cannot contact server addr=%u.%u.%u.%u port=%u prognum=%u using NFSv4 protocol",
               (ntohl(p_thr_context->srv_addr) & 0xFF000000) >> 24,
               (ntohl(p_thr_context->srv_addr) & 0x00FF0000) >> 16,
               (ntohl(p_thr_context->srv_addr) & 0x0000FF00) >> 8,
               (ntohl(p_thr_context->srv_addr) & 0x000000FF),
               ntohs(p_thr_context->srv_port), p_thr_context->srv_prognum);

          return -1;
        }
    }
Beispiel #11
0
/**
 * FSAL_getattrs.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_ATTRNOTSUPP  (attribute not supported)
 *        - ERR_FSAL_BADHANDLE    (illegal handle)
 *        - ERR_FSAL_FAULT        (null pointer parameter)
 *        - ERR_FSAL_IO           (corrupted FS)
 *        - ERR_FSAL_NOT_INIT     (ghostfs not initialize)
 *        - ERR_FSAL_SERVERFAULT  (unexpected error)
 */
fsal_status_t FSAL_getattrs(fsal_handle_t * filehandle, /* IN */
                            fsal_op_context_t * p_context,      /* IN */
                            fsal_attrib_list_t * object_attributes      /* IN/OUT */
    )
{

  int rc;
  GHOSTFS_Attrs_t ghost_attrs;
  fsal_attrib_mask_t supp_attr, unsupp_attr;

  /* For logging */
  SetFuncID(INDEX_FSAL_getattrs);

  /* sanity checks.
   * note : object_attributes is mandatory in FSAL_getattrs.
   */
  if(!filehandle || !p_context || !object_attributes)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);

  rc = GHOSTFS_GetAttrs((GHOSTFS_handle_t) (*filehandle), &ghost_attrs);

  if(rc)
    Return(ghost2fsal_error(rc), rc, INDEX_FSAL_getattrs);

  /* Credentials are not tested because
   * we consider that if the user got an handle to the object,
   * he has the right for retrieving its attributes.
   */

  /* supported attrs for GHOSTFS */
  supp_attr = GHOSTFS_SUPPORTED_ATTRIBUTES;

  /* tests whether we can supply all asked attributes */
  unsupp_attr = (object_attributes->asked_attributes) & (~supp_attr);
  if(unsupp_attr)
    {
      LogMajor(COMPONENT_FSAL,
               "Unsupported attributes: %#llX removing it from asked attributes ",
               unsupp_attr);
      object_attributes->asked_attributes =
          object_attributes->asked_attributes & (~unsupp_attr);
    }

  /* Fills the output struct */
  ghost2fsal_attrs(object_attributes, &ghost_attrs);

  /* everything has been copied ! */

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);

}
Beispiel #12
0
/**
 * @brief Schedule a lock notification
 *
 * @param[in] block Lock to schedule
 *
 * @return State status.
 */
state_status_t state_block_schedule(state_block_data_t *block)
{
	int rc;

	LogFullDebug(COMPONENT_STATE, "Schedule notification %p", block);

	rc = fridgethr_submit(state_async_fridge, state_blocked_lock_caller,
			      block);

	if (rc != 0)
		LogMajor(COMPONENT_STATE, "Unable to schedule request: %d", rc);

	return rc == 0 ? STATE_SUCCESS : STATE_SIGNAL_ERROR;
}
void TestMajor(int expect, char *buff, log_components_t component, char *string)
{
  char compare[2048];
  sprintf(compare, "%s: MAJOR ERROR: %s", LogComponents[component].comp_str, string);
  buff[0] = '\0';
  LogMajor(component, "%s", string);
  if (expect && strcmp(compare, buff) != 0 || !expect && buff[0] != '\0')
    {
      LogTest("FAILURE: %s produced \"%s\" expected \"%s\"", string, buff, compare);
      exit(1);
    }
  if (expect)
    LogTest("SUCCESS: %s produced \"%s\"", string, buff);
  else
    LogTest("SUCCESS: %s didn't produce anything", string);
}
Beispiel #14
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;
}
Beispiel #15
0
/**
 * @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);
}
Beispiel #16
0
int SetComponentLogFile(log_components_t component, const char *name)
{
  int newtype, changed;

  if (strcmp(name, "SYSLOG") == 0)
    newtype = SYSLOG;
  else if (strcmp(name, "STDERR") == 0)
    newtype = STDERRLOG;
  else if (strcmp(name, "STDOUT") == 0)
    newtype = STDOUTLOG;
  else if (strcmp(name, "TEST") == 0)
    newtype = TESTLOG;
  else
    newtype = FILELOG;

  if (newtype == FILELOG)
    {
      if (!isValidLogPath(name))
        {
          LogMajor(COMPONENT_LOG, "Could not set default logging to %s", name);
          errno = EINVAL;
          return -1;
        }
      }

  changed = (newtype != LogComponents[component].comp_log_type) ||
            (newtype == FILELOG && strcmp(name, LogComponents[component].comp_log_file) != 0);

  if (component != COMPONENT_LOG && changed)
    LogChanges("Changing log destination for %s from %s to %s",
               LogComponents[component].comp_name,
               LogComponents[component].comp_log_file,
               name);

  LogComponents[component].comp_log_type = newtype;
  strncpy(LogComponents[component].comp_log_file, name, MAXPATHLEN);

  if (component == COMPONENT_LOG && changed)
    LogChanges("Changing log destination for %s from %s to %s",
               LogComponents[component].comp_name,
               LogComponents[component].comp_log_file,
               name);

  return 0;
}                               /* SetComponentLogFile */
Beispiel #17
0
static fsal_status_t handle_digest(const struct fsal_obj_handle *obj_hdl,
				   fsal_digesttype_t output_type,
				   struct gsh_buffdesc *fh_desc)
{
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
	size_t fh_size;
	struct glusterfs_handle *objhandle;
#ifdef GLTIMING
	struct timespec s_time, e_time;

	now(&s_time);
#endif

	if (!fh_desc)
		return fsalstat(ERR_FSAL_FAULT, 0);

	objhandle = container_of(obj_hdl, struct glusterfs_handle, handle);

	switch (output_type) {
	case FSAL_DIGEST_NFSV2:
	case FSAL_DIGEST_NFSV3:
	case FSAL_DIGEST_NFSV4:
		fh_size = GLAPI_HANDLE_LENGTH;
		if (fh_desc->len < fh_size) {
			LogMajor(COMPONENT_FSAL,
				 "Space too small for handle.  need %lu, have %lu",
				 fh_size, fh_desc->len);
			status.major = ERR_FSAL_TOOSMALL;
			goto out;
		}
		memcpy(fh_desc->addr, objhandle->globjhdl, fh_size);
		break;
	default:
		status.major = ERR_FSAL_SERVERFAULT;
		goto out;
	}

	fh_desc->len = fh_size;
 out:
#ifdef GLTIMING
	now(&e_time);
	latency_update(&s_time, &e_time, lat_handle_digest);
#endif
	return status;
}
Beispiel #18
0
/**
 * @brief Commit a byte range to a DS handle.
 *
 * NFSv4.1 data server filehandles are disjount from normal
 * filehandles (in Ganesha, there is a ds_flag in the filehandle_v4_t
 * structure) and do not get loaded into cache_inode or processed the
 * normal way.
 *
 * @param[in]  ds_pub    FSAL DS handle
 * @param[in]  req_ctx   Credentials
 * @param[in]  offset    Start of commit window
 * @param[in]  count     Length of commit window
 * @param[out] writeverf Write verifier
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4 ds_commit(struct fsal_ds_handle *const ds_pub,
			  struct req_op_context *const req_ctx,
			  const offset4 offset, const count4 count,
			  verifier4 * const writeverf)
{
	memset(writeverf, 0, NFS4_VERIFIER_SIZE);
	struct glfs_ds_handle *ds =
		container_of(ds_pub, struct glfs_ds_handle, ds);
	int rc = 0;
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };

	if (ds->stability_got == FILE_SYNC4) {
		struct glusterfs_export *glfs_export =
			container_of(ds_pub->pds->mds_fsal_export,
				     struct glusterfs_export, export);
		struct glfs_fd *glfd = NULL;

		SET_GLUSTER_CREDS(glfs_export, &op_ctx->creds->caller_uid,
				  &op_ctx->creds->caller_gid,
				  op_ctx->creds->caller_glen,
				  op_ctx->creds->caller_garray);

		glfd = glfs_h_open(glfs_export->gl_fs->fs, ds->glhandle,
				   O_RDWR);
		if (glfd == NULL) {
			LogDebug(COMPONENT_PNFS, "glfd in ds_handle is NULL");
			SET_GLUSTER_CREDS(glfs_export, NULL, NULL, 0, NULL);
			return NFS4ERR_SERVERFAULT;
		}

		rc = glfs_fsync(glfd);
		if (rc != 0)
			LogMajor(COMPONENT_PNFS, "ds_commit() failed  %d", -rc);
		rc = glfs_close(glfd);
		if (rc != 0)
			LogDebug(COMPONENT_PNFS, "status after close %d", -rc);

		SET_GLUSTER_CREDS(glfs_export, NULL, NULL, 0, NULL);
	}

	if ((rc != 0) || (status.major != ERR_FSAL_NO_ERROR))
		return NFS4ERR_INVAL;

	return NFS4_OK;
}
Beispiel #19
0
/**
 *
 * @brief Write to a data-server handle.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  write_length     Length of write requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[in]  stability wanted Stability of write
 * @param[out] written_length   Length of data written
 * @param[out] writeverf        Write verifier
 * @param[out] stability_got    Stability used for write (must be as
 *                              or more stable than request)
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4 ds_write(struct fsal_ds_handle *const ds_pub,
			 struct req_op_context *const req_ctx,
			 const stateid4 *stateid, const offset4 offset,
			 const count4 write_length, const void *buffer,
			 const stable_how4 stability_wanted,
			 count4 * const written_length,
			 verifier4 * const writeverf,
			 stable_how4 * const stability_got)
{
	struct glfs_ds_handle *ds =
		container_of(ds_pub, struct glfs_ds_handle, ds);
	struct glusterfs_export *glfs_export =
	container_of(ds_pub->pds->mds_fsal_export,
		     struct glusterfs_export, export);
	int    rc = 0;

	memset(writeverf, 0, NFS4_VERIFIER_SIZE);

	if (ds->glhandle == NULL)
		LogDebug(COMPONENT_PNFS, "ds_write glhandle NULL");

	rc = glfs_h_anonymous_write(glfs_export->gl_fs->fs, ds->glhandle,
				    buffer, write_length, offset);
	if (rc < 0) {
		LogMajor(COMPONENT_PNFS, "status after write %d", -rc);
		return posix2nfs4_error(-rc);
	}

	/** @todo:Here DS is performing the write operation, so the MDS is not
	 *      aware of the change.We should inform MDS through upcalls about
	 *      change in file attributes such as size and time.
	 */
	*written_length = rc;

	*stability_got = stability_wanted;
	ds->stability_got = stability_wanted;

	/* Incase of MDS being DS, there shall not be upcalls sent from
	 * backend. Hence invalidate the entry here */
	(void)upcall_inode_invalidate(glfs_export->gl_fs, ds->glhandle);

	return NFS4_OK;
}
Beispiel #20
0
/**
 * @brief Destroy the package.
 */
void
cih_pkgdestroy(void)
{
	/* Index over partitions */
	int ix = 0;

	/* Destroy the partitions, warning if not empty */
	for (ix = 0; ix < cih_fhcache.npart; ++ix) {
		if (avltree_first(&cih_fhcache.partition[ix].t) != NULL)
			LogMajor(COMPONENT_CACHE_INODE,
				 "Cache inode AVL tree not empty");
		PTHREAD_RWLOCK_destroy(&cih_fhcache.partition[ix].lock);
		gsh_free(cih_fhcache.partition[ix].cache);
	}
	/* Destroy the partition table */
	gsh_free(cih_fhcache.partition);
	cih_fhcache.partition = NULL;
	initialized = false;
}
Beispiel #21
0
/* @brief Initialize the configuration
 *
 * Given the root of the Ganesha configuration structure, initialize
 * the FSAL parameters.
 *
 * @param[in] fsal_hdl      The FSAL module
 * @param[in] config_struct Parsed ganesha configuration file
 *
 * @return FSAL status.
 */
static fsal_status_t init_config(struct fsal_module *fsal_hdl,
                                 config_file_t /*config_struct*/)
{
    struct this_fsal_module *module_me =
        container_of(fsal_hdl, struct this_fsal_module, fsal);

    /* Get a copy of the defaults */
    module_me->fs_info = default_ovs_info;
    display_fsinfo(&module_me->fs_info);
    try
    {
        initialize_logging();
    }
    CATCH_STD_ALL_EWHAT({
            std::stringstream ss;
            ss << EWHAT;
            LogMajor(COMPONENT_FSAL,
                     const_cast<char*>("VFS FSAL: failed to initialize logging: %s"),
                     ss.str().c_str());
            return fsalstat(ERR_FSAL_BAD_INIT, 0);
    });
Beispiel #22
0
/**
 * FSAL_Init : Initializes the FileSystem Abstraction Layer.
 *
 * \param init_info (input, fsal_parameter_t *) :
 *        Pointer to a structure that contains
 *        all initialization parameters for the FSAL.
 *        Specifically, it contains settings about
 *        the filesystem on which the FSAL is based,
 *        security settings, logging policy and outputs,
 *        and other general FSAL options.
 *
 * \return Major error codes :
 *         ERR_FSAL_NO_ERROR     (initialisation OK)
 *         ERR_FSAL_FAULT        (init_info pointer is null)
 *         ERR_FSAL_SERVERFAULT  (misc FSAL error)
 *         ERR_FSAL_ALREADY_INIT (The FS is already initialized)
 *         ERR_FSAL_BAD_INIT     (FS specific init error,
 *                                minor error code gives the reason
 *                                for this error.)
 *         ERR_FSAL_SEC_INIT     (Security context init error).
 */
fsal_status_t POSIXFSAL_Init(fsal_parameter_t * init_info       /* IN */
    )
{
#if defined(_USE_PGSQL)
  posixfs_specific_initinfo_t * posix_init
    = (posixfs_specific_initinfo_t *)&init_info->fs_specific_info;
  int rc = 0 ;
#endif
  fsal_status_t status;

  /* sanity check.  */
  if(!init_info)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);

  /* proceeds FSAL internal initialization */

  status = fsal_internal_init_global(&(init_info->fsal_info),
                                     &(init_info->fs_common_info),
                                     &(init_info->fs_specific_info));

  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_Init);

  /* FS Specific initialization. */

  /* Define the password file path used by PostgreSQL */
#if defined(_USE_PGSQL)
  if(!posix_init->dbparams.passwdfile[0] == '\0')
    {
      rc = setenv("PGPASSFILE", posix_init->dbparams.passwdfile, 1);
      if(rc != 0)
        LogMajor(COMPONENT_FSAL, "FSAL INIT: *** WARNING: Could not set POSTGRESQL keytab path.");
    }
#elif defined (_USE_MYSQL)
  my_init();
#endif

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init);

}
Beispiel #23
0
/* handle_digest
 * fill in the opaque f/s file handle part.
 * we zero the buffer to length first.  This MAY already be done above
 * at which point, remove memset here because the caller is zeroing
 * the whole struct.
 */
static fsal_status_t handle_digest(const struct fsal_obj_handle *obj_hdl,
				   fsal_digesttype_t output_type,
				   struct gsh_buffdesc *fh_desc)
{
	const struct gpfs_fsal_obj_handle *myself;
	struct gpfs_file_handle *fh;
	size_t fh_size;

	/* sanity checks */
	if (!fh_desc)
		return fsalstat(ERR_FSAL_FAULT, 0);
	myself =
	    container_of(obj_hdl, const struct gpfs_fsal_obj_handle,
			 obj_handle);
	fh = myself->handle;

	switch (output_type) {
	case FSAL_DIGEST_NFSV3:
	case FSAL_DIGEST_NFSV4:
		fh_size = gpfs_sizeof_handle(fh);
		if (fh_desc->len < fh_size)
			goto errout;
		memcpy(fh_desc->addr, fh, fh_size);
		break;
	default:
		return fsalstat(ERR_FSAL_SERVERFAULT, 0);
	}
	fh_desc->len = fh_size;
	LogFullDebug(COMPONENT_FSAL,
		"FSAL fh_size %zu type %d", fh_size, output_type);

	return fsalstat(ERR_FSAL_NO_ERROR, 0);

 errout:
	LogMajor(COMPONENT_FSAL,
		 "Space too small for handle.  need %zu, have %zu",
		 fh_size, fh_desc->len);

	return fsalstat(ERR_FSAL_TOOSMALL, 0);
}
Beispiel #24
0
int vfs_get_root_handle(struct vfs_filesystem *vfs_fs,
			struct vfs_fsal_export *exp)
{
	int retval = 0;

	vfs_fs->root_fd = open(vfs_fs->fs->path, O_RDONLY | O_DIRECTORY);

	if (vfs_fs->root_fd < 0) {
		retval = errno;
		LogMajor(COMPONENT_FSAL,
			 "Could not open VFS mount point %s: rc = %s (%d)",
			 vfs_fs->fs->path, strerror(retval), retval);
		return retval;
	}

	/* Check if we have to re-index the fsid based on config */
	if (exp->fsid_type != -1 &&
	    exp->fsid_type != vfs_fs->fs->fsid_type) {
		retval = -change_fsid_type(vfs_fs->fs, exp->fsid_type);
		if (retval != 0) {
			LogCrit(COMPONENT_FSAL,
				"Can not change fsid type of %s to %d, error %s",
				vfs_fs->fs->path, exp->fsid_type,
				strerror(retval));
			return retval;
		}

		LogInfo(COMPONENT_FSAL,
			"Reindexed filesystem %s to "
			"fsid=0x%016"PRIx64".0x%016"PRIx64,
			vfs_fs->fs->path,
			vfs_fs->fs->fsid.major,
			vfs_fs->fs->fsid.minor);
	}

	/* May reindex for some platforms */
	return vfs_re_index(vfs_fs, exp);
}
cache_content_status_t cache_content_truncate(cache_content_entry_t * pentry,
                                              fsal_size_t length,
                                              cache_content_client_t * pclient,
                                              cache_content_status_t * pstatus)
{
  *pstatus = CACHE_CONTENT_SUCCESS;

  /* Perform the truncate operation */
  if(truncate(pentry->local_fs_entry.cache_path_data, (off_t) length) != 0)
    {
      /* Operation failed */

      /* LOG */
      LogMajor(COMPONENT_CACHE_CONTENT,
                        "cache_content_truncate: impossible to truncate %s on local fs, error = ( %d, '%s' )",
                        pentry->local_fs_entry.cache_path_data, errno, strerror(errno));

      /* Sets the error */
      *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR;
    }

  return *pstatus;
}                               /* cache_content_truncate */
void InitLogging()
{
  int i;
  char *env_value;
  int newlevel, component, oldlevel;

  /* Initialisation du tableau des familys */
  tab_family[0].num_family = 0;
  tab_family[0].tab_err = (family_error_t *) tab_systeme_err;
  strcpy(tab_family[0].name_family, "Errors Systeme UNIX");

  for(i = 1; i < MAX_NUM_FAMILY; i++)
    tab_family[i].num_family = UNUSED_SLOT;

  ArmeSignal(SIGUSR1, IncrementeLevelDebug);
  ArmeSignal(SIGUSR2, DecrementeLevelDebug);

  for(component = COMPONENT_ALL; component < COMPONENT_COUNT; component++)
    {
      env_value = getenv(LogComponents[component].comp_name);
      if (env_value == NULL)
        continue;
      newlevel = ReturnLevelAscii(env_value);
      if (newlevel == -1) {
        LogMajor(COMPONENT_LOG,
                 "Environment variable %s exists, but the value %s is not a valid log level.",
                 LogComponents[component].comp_name, env_value);
        continue;
      }
      oldlevel = LogComponents[component].comp_log_level;
      LogComponents[component].comp_log_level = newlevel;
      LogChanges("Using environment variable to switch log level for %s from %s to %s",
                 LogComponents[component].comp_name, ReturnLevelInt(oldlevel),
                 ReturnLevelInt(newlevel));
    }

}                               /* InitLevelDebug */
Beispiel #27
0
/**
 * FSAL_Init : Initializes the FileSystem Abstraction Layer.
 *
 * \param init_info (input, fsal_parameter_t *) :
 *        Pointer to a structure that contains
 *        all initialization parameters for the FSAL.
 *        Specifically, it contains settings about
 *        the filesystem on which the FSAL is based,
 *        security settings, logging policy and outputs,
 *        and other general FSAL options.
 *
 * \return Major error codes :
 *         ERR_FSAL_NO_ERROR     (initialisation OK)
 *         ERR_FSAL_FAULT        (init_info pointer is null)
 *         ERR_FSAL_SERVERFAULT  (misc FSAL error)
 *         ERR_FSAL_ALREADY_INIT (The FS is already initialized)
 *         ERR_FSAL_BAD_INIT     (FS specific init error,
 *                                minor error code gives the reason
 *                                for this error.)
 *         ERR_FSAL_SEC_INIT     (Security context init error).
 */
fsal_status_t GPFSFSAL_Init(fsal_parameter_t * init_info    /* IN */
    )
{
  char *fshandle;
  size_t fshandlelen = 0;

  fsal_status_t status;
  int rc = 0;

  /* sanity check.  */
  if(!init_info)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);

  /* save open-by-handle char device */
  memcpy(open_by_handle_path, init_info->fs_specific_info.open_by_handle_dev_file,
         MAXPATHLEN);
  open_by_handle_fd = open(init_info->fs_specific_info.open_by_handle_dev_file, O_RDONLY);
  if(open_by_handle_fd < 0)
    {
      LogMajor(COMPONENT_FSAL,
               "FSAL INIT: ERROR: Could not open open-by-handle character device file at %s: rc = %d",
               init_info->fs_specific_info.open_by_handle_dev_file, errno);
      ReturnCode(ERR_FSAL_INVAL, 0);
    }

  /* proceeds FSAL internal initialization */
  status = fsal_internal_init_global(&(init_info->fsal_info),
                                     &(init_info->fs_common_info),
                                     &(init_info->fs_specific_info));
  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_Init);

  /* Regular exit */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init);

}
Beispiel #28
0
/**
 * nlm4_Granted_Res: Lock Granted Result Handler
 *
 *  @param parg        [IN]
 *  @param pexportlist [IN]
 *  @param pcontextp   [IN]
 *  @param pclient     [INOUT]
 *  @param ht          [INOUT]
 *  @param preq        [IN]
 *  @param pres        [OUT]
 *
 */
int nlm4_Granted_Res(nfs_arg_t * parg /* IN     */ ,
                     exportlist_t * dummy_pexport /* IN     */ ,
                     fsal_op_context_t * dummy_pcontext /* IN     */ ,
                     cache_inode_client_t * pclient /* INOUT  */ ,
                     hash_table_t * ht /* INOUT  */ ,
                     struct svc_req *preq /* IN     */ ,
                     nfs_res_t * pres /* OUT    */ )
{
  nlm4_res             * arg = &parg->arg_nlm4_res;
  char                   buffer[1024];
  state_status_t         state_status = STATE_SUCCESS;
  state_cookie_entry_t * cookie_entry;
  fsal_op_context_t      context, * pcontext = &context;

  netobj_to_string(&arg->cookie, buffer, 1024);
  LogDebug(COMPONENT_NLM,
           "REQUEST PROCESSING: Calling nlm_Granted_Res cookie=%s",
           buffer);

  if(state_find_grant(arg->cookie.n_bytes,
                      arg->cookie.n_len,
                      &cookie_entry,
                      &state_status) != STATE_SUCCESS)
    {
      /* This must be an old NLM_GRANTED_RES */
      LogFullDebug(COMPONENT_NLM,
                   "Could not find cookie=%s (must be an old NLM_GRANTED_RES)",
                   buffer);
      return NFS_REQ_OK;
    }

  P(cookie_entry->sce_pentry->object.file.lock_list_mutex);

  if(cookie_entry->sce_lock_entry == NULL ||
     cookie_entry->sce_lock_entry->sle_block_data == NULL ||
     !nlm_block_data_to_fsal_context(&cookie_entry->sce_lock_entry->sle_block_data->sbd_block_data.sbd_nlm_block_data,
                                     pcontext))
    {
      /* This must be an old NLM_GRANTED_RES */
      V(cookie_entry->sce_pentry->object.file.lock_list_mutex);
      LogFullDebug(COMPONENT_NLM,
                   "Could not find block data for cookie=%s (must be an old NLM_GRANTED_RES)",
                   buffer);
      return NFS_REQ_OK;
    }

  V(cookie_entry->sce_pentry->object.file.lock_list_mutex);

  if(arg->stat.stat != NLM4_GRANTED)
    {
      LogMajor(COMPONENT_NLM,
               "Granted call failed due to client error, releasing lock");
      if(state_release_grant(pcontext,
                             cookie_entry,
                             pclient,
                             &state_status) != STATE_SUCCESS)
        {
          LogDebug(COMPONENT_NLM,
                   "cache_inode_release_grant failed");
        }
    }
  else
    {
      state_complete_grant(pcontext, cookie_entry, pclient);
      nlm_signal_async_resp(cookie_entry);
    }

  return NFS_REQ_OK;
}
Beispiel #29
0
/**
 * FSAL_mknode:
 * Create a special object in the filesystem.
 * Not supported upon HPSS.
 *
 * \return ERR_FSAL_NOTSUPP.
 */
fsal_status_t GPFSFSAL_mknode(fsal_handle_t * parentdir_handle,     /* IN */
                          fsal_name_t * p_node_name,    /* IN */
                          fsal_op_context_t * p_context,        /* IN */
                          fsal_accessmode_t accessmode, /* IN */
                          fsal_nodetype_t nodetype,     /* IN */
                          fsal_dev_t * dev,     /* IN */
                          fsal_handle_t * p_object_handle,      /* OUT (handle to the created node) */
                          fsal_attrib_list_t * node_attributes  /* [ IN/OUT ] */
    )
{
  int rc, errsv;
  int setgid_bit = 0;
  fsal_status_t status;
  int fd, newfd;

  mode_t unix_mode = 0;
  dev_t unix_dev = 0;
  fsal_accessflags_t access_mask = 0;
  fsal_attrib_list_t parent_dir_attrs;

  /* sanity checks.
   * note : link_attributes is optional.
   */
  if(!parentdir_handle || !p_context || !p_node_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);

  unix_mode = fsal2unix_mode(accessmode);

  /* Apply umask */
  unix_mode = unix_mode & ~global_fs_info.umask;

  switch (nodetype)
    {
    case FSAL_TYPE_BLK:
      if(!dev)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
      unix_mode |= S_IFBLK;
      unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
      break;

    case FSAL_TYPE_CHR:
      if(!dev)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
      unix_mode |= S_IFCHR;
      unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
      break;

    case FSAL_TYPE_SOCK:
      unix_mode |= S_IFSOCK;
      break;

    case FSAL_TYPE_FIFO:
      unix_mode |= S_IFIFO;
      break;

    default:
      LogMajor(COMPONENT_FSAL,
               "Invalid node type in FSAL_mknode: %d", nodetype);
      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode);
    }

  /* build the directory path */
  status =
      fsal_internal_handle2fd(p_context, parentdir_handle, &fd, O_RDONLY | O_DIRECTORY);

  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_mknode);

  /* retrieve directory attributes */
  parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
  status = GPFSFSAL_getattrs(parentdir_handle, p_context, &parent_dir_attrs);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_mknode);

  /* Check the user can write in the directory, and check weither the setgid bit on the directory */
  if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID)
    setgid_bit = 1;

  /* Set both mode and ace4 mask */
  access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
                FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);

  status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_mknode);

  /* creates the node, then stats it */
  rc = mknodat(fd, p_node_name->name, unix_mode, unix_dev);
  errsv = errno;

  if(rc)
    {
      close(fd);
      Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode);
    }

  /* WARNING:
   * After creating the new node, the node name could have been changed.
   * This is a race condition. However only root creates new nodes. This
   * is an unlikely race condition, but hopefully can be fixed someday.
   */

  if(FSAL_IS_ERROR(status = fsal_internal_get_handle_at(fd, p_node_name,
                                                        p_object_handle)))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_mknode);
    }

  if(FSAL_IS_ERROR(status = fsal_internal_handle2fd_at(fd,
                                                       p_object_handle, &newfd,
                                                       O_RDONLY | O_NOFOLLOW)))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_mknode);
    }

  /* the node has been created */
  /* chown the file to the current user/group */

  if(p_context->credential.user != geteuid())
    {
      /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */
      rc = fchown(newfd, p_context->credential.user,
                  setgid_bit ? -1 : (int)p_context->credential.group);
      errsv = errno;

      if(rc)
        {
          close(fd);
          close(newfd);
          Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode);
        }
    }

  close(fd);
  close(newfd);

  /* Fills the attributes if needed */
  if(node_attributes)
    {

      status = GPFSFSAL_getattrs(p_object_handle, p_context, node_attributes);

      /* on error, we set a special bit in the mask. */

      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(node_attributes->asked_attributes);
          FSAL_SET_MASK(node_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  /* Finished */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode);

}
Beispiel #30
0
/**
 * FSAL_mknode:
 * Create a special object in the filesystem.
 * Not supported upon HPSS.
 *
 * \return ERR_FSAL_NOTSUPP.
 */
fsal_status_t POSIXFSAL_mknode(fsal_handle_t * parentdir_hdl,   /* IN */
                               fsal_name_t * p_node_name,       /* IN */
                               fsal_op_context_t * context,      /* IN */
                               fsal_accessmode_t accessmode,    /* IN */
                               fsal_nodetype_t nodetype,        /* IN */
                               fsal_dev_t * dev,        /* IN */
                               fsal_handle_t * object_handle,    /* OUT (handle to the created node) */
                               fsal_attrib_list_t * node_attributes     /* [ IN/OUT ] */
    )
{
  posixfsal_handle_t * parentdir_handle = (posixfsal_handle_t *) parentdir_hdl;
  posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
  posixfsal_handle_t * p_object_handle = (posixfsal_handle_t *) object_handle;
  int rc, errsv;
  int setgid_bit = 0;
  struct stat buffstat;
  fsal_status_t status;
  fsal_path_t fsalpath;
  fsal_posixdb_fileinfo_t info;

  mode_t unix_mode = 0;
  dev_t unix_dev = 0;

  /* sanity checks.
   * note : link_attributes is optional.
   */
  if(!parentdir_handle || !p_context || !p_node_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);

  unix_mode = fsal2unix_mode(accessmode);

  /* Apply umask */
  unix_mode = unix_mode & ~global_fs_info.umask;

  switch (nodetype)
    {
    case FSAL_TYPE_BLK:
      if(!dev)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
      unix_mode |= S_IFBLK;
      unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
      break;

    case FSAL_TYPE_CHR:
      if(!dev)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
      unix_mode |= S_IFCHR;
      unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
      break;

    case FSAL_TYPE_SOCK:
      unix_mode |= S_IFSOCK;
      break;

    case FSAL_TYPE_FIFO:
      unix_mode |= S_IFIFO;
      break;

    default:
      LogMajor(COMPONENT_FSAL, "Invalid node type in FSAL_mknode: %d", nodetype);
      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode);
    }

  /* build the destination path */
  status =
      fsal_internal_getPathFromHandle(p_context, parentdir_handle, 1, &fsalpath,
                                      &buffstat);
  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_mknode);

  /* Check the user can write in the directory, and check weither the setgid bit on the directory */
  if(buffstat.st_mode & S_ISGID)
    setgid_bit = 1;

  status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL);
  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_mknode);

  status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_node_name);
  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_mknode);

  /* creates the node, then stats it */
  TakeTokenFSCall();

  rc = mknod(fsalpath.path, unix_mode, unix_dev);
  if(!rc)
    rc = lstat(fsalpath.path, &buffstat);
  errsv = errno;

  ReleaseTokenFSCall();

  if(rc)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode);

  /* add the object to the database */
  if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info)))
    Return(status.major, status.minor, INDEX_FSAL_mknode);

  if(FSAL_IS_ERROR
     (status =
      fsal_internal_posixdb_add_entry(p_context->p_conn, p_node_name, &info,
                                      parentdir_handle, p_object_handle)))
    Return(status.major, status.minor, INDEX_FSAL_mknode);

  /* the node has been created */
  /* chown the file to the current user/group */

  if(p_context->credential.user != geteuid())
    {
      TakeTokenFSCall();

      /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */
      rc = lchown(fsalpath.path, p_context->credential.user,
                  setgid_bit ? -1 : (int)p_context->credential.group);
      errsv = errno;

      ReleaseTokenFSCall();

      if(rc)
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode);

      buffstat.st_uid = p_context->credential.user;
      buffstat.st_gid = p_context->credential.group;
    }

  /* Fills the attributes if needed */
  if(node_attributes)
    {

      status = posix2fsal_attributes(&buffstat, node_attributes);

      /* on error, we set a special bit in the mask. */

      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(node_attributes->asked_attributes);
          FSAL_SET_MASK(node_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }

    }

  /* Finished */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode);

}