mirror of
https://github.com/linux-msm/rmtfs.git
synced 2025-12-24 22:19:15 +01:00
storage: Allow read only backing storage
Add a new argument '-r' to prevent writes back to the backing storage. This is useful for experimenting with the remote storage, without having the files overwritten. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
10
rmtfs.c
10
rmtfs.c
@@ -449,17 +449,23 @@ static int run_rmtfs(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bool read_only = false;
|
||||
int ret;
|
||||
int option;
|
||||
const char *storage_root = NULL;
|
||||
|
||||
while ((option = getopt(argc, argv, "o:v")) != -1) {
|
||||
while ((option = getopt(argc, argv, "o:rv")) != -1) {
|
||||
switch (option) {
|
||||
/* -o sets the directory where EFS images are stored. */
|
||||
case 'o':
|
||||
storage_root = optarg;
|
||||
break;
|
||||
|
||||
/* -r to avoid writing to storage */
|
||||
case 'r':
|
||||
read_only = true;
|
||||
break;
|
||||
|
||||
/* -v is for verbose */
|
||||
case 'v':
|
||||
dbgprintf_enabled = 1;
|
||||
@@ -475,7 +481,7 @@ int main(int argc, char **argv)
|
||||
if (!rmem)
|
||||
return 1;
|
||||
|
||||
ret = storage_init(storage_root);
|
||||
ret = storage_init(storage_root, read_only);
|
||||
if (ret) {
|
||||
fprintf(stderr, "failed to initialize storage system\n");
|
||||
goto close_rmtfs_mem;
|
||||
|
||||
4
rmtfs.h
4
rmtfs.h
@@ -25,7 +25,7 @@ ssize_t rmtfs_mem_write(struct rmtfs_mem *rmem, unsigned long phys_address, cons
|
||||
|
||||
struct rmtfd;
|
||||
|
||||
int storage_init(const char *storage_root);
|
||||
int storage_init(const char *storage_root, bool read_only);
|
||||
struct rmtfd *storage_open(unsigned node, const char *path);
|
||||
struct rmtfd *storage_get(unsigned node, int caller_id);
|
||||
void storage_close(struct rmtfd *rmtfd);
|
||||
@@ -33,6 +33,6 @@ 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(const struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset);
|
||||
ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset);
|
||||
|
||||
#endif
|
||||
|
||||
136
storage.c
136
storage.c
@@ -1,3 +1,4 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -8,6 +9,9 @@
|
||||
#include "rmtfs.h"
|
||||
|
||||
#define MAX_CALLERS 10
|
||||
#define STORAGE_MAX_SIZE (16 * 1024 * 1024)
|
||||
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
struct partition {
|
||||
const char *path;
|
||||
@@ -20,9 +24,13 @@ struct rmtfd {
|
||||
int fd;
|
||||
unsigned dev_error;
|
||||
const struct partition *partition;
|
||||
|
||||
void *shadow_buf;
|
||||
size_t shadow_len;
|
||||
};
|
||||
|
||||
static const char *storage_dir = "/boot";
|
||||
static int storage_read_only;
|
||||
|
||||
static const struct partition partition_table[] = {
|
||||
{ "/boot/modem_fs1", "modem_fs1" },
|
||||
@@ -34,13 +42,17 @@ static const struct partition partition_table[] = {
|
||||
|
||||
static struct rmtfd rmtfds[MAX_CALLERS];
|
||||
|
||||
int storage_init(const char *storage_root)
|
||||
static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file);
|
||||
|
||||
int storage_init(const char *storage_root, bool read_only)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (storage_root)
|
||||
storage_dir = storage_root;
|
||||
|
||||
storage_read_only = read_only;
|
||||
|
||||
for (i = 0; i < MAX_CALLERS; i++) {
|
||||
rmtfds[i].id = i;
|
||||
rmtfds[i].fd = -1;
|
||||
@@ -56,6 +68,7 @@ struct rmtfd *storage_open(unsigned node, const char *path)
|
||||
struct rmtfd *rmtfd = NULL;
|
||||
size_t pathlen;
|
||||
int saved_errno;
|
||||
int ret;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
@@ -90,17 +103,29 @@ found:
|
||||
pathlen = strlen(storage_dir) + strlen(part->actual) + 2;
|
||||
fspath = alloca(pathlen);
|
||||
snprintf(fspath, pathlen, "%s/%s", storage_dir, part->actual);
|
||||
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));
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
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));
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
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));
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
rmtfd->node = node;
|
||||
rmtfd->fd = fd;
|
||||
rmtfd->partition = part;
|
||||
|
||||
return rmtfd;
|
||||
@@ -110,6 +135,11 @@ void storage_close(struct rmtfd *rmtfd)
|
||||
{
|
||||
close(rmtfd->fd);
|
||||
rmtfd->fd = -1;
|
||||
|
||||
free(rmtfd->shadow_buf);
|
||||
rmtfd->shadow_buf = NULL;
|
||||
rmtfd->shadow_len = 0;
|
||||
|
||||
rmtfd->partition = NULL;
|
||||
}
|
||||
|
||||
@@ -149,11 +179,93 @@ void storage_exit(void)
|
||||
|
||||
ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset)
|
||||
{
|
||||
return pread(rmtfd->fd, buf, nbyte, offset);
|
||||
ssize_t n;
|
||||
|
||||
if (!storage_read_only) {
|
||||
n = pread(rmtfd->fd, buf, nbyte, offset);
|
||||
} else {
|
||||
n = MIN(nbyte, rmtfd->shadow_len - offset);
|
||||
if (n > 0)
|
||||
memcpy(buf, rmtfd->shadow_buf + offset, n);
|
||||
else
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if (n < nbyte)
|
||||
memset(buf + n, 0, nbyte - n);
|
||||
|
||||
return nbyte;
|
||||
}
|
||||
|
||||
ssize_t storage_pwrite(const struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
|
||||
ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
|
||||
{
|
||||
return pwrite(rmtfd->fd, buf, nbyte, 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(rmtfd->shadow_buf + offset, buf, nbyte);
|
||||
|
||||
return nbyte;
|
||||
}
|
||||
|
||||
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