int _9p_readlink(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;

	struct _9p_fid *pfid = NULL;

	cache_inode_status_t cache_status;
	struct gsh_buffdesc link_buffer = {.addr = NULL,
		.len = 0
	};

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

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

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, 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, msgtag, EIO, plenout, preply);
	}

	_9p_init_opctx(pfid, req9p);

	/* let's do the job */
	cache_status =
	    cache_inode_readlink(pfid->pentry, &link_buffer);

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

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

	_9p_setstr(cursor, link_buffer.len - 1, link_buffer.addr);

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

	LogDebug(COMPONENT_9P, "RREADLINK: tag=%u fid=%u link=%s", *msgtag,
		 (u32) *fid, (char *) link_buffer.addr);

	gsh_free(link_buffer.addr);
	return 1;
}
Beispiel #2
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 */
Beispiel #3
0
int _9p_lcreate(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u32 *flags = NULL;
	u32 *mode = NULL;
	u32 *gid = NULL;
	u16 *name_len = NULL;
	char *name_str = NULL;

	struct _9p_fid *pfid = NULL;
	struct _9p_qid qid_newfile;
	u32 iounit = _9P_IOUNIT;

	struct fsal_obj_handle *pentry_newfile = NULL;
	char file_name[MAXNAMLEN+1];
	fsal_status_t fsal_status;
	fsal_openflags_t openflags = 0;

	struct attrlist sattr;
	fsal_verifier_t verifier;
	enum fsal_create_mode createmode = FSAL_UNCHECKED;

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

	_9p_getptr(cursor, fid, u32);
	_9p_getstr(cursor, name_len, name_str);
	_9p_getptr(cursor, flags, u32);
	_9p_getptr(cursor, mode, u32);
	_9p_getptr(cursor, gid, u32);

	LogDebug(COMPONENT_9P,
		 "TLCREATE: tag=%u fid=%u name=%.*s flags=0%o mode=0%o gid=%u",
		 (u32) *msgtag, *fid, *name_len, name_str, *flags, *mode,
		 *gid);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, 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, msgtag, EIO, plenout, preply);
	}

	_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(file_name)) {
		LogDebug(COMPONENT_9P, "request with name too long (%u)",
			 *name_len);
		return _9p_rerror(req9p, msgtag, ENAMETOOLONG, plenout,
				  preply);
	}
	snprintf(file_name, sizeof(file_name), "%.*s", *name_len, name_str);

	_9p_openflags2FSAL(flags, &openflags);
	pfid->state->state_data.fid.share_access =
		_9p_openflags_to_share_access(flags);

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

	memset(&sattr, 0, sizeof(sattr));
	sattr.valid_mask = ATTR_MODE | ATTR_GROUP;
	sattr.mode = *mode;
	sattr.group = *gid;

	if (*flags & 0x10) {
		/* Filesize is already 0. */
		sattr.valid_mask |= ATTR_SIZE;
	}

	if (*flags & 0x1000) {
		/* If OEXCL, use FSAL_EXCLUSIVE_9P create mode
		 * so that we can pass the attributes specified
		 * above. Verifier is ignored for this create mode
		 * because we don't have to deal with retry.
		 */
		createmode = FSAL_EXCLUSIVE_9P;
	}

	fsal_status = fsal_open2(pfid->pentry,
				 pfid->state,
				 openflags,
				 createmode,
				 file_name,
				 &sattr,
				 verifier,
				 &pentry_newfile,
				 NULL);

	/* Release the attributes (may release an inherited ACL) */
	fsal_release_attrs(&sattr);

	if (FSAL_IS_ERROR(fsal_status))
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(fsal_status),
				  plenout, preply);

	/* put parent directory entry */
	pfid->pentry->obj_ops->put_ref(pfid->pentry);

	/* Build the qid */
	qid_newfile.type = _9P_QTFILE;
	qid_newfile.version = 0;
	qid_newfile.path = pentry_newfile->fileid;

	/* The fid will represent the new file now - we can't fail anymore */
	pfid->pentry = pentry_newfile;
	pfid->qid = qid_newfile;
	pfid->xattr = NULL;
	pfid->opens = 1;

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

	_9p_setqid(cursor, qid_newfile);
	_9p_setvalue(cursor, iounit, u32);

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

	LogDebug(COMPONENT_9P,
		 "RLCREATE: tag=%u fid=%u name=%.*s qid=(type=%u,version=%u,path=%llu) iounit=%u pentry=%p",
		 (u32) *msgtag, *fid, *name_len, name_str, qid_newfile.type,
		 qid_newfile.version, (unsigned long long)qid_newfile.path,
		 iounit, pfid->pentry);

	return 1;
}
Beispiel #4
0
int _9p_mkdir(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u32 *mode = NULL;
	u32 *gid = NULL;
	u16 *name_len = NULL;
	char *name_str = NULL;

	struct _9p_fid *pfid = NULL;
	struct _9p_qid qid_newdir;

	struct fsal_obj_handle *pentry_newdir = NULL;
	char dir_name[MAXNAMLEN+1];
	fsal_status_t fsal_status;
	struct attrlist sattr;

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

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

	LogDebug(COMPONENT_9P,
		 "TMKDIR: tag=%u fid=%u name=%.*s mode=0%o gid=%u",
		 (u32) *msgtag, *fid, *name_len, name_str, *mode, *gid);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, 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, msgtag, EIO, plenout, preply);
	}

	_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(dir_name)) {
		LogDebug(COMPONENT_9P, "request with name too long (%u)",
			 *name_len);
		return _9p_rerror(req9p, msgtag, ENAMETOOLONG, plenout,
				  preply);
	}
	snprintf(dir_name, sizeof(dir_name), "%.*s", *name_len, name_str);

	fsal_prepare_attrs(&sattr, ATTR_MODE);

	sattr.mode = *mode;
	sattr.valid_mask = ATTR_MODE;

	/* Create the directory */
	/* BUGAZOMEU: @todo : the gid parameter is not used yet */
	fsal_status = fsal_create(pfid->pentry, dir_name, DIRECTORY, &sattr,
				  NULL, &pentry_newdir, NULL);

	/* Release the attributes (may release an inherited ACL) */
	fsal_release_attrs(&sattr);

	if (FSAL_IS_ERROR(fsal_status))
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(fsal_status), plenout,
				  preply);

	pentry_newdir->obj_ops.put_ref(pentry_newdir);

	/* Build the qid */
	qid_newdir.type = _9P_QTDIR;
	qid_newdir.version = 0;
	qid_newdir.path = pentry_newdir->fileid;

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

	_9p_setqid(cursor, qid_newdir);

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

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

	return 1;
}
Beispiel #5
0
int _9p_setattr(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u32 *valid = NULL;
	u32 *mode = NULL;
	u32 *uid = NULL;
	u32 *gid = NULL;
	u64 *size = NULL;
	u64 *atime_sec = NULL;
	u64 *atime_nsec = NULL;
	u64 *mtime_sec = NULL;
	u64 *mtime_nsec = NULL;

	struct _9p_fid *pfid = NULL;

	struct attrlist fsalattr;
	fsal_status_t fsal_status;

	struct timeval t;

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

	_9p_getptr(cursor, valid, u32);
	_9p_getptr(cursor, mode, u32);
	_9p_getptr(cursor, uid, u32);
	_9p_getptr(cursor, gid, u32);
	_9p_getptr(cursor, size, u64);
	_9p_getptr(cursor, atime_sec, u64);
	_9p_getptr(cursor, atime_nsec, u64);
	_9p_getptr(cursor, mtime_sec, u64);
	_9p_getptr(cursor, mtime_nsec, u64);

	LogDebug(COMPONENT_9P,
		 "TSETATTR: tag=%u fid=%u valid=0x%x mode=0%o uid=%u gid=%u size=%"
		 PRIu64 " atime=(%llu|%llu) mtime=(%llu|%llu)", (u32) *msgtag,
		 *fid, *valid, *mode, *uid, *gid, *size,
		 (unsigned long long)*atime_sec,
		 (unsigned long long)*atime_nsec,
		 (unsigned long long)*mtime_sec,
		 (unsigned long long)*mtime_nsec);

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, 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, msgtag, EIO, plenout, preply);
	}

	_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 a "time" change is required, but not with the "_set" suffix,
	 * use gettimeofday */
	if (*valid &
	    (_9P_SETATTR_ATIME | _9P_SETATTR_CTIME | _9P_SETATTR_MTIME)) {
		if (gettimeofday(&t, NULL) == -1) {
			LogMajor(COMPONENT_9P,
				 "TSETATTR: tag=%u fid=%u ERROR !! gettimeofday returned -1 with errno=%u",
				 (u32) *msgtag, *fid, errno);
			return _9p_rerror(req9p, msgtag, errno,
					  plenout, preply);
		}
	}

	/* Let's do the job */
	memset((char *)&fsalattr, 0, sizeof(fsalattr));

	if (*valid & _9P_SETATTR_MODE) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_MODE);
		fsalattr.mode = *mode;
	}

	if (*valid & _9P_SETATTR_UID) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_OWNER);
		fsalattr.owner = *uid;
	}

	if (*valid & _9P_SETATTR_GID) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_GROUP);
		fsalattr.group = *gid;
	}

	if (*valid & _9P_SETATTR_SIZE) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_SIZE);
		fsalattr.filesize = *size;
	}

	if (*valid & _9P_SETATTR_ATIME) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_ATIME);
		fsalattr.atime.tv_sec = t.tv_sec;
		fsalattr.atime.tv_nsec = t.tv_usec * 1000;
	}

	if (*valid & _9P_SETATTR_MTIME) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_MTIME);
		fsalattr.mtime.tv_sec = t.tv_sec;
		fsalattr.mtime.tv_nsec = t.tv_usec * 1000;
	}

	if (*valid & _9P_SETATTR_CTIME) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_CTIME);
		fsalattr.ctime.tv_sec = t.tv_sec;
		fsalattr.ctime.tv_nsec = t.tv_usec * 1000;
	}

	if (*valid & _9P_SETATTR_ATIME_SET) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_ATIME);
		fsalattr.atime.tv_sec = *atime_sec;
		fsalattr.atime.tv_nsec = *atime_nsec;
	}

	if (*valid & _9P_SETATTR_MTIME_SET) {
		FSAL_SET_MASK(fsalattr.mask, ATTR_MTIME);
		fsalattr.mtime.tv_sec = *mtime_sec;
		fsalattr.mtime.tv_nsec = *mtime_nsec;
	}

	/* Now set the attr */
	fsal_status = fsal_setattr(pfid->pentry, false, pfid->state, &fsalattr);

	/* Release the attributes (may release an inherited ACL) */
	fsal_release_attrs(&fsalattr);

	if (FSAL_IS_ERROR(fsal_status))
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(fsal_status), plenout,
				  preply);

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

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

	LogDebug(COMPONENT_9P,
		 "RSETATTR: tag=%u fid=%u valid=0x%x mode=0%o uid=%u gid=%u size=%"
		 PRIu64 " atime=(%llu|%llu) mtime=(%llu|%llu)", (u32) *msgtag,
		 *fid, *valid, *mode, *uid, *gid, *size,
		 (unsigned long long)*atime_sec,
		 (unsigned long long)*atime_nsec,
		 (unsigned long long)*mtime_sec,
		 (unsigned long long)*mtime_nsec);

	/* _9p_stat_update(*pmsgtype, TRUE, &pwkrdata->stats._9p_stat_req); */
	return 1;
}
Beispiel #6
0
int _9p_write(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u64 *offset = NULL;
	u32 *count = NULL;

	u32 outcount = 0;

	struct _9p_fid *pfid = NULL;

	size_t size;
	size_t written_size = 0;

	char *databuffer = NULL;

	/* Get data */
	_9p_getptr(cursor, msgtag, u16);
	_9p_getptr(cursor, fid, u32);
	_9p_getptr(cursor, offset, u64);
	_9p_getptr(cursor, count, u32);

	databuffer = cursor;

	LogDebug(COMPONENT_9P, "TWRITE: tag=%u fid=%u offset=%llu count=%u",
		 (u32) *msgtag, *fid, (unsigned long long)*offset, *count);

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

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

	/* Make sure the requested amount of data respects negotiated msize */
	if (*count + _9P_ROOM_TWRITE > req9p->pconn->msize)
		return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply);

	/* 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);
	}

	_9p_init_opctx(pfid, req9p);

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

	/* Do the job */
	size = *count;

	if (pfid->xattr != NULL) {
		if (*offset > pfid->xattr->xattr_size)
			return _9p_rerror(req9p, msgtag, EINVAL, plenout,
					  preply);
		if (pfid->xattr->xattr_write != _9P_XATTR_CAN_WRITE &&
		    pfid->xattr->xattr_write != _9P_XATTR_DID_WRITE)
			return _9p_rerror(req9p, msgtag, EINVAL, plenout,
					  preply);

		written_size = MIN(*count,
				   pfid->xattr->xattr_size - *offset);

		memcpy(pfid->xattr->xattr_content + *offset,
		       databuffer, written_size);
		pfid->xattr->xattr_offset += size;
		pfid->xattr->xattr_write = _9P_XATTR_DID_WRITE;

		/* ADD CODE TO DETECT GAP */
#if 0
		fsal_status =
		    pfid->pentry->ops->setextattr_value_by_id(
			pfid->pentry,
			&pfid->op_context,
			pfid->xattr->xattr_id,
			xattrval, size + 1);

		if (FSAL_IS_ERROR(fsal_status))
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno(fsal_status), plenout,
					  preply);
