15e5c12b0Sopenharmony_ci/** 25e5c12b0Sopenharmony_ci * f2fs_format_utils.c 35e5c12b0Sopenharmony_ci * 45e5c12b0Sopenharmony_ci * Copyright (c) 2014 Samsung Electronics Co., Ltd. 55e5c12b0Sopenharmony_ci * http://www.samsung.com/ 65e5c12b0Sopenharmony_ci * 75e5c12b0Sopenharmony_ci * Dual licensed under the GPL or LGPL version 2 licenses. 85e5c12b0Sopenharmony_ci */ 95e5c12b0Sopenharmony_ci#ifndef _LARGEFILE_SOURCE 105e5c12b0Sopenharmony_ci#define _LARGEFILE_SOURCE 115e5c12b0Sopenharmony_ci#endif 125e5c12b0Sopenharmony_ci#ifndef _LARGEFILE64_SOURCE 135e5c12b0Sopenharmony_ci#define _LARGEFILE64_SOURCE 145e5c12b0Sopenharmony_ci#endif 155e5c12b0Sopenharmony_ci#ifndef _GNU_SOURCE 165e5c12b0Sopenharmony_ci#define _GNU_SOURCE 175e5c12b0Sopenharmony_ci#endif 185e5c12b0Sopenharmony_ci 195e5c12b0Sopenharmony_ci#ifndef _FILE_OFFSET_BITS 205e5c12b0Sopenharmony_ci#define _FILE_OFFSET_BITS 64 215e5c12b0Sopenharmony_ci#endif 225e5c12b0Sopenharmony_ci 235e5c12b0Sopenharmony_ci#include <f2fs_fs.h> 245e5c12b0Sopenharmony_ci 255e5c12b0Sopenharmony_ci#include <stdio.h> 265e5c12b0Sopenharmony_ci#include <unistd.h> 275e5c12b0Sopenharmony_ci#include <stdlib.h> 285e5c12b0Sopenharmony_ci#include <stdbool.h> 295e5c12b0Sopenharmony_ci#ifdef HAVE_SYS_IOCTL_H 305e5c12b0Sopenharmony_ci#include <sys/ioctl.h> 315e5c12b0Sopenharmony_ci#endif 325e5c12b0Sopenharmony_ci#include <sys/stat.h> 335e5c12b0Sopenharmony_ci#include <fcntl.h> 345e5c12b0Sopenharmony_ci 355e5c12b0Sopenharmony_ci#ifdef HAVE_LINUX_FS_H 365e5c12b0Sopenharmony_ci#include <linux/fs.h> 375e5c12b0Sopenharmony_ci#endif 385e5c12b0Sopenharmony_ci#ifdef HAVE_LINUX_FALLOC_H 395e5c12b0Sopenharmony_ci#include <linux/falloc.h> 405e5c12b0Sopenharmony_ci#endif 415e5c12b0Sopenharmony_ci 425e5c12b0Sopenharmony_ci#ifdef __linux__ 435e5c12b0Sopenharmony_ci#ifndef BLKDISCARD 445e5c12b0Sopenharmony_ci#define BLKDISCARD _IO(0x12,119) 455e5c12b0Sopenharmony_ci#endif 465e5c12b0Sopenharmony_ci#ifndef BLKSECDISCARD 475e5c12b0Sopenharmony_ci#define BLKSECDISCARD _IO(0x12,125) 485e5c12b0Sopenharmony_ci#endif 495e5c12b0Sopenharmony_ci#endif 505e5c12b0Sopenharmony_ci 515e5c12b0Sopenharmony_ci#if defined(FALLOC_FL_PUNCH_HOLE) || defined(BLKDISCARD) || \ 525e5c12b0Sopenharmony_ci defined(BLKSECDISCARD) 535e5c12b0Sopenharmony_cistatic int trim_device(int i) 545e5c12b0Sopenharmony_ci{ 555e5c12b0Sopenharmony_ci unsigned long long range[2]; 565e5c12b0Sopenharmony_ci struct stat *stat_buf; 575e5c12b0Sopenharmony_ci struct device_info *dev = c.devices + i; 585e5c12b0Sopenharmony_ci uint64_t bytes = dev->total_sectors * dev->sector_size; 595e5c12b0Sopenharmony_ci int fd = dev->fd; 605e5c12b0Sopenharmony_ci 615e5c12b0Sopenharmony_ci stat_buf = malloc(sizeof(struct stat)); 625e5c12b0Sopenharmony_ci if (stat_buf == NULL) { 635e5c12b0Sopenharmony_ci MSG(1, "\tError: Malloc Failed for trim_stat_buf!!!\n"); 645e5c12b0Sopenharmony_ci return -1; 655e5c12b0Sopenharmony_ci } 665e5c12b0Sopenharmony_ci 675e5c12b0Sopenharmony_ci if (fstat(fd, stat_buf) < 0 ) { 685e5c12b0Sopenharmony_ci MSG(1, "\tError: Failed to get the device stat!!!\n"); 695e5c12b0Sopenharmony_ci free(stat_buf); 705e5c12b0Sopenharmony_ci return -1; 715e5c12b0Sopenharmony_ci } 725e5c12b0Sopenharmony_ci 735e5c12b0Sopenharmony_ci range[0] = 0; 745e5c12b0Sopenharmony_ci range[1] = bytes; 755e5c12b0Sopenharmony_ci 765e5c12b0Sopenharmony_ci#if defined(WITH_BLKDISCARD) && defined(BLKDISCARD) 775e5c12b0Sopenharmony_ci MSG(0, "Info: [%s] Discarding device\n", dev->path); 785e5c12b0Sopenharmony_ci if (S_ISREG(stat_buf->st_mode)) { 795e5c12b0Sopenharmony_ci#if defined(HAVE_FALLOCATE) && defined(FALLOC_FL_PUNCH_HOLE) 805e5c12b0Sopenharmony_ci if (fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 815e5c12b0Sopenharmony_ci range[0], range[1]) < 0) { 825e5c12b0Sopenharmony_ci MSG(0, "Info: fallocate(PUNCH_HOLE|KEEP_SIZE) is failed\n"); 835e5c12b0Sopenharmony_ci } 845e5c12b0Sopenharmony_ci#endif 855e5c12b0Sopenharmony_ci free(stat_buf); 865e5c12b0Sopenharmony_ci return 0; 875e5c12b0Sopenharmony_ci } else if (S_ISBLK(stat_buf->st_mode)) { 885e5c12b0Sopenharmony_ci if (dev->zoned_model != F2FS_ZONED_NONE) { 895e5c12b0Sopenharmony_ci free(stat_buf); 905e5c12b0Sopenharmony_ci return f2fs_reset_zones(i); 915e5c12b0Sopenharmony_ci } 925e5c12b0Sopenharmony_ci#ifdef BLKSECDISCARD 935e5c12b0Sopenharmony_ci if (ioctl(fd, BLKSECDISCARD, &range) < 0) { 945e5c12b0Sopenharmony_ci MSG(0, "Info: This device doesn't support BLKSECDISCARD\n"); 955e5c12b0Sopenharmony_ci } else { 965e5c12b0Sopenharmony_ci MSG(0, "Info: Secure Discarded %lu MB\n", 975e5c12b0Sopenharmony_ci (unsigned long)stat_buf->st_size >> 20); 985e5c12b0Sopenharmony_ci free(stat_buf); 995e5c12b0Sopenharmony_ci return 0; 1005e5c12b0Sopenharmony_ci } 1015e5c12b0Sopenharmony_ci#endif 1025e5c12b0Sopenharmony_ci if (ioctl(fd, BLKDISCARD, &range) < 0) { 1035e5c12b0Sopenharmony_ci MSG(0, "Info: This device doesn't support BLKDISCARD\n"); 1045e5c12b0Sopenharmony_ci } else { 1055e5c12b0Sopenharmony_ci MSG(0, "Info: Discarded %llu MB\n", range[1] >> 20); 1065e5c12b0Sopenharmony_ci } 1075e5c12b0Sopenharmony_ci } else { 1085e5c12b0Sopenharmony_ci free(stat_buf); 1095e5c12b0Sopenharmony_ci return -1; 1105e5c12b0Sopenharmony_ci } 1115e5c12b0Sopenharmony_ci#endif 1125e5c12b0Sopenharmony_ci free(stat_buf); 1135e5c12b0Sopenharmony_ci return 0; 1145e5c12b0Sopenharmony_ci} 1155e5c12b0Sopenharmony_ci#else 1165e5c12b0Sopenharmony_cistatic int trim_device(int UNUSED(i)) 1175e5c12b0Sopenharmony_ci{ 1185e5c12b0Sopenharmony_ci return 0; 1195e5c12b0Sopenharmony_ci} 1205e5c12b0Sopenharmony_ci#endif 1215e5c12b0Sopenharmony_ci 1225e5c12b0Sopenharmony_ci#ifdef WITH_ANDROID 1235e5c12b0Sopenharmony_cistatic bool is_wiped_device(int i) 1245e5c12b0Sopenharmony_ci{ 1255e5c12b0Sopenharmony_ci struct device_info *dev = c.devices + i; 1265e5c12b0Sopenharmony_ci int fd = dev->fd; 1275e5c12b0Sopenharmony_ci char *buf, *zero_buf; 1285e5c12b0Sopenharmony_ci bool wiped = true; 1295e5c12b0Sopenharmony_ci int nblocks = 4096; /* 16MB size */ 1305e5c12b0Sopenharmony_ci int j; 1315e5c12b0Sopenharmony_ci 1325e5c12b0Sopenharmony_ci /* let's trim the other devices except the first device */ 1335e5c12b0Sopenharmony_ci if (i > 0) 1345e5c12b0Sopenharmony_ci return false; 1355e5c12b0Sopenharmony_ci 1365e5c12b0Sopenharmony_ci buf = malloc(F2FS_BLKSIZE); 1375e5c12b0Sopenharmony_ci if (buf == NULL) { 1385e5c12b0Sopenharmony_ci MSG(1, "\tError: Malloc Failed for buf!!!\n"); 1395e5c12b0Sopenharmony_ci return false; 1405e5c12b0Sopenharmony_ci } 1415e5c12b0Sopenharmony_ci zero_buf = calloc(1, F2FS_BLKSIZE); 1425e5c12b0Sopenharmony_ci if (zero_buf == NULL) { 1435e5c12b0Sopenharmony_ci MSG(1, "\tError: Calloc Failed for zero buf!!!\n"); 1445e5c12b0Sopenharmony_ci free(buf); 1455e5c12b0Sopenharmony_ci return false; 1465e5c12b0Sopenharmony_ci } 1475e5c12b0Sopenharmony_ci 1485e5c12b0Sopenharmony_ci if (lseek(fd, 0, SEEK_SET) < 0) { 1495e5c12b0Sopenharmony_ci free(zero_buf); 1505e5c12b0Sopenharmony_ci free(buf); 1515e5c12b0Sopenharmony_ci return false; 1525e5c12b0Sopenharmony_ci } 1535e5c12b0Sopenharmony_ci 1545e5c12b0Sopenharmony_ci /* check first n blocks */ 1555e5c12b0Sopenharmony_ci for (j = 0; j < nblocks; j++) { 1565e5c12b0Sopenharmony_ci if (read(fd, buf, F2FS_BLKSIZE) != F2FS_BLKSIZE || 1575e5c12b0Sopenharmony_ci memcmp(buf, zero_buf, F2FS_BLKSIZE)) { 1585e5c12b0Sopenharmony_ci wiped = false; 1595e5c12b0Sopenharmony_ci break; 1605e5c12b0Sopenharmony_ci } 1615e5c12b0Sopenharmony_ci } 1625e5c12b0Sopenharmony_ci free(zero_buf); 1635e5c12b0Sopenharmony_ci free(buf); 1645e5c12b0Sopenharmony_ci 1655e5c12b0Sopenharmony_ci if (wiped) 1665e5c12b0Sopenharmony_ci MSG(0, "Info: Found all zeros in first %d blocks\n", nblocks); 1675e5c12b0Sopenharmony_ci return wiped; 1685e5c12b0Sopenharmony_ci} 1695e5c12b0Sopenharmony_ci#else 1705e5c12b0Sopenharmony_cistatic bool is_wiped_device(int UNUSED(i)) 1715e5c12b0Sopenharmony_ci{ 1725e5c12b0Sopenharmony_ci return false; 1735e5c12b0Sopenharmony_ci} 1745e5c12b0Sopenharmony_ci#endif 1755e5c12b0Sopenharmony_ci 1765e5c12b0Sopenharmony_ciint f2fs_trim_devices(void) 1775e5c12b0Sopenharmony_ci{ 1785e5c12b0Sopenharmony_ci int i; 1795e5c12b0Sopenharmony_ci 1805e5c12b0Sopenharmony_ci for (i = 0; i < c.ndevs; i++) { 1815e5c12b0Sopenharmony_ci if (!is_wiped_device(i) && trim_device(i)) 1825e5c12b0Sopenharmony_ci return -1; 1835e5c12b0Sopenharmony_ci } 1845e5c12b0Sopenharmony_ci c.trimmed = 1; 1855e5c12b0Sopenharmony_ci return 0; 1865e5c12b0Sopenharmony_ci} 187