Skip to content
This repository has been archived by the owner on Dec 15, 2023. It is now read-only.

Commit

Permalink
Synchronized direct block device I/O & erase support
Browse files Browse the repository at this point in the history
* Open block device with O_SYNC | O_DIRECT to bypass host caches
* Implement a custom scheme to support block erase

Change-Id: I5bd70ae04426d34f4ea8a975f1c06e5c8e47fdb3
GitOrigin-RevId: 219613721786ebab9a85984db015322664732e8b
  • Loading branch information
Googler committed Oct 12, 2022
1 parent f6be262 commit 8311b60
Showing 1 changed file with 45 additions and 4 deletions.
49 changes: 45 additions & 4 deletions lfs_fuse_bd.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#define _GNU_SOURCE 1

#include "lfs_fuse_bd.h"

#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <assert.h>
#include <malloc.h>
#include <arpa/inet.h>
#if !defined(__FreeBSD__)
#include <sys/ioctl.h>
#include <linux/fs.h>
Expand All @@ -23,7 +27,7 @@

// Block device wrapper for user-space block devices
int lfs_fuse_bd_create(struct lfs_config *cfg, const char *path) {
int fd = open(path, O_RDWR);
int fd = open(path, O_RDWR | O_SYNC | O_DIRECT);
if (fd < 0) {
return -errno;
}
Expand Down Expand Up @@ -77,10 +81,14 @@ int lfs_fuse_bd_read(const struct lfs_config *cfg, lfs_block_t block,
}

// read block
ssize_t res = read(fd, buffer, (size_t)size);
void *aligned = memalign(cfg->read_size, size);
ssize_t res = read(fd, aligned, (size_t)size);
if (res < 0) {
free(aligned);
return -errno;
}
memcpy(buffer, aligned, size);
free(aligned);

return 0;
}
Expand All @@ -99,16 +107,49 @@ int lfs_fuse_bd_prog(const struct lfs_config *cfg, lfs_block_t block,
}

// write block
ssize_t res = write(fd, buffer, (size_t)size);
void *aligned = memalign(cfg->prog_size, size);
memcpy(aligned, buffer, size);
ssize_t res = write(fd, aligned, (size_t)size);
if (res < 0) {
free(aligned);
return -errno;
}
free(aligned);

return 0;
}

int lfs_fuse_bd_erase(const struct lfs_config *cfg, lfs_block_t block) {
// do nothing
// Custom: erase requests are written to block 0 with buffer contents
// [ 0xdeadbeef, block_num_32b] in network byte order.

int fd = (intptr_t)cfg->context;

// check if erase is valid
assert(block < cfg->block_count);

// go to block 0
off_t err = lseek(fd, 0, SEEK_SET);
if (err < 0) {
return -errno;
}

// prepare buffer
uint32_t network;
uint8_t *aligned = memalign(cfg->prog_size, cfg->prog_size);
network = htonl(0xdeadbeef);
memcpy(aligned, &network, sizeof(network));
network = htonl(block);
memcpy(aligned + sizeof(network), &network, sizeof(network));

// write block to trigger erase
ssize_t res = write(fd, aligned, cfg->prog_size);
if (res < 0) {
free(aligned);
return -errno;
}
free(aligned);

return 0;
}

Expand Down

0 comments on commit 8311b60

Please sign in to comment.