#endif

		outcount = written_size;
	} else {
		struct _9p_write_data write_data;
		struct fsal_io_arg *write_arg = alloca(sizeof(*write_arg) +
						      sizeof(struct iovec));

		write_arg->info = NULL;
		write_arg->state = pfid->state;
		write_arg->offset = *offset;
		write_arg->iov_count = 1;
		write_arg->iov[0].iov_len = size;
		write_arg->iov[0].iov_base = databuffer;
		write_arg->io_amount = 0;
		write_arg->fsal_stable = false;

		write_data.client = req9p->pconn->client;

		/* Do the actual write */
		pfid->pentry->obj_ops->write2(pfid->pentry, true, _9p_write_cb,
					    write_arg, &write_data);

		if (FSAL_IS_ERROR(write_data.ret))
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno(write_data.ret),
					  plenout, preply);

		outcount = (u32) write_arg->io_amount;

	}

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

	_9p_setvalue(cursor, outcount, u32);

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

	LogDebug(COMPONENT_9P,
		 "RWRITE: tag=%u fid=%u offset=%llu input count=%u output count=%u",
		 (u32) *msgtag, *fid, (unsigned long long)*offset, *count,
		 outcount);

/**
 * @todo write statistics accounting goes here
 * modeled on nfs I/O stats
 */
	return 1;
}
Beispiel #7
0
int _9p_read(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	char *databuffer;

	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u64 *offset = NULL;
	u32 *count = NULL;
	u32 outcount = 0;

	struct _9p_fid *pfid = NULL;

	size_t read_size = 0;
	bool eof_met;
	fsal_status_t fsal_status;
	/* uint64_t stable_flag = CACHE_INODE_SAFE_WRITE_TO_FS; */
	bool sync = false;

	/* Get data */
	_9p_getptr(cursor, msgtag, u16);
	_9p_getptr(cursor, fid, u32);
	_9p_getptr(cursor, offset, u64);
	_9p_getptr(cursor, count, u32);

	LogDebug(COMPONENT_9P, "TREAD: tag=%u fid=%u offset=%llu count=%u",
		 (u32) *msgtag, *fid, (unsigned long long)*offset, *count);

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

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

	/* Make sure the requested amount of data respects negotiated msize */
	if (*count + _9P_ROOM_RREAD > req9p->pconn->msize)
		return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply);

	/* 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);
	}

	_9p_init_opctx(pfid, req9p);

	/* Start building the reply already
	 * So we don't need to use an intermediate data buffer
	 */
	_9p_setinitptr(cursor, preply, _9P_RREAD);
	_9p_setptr(cursor, msgtag, u16);
	databuffer = _9p_getbuffertofill(cursor);

	/* Do the job */
	if (pfid->xattr != NULL) {
		/* Copy the value cached during xattrwalk */
		if (*offset > pfid->xattr->xattr_size)
			return _9p_rerror(req9p, msgtag, EINVAL, plenout,
					  preply);
		if (pfid->xattr->xattr_write != _9P_XATTR_READ_ONLY)
			return _9p_rerror(req9p, msgtag, EINVAL, plenout,
					  preply);

		read_size = MIN(*count,
				pfid->xattr->xattr_size - *offset);
		memcpy(databuffer,
		       pfid->xattr->xattr_content + *offset,
		       read_size);

		outcount = read_size;
	} else {
		if (pfid->pentry->fsal->m_ops.support_ex(pfid->pentry)) {
			/* Call the new fsal_read */
			fsal_status = fsal_read2(pfid->pentry,
						false,
						pfid->state,
						*offset,
						*count,
						&read_size,
						databuffer,
						&eof_met,
						NULL);
		} else {
			/* Call legacy fsal_rdwr */
			fsal_status = fsal_rdwr(pfid->pentry,
						 FSAL_IO_READ,
						 *offset,
						 *count,
						 &read_size,
						 databuffer,
						 &eof_met,
						 &sync,
						 NULL);
		}

		/* Get the handle, for stats */
		struct gsh_client *client = req9p->pconn->client;

		if (client == NULL) {
			LogDebug(COMPONENT_9P,
				 "Cannot get client block for 9P request");
		} else {
			op_ctx->client = client;

			server_stats_io_done(*count, read_size,
					     FSAL_IS_ERROR(fsal_status), false);
		}

		if (FSAL_IS_ERROR(fsal_status))
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno(fsal_status),
					  plenout, preply);

		outcount = (u32) read_size;
	}
	_9p_setfilledbuffer(cursor, outcount);

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

	LogDebug(COMPONENT_9P, "RREAD: tag=%u fid=%u offset=%llu count=%u",
		 (u32) *msgtag, *fid, (unsigned long long)*offset, *count);

