mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-17 04:36:22 +00:00
SCST events sample user space consumer
Prepared with help from Prasidh Srikanth <Prasidh.Srikanth@sandisk.com> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6581 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -23,46 +23,57 @@ SHELL=/bin/bash
|
||||
|
||||
FILEIO_DIR=fileio
|
||||
STPGD_DIR=stpgd
|
||||
EVENTS_DIR=events
|
||||
|
||||
all:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
# cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
install:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
# cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
uninstall:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
clean:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
extraclean:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
2release:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
2debug:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
2perf:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
disable_proc:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
enable_proc:
|
||||
cd $(FILEIO_DIR) && $(MAKE) $@
|
||||
cd $(STPGD_DIR) && $(MAKE) $@
|
||||
cd $(EVENTS_DIR) && $(MAKE) $@
|
||||
|
||||
help:
|
||||
@echo " all (the default) : make all"
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
ifndef PREFIX
|
||||
PREFIX=/usr/local
|
||||
endif
|
||||
|
||||
SHELL=/bin/bash
|
||||
|
||||
SRCS_F = events.c debug.c
|
||||
OBJS_F = $(SRCS_F:.c=.o)
|
||||
|
||||
#SRCS_C =
|
||||
#OBJS_C = $(SRCS_C:.c=.o)
|
||||
|
||||
SCST_INC_DIR := $(shell if [ -e "$$PWD/../../scst" ]; \
|
||||
then echo "$$PWD/../../scst/include"; \
|
||||
else echo "$(DESTDIR)$(PREFIX)/include/scst"; fi)
|
||||
DEBUG_INC_DIR := ../include
|
||||
INSTALL_DIR := $(DESTDIR)$(PREFIX)/bin/scst
|
||||
|
||||
CFLAGS += -O2 -Wall -Wextra -Wno-unused-parameter -Wstrict-prototypes \
|
||||
-I$(SCST_INC_DIR) -I$(DEBUG_INC_DIR) -D_GNU_SOURCE -D__USE_FILE_OFFSET64 \
|
||||
-D__USE_LARGEFILE64
|
||||
PROGS = events
|
||||
LIBS = -lpthread
|
||||
|
||||
CFLAGS += -DEXTRACHECKS
|
||||
#CFLAGS += -DTRACING
|
||||
CFLAGS += -DDEBUG -g -fno-inline -fno-inline-functions
|
||||
CFLAGS += -W -Wno-unused-parameter
|
||||
CFLAGS += $(LOCAL_CFLAGS)
|
||||
|
||||
#CFLAGS += -DDEBUG_NOMEM
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
events: .depend_f $(OBJS_F)
|
||||
$(CC) $(OBJS_F) $(LIBS) $(LOCAL_LD_FLAGS) -o $@
|
||||
|
||||
#cdrom_tgt: .depend_c $(OBJS_C)
|
||||
# $(CC) $(OBJS_C) $(LIBS) $(LOCAL_LD_FLAGS) -o $@
|
||||
|
||||
ifeq (.depend_f,$(wildcard .depend_f))
|
||||
-include .depend_f
|
||||
endif
|
||||
|
||||
#ifeq (.depend_c,$(wildcard .depend_c))
|
||||
#-include .depend_c
|
||||
#endif
|
||||
|
||||
%.o: %.c Makefile
|
||||
$(CC) -c -o $(@) $(CFLAGS) $(<)
|
||||
|
||||
.depend_f:
|
||||
$(CC) -M $(CFLAGS) $(SRCS_F) >$(@)
|
||||
|
||||
#.depend_c:
|
||||
# $(CC) -M $(CFLAGS) $(SRCS_C) >$(@)
|
||||
|
||||
install: all
|
||||
install -d $(INSTALL_DIR)
|
||||
install -m 755 $(PROGS) $(INSTALL_DIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(INSTALL_DIR)/$(PROGS)
|
||||
rm -rf $(INSTALL_DIR)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROGS) .depend*
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.orig *.rej
|
||||
|
||||
2release:
|
||||
sed -i.aa s/"^C\?FLAGS += \-DEXTRACHECKS"/"#CFLAGS += \-DEXTRACHECKS"/ Makefile
|
||||
grep "^#CFLAGS += \-DEXTRACHECKS" Makefile >/dev/null
|
||||
sed -i.aa s/"^#\?CFLAGS += \-DTRACING"/"CFLAGS += \-DTRACING"/ Makefile
|
||||
grep "^CFLAGS += \-DTRACING" Makefile >/dev/null
|
||||
sed -i.aa s/"^C\?FLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions"/"#CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions"/ Makefile
|
||||
grep "^#CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions" Makefile >/dev/null
|
||||
rm Makefile.aa
|
||||
|
||||
2debug:
|
||||
sed -i.aa s/"^#\?CFLAGS += \-DEXTRACHECKS"/"CFLAGS += \-DEXTRACHECKS"/ Makefile
|
||||
grep "^CFLAGS += \-DEXTRACHECKS" Makefile >/dev/null
|
||||
sed -i.aa s/"^C\?FLAGS += \-DTRACING"/"#CFLAGS += \-DTRACING"/ Makefile
|
||||
grep "^#CFLAGS += \-DTRACING" Makefile >/dev/null
|
||||
sed -i.aa s/"^#\?CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions"/"CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions"/ Makefile
|
||||
grep "^CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions" Makefile >/dev/null
|
||||
rm Makefile.aa
|
||||
|
||||
2perf:
|
||||
sed -i.aa s/"^C\?FLAGS += \-DEXTRACHECKS"/"#CFLAGS += \-DEXTRACHECKS"/ Makefile
|
||||
grep "^#CFLAGS += \-DEXTRACHECKS" Makefile >/dev/null
|
||||
sed -i.aa s/"^C\?FLAGS += \-DTRACING"/"#CFLAGS += \-DTRACING"/ Makefile
|
||||
grep "^#CFLAGS += \-DTRACING" Makefile >/dev/null
|
||||
sed -i.aa s/"^C\?FLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions"/"#CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions"/ Makefile
|
||||
grep "^#CFLAGS += \-DDEBUG -g -fno-inline -fno-inline-functions" Makefile >/dev/null
|
||||
rm Makefile.aa
|
||||
|
||||
release-archive:
|
||||
../../scripts/generate-release-archive events "$$(sed -n 's/^#define[[:blank:]]VERSION_STR[[:blank:]]*\"\([^\"]*\)\".*/\1/p' events.c)"
|
||||
|
||||
.PHONY: all install uninstall clean extraclean 2release 2debug 2perf
|
||||
@@ -0,0 +1,2 @@
|
||||
This is test/demo application for SCST events subsystem. For more
|
||||
information about this subsystem, see scst_event.h file.
|
||||
@@ -0,0 +1 @@
|
||||
#include "../include/debug.c"
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* events.c
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <malloc.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "debug.h"
|
||||
#include "scst_event.h"
|
||||
|
||||
char *app_name;
|
||||
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
|
||||
#ifdef DEBUG
|
||||
/*#define DEFAULT_LOG_FLAGS (TRACE_ALL & ~TRACE_MEMORY & ~TRACE_BUFF \
|
||||
& ~TRACE_FUNCTION)
|
||||
#define DEFAULT_LOG_FLAGS (TRACE_ALL & ~TRACE_MEMORY & ~TRACE_BUFF & \
|
||||
~TRACE_SCSI & ~TRACE_SCSI_SERIALIZING & ~TRACE_DEBUG)
|
||||
*/
|
||||
#define DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MINOR | TRACE_PID | \
|
||||
TRACE_FUNCTION | TRACE_SPECIAL | TRACE_MGMT | TRACE_MGMT_DEBUG | \
|
||||
TRACE_TIME)
|
||||
|
||||
#define TRACE_SN(args...) TRACE(TRACE_SCSI_SERIALIZING, args)
|
||||
|
||||
#else /* DEBUG */
|
||||
|
||||
# ifdef TRACING
|
||||
#define DEFAULT_LOG_FLAGS (TRACE_OUT_OF_MEM | TRACE_MGMT | \
|
||||
TRACE_TIME | TRACE_SPECIAL)
|
||||
# else
|
||||
#define DEFAULT_LOG_FLAGS 0
|
||||
# endif
|
||||
#endif /* DEBUG */
|
||||
|
||||
bool log_daemon = false; /* needed for the tracing infrastructure */
|
||||
unsigned long trace_flag = DEFAULT_LOG_FLAGS;
|
||||
#endif /* defined(DEBUG) || defined(TRACING) */
|
||||
|
||||
static struct option const long_options[] = {
|
||||
{"allowed_event", required_argument, 0, 'e'},
|
||||
{"allowed_issuer", required_argument, 0, 'i'},
|
||||
{"non_blocking", no_argument, 0, 'n'},
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
{"debug", required_argument, 0, 'd'},
|
||||
#endif
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
#define MAX_ALLOWED_EVENTS 16
|
||||
static struct scst_event allowed_events[MAX_ALLOWED_EVENTS];
|
||||
static int allowed_events_num;
|
||||
static int non_blocking;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: %s [OPTIONS]\n", app_name);
|
||||
printf("\nSCST events testing program\n");
|
||||
printf(" -e, --allowed_event=code Allowed event code, 0 - any event\n");
|
||||
printf(" -i, --allowed_issuer=issuer Allowed issuer, * - any issuer\n");
|
||||
printf(" -n, --non_blocking Use non-blocking operations\n");
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
printf(" -d, --debug=level Debug tracing level\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void handle_tm_received(struct scst_event_user *event_user)
|
||||
{
|
||||
struct scst_event_tm_fn_received_payload *p = (struct scst_event_tm_fn_received_payload *)event_user->out_event.payload;
|
||||
|
||||
printf("fn %d, device %s\n", p->fn, p->device_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int res = 0, i;
|
||||
int ch, longindex;
|
||||
int event_fd;
|
||||
uint8_t event_user_buf[10240];
|
||||
struct scst_event_user *event_user = (struct scst_event_user *)event_user_buf;
|
||||
struct pollfd pl;
|
||||
|
||||
setlinebuf(stdout);
|
||||
|
||||
res = debug_init();
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
app_name = argv[0];
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "+e:i:d:nhv",
|
||||
long_options, &longindex)) >= 0) {
|
||||
switch (ch) {
|
||||
case 'e':
|
||||
if (allowed_events[allowed_events_num].event_code != 0) {
|
||||
allowed_events_num++;
|
||||
if (allowed_events_num >= MAX_ALLOWED_EVENTS) {
|
||||
PRINT_ERROR("Too many allowed events %d",
|
||||
allowed_events_num);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
allowed_events[allowed_events_num].event_code = atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
if (allowed_events[allowed_events_num].issuer_name[0] != '\0') {
|
||||
allowed_events_num++;
|
||||
if (allowed_events_num >= MAX_ALLOWED_EVENTS) {
|
||||
PRINT_ERROR("Too many allowed events %d",
|
||||
allowed_events_num);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
strncpy(allowed_events[allowed_events_num].issuer_name,
|
||||
optarg, sizeof(allowed_events[allowed_events_num].issuer_name));
|
||||
allowed_events[allowed_events_num].issuer_name[
|
||||
sizeof(allowed_events[allowed_events_num].issuer_name)-1] = '\0';
|
||||
break;
|
||||
case 'n':
|
||||
non_blocking = 1;
|
||||
break;
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
case 'd':
|
||||
trace_flag = strtol(optarg, (char **)NULL, 0);
|
||||
break;
|
||||
#endif
|
||||
case 'v':
|
||||
printf("%s version %s\n", app_name, VERSION_STR);
|
||||
goto out_done;
|
||||
default:
|
||||
goto out_usage;
|
||||
}
|
||||
}
|
||||
|
||||
if (allowed_events_num == 0) {
|
||||
if ((allowed_events[0].event_code == 0) &&
|
||||
(allowed_events[0].issuer_name[0] == '\0'))
|
||||
allowed_events[0].issuer_name[0] = '*';
|
||||
}
|
||||
|
||||
allowed_events_num++;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRINT_INFO("trace_flag %lx", trace_flag);
|
||||
#endif
|
||||
|
||||
if (non_blocking)
|
||||
PRINT_INFO("%s", "NON-BLOCKING");
|
||||
|
||||
event_fd = open(SCST_EVENT_DEV, O_RDWR | (non_blocking ? O_NONBLOCK : 0));
|
||||
if (event_fd < 0) {
|
||||
res = -errno;
|
||||
PRINT_ERROR("Unable to open SCST event device %s (%s)",
|
||||
SCST_EVENT_DEV, strerror(-res));
|
||||
goto out_done;
|
||||
}
|
||||
|
||||
memset(&pl, 0, sizeof(pl));
|
||||
pl.fd = event_fd;
|
||||
pl.events = POLLIN;
|
||||
|
||||
for (i = 0; i < allowed_events_num; i++) {
|
||||
struct scst_event e;
|
||||
|
||||
PRINT_INFO("Setting allowed event code %d, issuer_name %s",
|
||||
allowed_events[i].event_code,
|
||||
allowed_events[i].issuer_name);
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.event_code = allowed_events[i].event_code;
|
||||
strncpy(e.issuer_name, allowed_events[i].issuer_name,
|
||||
sizeof(e.issuer_name));
|
||||
e.issuer_name[sizeof(e.issuer_name)-1] = '\0';
|
||||
|
||||
res = ioctl(event_fd, SCST_EVENT_ALLOW_EVENT, &e);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("SCST_EVENT_ALLOW_EVENT failed: %s (res %d)",
|
||||
strerror(errno), res);
|
||||
goto out_done;
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
memset(event_user_buf, 0, sizeof(event_user_buf));
|
||||
event_user->max_event_size = sizeof(event_user_buf);
|
||||
res = ioctl(event_fd, SCST_EVENT_GET_NEXT_EVENT, event_user);
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
switch (res) {
|
||||
case ESRCH:
|
||||
case EBUSY:
|
||||
TRACE_MGMT_DBG("SCST_EVENT_GET_NEXT_EVENT returned "
|
||||
"%d (%s)", res, strerror(res));
|
||||
/* go through */
|
||||
case EINTR:
|
||||
continue;
|
||||
case EAGAIN:
|
||||
TRACE_DBG("SCST_EVENT_GET_NEXT_EVENT, returned "
|
||||
"EAGAIN (%d)", res);
|
||||
if (non_blocking)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
default:
|
||||
PRINT_ERROR("SCST_EVENT_GET_NEXT_EVENT failed: %s (res %d)",
|
||||
strerror(errno), res);
|
||||
goto out_done;
|
||||
}
|
||||
again_poll:
|
||||
res = poll(&pl, 1, 2000);
|
||||
if (res > 0)
|
||||
continue;
|
||||
else if (res == 0)
|
||||
goto again_poll;
|
||||
else {
|
||||
res = errno;
|
||||
switch (res) {
|
||||
case ESRCH:
|
||||
case EBUSY:
|
||||
case EAGAIN:
|
||||
TRACE_MGMT_DBG("poll() returned %d "
|
||||
"(%s)", res, strerror(res));
|
||||
case EINTR:
|
||||
goto again_poll;
|
||||
default:
|
||||
PRINT_ERROR("poll() failed: %s", strerror(res));
|
||||
#if 1
|
||||
goto again_poll;
|
||||
#else
|
||||
goto out_close;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PRINT_INFO("\nevent_code %d, issuer_name %s",
|
||||
event_user->out_event.event_code,
|
||||
event_user->out_event.issuer_name);
|
||||
if (event_user->out_event.payload_len != 0)
|
||||
PRINT_BUFFER("payoad", event_user->out_event.payload,
|
||||
event_user->out_event.payload_len);
|
||||
PRINT_INFO("%s", "");
|
||||
|
||||
if (event_user->out_event.event_code == 0x12345) {
|
||||
struct scst_event_notify_done d;
|
||||
|
||||
PRINT_INFO("%s", "Press any key to send reply to event "
|
||||
"0x12345");
|
||||
getchar();
|
||||
|
||||
memset(&d, 0, sizeof(d));
|
||||
d.event_id = event_user->out_event.event_id;
|
||||
d.status = -19;
|
||||
res = ioctl(event_fd, SCST_EVENT_NOTIFY_DONE, &d);
|
||||
if (res != 0)
|
||||
PRINT_ERROR("SCST_EVENT_NOTIFY_DONE failed: %s "
|
||||
"(res %d)", strerror(errno), res);
|
||||
} else if (event_user->out_event.event_code == SCST_EVENT_TM_FN_RECEIVED)
|
||||
handle_tm_received(event_user);
|
||||
else if (event_user->out_event.event_code == SCST_EVENT_TM_FN_RECEIVED) {
|
||||
struct scst_event_notify_done d;
|
||||
|
||||
memset(&d, 0, sizeof(d));
|
||||
d.event_id = event_user->out_event.event_id;
|
||||
d.status = -20;
|
||||
res = ioctl(event_fd, SCST_EVENT_NOTIFY_DONE, &d);
|
||||
if (res != 0)
|
||||
PRINT_ERROR("SCST_EVENT_NOTIFY_DONE failed: %s "
|
||||
"(res %d)", strerror(errno), res);
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
struct scst_event e;
|
||||
|
||||
PRINT_INFO("Deleting allowed event code %d, issuer_name %s",
|
||||
allowed_events[0].event_code,
|
||||
allowed_events[0].issuer_name);
|
||||
memset(&e, 0, sizeof(e));
|
||||
e.event_code = allowed_events[0].event_code;
|
||||
strncpy(e.issuer_name, allowed_events[0].issuer_name,
|
||||
sizeof(e.issuer_name));
|
||||
e.issuer_name[sizeof(e.issuer_name)-1] = '\0';
|
||||
|
||||
res = ioctl(event_fd, SCST_EVENT_DISALLOW_EVENT, &e);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("SCST_EVENT_DISALLOW_EVENT failed: "
|
||||
"%s (res %d)", strerror(errno), res);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
out_done:
|
||||
debug_done();
|
||||
|
||||
out:
|
||||
return res;
|
||||
|
||||
out_usage:
|
||||
usage();
|
||||
goto out_done;
|
||||
}
|
||||
Reference in New Issue
Block a user