mirror of
https://gitee.com/openharmony/third_party_f2fs-tools
synced 2024-11-26 19:51:32 +00:00
f2fs-tools: support multiple devices
This patch adds an option to specify multiple devices for an f2fs instance. Up to 7 devices in addition to the default device can be added. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
ea1bd1ce31
commit
de7e07e011
@ -301,7 +301,7 @@ void f2fs_parse_options(int argc, char *argv[])
|
||||
else if (c.func == SLOAD)
|
||||
sload_usage();
|
||||
}
|
||||
c.device_name = argv[optind];
|
||||
c.devices[0].path = strdup(argv[optind]);
|
||||
}
|
||||
|
||||
static void do_fsck(struct f2fs_sb_info *sbi)
|
||||
@ -474,7 +474,7 @@ int main(int argc, char **argv)
|
||||
|
||||
f2fs_parse_options(argc, argv);
|
||||
|
||||
if (f2fs_dev_is_umounted() < 0) {
|
||||
if (f2fs_devs_are_umounted() < 0) {
|
||||
if (!c.ro || c.func == DEFRAG) {
|
||||
MSG(0, "\tError: Not available on mounted device!\n");
|
||||
return -1;
|
||||
|
34
fsck/mount.c
34
fsck/mount.c
@ -400,7 +400,7 @@ int sanity_check_raw_super(struct f2fs_super_block *sb, u64 offset)
|
||||
return -1;
|
||||
|
||||
/* Check zoned block device feature */
|
||||
if (c.zoned_model == F2FS_ZONED_HM &&
|
||||
if (c.devices[0].zoned_model == F2FS_ZONED_HM &&
|
||||
!(sb->feature & cpu_to_le32(F2FS_FEATURE_BLKZONED))) {
|
||||
MSG(0, "\tMissing zoned block device feature\n");
|
||||
return -1;
|
||||
@ -470,6 +470,7 @@ int init_sb_info(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi);
|
||||
u64 total_sectors;
|
||||
int i;
|
||||
|
||||
sbi->log_sectors_per_block = get_sb(log_sectors_per_block);
|
||||
sbi->log_blocksize = get_sb(log_blocksize);
|
||||
@ -486,6 +487,37 @@ int init_sb_info(struct f2fs_sb_info *sbi)
|
||||
sbi->meta_ino_num = get_sb(meta_ino);
|
||||
sbi->cur_victim_sec = NULL_SEGNO;
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i++) {
|
||||
if (!sb->devs[i].path[0])
|
||||
break;
|
||||
|
||||
if (i) {
|
||||
c.devices[i].path = strdup((char *)sb->devs[i].path);
|
||||
if (get_device_info(i))
|
||||
ASSERT(0);
|
||||
} else {
|
||||
ASSERT(!strcmp((char *)sb->devs[i].path,
|
||||
(char *)c.devices[i].path));
|
||||
}
|
||||
|
||||
c.devices[i].total_segments =
|
||||
le32_to_cpu(sb->devs[i].total_segments);
|
||||
if (i)
|
||||
c.devices[i].start_blkaddr =
|
||||
c.devices[i - 1].end_blkaddr + 1;
|
||||
c.devices[i].end_blkaddr = c.devices[i].start_blkaddr +
|
||||
c.devices[i].total_segments *
|
||||
c.blks_per_seg - 1;
|
||||
if (i == 0)
|
||||
c.devices[i].end_blkaddr += get_sb(segment0_blkaddr);
|
||||
|
||||
c.ndevs = i + 1;
|
||||
MSG(0, "Info: Device[%d] : %s blkaddr = %"PRIx64"--%"PRIx64"\n",
|
||||
i, c.devices[i].path,
|
||||
c.devices[i].start_blkaddr,
|
||||
c.devices[i].end_blkaddr);
|
||||
}
|
||||
|
||||
total_sectors = get_sb(block_count) << sbi->log_sectors_per_block;
|
||||
MSG(0, "Info: total FS sectors = %"PRIu64" (%"PRIu64" MB)\n",
|
||||
total_sectors, total_sectors >>
|
||||
|
@ -212,6 +212,8 @@ static inline uint64_t bswap_64(uint64_t val)
|
||||
#define BITS_PER_BYTE 8
|
||||
#define F2FS_SUPER_MAGIC 0xF2F52010 /* F2FS Magic Number */
|
||||
#define CHECKSUM_OFFSET 4092
|
||||
#define MAX_PATH_LEN 64
|
||||
#define MAX_DEVICES 8
|
||||
|
||||
#define F2FS_BYTES_TO_BLK(bytes) ((bytes) >> F2FS_BLKSIZE_BITS)
|
||||
#define F2FS_BLKSIZE_BITS 12
|
||||
@ -233,10 +235,28 @@ enum f2fs_config_func {
|
||||
SLOAD,
|
||||
};
|
||||
|
||||
struct f2fs_configuration {
|
||||
struct device_info {
|
||||
char *path;
|
||||
int32_t fd;
|
||||
u_int32_t sector_size;
|
||||
u_int64_t total_sectors; /* got by get_device_info */
|
||||
u_int64_t start_blkaddr;
|
||||
u_int64_t end_blkaddr;
|
||||
u_int32_t total_segments;
|
||||
|
||||
/* to handle zone block devices */
|
||||
int zoned_model;
|
||||
u_int32_t nr_zones;
|
||||
u_int32_t nr_rnd_zones;
|
||||
size_t zone_blocks;
|
||||
};
|
||||
|
||||
struct f2fs_configuration {
|
||||
u_int32_t reserved_segments;
|
||||
u_int32_t new_reserved_segments;
|
||||
int zoned_mode;
|
||||
int zoned_model;
|
||||
size_t zone_blocks;
|
||||
double overprovision;
|
||||
double new_overprovision;
|
||||
u_int32_t cur_seg[6];
|
||||
@ -244,7 +264,10 @@ struct f2fs_configuration {
|
||||
u_int32_t secs_per_zone;
|
||||
u_int32_t segs_per_zone;
|
||||
u_int32_t start_sector;
|
||||
u_int32_t total_segments;
|
||||
u_int32_t sector_size;
|
||||
u_int64_t total_sectors;
|
||||
u_int64_t wanted_total_sectors;
|
||||
u_int64_t target_sectors;
|
||||
u_int32_t sectors_per_blk;
|
||||
u_int32_t blks_per_seg;
|
||||
@ -253,9 +276,10 @@ struct f2fs_configuration {
|
||||
__u8 version[VERSION_LEN + 1];
|
||||
char *vol_label;
|
||||
int heap;
|
||||
int32_t fd, kd;
|
||||
int32_t kd;
|
||||
int32_t dump_fd;
|
||||
char *device_name;
|
||||
struct device_info devices[MAX_DEVICES];
|
||||
int ndevs;
|
||||
char *extension_list;
|
||||
const char *rootdev_name;
|
||||
int dbg_lv;
|
||||
@ -278,13 +302,6 @@ struct f2fs_configuration {
|
||||
/* sload parameters */
|
||||
char *from_dir;
|
||||
char *mount_point;
|
||||
|
||||
/* to handle zone block devices */
|
||||
int zoned_mode;
|
||||
int zoned_model;
|
||||
u_int32_t nr_zones;
|
||||
u_int32_t nr_rnd_zones;
|
||||
size_t zone_blocks;
|
||||
} __attribute__((packed));
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
@ -443,6 +460,11 @@ enum {
|
||||
/*
|
||||
* For superblock
|
||||
*/
|
||||
struct f2fs_device {
|
||||
__u8 path[MAX_PATH_LEN];
|
||||
__le32 total_segments;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct f2fs_super_block {
|
||||
__le32 magic; /* Magic Number */
|
||||
__le16 major_ver; /* Major Version */
|
||||
@ -481,7 +503,8 @@ struct f2fs_super_block {
|
||||
__le32 feature; /* defined features */
|
||||
__u8 encryption_level; /* versioning level for encryption */
|
||||
__u8 encrypt_pw_salt[16]; /* Salt used for string2key algorithm */
|
||||
__u8 reserved[871]; /* valid reserved region */
|
||||
struct f2fs_device devs[MAX_DEVICES]; /* device list */
|
||||
__u8 reserved[327]; /* valid reserved region */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
@ -933,8 +956,10 @@ extern u_int32_t f2fs_cal_crc32(u_int32_t, void *, int);
|
||||
extern int f2fs_crc_valid(u_int32_t blk_crc, void *buf, int len);
|
||||
|
||||
extern void f2fs_init_configuration(void);
|
||||
extern int f2fs_dev_is_umounted(void);
|
||||
extern int f2fs_devs_are_umounted(void);
|
||||
extern int f2fs_dev_is_umounted(char *);
|
||||
extern int f2fs_get_device_info(void);
|
||||
extern int get_device_info(int);
|
||||
extern void f2fs_finalize_device(void);
|
||||
|
||||
extern int dev_read(void *, __u64, size_t);
|
||||
@ -1014,10 +1039,10 @@ blk_zone_cond_str(struct blk_zone *blkz)
|
||||
|
||||
#endif
|
||||
|
||||
extern void f2fs_get_zoned_model();
|
||||
extern int f2fs_get_zone_blocks();
|
||||
extern int f2fs_check_zones();
|
||||
extern int f2fs_reset_zones();
|
||||
extern void f2fs_get_zoned_model(int);
|
||||
extern int f2fs_get_zone_blocks(int);
|
||||
extern int f2fs_check_zones(int);
|
||||
extern int f2fs_reset_zones(int);
|
||||
|
||||
extern struct f2fs_configuration c;
|
||||
|
||||
|
182
lib/libf2fs.c
182
lib/libf2fs.c
@ -541,13 +541,25 @@ const char *get_rootdev()
|
||||
*/
|
||||
void f2fs_init_configuration(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
c.ndevs = 1;
|
||||
c.total_sectors = 0;
|
||||
c.sector_size = DEFAULT_SECTOR_SIZE;
|
||||
c.sector_size = 0;
|
||||
c.sectors_per_blk = DEFAULT_SECTORS_PER_BLOCK;
|
||||
c.blks_per_seg = DEFAULT_BLOCKS_PER_SEGMENT;
|
||||
c.rootdev_name = get_rootdev();
|
||||
c.wanted_total_sectors = -1;
|
||||
c.zoned_mode = 0;
|
||||
c.zoned_model = F2FS_ZONED_NONE;
|
||||
c.zoned_model = 0;
|
||||
c.zone_blocks = 0;
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i++) {
|
||||
memset(&c.devices[i], 0, sizeof(struct device_info));
|
||||
c.devices[i].sector_size = DEFAULT_SECTOR_SIZE;
|
||||
c.devices[i].end_blkaddr = -1;
|
||||
c.devices[i].zoned_model = F2FS_ZONED_NONE;
|
||||
}
|
||||
|
||||
/* calculated by overprovision ratio */
|
||||
c.reserved_segments = 0;
|
||||
@ -557,9 +569,9 @@ void f2fs_init_configuration(void)
|
||||
c.segs_per_zone = 1;
|
||||
c.heap = 1;
|
||||
c.vol_label = "";
|
||||
c.device_name = NULL;
|
||||
c.trim = 1;
|
||||
c.ro = 0;
|
||||
c.kd = -1;
|
||||
}
|
||||
|
||||
static int is_mounted(const char *mpt, const char *device)
|
||||
@ -584,26 +596,26 @@ static int is_mounted(const char *mpt, const char *device)
|
||||
return mnt ? 1 : 0;
|
||||
}
|
||||
|
||||
int f2fs_dev_is_umounted(void)
|
||||
int f2fs_dev_is_umounted(char *path)
|
||||
{
|
||||
struct stat st_buf;
|
||||
int is_rootdev = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (c.rootdev_name && !strcmp(c.device_name, c.rootdev_name))
|
||||
if (c.rootdev_name && !strcmp(path, c.rootdev_name))
|
||||
is_rootdev = 1;
|
||||
|
||||
/*
|
||||
* try with /proc/mounts fist to detect RDONLY.
|
||||
* f2fs_stop_checkpoint makes RO in /proc/mounts while RW in /etc/mtab.
|
||||
*/
|
||||
ret = is_mounted("/proc/mounts", c.device_name);
|
||||
ret = is_mounted("/proc/mounts", path);
|
||||
if (ret) {
|
||||
MSG(0, "Info: Mounted device!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = is_mounted(MOUNTED, c.device_name);
|
||||
ret = is_mounted(MOUNTED, path);
|
||||
if (ret) {
|
||||
MSG(0, "Info: Mounted device!\n");
|
||||
return -1;
|
||||
@ -626,8 +638,8 @@ int f2fs_dev_is_umounted(void)
|
||||
* If f2fs is umounted with -l, the process can still use
|
||||
* the file system. In this case, we should not format.
|
||||
*/
|
||||
if (stat(c.device_name, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
|
||||
int fd = open(c.device_name, O_RDONLY | O_EXCL);
|
||||
if (stat(path, &st_buf) == 0 && S_ISBLK(st_buf.st_mode)) {
|
||||
int fd = open(path, O_RDONLY | O_EXCL);
|
||||
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
@ -639,6 +651,16 @@ int f2fs_dev_is_umounted(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f2fs_devs_are_umounted(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c.ndevs; i++)
|
||||
if (f2fs_dev_is_umounted((char *)c.devices[i].path))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_kernel_version(__u8 *version)
|
||||
{
|
||||
int i;
|
||||
@ -649,7 +671,7 @@ void get_kernel_version(__u8 *version)
|
||||
memset(version + i, 0, VERSION_LEN + 1 - i);
|
||||
}
|
||||
|
||||
int f2fs_get_device_info(void)
|
||||
int get_device_info(int i)
|
||||
{
|
||||
int32_t fd = 0;
|
||||
uint32_t sector_size;
|
||||
@ -663,18 +685,23 @@ int f2fs_get_device_info(void)
|
||||
unsigned char reply_buffer[96] = {0};
|
||||
unsigned char model_inq[6] = {MODELINQUIRY};
|
||||
#endif
|
||||
u_int64_t wanted_total_sectors = c.total_sectors;
|
||||
struct device_info *dev = c.devices + i;
|
||||
|
||||
fd = open(c.device_name, O_RDWR);
|
||||
fd = open((char *)dev->path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
MSG(0, "\tError: Failed to open the device!\n");
|
||||
return -1;
|
||||
}
|
||||
c.fd = fd;
|
||||
|
||||
c.kd = open("/proc/version", O_RDONLY);
|
||||
if (c.kd < 0)
|
||||
MSG(0, "\tInfo: No support kernel version!\n");
|
||||
dev->fd = fd;
|
||||
|
||||
if (c.kd == -1) {
|
||||
c.kd = open("/proc/version", O_RDONLY);
|
||||
if (c.kd < 0) {
|
||||
MSG(0, "\tInfo: No support kernel version!\n");
|
||||
c.kd = -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstat(fd, &stat_buf) < 0 ) {
|
||||
MSG(0, "\tError: Failed to get the device stat!\n");
|
||||
@ -682,31 +709,26 @@ int f2fs_get_device_info(void)
|
||||
}
|
||||
|
||||
if (S_ISREG(stat_buf.st_mode)) {
|
||||
c.total_sectors = stat_buf.st_size / c.sector_size;
|
||||
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) {
|
||||
if (ioctl(fd, BLKSSZGET, §or_size) < 0)
|
||||
MSG(0, "\tError: Using the default sector size\n");
|
||||
} else {
|
||||
if (c.sector_size < sector_size) {
|
||||
c.sector_size = sector_size;
|
||||
c.sectors_per_blk = PAGE_SIZE / sector_size;
|
||||
}
|
||||
}
|
||||
|
||||
else if (dev->sector_size < sector_size)
|
||||
dev->sector_size = sector_size;
|
||||
#ifdef BLKGETSIZE64
|
||||
if (ioctl(fd, BLKGETSIZE64, &c.total_sectors) < 0) {
|
||||
if (ioctl(fd, BLKGETSIZE64, &dev->total_sectors) < 0) {
|
||||
MSG(0, "\tError: Cannot get the device size\n");
|
||||
return -1;
|
||||
}
|
||||
c.total_sectors /= c.sector_size;
|
||||
#else
|
||||
if (ioctl(fd, BLKGETSIZE, &total_sectors) < 0) {
|
||||
MSG(0, "\tError: Cannot get the device size\n");
|
||||
return -1;
|
||||
}
|
||||
total_sectors /= c.sector_size;
|
||||
c.total_sectors = total_sectors;
|
||||
dev->total_sectors = total_sectors;
|
||||
#endif
|
||||
dev->total_sectors /= dev->sector_size;
|
||||
|
||||
if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
|
||||
c.start_sector = 0;
|
||||
else
|
||||
@ -723,10 +745,11 @@ int f2fs_get_device_info(void)
|
||||
io_hdr.cmdp = model_inq;
|
||||
io_hdr.timeout = 1000;
|
||||
|
||||
if (!ioctl(fd,SG_IO,&io_hdr)) {
|
||||
if (!ioctl(fd, SG_IO, &io_hdr)) {
|
||||
int i = 16;
|
||||
|
||||
MSG(0, "Info: Disk Model: ");
|
||||
MSG(0, "Info: [%s] Disk Model: ",
|
||||
dev->path);
|
||||
while (reply_buffer[i] != '`' && i < 80)
|
||||
printf("%c", reply_buffer[i++]);
|
||||
printf("\n");
|
||||
@ -736,10 +759,58 @@ int f2fs_get_device_info(void)
|
||||
MSG(0, "\tError: Volume type is not supported!!!\n");
|
||||
return -1;
|
||||
}
|
||||
if (wanted_total_sectors && wanted_total_sectors < c.total_sectors) {
|
||||
|
||||
if (!c.sector_size) {
|
||||
c.sector_size = dev->sector_size;
|
||||
c.sectors_per_blk = F2FS_BLKSIZE / c.sector_size;
|
||||
} else if (c.sector_size != c.devices[i].sector_size) {
|
||||
MSG(0, "\tError: Different sector sizes!!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef WITH_ANDROID
|
||||
if (S_ISBLK(stat_buf.st_mode))
|
||||
f2fs_get_zoned_model(i);
|
||||
|
||||
if (dev->zoned_model != F2FS_ZONED_NONE) {
|
||||
if (dev->zoned_model == F2FS_ZONED_HM)
|
||||
c.zoned_model = F2FS_ZONED_HM;
|
||||
|
||||
if (f2fs_get_zone_blocks(i)) {
|
||||
MSG(0, "\tError: Failed to get number of blocks per zone\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (f2fs_check_zones(i)) {
|
||||
MSG(0, "\tError: Failed to check zone configuration\n");
|
||||
return -1;
|
||||
}
|
||||
MSG(0, "Info: Host-%s zoned block device:\n",
|
||||
(dev->zoned_model == F2FS_ZONED_HA) ?
|
||||
"aware" : "managed");
|
||||
MSG(0, " %u zones, %u randomly writeable zones\n",
|
||||
dev->nr_zones, dev->nr_rnd_zones);
|
||||
MSG(0, " %lu blocks per zone\n",
|
||||
dev->zone_blocks);
|
||||
}
|
||||
#endif
|
||||
c.total_sectors += dev->total_sectors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f2fs_get_device_info(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c.ndevs; i++)
|
||||
if (get_device_info(i))
|
||||
return -1;
|
||||
|
||||
if (c.wanted_total_sectors < c.total_sectors) {
|
||||
MSG(0, "Info: total device sectors = %"PRIu64" (in %u bytes)\n",
|
||||
c.total_sectors, c.sector_size);
|
||||
c.total_sectors = wanted_total_sectors;
|
||||
c.total_sectors, c.sector_size);
|
||||
c.total_sectors = c.wanted_total_sectors;
|
||||
c.devices[0].total_sectors = c.total_sectors;
|
||||
}
|
||||
if (c.total_sectors * c.sector_size >
|
||||
(u_int64_t)F2FS_MAX_SEGMENT * 2 * 1024 * 1024) {
|
||||
@ -747,36 +818,28 @@ int f2fs_get_device_info(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef WITH_ANDROID
|
||||
if (S_ISBLK(stat_buf.st_mode))
|
||||
f2fs_get_zoned_model();
|
||||
if (c.zoned_model == F2FS_ZONED_NONE) {
|
||||
c.zoned_mode = 0;
|
||||
} else {
|
||||
if (f2fs_get_zone_blocks()) {
|
||||
MSG(0, "\tError: Failed to get number of blocks per zone\n");
|
||||
return -1;
|
||||
for (i = 0; i < c.ndevs; i++) {
|
||||
if (c.devices[i].zoned_model != F2FS_ZONED_NONE) {
|
||||
if (c.zone_blocks &&
|
||||
c.zone_blocks != c.devices[i].zone_blocks) {
|
||||
MSG(0, "\tError: not support different zone sizes!!!\n");
|
||||
return -1;
|
||||
}
|
||||
c.zone_blocks = c.devices[i].zone_blocks;
|
||||
}
|
||||
}
|
||||
|
||||
if (f2fs_check_zones()) {
|
||||
MSG(0, "\tError: Failed to check zone configuration\n");
|
||||
return -1;
|
||||
}
|
||||
MSG(0, "Info: Host-%s zoned block device:\n",
|
||||
(c.zoned_model == F2FS_ZONED_HA) ?
|
||||
"aware" : "managed");
|
||||
MSG(0, " %u zones, %u randomly writeable zones\n",
|
||||
c.nr_zones, c.nr_rnd_zones);
|
||||
MSG(0, " %lu blocks per zone\n",
|
||||
c.zone_blocks);
|
||||
/*
|
||||
* Align sections to the device zone size
|
||||
* and align F2FS zones to the device zones.
|
||||
*/
|
||||
/*
|
||||
* Align sections to the device zone size
|
||||
* and align F2FS zones to the device zones.
|
||||
*/
|
||||
if (c.zone_blocks) {
|
||||
c.segs_per_sec = c.zone_blocks / DEFAULT_BLOCKS_PER_SEGMENT;
|
||||
c.secs_per_zone = 1;
|
||||
} else {
|
||||
c.zoned_mode = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
c.segs_per_zone = c.segs_per_sec * c.secs_per_zone;
|
||||
|
||||
MSG(0, "Info: Segments per section = %d\n", c.segs_per_sec);
|
||||
@ -787,4 +850,3 @@ int f2fs_get_device_info(void)
|
||||
(c.sector_size >> 9)) >> 11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,22 @@
|
||||
|
||||
struct f2fs_configuration c;
|
||||
|
||||
static int __get_device_fd(__u64 *offset)
|
||||
{
|
||||
__u64 blk_addr = *offset >> F2FS_BLKSIZE_BITS;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c.ndevs; i++) {
|
||||
if (c.devices[i].start_blkaddr <= blk_addr &&
|
||||
c.devices[i].end_blkaddr >= blk_addr) {
|
||||
*offset -=
|
||||
c.devices[i].start_blkaddr << F2FS_BLKSIZE_BITS;
|
||||
return c.devices[i].fd;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* IO interfaces
|
||||
*/
|
||||
@ -39,17 +55,26 @@ int dev_read_version(void *buf, __u64 offset, size_t len)
|
||||
|
||||
int dev_read(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
if (lseek64(c.fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
int fd = __get_device_fd(&offset);
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
if (read(c.fd, buf, len) < 0)
|
||||
if (read(fd, buf, len) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_readahead(__u64 offset, size_t len)
|
||||
{
|
||||
int fd = __get_device_fd(&offset);
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
#ifdef POSIX_FADV_WILLNEED
|
||||
return posix_fadvise(c.fd, offset, len, POSIX_FADV_WILLNEED);
|
||||
return posix_fadvise(fd, offset, len, POSIX_FADV_WILLNEED);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
@ -57,9 +82,14 @@ int dev_readahead(__u64 offset, size_t len)
|
||||
|
||||
int dev_write(void *buf, __u64 offset, size_t len)
|
||||
{
|
||||
if (lseek64(c.fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
int fd = __get_device_fd(&offset);
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
if (write(c.fd, buf, len) < 0)
|
||||
if (write(fd, buf, len) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@ -80,12 +110,17 @@ 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);
|
||||
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
/* Only allow fill to zero */
|
||||
if (*((__u8*)buf))
|
||||
return -1;
|
||||
if (lseek64(c.fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
if (lseek64(fd, (off64_t)offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
if (write(c.fd, buf, len) < 0)
|
||||
if (write(fd, buf, len) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@ -107,15 +142,18 @@ int dev_reada_block(__u64 blk_addr)
|
||||
|
||||
void f2fs_finalize_device(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We should call fsync() to flush out all the dirty pages
|
||||
* in the block device page cache.
|
||||
*/
|
||||
if (fsync(c.fd) < 0)
|
||||
MSG(0, "\tError: Could not conduct fsync!!!\n");
|
||||
|
||||
if (close(c.fd) < 0)
|
||||
MSG(0, "\tError: Failed to close device file!!!\n");
|
||||
for (i = 0; i < c.ndevs; i++) {
|
||||
if (fsync(c.devices[i].fd) < 0)
|
||||
MSG(0, "\tError: Could not conduct fsync!!!\n");
|
||||
|
||||
if (close(c.devices[i].fd) < 0)
|
||||
MSG(0, "\tError: Failed to close device file!!!\n");
|
||||
}
|
||||
close(c.kd);
|
||||
}
|
||||
|
@ -22,8 +22,9 @@
|
||||
|
||||
#ifdef HAVE_LINUX_BLKZONED_H
|
||||
|
||||
void f2fs_get_zoned_model()
|
||||
void f2fs_get_zoned_model(int i)
|
||||
{
|
||||
struct device_info *dev = c.devices + i;
|
||||
char str[128];
|
||||
FILE *file;
|
||||
int res;
|
||||
@ -31,7 +32,7 @@ void f2fs_get_zoned_model()
|
||||
/* Check that this is a zoned block device */
|
||||
snprintf(str, sizeof(str),
|
||||
"/sys/block/%s/queue/zoned",
|
||||
basename(c.device_name));
|
||||
basename(dev->path));
|
||||
file = fopen(str, "r");
|
||||
if (!file)
|
||||
goto not_zoned;
|
||||
@ -44,31 +45,32 @@ void f2fs_get_zoned_model()
|
||||
goto not_zoned;
|
||||
|
||||
if (strcmp(str, "host-aware") == 0) {
|
||||
c.zoned_model = F2FS_ZONED_HA;
|
||||
dev->zoned_model = F2FS_ZONED_HA;
|
||||
return;
|
||||
}
|
||||
if (strcmp(str, "host-managed") == 0) {
|
||||
c.zoned_model = F2FS_ZONED_HM;
|
||||
dev->zoned_model = F2FS_ZONED_HM;
|
||||
return;
|
||||
}
|
||||
|
||||
not_zoned:
|
||||
c.zoned_model = F2FS_ZONED_NONE;
|
||||
dev->zoned_model = F2FS_ZONED_NONE;
|
||||
}
|
||||
|
||||
int f2fs_get_zone_blocks()
|
||||
int f2fs_get_zone_blocks(int i)
|
||||
{
|
||||
struct device_info *dev = c.devices + i;
|
||||
uint64_t sectors;
|
||||
char str[128];
|
||||
FILE *file;
|
||||
int res;
|
||||
|
||||
/* Get zone size */
|
||||
c.zone_blocks = 0;
|
||||
dev->zone_blocks = 0;
|
||||
|
||||
snprintf(str, sizeof(str),
|
||||
"/sys/block/%s/queue/chunk_sectors",
|
||||
basename(c.device_name));
|
||||
basename(dev->path));
|
||||
file = fopen(str, "r");
|
||||
if (!file)
|
||||
return -1;
|
||||
@ -84,24 +86,25 @@ int f2fs_get_zone_blocks()
|
||||
if (!sectors)
|
||||
return -1;
|
||||
|
||||
c.zone_blocks = sectors >> (F2FS_BLKSIZE_BITS - 9);
|
||||
dev->zone_blocks = sectors >> (F2FS_BLKSIZE_BITS - 9);
|
||||
sectors = (sectors << 9) / c.sector_size;
|
||||
|
||||
/*
|
||||
* Total number of zones: there may
|
||||
* be a last smaller runt zone.
|
||||
*/
|
||||
c.nr_zones = c.total_sectors / sectors;
|
||||
if (c.total_sectors % sectors)
|
||||
c.nr_zones++;
|
||||
dev->nr_zones = dev->total_sectors / sectors;
|
||||
if (dev->total_sectors % sectors)
|
||||
dev->nr_zones++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define F2FS_REPORT_ZONES_BUFSZ 524288
|
||||
|
||||
int f2fs_check_zones()
|
||||
int f2fs_check_zones(int j)
|
||||
{
|
||||
struct device_info *dev = c.devices + j;
|
||||
struct blk_zone_report *rep;
|
||||
struct blk_zone *blkz;
|
||||
unsigned int i, n = 0;
|
||||
@ -116,9 +119,9 @@ int f2fs_check_zones()
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
c.nr_rnd_zones = 0;
|
||||
dev->nr_rnd_zones = 0;
|
||||
sector = 0;
|
||||
total_sectors = (c.total_sectors * c.sector_size) >> 9;
|
||||
total_sectors = (dev->total_sectors * c.sector_size) >> 9;
|
||||
|
||||
while (sector < total_sectors) {
|
||||
|
||||
@ -128,7 +131,7 @@ int f2fs_check_zones()
|
||||
rep->nr_zones = (F2FS_REPORT_ZONES_BUFSZ - sizeof(struct blk_zone_report))
|
||||
/ sizeof(struct blk_zone);
|
||||
|
||||
ret = ioctl(c.fd, BLKREPORTZONE, rep);
|
||||
ret = ioctl(dev->fd, BLKREPORTZONE, rep);
|
||||
if (ret != 0) {
|
||||
ret = -errno;
|
||||
ERR_MSG("ioctl BLKREPORTZONE failed\n");
|
||||
@ -147,7 +150,7 @@ int f2fs_check_zones()
|
||||
if (blk_zone_conv(blkz) ||
|
||||
blk_zone_seq_pref(blkz)) {
|
||||
if (last_is_conv)
|
||||
c.nr_rnd_zones++;
|
||||
dev->nr_rnd_zones++;
|
||||
} else {
|
||||
last_is_conv = 0;
|
||||
}
|
||||
@ -180,26 +183,25 @@ int f2fs_check_zones()
|
||||
n++;
|
||||
blkz++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sector != total_sectors) {
|
||||
ERR_MSG("Invalid zones: last sector reported is %llu, expected %llu\n",
|
||||
(unsigned long long)(sector << 9) / c.sector_size,
|
||||
(unsigned long long)c.total_sectors);
|
||||
(unsigned long long)dev->total_sectors);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (n != c.nr_zones) {
|
||||
if (n != dev->nr_zones) {
|
||||
ERR_MSG("Inconsistent number of zones: expected %u zones, got %u\n",
|
||||
c.nr_zones, n);
|
||||
dev->nr_zones, n);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (c.zoned_model == F2FS_ZONED_HM &&
|
||||
!c.nr_rnd_zones) {
|
||||
if (dev->zoned_model == F2FS_ZONED_HM &&
|
||||
!dev->nr_rnd_zones) {
|
||||
ERR_MSG("No conventional zone for super block\n");
|
||||
ret = -1;
|
||||
}
|
||||
@ -208,8 +210,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int f2fs_reset_zones()
|
||||
int f2fs_reset_zones(int j)
|
||||
{
|
||||
struct device_info *dev = c.devices + j;
|
||||
struct blk_zone_report *rep;
|
||||
struct blk_zone *blkz;
|
||||
struct blk_zone_range range;
|
||||
@ -225,7 +228,7 @@ int f2fs_reset_zones()
|
||||
}
|
||||
|
||||
sector = 0;
|
||||
total_sectors = (c.total_sectors * c.sector_size) >> 9;
|
||||
total_sectors = (dev->total_sectors * c.sector_size) >> 9;
|
||||
while (sector < total_sectors) {
|
||||
|
||||
/* Get zone info */
|
||||
@ -234,7 +237,7 @@ int f2fs_reset_zones()
|
||||
rep->nr_zones = (F2FS_REPORT_ZONES_BUFSZ - sizeof(struct blk_zone_report))
|
||||
/ sizeof(struct blk_zone);
|
||||
|
||||
ret = ioctl(c.fd, BLKREPORTZONE, rep);
|
||||
ret = ioctl(dev->fd, BLKREPORTZONE, rep);
|
||||
if (ret != 0) {
|
||||
ret = -errno;
|
||||
ERR_MSG("ioctl BLKREPORTZONES failed\n");
|
||||
@ -251,8 +254,9 @@ int f2fs_reset_zones()
|
||||
/* Non empty sequential zone: reset */
|
||||
range.sector = blk_zone_sector(blkz);
|
||||
range.nr_sectors = blk_zone_length(blkz);
|
||||
ret = ioctl(c.fd, BLKRESETZONE, &range);
|
||||
ret = ioctl(dev->fd, BLKRESETZONE, &range);
|
||||
if (ret != 0) {
|
||||
ret = -errno;
|
||||
ERR_MSG("ioctl BLKRESETZONE failed\n");
|
||||
goto out;
|
||||
}
|
||||
@ -260,39 +264,43 @@ int f2fs_reset_zones()
|
||||
sector = blk_zone_sector(blkz) + blk_zone_length(blkz);
|
||||
blkz++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
free(rep);
|
||||
return 0;
|
||||
if (!ret)
|
||||
MSG(0, "Info: Discarded %"PRIu64" MB\n", (sector << 9) >> 20);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void f2fs_get_zoned_model()
|
||||
void f2fs_get_zoned_model(int i)
|
||||
{
|
||||
struct device_info *dev = c.devices + i;
|
||||
|
||||
c.zoned_mode = 0;
|
||||
c.zoned_model = F2FS_ZONED_NONE;
|
||||
dev->zoned_model = F2FS_ZONED_NONE;
|
||||
}
|
||||
|
||||
int f2fs_get_zone_blocks()
|
||||
int f2fs_get_zone_blocks(int i)
|
||||
{
|
||||
struct device_info *dev = c.devices + i;
|
||||
|
||||
c.zoned_mode = 0;
|
||||
c.nr_zones = 0;
|
||||
c.zone_blocks = 0;
|
||||
c.zoned_model = F2FS_ZONED_NONE;
|
||||
dev->nr_zones = 0;
|
||||
dev->zone_blocks = 0;
|
||||
dev->zoned_model = F2FS_ZONED_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f2fs_check_zones()
|
||||
int f2fs_check_zones(int i)
|
||||
{
|
||||
ERR_MSG("Zoned block devices are not supported\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int f2fs_reset_zones()
|
||||
int f2fs_reset_zones(int i)
|
||||
{
|
||||
ERR_MSG("Zoned block devices are not supported\n");
|
||||
return -1;
|
||||
|
@ -12,6 +12,10 @@ mkfs.f2fs \- create an F2FS file system
|
||||
.I heap-based-allocation
|
||||
]
|
||||
[
|
||||
.B \-c
|
||||
.I device
|
||||
]
|
||||
[
|
||||
.B \-l
|
||||
.I volume-label
|
||||
]
|
||||
@ -55,6 +59,10 @@ If the value is equal to 1, each of active log areas are initially
|
||||
assigned separately according to the whole volume size.
|
||||
The default value is 1.
|
||||
.TP
|
||||
.BI \-c " device"
|
||||
Build f2fs with this device additionally, so that user can see all
|
||||
the devices as one big volume.
|
||||
.TP
|
||||
.BI \-l " volume-label"
|
||||
Specify the volume label to the partition mounted as F2FS.
|
||||
.TP
|
||||
|
@ -131,6 +131,7 @@ static int f2fs_prepare_super_block(void)
|
||||
u_int32_t sit_bitmap_size, max_sit_bitmap_size;
|
||||
u_int32_t max_nat_bitmap_size, max_nat_segments;
|
||||
u_int32_t total_zones;
|
||||
int i;
|
||||
|
||||
set_sb(magic, F2FS_SUPER_MAGIC);
|
||||
set_sb(major_ver, F2FS_MAJOR_VERSION);
|
||||
@ -167,29 +168,59 @@ static int f2fs_prepare_super_block(void)
|
||||
c.start_sector * c.sector_size;
|
||||
|
||||
if (c.start_sector % c.sectors_per_blk) {
|
||||
MSG(1, "\tWARN: Align start sector number to the page unit\n");
|
||||
MSG(1, "\t%s: Align start sector number to the page unit\n",
|
||||
c.zoned_mode ? "FAIL" : "WARN");
|
||||
MSG(1, "\ti.e., start sector: %d, ofs:%d (sects/page: %d)\n",
|
||||
c.start_sector,
|
||||
c.start_sector % c.sectors_per_blk,
|
||||
c.sectors_per_blk);
|
||||
if (c.zoned_mode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_sb(segment_count, (c.total_sectors * c.sector_size -
|
||||
zone_align_start_offset) / segment_size_bytes /
|
||||
c.segs_per_zone * c.segs_per_zone);
|
||||
|
||||
set_sb(segment0_blkaddr, zone_align_start_offset / blk_size_bytes);
|
||||
sb->cp_blkaddr = sb->segment0_blkaddr;
|
||||
|
||||
MSG(0, "Info: zone aligned segment0 blkaddr: %u\n",
|
||||
get_sb(segment0_blkaddr));
|
||||
|
||||
if (c.zoned_mode && get_sb(segment0_blkaddr) % c.zone_blocks) {
|
||||
if (c.zoned_mode && (get_sb(segment0_blkaddr) + c.start_sector /
|
||||
c.sectors_per_blk) % c.zone_blocks) {
|
||||
MSG(1, "\tError: Unaligned segment0 block address %u\n",
|
||||
get_sb(segment0_blkaddr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < c.ndevs; i++) {
|
||||
if (i == 0) {
|
||||
c.devices[i].total_segments =
|
||||
(c.devices[i].total_sectors *
|
||||
c.sector_size - zone_align_start_offset) /
|
||||
segment_size_bytes;
|
||||
c.devices[i].start_blkaddr = 0;
|
||||
c.devices[i].end_blkaddr = c.devices[i].total_segments *
|
||||
c.blks_per_seg - 1 +
|
||||
sb->segment0_blkaddr;
|
||||
} else {
|
||||
c.devices[i].total_segments =
|
||||
c.devices[i].total_sectors /
|
||||
(c.sectors_per_blk * c.blks_per_seg);
|
||||
c.devices[i].start_blkaddr =
|
||||
c.devices[i - 1].end_blkaddr + 1;
|
||||
c.devices[i].end_blkaddr = c.devices[i].start_blkaddr +
|
||||
c.devices[i].total_segments *
|
||||
c.blks_per_seg - 1;
|
||||
}
|
||||
if (c.ndevs > 1) {
|
||||
memcpy(sb->devs[i].path, c.devices[i].path, MAX_PATH_LEN);
|
||||
sb->devs[i].total_segments =
|
||||
cpu_to_le32(c.devices[i].total_segments);
|
||||
}
|
||||
|
||||
c.total_segments += c.devices[i].total_segments;
|
||||
}
|
||||
set_sb(segment_count, (c.total_segments / c.segs_per_zone *
|
||||
c.segs_per_zone));
|
||||
set_sb(segment_count_ckpt, F2FS_NUMBER_OF_CHECKPOINT_PACK);
|
||||
|
||||
set_sb(sit_blkaddr, get_sb(segment0_blkaddr) +
|
||||
@ -286,9 +317,10 @@ static int f2fs_prepare_super_block(void)
|
||||
*/
|
||||
unsigned long main_blkzone = get_sb(main_blkaddr) / c.zone_blocks;
|
||||
|
||||
if (c.nr_rnd_zones < main_blkzone) {
|
||||
MSG(1, "\tError: Device does not have enough random "
|
||||
"write zones for F2FS volume (%lu needed)",
|
||||
if (c.devices[0].zoned_model == F2FS_ZONED_HM &&
|
||||
c.devices[0].nr_rnd_zones < main_blkzone) {
|
||||
MSG(0, "\tError: Device does not have enough random "
|
||||
"write zones for F2FS volume (%lu needed)\n",
|
||||
main_blkzone);
|
||||
return -1;
|
||||
}
|
||||
@ -969,7 +1001,7 @@ int f2fs_format_device(void)
|
||||
}
|
||||
|
||||
if (c.trim) {
|
||||
err = f2fs_trim_device(c.fd, c.total_sectors * c.sector_size);
|
||||
err = f2fs_trim_devices();
|
||||
if (err < 0) {
|
||||
MSG(0, "\tError: Failed to trim whole device!!!\n");
|
||||
goto exit;
|
||||
|
@ -28,6 +28,7 @@ static void mkfs_usage()
|
||||
MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
|
||||
MSG(0, "[options]:\n");
|
||||
MSG(0, " -a heap-based allocation [default:1]\n");
|
||||
MSG(0, " -c [device path]\n");
|
||||
MSG(0, " -d debug level [default:0]\n");
|
||||
MSG(0, " -e [extension list] e.g. \"mp3,gif,mov\"\n");
|
||||
MSG(0, " -l label\n");
|
||||
@ -71,7 +72,7 @@ static void parse_feature(const char *features)
|
||||
|
||||
static void f2fs_parse_options(int argc, char *argv[])
|
||||
{
|
||||
static const char *option_string = "qa:d:e:l:mo:O:s:z:t:";
|
||||
static const char *option_string = "qa:c:d:e:l:mo:O:s:z:t:";
|
||||
int32_t option=0;
|
||||
|
||||
while ((option = getopt(argc,argv,option_string)) != EOF) {
|
||||
@ -82,6 +83,14 @@ static void f2fs_parse_options(int argc, char *argv[])
|
||||
case 'a':
|
||||
c.heap = atoi(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
if (strlen(optarg) > MAX_PATH_LEN) {
|
||||
MSG(0, "Error: device path should be less than "
|
||||
"%d characters\n", MAX_PATH_LEN);
|
||||
mkfs_usage();
|
||||
}
|
||||
c.devices[c.ndevs++].path = strdup(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
c.dbg_lv = atoi(optarg);
|
||||
break;
|
||||
@ -125,7 +134,21 @@ static void f2fs_parse_options(int argc, char *argv[])
|
||||
MSG(0, "\tError: Device not specified\n");
|
||||
mkfs_usage();
|
||||
}
|
||||
c.device_name = argv[optind];
|
||||
|
||||
/* [0] : META, [1 to MAX_DEVICES + 1] : NODE/DATA */
|
||||
c.devices[0].path = strdup(argv[optind]);
|
||||
if (c.ndevs > MAX_DEVICES) {
|
||||
MSG(0, "\tError: Too many devices\n");
|
||||
mkfs_usage();
|
||||
}
|
||||
|
||||
if ((optind + 1) < argc) {
|
||||
if (c.ndevs > 1) {
|
||||
MSG(0, "\tError: Not support custom size on multi-devs.\n");
|
||||
mkfs_usage();
|
||||
}
|
||||
c.wanted_total_sectors = atoll(argv[optind+1]);
|
||||
}
|
||||
|
||||
if ((optind + 1) < argc)
|
||||
c.total_sectors = atoll(argv[optind+1]);
|
||||
@ -142,7 +165,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
f2fs_show_info();
|
||||
|
||||
if (f2fs_dev_is_umounted() < 0) {
|
||||
if (f2fs_devs_are_umounted() < 0) {
|
||||
MSG(0, "\tError: Not available on mounted device!\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -34,10 +34,13 @@
|
||||
#define BLKSECDISCARD _IO(0x12,125)
|
||||
#endif
|
||||
|
||||
int f2fs_trim_device(int fd, u_int64_t bytes)
|
||||
static int trim_device(int i)
|
||||
{
|
||||
unsigned long long range[2];
|
||||
struct stat stat_buf;
|
||||
struct device_info *dev = c.devices + i;
|
||||
u_int64_t bytes = dev->total_sectors * dev->sector_size;
|
||||
int fd = dev->fd;
|
||||
|
||||
if (fstat(fd, &stat_buf) < 0 ) {
|
||||
MSG(1, "\tError: Failed to get the device stat!!!\n");
|
||||
@ -48,7 +51,7 @@ int f2fs_trim_device(int fd, u_int64_t bytes)
|
||||
range[1] = bytes;
|
||||
|
||||
#if defined(WITH_BLKDISCARD) && defined(BLKDISCARD)
|
||||
MSG(0, "Info: Discarding device\n");
|
||||
MSG(0, "Info: [%s] Discarding device\n", dev->path);
|
||||
if (S_ISREG(stat_buf.st_mode)) {
|
||||
#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE)
|
||||
if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
@ -58,8 +61,8 @@ int f2fs_trim_device(int fd, u_int64_t bytes)
|
||||
#endif
|
||||
return 0;
|
||||
} else if (S_ISBLK(stat_buf.st_mode)) {
|
||||
if (c.zoned_mode)
|
||||
return f2fs_reset_zones();
|
||||
if (dev->zoned_model != F2FS_ZONED_NONE)
|
||||
return f2fs_reset_zones(i);
|
||||
#ifdef BLKSECDISCARD
|
||||
if (ioctl(fd, BLKSECDISCARD, &range) < 0) {
|
||||
MSG(0, "Info: This device doesn't support BLKSECDISCARD\n");
|
||||
@ -79,3 +82,13 @@ int f2fs_trim_device(int fd, u_int64_t bytes)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int f2fs_trim_devices(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < c.ndevs; i++)
|
||||
if (trim_device(i))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,4 +13,5 @@
|
||||
extern struct f2fs_configuration c;
|
||||
|
||||
int f2fs_trim_device(int, u_int64_t);
|
||||
int f2fs_trim_devices(void);
|
||||
int f2fs_format_device(void);
|
||||
|
Loading…
Reference in New Issue
Block a user