/**
 * @todo read statistics accounting goes here
 * modeled on nfs I/O statistics
 */
	return 1;
}
Beispiel #8
0
int _9p_remove(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;

	u16 *msgtag = NULL;
	u32 *fid = NULL;
	struct _9p_fid *pfid = NULL;
	cache_inode_status_t cache_status;

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

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

	if (*fid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, 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, msgtag, EIO, plenout, preply);
	}

	_9p_init_opctx(pfid, req9p);

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

	cache_status = cache_inode_remove(pfid->ppentry, pfid->name);
	if (cache_status != CACHE_INODE_SUCCESS)
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);

	/* If object is an opened file, close it */
	if ((pfid->pentry->type == REGULAR_FILE) && is_open(pfid->pentry)) {
		if (pfid->opens) {
			cache_inode_dec_pin_ref(pfid->pentry, false);
			pfid->opens = 0;	/* dead */

			/* Under this flag, pin ref is still checked */
			cache_status =
			    cache_inode_close(pfid->pentry,
					      CACHE_INODE_FLAG_REALLYCLOSE);
			if (cache_status != CACHE_INODE_SUCCESS) {
				FREE_FID(pfid, fid, req9p);
				return _9p_rerror(req9p, msgtag,
						  _9p_tools_errno(cache_status),
						  plenout, preply);
			}
		}
	}

	/* Clean the fid */
	FREE_FID(pfid, fid, req9p);

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

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

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

	/* _9p_stat_update( *pmsgtype, TRUE, &pwkrdata->stats._9p_stat_req); */
	return 1;

}
int _9p_xattrwalk(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u32 *attrfid = NULL;
	u16 *name_len;
	char *name_str;
	size_t attrsize = 0;

	fsal_status_t fsal_status;
	char name[MAXNAMLEN];
	fsal_xattrent_t xattrs_arr[XATTRS_ARRAY_LEN];
	int eod_met = false;
	unsigned int nb_xattrs_read = 0;
	unsigned int i = 0;
	char *xattr_cursor = NULL;
	unsigned int tmplen = 0;

	struct _9p_fid *pfid = NULL;
	struct _9p_fid *pxattrfid = NULL;

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

	LogDebug(COMPONENT_9P, "TXATTRWALK: tag=%u fid=%u attrfid=%u",
		 (u32) *msgtag, *fid, *attrfid);

	_9p_getstr(cursor, name_len, name_str);

	if (*name_len == 0)
		LogDebug(COMPONENT_9P,
			 "TXATTRWALK (component): tag=%u fid=%u attrfid=%u name=(LIST XATTR)",
			 (u32) *msgtag, *fid, *attrfid);
	else
		LogDebug(COMPONENT_9P,
			 "TXATTRWALK (component): tag=%u fid=%u attrfid=%u name=%.*s",
			 (u32) *msgtag, *fid, *attrfid, *name_len, name_str);

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

	if (*attrfid >= _9P_FID_PER_CONN)
		return _9p_rerror(req9p, 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, msgtag, EIO, plenout, preply);
	}

	pxattrfid = gsh_calloc(1, sizeof(struct _9p_fid));
	if (pxattrfid == NULL)
		return _9p_rerror(req9p, msgtag, ENOMEM, plenout, preply);

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

	/* Initiate xattr's fid by copying file's fid in it */
	memcpy((char *)pxattrfid, (char *)pfid, sizeof(struct _9p_fid));

	snprintf(name, MAXNAMLEN, "%.*s", *name_len, name_str);

	pxattrfid->specdata.xattr.xattr_content = gsh_malloc(XATTR_BUFFERSIZE);
	if (pxattrfid->specdata.xattr.xattr_content == NULL) {
		gsh_free(pxattrfid);
		return _9p_rerror(req9p, msgtag, ENOMEM, plenout, preply);
	}

	if (*name_len == 0) {
		/* xattrwalk is used with an empty name,
		 * this is a listxattr request */
		fsal_status =
		    pxattrfid->pentry->obj_handle->obj_ops.list_ext_attrs(
			pxattrfid->pentry->obj_handle,
			FSAL_XATTR_RW_COOKIE,	/* Start with RW cookie,
						 * hiding RO ones */
			 xattrs_arr,
			 XATTRS_ARRAY_LEN, /** @todo fix static length */
			 &nb_xattrs_read,
			 &eod_met);

		if (FSAL_IS_ERROR(fsal_status)) {
			gsh_free(pxattrfid->specdata.xattr.xattr_content);
			gsh_free(pxattrfid);
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno
					  (cache_inode_error_convert
					   (fsal_status)), plenout, preply);
		}

		/* if all xattrent are not read,
		 * returns ERANGE as listxattr does */
		if (eod_met != true) {
			gsh_free(pxattrfid->specdata.xattr.xattr_content);
			gsh_free(pxattrfid);
			return _9p_rerror(req9p, msgtag, ERANGE,
					  plenout, preply);
		}

		xattr_cursor = pxattrfid->specdata.xattr.xattr_content;
		attrsize = 0;
		for (i = 0; i < nb_xattrs_read; i++) {
			tmplen =
			    snprintf(xattr_cursor, MAXNAMLEN, "%s",
				     xattrs_arr[i].xattr_name);
			xattr_cursor[tmplen] = '\0';	/* Just to be sure */
			/* +1 for trailing '\0' */
			xattr_cursor += tmplen + 1;
			attrsize += tmplen + 1;

			/* Make sure not to go beyond the buffer */
			if (attrsize > XATTR_BUFFERSIZE) {
				gsh_free(pxattrfid->specdata.xattr.
					 xattr_content);
				gsh_free(pxattrfid);
				return _9p_rerror(req9p, msgtag, ERANGE,
						  plenout, preply);
			}
		}
	} else {
		/* xattrwalk has a non-empty name, use regular setxattr */
		fsal_status =
		    pxattrfid->pentry->obj_handle->obj_ops.
		    getextattr_id_by_name(pxattrfid->pentry->obj_handle,
					  name,
					  &pxattrfid->specdata.xattr.xattr_id);


		if (FSAL_IS_ERROR(fsal_status)) {
			gsh_free(pxattrfid->specdata.xattr.xattr_content);
			gsh_free(pxattrfid);

			/* ENOENT for xattr is ENOATTR */
			if (fsal_status.major == ERR_FSAL_NOENT)
				return _9p_rerror(req9p, msgtag, ENOATTR,
						  plenout, preply);
			else
				return _9p_rerror(req9p, msgtag,
						  _9p_tools_errno
						  (cache_inode_error_convert
						   (fsal_status)), plenout,
						  preply);
		}

		fsal_status =
		    pxattrfid->pentry->obj_handle->obj_ops.
		    getextattr_value_by_name(pxattrfid->pentry->obj_handle,
					     name,
					     pxattrfid->specdata.xattr.
					     xattr_content, XATTR_BUFFERSIZE,
					     &attrsize);

		if (FSAL_IS_ERROR(fsal_status)) {
			gsh_free(pxattrfid->specdata.xattr.xattr_content);
			gsh_free(pxattrfid);

			/* fsal_status.minor is a valid errno code */
			return _9p_rerror(req9p, msgtag,
					  fsal_status.minor, plenout, preply);
		}
	}

	req9p->pconn->fids[*attrfid] = pxattrfid;

	/* Increments refcount as we're manually making a new copy */
	(void) cache_inode_lru_ref(pfid->pentry, LRU_REQ_STALE_OK);

	/* hold reference on gdata */
	uid2grp_hold_group_data(pxattrfid->gdata);

	get_gsh_export_ref(pfid->export);
	get_9p_user_cred_ref(pfid->ucred);

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

	_9p_setvalue(cursor, attrsize, u64);

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

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

	return 1;
}				/* _9p_xattrwalk */
Beispiel #10
0
int _9p_statfs(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;

	struct _9p_fid *pfid = NULL;

	u32 type = 0x01021997;	/* V9FS_MAGIC */
	u32 bsize = 1;		/* cache_inode_statfs and
				 * FSAL already care for blocksize */
	u64 *blocks = NULL;
	u64 *bfree = NULL;
	u64 *bavail = NULL;
	u64 *files = NULL;
	u64 *ffree = NULL;
	u64 fsid = 0LL;

	u32 namelen = MAXNAMLEN;

	fsal_dynamicfsinfo_t dynamicinfo;
	cache_inode_status_t cache_status;

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

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

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

	pfid = req9p->pconn->fids[*fid];
	if (pfid == NULL)
		return _9p_rerror(req9p, msgtag, EINVAL, plenout, preply);
	_9p_init_opctx(pfid, req9p);
	/* Get the FS's stats */
	cache_status = cache_inode_statfs(pfid->pentry, &dynamicinfo);
	if (cache_status != CACHE_INODE_SUCCESS)
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);

	blocks = (u64 *) &dynamicinfo.total_bytes;
	bfree = (u64 *) &dynamicinfo.free_bytes;
	bavail = (u64 *) &dynamicinfo.avail_bytes;
	files = (u64 *) &dynamicinfo.total_files;
	ffree = (u64 *) &dynamicinfo.free_files;
	fsid = (u64) pfid->pentry->obj_handle->attrs->rawdev.major;

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

	_9p_setvalue(cursor, type, u32);
	_9p_setvalue(cursor, bsize, u32);
	_9p_setptr(cursor, blocks, u64);
	_9p_setptr(cursor, bfree, u64);
	_9p_setptr(cursor, bavail, u64);
	_9p_setptr(cursor, files, u64);
	_9p_setptr(cursor, ffree, u64);
	_9p_setvalue(cursor, fsid, u64);
	_9p_setvalue(cursor, namelen, u32);

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

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

	return 1;
}
Beispiel #11
0
int _9p_symlink(struct _9p_request_data *req9p, 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, 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, msgtag, EIO, plenout, preply);
	}

	_9p_init_opctx(pfid, req9p);

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

	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, 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, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);
	}

	fileid = cache_inode_fileid(pentry_symlink);

	/* put the entry. */
	cache_inode_put(pentry_symlink);

	/* 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;
}
Beispiel #12
0
int _9p_write(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *fid = NULL;
	u64 *offset = NULL;
	u32 *count = NULL;

	u32 outcount = 0;

	struct _9p_fid *pfid = NULL;

	size_t size;
	size_t written_size = 0;
	bool eof_met;
	cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
	/* bool sync = true; */
	bool sync = false;

	char *databuffer = NULL;

	/* fsal_status_t fsal_status; */

	/* Get data */
	_9p_getptr(cursor, msgtag, u16);
	_9p_getptr(cursor, fid, u32);
	_9p_getptr(cursor, offset, u64);
	_9p_getptr(cursor, count, u32);

	databuffer = cursor;

	LogDebug(COMPONENT_9P, "TWRITE: tag=%u fid=%u offset=%llu count=%u",
		 (u32) *msgtag, *fid, (unsigned long long)*offset, *count);

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

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

	/* Make sure the requested amount of data respects negotiated msize */
	if (*count + _9P_ROOM_TWRITE > req9p->pconn->msize)
		return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply);

	/* 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);
	}

	_9p_init_opctx(pfid, req9p);

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

	/* Do the job */
	size = *count;

	if (pfid->specdata.xattr.xattr_content != NULL) {
		memcpy(pfid->specdata.xattr.xattr_content + (*offset),
		       databuffer, size);
		pfid->specdata.xattr.xattr_offset += size;
		pfid->specdata.xattr.xattr_write = true;

		/* ADD CODE TO DETECT GAP */
#if 0
		fsal_status =
		    pfid->pentry->obj_handle->ops->setextattr_value_by_id(
			pfid->pentry->obj_handle,
			&pfid->op_context,
			pfid->specdata.xattr.xattr_id,
			xattrval, size + 1);

		if (FSAL_IS_ERROR(fsal_status))
			return _9p_rerror(req9p, msgtag,
					  _9p_tools_errno
					  (cache_inode_error_convert
					   (fsal_status)), plenout, preply);
#endif

		outcount = *count;
	} else {
		cache_status = cache_inode_rdwr(pfid->pentry, CACHE_INODE_WRITE,
						*offset, size, &written_size,
						databuffer, &eof_met, &sync,
						NULL);

		/* Get the handle, for stats */
		struct gsh_client *client = req9p->pconn->client;

		if (client == NULL) {
			LogDebug(COMPONENT_9P,
				 "Cannot get client block for 9P request");
		} else {
			op_ctx->client = client;

			server_stats_io_done(size,
					     written_size,
					     (cache_status ==
					      CACHE_INODE_SUCCESS) ?
					      true : false,
					     true);
		}

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

		outcount = (u32) written_size;

	}

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

	_9p_setvalue(cursor, outcount, u32);

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

	LogDebug(COMPONENT_9P,
		 "RWRITE: tag=%u fid=%u offset=%llu input count=%u output count=%u",
		 (u32) *msgtag, *fid, (unsigned long long)*offset, *count,
		 outcount);

