mirror of
https://github.com/linux-msm/rmtfs.git
synced 2026-01-24 12:15:21 +01:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14cb1ee69f | ||
|
|
f9847a777c | ||
|
|
f7566e4c82 | ||
|
|
27b3a6f00f | ||
|
|
2ee01bf752 | ||
|
|
586372e575 | ||
|
|
19d1acb728 | ||
|
|
44facf5694 | ||
|
|
5b214f61b9 | ||
|
|
b61c22b1cd | ||
|
|
b46235296f | ||
|
|
f24570816b | ||
|
|
33e1e40615 | ||
|
|
a2df4bd096 | ||
|
|
e4e6212c86 | ||
|
|
44fcb2ec64 | ||
|
|
0caf528637 | ||
|
|
cc5d4df973 | ||
|
|
75cb81d197 | ||
|
|
7a5ae7e0a5 | ||
|
|
695d0668ff | ||
|
|
b08ef6f98e | ||
|
|
293ab8babb | ||
|
|
1cc12d3dc1 | ||
|
|
bf5cb9faf2 | ||
|
|
30f5dfb890 | ||
|
|
8a1d24a704 | ||
|
|
3449744146 | ||
|
|
710e6cf908 | ||
|
|
417f04a9a7 | ||
|
|
0d00985e5e | ||
|
|
5b1471efa8 | ||
|
|
ad5f456c18 | ||
|
|
9ef260ba6f | ||
|
|
dfb8f3ed1c | ||
|
|
29eb4a5b06 | ||
|
|
df6c19d033 | ||
|
|
6d2cfcddfc | ||
|
|
976aa0ddbe | ||
|
|
42edb9c07a | ||
|
|
c35633ab23 | ||
|
|
e6d703b3c8 | ||
|
|
152b96981e | ||
|
|
886608484b | ||
|
|
cfb76ff6ee | ||
|
|
08d20f1646 | ||
|
|
0d3c49ec5a | ||
|
|
b3ea7fdf7b | ||
|
|
577aedad06 | ||
|
|
5eb67a1fb5 | ||
|
|
a75ad5dc2a | ||
|
|
0f800fa433 | ||
|
|
96a272bccb | ||
|
|
cff3f619d5 | ||
|
|
42ed7b4e4c | ||
|
|
db86a3b1a5 | ||
|
|
343817e402 | ||
|
|
91f765efa8 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
rmtfs
|
rmtfs
|
||||||
*.o
|
*.o
|
||||||
|
rmtfs.service
|
||||||
|
|||||||
13
Android.bp
Normal file
13
Android.bp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
cc_binary {
|
||||||
|
name: "rmtfs",
|
||||||
|
vendor: true,
|
||||||
|
srcs: [
|
||||||
|
"qmi_rmtfs.c",
|
||||||
|
"rmtfs.c",
|
||||||
|
"rproc.c",
|
||||||
|
"sharedmem.c",
|
||||||
|
"storage.c",
|
||||||
|
"util.c",
|
||||||
|
],
|
||||||
|
shared_libs: ["libqrtr"],
|
||||||
|
}
|
||||||
26
Makefile
26
Makefile
@@ -1,21 +1,31 @@
|
|||||||
OUT := rmtfs
|
OUT := rmtfs
|
||||||
|
|
||||||
CFLAGS := -Wall -g -I../qrtr/lib -O2
|
CFLAGS += -Wall -g -O2
|
||||||
LDFLAGS := -L../qrtr -lqrtr -ludev
|
LDFLAGS += -lqrtr -ludev -lpthread
|
||||||
prefix := /usr/local
|
prefix = /usr/local
|
||||||
|
bindir := $(prefix)/bin
|
||||||
|
servicedir := $(prefix)/lib/systemd/system
|
||||||
|
|
||||||
SRCS := qmi_rmtfs.c qmi_tlv.c rmtfs.c sharedmem.c storage.c util.c
|
RMTFS_EFS_PATH ?= /var/lib/rmtfs
|
||||||
|
|
||||||
|
SRCS := qmi_rmtfs.c rmtfs.c rproc.c sharedmem.c storage.c util.c
|
||||||
OBJS := $(SRCS:.c=.o)
|
OBJS := $(SRCS:.c=.o)
|
||||||
|
|
||||||
$(OUT): $(OBJS)
|
$(OUT): $(OBJS)
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
%.c: %.qmi
|
%.c: %.qmi
|
||||||
qmic < $<
|
qmic -k < $<
|
||||||
|
|
||||||
install: $(OUT)
|
%.service: %.service.in
|
||||||
install -D -m 755 $< $(DESTDIR)$(prefix)/bin/$<
|
@sed -e 's+RMTFS_PATH+$(bindir)+g' -e 's+RMTFS_EFS_PATH+$(RMTFS_EFS_PATH)+g' $< > $@
|
||||||
|
|
||||||
|
install: $(OUT) rmtfs.service rmtfs-dir.service
|
||||||
|
@install -D -m 755 $(OUT) $(DESTDIR)$(prefix)/bin/$(OUT)
|
||||||
|
@install -D -m 644 rmtfs.service $(DESTDIR)$(servicedir)/rmtfs.service
|
||||||
|
@install -D -m 644 rmtfs-dir.service $(DESTDIR)$(servicedir)/rmtfs-dir.service
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OUT) $(OBJS)
|
rm -f $(OUT) $(OBJS) rmtfs.service
|
||||||
|
rm -f $(OUT) $(OBJS) rmtfs-dir.service
|
||||||
|
|
||||||
|
|||||||
846
qmi_rmtfs.c
846
qmi_rmtfs.c
@@ -2,599 +2,255 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "qmi_rmtfs.h"
|
#include "qmi_rmtfs.h"
|
||||||
|
|
||||||
struct rmtfs_open_req *rmtfs_open_req_alloc(unsigned txn)
|
struct qmi_elem_info rmtfs_qmi_result_ei[] = {
|
||||||
{
|
{
|
||||||
return (struct rmtfs_open_req*)qmi_tlv_init(txn, 1, 0);
|
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||||
}
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(uint16_t),
|
||||||
struct rmtfs_open_req *rmtfs_open_req_parse(void *buf, size_t len, unsigned *txn)
|
.offset = offsetof(struct rmtfs_qmi_result, result),
|
||||||
{
|
},
|
||||||
return (struct rmtfs_open_req*)qmi_tlv_decode(buf, len, txn, 0);
|
{
|
||||||
}
|
.data_type = QMI_UNSIGNED_2_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
void *rmtfs_open_req_encode(struct rmtfs_open_req *open_req, size_t *len)
|
.elem_size = sizeof(uint16_t),
|
||||||
{
|
.offset = offsetof(struct rmtfs_qmi_result, error),
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)open_req, len);
|
},
|
||||||
}
|
{}
|
||||||
|
};
|
||||||
void rmtfs_open_req_free(struct rmtfs_open_req *open_req)
|
|
||||||
{
|
struct qmi_elem_info rmtfs_iovec_entry_ei[] = {
|
||||||
qmi_tlv_free((struct qmi_tlv*)open_req);
|
{
|
||||||
}
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
int rmtfs_open_req_set_path(struct rmtfs_open_req *open_req, char *buf, size_t len)
|
.elem_size = sizeof(uint32_t),
|
||||||
{
|
.offset = offsetof(struct rmtfs_iovec_entry, sector_addr),
|
||||||
return qmi_tlv_set((struct qmi_tlv*)open_req, 1, buf, len);
|
},
|
||||||
}
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
int rmtfs_open_req_get_path(struct rmtfs_open_req *open_req, char *buf, size_t buflen)
|
.elem_len = 1,
|
||||||
{
|
.elem_size = sizeof(uint32_t),
|
||||||
size_t len;
|
.offset = offsetof(struct rmtfs_iovec_entry, phys_offset),
|
||||||
char *ptr;
|
},
|
||||||
|
{
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)open_req, 1, &len);
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
if (!ptr)
|
.elem_len = 1,
|
||||||
return -ENOENT;
|
.elem_size = sizeof(uint32_t),
|
||||||
|
.offset = offsetof(struct rmtfs_iovec_entry, num_sector),
|
||||||
if (len >= buflen)
|
},
|
||||||
return -ENOMEM;
|
{}
|
||||||
|
};
|
||||||
memcpy(buf, ptr, len);
|
|
||||||
buf[len] = '\0';
|
struct qmi_elem_info rmtfs_open_req_ei[] = {
|
||||||
return len;
|
{
|
||||||
}
|
.data_type = QMI_STRING,
|
||||||
|
.elem_len = 256,
|
||||||
struct rmtfs_open_resp *rmtfs_open_resp_alloc(unsigned txn)
|
.elem_size = sizeof(char),
|
||||||
{
|
.array_type = VAR_LEN_ARRAY,
|
||||||
return (struct rmtfs_open_resp*)qmi_tlv_init(txn, 1, 2);
|
.tlv_type = 1,
|
||||||
}
|
.offset = offsetof(struct rmtfs_open_req, path)
|
||||||
|
},
|
||||||
struct rmtfs_open_resp *rmtfs_open_resp_parse(void *buf, size_t len, unsigned *txn)
|
{}
|
||||||
{
|
};
|
||||||
return (struct rmtfs_open_resp*)qmi_tlv_decode(buf, len, txn, 2);
|
|
||||||
}
|
struct qmi_elem_info rmtfs_open_resp_ei[] = {
|
||||||
|
{
|
||||||
void *rmtfs_open_resp_encode(struct rmtfs_open_resp *open_resp, size_t *len)
|
.data_type = QMI_STRUCT,
|
||||||
{
|
.elem_len = 1,
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)open_resp, len);
|
.elem_size = sizeof(struct rmtfs_qmi_result),
|
||||||
}
|
.tlv_type = 2,
|
||||||
|
.offset = offsetof(struct rmtfs_open_resp, result),
|
||||||
void rmtfs_open_resp_free(struct rmtfs_open_resp *open_resp)
|
.ei_array = rmtfs_qmi_result_ei,
|
||||||
{
|
},
|
||||||
qmi_tlv_free((struct qmi_tlv*)open_resp);
|
{
|
||||||
}
|
.data_type = QMI_OPT_FLAG,
|
||||||
|
.elem_len = 1,
|
||||||
int rmtfs_open_resp_set_result(struct rmtfs_open_resp *open_resp, struct rmtfs_qmi_result *val)
|
.elem_size = sizeof(bool),
|
||||||
{
|
.tlv_type = 16,
|
||||||
return qmi_tlv_set((struct qmi_tlv*)open_resp, 2, val, sizeof(struct rmtfs_qmi_result));
|
.offset = offsetof(struct rmtfs_open_resp, caller_id_valid),
|
||||||
}
|
},
|
||||||
|
{
|
||||||
struct rmtfs_qmi_result *rmtfs_open_resp_get_result(struct rmtfs_open_resp *open_resp)
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
{
|
.elem_len = 1,
|
||||||
size_t len;
|
.elem_size = sizeof(uint32_t),
|
||||||
void *ptr;
|
.tlv_type = 16,
|
||||||
|
.offset = offsetof(struct rmtfs_open_resp, caller_id),
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)open_resp, 2, &len);
|
},
|
||||||
if (!ptr)
|
{}
|
||||||
return NULL;
|
};
|
||||||
|
|
||||||
if (len != sizeof(struct rmtfs_qmi_result))
|
struct qmi_elem_info rmtfs_close_req_ei[] = {
|
||||||
return NULL;
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
return ptr;
|
.elem_len = 1,
|
||||||
}
|
.elem_size = sizeof(uint32_t),
|
||||||
|
.tlv_type = 1,
|
||||||
int rmtfs_open_resp_set_caller_id(struct rmtfs_open_resp *open_resp, uint32_t val)
|
.offset = offsetof(struct rmtfs_close_req, caller_id),
|
||||||
{
|
},
|
||||||
return qmi_tlv_set((struct qmi_tlv*)open_resp, 16, &val, sizeof(uint32_t));
|
{}
|
||||||
}
|
};
|
||||||
|
|
||||||
int rmtfs_open_resp_get_caller_id(struct rmtfs_open_resp *open_resp, uint32_t *val)
|
struct qmi_elem_info rmtfs_close_resp_ei[] = {
|
||||||
{
|
{
|
||||||
uint32_t *ptr;
|
.data_type = QMI_STRUCT,
|
||||||
size_t len;
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(struct rmtfs_qmi_result),
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)open_resp, 16, &len);
|
.tlv_type = 2,
|
||||||
if (!ptr)
|
.offset = offsetof(struct rmtfs_close_resp, result),
|
||||||
return -ENOENT;
|
.ei_array = rmtfs_qmi_result_ei,
|
||||||
|
},
|
||||||
if (len != sizeof(uint32_t))
|
{}
|
||||||
return -EINVAL;
|
};
|
||||||
|
|
||||||
*val = *(uint32_t*)ptr;
|
struct qmi_elem_info rmtfs_iovec_req_ei[] = {
|
||||||
return 0;
|
{
|
||||||
}
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
struct rmtfs_close_req *rmtfs_close_req_alloc(unsigned txn)
|
.elem_size = sizeof(uint32_t),
|
||||||
{
|
.tlv_type = 1,
|
||||||
return (struct rmtfs_close_req*)qmi_tlv_init(txn, 2, 0);
|
.offset = offsetof(struct rmtfs_iovec_req, caller_id),
|
||||||
}
|
},
|
||||||
|
{
|
||||||
struct rmtfs_close_req *rmtfs_close_req_parse(void *buf, size_t len, unsigned *txn)
|
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||||
{
|
.elem_len = 1,
|
||||||
return (struct rmtfs_close_req*)qmi_tlv_decode(buf, len, txn, 0);
|
.elem_size = sizeof(uint8_t),
|
||||||
}
|
.tlv_type = 2,
|
||||||
|
.offset = offsetof(struct rmtfs_iovec_req, direction),
|
||||||
void *rmtfs_close_req_encode(struct rmtfs_close_req *close_req, size_t *len)
|
},
|
||||||
{
|
{
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)close_req, len);
|
.data_type = QMI_DATA_LEN,
|
||||||
}
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(uint8_t),
|
||||||
void rmtfs_close_req_free(struct rmtfs_close_req *close_req)
|
.tlv_type = 3,
|
||||||
{
|
.offset = offsetof(struct rmtfs_iovec_req, iovec_len),
|
||||||
qmi_tlv_free((struct qmi_tlv*)close_req);
|
},
|
||||||
}
|
{
|
||||||
|
.data_type = QMI_STRUCT,
|
||||||
int rmtfs_close_req_set_caller_id(struct rmtfs_close_req *close_req, uint32_t val)
|
.elem_len = 255,
|
||||||
{
|
.elem_size = sizeof(struct rmtfs_iovec_entry),
|
||||||
return qmi_tlv_set((struct qmi_tlv*)close_req, 1, &val, sizeof(uint32_t));
|
.array_type = VAR_LEN_ARRAY,
|
||||||
}
|
.tlv_type = 3,
|
||||||
|
.offset = offsetof(struct rmtfs_iovec_req, iovec),
|
||||||
int rmtfs_close_req_get_caller_id(struct rmtfs_close_req *close_req, uint32_t *val)
|
.ei_array = rmtfs_iovec_entry_ei,
|
||||||
{
|
},
|
||||||
uint32_t *ptr;
|
{
|
||||||
size_t len;
|
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)close_req, 1, &len);
|
.elem_size = sizeof(uint8_t),
|
||||||
if (!ptr)
|
.tlv_type = 4,
|
||||||
return -ENOENT;
|
.offset = offsetof(struct rmtfs_iovec_req, is_force_sync),
|
||||||
|
},
|
||||||
if (len != sizeof(uint32_t))
|
{}
|
||||||
return -EINVAL;
|
};
|
||||||
|
|
||||||
*val = *(uint32_t*)ptr;
|
struct qmi_elem_info rmtfs_iovec_resp_ei[] = {
|
||||||
return 0;
|
{
|
||||||
}
|
.data_type = QMI_STRUCT,
|
||||||
|
.elem_len = 1,
|
||||||
struct rmtfs_close_resp *rmtfs_close_resp_alloc(unsigned txn)
|
.elem_size = sizeof(struct rmtfs_qmi_result),
|
||||||
{
|
.tlv_type = 2,
|
||||||
return (struct rmtfs_close_resp*)qmi_tlv_init(txn, 2, 2);
|
.offset = offsetof(struct rmtfs_iovec_resp, result),
|
||||||
}
|
.ei_array = rmtfs_qmi_result_ei,
|
||||||
|
},
|
||||||
struct rmtfs_close_resp *rmtfs_close_resp_parse(void *buf, size_t len, unsigned *txn)
|
{}
|
||||||
{
|
};
|
||||||
return (struct rmtfs_close_resp*)qmi_tlv_decode(buf, len, txn, 2);
|
|
||||||
}
|
struct qmi_elem_info rmtfs_alloc_buf_req_ei[] = {
|
||||||
|
{
|
||||||
void *rmtfs_close_resp_encode(struct rmtfs_close_resp *close_resp, size_t *len)
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
{
|
.elem_len = 1,
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)close_resp, len);
|
.elem_size = sizeof(uint32_t),
|
||||||
}
|
.tlv_type = 1,
|
||||||
|
.offset = offsetof(struct rmtfs_alloc_buf_req, caller_id),
|
||||||
void rmtfs_close_resp_free(struct rmtfs_close_resp *close_resp)
|
},
|
||||||
{
|
{
|
||||||
qmi_tlv_free((struct qmi_tlv*)close_resp);
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
}
|
.elem_len = 1,
|
||||||
|
.elem_size = sizeof(uint32_t),
|
||||||
int rmtfs_close_resp_set_result(struct rmtfs_close_resp *close_resp, struct rmtfs_qmi_result *val)
|
.tlv_type = 2,
|
||||||
{
|
.offset = offsetof(struct rmtfs_alloc_buf_req, buff_size),
|
||||||
return qmi_tlv_set((struct qmi_tlv*)close_resp, 2, val, sizeof(struct rmtfs_qmi_result));
|
},
|
||||||
}
|
{}
|
||||||
|
};
|
||||||
struct rmtfs_qmi_result *rmtfs_close_resp_get_result(struct rmtfs_close_resp *close_resp)
|
|
||||||
{
|
struct qmi_elem_info rmtfs_alloc_buf_resp_ei[] = {
|
||||||
size_t len;
|
{
|
||||||
void *ptr;
|
.data_type = QMI_STRUCT,
|
||||||
|
.elem_len = 1,
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)close_resp, 2, &len);
|
.elem_size = sizeof(struct rmtfs_qmi_result),
|
||||||
if (!ptr)
|
.tlv_type = 2,
|
||||||
return NULL;
|
.offset = offsetof(struct rmtfs_alloc_buf_resp, result),
|
||||||
|
.ei_array = rmtfs_qmi_result_ei,
|
||||||
if (len != sizeof(struct rmtfs_qmi_result))
|
},
|
||||||
return NULL;
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
return ptr;
|
.elem_len = 1,
|
||||||
}
|
.elem_size = sizeof(bool),
|
||||||
|
.tlv_type = 16,
|
||||||
struct rmtfs_iovec_req *rmtfs_iovec_req_alloc(unsigned txn)
|
.offset = offsetof(struct rmtfs_alloc_buf_resp, buff_address_valid),
|
||||||
{
|
},
|
||||||
return (struct rmtfs_iovec_req*)qmi_tlv_init(txn, 3, 0);
|
{
|
||||||
}
|
.data_type = QMI_UNSIGNED_8_BYTE,
|
||||||
|
.elem_len = 1,
|
||||||
struct rmtfs_iovec_req *rmtfs_iovec_req_parse(void *buf, size_t len, unsigned *txn)
|
.elem_size = sizeof(uint64_t),
|
||||||
{
|
.tlv_type = 16,
|
||||||
return (struct rmtfs_iovec_req*)qmi_tlv_decode(buf, len, txn, 0);
|
.offset = offsetof(struct rmtfs_alloc_buf_resp, buff_address),
|
||||||
}
|
},
|
||||||
|
{}
|
||||||
void *rmtfs_iovec_req_encode(struct rmtfs_iovec_req *iovec_req, size_t *len)
|
};
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)iovec_req, len);
|
struct qmi_elem_info rmtfs_dev_error_req_ei[] = {
|
||||||
}
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_4_BYTE,
|
||||||
void rmtfs_iovec_req_free(struct rmtfs_iovec_req *iovec_req)
|
.elem_len = 1,
|
||||||
{
|
.elem_size = sizeof(uint32_t),
|
||||||
qmi_tlv_free((struct qmi_tlv*)iovec_req);
|
.tlv_type = 1,
|
||||||
}
|
.offset = offsetof(struct rmtfs_dev_error_req, caller_id),
|
||||||
|
},
|
||||||
int rmtfs_iovec_req_set_caller_id(struct rmtfs_iovec_req *iovec_req, uint32_t val)
|
{}
|
||||||
{
|
};
|
||||||
return qmi_tlv_set((struct qmi_tlv*)iovec_req, 1, &val, sizeof(uint32_t));
|
|
||||||
}
|
struct qmi_elem_info rmtfs_dev_error_resp_ei[] = {
|
||||||
|
{
|
||||||
int rmtfs_iovec_req_get_caller_id(struct rmtfs_iovec_req *iovec_req, uint32_t *val)
|
.data_type = QMI_STRUCT,
|
||||||
{
|
.elem_len = 1,
|
||||||
uint32_t *ptr;
|
.elem_size = sizeof(struct rmtfs_qmi_result),
|
||||||
size_t len;
|
.tlv_type = 2,
|
||||||
|
.offset = offsetof(struct rmtfs_dev_error_resp, result),
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)iovec_req, 1, &len);
|
.ei_array = rmtfs_qmi_result_ei,
|
||||||
if (!ptr)
|
},
|
||||||
return -ENOENT;
|
{
|
||||||
|
.data_type = QMI_OPT_FLAG,
|
||||||
if (len != sizeof(uint32_t))
|
.elem_len = 1,
|
||||||
return -EINVAL;
|
.elem_size = sizeof(bool),
|
||||||
|
.tlv_type = 16,
|
||||||
*val = *(uint32_t*)ptr;
|
.offset = offsetof(struct rmtfs_dev_error_resp, status_valid),
|
||||||
return 0;
|
},
|
||||||
}
|
{
|
||||||
|
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||||
int rmtfs_iovec_req_set_direction(struct rmtfs_iovec_req *iovec_req, uint8_t val)
|
.elem_len = 1,
|
||||||
{
|
.elem_size = sizeof(uint8_t),
|
||||||
return qmi_tlv_set((struct qmi_tlv*)iovec_req, 2, &val, sizeof(uint8_t));
|
.tlv_type = 16,
|
||||||
}
|
.offset = offsetof(struct rmtfs_dev_error_resp, status),
|
||||||
|
},
|
||||||
int rmtfs_iovec_req_get_direction(struct rmtfs_iovec_req *iovec_req, uint8_t *val)
|
{}
|
||||||
{
|
};
|
||||||
uint8_t *ptr;
|
|
||||||
size_t len;
|
struct qmi_elem_info rmtfs_force_sync_ei[] = {
|
||||||
|
{
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)iovec_req, 2, &len);
|
.data_type = QMI_DATA_LEN,
|
||||||
if (!ptr)
|
.elem_len = 1,
|
||||||
return -ENOENT;
|
.elem_size = sizeof(uint8_t),
|
||||||
|
.tlv_type = 1,
|
||||||
if (len != sizeof(uint8_t))
|
.offset = offsetof(struct rmtfs_force_sync, caller_id_len),
|
||||||
return -EINVAL;
|
},
|
||||||
|
{
|
||||||
*val = *(uint8_t*)ptr;
|
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||||
return 0;
|
.elem_len = 10,
|
||||||
}
|
.elem_size = sizeof(uint32_t),
|
||||||
|
.array_type = VAR_LEN_ARRAY,
|
||||||
int rmtfs_iovec_req_set_iovec(struct rmtfs_iovec_req *iovec_req, struct rmtfs_iovec_entry *val, size_t count)
|
.tlv_type = 1,
|
||||||
{
|
.offset = offsetof(struct rmtfs_force_sync, caller_id),
|
||||||
return qmi_tlv_set_array((struct qmi_tlv*)iovec_req, 3, 1, val, count, sizeof(struct rmtfs_iovec_entry));
|
},
|
||||||
}
|
{}
|
||||||
|
};
|
||||||
struct rmtfs_iovec_entry *rmtfs_iovec_req_get_iovec(struct rmtfs_iovec_req *iovec_req, size_t *count)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
size_t len;
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get_array((struct qmi_tlv*)iovec_req, 3, 1, &len, &size);
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (size != sizeof(struct rmtfs_iovec_entry))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = len;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_iovec_req_set_is_force_sync(struct rmtfs_iovec_req *iovec_req, uint8_t val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)iovec_req, 4, &val, sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_iovec_req_get_is_force_sync(struct rmtfs_iovec_req *iovec_req, uint8_t *val)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)iovec_req, 4, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
if (len != sizeof(uint8_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*val = *(uint8_t*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_iovec_resp *rmtfs_iovec_resp_alloc(unsigned txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_iovec_resp*)qmi_tlv_init(txn, 3, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_iovec_resp *rmtfs_iovec_resp_parse(void *buf, size_t len, unsigned *txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_iovec_resp*)qmi_tlv_decode(buf, len, txn, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rmtfs_iovec_resp_encode(struct rmtfs_iovec_resp *iovec_resp, size_t *len)
|
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)iovec_resp, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmtfs_iovec_resp_free(struct rmtfs_iovec_resp *iovec_resp)
|
|
||||||
{
|
|
||||||
qmi_tlv_free((struct qmi_tlv*)iovec_resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_iovec_resp_set_result(struct rmtfs_iovec_resp *iovec_resp, struct rmtfs_qmi_result *val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)iovec_resp, 2, val, sizeof(struct rmtfs_qmi_result));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_qmi_result *rmtfs_iovec_resp_get_result(struct rmtfs_iovec_resp *iovec_resp)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)iovec_resp, 2, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (len != sizeof(struct rmtfs_qmi_result))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_alloc_buf_req *rmtfs_alloc_buf_req_alloc(unsigned txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_alloc_buf_req*)qmi_tlv_init(txn, 4, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_alloc_buf_req *rmtfs_alloc_buf_req_parse(void *buf, size_t len, unsigned *txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_alloc_buf_req*)qmi_tlv_decode(buf, len, txn, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rmtfs_alloc_buf_req_encode(struct rmtfs_alloc_buf_req *alloc_buf_req, size_t *len)
|
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)alloc_buf_req, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmtfs_alloc_buf_req_free(struct rmtfs_alloc_buf_req *alloc_buf_req)
|
|
||||||
{
|
|
||||||
qmi_tlv_free((struct qmi_tlv*)alloc_buf_req);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_req_set_caller_id(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)alloc_buf_req, 1, &val, sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_req_get_caller_id(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t *val)
|
|
||||||
{
|
|
||||||
uint32_t *ptr;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)alloc_buf_req, 1, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
if (len != sizeof(uint32_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*val = *(uint32_t*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_req_set_buff_size(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)alloc_buf_req, 2, &val, sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_req_get_buff_size(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t *val)
|
|
||||||
{
|
|
||||||
uint32_t *ptr;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)alloc_buf_req, 2, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
if (len != sizeof(uint32_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*val = *(uint32_t*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_alloc_buf_resp *rmtfs_alloc_buf_resp_alloc(unsigned txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_alloc_buf_resp*)qmi_tlv_init(txn, 4, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_alloc_buf_resp *rmtfs_alloc_buf_resp_parse(void *buf, size_t len, unsigned *txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_alloc_buf_resp*)qmi_tlv_decode(buf, len, txn, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rmtfs_alloc_buf_resp_encode(struct rmtfs_alloc_buf_resp *alloc_buf_resp, size_t *len)
|
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)alloc_buf_resp, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmtfs_alloc_buf_resp_free(struct rmtfs_alloc_buf_resp *alloc_buf_resp)
|
|
||||||
{
|
|
||||||
qmi_tlv_free((struct qmi_tlv*)alloc_buf_resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_resp_set_result(struct rmtfs_alloc_buf_resp *alloc_buf_resp, struct rmtfs_qmi_result *val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)alloc_buf_resp, 2, val, sizeof(struct rmtfs_qmi_result));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_qmi_result *rmtfs_alloc_buf_resp_get_result(struct rmtfs_alloc_buf_resp *alloc_buf_resp)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)alloc_buf_resp, 2, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (len != sizeof(struct rmtfs_qmi_result))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_resp_set_buff_address(struct rmtfs_alloc_buf_resp *alloc_buf_resp, uint64_t val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)alloc_buf_resp, 16, &val, sizeof(uint64_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_resp_get_buff_address(struct rmtfs_alloc_buf_resp *alloc_buf_resp, uint64_t *val)
|
|
||||||
{
|
|
||||||
uint64_t *ptr;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)alloc_buf_resp, 16, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
if (len != sizeof(uint64_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*val = *(uint64_t*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_dev_error_req *rmtfs_dev_error_req_alloc(unsigned txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_dev_error_req*)qmi_tlv_init(txn, 5, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_dev_error_req *rmtfs_dev_error_req_parse(void *buf, size_t len, unsigned *txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_dev_error_req*)qmi_tlv_decode(buf, len, txn, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rmtfs_dev_error_req_encode(struct rmtfs_dev_error_req *dev_error_req, size_t *len)
|
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)dev_error_req, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmtfs_dev_error_req_free(struct rmtfs_dev_error_req *dev_error_req)
|
|
||||||
{
|
|
||||||
qmi_tlv_free((struct qmi_tlv*)dev_error_req);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_dev_error_req_set_caller_id(struct rmtfs_dev_error_req *dev_error_req, uint32_t val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)dev_error_req, 1, &val, sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_dev_error_req_get_caller_id(struct rmtfs_dev_error_req *dev_error_req, uint32_t *val)
|
|
||||||
{
|
|
||||||
uint32_t *ptr;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)dev_error_req, 1, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
if (len != sizeof(uint32_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*val = *(uint32_t*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_dev_error_resp *rmtfs_dev_error_resp_alloc(unsigned txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_dev_error_resp*)qmi_tlv_init(txn, 5, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_dev_error_resp *rmtfs_dev_error_resp_parse(void *buf, size_t len, unsigned *txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_dev_error_resp*)qmi_tlv_decode(buf, len, txn, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rmtfs_dev_error_resp_encode(struct rmtfs_dev_error_resp *dev_error_resp, size_t *len)
|
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)dev_error_resp, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmtfs_dev_error_resp_free(struct rmtfs_dev_error_resp *dev_error_resp)
|
|
||||||
{
|
|
||||||
qmi_tlv_free((struct qmi_tlv*)dev_error_resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_dev_error_resp_set_result(struct rmtfs_dev_error_resp *dev_error_resp, struct rmtfs_qmi_result *val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)dev_error_resp, 2, val, sizeof(struct rmtfs_qmi_result));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_qmi_result *rmtfs_dev_error_resp_get_result(struct rmtfs_dev_error_resp *dev_error_resp)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)dev_error_resp, 2, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (len != sizeof(struct rmtfs_qmi_result))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_dev_error_resp_set_status(struct rmtfs_dev_error_resp *dev_error_resp, uint8_t val)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set((struct qmi_tlv*)dev_error_resp, 16, &val, sizeof(uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_dev_error_resp_get_status(struct rmtfs_dev_error_resp *dev_error_resp, uint8_t *val)
|
|
||||||
{
|
|
||||||
uint8_t *ptr;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get((struct qmi_tlv*)dev_error_resp, 16, &len);
|
|
||||||
if (!ptr)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
if (len != sizeof(uint8_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
*val = *(uint8_t*)ptr;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_force_sync *rmtfs_force_sync_alloc(unsigned txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_force_sync*)qmi_tlv_init(txn, 6, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rmtfs_force_sync *rmtfs_force_sync_parse(void *buf, size_t len, unsigned *txn)
|
|
||||||
{
|
|
||||||
return (struct rmtfs_force_sync*)qmi_tlv_decode(buf, len, txn, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *rmtfs_force_sync_encode(struct rmtfs_force_sync *force_sync, size_t *len)
|
|
||||||
{
|
|
||||||
return qmi_tlv_encode((struct qmi_tlv*)force_sync, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rmtfs_force_sync_free(struct rmtfs_force_sync *force_sync)
|
|
||||||
{
|
|
||||||
qmi_tlv_free((struct qmi_tlv*)force_sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rmtfs_force_sync_set_caller_id(struct rmtfs_force_sync *force_sync, uint32_t *val, size_t count)
|
|
||||||
{
|
|
||||||
return qmi_tlv_set_array((struct qmi_tlv*)force_sync, 1, 1, val, count, sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t *rmtfs_force_sync_get_caller_id(struct rmtfs_force_sync *force_sync, size_t *count)
|
|
||||||
{
|
|
||||||
uint32_t *ptr;
|
|
||||||
size_t size;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
ptr = qmi_tlv_get_array((struct qmi_tlv*)force_sync, 1, 1, &len, &size);
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (size != sizeof(uint32_t))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
*count = len;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
213
qmi_rmtfs.h
213
qmi_rmtfs.h
@@ -2,19 +2,9 @@
|
|||||||
#define __QMI_RMTFS_H__
|
#define __QMI_RMTFS_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct qmi_tlv;
|
#include "libqrtr.h"
|
||||||
|
|
||||||
struct qmi_tlv *qmi_tlv_init(unsigned txn, unsigned msg_id, unsigned type);
|
|
||||||
struct qmi_tlv *qmi_tlv_decode(void *buf, size_t len, unsigned *txn, unsigned type);
|
|
||||||
void *qmi_tlv_encode(struct qmi_tlv *tlv, size_t *len);
|
|
||||||
void qmi_tlv_free(struct qmi_tlv *tlv);
|
|
||||||
|
|
||||||
void *qmi_tlv_get(struct qmi_tlv *tlv, unsigned id, size_t *len);
|
|
||||||
void *qmi_tlv_get_array(struct qmi_tlv *tlv, unsigned id, unsigned len_size, size_t *len, size_t *size);
|
|
||||||
int qmi_tlv_set(struct qmi_tlv *tlv, unsigned id, void *buf, size_t len);
|
|
||||||
int qmi_tlv_set_array(struct qmi_tlv *tlv, unsigned id, unsigned len_size, void *buf, size_t len, size_t size);
|
|
||||||
|
|
||||||
#define QMI_RMTFS_RESULT_SUCCESS 0
|
#define QMI_RMTFS_RESULT_SUCCESS 0
|
||||||
#define QMI_RMTFS_RESULT_FAILURE 1
|
#define QMI_RMTFS_RESULT_FAILURE 1
|
||||||
@@ -39,158 +29,73 @@ struct rmtfs_iovec_entry {
|
|||||||
uint32_t num_sector;
|
uint32_t num_sector;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rmtfs_open_req;
|
struct rmtfs_open_req {
|
||||||
struct rmtfs_open_resp;
|
uint32_t path_len;
|
||||||
struct rmtfs_close_req;
|
char path[256];
|
||||||
struct rmtfs_close_resp;
|
};
|
||||||
struct rmtfs_iovec_req;
|
|
||||||
struct rmtfs_iovec_resp;
|
|
||||||
struct rmtfs_alloc_buf_req;
|
|
||||||
struct rmtfs_alloc_buf_resp;
|
|
||||||
struct rmtfs_dev_error_req;
|
|
||||||
struct rmtfs_dev_error_resp;
|
|
||||||
struct rmtfs_force_sync;
|
|
||||||
|
|
||||||
/*
|
struct rmtfs_open_resp {
|
||||||
* rmtfs_open_req message
|
struct rmtfs_qmi_result result;
|
||||||
*/
|
bool caller_id_valid;
|
||||||
struct rmtfs_open_req *rmtfs_open_req_alloc(unsigned txn);
|
uint32_t caller_id;
|
||||||
struct rmtfs_open_req *rmtfs_open_req_parse(void *buf, size_t len, unsigned *txn);
|
};
|
||||||
void *rmtfs_open_req_encode(struct rmtfs_open_req *open_req, size_t *len);
|
|
||||||
void rmtfs_open_req_free(struct rmtfs_open_req *open_req);
|
|
||||||
|
|
||||||
int rmtfs_open_req_set_path(struct rmtfs_open_req *open_req, char *buf, size_t len);
|
struct rmtfs_close_req {
|
||||||
int rmtfs_open_req_get_path(struct rmtfs_open_req *open_req, char *buf, size_t buflen);
|
uint32_t caller_id;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
struct rmtfs_close_resp {
|
||||||
* rmtfs_open_resp message
|
struct rmtfs_qmi_result result;
|
||||||
*/
|
};
|
||||||
struct rmtfs_open_resp *rmtfs_open_resp_alloc(unsigned txn);
|
|
||||||
struct rmtfs_open_resp *rmtfs_open_resp_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_open_resp_encode(struct rmtfs_open_resp *open_resp, size_t *len);
|
|
||||||
void rmtfs_open_resp_free(struct rmtfs_open_resp *open_resp);
|
|
||||||
|
|
||||||
int rmtfs_open_resp_set_result(struct rmtfs_open_resp *open_resp, struct rmtfs_qmi_result *val);
|
struct rmtfs_iovec_req {
|
||||||
struct rmtfs_qmi_result *rmtfs_open_resp_get_result(struct rmtfs_open_resp *open_resp);
|
uint32_t caller_id;
|
||||||
|
uint8_t direction;
|
||||||
|
size_t iovec_len;
|
||||||
|
struct rmtfs_iovec_entry iovec[255];
|
||||||
|
uint8_t is_force_sync;
|
||||||
|
};
|
||||||
|
|
||||||
int rmtfs_open_resp_set_caller_id(struct rmtfs_open_resp *open_resp, uint32_t val);
|
struct rmtfs_iovec_resp {
|
||||||
int rmtfs_open_resp_get_caller_id(struct rmtfs_open_resp *open_resp, uint32_t *val);
|
struct rmtfs_qmi_result result;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
struct rmtfs_alloc_buf_req {
|
||||||
* rmtfs_close_req message
|
uint32_t caller_id;
|
||||||
*/
|
uint32_t buff_size;
|
||||||
struct rmtfs_close_req *rmtfs_close_req_alloc(unsigned txn);
|
};
|
||||||
struct rmtfs_close_req *rmtfs_close_req_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_close_req_encode(struct rmtfs_close_req *close_req, size_t *len);
|
|
||||||
void rmtfs_close_req_free(struct rmtfs_close_req *close_req);
|
|
||||||
|
|
||||||
int rmtfs_close_req_set_caller_id(struct rmtfs_close_req *close_req, uint32_t val);
|
struct rmtfs_alloc_buf_resp {
|
||||||
int rmtfs_close_req_get_caller_id(struct rmtfs_close_req *close_req, uint32_t *val);
|
struct rmtfs_qmi_result result;
|
||||||
|
bool buff_address_valid;
|
||||||
|
uint64_t buff_address;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
struct rmtfs_dev_error_req {
|
||||||
* rmtfs_close_resp message
|
uint32_t caller_id;
|
||||||
*/
|
};
|
||||||
struct rmtfs_close_resp *rmtfs_close_resp_alloc(unsigned txn);
|
|
||||||
struct rmtfs_close_resp *rmtfs_close_resp_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_close_resp_encode(struct rmtfs_close_resp *close_resp, size_t *len);
|
|
||||||
void rmtfs_close_resp_free(struct rmtfs_close_resp *close_resp);
|
|
||||||
|
|
||||||
int rmtfs_close_resp_set_result(struct rmtfs_close_resp *close_resp, struct rmtfs_qmi_result *val);
|
struct rmtfs_dev_error_resp {
|
||||||
struct rmtfs_qmi_result *rmtfs_close_resp_get_result(struct rmtfs_close_resp *close_resp);
|
struct rmtfs_qmi_result result;
|
||||||
|
bool status_valid;
|
||||||
|
uint8_t status;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
struct rmtfs_force_sync {
|
||||||
* rmtfs_iovec_req message
|
size_t caller_id_len;
|
||||||
*/
|
uint32_t caller_id[10];
|
||||||
struct rmtfs_iovec_req *rmtfs_iovec_req_alloc(unsigned txn);
|
};
|
||||||
struct rmtfs_iovec_req *rmtfs_iovec_req_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_iovec_req_encode(struct rmtfs_iovec_req *iovec_req, size_t *len);
|
|
||||||
void rmtfs_iovec_req_free(struct rmtfs_iovec_req *iovec_req);
|
|
||||||
|
|
||||||
int rmtfs_iovec_req_set_caller_id(struct rmtfs_iovec_req *iovec_req, uint32_t val);
|
extern struct qmi_elem_info rmtfs_open_req_ei[];
|
||||||
int rmtfs_iovec_req_get_caller_id(struct rmtfs_iovec_req *iovec_req, uint32_t *val);
|
extern struct qmi_elem_info rmtfs_open_resp_ei[];
|
||||||
|
extern struct qmi_elem_info rmtfs_close_req_ei[];
|
||||||
int rmtfs_iovec_req_set_direction(struct rmtfs_iovec_req *iovec_req, uint8_t val);
|
extern struct qmi_elem_info rmtfs_close_resp_ei[];
|
||||||
int rmtfs_iovec_req_get_direction(struct rmtfs_iovec_req *iovec_req, uint8_t *val);
|
extern struct qmi_elem_info rmtfs_iovec_req_ei[];
|
||||||
|
extern struct qmi_elem_info rmtfs_iovec_resp_ei[];
|
||||||
int rmtfs_iovec_req_set_iovec(struct rmtfs_iovec_req *iovec_req, struct rmtfs_iovec_entry *val, size_t count);
|
extern struct qmi_elem_info rmtfs_alloc_buf_req_ei[];
|
||||||
struct rmtfs_iovec_entry *rmtfs_iovec_req_get_iovec(struct rmtfs_iovec_req *iovec_req, size_t *count);
|
extern struct qmi_elem_info rmtfs_alloc_buf_resp_ei[];
|
||||||
|
extern struct qmi_elem_info rmtfs_dev_error_req_ei[];
|
||||||
int rmtfs_iovec_req_set_is_force_sync(struct rmtfs_iovec_req *iovec_req, uint8_t val);
|
extern struct qmi_elem_info rmtfs_dev_error_resp_ei[];
|
||||||
int rmtfs_iovec_req_get_is_force_sync(struct rmtfs_iovec_req *iovec_req, uint8_t *val);
|
extern struct qmi_elem_info rmtfs_force_sync_ei[];
|
||||||
|
|
||||||
/*
|
|
||||||
* rmtfs_iovec_resp message
|
|
||||||
*/
|
|
||||||
struct rmtfs_iovec_resp *rmtfs_iovec_resp_alloc(unsigned txn);
|
|
||||||
struct rmtfs_iovec_resp *rmtfs_iovec_resp_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_iovec_resp_encode(struct rmtfs_iovec_resp *iovec_resp, size_t *len);
|
|
||||||
void rmtfs_iovec_resp_free(struct rmtfs_iovec_resp *iovec_resp);
|
|
||||||
|
|
||||||
int rmtfs_iovec_resp_set_result(struct rmtfs_iovec_resp *iovec_resp, struct rmtfs_qmi_result *val);
|
|
||||||
struct rmtfs_qmi_result *rmtfs_iovec_resp_get_result(struct rmtfs_iovec_resp *iovec_resp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rmtfs_alloc_buf_req message
|
|
||||||
*/
|
|
||||||
struct rmtfs_alloc_buf_req *rmtfs_alloc_buf_req_alloc(unsigned txn);
|
|
||||||
struct rmtfs_alloc_buf_req *rmtfs_alloc_buf_req_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_alloc_buf_req_encode(struct rmtfs_alloc_buf_req *alloc_buf_req, size_t *len);
|
|
||||||
void rmtfs_alloc_buf_req_free(struct rmtfs_alloc_buf_req *alloc_buf_req);
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_req_set_caller_id(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t val);
|
|
||||||
int rmtfs_alloc_buf_req_get_caller_id(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t *val);
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_req_set_buff_size(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t val);
|
|
||||||
int rmtfs_alloc_buf_req_get_buff_size(struct rmtfs_alloc_buf_req *alloc_buf_req, uint32_t *val);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rmtfs_alloc_buf_resp message
|
|
||||||
*/
|
|
||||||
struct rmtfs_alloc_buf_resp *rmtfs_alloc_buf_resp_alloc(unsigned txn);
|
|
||||||
struct rmtfs_alloc_buf_resp *rmtfs_alloc_buf_resp_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_alloc_buf_resp_encode(struct rmtfs_alloc_buf_resp *alloc_buf_resp, size_t *len);
|
|
||||||
void rmtfs_alloc_buf_resp_free(struct rmtfs_alloc_buf_resp *alloc_buf_resp);
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_resp_set_result(struct rmtfs_alloc_buf_resp *alloc_buf_resp, struct rmtfs_qmi_result *val);
|
|
||||||
struct rmtfs_qmi_result *rmtfs_alloc_buf_resp_get_result(struct rmtfs_alloc_buf_resp *alloc_buf_resp);
|
|
||||||
|
|
||||||
int rmtfs_alloc_buf_resp_set_buff_address(struct rmtfs_alloc_buf_resp *alloc_buf_resp, uint64_t val);
|
|
||||||
int rmtfs_alloc_buf_resp_get_buff_address(struct rmtfs_alloc_buf_resp *alloc_buf_resp, uint64_t *val);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rmtfs_dev_error_req message
|
|
||||||
*/
|
|
||||||
struct rmtfs_dev_error_req *rmtfs_dev_error_req_alloc(unsigned txn);
|
|
||||||
struct rmtfs_dev_error_req *rmtfs_dev_error_req_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_dev_error_req_encode(struct rmtfs_dev_error_req *dev_error_req, size_t *len);
|
|
||||||
void rmtfs_dev_error_req_free(struct rmtfs_dev_error_req *dev_error_req);
|
|
||||||
|
|
||||||
int rmtfs_dev_error_req_set_caller_id(struct rmtfs_dev_error_req *dev_error_req, uint32_t val);
|
|
||||||
int rmtfs_dev_error_req_get_caller_id(struct rmtfs_dev_error_req *dev_error_req, uint32_t *val);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rmtfs_dev_error_resp message
|
|
||||||
*/
|
|
||||||
struct rmtfs_dev_error_resp *rmtfs_dev_error_resp_alloc(unsigned txn);
|
|
||||||
struct rmtfs_dev_error_resp *rmtfs_dev_error_resp_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_dev_error_resp_encode(struct rmtfs_dev_error_resp *dev_error_resp, size_t *len);
|
|
||||||
void rmtfs_dev_error_resp_free(struct rmtfs_dev_error_resp *dev_error_resp);
|
|
||||||
|
|
||||||
int rmtfs_dev_error_resp_set_result(struct rmtfs_dev_error_resp *dev_error_resp, struct rmtfs_qmi_result *val);
|
|
||||||
struct rmtfs_qmi_result *rmtfs_dev_error_resp_get_result(struct rmtfs_dev_error_resp *dev_error_resp);
|
|
||||||
|
|
||||||
int rmtfs_dev_error_resp_set_status(struct rmtfs_dev_error_resp *dev_error_resp, uint8_t val);
|
|
||||||
int rmtfs_dev_error_resp_get_status(struct rmtfs_dev_error_resp *dev_error_resp, uint8_t *val);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* rmtfs_force_sync message
|
|
||||||
*/
|
|
||||||
struct rmtfs_force_sync *rmtfs_force_sync_alloc(unsigned txn);
|
|
||||||
struct rmtfs_force_sync *rmtfs_force_sync_parse(void *buf, size_t len, unsigned *txn);
|
|
||||||
void *rmtfs_force_sync_encode(struct rmtfs_force_sync *force_sync, size_t *len);
|
|
||||||
void rmtfs_force_sync_free(struct rmtfs_force_sync *force_sync);
|
|
||||||
|
|
||||||
int rmtfs_force_sync_set_caller_id(struct rmtfs_force_sync *force_sync, uint32_t *val, size_t count);
|
|
||||||
uint32_t *rmtfs_force_sync_get_caller_id(struct rmtfs_force_sync *force_sync, size_t *count);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ response close_resp {
|
|||||||
request iovec_req {
|
request iovec_req {
|
||||||
required u32 caller_id = 1;
|
required u32 caller_id = 1;
|
||||||
required u8 direction = 2;
|
required u8 direction = 2;
|
||||||
required iovec_entry iovec[] = 3;
|
required iovec_entry iovec(255) = 3;
|
||||||
required u8 is_force_sync = 4;
|
required u8 is_force_sync = 4;
|
||||||
} = 3;
|
} = 3;
|
||||||
|
|
||||||
@@ -73,5 +73,5 @@ response dev_error_resp {
|
|||||||
} = 5;
|
} = 5;
|
||||||
|
|
||||||
indication force_sync {
|
indication force_sync {
|
||||||
required u32 caller_id[] = 1;
|
required u32 caller_id(10) = 1;
|
||||||
} = 6;
|
} = 6;
|
||||||
|
|||||||
11
rmtfs-dir.service.in
Normal file
11
rmtfs-dir.service.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Qualcomm remotefs service
|
||||||
|
Before=NetworkManager.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=RMTFS_PATH/rmtfs -s -o RMTFS_EFS_PATH
|
||||||
|
Restart=always
|
||||||
|
RestartSec=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
697
rmtfs.c
697
rmtfs.c
@@ -2,14 +2,18 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <libqrtr.h>
|
#include <libqrtr.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@@ -17,22 +21,13 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "rmtfs.h"
|
#include "rmtfs.h"
|
||||||
|
|
||||||
#define RFSA_QMI_SERVICE 28
|
|
||||||
#define RFSA_QMI_VERSION 1
|
|
||||||
#define RFSA_QMI_INSTANCE 0
|
|
||||||
|
|
||||||
#define RMTFS_QMI_SERVICE 14
|
#define RMTFS_QMI_SERVICE 14
|
||||||
#define RMTFS_QMI_VERSION 1
|
#define RMTFS_QMI_VERSION 1
|
||||||
#define RMTFS_QMI_INSTANCE 0
|
#define RMTFS_QMI_INSTANCE 0
|
||||||
|
|
||||||
static struct rmtfs_mem *rmem;
|
static struct rmtfs_mem *rmem;
|
||||||
|
static sig_atomic_t sig_int_count;
|
||||||
/* TODO: include from kernel once it lands */
|
static char slot_suffix[SLOT_SUFFIX_LEN];
|
||||||
struct sockaddr_qrtr {
|
|
||||||
unsigned short sq_family;
|
|
||||||
uint32_t sq_node;
|
|
||||||
uint32_t sq_port;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool dbgprintf_enabled;
|
static bool dbgprintf_enabled;
|
||||||
static void dbgprintf(const char *fmt, ...)
|
static void dbgprintf(const char *fmt, ...)
|
||||||
@@ -57,191 +52,179 @@ static void qmi_result_error(struct rmtfs_qmi_result *result, unsigned error)
|
|||||||
result->error = error;
|
result->error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmtfs_open(int sock, unsigned node, unsigned port, void *msg, size_t msg_len)
|
static void rmtfs_open(int sock, const struct qrtr_packet *pkt)
|
||||||
{
|
{
|
||||||
struct rmtfs_qmi_result result = {};
|
struct rmtfs_open_resp resp = {};
|
||||||
struct rmtfs_open_resp *resp;
|
struct rmtfs_open_req req = {};
|
||||||
struct rmtfs_open_req *req;
|
DEFINE_QRTR_PACKET(resp_buf, 256);
|
||||||
|
struct rmtfd *rmtfd;
|
||||||
|
unsigned int txn;
|
||||||
|
ssize_t len;
|
||||||
int caller_id = -1;
|
int caller_id = -1;
|
||||||
unsigned txn;
|
|
||||||
size_t len;
|
|
||||||
void *ptr;
|
|
||||||
char path[256] = {};
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
req = rmtfs_open_req_parse(msg, msg_len, &txn);
|
ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
|
||||||
if (!req) {
|
QMI_RMTFS_OPEN, rmtfs_open_req_ei);
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rmtfs_open_req_get_path(req, path, sizeof(path));
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
caller_id = storage_get(node, path);
|
rmtfd = storage_open(pkt->node, req.path, slot_suffix);
|
||||||
if (caller_id < 0)
|
if (!rmtfd) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
caller_id = storage_get_caller_id(rmtfd);
|
||||||
|
resp.caller_id = caller_id;
|
||||||
|
resp.caller_id_valid = true;
|
||||||
|
|
||||||
respond:
|
respond:
|
||||||
dbgprintf("[RMTFS] open %s => %d (%d:%d)\n", path, caller_id, result.result, result.error);
|
dbgprintf("[RMTFS] open %s => %d (%d:%d)\n",
|
||||||
|
req.path, caller_id, resp.result.result, resp.result.error);
|
||||||
|
|
||||||
resp = rmtfs_open_resp_alloc(txn);
|
len = qmi_encode_message(&resp_buf,
|
||||||
rmtfs_open_resp_set_result(resp, &result);
|
QMI_RESPONSE, QMI_RMTFS_OPEN, txn, &resp,
|
||||||
rmtfs_open_resp_set_caller_id(resp, caller_id);
|
rmtfs_open_resp_ei);
|
||||||
ptr = rmtfs_open_resp_encode(resp, &len);
|
if (len < 0) {
|
||||||
if (!ptr)
|
fprintf(stderr, "[RMTFS] failed to encode open-response: %s\n",
|
||||||
goto free_resp;
|
strerror(-len));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = qrtr_sendto(sock, node, port, ptr, len);
|
ret = qrtr_sendto(sock, pkt->node, pkt->port,
|
||||||
|
resp_buf.data, resp_buf.data_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fprintf(stderr, "[RMTFS] failed to send open-response: %s\n", strerror(-ret));
|
fprintf(stderr, "[RMTFS] failed to send open-response: %s\n",
|
||||||
|
strerror(-ret));
|
||||||
free_resp:
|
|
||||||
rmtfs_open_resp_free(resp);
|
|
||||||
rmtfs_open_req_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmtfs_close(int sock, unsigned node, unsigned port, void *msg, size_t msg_len)
|
static void rmtfs_close(int sock, const struct qrtr_packet *pkt)
|
||||||
{
|
{
|
||||||
struct rmtfs_qmi_result result = {};
|
struct rmtfs_close_resp resp = {};
|
||||||
struct rmtfs_close_resp *resp;
|
struct rmtfs_close_req req = {};
|
||||||
struct rmtfs_close_req *req;
|
DEFINE_QRTR_PACKET(resp_buf, 256);
|
||||||
uint32_t caller_id;
|
struct rmtfd *rmtfd;
|
||||||
unsigned txn;
|
unsigned int txn;
|
||||||
size_t len;
|
ssize_t len;
|
||||||
void *ptr;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
req = rmtfs_close_req_parse(msg, msg_len, &txn);
|
ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
|
||||||
if (!req) {
|
QMI_RMTFS_CLOSE, rmtfs_close_req_ei);
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rmtfs_close_req_get_caller_id(req, &caller_id);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = storage_put(node, caller_id);
|
rmtfd = storage_get(pkt->node, req.caller_id);
|
||||||
if (ret < 0)
|
if (!rmtfd) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage_close(rmtfd);
|
||||||
rmtfs_mem_free(rmem);
|
rmtfs_mem_free(rmem);
|
||||||
|
|
||||||
respond:
|
respond:
|
||||||
dbgprintf("[RMTFS] close %d => (%d:%d)\n", caller_id, result.result, result.error);
|
dbgprintf("[RMTFS] close %s => %d (%d:%d)\n",
|
||||||
|
req.caller_id, resp.result.result, resp.result.error);
|
||||||
|
|
||||||
resp = rmtfs_close_resp_alloc(txn);
|
len = qmi_encode_message(&resp_buf,
|
||||||
rmtfs_close_resp_set_result(resp, &result);
|
QMI_RESPONSE, QMI_RMTFS_CLOSE, txn, &resp,
|
||||||
ptr = rmtfs_close_resp_encode(resp, &len);
|
rmtfs_close_resp_ei);
|
||||||
if (!ptr)
|
if (len < 0) {
|
||||||
goto free_resp;
|
fprintf(stderr, "[RMTFS] failed to encode close-response: %s\n",
|
||||||
|
strerror(-len));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = qrtr_sendto(sock, node, port, ptr, len);
|
ret = qrtr_sendto(sock, pkt->node, pkt->port,
|
||||||
|
resp_buf.data, resp_buf.data_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fprintf(stderr, "[RMTFS] failed to send close-response: %s\n", strerror(-ret));
|
fprintf(stderr, "[RMTFS] failed to send close-response: %s\n",
|
||||||
|
strerror(-ret));
|
||||||
free_resp:
|
|
||||||
rmtfs_close_resp_free(resp);
|
|
||||||
rmtfs_close_req_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmtfs_iovec(int sock, unsigned node, unsigned port, void *msg, size_t msg_len)
|
static void rmtfs_iovec(int sock, struct qrtr_packet *pkt)
|
||||||
{
|
{
|
||||||
struct rmtfs_iovec_entry *entries;
|
struct rmtfs_iovec_entry *entries;
|
||||||
struct rmtfs_qmi_result result = {};
|
struct rmtfs_iovec_resp resp = {};
|
||||||
struct rmtfs_iovec_resp *resp;
|
struct rmtfs_iovec_req req = {};
|
||||||
struct rmtfs_iovec_req *req;
|
DEFINE_QRTR_PACKET(resp_buf, 256);
|
||||||
unsigned long phys_offset;
|
struct rmtfd *rmtfd = NULL;
|
||||||
uint32_t caller_id;
|
uint32_t caller_id = 0;
|
||||||
size_t num_entries;
|
size_t num_entries = 0;
|
||||||
uint8_t is_write;
|
off_t sector_base;
|
||||||
uint8_t force;
|
uint8_t is_write = 0;
|
||||||
|
off_t phys_base;
|
||||||
|
uint8_t force = 0;
|
||||||
unsigned txn;
|
unsigned txn;
|
||||||
|
off_t offset;
|
||||||
|
ssize_t len;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
size_t len;
|
|
||||||
void *ptr;
|
|
||||||
char buf[SECTOR_SIZE];
|
char buf[SECTOR_SIZE];
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
req = rmtfs_iovec_req_parse(msg, msg_len, &txn);
|
ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
|
||||||
if (!req) {
|
QMI_RMTFS_RW_IOVEC, rmtfs_iovec_req_ei);
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rmtfs_iovec_req_get_caller_id(req, &caller_id);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rmtfs_iovec_req_get_direction(req, &is_write);
|
caller_id = req.caller_id;
|
||||||
if (ret < 0) {
|
is_write = req.direction;
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
entries = req.iovec;
|
||||||
goto respond;
|
num_entries = req.iovec_len;
|
||||||
}
|
force = req.is_force_sync;
|
||||||
|
|
||||||
entries = rmtfs_iovec_req_get_iovec(req, &num_entries);
|
rmtfd = storage_get(pkt->node, caller_id);
|
||||||
if (!entries) {
|
if (!rmtfd) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rmtfs_iovec_req_get_is_force_sync(req, &force);
|
|
||||||
if (ret < 0) {
|
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = storage_get_handle(node, caller_id);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "[RMTFS] iovec request for non-existing caller\n");
|
fprintf(stderr, "[RMTFS] iovec request for non-existing caller\n");
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_entries; i++) {
|
for (i = 0; i < num_entries; i++) {
|
||||||
phys_offset = entries[i].phys_offset;
|
phys_base = entries[i].phys_offset;
|
||||||
|
sector_base = entries[i].sector_addr * SECTOR_SIZE;
|
||||||
n = lseek(fd, entries[i].sector_addr * SECTOR_SIZE, SEEK_SET);
|
offset = 0;
|
||||||
if (n < 0) {
|
|
||||||
fprintf(stderr, "[RMTFS] failed to seek sector %d\n", entries[i].sector_addr);
|
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < entries[i].num_sector; j++) {
|
for (j = 0; j < entries[i].num_sector; j++) {
|
||||||
if (is_write) {
|
if (is_write) {
|
||||||
n = rmtfs_mem_read(rmem, phys_offset, buf, SECTOR_SIZE);
|
n = rmtfs_mem_read(rmem, phys_base + offset, buf, SECTOR_SIZE);
|
||||||
n = write(fd, buf, n);
|
if (n == SECTOR_SIZE)
|
||||||
|
n = storage_pwrite(rmtfd, buf, n, sector_base + offset);
|
||||||
} else {
|
} else {
|
||||||
n = read(fd, buf, SECTOR_SIZE);
|
n = storage_pread(rmtfd, buf, SECTOR_SIZE, sector_base + offset);
|
||||||
n = rmtfs_mem_write(rmem, phys_offset, buf, n);
|
if (n >= 0) {
|
||||||
|
if (n < SECTOR_SIZE)
|
||||||
|
memset(buf + n, 0, SECTOR_SIZE - n);
|
||||||
|
n = rmtfs_mem_write(rmem, phys_base + offset, buf, SECTOR_SIZE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n != SECTOR_SIZE) {
|
if (n != SECTOR_SIZE) {
|
||||||
fprintf(stderr, "[RMTFS] failed to %s sector %d\n",
|
fprintf(stderr, "[RMTFS] failed to %s sector %d\n",
|
||||||
is_write ? "write" : "read", entries[i].sector_addr + j);
|
is_write ? "write" : "read", entries[i].sector_addr + j);
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_offset += SECTOR_SIZE;
|
offset += SECTOR_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
respond:
|
respond:
|
||||||
dbgprintf("[RMTFS] iovec %d, %sforced => (%d:%d)\n", caller_id, force ? "" : "not ",
|
dbgprintf("[RMTFS] iovec %d, %sforced => (%d:%d)\n", caller_id, force ? "" : "not ",
|
||||||
result.result, result.error);
|
resp.result.result, resp.result.error);
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
|
storage_sync(rmtfd);
|
||||||
|
|
||||||
for (i = 0; i < num_entries; i++) {
|
for (i = 0; i < num_entries; i++) {
|
||||||
dbgprintf("[RMTFS] %s %d:%d 0x%x\n", is_write ? "write" : "read",
|
dbgprintf("[RMTFS] %s %d:%d 0x%x\n", is_write ? "write" : "read",
|
||||||
entries[i].sector_addr,
|
entries[i].sector_addr,
|
||||||
@@ -249,168 +232,136 @@ respond:
|
|||||||
entries[i].phys_offset);
|
entries[i].phys_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = rmtfs_iovec_resp_alloc(txn);
|
len = qmi_encode_message(&resp_buf,
|
||||||
rmtfs_iovec_resp_set_result(resp, &result);
|
QMI_RESPONSE, QMI_RMTFS_RW_IOVEC, txn, &resp,
|
||||||
ptr = rmtfs_iovec_resp_encode(resp, &len);
|
rmtfs_iovec_resp_ei);
|
||||||
if (!ptr)
|
if (len < 0) {
|
||||||
goto free_resp;
|
fprintf(stderr, "[RMTFS] failed to encode iovec-response: %s\n",
|
||||||
|
strerror(-len));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = qrtr_sendto(sock, node, port, ptr, len);
|
ret = qrtr_sendto(sock, pkt->node, pkt->port,
|
||||||
|
resp_buf.data, resp_buf.data_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fprintf(stderr, "[RMTFS] failed to send iovec-response: %s\n", strerror(-ret));
|
fprintf(stderr, "[RMTFS] failed to send iovec-response: %s\n",
|
||||||
|
strerror(-ret));
|
||||||
free_resp:
|
|
||||||
rmtfs_iovec_resp_free(resp);
|
|
||||||
rmtfs_iovec_req_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmtfs_alloc_buf(int sock, unsigned node, unsigned port, void *msg, size_t msg_len)
|
static void rmtfs_alloc_buf(int sock, struct qrtr_packet *pkt)
|
||||||
{
|
{
|
||||||
struct rmtfs_alloc_buf_resp *resp;
|
struct rmtfs_alloc_buf_resp resp = {};
|
||||||
struct rmtfs_alloc_buf_req *req;
|
struct rmtfs_alloc_buf_req req = {};
|
||||||
struct rmtfs_qmi_result result = {};
|
DEFINE_QRTR_PACKET(resp_buf, 256);
|
||||||
uint32_t alloc_size;
|
uint32_t alloc_size = 0;
|
||||||
uint32_t caller_id;
|
uint32_t caller_id = 0;
|
||||||
int64_t address;
|
int64_t address = 0;
|
||||||
unsigned txn;
|
unsigned txn;
|
||||||
size_t len;
|
ssize_t len;
|
||||||
void *ptr;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
req = rmtfs_alloc_buf_req_parse(msg, msg_len, &txn);
|
ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
|
||||||
if (!req) {
|
QMI_RMTFS_ALLOC_BUFF, rmtfs_alloc_buf_req_ei);
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
if (ret < 0) {
|
||||||
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rmtfs_alloc_buf_req_get_caller_id(req, &caller_id);
|
caller_id = req.caller_id;
|
||||||
if (ret < 0) {
|
alloc_size = req.buff_size;
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rmtfs_alloc_buf_req_get_buff_size(req, &alloc_size);
|
|
||||||
if (ret < 0) {
|
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
address = rmtfs_mem_alloc(rmem, alloc_size);
|
address = rmtfs_mem_alloc(rmem, alloc_size);
|
||||||
if (address < 0)
|
if (address < 0) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.buff_address = address;
|
||||||
|
resp.buff_address_valid = true;
|
||||||
respond:
|
respond:
|
||||||
dbgprintf("[RMTFS] alloc %d, %d => 0x%lx (%d:%d)\n", caller_id, alloc_size, address, result.result, result.error);
|
dbgprintf("[RMTFS] alloc %d, %d => 0x%lx (%d:%d)\n", caller_id, alloc_size, address, resp.result.result, resp.result.error);
|
||||||
|
|
||||||
resp = rmtfs_alloc_buf_resp_alloc(txn);
|
len = qmi_encode_message(&resp_buf,
|
||||||
rmtfs_alloc_buf_resp_set_result(resp, &result);
|
QMI_RESPONSE, QMI_RMTFS_ALLOC_BUFF, txn, &resp,
|
||||||
rmtfs_alloc_buf_resp_set_buff_address(resp, address);
|
rmtfs_alloc_buf_resp_ei);
|
||||||
ptr = rmtfs_alloc_buf_resp_encode(resp, &len);
|
if (len < 0) {
|
||||||
if (!ptr)
|
fprintf(stderr, "[RMTFS] failed to encode alloc-buf-response: %s\n",
|
||||||
goto free_resp;
|
strerror(-len));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = qrtr_sendto(sock, node, port, ptr, len);
|
ret = qrtr_sendto(sock, pkt->node, pkt->port,
|
||||||
|
resp_buf.data, resp_buf.data_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fprintf(stderr, "[RMTFS] failed to send alloc-response: %s\n", strerror(-ret));
|
fprintf(stderr, "[RMTFS] failed to send alloc-buf-response: %s\n",
|
||||||
|
strerror(-ret));
|
||||||
free_resp:
|
|
||||||
rmtfs_alloc_buf_resp_free(resp);
|
|
||||||
rmtfs_alloc_buf_req_free(req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmtfs_get_dev_error(int sock, unsigned node, unsigned port, void *msg, size_t msg_len)
|
static void rmtfs_get_dev_error(int sock, struct qrtr_packet *pkt)
|
||||||
{
|
{
|
||||||
struct rmtfs_dev_error_resp *resp;
|
struct rmtfs_dev_error_resp resp = {};
|
||||||
struct rmtfs_dev_error_req *req;
|
struct rmtfs_dev_error_req req = {};
|
||||||
struct rmtfs_qmi_result result = {};
|
DEFINE_QRTR_PACKET(resp_buf, 256);
|
||||||
uint32_t caller_id;
|
struct rmtfd *rmtfd;
|
||||||
int dev_error;
|
|
||||||
unsigned txn;
|
unsigned txn;
|
||||||
size_t len;
|
ssize_t len;
|
||||||
void *ptr;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
req = rmtfs_dev_error_req_parse(msg, msg_len, &txn);
|
ret = qmi_decode_message(&req, &txn, pkt, QMI_REQUEST,
|
||||||
if (!req) {
|
QMI_RMTFS_GET_DEV_ERROR,
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
rmtfs_dev_error_req_ei);
|
||||||
goto respond;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = rmtfs_dev_error_req_get_caller_id(req, &caller_id);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_MALFORMED_MSG);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_error = storage_get_error(node, caller_id);
|
rmtfd = storage_get(pkt->node, req.caller_id);
|
||||||
if (dev_error < 0)
|
if (rmtfd) {
|
||||||
qmi_result_error(&result, QMI_RMTFS_ERR_INTERNAL);
|
qmi_result_error(&resp.result, QMI_RMTFS_ERR_INTERNAL);
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.status = storage_get_error(rmtfd);
|
||||||
|
resp.status_valid = true;
|
||||||
|
|
||||||
respond:
|
respond:
|
||||||
dbgprintf("[RMTFS] dev_error %d => %d (%d:%d)\n", caller_id, dev_error, result.result, result.error);
|
dbgprintf("[RMTFS] dev_error %d => %d (%d:%d)\n", req.caller_id, resp.status, resp.result.result, resp.result.error);
|
||||||
|
|
||||||
resp = rmtfs_dev_error_resp_alloc(txn);
|
len = qmi_encode_message(&resp_buf,
|
||||||
rmtfs_dev_error_resp_set_result(resp, &result);
|
QMI_RESPONSE, QMI_RMTFS_GET_DEV_ERROR, txn,
|
||||||
rmtfs_dev_error_resp_set_status(resp, dev_error);
|
&resp, rmtfs_dev_error_resp_ei);
|
||||||
ptr = rmtfs_dev_error_resp_encode(resp, &len);
|
if (len < 0) {
|
||||||
if (!ptr)
|
fprintf(stderr, "[RMTFS] failed to encode dev-error-response: %s\n",
|
||||||
goto free_resp;
|
strerror(-len));
|
||||||
|
return;
|
||||||
ret = qrtr_sendto(sock, node, port, ptr, len);
|
|
||||||
if (ret < 0)
|
|
||||||
fprintf(stderr, "[RMTFS] failed to send error-response: %s\n", strerror(-ret));
|
|
||||||
|
|
||||||
free_resp:
|
|
||||||
rmtfs_dev_error_resp_free(resp);
|
|
||||||
rmtfs_dev_error_req_free(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_rfsa(int sock)
|
|
||||||
{
|
|
||||||
struct sockaddr_qrtr sq;
|
|
||||||
socklen_t sl;
|
|
||||||
char buf[4096];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
sl = sizeof(sq);
|
|
||||||
ret = recvfrom(sock, buf, sizeof(buf), 0, (void *)&sq, &sl);
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
if (ret != -ENETRESET)
|
|
||||||
fprintf(stderr, "[RFSA] recvfrom failed: %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbgprintf("[RFSA] packet; from: %d:%d\n", sq.sq_node, sq.sq_port);
|
ret = qrtr_sendto(sock, pkt->node, pkt->port,
|
||||||
if (dbgprintf_enabled)
|
resp_buf.data, resp_buf.data_len);
|
||||||
print_hex_dump("[RFSA <-]", buf, ret);
|
if (ret < 0)
|
||||||
|
fprintf(stderr, "[RMTFS] failed to send dev-error-response: %s\n",
|
||||||
return 0;
|
strerror(-ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rmtfs_bye(uint32_t node, void *data)
|
static int rmtfs_bye(uint32_t node)
|
||||||
{
|
{
|
||||||
dbgprintf("[RMTFS] bye from %d\n", node);
|
dbgprintf("[RMTFS] bye from %d\n", node);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rmtfs_del_client(uint32_t node, uint32_t port, void *data)
|
static int rmtfs_del_client(uint32_t node, uint32_t port)
|
||||||
{
|
{
|
||||||
dbgprintf("[RMTFS] del_client %d:%d\n", node, port);
|
dbgprintf("[RMTFS] del_client %d:%d\n", node, port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct qrtr_ind_ops rmtfs_ctrl_ops = {
|
|
||||||
.bye = rmtfs_bye,
|
|
||||||
.del_client = rmtfs_del_client,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int handle_rmtfs(int sock)
|
static int handle_rmtfs(int sock)
|
||||||
{
|
{
|
||||||
struct sockaddr_qrtr sq;
|
struct sockaddr_qrtr sq;
|
||||||
struct qmi_packet *qmi;
|
struct qrtr_packet pkt;
|
||||||
|
unsigned int msg_id;
|
||||||
socklen_t sl;
|
socklen_t sl;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
int ret;
|
int ret;
|
||||||
@@ -426,134 +377,212 @@ static int handle_rmtfs(int sock)
|
|||||||
|
|
||||||
dbgprintf("[RMTFS] packet; from: %d:%d\n", sq.sq_node, sq.sq_port);
|
dbgprintf("[RMTFS] packet; from: %d:%d\n", sq.sq_node, sq.sq_port);
|
||||||
|
|
||||||
if (qrtr_is_ctrl_addr(&sq)) {
|
ret = qrtr_decode(&pkt, buf, ret, &sq);
|
||||||
return qrtr_handle_ctrl_msg(&sq, buf, sizeof(buf),
|
if (ret < 0) {
|
||||||
&rmtfs_ctrl_ops, NULL);
|
fprintf(stderr, "[RMTFS] unable to decode qrtr packet\n");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
qmi = (struct qmi_packet*)buf;
|
switch (pkt.type) {
|
||||||
if (qmi->msg_len != ret - sizeof(struct qmi_packet)) {
|
case QRTR_TYPE_BYE:
|
||||||
fprintf(stderr, "[RMTFS] Invalid length of incoming qmi request\n");
|
return rmtfs_bye(pkt.node);
|
||||||
return -EINVAL;
|
case QRTR_TYPE_DEL_CLIENT:
|
||||||
}
|
return rmtfs_del_client(pkt.node, pkt.port);
|
||||||
|
case QRTR_TYPE_DATA:
|
||||||
|
ret = qmi_decode_header(&pkt, &msg_id);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
switch (qmi->msg_id) {
|
switch (msg_id) {
|
||||||
case QMI_RMTFS_OPEN:
|
case QMI_RMTFS_OPEN:
|
||||||
rmtfs_open(sock, sq.sq_node, sq.sq_port, qmi, qmi->msg_len);
|
rmtfs_open(sock, &pkt);
|
||||||
break;
|
break;
|
||||||
case QMI_RMTFS_CLOSE:
|
case QMI_RMTFS_CLOSE:
|
||||||
rmtfs_close(sock, sq.sq_node, sq.sq_port, qmi, qmi->msg_len);
|
rmtfs_close(sock, &pkt);
|
||||||
break;
|
break;
|
||||||
case QMI_RMTFS_RW_IOVEC:
|
case QMI_RMTFS_RW_IOVEC:
|
||||||
rmtfs_iovec(sock, sq.sq_node, sq.sq_port, qmi, qmi->msg_len);
|
rmtfs_iovec(sock, &pkt);
|
||||||
break;
|
break;
|
||||||
case QMI_RMTFS_ALLOC_BUFF:
|
case QMI_RMTFS_ALLOC_BUFF:
|
||||||
rmtfs_alloc_buf(sock, sq.sq_node, sq.sq_port, qmi, qmi->msg_len);
|
rmtfs_alloc_buf(sock, &pkt);
|
||||||
break;
|
break;
|
||||||
case QMI_RMTFS_GET_DEV_ERROR:
|
case QMI_RMTFS_GET_DEV_ERROR:
|
||||||
rmtfs_get_dev_error(sock, sq.sq_node, sq.sq_port, qmi, qmi->msg_len);
|
rmtfs_get_dev_error(sock, &pkt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "[RMTFS] Unknown request: %d\n", qmi->msg_id);
|
fprintf(stderr, "[RMTFS] Unknown request: %d\n", msg_id);
|
||||||
ret = -EINVAL;
|
break;
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int register_services(int rfsa_fd, int rmtfs_fd)
|
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;
|
int ret;
|
||||||
|
|
||||||
ret = qrtr_publish(rfsa_fd, RFSA_QMI_SERVICE, RFSA_QMI_VERSION, RFSA_QMI_INSTANCE);
|
rmtfs_fd = qrtr_open(RMTFS_QMI_SERVICE);
|
||||||
|
if (rmtfs_fd < 0) {
|
||||||
|
fprintf(stderr, "failed to create qrtr socket\n");
|
||||||
|
return rmtfs_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgprintf("registering services\n");
|
||||||
|
|
||||||
|
ret = qrtr_publish(rmtfs_fd, RMTFS_QMI_SERVICE,
|
||||||
|
RMTFS_QMI_VERSION, RMTFS_QMI_INSTANCE);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "failed to publish rfsa service");
|
fprintf(stderr, "failed to publish rmtfs service");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qrtr_publish(rmtfs_fd, RMTFS_QMI_SERVICE, RMTFS_QMI_VERSION, RMTFS_QMI_INSTANCE);
|
if (rprocfd >= 0)
|
||||||
if (ret < 0) {
|
rproc_start();
|
||||||
fprintf(stderr, "failed to publish misc ta service");
|
|
||||||
|
|
||||||
qrtr_bye(rfsa_fd, RFSA_QMI_SERVICE, RFSA_QMI_VERSION, RFSA_QMI_INSTANCE);
|
for (;;) {
|
||||||
return ret;
|
if (sig_int_count == 1 && !sig_int_handled) {
|
||||||
|
if (rprocfd < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
close(rmtfs_fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sig_int_handler(int signo)
|
||||||
|
{
|
||||||
|
sig_int_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool do_register = true;
|
struct sigaction action;
|
||||||
int rmtfs_fd;
|
bool use_partitions = false;
|
||||||
int rfsa_fd;
|
bool read_only = false;
|
||||||
fd_set rfds;
|
int rprocfd = -1;
|
||||||
int nfds;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
int option;
|
||||||
|
const char *storage_root = NULL;
|
||||||
|
|
||||||
if (argc == 2 && strcmp(argv[1], "-v") == 0)
|
while ((option = getopt(argc, argv, "o:S:Prsv")) != -1) {
|
||||||
dbgprintf_enabled = true;
|
switch (option) {
|
||||||
|
/*
|
||||||
|
* -o sets the directory where EFS images are stored,
|
||||||
|
* or sets the directory from where raw EFS partitions
|
||||||
|
* can be picked by-name when used with -P option.
|
||||||
|
*/
|
||||||
|
case 'o':
|
||||||
|
storage_root = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* -P to find and use raw EFS partitions */
|
||||||
|
case 'P':
|
||||||
|
use_partitions = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* -r to avoid writing to storage */
|
||||||
|
case 'r':
|
||||||
|
read_only = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* enable sync for the mss rproc instance */
|
||||||
|
case 's':
|
||||||
|
rprocfd = rproc_init();
|
||||||
|
if (rprocfd < 0) {
|
||||||
|
fprintf(stderr, "Failed to get rprocfd\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Partlabel slot suffix on A/B devices */
|
||||||
|
case 'S':
|
||||||
|
if (strnlen(optarg, 1 + 1) != 1) {
|
||||||
|
fprintf(stderr, "Couldn't parse slot name (too long?)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snprintf(slot_suffix, SLOT_SUFFIX_LEN, "_%s", optarg);
|
||||||
|
if (ret != SLOT_SUFFIX_LEN - 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dbgprintf("Using slot %s\n", slot_suffix);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* -v is for verbose */
|
||||||
|
case 'v':
|
||||||
|
dbgprintf_enabled = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
fprintf(stderr, "Unknown option: -%c\n", option);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
rmem = rmtfs_mem_open();
|
||||||
if (!rmem)
|
if (!rmem)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
ret = storage_open();
|
ret = storage_init(storage_root, read_only, use_partitions);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "failed to initialize storage system\n");
|
fprintf(stderr, "failed to initialize storage system\n");
|
||||||
goto close_rmtfs_mem;
|
goto close_rmtfs_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfsa_fd = qrtr_open(RFSA_QMI_SERVICE);
|
do {
|
||||||
if (rfsa_fd < 0) {
|
ret = run_rmtfs(rprocfd);
|
||||||
fprintf(stderr, "failed to create qrtr socket\n");
|
} while (ret == -ENETRESET);
|
||||||
goto close_storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
rmtfs_fd = qrtr_open(RMTFS_QMI_SERVICE);
|
storage_exit();
|
||||||
if (rmtfs_fd < 0) {
|
|
||||||
fprintf(stderr, "failed to create qrtr socket\n");
|
|
||||||
goto close_storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (do_register) {
|
|
||||||
dbgprintf("registering services\n");
|
|
||||||
ret = register_services(rfsa_fd, rmtfs_fd);
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
|
|
||||||
do_register = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(rfsa_fd, &rfds);
|
|
||||||
FD_SET(rmtfs_fd, &rfds);
|
|
||||||
|
|
||||||
nfds = MAX(rfsa_fd, rmtfs_fd) + 1;
|
|
||||||
ret = select(nfds, &rfds, NULL, NULL, NULL);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "select failed: %d\n", ret);
|
|
||||||
break;
|
|
||||||
} else if (ret == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(rfsa_fd, &rfds))
|
|
||||||
ret = handle_rfsa(rfsa_fd);
|
|
||||||
else if (FD_ISSET(rmtfs_fd, &rfds))
|
|
||||||
ret = handle_rmtfs(rmtfs_fd);
|
|
||||||
|
|
||||||
if (ret == -ENETRESET)
|
|
||||||
do_register = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
qrtr_bye(rmtfs_fd, RMTFS_QMI_SERVICE, RMTFS_QMI_VERSION, RMTFS_QMI_INSTANCE);
|
|
||||||
unpublish_rfsa:
|
|
||||||
qrtr_bye(rfsa_fd, RFSA_QMI_SERVICE, RFSA_QMI_VERSION, RFSA_QMI_INSTANCE);
|
|
||||||
close_storage:
|
|
||||||
storage_close();
|
|
||||||
close_rmtfs_mem:
|
close_rmtfs_mem:
|
||||||
rmtfs_mem_close(rmem);
|
rmtfs_mem_close(rmem);
|
||||||
|
|
||||||
|
|||||||
23
rmtfs.h
23
rmtfs.h
@@ -23,11 +23,22 @@ void rmtfs_mem_free(struct rmtfs_mem *rmem);
|
|||||||
ssize_t rmtfs_mem_read(struct rmtfs_mem *rmem, unsigned long phys_address, void *buf, ssize_t len);
|
ssize_t rmtfs_mem_read(struct rmtfs_mem *rmem, unsigned long phys_address, void *buf, ssize_t len);
|
||||||
ssize_t rmtfs_mem_write(struct rmtfs_mem *rmem, unsigned long phys_address, const void *buf, ssize_t len);
|
ssize_t rmtfs_mem_write(struct rmtfs_mem *rmem, unsigned long phys_address, const void *buf, ssize_t len);
|
||||||
|
|
||||||
int storage_open(void);
|
struct rmtfd;
|
||||||
int storage_get(unsigned node, const char *path);
|
|
||||||
int storage_put(unsigned node, int caller_id);
|
int storage_init(const char *storage_root, bool read_only, bool use_partitions);
|
||||||
int storage_get_handle(unsigned node, int caller_id);
|
#define SLOT_SUFFIX_LEN (2 + 1) /* "_a" or "_b", null-terminated */
|
||||||
int storage_get_error(unsigned node, int caller_id);
|
struct rmtfd *storage_open(unsigned node, const char *path, const char *slot_suffix);
|
||||||
void storage_close(void);
|
struct rmtfd *storage_get(unsigned node, int caller_id);
|
||||||
|
void storage_close(struct rmtfd *rmtfd);
|
||||||
|
int storage_get_caller_id(const struct rmtfd *rmtfd);
|
||||||
|
int storage_get_error(const struct rmtfd *rmtfd);
|
||||||
|
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 storage_sync(struct rmtfd *rmtfd);
|
||||||
|
|
||||||
|
int rproc_init(void);
|
||||||
|
int rproc_start(void);
|
||||||
|
int rproc_stop(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
11
rmtfs.service.in
Normal file
11
rmtfs.service.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Qualcomm remotefs service
|
||||||
|
Before=NetworkManager.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=RMTFS_PATH/rmtfs -r -P -s
|
||||||
|
Restart=always
|
||||||
|
RestartSec=1
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
225
rproc.c
Normal file
225
rproc.c
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#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/"
|
||||||
|
#define RPROC_CLASS_PATH "/sys/class/remoteproc/"
|
||||||
|
|
||||||
|
static pthread_t start_thread;
|
||||||
|
static pthread_t stop_thread;
|
||||||
|
static int rproc_state_fd;
|
||||||
|
static int rproc_pipe[2];
|
||||||
|
|
||||||
|
static int rproc_init_by_modalias(void)
|
||||||
|
{
|
||||||
|
struct dirent *rproc_de;
|
||||||
|
char modalias[256];
|
||||||
|
DIR *base_dir;
|
||||||
|
int modalias_fd;
|
||||||
|
int rproc_fd;
|
||||||
|
int state_fd = -1;
|
||||||
|
int base_fd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
base_fd = open(RPROC_CLASS_PATH, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (base_fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
base_dir = fdopendir(base_fd);
|
||||||
|
if (!base_dir) {
|
||||||
|
fprintf(stderr, "failed to open remoteproc class path\n");
|
||||||
|
close(base_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (state_fd < 0 && (rproc_de = readdir(base_dir)) != NULL) {
|
||||||
|
if (!strcmp(rproc_de->d_name, ".") ||
|
||||||
|
!strcmp(rproc_de->d_name, ".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rproc_fd = openat(base_fd, rproc_de->d_name, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (rproc_fd < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
modalias_fd = openat(rproc_fd, "device/modalias", O_RDONLY);
|
||||||
|
if (modalias_fd < 0)
|
||||||
|
goto close_rproc_fd;
|
||||||
|
|
||||||
|
ret = read(modalias_fd, modalias, sizeof(modalias) - 1);
|
||||||
|
if (ret < 0)
|
||||||
|
goto close_modalias_fd;
|
||||||
|
modalias[ret] = '\0';
|
||||||
|
|
||||||
|
if (!strstr(modalias, "-mpss-pas") && !strstr(modalias, "-mss-pil"))
|
||||||
|
goto close_modalias_fd;
|
||||||
|
|
||||||
|
state_fd = openat(rproc_fd, "state", O_WRONLY);
|
||||||
|
if (state_fd < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"unable to open remoteproc \"state\" control file of %s\n",
|
||||||
|
rproc_de->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
close_modalias_fd:
|
||||||
|
close(modalias_fd);
|
||||||
|
close_rproc_fd:
|
||||||
|
close(rproc_fd);
|
||||||
|
}
|
||||||
|
closedir(base_dir);
|
||||||
|
close(base_fd);
|
||||||
|
|
||||||
|
return state_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rproc_init_by_mss_driver(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 state_fd = -1;
|
||||||
|
int base_fd;
|
||||||
|
|
||||||
|
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 (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 (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;
|
||||||
|
|
||||||
|
state_fd = openat(rproc_fd, "state", O_WRONLY);
|
||||||
|
if (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);
|
||||||
|
|
||||||
|
return state_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rproc_init(void)
|
||||||
|
{
|
||||||
|
int state_fd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
state_fd = rproc_init_by_modalias();
|
||||||
|
if (state_fd < 0) {
|
||||||
|
state_fd = rproc_init_by_mss_driver();
|
||||||
|
if (state_fd < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pipe(rproc_pipe);
|
||||||
|
if (ret < 0) {
|
||||||
|
close(state_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rproc_state_fd = state_fd;
|
||||||
|
|
||||||
|
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: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rproc_start()
|
||||||
|
{
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
|
return pthread_create(&start_thread, &attr, 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: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
|
return pthread_create(&stop_thread, &attr, do_rproc_stop, NULL);
|
||||||
|
}
|
||||||
215
sharedmem.c
215
sharedmem.c
@@ -4,7 +4,12 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#ifndef ANDROID
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
|
#else
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#endif
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -22,10 +27,12 @@ struct rmtfs_mem {
|
|||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef ANDROID
|
||||||
|
|
||||||
static int parse_hex_sysattr(struct udev_device *dev, const char *name,
|
static int parse_hex_sysattr(struct udev_device *dev, const char *name,
|
||||||
unsigned long *value)
|
uint64_t *value)
|
||||||
{
|
{
|
||||||
unsigned long val;
|
unsigned long long val;
|
||||||
const char *buf;
|
const char *buf;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
@@ -34,8 +41,8 @@ static int parse_hex_sysattr(struct udev_device *dev, const char *name,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
val = strtoul(buf, &endptr, 16);
|
val = strtoull(buf, &endptr, 16);
|
||||||
if ((val == LONG_MAX && errno == ERANGE) || endptr == buf) {
|
if ((val == ULLONG_MAX && errno == ERANGE) || endptr == buf) {
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +61,7 @@ static int rmtfs_mem_open_rfsa(struct rmtfs_mem *rmem, int client_id)
|
|||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
sprintf(path, "/dev/qcom_rfsa%d", client_id);
|
sprintf(path, "/dev/qcom_rmtfs_mem%d", client_id);
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
fd = open(path, O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@@ -114,6 +121,150 @@ err_close_fd:
|
|||||||
return -saved_errno;
|
return -saved_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rmtfs_mem_open_uio(struct rmtfs_mem *rmem, int client_id)
|
||||||
|
{
|
||||||
|
struct udev_device *dev;
|
||||||
|
struct udev *udev;
|
||||||
|
int saved_errno;
|
||||||
|
struct stat sb;
|
||||||
|
char path[32];
|
||||||
|
int ret;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/dev/qcom_rmtfs_uio%d", client_id);
|
||||||
|
|
||||||
|
fd = open(path, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
return -saved_errno;
|
||||||
|
}
|
||||||
|
rmem->fd = fd;
|
||||||
|
|
||||||
|
ret = fstat(fd, &sb);
|
||||||
|
if (ret < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to stat %s: %s\n", path, strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
udev = udev_new();
|
||||||
|
if (!udev) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to create udev context\n");
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = udev_device_new_from_devnum(udev, 'c', sb.st_rdev);
|
||||||
|
if (!dev) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "unable to find udev device\n");
|
||||||
|
goto err_unref_udev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = parse_hex_sysattr(dev, "maps/map0/addr", &rmem->address);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "failed to parse phys_addr of %s\n", path);
|
||||||
|
saved_errno = -ret;
|
||||||
|
goto err_unref_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = parse_hex_sysattr(dev, "maps/map0/size", &rmem->size);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "failed to parse size of %s\n", path);
|
||||||
|
saved_errno = -ret;
|
||||||
|
goto err_unref_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
rmem->base = mmap(0, rmem->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
if (rmem->base == MAP_FAILED) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to mmap: %s\n", strerror(errno));
|
||||||
|
goto err_unref_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
udev_device_unref(dev);
|
||||||
|
udev_unref(udev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_unref_dev:
|
||||||
|
udev_device_unref(dev);
|
||||||
|
err_unref_udev:
|
||||||
|
udev_unref(udev);
|
||||||
|
err_close_fd:
|
||||||
|
close(fd);
|
||||||
|
return -saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
static int rmtfs_mem_open_rfsa(struct rmtfs_mem *rmem, int client_id)
|
||||||
|
{
|
||||||
|
int saved_errno;
|
||||||
|
int fd;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char val[PAGE_SIZE];
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/dev/qcom_rmtfs_mem%d", client_id);
|
||||||
|
rmem->fd = open(path, O_RDWR);
|
||||||
|
if (rmem->fd < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
return -saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/sys/class/rmtfs/qcom_rmtfs_mem%d/phys_addr", client_id);
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
return -saved_errno;
|
||||||
|
}
|
||||||
|
read(fd, val, sizeof(val));
|
||||||
|
rmem->address = strtoull(val, &endptr, 16);
|
||||||
|
if ((rmem->address == ULLONG_MAX && errno == ERANGE) || endptr == val) {
|
||||||
|
saved_errno = errno;
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/sys/class/rmtfs/qcom_rmtfs_mem%d/size", client_id);
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno));
|
||||||
|
return -saved_errno;
|
||||||
|
}
|
||||||
|
read(fd, val, sizeof(val));
|
||||||
|
rmem->size = strtoull(val, &endptr, 16);
|
||||||
|
if ((rmem->size == ULLONG_MAX && errno == ERANGE) || endptr == val) {
|
||||||
|
saved_errno = errno;
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_close_fd:
|
||||||
|
close(fd);
|
||||||
|
return -saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rmtfs_mem_open_uio(struct rmtfs_mem *rmem, int client_id)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "uio access is not supported on ANDROID yet\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
struct rmtfs_mem *rmtfs_mem_open(void)
|
struct rmtfs_mem *rmtfs_mem_open(void)
|
||||||
{
|
{
|
||||||
struct rmtfs_mem *rmem;
|
struct rmtfs_mem *rmem;
|
||||||
@@ -131,26 +282,32 @@ struct rmtfs_mem *rmtfs_mem_open(void)
|
|||||||
if (ret < 0 && ret != -ENOENT) {
|
if (ret < 0 && ret != -ENOENT) {
|
||||||
goto err;
|
goto err;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
fprintf(stderr, "falling back to /dev/mem access\n");
|
fprintf(stderr, "falling back to uio access\n");
|
||||||
|
ret = rmtfs_mem_open_uio(rmem, 1);
|
||||||
ret = rmtfs_mem_enumerate(rmem);
|
if (ret < 0 && ret != -ENOENT) {
|
||||||
if (ret < 0)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
fprintf(stderr, "falling back to /dev/mem access\n");
|
||||||
|
|
||||||
fd = open("/dev/mem", O_RDWR|O_SYNC);
|
ret = rmtfs_mem_enumerate(rmem);
|
||||||
if (fd < 0) {
|
if (ret < 0)
|
||||||
fprintf(stderr, "failed to open /dev/mem\n");
|
goto err;
|
||||||
goto err;
|
|
||||||
|
fd = open("/dev/mem", O_RDWR|O_SYNC);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "failed to open /dev/mem\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = mmap(0, rmem->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, rmem->address);
|
||||||
|
if (base == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "failed to mmap: %s\n", strerror(errno));
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
rmem->base = base;
|
||||||
|
rmem->fd = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = mmap(0, rmem->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, rmem->address);
|
|
||||||
if (base == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "failed to mmap: %s\n", strerror(errno));
|
|
||||||
goto err_close_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
rmem->base = base;
|
|
||||||
rmem->fd = fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rmem;
|
return rmem;
|
||||||
@@ -166,7 +323,7 @@ int64_t rmtfs_mem_alloc(struct rmtfs_mem *rmem, size_t alloc_size)
|
|||||||
{
|
{
|
||||||
if (alloc_size > rmem->size) {
|
if (alloc_size > rmem->size) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"[RMTFS] rmtfs shared memory not large enough for allocation request 0x%zx vs 0x%lx\n",
|
"[RMTFS] rmtfs shared memory not large enough for allocation request 0x%zx vs %" PRIu64 "\n",
|
||||||
alloc_size, rmem->size);
|
alloc_size, rmem->size);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -178,7 +335,7 @@ void rmtfs_mem_free(struct rmtfs_mem *rmem)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *rmtfs_mem_ptr(struct rmtfs_mem *rmem, unsigned phys_address, ssize_t len)
|
static void *rmtfs_mem_ptr(struct rmtfs_mem *rmem, unsigned long phys_address, ssize_t len)
|
||||||
{
|
{
|
||||||
uint64_t start;
|
uint64_t start;
|
||||||
uint64_t end;
|
uint64_t end;
|
||||||
@@ -192,7 +349,7 @@ static void *rmtfs_mem_ptr(struct rmtfs_mem *rmem, unsigned phys_address, ssize_
|
|||||||
if (start < rmem->address || end > rmem->address + rmem->size)
|
if (start < rmem->address || end > rmem->address + rmem->size)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return rmem->base + phys_address - rmem->address;
|
return (char*)rmem->base + phys_address - rmem->address;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t rmtfs_mem_read(struct rmtfs_mem *rmem, unsigned long phys_address, void *buf, ssize_t len)
|
ssize_t rmtfs_mem_read(struct rmtfs_mem *rmem, unsigned long phys_address, void *buf, ssize_t len)
|
||||||
@@ -262,7 +419,7 @@ static int rmtfs_mem_enumerate(struct rmtfs_mem *rmem)
|
|||||||
if (!dir) {
|
if (!dir) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Unable to open reserved-memory device tree node: %s\n",
|
"Unable to open reserved-memory device tree node: %s\n",
|
||||||
strerror(-errno));
|
strerror(errno));
|
||||||
close(basefd);
|
close(basefd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -274,7 +431,7 @@ static int rmtfs_mem_enumerate(struct rmtfs_mem *rmem)
|
|||||||
dirfd = openat(basefd, de->d_name, O_DIRECTORY);
|
dirfd = openat(basefd, de->d_name, O_DIRECTORY);
|
||||||
if (dirfd < 0) {
|
if (dirfd < 0) {
|
||||||
fprintf(stderr, "failed to open %s: %s\n",
|
fprintf(stderr, "failed to open %s: %s\n",
|
||||||
de->d_name, strerror(-errno));
|
de->d_name, strerror(errno));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -282,7 +439,7 @@ static int rmtfs_mem_enumerate(struct rmtfs_mem *rmem)
|
|||||||
regfd = openat(dirfd, "reg", O_RDONLY);
|
regfd = openat(dirfd, "reg", O_RDONLY);
|
||||||
if (regfd < 0) {
|
if (regfd < 0) {
|
||||||
fprintf(stderr, "failed to open reg of %s: %s\n",
|
fprintf(stderr, "failed to open reg of %s: %s\n",
|
||||||
de->d_name, strerror(-errno));
|
de->d_name, strerror(errno));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -296,7 +453,7 @@ static int rmtfs_mem_enumerate(struct rmtfs_mem *rmem)
|
|||||||
rmem->size = be64toh(reg.qw[1]);
|
rmem->size = be64toh(reg.qw[1]);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "failed to read reg of %s: %s\n",
|
fprintf(stderr, "failed to read reg of %s: %s\n",
|
||||||
de->d_name, strerror(-errno));
|
de->d_name, strerror(errno));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
303
storage.c
303
storage.c
@@ -1,3 +1,4 @@
|
|||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -8,48 +9,109 @@
|
|||||||
#include "rmtfs.h"
|
#include "rmtfs.h"
|
||||||
|
|
||||||
#define MAX_CALLERS 10
|
#define MAX_CALLERS 10
|
||||||
|
#define STORAGE_MAX_SIZE (16 * 1024 * 1024)
|
||||||
|
|
||||||
|
#define BY_PARTLABEL_PATH "/dev/disk/by-partlabel"
|
||||||
|
|
||||||
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||||
|
|
||||||
struct partition {
|
struct partition {
|
||||||
const char *path;
|
const char *path;
|
||||||
const char *actual;
|
const char *actual;
|
||||||
|
const char *partlabel;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct caller {
|
struct rmtfd {
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned node;
|
unsigned node;
|
||||||
int fd;
|
int fd;
|
||||||
unsigned dev_error;
|
unsigned dev_error;
|
||||||
const struct partition *partition;
|
const struct partition *partition;
|
||||||
|
|
||||||
|
void *shadow_buf;
|
||||||
|
size_t shadow_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *storage_dir = "/boot";
|
||||||
|
static int storage_read_only;
|
||||||
|
static int storage_use_partitions;
|
||||||
|
|
||||||
static const struct partition partition_table[] = {
|
static const struct partition partition_table[] = {
|
||||||
{ "/boot/modem_fs1", "/boot/modem_fs1" },
|
{ "/boot/modem_fs1", "modem_fs1", "modemst1" },
|
||||||
{ "/boot/modem_fs2", "/boot/modem_fs2" },
|
{ "/boot/modem_fs2", "modem_fs2", "modemst2" },
|
||||||
{ "/boot/modem_fsc", "/boot/modem_fsc" },
|
{ "/boot/modem_fsc", "modem_fsc", "fsc" },
|
||||||
{ "/boot/modem_fsg", "/boot/modem_fsg" },
|
{ "/boot/modem_fsg", "modem_fsg", "fsg" },
|
||||||
|
{ "/boot/modem_study", "modem_study", "study" },
|
||||||
|
{ "/boot/modem_tunning", "modem_tunning", "tunning" },
|
||||||
|
{ "/boot/modem_tng", "modem_tng", "tunning" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct caller caller_handles[MAX_CALLERS];
|
static struct rmtfd rmtfds[MAX_CALLERS];
|
||||||
|
|
||||||
int storage_open(void)
|
static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file);
|
||||||
|
|
||||||
|
int storage_init(const char *storage_root, bool read_only, bool use_partitions)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (storage_root)
|
||||||
|
storage_dir = storage_root;
|
||||||
|
|
||||||
|
if (use_partitions) {
|
||||||
|
if (!storage_root)
|
||||||
|
storage_dir = BY_PARTLABEL_PATH;
|
||||||
|
storage_use_partitions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage_read_only = read_only;
|
||||||
|
|
||||||
for (i = 0; i < MAX_CALLERS; i++) {
|
for (i = 0; i < MAX_CALLERS; i++) {
|
||||||
caller_handles[i].id = i;
|
rmtfds[i].id = i;
|
||||||
caller_handles[i].fd = -1;
|
rmtfds[i].fd = -1;
|
||||||
|
rmtfds[i].shadow_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int storage_get(unsigned node, const char *path)
|
static int fd_open(struct rmtfd *rmtfd, const char *fspath, const struct partition *part)
|
||||||
{
|
{
|
||||||
const struct partition *part;
|
|
||||||
struct caller *caller = NULL;
|
|
||||||
int saved_errno;
|
int saved_errno;
|
||||||
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
if (!storage_read_only) {
|
||||||
|
fd = open(fspath, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
|
||||||
|
fspath, part->path, strerror(saved_errno));
|
||||||
|
return saved_errno;
|
||||||
|
}
|
||||||
|
rmtfd->fd = fd;
|
||||||
|
rmtfd->shadow_len = 0;
|
||||||
|
} else {
|
||||||
|
ret = storage_populate_shadow_buf(rmtfd, fspath);
|
||||||
|
if (ret < 0) {
|
||||||
|
saved_errno = errno;
|
||||||
|
fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
|
||||||
|
fspath, part->path, strerror(saved_errno));
|
||||||
|
return saved_errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rmtfd *storage_open(unsigned node, const char *path, const char *slot_suffix)
|
||||||
|
{
|
||||||
|
char *fspath;
|
||||||
|
const struct partition *part;
|
||||||
|
struct rmtfd *rmtfd = NULL;
|
||||||
|
const char *file;
|
||||||
|
size_t pathlen;
|
||||||
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (part = partition_table; part->path; part++) {
|
for (part = partition_table; part->path; part++) {
|
||||||
@@ -58,96 +120,197 @@ int storage_get(unsigned node, const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "[RMTFS storage] request for unknown partition '%s', rejecting\n", path);
|
fprintf(stderr, "[RMTFS storage] request for unknown partition '%s', rejecting\n", path);
|
||||||
return -EPERM;
|
return NULL;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
/* Check if this node already has the requested path open */
|
/* Check if this node already has the requested path open */
|
||||||
for (i = 0; i < MAX_CALLERS; i++) {
|
for (i = 0; i < MAX_CALLERS; i++) {
|
||||||
if (caller_handles[i].fd != -1 &&
|
if ((rmtfds[i].fd != -1 || rmtfds[i].shadow_buf) &&
|
||||||
caller_handles[i].node == node &&
|
rmtfds[i].node == node &&
|
||||||
caller_handles[i].partition == part)
|
rmtfds[i].partition == part)
|
||||||
return caller_handles[i].id;
|
return &rmtfds[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_CALLERS; i++) {
|
for (i = 0; i < MAX_CALLERS; i++) {
|
||||||
if (caller_handles[i].fd == -1) {
|
if (rmtfds[i].fd == -1 && !rmtfds[i].shadow_buf) {
|
||||||
caller = &caller_handles[i];
|
rmtfd = &rmtfds[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!caller) {
|
if (!rmtfd) {
|
||||||
fprintf(stderr, "[storage] out of free caller handles\n");
|
fprintf(stderr, "[storage] out of free rmtfd handles\n");
|
||||||
return -EBUSY;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(part->actual, O_RDWR);
|
if (storage_use_partitions)
|
||||||
if (fd < 0) {
|
file = part->partlabel;
|
||||||
saved_errno = errno;
|
else
|
||||||
fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
|
file = part->actual;
|
||||||
part->actual, part->path, strerror(-errno));
|
|
||||||
return -saved_errno;
|
pathlen = strlen(storage_dir) + strlen(file) + 2 + strnlen(slot_suffix, SLOT_SUFFIX_LEN);
|
||||||
|
fspath = alloca(pathlen);
|
||||||
|
snprintf(fspath, pathlen, "%s/%s", storage_dir, file);
|
||||||
|
ret = fd_open(rmtfd, fspath, part);
|
||||||
|
if (ret) {
|
||||||
|
/* Try again with the slot suffix before giving up */
|
||||||
|
if (!slot_suffix)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
snprintf(fspath, pathlen, "%s/%s%s", storage_dir, file, slot_suffix);
|
||||||
|
ret = fd_open(rmtfd, fspath, part);
|
||||||
|
if (ret)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
caller->node = node;
|
rmtfd->node = node;
|
||||||
caller->fd = fd;
|
rmtfd->partition = part;
|
||||||
caller->partition = part;
|
|
||||||
|
|
||||||
return caller->id;
|
return rmtfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int storage_put(unsigned node, int caller_id)
|
void storage_close(struct rmtfd *rmtfd)
|
||||||
{
|
{
|
||||||
struct caller *caller;
|
if (rmtfd->fd >= 0) {
|
||||||
|
close(rmtfd->fd);
|
||||||
|
rmtfd->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(rmtfd->shadow_buf);
|
||||||
|
rmtfd->shadow_buf = NULL;
|
||||||
|
rmtfd->shadow_len = 0;
|
||||||
|
|
||||||
|
rmtfd->partition = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rmtfd *storage_get(unsigned node, int caller_id)
|
||||||
|
{
|
||||||
|
struct rmtfd *rmtfd;
|
||||||
|
|
||||||
if (caller_id >= MAX_CALLERS)
|
if (caller_id >= MAX_CALLERS)
|
||||||
return -EINVAL;
|
return NULL;
|
||||||
|
|
||||||
caller = &caller_handles[caller_id];
|
rmtfd = &rmtfds[caller_id];
|
||||||
if (caller->node != node)
|
if (rmtfd->node != node)
|
||||||
return -EINVAL;
|
return NULL;
|
||||||
|
|
||||||
close(caller->fd);
|
return rmtfd;
|
||||||
caller->fd = -1;
|
|
||||||
caller->partition = NULL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int storage_get_handle(unsigned node, int caller_id)
|
int storage_get_caller_id(const struct rmtfd *rmtfd)
|
||||||
{
|
{
|
||||||
struct caller *caller;
|
return rmtfd->id;
|
||||||
|
|
||||||
if (caller_id >= MAX_CALLERS)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
caller = &caller_handles[caller_id];
|
|
||||||
if (caller->node != node)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return caller->fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int storage_get_error(unsigned node, int caller_id)
|
int storage_get_error(const struct rmtfd *rmtfd)
|
||||||
{
|
{
|
||||||
struct caller *caller;
|
return rmtfd->dev_error;
|
||||||
|
|
||||||
if (caller_id >= MAX_CALLERS)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
caller = &caller_handles[caller_id];
|
|
||||||
if (caller->node != node)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return caller->dev_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void storage_close(void)
|
void storage_exit(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MAX_CALLERS; i++) {
|
for (i = 0; i < MAX_CALLERS; i++)
|
||||||
if (caller_handles[i].fd >= 0)
|
storage_close(&rmtfds[i]);
|
||||||
close(caller_handles[i].fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset)
|
||||||
|
{
|
||||||
|
ssize_t n;
|
||||||
|
|
||||||
|
if (!storage_read_only) {
|
||||||
|
n = pread(rmtfd->fd, buf, nbyte, offset);
|
||||||
|
} else {
|
||||||
|
n = MIN((ssize_t)nbyte, (ssize_t)rmtfd->shadow_len - offset);
|
||||||
|
if (n > 0)
|
||||||
|
memcpy(buf, (char*)rmtfd->shadow_buf + offset, n);
|
||||||
|
else
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < nbyte)
|
||||||
|
memset((char*)buf + n, 0, nbyte - n);
|
||||||
|
|
||||||
|
return nbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
|
||||||
|
{
|
||||||
|
size_t new_len = offset + nbyte;
|
||||||
|
void *new_buf;
|
||||||
|
|
||||||
|
if (!storage_read_only)
|
||||||
|
return pwrite(rmtfd->fd, buf, nbyte, offset);
|
||||||
|
|
||||||
|
if (new_len >= STORAGE_MAX_SIZE) {
|
||||||
|
fprintf(stderr, "write to %zd bytes exceededs max size\n", new_len);
|
||||||
|
errno = -EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_len > rmtfd->shadow_len) {
|
||||||
|
new_buf = realloc(rmtfd->shadow_buf, new_len);
|
||||||
|
if (!new_buf) {
|
||||||
|
errno = -ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rmtfd->shadow_buf = new_buf;
|
||||||
|
rmtfd->shadow_len = new_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((char*)rmtfd->shadow_buf + offset, buf, nbyte);
|
||||||
|
|
||||||
|
return nbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
int storage_sync(struct rmtfd *rmtfd)
|
||||||
|
{
|
||||||
|
if (storage_read_only)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return fdatasync(rmtfd->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file)
|
||||||
|
{
|
||||||
|
ssize_t len;
|
||||||
|
ssize_t n;
|
||||||
|
void *buf;
|
||||||
|
int ret;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(file, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
len = lseek(fd, 0, SEEK_END);
|
||||||
|
if (len < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
buf = calloc(1, len);
|
||||||
|
if (!buf) {
|
||||||
|
ret = -1;
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = read(fd, buf, len);
|
||||||
|
if (n < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto err_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
rmtfd->shadow_buf = buf;
|
||||||
|
rmtfd->shadow_len = n;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
err_close_fd:
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user