mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-21 06:36:27 +00:00
2 missed functions added to scst_user interface:
- SCST_USER_UNREGISTER_DEVICE - to unregister device, flush mem reuse (SGV) cache and send UCMD_STATE_ON_CACHE_FREEING notifications for all freed buffers to the user space handler. Simple device close doesn't allow that, so all the cached buffers might look as "leaked" from the user space handler POV. - SCST_USER_FLUSH_CACHE - to flush mem reuse (SGV) cache and send UCMD_STATE_ON_CACHE_FREEING notifications for all freed buffers to the user space handler + some cosmetics Docs update is coming git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@665 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+2
-2
@@ -781,10 +781,10 @@ void *main_loop(void *arg)
|
||||
switch(res) {
|
||||
case ESRCH:
|
||||
case EBUSY:
|
||||
case EINTR:
|
||||
TRACE_MGMT_DBG("SCST_USER_REPLY_AND_GET_CMD returned "
|
||||
"%d (%s)", res, strerror(res));
|
||||
cmd.preply = 0;
|
||||
case EINTR:
|
||||
continue;
|
||||
case EAGAIN:
|
||||
TRACE_DBG("SCST_USER_REPLY_AND_GET_CMD returned "
|
||||
@@ -815,9 +815,9 @@ again_poll:
|
||||
case ESRCH:
|
||||
case EBUSY:
|
||||
case EAGAIN:
|
||||
case EINTR:
|
||||
TRACE_MGMT_DBG("poll() returned %d "
|
||||
"(%s)", res, strerror(res));
|
||||
case EINTR:
|
||||
goto again_poll;
|
||||
default:
|
||||
PRINT_ERROR("poll() failed: %s", strerror(res));
|
||||
|
||||
@@ -129,6 +129,8 @@ do { \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TRACE_DBG_SPECIAL(args...) TRACE(TRACE_DEBUG|TRACE_SPECIAL, args)
|
||||
|
||||
#define TRACE_MGMT_DBG(format, args...) \
|
||||
do { \
|
||||
if (trace_flag & TRACE_MGMT_DEBUG) \
|
||||
@@ -246,6 +248,7 @@ do { \
|
||||
|
||||
#define TRACE_MEM(format, args...) {}
|
||||
#define TRACE_DBG(format, args...) {}
|
||||
#define TRACE_DBG_SPECIAL(args...) {}
|
||||
#define TRACE_MGMT_DBG(format, args...) {}
|
||||
#define TRACE_BUFFER(message, buff, len) {}
|
||||
#define TRACE_BUFF_FLAG(flag, message, buff, len) {}
|
||||
|
||||
+91
-6
@@ -26,7 +26,7 @@
|
||||
#include <getopt.h>
|
||||
#include <malloc.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/poll.h>
|
||||
@@ -69,7 +69,9 @@ unsigned long trace_flag = DEFAULT_LOG_FLAGS;
|
||||
#define VERSION_STR "1.0.1"
|
||||
#define THREADS 7
|
||||
|
||||
struct vdisk_dev dev;
|
||||
int vdisk_ID;
|
||||
int flush_interval;
|
||||
|
||||
static struct option const long_options[] =
|
||||
{
|
||||
@@ -85,6 +87,8 @@ static struct option const long_options[] =
|
||||
{"mem_reuse", required_argument, 0, 'm'},
|
||||
{"non_blocking", no_argument, 0, 'l'},
|
||||
{"vdisk_id", required_argument, 0, 'I'},
|
||||
{"flush", required_argument, 0, 'F'},
|
||||
{"unreg_before_close", no_argument, 0, 'u'},
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
{"debug", required_argument, 0, 'd'},
|
||||
#endif
|
||||
@@ -115,6 +119,8 @@ static void usage(void)
|
||||
"(default), \"read\", \"write\" or \"none\"\n");
|
||||
printf(" -l, --non_blocking Use non-blocking operations\n");
|
||||
printf(" -I, --vdisk_id=ID Vdisk ID (used in multi-targets setups)\n");
|
||||
printf(" -F, --flush=n Flush SGV cache each n seconds\n");
|
||||
printf(" -u, --unreg_before_close Unregister before close\n");
|
||||
#if defined(DEBUG) || defined(TRACING)
|
||||
printf(" -d, --debug=level Debug tracing level\n");
|
||||
#endif
|
||||
@@ -154,6 +160,36 @@ static void *align_alloc(size_t size)
|
||||
return memalign(PAGE_SIZE, size);
|
||||
}
|
||||
|
||||
void sigalrm_handler(int signo)
|
||||
{
|
||||
int res;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
TRACE_DBG("%s", "Flushing cache...");
|
||||
|
||||
res = ioctl(dev.scst_usr_fd, SCST_USER_FLUSH_CACHE, NULL);
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("Unable to flush cache: %s",
|
||||
strerror(res));
|
||||
goto out;
|
||||
}
|
||||
|
||||
TRACE_DBG("%s", "Flushing cache done.");
|
||||
|
||||
res = alarm(flush_interval);
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("alarm() failed: %s", strerror(res));
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -165,7 +201,7 @@ int main(int argc, char **argv)
|
||||
int memory_reuse_type = SCST_USER_MEM_REUSE_ALL;
|
||||
int threads = THREADS;
|
||||
struct scst_user_dev_desc desc;
|
||||
struct vdisk_dev dev;
|
||||
int unreg_before_close = 0;
|
||||
|
||||
setlinebuf(stdout);
|
||||
|
||||
@@ -181,7 +217,7 @@ int main(int argc, char **argv)
|
||||
dev.type = TYPE_DISK;
|
||||
dev.alloc_fn = align_alloc;
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "+b:e:tronglI:cp:f:m:d:vh", long_options,
|
||||
while ((ch = getopt_long(argc, argv, "+b:e:trongluF:I:cp:f:m:d:vh", long_options,
|
||||
&longindex)) >= 0) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
@@ -254,6 +290,17 @@ int main(int argc, char **argv)
|
||||
case 'I':
|
||||
vdisk_ID = strtol(optarg, (char **)NULL, 0);
|
||||
break;
|
||||
case 'F':
|
||||
flush_interval = strtol(optarg, (char **)NULL, 0);
|
||||
if (flush_interval < 0) {
|
||||
PRINT_ERROR("Wrong flush interval %d",
|
||||
flush_interval);
|
||||
flush_interval = 0;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
unreg_before_close = 1;
|
||||
break;
|
||||
#if defined(DEBUG_TM_IGNORE) || defined(DEBUG_TM_IGNORE_ALL)
|
||||
case 'g':
|
||||
dev.debug_tm_ignore = 1;
|
||||
@@ -407,7 +454,7 @@ int main(int argc, char **argv)
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("Unable to get options: %s", strerror(res));
|
||||
goto out_close;
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
opt.parse_type = parse_type;
|
||||
@@ -418,7 +465,7 @@ int main(int argc, char **argv)
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("Unable to set options: %s", strerror(res));
|
||||
goto out_close;
|
||||
goto out_unreg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -427,7 +474,7 @@ int main(int argc, char **argv)
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("pthread_mutex_init() failed: %s", strerror(res));
|
||||
goto out_close;
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -445,6 +492,31 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (flush_interval != 0) {
|
||||
struct sigaction act;
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = sigalrm_handler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigemptyset(&act.sa_mask);
|
||||
res = sigaction(SIGALRM, &act, NULL);
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("sigaction() failed: %s",
|
||||
strerror(res));
|
||||
goto join;
|
||||
}
|
||||
|
||||
res = alarm(flush_interval);
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("alarm() failed: %s",
|
||||
strerror(res));
|
||||
goto join;
|
||||
}
|
||||
}
|
||||
|
||||
join:
|
||||
j = i;
|
||||
for(i = 0; i < j; i++) {
|
||||
rc = pthread_join(thread[i], &rc1);
|
||||
@@ -463,6 +535,19 @@ int main(int argc, char **argv)
|
||||
|
||||
pthread_mutex_destroy(&dev.dev_mutex);
|
||||
|
||||
alarm(0);
|
||||
|
||||
out_unreg:
|
||||
if (unreg_before_close) {
|
||||
res = ioctl(dev.scst_usr_fd, SCST_USER_UNREGISTER_DEVICE, NULL);
|
||||
if (res != 0) {
|
||||
res = errno;
|
||||
PRINT_ERROR("Unable to unregister device: %s",
|
||||
strerror(res));
|
||||
/* go through */
|
||||
}
|
||||
}
|
||||
|
||||
out_close:
|
||||
close(dev.scst_usr_fd);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user