/**
 * @todo write statistics accounting goes here
 * modeled on nfs I/O stats
 */
	return 1;
}
Beispiel #13
0
int _9p_unlinkat(struct _9p_request_data *req9p, u32 *plenout, char *preply)
{
	char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE;
	u16 *msgtag = NULL;
	u32 *dfid = NULL;
	u16 *name_len = NULL;
	char *name_str = NULL;
	/* flags are not used */
	__attribute__ ((unused)) u32 *flags = NULL;

	struct _9p_fid *pdfid = NULL;

	fsal_status_t fsal_status;
	char name[MAXNAMLEN];

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

	_9p_getptr(cursor, dfid, u32);
	_9p_getstr(cursor, name_len, name_str);
	_9p_getptr(cursor, flags, u32);

	LogDebug(COMPONENT_9P, "TUNLINKAT: tag=%u dfid=%u name=%.*s",
		 (u32) *msgtag, *dfid, *name_len, name_str);

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

	pdfid = req9p->pconn->fids[*dfid];

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

	_9p_init_opctx(pdfid, req9p);

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

	/* Let's do the job */
	snprintf(name, MAXNAMLEN, "%.*s", *name_len, name_str);

	fsal_status = fsal_remove(pdfid->pentry, name);
	if (FSAL_IS_ERROR(fsal_status))
		return _9p_rerror(req9p, msgtag,
				  _9p_tools_errno(fsal_status), plenout,
				  preply);

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

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

	LogDebug(COMPONENT_9P, "TUNLINKAT: tag=%u dfid=%u name=%.*s",
		 (u32) *msgtag, *dfid, *name_len, name_str);

	return 1;
}