rmtfs: Sync rmtfs server with rproc instance

Add sigterm/sigint handlers to enable graceful rmtfs server
bringdown on first instance of SIGINT/SIGTERM. Start/Stop the
remoteproc instance on RMTFS service up and SIGINT/SIGTERM
respectively. Force quit on second instance of SIGINT/SIGTERM.

Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
[bjorn: Pipe for event loop signaling, reworked /sys traversal]
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
Sibi Sankar 2019-04-15 16:21:28 +05:30 committed by Bjorn Andersson
parent 42edb9c07a
commit 976aa0ddbe
4 changed files with 204 additions and 16 deletions

View File

@ -1,10 +1,10 @@
OUT := rmtfs
CFLAGS += -Wall -g -O2
LDFLAGS += -lqrtr -ludev
LDFLAGS += -lqrtr -ludev -lpthread
prefix = /usr/local
SRCS := qmi_rmtfs.c rmtfs.c sharedmem.c storage.c util.c
SRCS := qmi_rmtfs.c rmtfs.c rproc.c sharedmem.c storage.c util.c
OBJS := $(SRCS:.c=.o)
$(OUT): $(OBJS)

69
rmtfs.c
View File

@ -2,14 +2,18 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libqrtr.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -22,6 +26,7 @@
#define RMTFS_QMI_INSTANCE 0
static struct rmtfs_mem *rmem;
static sig_atomic_t sig_int_count;
static bool dbgprintf_enabled;
static void dbgprintf(const char *fmt, ...)
@ -410,9 +415,15 @@ static int handle_rmtfs(int sock)
return ret;
}
static int run_rmtfs(void)
static int sig_int_count;
static int run_rmtfs(int rprocfd)
{
bool sig_int_handled = false;
int rmtfs_fd;
fd_set rfds;
char done;
int nfds;
int ret;
rmtfs_fd = qrtr_open(RMTFS_QMI_SERVICE);
@ -430,32 +441,63 @@ static int run_rmtfs(void)
return ret;
}
if (rprocfd >= 0)
rproc_start();
for (;;) {
ret = qrtr_poll(rmtfs_fd, -1);
if (rprocfd >= 0 && sig_int_count == 1 && !sig_int_handled) {
rproc_stop();
sig_int_handled = true;
} else if (sig_int_count > 1) {
break;
}
FD_ZERO(&rfds);
FD_SET(rmtfs_fd, &rfds);
if (rprocfd >= 0)
FD_SET(rprocfd, &rfds);
nfds = MAX(rmtfs_fd, rprocfd) + 1;
ret = select(nfds, &rfds, NULL, NULL, NULL);
if (ret < 0 && errno != EINTR)
break;
else if (ret < 0 && errno == EINTR)
continue;
if (rprocfd >= 0 && FD_ISSET(rprocfd, &rfds)) {
ret = read(rprocfd, &done, 1);
if (!ret || done == 'Y')
break;
}
if (FD_ISSET(rmtfs_fd, &rfds)) {
ret = handle_rmtfs(rmtfs_fd);
if (ret == -ENETRESET)
break;
}
}
close(rmtfs_fd);
return ret;
}
static void sig_int_handler(int signo)
{
sig_int_count++;
}
int main(int argc, char **argv)
{
struct sigaction action;
bool use_partitions = false;
bool read_only = false;
int rprocfd = -1;
int ret;
int option;
const char *storage_root = NULL;
while ((option = getopt(argc, argv, "o:Prv")) != -1) {
while ((option = getopt(argc, argv, "o:Prsv")) != -1) {
switch (option) {
/* -o sets the directory where EFS images are stored. */
case 'o':
@ -472,6 +514,11 @@ int main(int argc, char **argv)
read_only = true;
break;
/* enable sync for the mss rproc instance */
case 's':
rprocfd = rproc_init();
break;
/* -v is for verbose */
case 'v':
dbgprintf_enabled = 1;
@ -483,6 +530,13 @@ int main(int argc, char **argv)
}
}
sigemptyset(&action.sa_mask);
action.sa_handler = sig_int_handler;
action.sa_flags = 0;
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
rmem = rmtfs_mem_open();
if (!rmem)
return 1;
@ -493,15 +547,8 @@ int main(int argc, char **argv)
goto close_rmtfs_mem;
}
for (;;) {
ret = run_rmtfs();
if (ret <= 0 && ret != -ENETRESET)
break;
}
do {
ret = run_rmtfs();
ret = run_rmtfs(rprocfd);
} while (ret == -ENETRESET);
storage_exit();

View File

@ -35,4 +35,8 @@ void storage_exit(void);
ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset);
ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset);
int rproc_init(void);
int rproc_start(void);
int rproc_stop(void);
#endif

