mirror of
https://gitee.com/openharmony/third_party_f2fs-tools
synced 2024-11-23 10:10:00 +00:00
add sparse support for f2fs
Description: modify I/O operations to support writing in sparse format build host executable for making sparse image Signed-off-by: Yang Jin <yajin@google.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
ea008a24f7
commit
4abc53c38f
@ -256,6 +256,7 @@ struct device_info {
|
||||
struct f2fs_configuration {
|
||||
u_int32_t reserved_segments;
|
||||
u_int32_t new_reserved_segments;
|
||||
int sparse_mode;
|
||||
int zoned_mode;
|
||||
int zoned_model;
|
||||
size_t zone_blocks;
|
||||
@ -268,6 +269,7 @@ struct f2fs_configuration {
|
||||
u_int32_t start_sector;
|
||||
u_int32_t total_segments;
|
||||
u_int32_t sector_size;
|
||||
u_int64_t device_size;
|
||||
u_int64_t total_sectors;
|
||||
u_int64_t wanted_total_sectors;
|
||||
u_int64_t target_sectors;
|
||||
|
@ -32,6 +32,10 @@
|
||||
#define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32 /* O_BINARY is windows-specific flag */
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* UTF conversion codes are Copied from exfat tools.
|
||||
*/
|
||||
@ -689,7 +693,11 @@ int get_device_info(int i)
|
||||
#endif
|
||||
struct device_info *dev = c.devices + i;
|
||||
|
||||
fd = open((char *)dev->path, O_RDWR);
|
||||
if (c.sparse_mode) {
|
||||
fd = open((char *)dev->path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
|
||||
} else {
|
||||
fd = open((char *)dev->path, O_RDWR);
|
||||
}
|
||||
if (fd < 0) {
|
||||
MSG(0, "\tError: Failed to open the device!\n");
|
||||
return -1;
|
||||
@ -710,7 +718,9 @@ int get_device_info(int i)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (S_ISREG(stat_buf.st_mode)) {
|
||||
if (c.sparse_mode) {
|
||||
dev->total_sectors = c.device_size / dev->sector_size;
|
||||
} else if (S_ISREG(stat_buf.st_mode)) {
|
||||
dev->total_sectors = stat_buf.st_size / dev->sector_size;
|
||||
} else if (S_ISBLK(stat_buf.st_mode)) {
|
||||
if (ioctl(fd, BLKSSZGET, §or_size) < 0)
|
||||
|
@ -25,6 +25,19 @@
|
||||
|
||||
struct f2fs_configuration c;
|
||||
|
||||
#ifdef WITH_ANDROID
|
||||
#include <sparse/sparse.h>
|
||||
struct sparse_file *f2fs_sparse_file;
|
||||
|
||||
struct buf_item {
|
||||
void *buf;
|
||||
size_t len;
|
||||
struct buf_item *next;
|
||||
};
|
||||
|
||||
struct buf_item *buf_list;
|
||||
#endif
|
||||
|
||||
static int __get_device_fd(__u64 *offset)
|
||||
{
|
||||
__u64 blk_addr = *offset >> F2FS_BLKSIZE_BITS;
|
||||
@ -46,6 +59,8 @@ static int __get_device_fd(__u64 *offset)
|
||||
*/
|
||||
int dev_read_version(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
if (c.sparse_mode)
|
||||
return 0;
|
||||
if (lseek64(c.kd, (off64_t)offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
if (read(c.kd, buf, len) < 0)
|
||||
@ -55,8 +70,12 @@ int dev_read_version(void *buf, __u64 offset, size_t len)
|
||||
|
||||
int dev_read(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
int fd = __get_device_fd(&offset);
|
||||
int fd;
|
||||
|
||||
if (c.sparse_mode)
|
||||
return 0;
|
||||
|
||||
fd = __get_device_fd(&offset);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@ -80,10 +99,40 @@ int dev_readahead(__u64 offset, size_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_ANDROID
|
||||
static int dev_write_sparse(void *buf, __u64 byte_offset, size_t byte_len)
|
||||
{
|
||||
struct buf_item *bi = calloc(1, sizeof(struct buf_item));
|
||||
|
||||
if (bi == NULL) {
|
||||
return -1;
|
||||
}
|
||||
bi->buf = malloc(byte_len);
|
||||
if (bi->buf == NULL) {
|
||||
free(bi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bi->len = byte_len;
|
||||
memcpy(bi->buf, buf, byte_len);
|
||||
bi->next = buf_list;
|
||||
buf_list = bi;
|
||||
|
||||
sparse_file_add_data(f2fs_sparse_file, bi->buf, byte_len, byte_offset/F2FS_BLKSIZE);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int dev_write_sparse(void *buf, __u64 byte_offset, size_t byte_len) { return 0; }
|
||||
#endif
|
||||
|
||||
int dev_write(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
int fd = __get_device_fd(&offset);
|
||||
int fd;
|
||||
|
||||
if (c.sparse_mode)
|
||||
return dev_write_sparse(buf, offset, len);
|
||||
|
||||
fd = __get_device_fd(&offset);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@ -110,8 +159,12 @@ int dev_write_dump(void *buf, __u64 offset, size_t len)
|
||||
|
||||
int dev_fill(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
int fd = __get_device_fd(&offset);
|
||||
int fd;
|
||||
|
||||
if (c.sparse_mode)
|
||||
return 0;
|
||||
|
||||
fd = __get_device_fd(&offset);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@ -144,6 +197,20 @@ void f2fs_finalize_device(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef WITH_ANDROID
|
||||
if (c.sparse_mode) {
|
||||
sparse_file_write(f2fs_sparse_file, c.devices[0].fd, /*gzip*/0, /*sparse*/1, /*crc*/0);
|
||||
sparse_file_destroy(f2fs_sparse_file);
|
||||
while (buf_list) {
|
||||
struct buf_item *bi = buf_list;
|
||||
buf_list = buf_list->next;
|
||||
free(bi->buf);
|
||||
free(bi);
|
||||
}
|
||||
f2fs_sparse_file = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We should call fsync() to flush out all the dirty pages
|
||||
* in the block device page cache.
|
||||
|
@ -27,6 +27,11 @@
|
||||
#include "f2fs_fs.h"
|
||||
#include "f2fs_format_utils.h"
|
||||
|
||||
#ifdef WITH_ANDROID
|
||||
#include <sparse/sparse.h>
|
||||
extern struct sparse_file *f2fs_sparse_file;
|
||||
#endif
|
||||
|
||||
extern struct f2fs_configuration c;
|
||||
static int force_overwrite = 0;
|
||||
|
||||
@ -45,6 +50,7 @@ static void mkfs_usage()
|
||||
MSG(0, " -O [feature list] e.g. \"encrypt\"\n");
|
||||
MSG(0, " -q quiet mode\n");
|
||||
MSG(0, " -s # of segments per section [default:1]\n");
|
||||
MSG(0, " -S sparse mode\n");
|
||||
MSG(0, " -t 0: nodiscard, 1: discard [default:1]\n");
|
||||
MSG(0, " -z # of sections per zone [default:1]\n");
|
||||
MSG(0, "sectors: number of sectors. [default: determined by device size]\n");
|
||||
@ -82,7 +88,7 @@ static void parse_feature(const char *features)
|
||||
|
||||
static void f2fs_parse_options(int argc, char *argv[])
|
||||
{
|
||||
static const char *option_string = "qa:c:d:e:l:mo:O:s:z:t:f";
|
||||
static const char *option_string = "qa:c:d:e:l:mo:O:s:S:z:t:f";
|
||||
int32_t option=0;
|
||||
|
||||
while ((option = getopt(argc,argv,option_string)) != EOF) {
|
||||
@ -132,6 +138,11 @@ static void f2fs_parse_options(int argc, char *argv[])
|
||||
case 's':
|
||||
c.segs_per_sec = atoi(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
c.device_size = atoll(optarg);
|
||||
c.device_size &= (~((u_int64_t)(F2FS_BLKSIZE - 1)));
|
||||
c.sparse_mode = 1;
|
||||
break;
|
||||
case 'z':
|
||||
c.secs_per_zone = atoi(optarg);
|
||||
break;
|
||||
@ -164,6 +175,9 @@ static void f2fs_parse_options(int argc, char *argv[])
|
||||
c.wanted_total_sectors = atoll(argv[optind+1]);
|
||||
}
|
||||
|
||||
if (c.sparse_mode)
|
||||
c.trim = 0;
|
||||
|
||||
if (c.zoned_mode)
|
||||
c.feature |= cpu_to_le32(F2FS_FEATURE_BLKZONED);
|
||||
}
|
||||
@ -277,6 +291,17 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (c.sparse_mode) {
|
||||
#ifndef WITH_ANDROID
|
||||
MSG(0, "\tError: Sparse mode is only supported for android\n");
|
||||
return -1;
|
||||
#else
|
||||
if (f2fs_sparse_file)
|
||||
sparse_file_destroy(f2fs_sparse_file);
|
||||
f2fs_sparse_file = sparse_file_new(F2FS_BLKSIZE, c.device_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (f2fs_format_device() < 0)
|
||||
return -1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user