137
rproc.c Normal file
View File

@ -0,0 +1,137 @@
#include <sys/syscall.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include "rmtfs.h"
#define RPROC_BASE_PATH "/sys/bus/platform/drivers/qcom-q6v5-mss/"
static pthread_t start_thread;
static pthread_t stop_thread;
static int rproc_state_fd;
static int rproc_pipe[2];
int rproc_init(void)
{
struct dirent *device_de;
struct dirent *rproc_de;
int rproc_base_fd;
DIR *rproc_dir;
DIR *base_dir;
int device_fd;
int rproc_fd;
int base_fd;
int ret;
rproc_state_fd = -1;
base_fd = open(RPROC_BASE_PATH, O_RDONLY | O_DIRECTORY);
if (base_fd < 0)
return -1;
base_dir = fdopendir(base_fd);
if (!base_dir) {
fprintf(stderr, "failed to open mss driver path\n");
close(base_fd);
return -1;
}
while (rproc_state_fd < 0 && (device_de = readdir(base_dir)) != NULL) {
if (!strcmp(device_de->d_name, ".") ||
!strcmp(device_de->d_name, ".."))
continue;
device_fd = openat(base_fd, device_de->d_name, O_RDONLY | O_DIRECTORY);
if (device_fd < 0)
continue;
rproc_base_fd = openat(device_fd, "remoteproc", O_RDONLY | O_DIRECTORY);
if (rproc_base_fd < 0) {
close(device_fd);
continue;
}
rproc_dir = fdopendir(rproc_base_fd);
while (rproc_state_fd < 0 && (rproc_de = readdir(rproc_dir)) != NULL) {
if (!strcmp(rproc_de->d_name, ".") ||
!strcmp(rproc_de->d_name, ".."))
continue;
rproc_fd = openat(rproc_base_fd, rproc_de->d_name, O_RDONLY | O_DIRECTORY);
if (rproc_fd < 0)
continue;
rproc_state_fd = openat(rproc_fd, "state", O_WRONLY);
if (rproc_state_fd < 0) {
fprintf(stderr,
"unable to open remoteproc \"state\" control file of %s\n",
device_de->d_name);
}
close(rproc_fd);
}
closedir(rproc_dir);
close(rproc_base_fd);
close(device_fd);
}
closedir(base_dir);
close(base_fd);
if (rproc_state_fd < 0)
return -1;
ret = pipe(rproc_pipe);
if (ret < 0) {
close(rproc_state_fd);
return -1;
}
return rproc_pipe[0];
}
static void *do_rproc_start(void *unused)
{
ssize_t ret;
ret = pwrite(rproc_state_fd, "start", 5, 0);
if (ret < 4)
fprintf(stderr, "failed to update start state\n");
return NULL;
}
int rproc_start()
{
return pthread_create(&start_thread, NULL, do_rproc_start, NULL);
}
static void *do_rproc_stop(void *unused)
{
ssize_t ret;
ret = pwrite(rproc_state_fd, "stop", 4, 0);
if (ret < 4)
fprintf(stderr, "failed to update stop state\n");
ret = write(rproc_pipe[1], "Y", 1);
if (ret != 1) {
fprintf(stderr, "failed to signal event loop about exit\n");
exit(0);
}
return NULL;
}
int rproc_stop(void)
{
return pthread_create(&stop_thread, NULL, do_rproc_stop, NULL);
}