#clang-format-3.7 -style=file -i lwext4/*
BasedOnStyle: LLVM
-IndentWidth: 4
-UseTab: Never
+IndentWidth: 8
+UseTab: Always
BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
/**********************BLOCKDEV INTERFACE**************************************/
static int filedev_open(struct ext4_blockdev *bdev);
static int filedev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt);
+ uint32_t blk_cnt);
static int filedev_bwrite(struct ext4_blockdev *bdev, const void *buf,
- uint64_t blk_id, uint32_t blk_cnt);
+ uint64_t blk_id, uint32_t blk_cnt);
static int filedev_close(struct ext4_blockdev *bdev);
/******************************************************************************/
EXT4_BLOCKDEV_STATIC_INSTANCE(_filedev, EXT4_FILEDEV_BSIZE, 0, filedev_open,
- filedev_bread, filedev_bwrite, filedev_close);
+ filedev_bread, filedev_bwrite, filedev_close);
/******************************************************************************/
static int filedev_open(struct ext4_blockdev *bdev)
{
- dev_file = fopen(fname, "r+b");
+ dev_file = fopen(fname, "r+b");
- if (!dev_file)
- return EIO;
+ if (!dev_file)
+ return EIO;
- /*No buffering at file.*/
- setbuf(dev_file, 0);
+ /*No buffering at file.*/
+ setbuf(dev_file, 0);
- if (fseek(dev_file, 0, SEEK_END))
- return EFAULT;
+ if (fseek(dev_file, 0, SEEK_END))
+ return EFAULT;
- _filedev.ph_bcnt = ftell(dev_file) / _filedev.ph_bsize;
+ _filedev.ph_bcnt = ftell(dev_file) / _filedev.ph_bsize;
- return EOK;
+ return EOK;
}
/******************************************************************************/
static int filedev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt)
+ uint32_t blk_cnt)
{
- if (fseek(dev_file, blk_id * bdev->ph_bsize, SEEK_SET))
- return EIO;
+ if (fseek(dev_file, blk_id * bdev->ph_bsize, SEEK_SET))
+ return EIO;
- if (!fread(buf, bdev->ph_bsize * blk_cnt, 1, dev_file))
- return EIO;
+ if (!fread(buf, bdev->ph_bsize * blk_cnt, 1, dev_file))
+ return EIO;
- return EOK;
+ return EOK;
}
static void drop_cache(void)
{
#if defined(__linux__) && DROP_LINUXCACHE_BUFFERS
- int fd;
- char *data = "3";
+ int fd;
+ char *data = "3";
- sync();
- fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
- write(fd, data, sizeof(char));
- close(fd);
+ sync();
+ fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
+ write(fd, data, sizeof(char));
+ close(fd);
#endif
}
/******************************************************************************/
static int filedev_bwrite(struct ext4_blockdev *bdev, const void *buf,
- uint64_t blk_id, uint32_t blk_cnt)
+ uint64_t blk_id, uint32_t blk_cnt)
{
- if (fseek(dev_file, blk_id * bdev->ph_bsize, SEEK_SET))
- return EIO;
+ if (fseek(dev_file, blk_id * bdev->ph_bsize, SEEK_SET))
+ return EIO;
- if (!fwrite(buf, bdev->ph_bsize * blk_cnt, 1, dev_file))
- return EIO;
+ if (!fwrite(buf, bdev->ph_bsize * blk_cnt, 1, dev_file))
+ return EIO;
- drop_cache();
- return EOK;
+ drop_cache();
+ return EOK;
}
/******************************************************************************/
static int filedev_close(struct ext4_blockdev *bdev)
{
- fclose(dev_file);
- return EOK;
+ fclose(dev_file);
+ return EOK;
}
/******************************************************************************/
/**********************BLOCKDEV INTERFACE**************************************/\r
static int io_raw_open(struct ext4_blockdev *bdev);\r
static int io_raw_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
- uint32_t blk_cnt);\r
+ uint32_t blk_cnt);\r
static int io_raw_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
- uint64_t blk_id, uint32_t blk_cnt);\r
+ uint64_t blk_id, uint32_t blk_cnt);\r
static int io_raw_close(struct ext4_blockdev *bdev);\r
\r
/******************************************************************************/\r
EXT4_BLOCKDEV_STATIC_INSTANCE(_filedev, EXT4_IORAW_BSIZE, 0, io_raw_open,\r
- io_raw_bread, io_raw_bwrite, io_raw_close);\r
+ io_raw_bread, io_raw_bwrite, io_raw_close);\r
\r
/******************************************************************************/\r
static int io_raw_open(struct ext4_blockdev *bdev)\r
{\r
- char path[64];\r
- DISK_GEOMETRY pdg;\r
- uint64_t disk_size;\r
- BOOL bResult = FALSE;\r
- DWORD junk;\r
+ char path[64];\r
+ DISK_GEOMETRY pdg;\r
+ uint64_t disk_size;\r
+ BOOL bResult = FALSE;\r
+ DWORD junk;\r
\r
- sprintf(path, "\\\\.\\%s", fname);\r
+ sprintf(path, "\\\\.\\%s", fname);\r
\r
- dev_file =\r
- CreateFile(path, GENERIC_READ | GENERIC_WRITE,\r
- FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,\r
- FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL);\r
+ dev_file =\r
+ CreateFile(path, GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,\r
+ FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, NULL);\r
\r
- if (dev_file == INVALID_HANDLE_VALUE) {\r
- return EIO;\r
- }\r
+ if (dev_file == INVALID_HANDLE_VALUE) {\r
+ return EIO;\r
+ }\r
\r
- bResult = DeviceIoControl(dev_file, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,\r
- &pdg, sizeof(pdg), &junk, (LPOVERLAPPED)NULL);\r
+ bResult =\r
+ DeviceIoControl(dev_file, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,\r
+ &pdg, sizeof(pdg), &junk, (LPOVERLAPPED)NULL);\r
\r
- if (bResult == FALSE) {\r
- CloseHandle(dev_file);\r
- return EIO;\r
- }\r
+ if (bResult == FALSE) {\r
+ CloseHandle(dev_file);\r
+ return EIO;\r
+ }\r
\r
- disk_size = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *\r
- (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;\r
+ disk_size = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *\r
+ (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;\r
\r
- _filedev.ph_bsize = pdg.BytesPerSector;\r
- _filedev.ph_bcnt = disk_size / pdg.BytesPerSector;\r
+ _filedev.ph_bsize = pdg.BytesPerSector;\r
+ _filedev.ph_bcnt = disk_size / pdg.BytesPerSector;\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
/******************************************************************************/\r
\r
static int io_raw_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
- uint32_t blk_cnt)\r
+ uint32_t blk_cnt)\r
{\r
- long hipart = blk_id >> (32 - 9);\r
- long lopart = blk_id << 9;\r
- long err;\r
+ long hipart = blk_id >> (32 - 9);\r
+ long lopart = blk_id << 9;\r
+ long err;\r
\r
- SetLastError(0);\r
- lopart = SetFilePointer(dev_file, lopart, &hipart, FILE_BEGIN);\r
+ SetLastError(0);\r
+ lopart = SetFilePointer(dev_file, lopart, &hipart, FILE_BEGIN);\r
\r
- if (lopart == -1 && NO_ERROR != (err = GetLastError())) {\r
- return EIO;\r
- }\r
+ if (lopart == -1 && NO_ERROR != (err = GetLastError())) {\r
+ return EIO;\r
+ }\r
\r
- DWORD n;\r
+ DWORD n;\r
\r
- if (!ReadFile(dev_file, buf, blk_cnt * 512, &n, NULL)) {\r
- err = GetLastError();\r
- return EIO;\r
- }\r
- return EOK;\r
+ if (!ReadFile(dev_file, buf, blk_cnt * 512, &n, NULL)) {\r
+ err = GetLastError();\r
+ return EIO;\r
+ }\r
+ return EOK;\r
}\r
\r
/******************************************************************************/\r
static int io_raw_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
- uint64_t blk_id, uint32_t blk_cnt)\r
+ uint64_t blk_id, uint32_t blk_cnt)\r
{\r
- long hipart = blk_id >> (32 - 9);\r
- long lopart = blk_id << 9;\r
- long err;\r
+ long hipart = blk_id >> (32 - 9);\r
+ long lopart = blk_id << 9;\r
+ long err;\r
\r
- SetLastError(0);\r
- lopart = SetFilePointer(dev_file, lopart, &hipart, FILE_BEGIN);\r
+ SetLastError(0);\r
+ lopart = SetFilePointer(dev_file, lopart, &hipart, FILE_BEGIN);\r
\r
- if (lopart == -1 && NO_ERROR != (err = GetLastError())) {\r
- return EIO;\r
- }\r
+ if (lopart == -1 && NO_ERROR != (err = GetLastError())) {\r
+ return EIO;\r
+ }\r
\r
- DWORD n;\r
+ DWORD n;\r
\r
- if (!WriteFile(dev_file, buf, blk_cnt * 512, &n, NULL)) {\r
- err = GetLastError();\r
- return EIO;\r
- }\r
- return EOK;\r
+ if (!WriteFile(dev_file, buf, blk_cnt * 512, &n, NULL)) {\r
+ err = GetLastError();\r
+ return EIO;\r
+ }\r
+ return EOK;\r
}\r
\r
/******************************************************************************/\r
static int io_raw_close(struct ext4_blockdev *bdev)\r
{\r
- CloseHandle(dev_file);\r
- return EOK;\r
+ CloseHandle(dev_file);\r
+ return EOK;\r
}\r
\r
/******************************************************************************/\r
#define MBR_BLOCK_ID 0\r
#define MBR_PART_TABLE_OFF 446\r
\r
-struct part_tab_entry\r
-{\r
- uint8_t status;\r
- uint8_t chs1[3];\r
- uint8_t type;\r
- uint8_t chs2[3];\r
- uint32_t first_lba;\r
- uint32_t sectors;\r
+struct part_tab_entry {\r
+ uint8_t status;\r
+ uint8_t chs1[3];\r
+ uint8_t type;\r
+ uint8_t chs2[3];\r
+ uint32_t first_lba;\r
+ uint32_t sectors;\r
} __attribute__((packed));\r
\r
/**@brief Partition block offset*/\r
static uint32_t part_offset;\r
\r
/**@brief IO timings*/\r
-struct sdc_io_timings\r
-{\r
- uint64_t acc_bread;\r
- uint64_t acc_bwrite;\r
+struct sdc_io_timings {\r
+ uint64_t acc_bread;\r
+ uint64_t acc_bwrite;\r
\r
- uint32_t cnt_bread;\r
- uint32_t cnt_bwrite;\r
+ uint32_t cnt_bread;\r
+ uint32_t cnt_bwrite;\r
\r
- uint32_t av_bread;\r
- uint32_t av_bwrite;\r
+ uint32_t av_bread;\r
+ uint32_t av_bwrite;\r
};\r
\r
static struct sdc_io_timings io_timings;\r
\r
void io_timings_clear(void)\r
{\r
- memset(&io_timings, 0, sizeof(struct sdc_io_timings));\r
+ memset(&io_timings, 0, sizeof(struct sdc_io_timings));\r
}\r
\r
const struct ext4_io_stats *io_timings_get(uint32_t time_sum_ms)\r
{\r
- static struct ext4_io_stats s;\r
+ static struct ext4_io_stats s;\r
\r
- s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);\r
- s.io_read /= 1000.0;\r
+ s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);\r
+ s.io_read /= 1000.0;\r
\r
- s.io_write = (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);\r
- s.io_write /= 1000.0;\r
+ s.io_write = (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);\r
+ s.io_write /= 1000.0;\r
\r
- s.cpu = 100.0 - s.io_read - s.io_write;\r
+ s.cpu = 100.0 - s.io_read - s.io_write;\r
\r
- return &s;\r
+ return &s;\r
}\r
\r
/**********************BLOCKDEV INTERFACE**************************************/\r
static int sdc_open(struct ext4_blockdev *bdev);\r
static int sdc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
- uint32_t blk_cnt);\r
+ uint32_t blk_cnt);\r
static int sdc_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
- uint64_t blk_id, uint32_t blk_cnt);\r
+ uint64_t blk_id, uint32_t blk_cnt);\r
static int sdc_close(struct ext4_blockdev *bdev);\r
\r
/******************************************************************************/\r
EXT4_BLOCKDEV_STATIC_INSTANCE(_sdc, SDC_BLOCK_SIZE, 0, sdc_open, sdc_bread,\r
- sdc_bwrite, sdc_close);\r
+ sdc_bwrite, sdc_close);\r
\r
/******************************************************************************/\r
EXT4_BCACHE_STATIC_INSTANCE(_sdc_cache, CONFIG_BLOCK_DEV_CACHE_SIZE,\r
- EXT_LOGICAL_BLOCK_SIZE);\r
+ EXT_LOGICAL_BLOCK_SIZE);\r
\r
/******************************************************************************/\r
\r
static int sdc_open(struct ext4_blockdev *bdev)\r
{\r
- (void)bdev;\r
+ (void)bdev;\r
\r
- static uint8_t mbr[512];\r
- struct part_tab_entry *part0;\r
+ static uint8_t mbr[512];\r
+ struct part_tab_entry *part0;\r
\r
- sdcStart(&SDCD1, NULL);\r
+ sdcStart(&SDCD1, NULL);\r
\r
- if (sdcConnect(&SDCD1) != HAL_SUCCESS)\r
- return EIO;\r
+ if (sdcConnect(&SDCD1) != HAL_SUCCESS)\r
+ return EIO;\r
\r
- if (sdcRead(&SDCD1, 0, mbr, 1) != HAL_SUCCESS)\r
- return EIO;\r
+ if (sdcRead(&SDCD1, 0, mbr, 1) != HAL_SUCCESS)\r
+ return EIO;\r
\r
- part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);\r
+ part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);\r
\r
- part_offset = part0->first_lba;\r
- _sdc.ph_bcnt = SDCD1.capacity * SDC_BLOCK_SIZE;\r
+ part_offset = part0->first_lba;\r
+ _sdc.ph_bcnt = SDCD1.capacity * SDC_BLOCK_SIZE;\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
static int sdc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
- uint32_t blk_cnt)\r
+ uint32_t blk_cnt)\r
{\r
- (void)bdev;\r
- bool status;\r
- uint64_t v = tim_get_us();\r
+ (void)bdev;\r
+ bool status;\r
+ uint64_t v = tim_get_us();\r
\r
- status = sdcRead(&SDCD1, blk_id, buf, blk_cnt);\r
- if (status != HAL_SUCCESS)\r
- return EIO;\r
+ status = sdcRead(&SDCD1, blk_id, buf, blk_cnt);\r
+ if (status != HAL_SUCCESS)\r
+ return EIO;\r
\r
- io_timings.acc_bread += tim_get_us() - v;\r
- io_timings.cnt_bread++;\r
- io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;\r
+ io_timings.acc_bread += tim_get_us() - v;\r
+ io_timings.cnt_bread++;\r
+ io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
static int sdc_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
- uint64_t blk_id, uint32_t blk_cnt)\r
+ uint64_t blk_id, uint32_t blk_cnt)\r
{\r
- (void)bdev;\r
- bool status;\r
- uint64_t v = tim_get_us();\r
+ (void)bdev;\r
+ bool status;\r
+ uint64_t v = tim_get_us();\r
\r
- status = sdcWrite(&SDCD1, blk_id, buf, blk_cnt);\r
- if (status != HAL_SUCCESS)\r
- return EIO;\r
+ status = sdcWrite(&SDCD1, blk_id, buf, blk_cnt);\r
+ if (status != HAL_SUCCESS)\r
+ return EIO;\r
\r
- io_timings.acc_bwrite += tim_get_us() - v;\r
- io_timings.cnt_bwrite++;\r
- io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;\r
+ io_timings.acc_bwrite += tim_get_us() - v;\r
+ io_timings.cnt_bwrite++;\r
+ io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
static int sdc_close(struct ext4_blockdev *bdev)\r
{\r
- (void)bdev;\r
- return EOK;\r
+ (void)bdev;\r
+ return EOK;\r
}\r
\r
/******************************************************************************/\r
/**@brief SDC blockdev get.*/\r
struct ext4_blockdev *sdc_bdev_get(void);\r
\r
-struct ext4_io_stats\r
-{\r
- float io_read;\r
- float io_write;\r
- float cpu;\r
+struct ext4_io_stats {\r
+ float io_read;\r
+ float io_write;\r
+ float cpu;\r
};\r
\r
void io_timings_clear(void);\r
#define MBR_BLOCK_ID 0
#define MBR_PART_TABLE_OFF 446
-struct part_tab_entry
-{
- uint8_t status;
- uint8_t chs1[3];
- uint8_t type;
- uint8_t chs2[3];
- uint32_t first_lba;
- uint32_t sectors;
+struct part_tab_entry {
+ uint8_t status;
+ uint8_t chs1[3];
+ uint8_t type;
+ uint8_t chs2[3];
+ uint32_t first_lba;
+ uint32_t sectors;
} __attribute__((packed));
/**@brief Partition block offset*/
static uint32_t part_offset;
/**@brief IO timings*/
-struct spi_io_timings
-{
- uint64_t acc_bread;
- uint64_t acc_bwrite;
+struct spi_io_timings {
+ uint64_t acc_bread;
+ uint64_t acc_bwrite;
- uint32_t cnt_bread;
- uint32_t cnt_bwrite;
+ uint32_t cnt_bread;
+ uint32_t cnt_bwrite;
- uint32_t av_bread;
- uint32_t av_bwrite;
+ uint32_t av_bread;
+ uint32_t av_bwrite;
};
static struct spi_io_timings io_timings;
void io_timings_clear(void)
{
- memset(&io_timings, 0, sizeof(struct spi_io_timings));
+ memset(&io_timings, 0, sizeof(struct spi_io_timings));
}
const struct ext4_io_stats *io_timings_get(uint32_t time_sum_ms)
{
- static struct ext4_io_stats s;
+ static struct ext4_io_stats s;
- s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);
- s.io_read /= 1000.0;
+ s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);
+ s.io_read /= 1000.0;
- s.io_write = (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);
- s.io_write /= 1000.0;
+ s.io_write = (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);
+ s.io_write /= 1000.0;
- s.cpu = 100.0 - s.io_read - s.io_write;
+ s.cpu = 100.0 - s.io_read - s.io_write;
- return &s;
+ return &s;
}
/**********************BLOCKDEV INTERFACE**************************************/
static int spi_open(struct ext4_blockdev *bdev);
static int spi_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt);
+ uint32_t blk_cnt);
static int spi_bwrite(struct ext4_blockdev *bdev, const void *buf,
- uint64_t blk_id, uint32_t blk_cnt);
+ uint64_t blk_id, uint32_t blk_cnt);
static int spi_close(struct ext4_blockdev *bdev);
/******************************************************************************/
EXT4_BLOCKDEV_STATIC_INSTANCE(_spi, SPI_BLOCK_SIZE, 0, spi_open, spi_bread,
- spi_bwrite, spi_close);
+ spi_bwrite, spi_close);
/******************************************************************************/
EXT4_BCACHE_STATIC_INSTANCE(_spi_cache, CONFIG_BLOCK_DEV_CACHE_SIZE,
- EXT_LOGICAL_BLOCK_SIZE);
+ EXT_LOGICAL_BLOCK_SIZE);
/******************************************************************************/
static int spi_open(struct ext4_blockdev *bdev)
{
- (void)bdev;
+ (void)bdev;
- static uint8_t mbr[512];
- struct part_tab_entry *part0;
+ static uint8_t mbr[512];
+ struct part_tab_entry *part0;
- if (mmcConnect(&MMCD1) != HAL_SUCCESS)
- return EIO;
+ if (mmcConnect(&MMCD1) != HAL_SUCCESS)
+ return EIO;
- if (mmcStartSequentialRead(&MMCD1, 0) != HAL_SUCCESS)
- return EIO;
+ if (mmcStartSequentialRead(&MMCD1, 0) != HAL_SUCCESS)
+ return EIO;
- if (mmcSequentialRead(&MMCD1, mbr) != HAL_SUCCESS)
- return EIO;
+ if (mmcSequentialRead(&MMCD1, mbr) != HAL_SUCCESS)
+ return EIO;
- if (mmcStopSequentialRead(&MMCD1) != HAL_SUCCESS)
- return EIO;
+ if (mmcStopSequentialRead(&MMCD1) != HAL_SUCCESS)
+ return EIO;
- part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);
+ part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);
- part_offset = part0->first_lba;
- _spi.ph_bcnt = MMCD1.capacity * SPI_BLOCK_SIZE;
+ part_offset = part0->first_lba;
+ _spi.ph_bcnt = MMCD1.capacity * SPI_BLOCK_SIZE;
- return EOK;
+ return EOK;
}
static int spi_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt)
+ uint32_t blk_cnt)
{
- (void)bdev;
- uint64_t v = tim_get_us();
+ (void)bdev;
+ uint64_t v = tim_get_us();
- if (mmcStartSequentialRead(&MMCD1, blk_id) != HAL_SUCCESS)
- return EIO;
+ if (mmcStartSequentialRead(&MMCD1, blk_id) != HAL_SUCCESS)
+ return EIO;
- while (blk_cnt) {
- if (mmcSequentialRead(&MMCD1, buf) != HAL_SUCCESS)
- return EIO;
+ while (blk_cnt) {
+ if (mmcSequentialRead(&MMCD1, buf) != HAL_SUCCESS)
+ return EIO;
- buf += SPI_BLOCK_SIZE;
- blk_cnt--;
- }
+ buf += SPI_BLOCK_SIZE;
+ blk_cnt--;
+ }
- if (mmcStopSequentialRead(&MMCD1) != HAL_SUCCESS)
- return EIO;
+ if (mmcStopSequentialRead(&MMCD1) != HAL_SUCCESS)
+ return EIO;
- io_timings.acc_bread += tim_get_us() - v;
- io_timings.cnt_bread++;
- io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;
+ io_timings.acc_bread += tim_get_us() - v;
+ io_timings.cnt_bread++;
+ io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;
- return EOK;
+ return EOK;
}
static int spi_bwrite(struct ext4_blockdev *bdev, const void *buf,
- uint64_t blk_id, uint32_t blk_cnt)
+ uint64_t blk_id, uint32_t blk_cnt)
{
- (void)bdev;
- uint64_t v = tim_get_us();
+ (void)bdev;
+ uint64_t v = tim_get_us();
- if (mmcStartSequentialWrite(&MMCD1, blk_id) != HAL_SUCCESS)
- return EIO;
+ if (mmcStartSequentialWrite(&MMCD1, blk_id) != HAL_SUCCESS)
+ return EIO;
- while (blk_cnt) {
- if (mmcSequentialWrite(&MMCD1, buf) != HAL_SUCCESS)
- return EIO;
+ while (blk_cnt) {
+ if (mmcSequentialWrite(&MMCD1, buf) != HAL_SUCCESS)
+ return EIO;
- buf += SPI_BLOCK_SIZE;
- blk_cnt--;
- }
+ buf += SPI_BLOCK_SIZE;
+ blk_cnt--;
+ }
- if (mmcStopSequentialWrite(&MMCD1) != HAL_SUCCESS)
- return EIO;
+ if (mmcStopSequentialWrite(&MMCD1) != HAL_SUCCESS)
+ return EIO;
- io_timings.acc_bwrite += tim_get_us() - v;
- io_timings.cnt_bwrite++;
- io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;
+ io_timings.acc_bwrite += tim_get_us() - v;
+ io_timings.cnt_bwrite++;
+ io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;
- return EOK;
+ return EOK;
}
static int spi_close(struct ext4_blockdev *bdev)
{
- (void)bdev;
- return EOK;
+ (void)bdev;
+ return EOK;
}
/******************************************************************************/
/**@brief SPI blockdev get.*/
struct ext4_blockdev *spi_bdev_get(void);
-struct ext4_io_stats
-{
- float io_read;
- float io_write;
- float cpu;
+struct ext4_io_stats {
+ float io_read;
+ float io_write;
+ float cpu;
};
void io_timings_clear(void);
static char *entry_to_str(uint8_t type)
{
- switch (type) {
- case EXT4_DIRENTRY_UNKNOWN:
- return "[unk] ";
- case EXT4_DIRENTRY_REG_FILE:
- return "[fil] ";
- case EXT4_DIRENTRY_DIR:
- return "[dir] ";
- case EXT4_DIRENTRY_CHRDEV:
- return "[cha] ";
- case EXT4_DIRENTRY_BLKDEV:
- return "[blk] ";
- case EXT4_DIRENTRY_FIFO:
- return "[fif] ";
- case EXT4_DIRENTRY_SOCK:
- return "[soc] ";
- case EXT4_DIRENTRY_SYMLINK:
- return "[sym] ";
- default:
- break;
- }
- return "[???]";
+ switch (type) {
+ case EXT4_DIRENTRY_UNKNOWN:
+ return "[unk] ";
+ case EXT4_DIRENTRY_REG_FILE:
+ return "[fil] ";
+ case EXT4_DIRENTRY_DIR:
+ return "[dir] ";
+ case EXT4_DIRENTRY_CHRDEV:
+ return "[cha] ";
+ case EXT4_DIRENTRY_BLKDEV:
+ return "[blk] ";
+ case EXT4_DIRENTRY_FIFO:
+ return "[fif] ";
+ case EXT4_DIRENTRY_SOCK:
+ return "[soc] ";
+ case EXT4_DIRENTRY_SYMLINK:
+ return "[sym] ";
+ default:
+ break;
+ }
+ return "[???]";
}
static clock_t get_ms(void) { return tim_get_ms(); }
static void printf_io_timings(clock_t diff)
{
- const struct ext4_io_stats *stats = io_timings_get(diff);
- printf("io_timings:\n");
- printf(" io_read: %.3f%%\n", stats->io_read);
- printf(" io_write: %.3f%%\n", stats->io_write);
- printf(" io_cpu: %.3f%%\n", stats->cpu);
+ const struct ext4_io_stats *stats = io_timings_get(diff);
+ printf("io_timings:\n");
+ printf(" io_read: %.3f%%\n", stats->io_read);
+ printf(" io_write: %.3f%%\n", stats->io_write);
+ printf(" io_cpu: %.3f%%\n", stats->cpu);
}
void test_lwext4_dir_ls(const char *path)
{
- char sss[255];
- ext4_dir d;
- const ext4_direntry *de;
-
- printf("ls %s\n", path);
-
- ext4_dir_open(&d, path);
- de = ext4_dir_entry_next(&d);
-
- while (de) {
- memcpy(sss, de->name, de->name_length);
- sss[de->name_length] = 0;
- printf(" %s%s\n", entry_to_str(de->inode_type), sss);
- de = ext4_dir_entry_next(&d);
- }
- ext4_dir_close(&d);
+ char sss[255];
+ ext4_dir d;
+ const ext4_direntry *de;
+
+ printf("ls %s\n", path);
+
+ ext4_dir_open(&d, path);
+ de = ext4_dir_entry_next(&d);
+
+ while (de) {
+ memcpy(sss, de->name, de->name_length);
+ sss[de->name_length] = 0;
+ printf(" %s%s\n", entry_to_str(de->inode_type), sss);
+ de = ext4_dir_entry_next(&d);
+ }
+ ext4_dir_close(&d);
}
void test_lwext4_mp_stats(void)
{
- struct ext4_mount_stats stats;
- ext4_mount_point_stats("/mp/", &stats);
-
- printf("********************\n");
- printf("ext4_mount_point_stats\n");
- printf("inodes_count = %" PRIu32 "\n", stats.inodes_count);
- printf("free_inodes_count = %" PRIu32 "\n", stats.free_inodes_count);
- printf("blocks_count = %" PRIu32 "\n", (uint32_t)stats.blocks_count);
- printf("free_blocks_count = %" PRIu32 "\n",
- (uint32_t)stats.free_blocks_count);
- printf("block_size = %" PRIu32 "\n", stats.block_size);
- printf("block_group_count = %" PRIu32 "\n", stats.block_group_count);
- printf("blocks_per_group= %" PRIu32 "\n", stats.blocks_per_group);
- printf("inodes_per_group = %" PRIu32 "\n", stats.inodes_per_group);
- printf("volume_name = %s\n", stats.volume_name);
- printf("********************\n");
+ struct ext4_mount_stats stats;
+ ext4_mount_point_stats("/mp/", &stats);
+
+ printf("********************\n");
+ printf("ext4_mount_point_stats\n");
+ printf("inodes_count = %" PRIu32 "\n", stats.inodes_count);
+ printf("free_inodes_count = %" PRIu32 "\n", stats.free_inodes_count);
+ printf("blocks_count = %" PRIu32 "\n", (uint32_t)stats.blocks_count);
+ printf("free_blocks_count = %" PRIu32 "\n",
+ (uint32_t)stats.free_blocks_count);
+ printf("block_size = %" PRIu32 "\n", stats.block_size);
+ printf("block_group_count = %" PRIu32 "\n", stats.block_group_count);
+ printf("blocks_per_group= %" PRIu32 "\n", stats.blocks_per_group);
+ printf("inodes_per_group = %" PRIu32 "\n", stats.inodes_per_group);
+ printf("volume_name = %s\n", stats.volume_name);
+ printf("********************\n");
}
void test_lwext4_block_stats(void)
{
- if (!bd)
- return;
-
- printf("********************\n");
- printf("ext4 blockdev stats\n");
- printf("bdev->bread_ctr = %" PRIu32 "\n", bd->bread_ctr);
- printf("bdev->bwrite_ctr = %" PRIu32 "\n", bd->bwrite_ctr);
-
- printf("bcache->ref_blocks = %" PRIu32 "\n", bc->ref_blocks);
- printf("bcache->max_ref_blocks = %" PRIu32 "\n", bc->max_ref_blocks);
- printf("bcache->lru_ctr = %" PRIu32 "\n", bc->lru_ctr);
-
- printf("\n");
-
- uint32_t i;
- for (i = 0; i < bc->cnt; ++i) {
- printf("bcache->refctr[%" PRIu32 "]= %" PRIu32 "\n", i, bc->refctr[i]);
- }
-
- printf("\n");
- for (i = 0; i < bc->cnt; ++i) {
- printf("bcache->lru_id[%" PRIu32 "] = %" PRIu32 "\n", i, bc->lru_id[i]);
- }
-
- printf("\n");
- for (i = 0; i < bc->cnt; ++i) {
- printf("bcache->free_delay[%" PRIu32 "] = %d\n", i, bc->free_delay[i]);
- }
-
- printf("\n");
- for (i = 0; i < bc->cnt; ++i) {
- printf("bcache->lba[%" PRIu32 "] = %" PRIu32 "\n", i,
- (uint32_t)bc->lba[i]);
- }
-
- printf("********************\n");
+ if (!bd)
+ return;
+
+ printf("********************\n");
+ printf("ext4 blockdev stats\n");
+ printf("bdev->bread_ctr = %" PRIu32 "\n", bd->bread_ctr);
+ printf("bdev->bwrite_ctr = %" PRIu32 "\n", bd->bwrite_ctr);
+
+ printf("bcache->ref_blocks = %" PRIu32 "\n", bc->ref_blocks);
+ printf("bcache->max_ref_blocks = %" PRIu32 "\n", bc->max_ref_blocks);
+ printf("bcache->lru_ctr = %" PRIu32 "\n", bc->lru_ctr);
+
+ printf("\n");
+
+ uint32_t i;
+ for (i = 0; i < bc->cnt; ++i) {
+ printf("bcache->refctr[%" PRIu32 "]= %" PRIu32 "\n", i,
+ bc->refctr[i]);
+ }
+
+ printf("\n");
+ for (i = 0; i < bc->cnt; ++i) {
+ printf("bcache->lru_id[%" PRIu32 "] = %" PRIu32 "\n", i,
+ bc->lru_id[i]);
+ }
+
+ printf("\n");
+ for (i = 0; i < bc->cnt; ++i) {
+ printf("bcache->free_delay[%" PRIu32 "] = %d\n", i,
+ bc->free_delay[i]);
+ }
+
+ printf("\n");
+ for (i = 0; i < bc->cnt; ++i) {
+ printf("bcache->lba[%" PRIu32 "] = %" PRIu32 "\n", i,
+ (uint32_t)bc->lba[i]);
+ }
+
+ printf("********************\n");
}
bool test_lwext4_dir_test(int len)
{
- ext4_file f;
- int r;
- int i;
- char path[64];
- clock_t diff;
- clock_t stop;
- clock_t start;
-
- printf("test_lwext4_dir_test: %d\n", len);
- io_timings_clear();
- start = get_ms();
-
- printf("directory create: /mp/dir1\n");
- r = ext4_dir_mk("/mp/dir1");
- if (r != EOK) {
- printf("ext4_dir_mk: rc = %d\n", r);
- return false;
- }
-
- printf("add files to: /mp/dir1\n");
- for (i = 0; i < len; ++i) {
- sprintf(path, "/mp/dir1/f%d", i);
- r = ext4_fopen(&f, path, "wb");
- if (r != EOK) {
- printf("ext4_fopen: rc = %d\n", r);
- return false;
- }
- }
-
- stop = get_ms();
- diff = stop - start;
- test_lwext4_dir_ls("/mp/dir1");
- printf("test_lwext4_dir_test: time: %d ms\n", (int)diff);
- printf("test_lwext4_dir_test: av: %d ms/entry\n", (int)diff / len);
- printf_io_timings(diff);
- return true;
+ ext4_file f;
+ int r;
+ int i;
+ char path[64];
+ clock_t diff;
+ clock_t stop;
+ clock_t start;
+
+ printf("test_lwext4_dir_test: %d\n", len);
+ io_timings_clear();
+ start = get_ms();
+
+ printf("directory create: /mp/dir1\n");
+ r = ext4_dir_mk("/mp/dir1");
+ if (r != EOK) {
+ printf("ext4_dir_mk: rc = %d\n", r);
+ return false;
+ }
+
+ printf("add files to: /mp/dir1\n");
+ for (i = 0; i < len; ++i) {
+ sprintf(path, "/mp/dir1/f%d", i);
+ r = ext4_fopen(&f, path, "wb");
+ if (r != EOK) {
+ printf("ext4_fopen: rc = %d\n", r);
+ return false;
+ }
+ }
+
+ stop = get_ms();
+ diff = stop - start;
+ test_lwext4_dir_ls("/mp/dir1");
+ printf("test_lwext4_dir_test: time: %d ms\n", (int)diff);
+ printf("test_lwext4_dir_test: av: %d ms/entry\n", (int)diff / len);
+ printf_io_timings(diff);
+ return true;
}
static int verify_buf(const unsigned char *b, size_t len, unsigned char c)
{
- size_t i;
- for (i = 0; i < len; ++i) {
- if (b[i] != c)
- return c - b[i];
- }
+ size_t i;
+ for (i = 0; i < len; ++i) {
+ if (b[i] != c)
+ return c - b[i];
+ }
- return 0;
+ return 0;
}
bool test_lwext4_file_test(uint32_t rw_szie, uint32_t rw_count)
{
- int r;
- uint32_t size;
- uint32_t i;
- clock_t start;
- clock_t stop;
- clock_t diff;
- uint32_t kbps;
- uint64_t size_bytes;
-
- ext4_file f;
-
- printf("file_test:\n");
- printf(" rw size: %" PRIu32 "\n", rw_szie);
- printf(" rw count: %" PRIu32 "\n", rw_count);
-
- /*Add hello world file.*/
- r = ext4_fopen(&f, "/mp/hello.txt", "wb");
- r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);
- r = ext4_fclose(&f);
-
- io_timings_clear();
- start = get_ms();
- r = ext4_fopen(&f, "/mp/test1", "wb");
- if (r != EOK) {
- printf("ext4_fopen ERROR = %d\n", r);
- return false;
- }
-
- printf("ext4_write: %" PRIu32 " * %" PRIu32 " ...\n", rw_szie, rw_count);
- for (i = 0; i < rw_count; ++i) {
-
- memset(rw_buff, i % 10 + '0', rw_szie);
-
- r = ext4_fwrite(&f, rw_buff, rw_szie, &size);
-
- if ((r != EOK) || (size != rw_szie))
- break;
- }
-
- if (i != rw_count) {
- printf(" file_test: rw_count = %" PRIu32 "\n", i);
- return false;
- }
-
- stop = get_ms();
- diff = stop - start;
- size_bytes = rw_szie * rw_count;
- size_bytes = (size_bytes * 1000) / 1024;
- kbps = (size_bytes) / (diff + 1);
- printf(" write time: %d ms\n", (int)diff);
- printf(" write speed: %" PRIu32 " KB/s\n", kbps);
- printf_io_timings(diff);
- r = ext4_fclose(&f);
-
- io_timings_clear();
- start = get_ms();
- r = ext4_fopen(&f, "/mp/test1", "r+");
- if (r != EOK) {
- printf("ext4_fopen ERROR = %d\n", r);
- return false;
- }
-
- printf("ext4_read: %" PRIu32 " * %" PRIu32 " ...\n", rw_szie, rw_count);
-
- for (i = 0; i < rw_count; ++i) {
- r = ext4_fread(&f, rw_buff, rw_szie, &size);
-
- if ((r != EOK) || (size != rw_szie))
- break;
-
- if (verify_buf(rw_buff, rw_szie, i % 10 + '0'))
- break;
- }
-
- if (i != rw_count) {
- printf(" file_test: rw_count = %" PRIu32 "\n", i);
- return false;
- }
-
- stop = get_ms();
- diff = stop - start;
- size_bytes = rw_szie * rw_count;
- size_bytes = (size_bytes * 1000) / 1024;
- kbps = (size_bytes) / (diff + 1);
- printf(" read time: %d ms\n", (int)diff);
- printf(" read speed: %d KB/s\n", (int)kbps);
- printf_io_timings(diff);
-
- r = ext4_fclose(&f);
- return true;
+ int r;
+ uint32_t size;
+ uint32_t i;
+ clock_t start;
+ clock_t stop;
+ clock_t diff;
+ uint32_t kbps;
+ uint64_t size_bytes;
+
+ ext4_file f;
+
+ printf("file_test:\n");
+ printf(" rw size: %" PRIu32 "\n", rw_szie);
+ printf(" rw count: %" PRIu32 "\n", rw_count);
+
+ /*Add hello world file.*/
+ r = ext4_fopen(&f, "/mp/hello.txt", "wb");
+ r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);
+ r = ext4_fclose(&f);
+
+ io_timings_clear();
+ start = get_ms();
+ r = ext4_fopen(&f, "/mp/test1", "wb");
+ if (r != EOK) {
+ printf("ext4_fopen ERROR = %d\n", r);
+ return false;
+ }
+
+ printf("ext4_write: %" PRIu32 " * %" PRIu32 " ...\n", rw_szie,
+ rw_count);
+ for (i = 0; i < rw_count; ++i) {
+
+ memset(rw_buff, i % 10 + '0', rw_szie);
+
+ r = ext4_fwrite(&f, rw_buff, rw_szie, &size);
+
+ if ((r != EOK) || (size != rw_szie))
+ break;
+ }
+
+ if (i != rw_count) {
+ printf(" file_test: rw_count = %" PRIu32 "\n", i);
+ return false;
+ }
+
+ stop = get_ms();
+ diff = stop - start;
+ size_bytes = rw_szie * rw_count;
+ size_bytes = (size_bytes * 1000) / 1024;
+ kbps = (size_bytes) / (diff + 1);
+ printf(" write time: %d ms\n", (int)diff);
+ printf(" write speed: %" PRIu32 " KB/s\n", kbps);
+ printf_io_timings(diff);
+ r = ext4_fclose(&f);
+
+ io_timings_clear();
+ start = get_ms();
+ r = ext4_fopen(&f, "/mp/test1", "r+");
+ if (r != EOK) {
+ printf("ext4_fopen ERROR = %d\n", r);
+ return false;
+ }
+
+ printf("ext4_read: %" PRIu32 " * %" PRIu32 " ...\n", rw_szie, rw_count);
+
+ for (i = 0; i < rw_count; ++i) {
+ r = ext4_fread(&f, rw_buff, rw_szie, &size);
+
+ if ((r != EOK) || (size != rw_szie))
+ break;
+
+ if (verify_buf(rw_buff, rw_szie, i % 10 + '0'))
+ break;
+ }
+
+ if (i != rw_count) {
+ printf(" file_test: rw_count = %" PRIu32 "\n", i);
+ return false;
+ }
+
+ stop = get_ms();
+ diff = stop - start;
+ size_bytes = rw_szie * rw_count;
+ size_bytes = (size_bytes * 1000) / 1024;
+ kbps = (size_bytes) / (diff + 1);
+ printf(" read time: %d ms\n", (int)diff);
+ printf(" read speed: %d KB/s\n", (int)kbps);
+ printf_io_timings(diff);
+
+ r = ext4_fclose(&f);
+ return true;
}
void test_lwext4_cleanup(void)
{
- clock_t start;
- clock_t stop;
- clock_t diff;
-
- printf("\ncleanup:\n");
- ext4_fremove("/mp/hello.txt");
-
- printf("remove /mp/test1\n");
- ext4_fremove("/mp/test1");
-
- printf("remove /mp/dir1\n");
- io_timings_clear();
- start = get_ms();
- ext4_dir_rm("/mp/dir1");
- stop = get_ms();
- diff = stop - start;
- printf("cleanup: time: %d ms\n", (int)diff);
- printf_io_timings(diff);
+ clock_t start;
+ clock_t stop;
+ clock_t diff;
+
+ printf("\ncleanup:\n");
+ ext4_fremove("/mp/hello.txt");
+
+ printf("remove /mp/test1\n");
+ ext4_fremove("/mp/test1");
+
+ printf("remove /mp/dir1\n");
+ io_timings_clear();
+ start = get_ms();
+ ext4_dir_rm("/mp/dir1");
+ stop = get_ms();
+ diff = stop - start;
+ printf("cleanup: time: %d ms\n", (int)diff);
+ printf_io_timings(diff);
}
bool test_lwext4_mount(struct ext4_blockdev *bdev, struct ext4_bcache *bcache)
{
- int r;
+ int r;
- bc = bcache;
- bd = bdev;
+ bc = bcache;
+ bd = bdev;
- if (!bd) {
- printf("test_lwext4_mount: no block device\n");
- return false;
- }
+ if (!bd) {
+ printf("test_lwext4_mount: no block device\n");
+ return false;
+ }
- ext4_dmask_set(EXT4_DEBUG_ALL);
+ ext4_dmask_set(EXT4_DEBUG_ALL);
- r = ext4_device_register(bd, bc ? bc : 0, "ext4_fs");
- if (r != EOK) {
- printf("ext4_device_register: rc = %d\n", r);
- return false;
- }
+ r = ext4_device_register(bd, bc ? bc : 0, "ext4_fs");
+ if (r != EOK) {
+ printf("ext4_device_register: rc = %d\n", r);
+ return false;
+ }
- r = ext4_mount("ext4_fs", "/mp/");
- if (r != EOK) {
- printf("ext4_mount: rc = %d\n", r);
- return false;
- }
+ r = ext4_mount("ext4_fs", "/mp/");
+ if (r != EOK) {
+ printf("ext4_mount: rc = %d\n", r);
+ return false;
+ }
- ext4_cache_write_back("/mp/", 1);
- return true;
+ ext4_cache_write_back("/mp/", 1);
+ return true;
}
bool test_lwext4_umount(void)
{
- ext4_cache_write_back("/mp/", 0);
- int r = ext4_umount("/mp/");
- if (r != EOK) {
- printf("ext4_umount: fail %d", r);
- return false;
- }
- return true;
+ ext4_cache_write_back("/mp/", 0);
+ int r = ext4_umount("/mp/");
+ if (r != EOK) {
+ printf("ext4_umount: fail %d", r);
+ return false;
+ }
+ return true;
}
uint64_t tim_get_us(void)
{
- uint64_t v = chVTGetSystemTimeX();
- return ST2US(v);
+ uint64_t v = chVTGetSystemTimeX();
+ return ST2US(v);
}
uint32_t tim_get_ms(void)
{
- uint32_t v = chVTGetSystemTimeX();
- return ST2MS(v);
+ uint32_t v = chVTGetSystemTimeX();
+ return ST2MS(v);
}
\r
static char *entry_to_str(uint8_t type)\r
{\r
- switch (type) {\r
- case EXT4_DIRENTRY_UNKNOWN:\r
- return "[UNK] ";\r
- case EXT4_DIRENTRY_REG_FILE:\r
- return "[FIL] ";\r
- case EXT4_DIRENTRY_DIR:\r
- return "[DIR] ";\r
- case EXT4_DIRENTRY_CHRDEV:\r
- return "[CHA] ";\r
- case EXT4_DIRENTRY_BLKDEV:\r
- return "[BLK] ";\r
- case EXT4_DIRENTRY_FIFO:\r
- return "[FIF] ";\r
- case EXT4_DIRENTRY_SOCK:\r
- return "[SOC] ";\r
- case EXT4_DIRENTRY_SYMLINK:\r
- return "[SYM] ";\r
- default:\r
- break;\r
- }\r
- return "[???]";\r
+ switch (type) {\r
+ case EXT4_DIRENTRY_UNKNOWN:\r
+ return "[UNK] ";\r
+ case EXT4_DIRENTRY_REG_FILE:\r
+ return "[FIL] ";\r
+ case EXT4_DIRENTRY_DIR:\r
+ return "[DIR] ";\r
+ case EXT4_DIRENTRY_CHRDEV:\r
+ return "[CHA] ";\r
+ case EXT4_DIRENTRY_BLKDEV:\r
+ return "[BLK] ";\r
+ case EXT4_DIRENTRY_FIFO:\r
+ return "[FIF] ";\r
+ case EXT4_DIRENTRY_SOCK:\r
+ return "[SOC] ";\r
+ case EXT4_DIRENTRY_SYMLINK:\r
+ return "[SYM] ";\r
+ default:\r
+ break;\r
+ }\r
+ return "[???]";\r
}\r
\r
static void dir_ls(const char *path)\r
{\r
- char sss[255];\r
- ext4_dir d;\r
- const ext4_direntry *de;\r
-\r
- printf("ls %s:\n", path);\r
-\r
- ext4_dir_open(&d, path);\r
- de = ext4_dir_entry_next(&d);\r
-\r
- while (de) {\r
- memcpy(sss, de->name, de->name_length);\r
- sss[de->name_length] = 0;\r
- printf("\t%s", entry_to_str(de->inode_type));\r
- printf("%s", sss);\r
- printf("\n");\r
- de = ext4_dir_entry_next(&d);\r
- }\r
- ext4_dir_close(&d);\r
+ char sss[255];\r
+ ext4_dir d;\r
+ const ext4_direntry *de;\r
+\r
+ printf("ls %s:\n", path);\r
+\r
+ ext4_dir_open(&d, path);\r
+ de = ext4_dir_entry_next(&d);\r
+\r
+ while (de) {\r
+ memcpy(sss, de->name, de->name_length);\r
+ sss[de->name_length] = 0;\r
+ printf("\t%s", entry_to_str(de->inode_type));\r
+ printf("%s", sss);\r
+ printf("\n");\r
+ de = ext4_dir_entry_next(&d);\r
+ }\r
+ ext4_dir_close(&d);\r
}\r
\r
static void mp_stats(void)\r
{\r
- struct ext4_mount_stats stats;\r
- ext4_mount_point_stats("/mp/", &stats);\r
-\r
- printf("ext4_mount_point_stats:\n");\r
- printf("\tinodes_count = %" PRIu32 "\n", stats.inodes_count);\r
- printf("\tfree_inodes_count = %" PRIu32 "\n", stats.free_inodes_count);\r
- printf("\tblocks_count = %" PRIu32 "\n",\r
- (uint32_t)stats.blocks_count);\r
- printf("\tfree_blocks_count = %" PRIu32 "\n",\r
- (uint32_t)stats.free_blocks_count);\r
- printf("\tblock_size = %" PRIu32 "\n", stats.block_size);\r
- printf("\tblock_group_count = %" PRIu32 "\n", stats.block_group_count);\r
- printf("\tblocks_per_group = %" PRIu32 "\n", stats.blocks_per_group);\r
- printf("\tinodes_per_group = %" PRIu32 "\n", stats.inodes_per_group);\r
- printf("\tvolume_name = %s\n", stats.volume_name);\r
+ struct ext4_mount_stats stats;\r
+ ext4_mount_point_stats("/mp/", &stats);\r
+\r
+ printf("ext4_mount_point_stats:\n");\r
+ printf("\tinodes_count = %" PRIu32 "\n", stats.inodes_count);\r
+ printf("\tfree_inodes_count = %" PRIu32 "\n",\r
+ stats.free_inodes_count);\r
+ printf("\tblocks_count = %" PRIu32 "\n",\r
+ (uint32_t)stats.blocks_count);\r
+ printf("\tfree_blocks_count = %" PRIu32 "\n",\r
+ (uint32_t)stats.free_blocks_count);\r
+ printf("\tblock_size = %" PRIu32 "\n", stats.block_size);\r
+ printf("\tblock_group_count = %" PRIu32 "\n",\r
+ stats.block_group_count);\r
+ printf("\tblocks_per_group = %" PRIu32 "\n", stats.blocks_per_group);\r
+ printf("\tinodes_per_group = %" PRIu32 "\n", stats.inodes_per_group);\r
+ printf("\tvolume_name = %s\n", stats.volume_name);\r
}\r
\r
static void block_stats(void)\r
{\r
- uint32_t i;\r
-\r
- printf("ext4 blockdev stats\n");\r
- printf("\tbdev->bread_ctr = %" PRIu32 "\n", bd->bread_ctr);\r
- printf("\tbdev->bwrite_ctr = %" PRIu32 "\n", bd->bwrite_ctr);\r
-\r
- printf("\tbcache->ref_blocks = %" PRIu32 "\n", bc->ref_blocks);\r
- printf("\tbcache->max_ref_blocks = %" PRIu32 "\n", bc->max_ref_blocks);\r
- printf("\tbcache->lru_ctr = %" PRIu32 "\n", bc->lru_ctr);\r
-\r
- printf("\n");\r
- for (i = 0; i < bc->cnt; ++i) {\r
- printf("\tbcache->refctr[%" PRIu32 "] = %" PRIu32 "\n", i,\r
- bc->refctr[i]);\r
- }\r
-\r
- printf("\n");\r
- for (i = 0; i < bc->cnt; ++i) {\r
- printf("\tbcache->lru_id[%" PRIu32 "] = %" PRIu32 "\n", i,\r
- bc->lru_id[i]);\r
- }\r
-\r
- printf("\n");\r
- for (i = 0; i < bc->cnt; ++i) {\r
- printf("\tbcache->free_delay[%" PRIu32 "] = %d\n", i,\r
- bc->free_delay[i]);\r
- }\r
-\r
- printf("\n");\r
- for (i = 0; i < bc->cnt; ++i) {\r
- printf("\tbcache->lba[%" PRIu32 "] = %" PRIu32 "\n", i,\r
- (uint32_t)bc->lba[i]);\r
- }\r
+ uint32_t i;\r
+\r
+ printf("ext4 blockdev stats\n");\r
+ printf("\tbdev->bread_ctr = %" PRIu32 "\n", bd->bread_ctr);\r
+ printf("\tbdev->bwrite_ctr = %" PRIu32 "\n", bd->bwrite_ctr);\r
+\r
+ printf("\tbcache->ref_blocks = %" PRIu32 "\n", bc->ref_blocks);\r
+ printf("\tbcache->max_ref_blocks = %" PRIu32 "\n",\r
+ bc->max_ref_blocks);\r
+ printf("\tbcache->lru_ctr = %" PRIu32 "\n", bc->lru_ctr);\r
+\r
+ printf("\n");\r
+ for (i = 0; i < bc->cnt; ++i) {\r
+ printf("\tbcache->refctr[%" PRIu32 "] = %" PRIu32 "\n", i,\r
+ bc->refctr[i]);\r
+ }\r
+\r
+ printf("\n");\r
+ for (i = 0; i < bc->cnt; ++i) {\r
+ printf("\tbcache->lru_id[%" PRIu32 "] = %" PRIu32 "\n", i,\r
+ bc->lru_id[i]);\r
+ }\r
+\r
+ printf("\n");\r
+ for (i = 0; i < bc->cnt; ++i) {\r
+ printf("\tbcache->free_delay[%" PRIu32 "] = %d\n", i,\r
+ bc->free_delay[i]);\r
+ }\r
+\r
+ printf("\n");\r
+ for (i = 0; i < bc->cnt; ++i) {\r
+ printf("\tbcache->lba[%" PRIu32 "] = %" PRIu32 "\n", i,\r
+ (uint32_t)bc->lba[i]);\r
+ }\r
}\r
\r
static clock_t get_ms(void)\r
{\r
- struct timeval t;\r
- gettimeofday(&t, NULL);\r
- return (t.tv_sec * 1000) + (t.tv_usec / 1000);\r
+ struct timeval t;\r
+ gettimeofday(&t, NULL);\r
+ return (t.tv_sec * 1000) + (t.tv_usec / 1000);\r
}\r
\r
static bool dir_test(int len)\r
{\r
- ext4_file f;\r
- int r;\r
- int i;\r
- char path[64];\r
- clock_t diff;\r
- clock_t stop;\r
- clock_t start;\r
-\r
- printf("\ndir_test: %d\n", len);\r
- printf("directory create: /mp/dir1\n");\r
- start = get_ms();\r
- r = ext4_dir_mk("/mp/dir1");\r
- if (r != EOK) {\r
- printf("\text4_dir_mk: rc = %d\n", r);\r
- return false;\r
- }\r
-\r
- ext4_cache_write_back("/mp/", 1);\r
- printf("add files to: /mp/dir1\n");\r
- for (i = 0; i < len; ++i) {\r
- sprintf(path, "/mp/dir1/f%d", i);\r
- r = ext4_fopen(&f, path, "wb");\r
- if (r != EOK) {\r
- printf("\text4_fopen: rc = %d\n", r);\r
- return false;\r
- }\r
- }\r
- ext4_cache_write_back("/mp/", 0);\r
-\r
- stop = get_ms();\r
- diff = stop - start;\r
- dir_ls("/mp/dir1");\r
- printf("dir_test: time: %d ms\n", (int)diff);\r
- return true;\r
+ ext4_file f;\r
+ int r;\r
+ int i;\r
+ char path[64];\r
+ clock_t diff;\r
+ clock_t stop;\r
+ clock_t start;\r
+\r
+ printf("\ndir_test: %d\n", len);\r
+ printf("directory create: /mp/dir1\n");\r
+ start = get_ms();\r
+ r = ext4_dir_mk("/mp/dir1");\r
+ if (r != EOK) {\r
+ printf("\text4_dir_mk: rc = %d\n", r);\r
+ return false;\r
+ }\r
+\r
+ ext4_cache_write_back("/mp/", 1);\r
+ printf("add files to: /mp/dir1\n");\r
+ for (i = 0; i < len; ++i) {\r
+ sprintf(path, "/mp/dir1/f%d", i);\r
+ r = ext4_fopen(&f, path, "wb");\r
+ if (r != EOK) {\r
+ printf("\text4_fopen: rc = %d\n", r);\r
+ return false;\r
+ }\r
+ }\r
+ ext4_cache_write_back("/mp/", 0);\r
+\r
+ stop = get_ms();\r
+ diff = stop - start;\r
+ dir_ls("/mp/dir1");\r
+ printf("dir_test: time: %d ms\n", (int)diff);\r
+ return true;\r
}\r
\r
static bool file_test(void)\r
{\r
- int r;\r
- uint32_t size;\r
- ext4_file f;\r
- int i;\r
- clock_t start;\r
- clock_t stop;\r
- clock_t diff;\r
- uint32_t kbps;\r
- uint64_t size_bytes;\r
-\r
- printf("\nfile_test:\n");\r
- /*Add hello world file.*/\r
- r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
- r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
- r = ext4_fclose(&f);\r
-\r
- printf("ext4_fopen: write test\n");\r
- start = get_ms();\r
- r = ext4_fopen(&f, "/mp/test1", "wb");\r
- if (r != EOK) {\r
- printf("\text4_fopen rc = %d\n", r);\r
- return false;\r
- }\r
-\r
- printf("ext4_write: %d * %d ...\n", rw_szie, rw_count);\r
- for (i = 0; i < rw_count; ++i) {\r
-\r
- memset(wr_buff, i % 10 + '0', rw_szie);\r
-\r
- r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
-\r
- if ((r != EOK) || (size != rw_szie))\r
- break;\r
- }\r
-\r
- if (i != rw_count) {\r
- printf("\tfile_test: rw_count = %d\n", i);\r
- return false;\r
- }\r
-\r
- stop = get_ms();\r
- diff = stop - start;\r
- size_bytes = rw_szie * rw_count;\r
- size_bytes = (size_bytes * 1000) / 1024;\r
- kbps = (size_bytes) / (diff + 1);\r
- printf("\twrite time: %d ms\n", (int)diff);\r
- printf("\twrite speed: %" PRIu32 " KB/s\n", kbps);\r
- r = ext4_fclose(&f);\r
-\r
- printf("ext4_fopen: read test\n");\r
- start = get_ms();\r
- r = ext4_fopen(&f, "/mp/test1", "r+");\r
- if (r != EOK) {\r
- printf("\text4_fopen rc = %d\n", r);\r
- return false;\r
- }\r
-\r
- printf("ext4_read: %d * %d ...\n", rw_szie, rw_count);\r
- for (i = 0; i < rw_count; ++i) {\r
- memset(wr_buff, i % 10 + '0', rw_szie);\r
- r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
-\r
- if ((r != EOK) || (size != rw_szie))\r
- break;\r
-\r
- if (memcmp(rd_buff, wr_buff, rw_szie)) {\r
- break;\r
- }\r
- }\r
- if (i != rw_count) {\r
- printf("\tfile_test: rw_count = %d\n", i);\r
- return false;\r
- }\r
- stop = get_ms();\r
- diff = stop - start;\r
- size_bytes = rw_szie * rw_count;\r
- size_bytes = (size_bytes * 1000) / 1024;\r
- kbps = (size_bytes) / (diff + 1);\r
- printf("\tread time: %d ms\n", (int)diff);\r
- printf("\tread speed: %" PRIu32 " KB/s\n", kbps);\r
- r = ext4_fclose(&f);\r
-\r
- return true;\r
+ int r;\r
+ uint32_t size;\r
+ ext4_file f;\r
+ int i;\r
+ clock_t start;\r
+ clock_t stop;\r
+ clock_t diff;\r
+ uint32_t kbps;\r
+ uint64_t size_bytes;\r
+\r
+ printf("\nfile_test:\n");\r
+ /*Add hello world file.*/\r
+ r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
+ r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
+ r = ext4_fclose(&f);\r
+\r
+ printf("ext4_fopen: write test\n");\r
+ start = get_ms();\r
+ r = ext4_fopen(&f, "/mp/test1", "wb");\r
+ if (r != EOK) {\r
+ printf("\text4_fopen rc = %d\n", r);\r
+ return false;\r
+ }\r
+\r
+ printf("ext4_write: %d * %d ...\n", rw_szie, rw_count);\r
+ for (i = 0; i < rw_count; ++i) {\r
+\r
+ memset(wr_buff, i % 10 + '0', rw_szie);\r
+\r
+ r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
+\r
+ if ((r != EOK) || (size != rw_szie))\r
+ break;\r
+ }\r
+\r
+ if (i != rw_count) {\r
+ printf("\tfile_test: rw_count = %d\n", i);\r
+ return false;\r
+ }\r
+\r
+ stop = get_ms();\r
+ diff = stop - start;\r
+ size_bytes = rw_szie * rw_count;\r
+ size_bytes = (size_bytes * 1000) / 1024;\r
+ kbps = (size_bytes) / (diff + 1);\r
+ printf("\twrite time: %d ms\n", (int)diff);\r
+ printf("\twrite speed: %" PRIu32 " KB/s\n", kbps);\r
+ r = ext4_fclose(&f);\r
+\r
+ printf("ext4_fopen: read test\n");\r
+ start = get_ms();\r
+ r = ext4_fopen(&f, "/mp/test1", "r+");\r
+ if (r != EOK) {\r
+ printf("\text4_fopen rc = %d\n", r);\r
+ return false;\r
+ }\r
+\r
+ printf("ext4_read: %d * %d ...\n", rw_szie, rw_count);\r
+ for (i = 0; i < rw_count; ++i) {\r
+ memset(wr_buff, i % 10 + '0', rw_szie);\r
+ r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
+\r
+ if ((r != EOK) || (size != rw_szie))\r
+ break;\r
+\r
+ if (memcmp(rd_buff, wr_buff, rw_szie)) {\r
+ break;\r
+ }\r
+ }\r
+ if (i != rw_count) {\r
+ printf("\tfile_test: rw_count = %d\n", i);\r
+ return false;\r
+ }\r
+ stop = get_ms();\r
+ diff = stop - start;\r
+ size_bytes = rw_szie * rw_count;\r
+ size_bytes = (size_bytes * 1000) / 1024;\r
+ kbps = (size_bytes) / (diff + 1);\r
+ printf("\tread time: %d ms\n", (int)diff);\r
+ printf("\tread speed: %" PRIu32 " KB/s\n", kbps);\r
+ r = ext4_fclose(&f);\r
+\r
+ return true;\r
}\r
static void cleanup(void)\r
{\r
- clock_t start;\r
- clock_t stop;\r
- clock_t diff;\r
-\r
- printf("\ncleanup:\n");\r
- ext4_fremove("/mp/hello.txt");\r
- printf("cleanup: remove /mp/test1\n");\r
- ext4_fremove("/mp/test1");\r
-\r
- printf("cleanup: remove /mp/dir1\n");\r
- start = get_ms();\r
- ext4_dir_rm("/mp/dir1");\r
- stop = get_ms();\r
- diff = stop - start;\r
- printf("cleanup: time: %d ms\n", (int)diff);\r
+ clock_t start;\r
+ clock_t stop;\r
+ clock_t diff;\r
+\r
+ printf("\ncleanup:\n");\r
+ ext4_fremove("/mp/hello.txt");\r
+ printf("cleanup: remove /mp/test1\n");\r
+ ext4_fremove("/mp/test1");\r
+\r
+ printf("cleanup: remove /mp/dir1\n");\r
+ start = get_ms();\r
+ ext4_dir_rm("/mp/dir1");\r
+ stop = get_ms();\r
+ diff = stop - start;\r
+ printf("cleanup: time: %d ms\n", (int)diff);\r
}\r
\r
static bool open_filedev(void)\r
{\r
- ext4_filedev_filename(input_name);\r
- bd = ext4_filedev_get();\r
- if (!bd) {\r
- printf("open_filedev: fail\n");\r
- return false;\r
- }\r
- return true;\r
+ ext4_filedev_filename(input_name);\r
+ bd = ext4_filedev_get();\r
+ if (!bd) {\r
+ printf("open_filedev: fail\n");\r
+ return false;\r
+ }\r
+ return true;\r
}\r
\r
static bool open_winpartition(void)\r
{\r
#ifdef WIN32\r
- ext4_io_raw_filename(input_name);\r
- bd = ext4_io_raw_dev_get();\r
- if (!bd) {\r
- printf("open_winpartition: fail\n");\r
- return false;\r
- }\r
- return true;\r
+ ext4_io_raw_filename(input_name);\r
+ bd = ext4_io_raw_dev_get();\r
+ if (!bd) {\r
+ printf("open_winpartition: fail\n");\r
+ return false;\r
+ }\r
+ return true;\r
#else\r
- printf(\r
- "open_winpartition: this mode should be used only under windows !\n");\r
- return false;\r
+ printf("open_winpartition: this mode should be used only under windows "\r
+ "!\n");\r
+ return false;\r
#endif\r
}\r
\r
static bool mount(void)\r
{\r
- int r;\r
- if (winpart) {\r
- if (!open_winpartition())\r
- return false;\r
- } else {\r
- if (!open_filedev())\r
- return false;\r
- }\r
- wr_buff = malloc(rw_szie);\r
- rd_buff = malloc(rw_szie);\r
-\r
- if (!wr_buff || !rd_buff) {\r
- printf("mount: allocation failed\n");\r
- return false;\r
- }\r
-\r
- ext4_dmask_set(EXT4_DEBUG_ALL);\r
-\r
- r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_fs");\r
- if (r != EOK) {\r
- printf("ext4_device_register: rc = %d\n", r);\r
- return false;\r
- }\r
-\r
- r = ext4_mount("ext4_fs", "/mp/");\r
- if (r != EOK) {\r
- printf("ext4_mount: rc = %d\n", r);\r
- return false;\r
- }\r
-\r
- return true;\r
+ int r;\r
+ if (winpart) {\r
+ if (!open_winpartition())\r
+ return false;\r
+ } else {\r
+ if (!open_filedev())\r
+ return false;\r
+ }\r
+ wr_buff = malloc(rw_szie);\r
+ rd_buff = malloc(rw_szie);\r
+\r
+ if (!wr_buff || !rd_buff) {\r
+ printf("mount: allocation failed\n");\r
+ return false;\r
+ }\r
+\r
+ ext4_dmask_set(EXT4_DEBUG_ALL);\r
+\r
+ r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_fs");\r
+ if (r != EOK) {\r
+ printf("ext4_device_register: rc = %d\n", r);\r
+ return false;\r
+ }\r
+\r
+ r = ext4_mount("ext4_fs", "/mp/");\r
+ if (r != EOK) {\r
+ printf("ext4_mount: rc = %d\n", r);\r
+ return false;\r
+ }\r
+\r
+ return true;\r
}\r
\r
static bool umount(void)\r
{\r
- int r = ext4_umount("/mp/");\r
- if (r != EOK) {\r
- printf("ext4_umount: rc = %d", r);\r
- return false;\r
- }\r
- return true;\r
+ int r = ext4_umount("/mp/");\r
+ if (r != EOK) {\r
+ printf("ext4_umount: rc = %d", r);\r
+ return false;\r
+ }\r
+ return true;\r
}\r
\r
static bool parse_opt(int argc, char **argv)\r
{\r
- int option_index = 0;\r
- int c;\r
-\r
- static struct option long_options[] = {{"in", required_argument, 0, 'a'},\r
- {"rws", required_argument, 0, 'b'},\r
- {"rwc", required_argument, 0, 'c'},\r
- {"cache", required_argument, 0, 'd'},\r
- {"dirs", required_argument, 0, 'e'},\r
- {"clean", no_argument, 0, 'f'},\r
- {"bstat", no_argument, 0, 'g'},\r
- {"sbstat", no_argument, 0, 'h'},\r
- {"wpart", no_argument, 0, 'i'},\r
- {0, 0, 0, 0}};\r
-\r
- while (-1 != (c = getopt_long(argc, argv, "a:b:c:d:e:fghi", long_options,\r
- &option_index))) {\r
-\r
- switch (c) {\r
- case 'a':\r
- strcpy(input_name, optarg);\r
- break;\r
- case 'b':\r
- rw_szie = atoi(optarg);\r
- break;\r
- case 'c':\r
- rw_count = atoi(optarg);\r
- break;\r
- case 'd':\r
- cache_mode = atoi(optarg);\r
- break;\r
- case 'e':\r
- dir_cnt = atoi(optarg);\r
- break;\r
- case 'f':\r
- cleanup_flag = true;\r
- break;\r
- case 'g':\r
- bstat = true;\r
- break;\r
- case 'h':\r
- sbstat = true;\r
- break;\r
- case 'i':\r
- winpart = true;\r
- break;\r
- default:\r
- printf("%s", usage);\r
- return false;\r
- }\r
- }\r
- return true;\r
+ int option_index = 0;\r
+ int c;\r
+\r
+ static struct option long_options[] = {\r
+ {"in", required_argument, 0, 'a'},\r
+ {"rws", required_argument, 0, 'b'},\r
+ {"rwc", required_argument, 0, 'c'},\r
+ {"cache", required_argument, 0, 'd'},\r
+ {"dirs", required_argument, 0, 'e'},\r
+ {"clean", no_argument, 0, 'f'},\r
+ {"bstat", no_argument, 0, 'g'},\r
+ {"sbstat", no_argument, 0, 'h'},\r
+ {"wpart", no_argument, 0, 'i'},\r
+ {0, 0, 0, 0}};\r
+\r
+ while (-1 != (c = getopt_long(argc, argv, "a:b:c:d:e:fghi",\r
+ long_options, &option_index))) {\r
+\r
+ switch (c) {\r
+ case 'a':\r
+ strcpy(input_name, optarg);\r
+ break;\r
+ case 'b':\r
+ rw_szie = atoi(optarg);\r
+ break;\r
+ case 'c':\r
+ rw_count = atoi(optarg);\r
+ break;\r
+ case 'd':\r
+ cache_mode = atoi(optarg);\r
+ break;\r
+ case 'e':\r
+ dir_cnt = atoi(optarg);\r
+ break;\r
+ case 'f':\r
+ cleanup_flag = true;\r
+ break;\r
+ case 'g':\r
+ bstat = true;\r
+ break;\r
+ case 'h':\r
+ sbstat = true;\r
+ break;\r
+ case 'i':\r
+ winpart = true;\r
+ break;\r
+ default:\r
+ printf("%s", usage);\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
}\r
\r
int main(int argc, char **argv)\r
{\r
- if (!parse_opt(argc, argv))\r
- return EXIT_FAILURE;\r
+ if (!parse_opt(argc, argv))\r
+ return EXIT_FAILURE;\r
\r
- printf("test conditions:\n");\r
- printf("\timput name: %s\n", input_name);\r
- printf("\trw size: %d\n", rw_szie);\r
- printf("\trw count: %d\n", rw_count);\r
- printf("\tcache mode: %s\n", cache_mode ? "dynamic" : "static");\r
+ printf("test conditions:\n");\r
+ printf("\timput name: %s\n", input_name);\r
+ printf("\trw size: %d\n", rw_szie);\r
+ printf("\trw count: %d\n", rw_count);\r
+ printf("\tcache mode: %s\n", cache_mode ? "dynamic" : "static");\r
\r
- if (!mount())\r
- return EXIT_FAILURE;\r
+ if (!mount())\r
+ return EXIT_FAILURE;\r
\r
- cleanup();\r
+ cleanup();\r
\r
- if (sbstat)\r
- mp_stats();\r
+ if (sbstat)\r
+ mp_stats();\r
\r
- dir_ls("/mp/");\r
- fflush(stdout);\r
- if (!dir_test(dir_cnt))\r
- return EXIT_FAILURE;\r
+ dir_ls("/mp/");\r
+ fflush(stdout);\r
+ if (!dir_test(dir_cnt))\r
+ return EXIT_FAILURE;\r
\r
- fflush(stdout);\r
- if (!file_test())\r
- return EXIT_FAILURE;\r
+ fflush(stdout);\r
+ if (!file_test())\r
+ return EXIT_FAILURE;\r
\r
- fflush(stdout);\r
- dir_ls("/mp/");\r
+ fflush(stdout);\r
+ dir_ls("/mp/");\r
\r
- if (sbstat)\r
- mp_stats();\r
+ if (sbstat)\r
+ mp_stats();\r
\r
- if (cleanup_flag)\r
- cleanup();\r
+ if (cleanup_flag)\r
+ cleanup();\r
\r
- if (bstat)\r
- block_stats();\r
+ if (bstat)\r
+ block_stats();\r
\r
- if (!umount())\r
- return EXIT_FAILURE;\r
+ if (!umount())\r
+ return EXIT_FAILURE;\r
\r
- printf("\ntest finished\n");\r
- return EXIT_SUCCESS;\r
+ printf("\ntest finished\n");\r
+ return EXIT_SUCCESS;\r
}\r
\r
static int client_connect(void)\r
{\r
- int fd = 0;\r
- struct sockaddr_in serv_addr;\r
-\r
- if (winsock_init() < 0) {\r
- printf("winsock_init error\n");\r
- exit(-1);\r
- }\r
-\r
- memset(&serv_addr, '0', sizeof(serv_addr));\r
- fd = socket(AF_INET, SOCK_STREAM, 0);\r
- if (fd < 0) {\r
- printf("socket() error: %s\n", strerror(errno));\r
- exit(-1);\r
- }\r
-\r
- serv_addr.sin_family = AF_INET;\r
- serv_addr.sin_port = htons(connection_port);\r
-\r
- if (!inet_pton(AF_INET, server_addr, &serv_addr.sin_addr)) {\r
- printf("inet_pton() error\n");\r
- exit(-1);\r
- }\r
-\r
- if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {\r
- printf("connect() error: %s\n", strerror(errno));\r
- exit(-1);\r
- }\r
-\r
- return fd;\r
+ int fd = 0;\r
+ struct sockaddr_in serv_addr;\r
+\r
+ if (winsock_init() < 0) {\r
+ printf("winsock_init error\n");\r
+ exit(-1);\r
+ }\r
+\r
+ memset(&serv_addr, '0', sizeof(serv_addr));\r
+ fd = socket(AF_INET, SOCK_STREAM, 0);\r
+ if (fd < 0) {\r
+ printf("socket() error: %s\n", strerror(errno));\r
+ exit(-1);\r
+ }\r
+\r
+ serv_addr.sin_family = AF_INET;\r
+ serv_addr.sin_port = htons(connection_port);\r
+\r
+ if (!inet_pton(AF_INET, server_addr, &serv_addr.sin_addr)) {\r
+ printf("inet_pton() error\n");\r
+ exit(-1);\r
+ }\r
+\r
+ if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {\r
+ printf("connect() error: %s\n", strerror(errno));\r
+ exit(-1);\r
+ }\r
+\r
+ return fd;\r
}\r
\r
static bool parse_opt(int argc, char **argv)\r
{\r
- int option_index = 0;\r
- int c;\r
-\r
- static struct option long_options[] = {{"call", required_argument, 0, 'c'},\r
- {"port", required_argument, 0, 'p'},\r
- {"addr", required_argument, 0, 'a'},\r
- {0, 0, 0, 0}};\r
-\r
- while (-1 != (c = getopt_long(argc, argv, "c:p:a:", long_options,\r
- &option_index))) {\r
-\r
- switch (c) {\r
- case 'a':\r
- server_addr = optarg;\r
- break;\r
- case 'p':\r
- connection_port = atoi(optarg);\r
- break;\r
- case 'c':\r
- op_code = optarg;\r
- break;\r
- default:\r
- printf("%s", usage);\r
- return false;\r
- }\r
- }\r
- return true;\r
+ int option_index = 0;\r
+ int c;\r
+\r
+ static struct option long_options[] = {\r
+ {"call", required_argument, 0, 'c'},\r
+ {"port", required_argument, 0, 'p'},\r
+ {"addr", required_argument, 0, 'a'},\r
+ {0, 0, 0, 0}};\r
+\r
+ while (-1 != (c = getopt_long(argc, argv, "c:p:a:", long_options,\r
+ &option_index))) {\r
+\r
+ switch (c) {\r
+ case 'a':\r
+ server_addr = optarg;\r
+ break;\r
+ case 'p':\r
+ connection_port = atoi(optarg);\r
+ break;\r
+ case 'c':\r
+ op_code = optarg;\r
+ break;\r
+ default:\r
+ printf("%s", usage);\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
}\r
\r
int main(int argc, char *argv[])\r
{\r
- int sockfd;\r
- int n;\r
- int rc;\r
- char recvBuff[1024];\r
-\r
- if (!parse_opt(argc, argv))\r
- return -1;\r
-\r
- sockfd = client_connect();\r
-\r
- n = send(sockfd, op_code, strlen(op_code), 0);\r
- if (n < 0) {\r
- printf("\tWrite error: %s fd = %d\n", strerror(errno), sockfd);\r
- return -1;\r
- }\r
-\r
- n = recv(sockfd, (void *)&rc, sizeof(rc), 0);\r
- if (n < 0) {\r
- printf("\tWrite error: %s fd = %d\n", strerror(errno), sockfd);\r
- return -1;\r
- }\r
-\r
- printf("rc: %d %s\n", rc, strerror(rc));\r
- if (rc)\r
- printf("\t%s\n", op_code);\r
-\r
- winsock_fini();\r
- return rc;\r
+ int sockfd;\r
+ int n;\r
+ int rc;\r
+ char recvBuff[1024];\r
+\r
+ if (!parse_opt(argc, argv))\r
+ return -1;\r
+\r
+ sockfd = client_connect();\r
+\r
+ n = send(sockfd, op_code, strlen(op_code), 0);\r
+ if (n < 0) {\r
+ printf("\tWrite error: %s fd = %d\n", strerror(errno), sockfd);\r
+ return -1;\r
+ }\r
+\r
+ n = recv(sockfd, (void *)&rc, sizeof(rc), 0);\r
+ if (n < 0) {\r
+ printf("\tWrite error: %s fd = %d\n", strerror(errno), sockfd);\r
+ return -1;\r
+ }\r
+\r
+ printf("rc: %d %s\n", rc, strerror(rc));\r
+ if (rc)\r
+ printf("\t%s\n", op_code);\r
+\r
+ winsock_fini();\r
+ return rc;\r
}\r
\r
static int winsock_init(void)\r
{\r
#if WIN32\r
- int rc;\r
- static WSADATA wsaData;\r
- rc = WSAStartup(MAKEWORD(2, 2), &wsaData);\r
- if (rc != 0) {\r
- return -1;\r
- }\r
+ int rc;\r
+ static WSADATA wsaData;\r
+ rc = WSAStartup(MAKEWORD(2, 2), &wsaData);\r
+ if (rc != 0) {\r
+ return -1;\r
+ }\r
#endif\r
- return 0;\r
+ return 0;\r
}\r
\r
static void winsock_fini(void)\r
{\r
#if WIN32\r
- WSACleanup();\r
+ WSACleanup();\r
#endif\r
}\r
\r
#if WIN32\r
static int inet_pton(int af, const char *src, void *dst)\r
{\r
- struct sockaddr_storage ss;\r
- int size = sizeof(ss);\r
- char src_copy[INET6_ADDRSTRLEN + 1];\r
-\r
- ZeroMemory(&ss, sizeof(ss));\r
- /* stupid non-const API */\r
- strncpy(src_copy, src, INET6_ADDRSTRLEN + 1);\r
- src_copy[INET6_ADDRSTRLEN] = 0;\r
-\r
- if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) ==\r
- 0) {\r
- switch (af) {\r
- case AF_INET:\r
- *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;\r
- return 1;\r
- case AF_INET6:\r
- *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;\r
- return 1;\r
- }\r
- }\r
- return 0;\r
+ struct sockaddr_storage ss;\r
+ int size = sizeof(ss);\r
+ char src_copy[INET6_ADDRSTRLEN + 1];\r
+\r
+ ZeroMemory(&ss, sizeof(ss));\r
+ /* stupid non-const API */\r
+ strncpy(src_copy, src, INET6_ADDRSTRLEN + 1);\r
+ src_copy[INET6_ADDRSTRLEN] = 0;\r
+\r
+ if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss,\r
+ &size) == 0) {\r
+ switch (af) {\r
+ case AF_INET:\r
+ *(struct in_addr *)dst =\r
+ ((struct sockaddr_in *)&ss)->sin_addr;\r
+ return 1;\r
+ case AF_INET6:\r
+ *(struct in6_addr *)dst =\r
+ ((struct sockaddr_in6 *)&ss)->sin6_addr;\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
}\r
#endif\r
\r
/**@brief Open file instance descriptor.*/\r
struct lwext4_files {\r
- char name[255];\r
- ext4_file fd;\r
+ char name[255];\r
+ ext4_file fd;\r
};\r
\r
/**@brief Open directory instance descriptor.*/\r
struct lwext4_dirs {\r
- char name[255];\r
- ext4_dir fd;\r
+ char name[255];\r
+ ext4_dir fd;\r
};\r
\r
/**@brief Library call opcode.*/\r
struct lwext4_op_codes {\r
- char *func;\r
+ char *func;\r
};\r
\r
/**@brief Library call wraper.*/\r
struct lwext4_call {\r
- int (*lwext4_call)(char *p);\r
+ int (*lwext4_call)(char *p);\r
};\r
\r
/**@brief */\r
/**@brief */\r
static struct lwext4_call op_call[] = {\r
_device_register, /*PARAMS(3): 0 cache_mode dev_name */\r
- _mount, /*PARAMS(2): dev_name mount_point */\r
- _umount, /*PARAMS(1): mount_point */\r
+ _mount, /*PARAMS(2): dev_name mount_point */\r
+ _umount, /*PARAMS(1): mount_point */\r
_mount_point_stats, /*PARAMS(2): mount_point, 0 */\r
_cache_write_back, /*PARAMS(2): mount_point, en */\r
- _fremove, /*PARAMS(1): path */\r
- _fopen, /*PARAMS(2): fid path flags */\r
- _fclose, /*PARAMS(1): fid */\r
- _fread, /*PARAMS(4): fid 0 len 0 */\r
- _fwrite, /*PARAMS(4): fid 0 len 0 */\r
- _fseek, /*PARAMS(2): fid off origin */\r
- _ftell, /*PARAMS(2): fid exp */\r
- _fsize, /*PARAMS(2): fid exp */\r
- _dir_rm, /*PARAMS(1): path */\r
- _dir_mk, /*PARAMS(1): path */\r
- _dir_open, /*PARAMS(2): did, path */\r
- _dir_close, /*PARAMS(1): did */\r
+ _fremove, /*PARAMS(1): path */\r
+ _fopen, /*PARAMS(2): fid path flags */\r
+ _fclose, /*PARAMS(1): fid */\r
+ _fread, /*PARAMS(4): fid 0 len 0 */\r
+ _fwrite, /*PARAMS(4): fid 0 len 0 */\r
+ _fseek, /*PARAMS(2): fid off origin */\r
+ _ftell, /*PARAMS(2): fid exp */\r
+ _fsize, /*PARAMS(2): fid exp */\r
+ _dir_rm, /*PARAMS(1): path */\r
+ _dir_mk, /*PARAMS(1): path */\r
+ _dir_open, /*PARAMS(2): did, path */\r
+ _dir_close, /*PARAMS(1): did */\r
_dir_entry_get, /*PARAMS(2): did, exp */\r
\r
_multi_fcreate, /*PARAMS(3): path prefix cnt */\r
\r
static clock_t get_ms(void)\r
{\r
- struct timeval t;\r
- gettimeofday(&t, NULL);\r
- return (t.tv_sec * 1000) + (t.tv_usec / 1000);\r
+ struct timeval t;\r
+ gettimeofday(&t, NULL);\r
+ return (t.tv_sec * 1000) + (t.tv_usec / 1000);\r
}\r
\r
/**@brief */\r
static int exec_op_code(char *opcode)\r
{\r
- int i;\r
- int r = -1;\r
+ int i;\r
+ int r = -1;\r
\r
- for (i = 0; i < sizeof(op_codes) / sizeof(op_codes[0]); ++i) {\r
+ for (i = 0; i < sizeof(op_codes) / sizeof(op_codes[0]); ++i) {\r
\r
- if (strncmp(op_codes[i].func, opcode, strlen(op_codes[i].func)))\r
- continue;\r
+ if (strncmp(op_codes[i].func, opcode, strlen(op_codes[i].func)))\r
+ continue;\r
\r
- if (opcode[strlen(op_codes[i].func)] != ' ')\r
- continue;\r
+ if (opcode[strlen(op_codes[i].func)] != ' ')\r
+ continue;\r
\r
- printf("%s\n", opcode);\r
- opcode += strlen(op_codes[i].func);\r
- /*Call*/\r
+ printf("%s\n", opcode);\r
+ opcode += strlen(op_codes[i].func);\r
+ /*Call*/\r
\r
- clock_t t = get_ms();\r
- r = op_call[i].lwext4_call(opcode);\r
+ clock_t t = get_ms();\r
+ r = op_call[i].lwext4_call(opcode);\r
\r
- printf("rc: %d, time: %ums\n", r, (unsigned int)(get_ms() - t));\r
+ printf("rc: %d, time: %ums\n", r, (unsigned int)(get_ms() - t));\r
\r
- break;\r
- }\r
+ break;\r
+ }\r
\r
- return r;\r
+ return r;\r
}\r
\r
static int server_open(void)\r
{\r
- int fd = 0;\r
- struct sockaddr_in serv_addr;\r
-\r
- memset(&serv_addr, 0, sizeof(serv_addr));\r
-\r
- if (winsock_init() < 0) {\r
- printf("winsock_init() error\n");\r
- exit(-1);\r
- }\r
-\r
- fd = socket(AF_INET, SOCK_STREAM, 0);\r
- if (fd < 0) {\r
- printf("socket() error: %s\n", strerror(errno));\r
- exit(-1);\r
- }\r
-\r
- int yes = 1;\r
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(int))) {\r
- printf("setsockopt() error: %s\n", strerror(errno));\r
- exit(-1);\r
- }\r
-\r
- serv_addr.sin_family = AF_INET;\r
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);\r
- serv_addr.sin_port = htons(connection_port);\r
-\r
- if (bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {\r
- printf("bind() error: %s\n", strerror(errno));\r
- exit(-1);\r
- }\r
-\r
- if (listen(fd, 1)) {\r
- printf("listen() error: %s\n", strerror(errno));\r
- exit(-1);\r
- }\r
-\r
- return fd;\r
+ int fd = 0;\r
+ struct sockaddr_in serv_addr;\r
+\r
+ memset(&serv_addr, 0, sizeof(serv_addr));\r
+\r
+ if (winsock_init() < 0) {\r
+ printf("winsock_init() error\n");\r
+ exit(-1);\r
+ }\r
+\r
+ fd = socket(AF_INET, SOCK_STREAM, 0);\r
+ if (fd < 0) {\r
+ printf("socket() error: %s\n", strerror(errno));\r
+ exit(-1);\r
+ }\r
+\r
+ int yes = 1;\r
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes,\r
+ sizeof(int))) {\r
+ printf("setsockopt() error: %s\n", strerror(errno));\r
+ exit(-1);\r
+ }\r
+\r
+ serv_addr.sin_family = AF_INET;\r
+ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);\r
+ serv_addr.sin_port = htons(connection_port);\r
+\r
+ if (bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {\r
+ printf("bind() error: %s\n", strerror(errno));\r
+ exit(-1);\r
+ }\r
+\r
+ if (listen(fd, 1)) {\r
+ printf("listen() error: %s\n", strerror(errno));\r
+ exit(-1);\r
+ }\r
+\r
+ return fd;\r
}\r
\r
static bool parse_opt(int argc, char **argv)\r
{\r
- int option_index = 0;\r
- int c;\r
-\r
- static struct option long_options[] = {\r
- {"image", required_argument, 0, 'i'},\r
- {"port", required_argument, 0, 'p'},\r
- {"verbose", required_argument, 0, 'v'},\r
- {"winpart", required_argument, 0, 'w'},\r
- {"cache_wb", required_argument, 0, 'c'},\r
- {0, 0, 0, 0}};\r
-\r
- while (-1 != (c = getopt_long(argc, argv, "c:i:p:v:w:", long_options,\r
- &option_index))) {\r
-\r
- switch (c) {\r
- case 'i':\r
- ext4_fname = optarg;\r
- break;\r
- case 'p':\r
- connection_port = atoi(optarg);\r
- break;\r
- case 'v':\r
- verbose = atoi(optarg);\r
- break;\r
- case 'c':\r
- cache_wb = atoi(optarg);\r
- break;\r
- case 'w':\r
- winpart = atoi(optarg);\r
- break;\r
- default:\r
- printf("%s", usage);\r
- return false;\r
- }\r
- }\r
- return true;\r
+ int option_index = 0;\r
+ int c;\r
+\r
+ static struct option long_options[] = {\r
+ {"image", required_argument, 0, 'i'},\r
+ {"port", required_argument, 0, 'p'},\r
+ {"verbose", required_argument, 0, 'v'},\r
+ {"winpart", required_argument, 0, 'w'},\r
+ {"cache_wb", required_argument, 0, 'c'},\r
+ {0, 0, 0, 0}};\r
+\r
+ while (-1 != (c = getopt_long(argc, argv, "c:i:p:v:w:", long_options,\r
+ &option_index))) {\r
+\r
+ switch (c) {\r
+ case 'i':\r
+ ext4_fname = optarg;\r
+ break;\r
+ case 'p':\r
+ connection_port = atoi(optarg);\r
+ break;\r
+ case 'v':\r
+ verbose = atoi(optarg);\r
+ break;\r
+ case 'c':\r
+ cache_wb = atoi(optarg);\r
+ break;\r
+ case 'w':\r
+ winpart = atoi(optarg);\r
+ break;\r
+ default:\r
+ printf("%s", usage);\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
}\r
\r
int main(int argc, char *argv[])\r
{\r
- int n;\r
- int listenfd;\r
- int connfd;\r
- char op_code[128];\r
+ int n;\r
+ int listenfd;\r
+ int connfd;\r
+ char op_code[128];\r
\r
- if (!parse_opt(argc, argv))\r
- return -1;\r
+ if (!parse_opt(argc, argv))\r
+ return -1;\r
\r
- listenfd = server_open();\r
+ listenfd = server_open();\r
\r
- printf("lwext4_server: listening on port: %d\n", connection_port);\r
+ printf("lwext4_server: listening on port: %d\n", connection_port);\r
\r
- memset(write_buffer, RW_BUFFER_PATERN, MAX_RW_BUFFER);\r
- while (1) {\r
- connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);\r
+ memset(write_buffer, RW_BUFFER_PATERN, MAX_RW_BUFFER);\r
+ while (1) {\r
+ connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);\r
\r
- n = recv(connfd, op_code, sizeof(op_code), 0);\r
+ n = recv(connfd, op_code, sizeof(op_code), 0);\r
\r
- if (n < 0) {\r
- printf("recv() error: %s fd = %d\n", strerror(errno), connfd);\r
- break;\r
- }\r
+ if (n < 0) {\r
+ printf("recv() error: %s fd = %d\n", strerror(errno),\r
+ connfd);\r
+ break;\r
+ }\r
\r
- op_code[n] = 0;\r
+ op_code[n] = 0;\r
\r
- int r = exec_op_code(op_code);\r
+ int r = exec_op_code(op_code);\r
\r
- n = send(connfd, (void *)&r, sizeof(r), 0);\r
- if (n < 0) {\r
- printf("send() error: %s fd = %d\n", strerror(errno), connfd);\r
- break;\r
- }\r
+ n = send(connfd, (void *)&r, sizeof(r), 0);\r
+ if (n < 0) {\r
+ printf("send() error: %s fd = %d\n", strerror(errno),\r
+ connfd);\r
+ break;\r
+ }\r
\r
- close(connfd);\r
- }\r
+ close(connfd);\r
+ }\r
\r
- winsock_fini();\r
- return 0;\r
+ winsock_fini();\r
+ return 0;\r
}\r
\r
int _device_register(char *p)\r
{\r
- int dev;\r
- int cache_mode;\r
- char dev_name[32];\r
+ int dev;\r
+ int cache_mode;\r
+ char dev_name[32];\r
\r
- if (sscanf(p, "%d %d %s", &dev, &cache_mode, dev_name) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%d %d %s", &dev, &cache_mode, dev_name) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
#ifdef WIN32\r
- if (winpart) {\r
- ext4_io_raw_filename(ext4_fname);\r
- bd = ext4_io_raw_dev_get();\r
+ if (winpart) {\r
+ ext4_io_raw_filename(ext4_fname);\r
+ bd = ext4_io_raw_dev_get();\r
\r
- } else\r
+ } else\r
#endif\r
- {\r
- ext4_filedev_filename(ext4_fname);\r
- bd = ext4_filedev_get();\r
- }\r
- return ext4_device_register(bd, 0, dev_name);\r
+ {\r
+ ext4_filedev_filename(ext4_fname);\r
+ bd = ext4_filedev_get();\r
+ }\r
+ return ext4_device_register(bd, 0, dev_name);\r
}\r
\r
int _mount(char *p)\r
{\r
- char dev_name[32];\r
- char mount_point[32];\r
- int rc;\r
-\r
- if (sscanf(p, "%s %s", dev_name, mount_point) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- rc = ext4_mount(dev_name, mount_point);\r
- if (cache_wb)\r
- ext4_cache_write_back(mount_point, 1);\r
- return rc;\r
+ char dev_name[32];\r
+ char mount_point[32];\r
+ int rc;\r
+\r
+ if (sscanf(p, "%s %s", dev_name, mount_point) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ rc = ext4_mount(dev_name, mount_point);\r
+ if (cache_wb)\r
+ ext4_cache_write_back(mount_point, 1);\r
+ return rc;\r
}\r
\r
int _umount(char *p)\r
{\r
- char mount_point[32];\r
+ char mount_point[32];\r
\r
- if (sscanf(p, "%s", mount_point) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s", mount_point) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- if (cache_wb)\r
- ext4_cache_write_back(mount_point, 0);\r
+ if (cache_wb)\r
+ ext4_cache_write_back(mount_point, 0);\r
\r
- return ext4_umount(mount_point);\r
+ return ext4_umount(mount_point);\r
}\r
\r
int _mount_point_stats(char *p)\r
{\r
- char mount_point[32];\r
- int d;\r
- int rc;\r
- struct ext4_mount_stats stats;\r
+ char mount_point[32];\r
+ int d;\r
+ int rc;\r
+ struct ext4_mount_stats stats;\r
\r
- if (sscanf(p, "%s %d", mount_point, &d) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s %d", mount_point, &d) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- rc = ext4_mount_point_stats(mount_point, &stats);\r
+ rc = ext4_mount_point_stats(mount_point, &stats);\r
\r
- if (rc != EOK)\r
- return rc;\r
+ if (rc != EOK)\r
+ return rc;\r
\r
- if (verbose) {\r
- printf("\tinodes_count = %d\n", stats.inodes_count);\r
- printf("\tfree_inodes_count = %d\n", stats.free_inodes_count);\r
- printf("\tblocks_count = %llu\n", stats.blocks_count);\r
- printf("\tfree_blocks_count = %llu\n", stats.free_blocks_count);\r
+ if (verbose) {\r
+ printf("\tinodes_count = %d\n", stats.inodes_count);\r
+ printf("\tfree_inodes_count = %d\n", stats.free_inodes_count);\r
+ printf("\tblocks_count = %llu\n", stats.blocks_count);\r
+ printf("\tfree_blocks_count = %llu\n", stats.free_blocks_count);\r
\r
- printf("\tblock_size = %d\n", stats.block_size);\r
- printf("\tblock_group_count = %d\n", stats.block_group_count);\r
- printf("\tblocks_per_group = %d\n", stats.blocks_per_group);\r
- printf("\tinodes_per_group = %d\n", stats.inodes_per_group);\r
+ printf("\tblock_size = %d\n", stats.block_size);\r
+ printf("\tblock_group_count = %d\n", stats.block_group_count);\r
+ printf("\tblocks_per_group = %d\n", stats.blocks_per_group);\r
+ printf("\tinodes_per_group = %d\n", stats.inodes_per_group);\r
\r
- printf("\tvolume_name = %s\n", stats.volume_name);\r
- }\r
+ printf("\tvolume_name = %s\n", stats.volume_name);\r
+ }\r
\r
- return rc;\r
+ return rc;\r
}\r
\r
int _cache_write_back(char *p)\r
{\r
- char mount_point[32];\r
- int en;\r
+ char mount_point[32];\r
+ int en;\r
\r
- if (sscanf(p, "%s %d", mount_point, &en) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s %d", mount_point, &en) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- return ext4_cache_write_back(mount_point, en);\r
+ return ext4_cache_write_back(mount_point, en);\r
}\r
\r
int _fremove(char *p)\r
{\r
- char path[255];\r
+ char path[255];\r
\r
- if (sscanf(p, "%s", path) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s", path) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- return ext4_fremove(path);\r
+ return ext4_fremove(path);\r
}\r
\r
int _fopen(char *p)\r
{\r
- int fid = MAX_FILES;\r
- char path[256];\r
- char flags[8];\r
- int rc;\r
+ int fid = MAX_FILES;\r
+ char path[256];\r
+ char flags[8];\r
+ int rc;\r
\r
- if (sscanf(p, "%d %s %s", &fid, path, flags) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%d %s %s", &fid, path, flags) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
\r
- rc = ext4_fopen(&file_tab[fid].fd, path, flags);\r
+ rc = ext4_fopen(&file_tab[fid].fd, path, flags);\r
\r
- if (rc == EOK)\r
- strcpy(file_tab[fid].name, path);\r
+ if (rc == EOK)\r
+ strcpy(file_tab[fid].name, path);\r
\r
- return rc;\r
+ return rc;\r
}\r
\r
int _fclose(char *p)\r
{\r
- int fid = MAX_FILES;\r
- int rc;\r
+ int fid = MAX_FILES;\r
+ int rc;\r
\r
- if (sscanf(p, "%d", &fid) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%d", &fid) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
\r
- if (file_tab[fid].name[0] == 0) {\r
- printf("File id empty\n");\r
- return -1;\r
- }\r
+ if (file_tab[fid].name[0] == 0) {\r
+ printf("File id empty\n");\r
+ return -1;\r
+ }\r
\r
- rc = ext4_fclose(&file_tab[fid].fd);\r
+ rc = ext4_fclose(&file_tab[fid].fd);\r
\r
- if (rc == EOK)\r
- file_tab[fid].name[0] = 0;\r
+ if (rc == EOK)\r
+ file_tab[fid].name[0] = 0;\r
\r
- return rc;\r
+ return rc;\r
}\r
\r
int _fread(char *p)\r
{\r
- int fid = MAX_FILES;\r
- int len;\r
- int d;\r
- int rc;\r
- int rb;\r
-\r
- if (sscanf(p, "%d %d %d %d", &fid, &d, &len, &d) != 4) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
-\r
- if (file_tab[fid].name[0] == 0) {\r
- printf("File id empty\n");\r
- return -1;\r
- }\r
-\r
- while (len) {\r
- d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
-\r
- memset(read_buffer, 0, MAX_RW_BUFFER);\r
- rc = ext4_fread(&file_tab[fid].fd, read_buffer, d, &rb);\r
-\r
- if (rc != EOK)\r
- break;\r
-\r
- if (rb != d) {\r
- printf("Read count error\n");\r
- return -1;\r
- }\r
-\r
- if (memcmp(read_buffer, write_buffer, d)) {\r
- printf("Read compare error\n");\r
- return -1;\r
- }\r
-\r
- len -= d;\r
- }\r
-\r
- return rc;\r
+ int fid = MAX_FILES;\r
+ int len;\r
+ int d;\r
+ int rc;\r
+ int rb;\r
+\r
+ if (sscanf(p, "%d %d %d %d", &fid, &d, &len, &d) != 4) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
+\r
+ if (file_tab[fid].name[0] == 0) {\r
+ printf("File id empty\n");\r
+ return -1;\r
+ }\r
+\r
+ while (len) {\r
+ d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
+\r
+ memset(read_buffer, 0, MAX_RW_BUFFER);\r
+ rc = ext4_fread(&file_tab[fid].fd, read_buffer, d, &rb);\r
+\r
+ if (rc != EOK)\r
+ break;\r
+\r
+ if (rb != d) {\r
+ printf("Read count error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (memcmp(read_buffer, write_buffer, d)) {\r
+ printf("Read compare error\n");\r
+ return -1;\r
+ }\r
+\r
+ len -= d;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _fwrite(char *p)\r
{\r
- int fid = MAX_FILES;\r
- int len;\r
- int d;\r
- int rc;\r
- int wb;\r
-\r
- if (sscanf(p, "%d %d %d %d", &fid, &d, &len, &d) != 4) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
-\r
- if (file_tab[fid].name[0] == 0) {\r
- printf("File id empty\n");\r
- return -1;\r
- }\r
-\r
- while (len) {\r
- d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
- rc = ext4_fwrite(&file_tab[fid].fd, write_buffer, d, &wb);\r
-\r
- if (rc != EOK)\r
- break;\r
-\r
- if (wb != d) {\r
- printf("Write count error\n");\r
- return -1;\r
- }\r
-\r
- len -= d;\r
- }\r
-\r
- return rc;\r
+ int fid = MAX_FILES;\r
+ int len;\r
+ int d;\r
+ int rc;\r
+ int wb;\r
+\r
+ if (sscanf(p, "%d %d %d %d", &fid, &d, &len, &d) != 4) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
+\r
+ if (file_tab[fid].name[0] == 0) {\r
+ printf("File id empty\n");\r
+ return -1;\r
+ }\r
+\r
+ while (len) {\r
+ d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
+ rc = ext4_fwrite(&file_tab[fid].fd, write_buffer, d, &wb);\r
+\r
+ if (rc != EOK)\r
+ break;\r
+\r
+ if (wb != d) {\r
+ printf("Write count error\n");\r
+ return -1;\r
+ }\r
+\r
+ len -= d;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _fseek(char *p)\r
{\r
- int fid = MAX_FILES;\r
- int off;\r
- int origin;\r
-\r
- if (sscanf(p, "%d %d %d", &fid, &off, &origin) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
-\r
- if (file_tab[fid].name[0] == 0) {\r
- printf("File id empty\n");\r
- return -1;\r
- }\r
-\r
- return ext4_fseek(&file_tab[fid].fd, off, origin);\r
+ int fid = MAX_FILES;\r
+ int off;\r
+ int origin;\r
+\r
+ if (sscanf(p, "%d %d %d", &fid, &off, &origin) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
+\r
+ if (file_tab[fid].name[0] == 0) {\r
+ printf("File id empty\n");\r
+ return -1;\r
+ }\r
+\r
+ return ext4_fseek(&file_tab[fid].fd, off, origin);\r
}\r
\r
int _ftell(char *p)\r
{\r
- int fid = MAX_FILES;\r
- uint32_t exp_pos;\r
-\r
- if (sscanf(p, "%d %u", &fid, &exp_pos) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
-\r
- if (file_tab[fid].name[0] == 0) {\r
- printf("File id empty\n");\r
- return -1;\r
- }\r
-\r
- if (exp_pos != ext4_ftell(&file_tab[fid].fd)) {\r
- printf("Expected filepos error\n");\r
- return -1;\r
- }\r
-\r
- return EOK;\r
+ int fid = MAX_FILES;\r
+ uint32_t exp_pos;\r
+\r
+ if (sscanf(p, "%d %u", &fid, &exp_pos) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
+\r
+ if (file_tab[fid].name[0] == 0) {\r
+ printf("File id empty\n");\r
+ return -1;\r
+ }\r
+\r
+ if (exp_pos != ext4_ftell(&file_tab[fid].fd)) {\r
+ printf("Expected filepos error\n");\r
+ return -1;\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
int _fsize(char *p)\r
{\r
- int fid = MAX_FILES;\r
- uint32_t exp_size;\r
-\r
- if (sscanf(p, "%d %u", &fid, &exp_size) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- if (!(fid < MAX_FILES)) {\r
- printf("File id too big\n");\r
- return -1;\r
- }\r
-\r
- if (file_tab[fid].name[0] == 0) {\r
- printf("File id empty\n");\r
- return -1;\r
- }\r
-\r
- if (exp_size != ext4_fsize(&file_tab[fid].fd)) {\r
- printf("Expected filesize error\n");\r
- return -1;\r
- }\r
-\r
- return EOK;\r
+ int fid = MAX_FILES;\r
+ uint32_t exp_size;\r
+\r
+ if (sscanf(p, "%d %u", &fid, &exp_size) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (!(fid < MAX_FILES)) {\r
+ printf("File id too big\n");\r
+ return -1;\r
+ }\r
+\r
+ if (file_tab[fid].name[0] == 0) {\r
+ printf("File id empty\n");\r
+ return -1;\r
+ }\r
+\r
+ if (exp_size != ext4_fsize(&file_tab[fid].fd)) {\r
+ printf("Expected filesize error\n");\r
+ return -1;\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
int _dir_rm(char *p)\r
{\r
- char path[255];\r
+ char path[255];\r
\r
- if (sscanf(p, "%s", path) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s", path) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- return ext4_dir_rm(path);\r
+ return ext4_dir_rm(path);\r
}\r
\r
int _dir_mk(char *p)\r
{\r
- char path[255];\r
+ char path[255];\r
\r
- if (sscanf(p, "%s", path) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s", path) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- return ext4_dir_mk(path);\r
+ return ext4_dir_mk(path);\r
}\r
\r
int _dir_open(char *p)\r
{\r
- int did = MAX_DIRS;\r
- char path[255];\r
- int rc;\r
+ int did = MAX_DIRS;\r
+ char path[255];\r
+ int rc;\r
\r
- if (sscanf(p, "%d %s", &did, path) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%d %s", &did, path) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- if (!(did < MAX_DIRS)) {\r
- printf("Dir id too big\n");\r
- return -1;\r
- }\r
+ if (!(did < MAX_DIRS)) {\r
+ printf("Dir id too big\n");\r
+ return -1;\r
+ }\r
\r
- rc = ext4_dir_open(&dir_tab[did].fd, path);\r
+ rc = ext4_dir_open(&dir_tab[did].fd, path);\r
\r
- if (rc == EOK)\r
- strcpy(dir_tab[did].name, path);\r
+ if (rc == EOK)\r
+ strcpy(dir_tab[did].name, path);\r
\r
- return rc;\r
+ return rc;\r
}\r
\r
int _dir_close(char *p)\r
{\r
- int did = MAX_DIRS;\r
- int rc;\r
+ int did = MAX_DIRS;\r
+ int rc;\r
\r
- if (sscanf(p, "%d", &did) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%d", &did) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- if (!(did < MAX_DIRS)) {\r
- printf("Dir id too big\n");\r
- return -1;\r
- }\r
+ if (!(did < MAX_DIRS)) {\r
+ printf("Dir id too big\n");\r
+ return -1;\r
+ }\r
\r
- if (dir_tab[did].name[0] == 0) {\r
- printf("Dir id empty\n");\r
- return -1;\r
- }\r
+ if (dir_tab[did].name[0] == 0) {\r
+ printf("Dir id empty\n");\r
+ return -1;\r
+ }\r
\r
- rc = ext4_dir_close(&dir_tab[did].fd);\r
+ rc = ext4_dir_close(&dir_tab[did].fd);\r
\r
- if (rc == EOK)\r
- dir_tab[did].name[0] = 0;\r
+ if (rc == EOK)\r
+ dir_tab[did].name[0] = 0;\r
\r
- return rc;\r
+ return rc;\r
}\r
\r
int _dir_entry_get(char *p)\r
{\r
- int did = MAX_DIRS;\r
- int exp;\r
- char name[256];\r
-\r
- if (sscanf(p, "%d %d", &did, &exp) != 2) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- if (!(did < MAX_DIRS)) {\r
- printf("Dir id too big\n");\r
- return -1;\r
- }\r
-\r
- if (dir_tab[did].name[0] == 0) {\r
- printf("Dir id empty\n");\r
- return -1;\r
- }\r
-\r
- int idx = 0;\r
- const ext4_direntry *d;\r
-\r
- while ((d = ext4_dir_entry_next(&dir_tab[did].fd)) != NULL) {\r
-\r
- idx++;\r
- memcpy(name, d->name, d->name_length);\r
- name[d->name_length] = 0;\r
- if (verbose) {\r
- printf("\t%s %s\n", entry_to_str(d->inode_type), name);\r
- }\r
- }\r
-\r
- if (idx < 2) {\r
- printf("Minumum dir entry error\n");\r
- return -1;\r
- }\r
-\r
- if ((idx - 2) != exp) {\r
- printf("Expected dir entry error\n");\r
- return -1;\r
- }\r
-\r
- return EOK;\r
+ int did = MAX_DIRS;\r
+ int exp;\r
+ char name[256];\r
+\r
+ if (sscanf(p, "%d %d", &did, &exp) != 2) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (!(did < MAX_DIRS)) {\r
+ printf("Dir id too big\n");\r
+ return -1;\r
+ }\r
+\r
+ if (dir_tab[did].name[0] == 0) {\r
+ printf("Dir id empty\n");\r
+ return -1;\r
+ }\r
+\r
+ int idx = 0;\r
+ const ext4_direntry *d;\r
+\r
+ while ((d = ext4_dir_entry_next(&dir_tab[did].fd)) != NULL) {\r
+\r
+ idx++;\r
+ memcpy(name, d->name, d->name_length);\r
+ name[d->name_length] = 0;\r
+ if (verbose) {\r
+ printf("\t%s %s\n", entry_to_str(d->inode_type), name);\r
+ }\r
+ }\r
+\r
+ if (idx < 2) {\r
+ printf("Minumum dir entry error\n");\r
+ return -1;\r
+ }\r
+\r
+ if ((idx - 2) != exp) {\r
+ printf("Expected dir entry error\n");\r
+ return -1;\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
int _multi_fcreate(char *p)\r
{\r
- char path[256];\r
- char path1[256];\r
- char prefix[32];\r
- int cnt;\r
- int rc;\r
- int i;\r
- ext4_file fd;\r
-\r
- if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- for (i = 0; i < cnt; ++i) {\r
- sprintf(path1, "%s%s%d", path, prefix, i);\r
- rc = ext4_fopen(&fd, path1, "wb+");\r
-\r
- if (rc != EOK)\r
- break;\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ char path1[256];\r
+ char prefix[32];\r
+ int cnt;\r
+ int rc;\r
+ int i;\r
+ ext4_file fd;\r
+\r
+ if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ for (i = 0; i < cnt; ++i) {\r
+ sprintf(path1, "%s%s%d", path, prefix, i);\r
+ rc = ext4_fopen(&fd, path1, "wb+");\r
+\r
+ if (rc != EOK)\r
+ break;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _multi_fwrite(char *p)\r
{\r
- char path[256];\r
- char path1[256];\r
- char prefix[32];\r
- int cnt;\r
- int len, ll;\r
- int rc;\r
- int i, d, wb;\r
- ext4_file fd;\r
-\r
- if (sscanf(p, "%s %s %d %d", path, prefix, &cnt, &ll) != 4) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- for (i = 0; i < cnt; ++i) {\r
- sprintf(path1, "%s%s%d", path, prefix, i);\r
- rc = ext4_fopen(&fd, path1, "rb+");\r
-\r
- if (rc != EOK)\r
- break;\r
-\r
- len = ll;\r
- while (len) {\r
- d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
- rc = ext4_fwrite(&fd, write_buffer, d, &wb);\r
-\r
- if (rc != EOK)\r
- break;\r
-\r
- if (wb != d) {\r
- printf("Write count error\n");\r
- return -1;\r
- }\r
-\r
- len -= d;\r
- }\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ char path1[256];\r
+ char prefix[32];\r
+ int cnt;\r
+ int len, ll;\r
+ int rc;\r
+ int i, d, wb;\r
+ ext4_file fd;\r
+\r
+ if (sscanf(p, "%s %s %d %d", path, prefix, &cnt, &ll) != 4) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ for (i = 0; i < cnt; ++i) {\r
+ sprintf(path1, "%s%s%d", path, prefix, i);\r
+ rc = ext4_fopen(&fd, path1, "rb+");\r
+\r
+ if (rc != EOK)\r
+ break;\r
+\r
+ len = ll;\r
+ while (len) {\r
+ d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
+ rc = ext4_fwrite(&fd, write_buffer, d, &wb);\r
+\r
+ if (rc != EOK)\r
+ break;\r
+\r
+ if (wb != d) {\r
+ printf("Write count error\n");\r
+ return -1;\r
+ }\r
+\r
+ len -= d;\r
+ }\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _multi_fread(char *p)\r
{\r
- char path[256];\r
- char path1[256];\r
- char prefix[32];\r
- int cnt;\r
- int len, ll;\r
- int rc;\r
- int i, d, rb;\r
- ext4_file fd;\r
-\r
- if (sscanf(p, "%s %s %d %d", path, prefix, &cnt, &ll) != 4) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- for (i = 0; i < cnt; ++i) {\r
- sprintf(path1, "%s%s%d", path, prefix, i);\r
- rc = ext4_fopen(&fd, path1, "rb+");\r
-\r
- if (rc != EOK)\r
- break;\r
-\r
- len = ll;\r
- while (len) {\r
- d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
-\r
- memset(read_buffer, 0, MAX_RW_BUFFER);\r
- rc = ext4_fread(&fd, read_buffer, d, &rb);\r
-\r
- if (rc != EOK)\r
- break;\r
-\r
- if (rb != d) {\r
- printf("Read count error\n");\r
- return -1;\r
- }\r
-\r
- if (memcmp(read_buffer, write_buffer, d)) {\r
- printf("Read compare error\n");\r
- return -1;\r
- }\r
-\r
- len -= d;\r
- }\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ char path1[256];\r
+ char prefix[32];\r
+ int cnt;\r
+ int len, ll;\r
+ int rc;\r
+ int i, d, rb;\r
+ ext4_file fd;\r
+\r
+ if (sscanf(p, "%s %s %d %d", path, prefix, &cnt, &ll) != 4) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ for (i = 0; i < cnt; ++i) {\r
+ sprintf(path1, "%s%s%d", path, prefix, i);\r
+ rc = ext4_fopen(&fd, path1, "rb+");\r
+\r
+ if (rc != EOK)\r
+ break;\r
+\r
+ len = ll;\r
+ while (len) {\r
+ d = len > MAX_RW_BUFFER ? MAX_RW_BUFFER : len;\r
+\r
+ memset(read_buffer, 0, MAX_RW_BUFFER);\r
+ rc = ext4_fread(&fd, read_buffer, d, &rb);\r
+\r
+ if (rc != EOK)\r
+ break;\r
+\r
+ if (rb != d) {\r
+ printf("Read count error\n");\r
+ return -1;\r
+ }\r
+\r
+ if (memcmp(read_buffer, write_buffer, d)) {\r
+ printf("Read compare error\n");\r
+ return -1;\r
+ }\r
+\r
+ len -= d;\r
+ }\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _multi_fremove(char *p)\r
{\r
- char path[256];\r
- char path1[256];\r
- char prefix[32];\r
- int cnt, i, rc;\r
-\r
- if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- for (i = 0; i < cnt; ++i) {\r
- sprintf(path1, "%s%s%d", path, prefix, i);\r
- rc = ext4_fremove(path1);\r
- if (rc != EOK)\r
- break;\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ char path1[256];\r
+ char prefix[32];\r
+ int cnt, i, rc;\r
+\r
+ if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ for (i = 0; i < cnt; ++i) {\r
+ sprintf(path1, "%s%s%d", path, prefix, i);\r
+ rc = ext4_fremove(path1);\r
+ if (rc != EOK)\r
+ break;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _multi_dcreate(char *p)\r
{\r
- char path[256];\r
- char path1[256];\r
- char prefix[32];\r
- int cnt, i, rc;\r
-\r
- if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- for (i = 0; i < cnt; ++i) {\r
- sprintf(path1, "%s%s%d", path, prefix, i);\r
- rc = ext4_dir_mk(path1);\r
- if (rc != EOK)\r
- break;\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ char path1[256];\r
+ char prefix[32];\r
+ int cnt, i, rc;\r
+\r
+ if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ for (i = 0; i < cnt; ++i) {\r
+ sprintf(path1, "%s%s%d", path, prefix, i);\r
+ rc = ext4_dir_mk(path1);\r
+ if (rc != EOK)\r
+ break;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
int _multi_dremove(char *p)\r
{\r
- char path[256];\r
- char path1[256];\r
- char prefix[32];\r
- int cnt, i, rc;\r
-\r
- if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- for (i = 0; i < cnt; ++i) {\r
- sprintf(path1, "%s%s%d", path, prefix, i);\r
- rc = ext4_dir_rm(path1);\r
- if (rc != EOK)\r
- break;\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ char path1[256];\r
+ char prefix[32];\r
+ int cnt, i, rc;\r
+\r
+ if (sscanf(p, "%s %s %d", path, prefix, &cnt) != 3) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ for (i = 0; i < cnt; ++i) {\r
+ sprintf(path1, "%s%s%d", path, prefix, i);\r
+ rc = ext4_dir_rm(path1);\r
+ if (rc != EOK)\r
+ break;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
struct ext4_mount_stats saved_stats;\r
\r
int _stats_save(char *p)\r
{\r
- char path[256];\r
+ char path[256];\r
\r
- if (sscanf(p, "%s", path) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
+ if (sscanf(p, "%s", path) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
\r
- return ext4_mount_point_stats(path, &saved_stats);\r
+ return ext4_mount_point_stats(path, &saved_stats);\r
}\r
\r
int _stats_check(char *p)\r
{\r
- char path[256];\r
- int rc;\r
-\r
- struct ext4_mount_stats actual_stats;\r
-\r
- if (sscanf(p, "%s", path) != 1) {\r
- printf("Param list error\n");\r
- return -1;\r
- }\r
-\r
- rc = ext4_mount_point_stats(path, &actual_stats);\r
-\r
- if (rc != EOK)\r
- return rc;\r
-\r
- if (memcmp(&saved_stats, &actual_stats, sizeof(struct ext4_mount_stats))) {\r
- if (verbose) {\r
- printf("\tMount point stats error:\n");\r
- printf("\tsaved_stats:\n");\r
- printf("\tinodes_count = %d\n", saved_stats.inodes_count);\r
- printf("\tfree_inodes_count = %d\n", saved_stats.free_inodes_count);\r
- printf("\tblocks_count = %llu\n", saved_stats.blocks_count);\r
- printf("\tfree_blocks_count = %llu\n",\r
- saved_stats.free_blocks_count);\r
- printf("\tblock_size = %d\n", saved_stats.block_size);\r
- printf("\tblock_group_count = %d\n", saved_stats.block_group_count);\r
- printf("\tblocks_per_group = %d\n", saved_stats.blocks_per_group);\r
- printf("\tinodes_per_group = %d\n", saved_stats.inodes_per_group);\r
- printf("\tvolume_name = %s\n", saved_stats.volume_name);\r
- printf("\tactual_stats:\n");\r
- printf("\tinodes_count = %d\n", actual_stats.inodes_count);\r
- printf("\tfree_inodes_count = %d\n",\r
- actual_stats.free_inodes_count);\r
- printf("\tblocks_count = %llu\n", actual_stats.blocks_count);\r
- printf("\tfree_blocks_count = %llu\n",\r
- actual_stats.free_blocks_count);\r
- printf("\tblock_size = %d\n", actual_stats.block_size);\r
- printf("\tblock_group_count = %d\n",\r
- actual_stats.block_group_count);\r
- printf("\tblocks_per_group = %d\n", actual_stats.blocks_per_group);\r
- printf("\tinodes_per_group = %d\n", actual_stats.inodes_per_group);\r
- printf("\tvolume_name = %s\n", actual_stats.volume_name);\r
- }\r
- return -1;\r
- }\r
-\r
- return rc;\r
+ char path[256];\r
+ int rc;\r
+\r
+ struct ext4_mount_stats actual_stats;\r
+\r
+ if (sscanf(p, "%s", path) != 1) {\r
+ printf("Param list error\n");\r
+ return -1;\r
+ }\r
+\r
+ rc = ext4_mount_point_stats(path, &actual_stats);\r
+\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ if (memcmp(&saved_stats, &actual_stats,\r
+ sizeof(struct ext4_mount_stats))) {\r
+ if (verbose) {\r
+ printf("\tMount point stats error:\n");\r
+ printf("\tsaved_stats:\n");\r
+ printf("\tinodes_count = %d\n",\r
+ saved_stats.inodes_count);\r
+ printf("\tfree_inodes_count = %d\n",\r
+ saved_stats.free_inodes_count);\r
+ printf("\tblocks_count = %llu\n",\r
+ saved_stats.blocks_count);\r
+ printf("\tfree_blocks_count = %llu\n",\r
+ saved_stats.free_blocks_count);\r
+ printf("\tblock_size = %d\n", saved_stats.block_size);\r
+ printf("\tblock_group_count = %d\n",\r
+ saved_stats.block_group_count);\r
+ printf("\tblocks_per_group = %d\n",\r
+ saved_stats.blocks_per_group);\r
+ printf("\tinodes_per_group = %d\n",\r
+ saved_stats.inodes_per_group);\r
+ printf("\tvolume_name = %s\n", saved_stats.volume_name);\r
+ printf("\tactual_stats:\n");\r
+ printf("\tinodes_count = %d\n",\r
+ actual_stats.inodes_count);\r
+ printf("\tfree_inodes_count = %d\n",\r
+ actual_stats.free_inodes_count);\r
+ printf("\tblocks_count = %llu\n",\r
+ actual_stats.blocks_count);\r
+ printf("\tfree_blocks_count = %llu\n",\r
+ actual_stats.free_blocks_count);\r
+ printf("\tblock_size = %d\n", actual_stats.block_size);\r
+ printf("\tblock_group_count = %d\n",\r
+ actual_stats.block_group_count);\r
+ printf("\tblocks_per_group = %d\n",\r
+ actual_stats.blocks_per_group);\r
+ printf("\tinodes_per_group = %d\n",\r
+ actual_stats.inodes_per_group);\r
+ printf("\tvolume_name = %s\n",\r
+ actual_stats.volume_name);\r
+ }\r
+ return -1;\r
+ }\r
+\r
+ return rc;\r
}\r
\r
static char *entry_to_str(uint8_t type)\r
{\r
- switch (type) {\r
- case EXT4_DIRENTRY_UNKNOWN:\r
- return "[UNK] ";\r
- case EXT4_DIRENTRY_REG_FILE:\r
- return "[FIL] ";\r
- case EXT4_DIRENTRY_DIR:\r
- return "[DIR] ";\r
- case EXT4_DIRENTRY_CHRDEV:\r
- return "[CHA] ";\r
- case EXT4_DIRENTRY_BLKDEV:\r
- return "[BLK] ";\r
- case EXT4_DIRENTRY_FIFO:\r
- return "[FIF] ";\r
- case EXT4_DIRENTRY_SOCK:\r
- return "[SOC] ";\r
- case EXT4_DIRENTRY_SYMLINK:\r
- return "[SYM] ";\r
- default:\r
- break;\r
- }\r
- return "[???]";\r
+ switch (type) {\r
+ case EXT4_DIRENTRY_UNKNOWN:\r
+ return "[UNK] ";\r
+ case EXT4_DIRENTRY_REG_FILE:\r
+ return "[FIL] ";\r
+ case EXT4_DIRENTRY_DIR:\r
+ return "[DIR] ";\r
+ case EXT4_DIRENTRY_CHRDEV:\r
+ return "[CHA] ";\r
+ case EXT4_DIRENTRY_BLKDEV:\r
+ return "[BLK] ";\r
+ case EXT4_DIRENTRY_FIFO:\r
+ return "[FIF] ";\r
+ case EXT4_DIRENTRY_SOCK:\r
+ return "[SOC] ";\r
+ case EXT4_DIRENTRY_SYMLINK:\r
+ return "[SYM] ";\r
+ default:\r
+ break;\r
+ }\r
+ return "[???]";\r
}\r
\r
static int winsock_init(void)\r
{\r
#if WIN32\r
- int rc;\r
- static WSADATA wsaData;\r
- rc = WSAStartup(MAKEWORD(2, 2), &wsaData);\r
- if (rc != 0) {\r
- return -1;\r
- }\r
+ int rc;\r
+ static WSADATA wsaData;\r
+ rc = WSAStartup(MAKEWORD(2, 2), &wsaData);\r
+ if (rc != 0) {\r
+ return -1;\r
+ }\r
#endif\r
- return 0;\r
+ return 0;\r
}\r
\r
static void winsock_fini(void)\r
{\r
#if WIN32\r
- WSACleanup();\r
+ WSACleanup();\r
#endif\r
}\r
\r
/**@brief Mount point OS dependent lock*/\r
#define EXT4_MP_LOCK(_m) \\r
- do { \\r
- if ((_m)->os_locks) \\r
- (_m)->os_locks->lock(); \\r
- } while (0)\r
+ do { \\r
+ if ((_m)->os_locks) \\r
+ (_m)->os_locks->lock(); \\r
+ } while (0)\r
\r
/**@brief Mount point OS dependent unlock*/\r
#define EXT4_MP_UNLOCK(_m) \\r
- do { \\r
- if ((_m)->os_locks) \\r
- (_m)->os_locks->unlock(); \\r
- } while (0)\r
+ do { \\r
+ if ((_m)->os_locks) \\r
+ (_m)->os_locks->unlock(); \\r
+ } while (0)\r
\r
/**@brief Mount point descriptor.*/\r
struct ext4_mountpoint {\r
\r
- /**@brief Mount done flag.*/\r
- bool mounted;\r
+ /**@brief Mount done flag.*/\r
+ bool mounted;\r
\r
- /**@brief Mount point name (@ref ext4_mount)*/\r
- char name[32];\r
+ /**@brief Mount point name (@ref ext4_mount)*/\r
+ char name[32];\r
\r
- /**@brief OS dependent lock/unlock functions.*/\r
- const struct ext4_lock *os_locks;\r
+ /**@brief OS dependent lock/unlock functions.*/\r
+ const struct ext4_lock *os_locks;\r
\r
- /**@brief Ext4 filesystem internals.*/\r
- struct ext4_fs fs;\r
+ /**@brief Ext4 filesystem internals.*/\r
+ struct ext4_fs fs;\r
\r
- /**@brief Dynamic allocation cache flag.*/\r
- bool cache_dynamic;\r
+ /**@brief Dynamic allocation cache flag.*/\r
+ bool cache_dynamic;\r
};\r
\r
/**@brief Block devices descriptor.*/\r
struct _ext4_devices {\r
\r
- /**@brief Block device name (@ref ext4_device_register)*/\r
- char name[32];\r
+ /**@brief Block device name (@ref ext4_device_register)*/\r
+ char name[32];\r
\r
- /**@brief Block device handle.*/\r
- struct ext4_blockdev *bd;\r
+ /**@brief Block device handle.*/\r
+ struct ext4_blockdev *bd;\r
\r
- /**@brief Block cache handle.*/\r
- struct ext4_bcache *bc;\r
+ /**@brief Block cache handle.*/\r
+ struct ext4_bcache *bc;\r
};\r
\r
/**@brief Block devices.*/\r
struct ext4_mountpoint _mp[CONFIG_EXT4_MOUNTPOINTS_COUNT];\r
\r
int ext4_device_register(struct ext4_blockdev *bd, struct ext4_bcache *bc,\r
- const char *dev_name)\r
+ const char *dev_name)\r
{\r
- uint32_t i;\r
- ext4_assert(bd && dev_name);\r
-\r
- for (i = 0; i < CONFIG_EXT4_BLOCKDEVS_COUNT; ++i) {\r
- if (!_bdevices[i].bd) {\r
- strcpy(_bdevices[i].name, dev_name);\r
- _bdevices[i].bd = bd;\r
- _bdevices[i].bc = bc;\r
- return EOK;\r
- }\r
-\r
- if (!strcmp(_bdevices[i].name, dev_name))\r
- return EOK;\r
- }\r
- return ENOSPC;\r
+ uint32_t i;\r
+ ext4_assert(bd && dev_name);\r
+\r
+ for (i = 0; i < CONFIG_EXT4_BLOCKDEVS_COUNT; ++i) {\r
+ if (!_bdevices[i].bd) {\r
+ strcpy(_bdevices[i].name, dev_name);\r
+ _bdevices[i].bd = bd;\r
+ _bdevices[i].bc = bc;\r
+ return EOK;\r
+ }\r
+\r
+ if (!strcmp(_bdevices[i].name, dev_name))\r
+ return EOK;\r
+ }\r
+ return ENOSPC;\r
}\r
\r
/****************************************************************************/\r
\r
static bool ext4_is_dots(const uint8_t *name, size_t name_size)\r
{\r
- if ((name_size == 1) && (name[0] == '.'))\r
- return true;\r
+ if ((name_size == 1) && (name[0] == '.'))\r
+ return true;\r
\r
- if ((name_size == 2) && (name[0] == '.') && (name[1] == '.'))\r
- return true;\r
+ if ((name_size == 2) && (name[0] == '.') && (name[1] == '.'))\r
+ return true;\r
\r
- return false;\r
+ return false;\r
}\r
\r
static int ext4_has_children(bool *has_children, struct ext4_inode_ref *enode)\r
{\r
- struct ext4_fs *fs = enode->fs;\r
-\r
- /* Check if node is directory */\r
- if (!ext4_inode_is_type(&fs->sb, enode->inode, EXT4_INODE_MODE_DIRECTORY)) {\r
- *has_children = false;\r
- return EOK;\r
- }\r
-\r
- struct ext4_directory_iterator it;\r
- int rc = ext4_dir_iterator_init(&it, enode, 0);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Find a non-empty directory entry */\r
- bool found = false;\r
- while (it.current != NULL) {\r
- if (it.current->inode != 0) {\r
- uint16_t name_size =\r
- ext4_dir_entry_ll_get_name_length(&fs->sb, it.current);\r
- if (!ext4_is_dots(it.current->name, name_size)) {\r
- found = true;\r
- break;\r
- }\r
- }\r
-\r
- rc = ext4_dir_iterator_next(&it);\r
- if (rc != EOK) {\r
- ext4_dir_iterator_fini(&it);\r
- return rc;\r
- }\r
- }\r
-\r
- rc = ext4_dir_iterator_fini(&it);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- *has_children = found;\r
-\r
- return EOK;\r
+ struct ext4_fs *fs = enode->fs;\r
+\r
+ /* Check if node is directory */\r
+ if (!ext4_inode_is_type(&fs->sb, enode->inode,\r
+ EXT4_INODE_MODE_DIRECTORY)) {\r
+ *has_children = false;\r
+ return EOK;\r
+ }\r
+\r
+ struct ext4_directory_iterator it;\r
+ int rc = ext4_dir_iterator_init(&it, enode, 0);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Find a non-empty directory entry */\r
+ bool found = false;\r
+ while (it.current != NULL) {\r
+ if (it.current->inode != 0) {\r
+ uint16_t name_size = ext4_dir_entry_ll_get_name_length(\r
+ &fs->sb, it.current);\r
+ if (!ext4_is_dots(it.current->name, name_size)) {\r
+ found = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ rc = ext4_dir_iterator_next(&it);\r
+ if (rc != EOK) {\r
+ ext4_dir_iterator_fini(&it);\r
+ return rc;\r
+ }\r
+ }\r
+\r
+ rc = ext4_dir_iterator_fini(&it);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ *has_children = found;\r
+\r
+ return EOK;\r
}\r
\r
static int ext4_link(struct ext4_mountpoint *mp, struct ext4_inode_ref *parent,\r
- struct ext4_inode_ref *child, const char *name,\r
- uint32_t name_len)\r
+ struct ext4_inode_ref *child, const char *name,\r
+ uint32_t name_len)\r
{\r
- /* Check maximum name length */\r
- if (name_len > EXT4_DIRECTORY_FILENAME_LEN)\r
- return EINVAL;\r
-\r
- /* Add entry to parent directory */\r
- int rc = ext4_dir_add_entry(parent, name, name_len, child);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Fill new dir -> add '.' and '..' entries.\r
- * Also newly allocated inode should have 0 link count.\r
- */\r
- if (ext4_inode_is_type(&mp->fs.sb, child->inode,\r
- EXT4_INODE_MODE_DIRECTORY)\r
- && ext4_inode_get_links_count(child->inode) == 0) {\r
- rc = ext4_dir_add_entry(child, ".", strlen("."), child);\r
- if (rc != EOK) {\r
- ext4_dir_remove_entry(parent, name, strlen(name));\r
- return rc;\r
- }\r
-\r
- rc = ext4_dir_add_entry(child, "..", strlen(".."), parent);\r
- if (rc != EOK) {\r
- ext4_dir_remove_entry(parent, name, strlen(name));\r
- ext4_dir_remove_entry(child, ".", strlen("."));\r
- return rc;\r
- }\r
-\r
- /*New empty directory. Two links (. and ..) */\r
- ext4_inode_set_links_count(child->inode, 2);\r
+ /* Check maximum name length */\r
+ if (name_len > EXT4_DIRECTORY_FILENAME_LEN)\r
+ return EINVAL;\r
+\r
+ /* Add entry to parent directory */\r
+ int rc = ext4_dir_add_entry(parent, name, name_len, child);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Fill new dir -> add '.' and '..' entries.\r
+ * Also newly allocated inode should have 0 link count.\r
+ */\r
+ if (ext4_inode_is_type(&mp->fs.sb, child->inode,\r
+ EXT4_INODE_MODE_DIRECTORY) &&\r
+ ext4_inode_get_links_count(child->inode) == 0) {\r
+ rc = ext4_dir_add_entry(child, ".", strlen("."), child);\r
+ if (rc != EOK) {\r
+ ext4_dir_remove_entry(parent, name, strlen(name));\r
+ return rc;\r
+ }\r
+\r
+ rc = ext4_dir_add_entry(child, "..", strlen(".."), parent);\r
+ if (rc != EOK) {\r
+ ext4_dir_remove_entry(parent, name, strlen(name));\r
+ ext4_dir_remove_entry(child, ".", strlen("."));\r
+ return rc;\r
+ }\r
+\r
+ /*New empty directory. Two links (. and ..) */\r
+ ext4_inode_set_links_count(child->inode, 2);\r
\r
#if CONFIG_DIR_INDEX_ENABLE\r
- /* Initialize directory index if supported */\r
- if (ext4_sb_has_feature_compatible(&mp->fs.sb,\r
- EXT4_FEATURE_COMPAT_DIR_INDEX)) {\r
- rc = ext4_dir_dx_init(child);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- ext4_inode_set_flag(child->inode, EXT4_INODE_FLAG_INDEX);\r
- child->dirty = true;\r
- }\r
+ /* Initialize directory index if supported */\r
+ if (ext4_sb_has_feature_compatible(\r
+ &mp->fs.sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {\r
+ rc = ext4_dir_dx_init(child);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ ext4_inode_set_flag(child->inode,\r
+ EXT4_INODE_FLAG_INDEX);\r
+ child->dirty = true;\r
+ }\r
#endif\r
\r
- ext4_fs_inode_links_count_inc(parent);\r
- child->dirty = true;\r
- parent->dirty = true;\r
- } else {\r
- if (ext4_inode_is_type(&mp->fs.sb, child->inode,\r
- EXT4_INODE_MODE_DIRECTORY)) {\r
- /* FIXME: SO TRICKY. */\r
- int has_flag_index =\r
- ext4_inode_has_flag(child->inode, EXT4_INODE_FLAG_INDEX);\r
- struct ext4_directory_search_result result;\r
- if (has_flag_index)\r
- ext4_inode_clear_flag(child->inode, EXT4_INODE_FLAG_INDEX);\r
-\r
- rc = ext4_dir_find_entry(&result, child, "..", strlen(".."));\r
- if (has_flag_index)\r
- ext4_inode_set_flag(child->inode, EXT4_INODE_FLAG_INDEX);\r
-\r
- if (rc != EOK)\r
- return EIO;\r
-\r
- ext4_dir_entry_ll_set_inode(result.dentry, parent->index);\r
- result.block.dirty = true;\r
- rc = ext4_dir_destroy_result(child, &result);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- ext4_fs_inode_links_count_inc(parent);\r
- parent->dirty = true;\r
- } else {\r
- ext4_fs_inode_links_count_inc(child);\r
- child->dirty = true;\r
- }\r
- }\r
-\r
- return rc;\r
+ ext4_fs_inode_links_count_inc(parent);\r
+ child->dirty = true;\r
+ parent->dirty = true;\r
+ } else {\r
+ if (ext4_inode_is_type(&mp->fs.sb, child->inode,\r
+ EXT4_INODE_MODE_DIRECTORY)) {\r
+ /* FIXME: SO TRICKY. */\r
+ int has_flag_index = ext4_inode_has_flag(\r
+ child->inode, EXT4_INODE_FLAG_INDEX);\r
+ struct ext4_directory_search_result result;\r
+ if (has_flag_index)\r
+ ext4_inode_clear_flag(child->inode,\r
+ EXT4_INODE_FLAG_INDEX);\r
+\r
+ rc = ext4_dir_find_entry(&result, child, "..",\r
+ strlen(".."));\r
+ if (has_flag_index)\r
+ ext4_inode_set_flag(child->inode,\r
+ EXT4_INODE_FLAG_INDEX);\r
+\r
+ if (rc != EOK)\r
+ return EIO;\r
+\r
+ ext4_dir_entry_ll_set_inode(result.dentry,\r
+ parent->index);\r
+ result.block.dirty = true;\r
+ rc = ext4_dir_destroy_result(child, &result);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ ext4_fs_inode_links_count_inc(parent);\r
+ parent->dirty = true;\r
+ } else {\r
+ ext4_fs_inode_links_count_inc(child);\r
+ child->dirty = true;\r
+ }\r
+ }\r
+\r
+ return rc;\r
}\r
\r
static int ext4_unlink(struct ext4_mountpoint *mp,\r
- struct ext4_inode_ref *parent,\r
- struct ext4_inode_ref *child_inode_ref, const char *name,\r
- uint32_t name_len)\r
+ struct ext4_inode_ref *parent,\r
+ struct ext4_inode_ref *child_inode_ref, const char *name,\r
+ uint32_t name_len)\r
{\r
- bool has_children;\r
- int rc = ext4_has_children(&has_children, child_inode_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Cannot unlink non-empty node */\r
- if (has_children)\r
- return ENOTSUP;\r
-\r
- /* Remove entry from parent directory */\r
- rc = ext4_dir_remove_entry(parent, name, name_len);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- bool is_dir = ext4_inode_is_type(&mp->fs.sb, child_inode_ref->inode,\r
- EXT4_INODE_MODE_DIRECTORY);\r
-\r
- /* If directory - handle links from parent */\r
- if (is_dir) {\r
- // ext4_assert(ext4_inode_get_links_count(child_inode_ref->inode) == 1);\r
- ext4_fs_inode_links_count_dec(parent);\r
- parent->dirty = true;\r
- }\r
-\r
- /*\r
- * TODO: Update timestamps of the parent\r
- * (when we have wall-clock time).\r
- *\r
- * ext4_inode_set_change_inode_time(parent->inode, (uint32_t) now);\r
- * ext4_inode_set_modification_time(parent->inode, (uint32_t) now);\r
- * parent->dirty = true;\r
- */\r
-\r
- /*\r
- * TODO: Update timestamp for inode.\r
- *\r
- * ext4_inode_set_change_inode_time(child_inode_ref->inode,\r
- * (uint32_t) now);\r
- */\r
- if (ext4_inode_get_links_count(child_inode_ref->inode)) {\r
- ext4_fs_inode_links_count_dec(child_inode_ref);\r
- child_inode_ref->dirty = true;\r
- }\r
-\r
- return EOK;\r
+ bool has_children;\r
+ int rc = ext4_has_children(&has_children, child_inode_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Cannot unlink non-empty node */\r
+ if (has_children)\r
+ return ENOTSUP;\r
+\r
+ /* Remove entry from parent directory */\r
+ rc = ext4_dir_remove_entry(parent, name, name_len);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ bool is_dir = ext4_inode_is_type(&mp->fs.sb, child_inode_ref->inode,\r
+ EXT4_INODE_MODE_DIRECTORY);\r
+\r
+ /* If directory - handle links from parent */\r
+ if (is_dir) {\r
+ // ext4_assert(ext4_inode_get_links_count(child_inode_ref->inode)\r
+ // == 1);\r
+ ext4_fs_inode_links_count_dec(parent);\r
+ parent->dirty = true;\r
+ }\r
+\r
+ /*\r
+ * TODO: Update timestamps of the parent\r
+ * (when we have wall-clock time).\r
+ *\r
+ * ext4_inode_set_change_inode_time(parent->inode, (uint32_t) now);\r
+ * ext4_inode_set_modification_time(parent->inode, (uint32_t) now);\r
+ * parent->dirty = true;\r
+ */\r
+\r
+ /*\r
+ * TODO: Update timestamp for inode.\r
+ *\r
+ * ext4_inode_set_change_inode_time(child_inode_ref->inode,\r
+ * (uint32_t) now);\r
+ */\r
+ if (ext4_inode_get_links_count(child_inode_ref->inode)) {\r
+ ext4_fs_inode_links_count_dec(child_inode_ref);\r
+ child_inode_ref->dirty = true;\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
/****************************************************************************/\r
\r
int ext4_mount(const char *dev_name, const char *mount_point)\r
{\r
- ext4_assert(mount_point && dev_name);\r
- int r;\r
- int i;\r
-\r
- uint32_t bsize;\r
- struct ext4_blockdev *bd = 0;\r
- struct ext4_bcache *bc = 0;\r
- struct ext4_mountpoint *mp = 0;\r
-\r
- if (mount_point[strlen(mount_point) - 1] != '/')\r
- return ENOTSUP;\r
-\r
- for (i = 0; i < CONFIG_EXT4_BLOCKDEVS_COUNT; ++i) {\r
- if (_bdevices[i].name) {\r
- if (!strcmp(dev_name, _bdevices[i].name)) {\r
- bd = _bdevices[i].bd;\r
- bc = _bdevices[i].bc;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (!bd)\r
- return ENODEV;\r
-\r
- for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
- if (!_mp[i].mounted) {\r
- strcpy(_mp[i].name, mount_point);\r
- _mp[i].mounted = 1;\r
- mp = &_mp[i];\r
- break;\r
- }\r
-\r
- if (!strcmp(_mp[i].name, mount_point))\r
- return EOK;\r
- }\r
-\r
- if (!mp)\r
- return ENOMEM;\r
-\r
- r = ext4_block_init(bd);\r
- if (r != EOK)\r
- return r;\r
-\r
- r = ext4_fs_init(&mp->fs, bd);\r
- if (r != EOK) {\r
- ext4_block_fini(bd);\r
- return r;\r
- }\r
-\r
- bsize = ext4_sb_get_block_size(&mp->fs.sb);\r
- ext4_block_set_lb_size(bd, bsize);\r
-\r
- mp->cache_dynamic = 0;\r
-\r
- if (!bc) {\r
- /*Automatic block cache alloc.*/\r
- mp->cache_dynamic = 1;\r
- bc = malloc(sizeof(struct ext4_bcache));\r
-\r
- r = ext4_bcache_init_dynamic(bc, CONFIG_BLOCK_DEV_CACHE_SIZE, bsize);\r
- if (r != EOK) {\r
- free(bc);\r
- ext4_block_fini(bd);\r
- return r;\r
- }\r
- }\r
-\r
- if (bsize != bc->itemsize)\r
- return ENOTSUP;\r
-\r
- /*Bind block cache to block device*/\r
- r = ext4_block_bind_bcache(bd, bc);\r
- if (r != EOK) {\r
- ext4_block_fini(bd);\r
- if (mp->cache_dynamic) {\r
- ext4_bcache_fini_dynamic(bc);\r
- free(bc);\r
- }\r
- return r;\r
- }\r
-\r
- return r;\r
+ ext4_assert(mount_point && dev_name);\r
+ int r;\r
+ int i;\r
+\r
+ uint32_t bsize;\r
+ struct ext4_blockdev *bd = 0;\r
+ struct ext4_bcache *bc = 0;\r
+ struct ext4_mountpoint *mp = 0;\r
+\r
+ if (mount_point[strlen(mount_point) - 1] != '/')\r
+ return ENOTSUP;\r
+\r
+ for (i = 0; i < CONFIG_EXT4_BLOCKDEVS_COUNT; ++i) {\r
+ if (_bdevices[i].name) {\r
+ if (!strcmp(dev_name, _bdevices[i].name)) {\r
+ bd = _bdevices[i].bd;\r
+ bc = _bdevices[i].bc;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!bd)\r
+ return ENODEV;\r
+\r
+ for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
+ if (!_mp[i].mounted) {\r
+ strcpy(_mp[i].name, mount_point);\r
+ _mp[i].mounted = 1;\r
+ mp = &_mp[i];\r
+ break;\r
+ }\r
+\r
+ if (!strcmp(_mp[i].name, mount_point))\r
+ return EOK;\r
+ }\r
+\r
+ if (!mp)\r
+ return ENOMEM;\r
+\r
+ r = ext4_block_init(bd);\r
+ if (r != EOK)\r
+ return r;\r
+\r
+ r = ext4_fs_init(&mp->fs, bd);\r
+ if (r != EOK) {\r
+ ext4_block_fini(bd);\r
+ return r;\r
+ }\r
+\r
+ bsize = ext4_sb_get_block_size(&mp->fs.sb);\r
+ ext4_block_set_lb_size(bd, bsize);\r
+\r
+ mp->cache_dynamic = 0;\r
+\r
+ if (!bc) {\r
+ /*Automatic block cache alloc.*/\r
+ mp->cache_dynamic = 1;\r
+ bc = malloc(sizeof(struct ext4_bcache));\r
+\r
+ r = ext4_bcache_init_dynamic(bc, CONFIG_BLOCK_DEV_CACHE_SIZE,\r
+ bsize);\r
+ if (r != EOK) {\r
+ free(bc);\r
+ ext4_block_fini(bd);\r
+ return r;\r
+ }\r
+ }\r
+\r
+ if (bsize != bc->itemsize)\r
+ return ENOTSUP;\r
+\r
+ /*Bind block cache to block device*/\r
+ r = ext4_block_bind_bcache(bd, bc);\r
+ if (r != EOK) {\r
+ ext4_block_fini(bd);\r
+ if (mp->cache_dynamic) {\r
+ ext4_bcache_fini_dynamic(bc);\r
+ free(bc);\r
+ }\r
+ return r;\r
+ }\r
+\r
+ return r;\r
}\r
\r
int ext4_umount(const char *mount_point)\r
{\r
- int i;\r
- int r;\r
- struct ext4_mountpoint *mp = 0;\r
+ int i;\r
+ int r;\r
+ struct ext4_mountpoint *mp = 0;\r
\r
- for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
- if (!strcmp(_mp[i].name, mount_point)) {\r
- mp = &_mp[i];\r
- break;\r
- }\r
- }\r
+ for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
+ if (!strcmp(_mp[i].name, mount_point)) {\r
+ mp = &_mp[i];\r
+ break;\r
+ }\r
+ }\r
\r
- if (!mp)\r
- return ENODEV;\r
+ if (!mp)\r
+ return ENODEV;\r
\r
- r = ext4_fs_fini(&mp->fs);\r
- if (r != EOK)\r
- return r;\r
+ r = ext4_fs_fini(&mp->fs);\r
+ if (r != EOK)\r
+ return r;\r
\r
- mp->mounted = 0;\r
+ mp->mounted = 0;\r
\r
- if (mp->cache_dynamic) {\r
- ext4_bcache_fini_dynamic(mp->fs.bdev->bc);\r
- free(mp->fs.bdev->bc);\r
- }\r
+ if (mp->cache_dynamic) {\r
+ ext4_bcache_fini_dynamic(mp->fs.bdev->bc);\r
+ free(mp->fs.bdev->bc);\r
+ }\r
\r
- return ext4_block_fini(mp->fs.bdev);\r
+ return ext4_block_fini(mp->fs.bdev);\r
}\r
\r
int ext4_mount_point_stats(const char *mount_point,\r
- struct ext4_mount_stats *stats)\r
+ struct ext4_mount_stats *stats)\r
{\r
- uint32_t i;\r
- struct ext4_mountpoint *mp = 0;\r
-\r
- for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
- if (!strcmp(_mp[i].name, mount_point)) {\r
- mp = &_mp[i];\r
- break;\r
- }\r
- }\r
- if (!mp)\r
- return ENOENT;\r
-\r
- EXT4_MP_LOCK(mp);\r
- stats->inodes_count = ext4_get32(&mp->fs.sb, inodes_count);\r
- stats->free_inodes_count = ext4_get32(&mp->fs.sb, free_inodes_count);\r
- stats->blocks_count = ext4_sb_get_blocks_cnt(&mp->fs.sb);\r
- stats->free_blocks_count = ext4_sb_get_free_blocks_cnt(&mp->fs.sb);\r
- stats->block_size = ext4_sb_get_block_size(&mp->fs.sb);\r
-\r
- stats->block_group_count = ext4_block_group_cnt(&mp->fs.sb);\r
- stats->blocks_per_group = ext4_get32(&mp->fs.sb, blocks_per_group);\r
- stats->inodes_per_group = ext4_get32(&mp->fs.sb, inodes_per_group);\r
-\r
- memcpy(stats->volume_name, mp->fs.sb.volume_name, 16);\r
- EXT4_MP_UNLOCK(mp);\r
-\r
- return EOK;\r
+ uint32_t i;\r
+ struct ext4_mountpoint *mp = 0;\r
+\r
+ for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
+ if (!strcmp(_mp[i].name, mount_point)) {\r
+ mp = &_mp[i];\r
+ break;\r
+ }\r
+ }\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+ stats->inodes_count = ext4_get32(&mp->fs.sb, inodes_count);\r
+ stats->free_inodes_count = ext4_get32(&mp->fs.sb, free_inodes_count);\r
+ stats->blocks_count = ext4_sb_get_blocks_cnt(&mp->fs.sb);\r
+ stats->free_blocks_count = ext4_sb_get_free_blocks_cnt(&mp->fs.sb);\r
+ stats->block_size = ext4_sb_get_block_size(&mp->fs.sb);\r
+\r
+ stats->block_group_count = ext4_block_group_cnt(&mp->fs.sb);\r
+ stats->blocks_per_group = ext4_get32(&mp->fs.sb, blocks_per_group);\r
+ stats->inodes_per_group = ext4_get32(&mp->fs.sb, inodes_per_group);\r
+\r
+ memcpy(stats->volume_name, mp->fs.sb.volume_name, 16);\r
+ EXT4_MP_UNLOCK(mp);\r
+\r
+ return EOK;\r
}\r
\r
int ext4_mount_setup_locks(const char *mount_point,\r
- const struct ext4_lock *locks)\r
+ const struct ext4_lock *locks)\r
{\r
- uint32_t i;\r
- struct ext4_mountpoint *mp = 0;\r
-\r
- for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
- if (!strcmp(_mp[i].name, mount_point)) {\r
- mp = &_mp[i];\r
- break;\r
- }\r
- }\r
- if (!mp)\r
- return ENOENT;\r
-\r
- mp->os_locks = locks;\r
- return EOK;\r
+ uint32_t i;\r
+ struct ext4_mountpoint *mp = 0;\r
+\r
+ for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
+ if (!strcmp(_mp[i].name, mount_point)) {\r
+ mp = &_mp[i];\r
+ break;\r
+ }\r
+ }\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ mp->os_locks = locks;\r
+ return EOK;\r
}\r
\r
/********************************FILE OPERATIONS*****************************/\r
\r
static struct ext4_mountpoint *ext4_get_mount(const char *path)\r
{\r
- int i;\r
- for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
+ int i;\r
+ for (i = 0; i < CONFIG_EXT4_MOUNTPOINTS_COUNT; ++i) {\r
\r
- if (!_mp[i].mounted)\r
- continue;\r
+ if (!_mp[i].mounted)\r
+ continue;\r
\r
- if (!strncmp(_mp[i].name, path, strlen(_mp[i].name)))\r
- return &_mp[i];\r
- }\r
- return 0;\r
+ if (!strncmp(_mp[i].name, path, strlen(_mp[i].name)))\r
+ return &_mp[i];\r
+ }\r
+ return 0;\r
}\r
\r
static int ext4_path_check(const char *path, bool *is_goal)\r
{\r
- int i;\r
+ int i;\r
\r
- for (i = 0; i < EXT4_DIRECTORY_FILENAME_LEN; ++i) {\r
+ for (i = 0; i < EXT4_DIRECTORY_FILENAME_LEN; ++i) {\r
\r
- if (path[i] == '/') {\r
- *is_goal = false;\r
- return i;\r
- }\r
+ if (path[i] == '/') {\r
+ *is_goal = false;\r
+ return i;\r
+ }\r
\r
- if (path[i] == 0) {\r
- *is_goal = true;\r
- return i;\r
- }\r
- }\r
+ if (path[i] == 0) {\r
+ *is_goal = true;\r
+ return i;\r
+ }\r
+ }\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
static bool ext4_parse_flags(const char *flags, uint32_t *file_flags)\r
{\r
- if (!flags)\r
- return false;\r
-\r
- if (!strcmp(flags, "r") || !strcmp(flags, "rb")) {\r
- *file_flags = O_RDONLY;\r
- return true;\r
- }\r
-\r
- if (!strcmp(flags, "w") || !strcmp(flags, "wb")) {\r
- *file_flags = O_WRONLY | O_CREAT | O_TRUNC;\r
- return true;\r
- }\r
-\r
- if (!strcmp(flags, "a") || !strcmp(flags, "ab")) {\r
- *file_flags = O_WRONLY | O_CREAT | O_APPEND;\r
- return true;\r
- }\r
-\r
- if (!strcmp(flags, "r+") || !strcmp(flags, "rb+") ||\r
- !strcmp(flags, "r+b")) {\r
- *file_flags = O_RDWR;\r
- return true;\r
- }\r
-\r
- if (!strcmp(flags, "w+") || !strcmp(flags, "wb+") ||\r
- !strcmp(flags, "w+b")) {\r
- *file_flags = O_RDWR | O_CREAT | O_TRUNC;\r
- return true;\r
- }\r
-\r
- if (!strcmp(flags, "a+") || !strcmp(flags, "ab+") ||\r
- !strcmp(flags, "a+b")) {\r
- *file_flags = O_RDWR | O_CREAT | O_APPEND;\r
- return true;\r
- }\r
-\r
- return false;\r
+ if (!flags)\r
+ return false;\r
+\r
+ if (!strcmp(flags, "r") || !strcmp(flags, "rb")) {\r
+ *file_flags = O_RDONLY;\r
+ return true;\r
+ }\r
+\r
+ if (!strcmp(flags, "w") || !strcmp(flags, "wb")) {\r
+ *file_flags = O_WRONLY | O_CREAT | O_TRUNC;\r
+ return true;\r
+ }\r
+\r
+ if (!strcmp(flags, "a") || !strcmp(flags, "ab")) {\r
+ *file_flags = O_WRONLY | O_CREAT | O_APPEND;\r
+ return true;\r
+ }\r
+\r
+ if (!strcmp(flags, "r+") || !strcmp(flags, "rb+") ||\r
+ !strcmp(flags, "r+b")) {\r
+ *file_flags = O_RDWR;\r
+ return true;\r
+ }\r
+\r
+ if (!strcmp(flags, "w+") || !strcmp(flags, "wb+") ||\r
+ !strcmp(flags, "w+b")) {\r
+ *file_flags = O_RDWR | O_CREAT | O_TRUNC;\r
+ return true;\r
+ }\r
+\r
+ if (!strcmp(flags, "a+") || !strcmp(flags, "ab+") ||\r
+ !strcmp(flags, "a+b")) {\r
+ *file_flags = O_RDWR | O_CREAT | O_APPEND;\r
+ return true;\r
+ }\r
+\r
+ return false;\r
}\r
\r
/*\r
* any filetype of the target dir entry will be accepted.\r
*/\r
static int ext4_generic_open2(ext4_file *f, const char *path, int flags,\r
- int filetype, uint32_t *parent_inode,\r
- uint32_t *name_off)\r
+ int filetype, uint32_t *parent_inode,\r
+ uint32_t *name_off)\r
{\r
- bool is_goal = false;\r
- uint8_t inode_type = EXT4_DIRECTORY_FILETYPE_DIR;\r
- uint32_t next_inode;\r
+ bool is_goal = false;\r
+ uint8_t inode_type = EXT4_DIRECTORY_FILETYPE_DIR;\r
+ uint32_t next_inode;\r
\r
- int r;\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- struct ext4_directory_search_result result;\r
- struct ext4_inode_ref ref;\r
+ int r;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ struct ext4_directory_search_result result;\r
+ struct ext4_inode_ref ref;\r
\r
- f->mp = 0;\r
+ f->mp = 0;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- f->flags = flags;\r
+ f->flags = flags;\r
+\r
+ /*Skip mount point*/\r
+ path += strlen(mp->name);\r
\r
- /*Skip mount point*/\r
- path += strlen(mp->name);\r
+ if (name_off)\r
+ *name_off = strlen(mp->name);\r
\r
- if (name_off)\r
- *name_off = strlen(mp->name);\r
+ /*Load root*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &ref);\r
\r
- /*Load root*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &ref);\r
+ if (r != EOK)\r
+ return r;\r
\r
- if (r != EOK)\r
- return r;\r
+ if (parent_inode)\r
+ *parent_inode = ref.index;\r
\r
- if (parent_inode)\r
- *parent_inode = ref.index;\r
+ int len = ext4_path_check(path, &is_goal);\r
\r
- int len = ext4_path_check(path, &is_goal);\r
+ while (1) {\r
\r
- while (1) {\r
+ len = ext4_path_check(path, &is_goal);\r
\r
- len = ext4_path_check(path, &is_goal);\r
+ if (!len) {\r
+ /*If root open was request.*/\r
+ if (is_goal &&\r
+ ((filetype == EXT4_DIRECTORY_FILETYPE_DIR) ||\r
+ (filetype == EXT4_DIRECTORY_FILETYPE_UNKNOWN)))\r
+ break;\r
\r
- if (!len) {\r
- /*If root open was request.*/\r
- if (is_goal && ((filetype == EXT4_DIRECTORY_FILETYPE_DIR)\r
- || (filetype == EXT4_DIRECTORY_FILETYPE_UNKNOWN)))\r
- break;\r
+ r = ENOENT;\r
+ break;\r
+ }\r
\r
- r = ENOENT;\r
- break;\r
- }\r
+ r = ext4_dir_find_entry(&result, &ref, path, len);\r
+ if (r != EOK) {\r
\r
- r = ext4_dir_find_entry(&result, &ref, path, len);\r
- if (r != EOK) {\r
+ if (r != ENOENT)\r
+ break;\r
\r
- if (r != ENOENT)\r
- break;\r
+ if (!(f->flags & O_CREAT))\r
+ break;\r
\r
- if (!(f->flags & O_CREAT))\r
- break;\r
+ /*O_CREAT allows create new entry*/\r
+ struct ext4_inode_ref child_ref;\r
+ r = ext4_fs_alloc_inode(\r
+ &mp->fs, &child_ref,\r
+ is_goal ? (filetype == EXT4_DIRECTORY_FILETYPE_DIR)\r
+ : true);\r
+ if (r != EOK)\r
+ break;\r
\r
- /*O_CREAT allows create new entry*/\r
- struct ext4_inode_ref child_ref;\r
- r = ext4_fs_alloc_inode(&mp->fs, &child_ref,\r
- is_goal\r
- ? (filetype == EXT4_DIRECTORY_FILETYPE_DIR)\r
- : true);\r
- if (r != EOK)\r
- break;\r
+ /*Destroy last result*/\r
+ ext4_dir_destroy_result(&ref, &result);\r
\r
- /*Destroy last result*/\r
- ext4_dir_destroy_result(&ref, &result);\r
+ /*Link with root dir.*/\r
+ r = ext4_link(mp, &ref, &child_ref, path, len);\r
+ if (r != EOK) {\r
+ /*Fail. Free new inode.*/\r
+ ext4_fs_free_inode(&child_ref);\r
+ /*We do not want to write new inode.\r
+ But block has to be released.*/\r
+ child_ref.dirty = false;\r
+ ext4_fs_put_inode_ref(&child_ref);\r
+ break;\r
+ }\r
\r
- /*Link with root dir.*/\r
- r = ext4_link(mp, &ref, &child_ref, path, len);\r
- if (r != EOK) {\r
- /*Fail. Free new inode.*/\r
- ext4_fs_free_inode(&child_ref);\r
- /*We do not want to write new inode.\r
- But block has to be released.*/\r
- child_ref.dirty = false;\r
- ext4_fs_put_inode_ref(&child_ref);\r
- break;\r
- }\r
+ ext4_fs_put_inode_ref(&child_ref);\r
\r
- ext4_fs_put_inode_ref(&child_ref);\r
+ continue;\r
+ }\r
\r
- continue;\r
- }\r
+ if (parent_inode)\r
+ *parent_inode = ref.index;\r
\r
- if (parent_inode)\r
- *parent_inode = ref.index;\r
+ next_inode = result.dentry->inode;\r
+ inode_type =\r
+ ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry);\r
\r
- next_inode = result.dentry->inode;\r
- inode_type =\r
- ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry);\r
+ r = ext4_dir_destroy_result(&ref, &result);\r
+ if (r != EOK)\r
+ break;\r
\r
- r = ext4_dir_destroy_result(&ref, &result);\r
- if (r != EOK)\r
- break;\r
+ /*If expected file error*/\r
+ if (inode_type != EXT4_DIRECTORY_FILETYPE_DIR && !is_goal) {\r
+ r = ENOENT;\r
+ break;\r
+ }\r
+ if (filetype != EXT4_DIRECTORY_FILETYPE_UNKNOWN) {\r
+ if ((inode_type != filetype) && is_goal) {\r
+ r = ENOENT;\r
+ break;\r
+ }\r
+ }\r
\r
- /*If expected file error*/\r
- if (inode_type != EXT4_DIRECTORY_FILETYPE_DIR && !is_goal) {\r
- r = ENOENT;\r
- break;\r
- }\r
- if (filetype != EXT4_DIRECTORY_FILETYPE_UNKNOWN) {\r
- if ((inode_type != filetype) && is_goal) {\r
- r = ENOENT;\r
- break;\r
- }\r
- }\r
+ r = ext4_fs_put_inode_ref(&ref);\r
+ if (r != EOK)\r
+ break;\r
\r
- r = ext4_fs_put_inode_ref(&ref);\r
- if (r != EOK)\r
- break;\r
-\r
- r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &ref);\r
- if (r != EOK)\r
- break;\r
-\r
- if (is_goal)\r
- break;\r
-\r
- path += len + 1;\r
-\r
- if (name_off)\r
- *name_off += len + 1;\r
- };\r
-\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&ref);\r
- return r;\r
- }\r
-\r
- if (is_goal) {\r
-\r
- if ((f->flags & O_TRUNC) &&\r
- (inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE)) {\r
-\r
- r = ext4_fs_truncate_inode(&ref, 0);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&ref);\r
- return r;\r
- }\r
- }\r
-\r
- f->mp = mp;\r
- f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
- f->inode = ref.index;\r
- f->fpos = 0;\r
-\r
- if (f->flags & O_APPEND)\r
- f->fpos = f->fsize;\r
- }\r
-\r
- r = ext4_fs_put_inode_ref(&ref);\r
- return r;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &ref);\r
+ if (r != EOK)\r
+ break;\r
+\r
+ if (is_goal)\r
+ break;\r
+\r
+ path += len + 1;\r
+\r
+ if (name_off)\r
+ *name_off += len + 1;\r
+ };\r
+\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&ref);\r
+ return r;\r
+ }\r
+\r
+ if (is_goal) {\r
+\r
+ if ((f->flags & O_TRUNC) &&\r
+ (inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE)) {\r
+\r
+ r = ext4_fs_truncate_inode(&ref, 0);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&ref);\r
+ return r;\r
+ }\r
+ }\r
+\r
+ f->mp = mp;\r
+ f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
+ f->inode = ref.index;\r
+ f->fpos = 0;\r
+\r
+ if (f->flags & O_APPEND)\r
+ f->fpos = f->fsize;\r
+ }\r
+\r
+ r = ext4_fs_put_inode_ref(&ref);\r
+ return r;\r
}\r
\r
/****************************************************************************/\r
\r
static int ext4_generic_open(ext4_file *f, const char *path, const char *flags,\r
- bool file_expect, uint32_t *parent_inode,\r
- uint32_t *name_off)\r
+ bool file_expect, uint32_t *parent_inode,\r
+ uint32_t *name_off)\r
{\r
- uint32_t iflags;\r
- int filetype;\r
- if (ext4_parse_flags(flags, &iflags) == false)\r
- return EINVAL;\r
-\r
- if (file_expect == true)\r
- filetype = EXT4_DIRECTORY_FILETYPE_REG_FILE;\r
- else\r
- filetype = EXT4_DIRECTORY_FILETYPE_DIR;\r
-\r
- return ext4_generic_open2(f, path, iflags, filetype,\r
- parent_inode, name_off);\r
+ uint32_t iflags;\r
+ int filetype;\r
+ if (ext4_parse_flags(flags, &iflags) == false)\r
+ return EINVAL;\r
+\r
+ if (file_expect == true)\r
+ filetype = EXT4_DIRECTORY_FILETYPE_REG_FILE;\r
+ else\r
+ filetype = EXT4_DIRECTORY_FILETYPE_DIR;\r
+\r
+ return ext4_generic_open2(f, path, iflags, filetype, parent_inode,\r
+ name_off);\r
}\r
\r
static int __ext4_create_hardlink(const char *path,\r
- struct ext4_inode_ref *child_ref)\r
+ struct ext4_inode_ref *child_ref)\r
{\r
- bool is_goal = false;\r
- uint8_t inode_type = EXT4_DIRECTORY_FILETYPE_DIR;\r
- uint32_t next_inode;\r
+ bool is_goal = false;\r
+ uint8_t inode_type = EXT4_DIRECTORY_FILETYPE_DIR;\r
+ uint32_t next_inode;\r
\r
- int r;\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- struct ext4_directory_search_result result;\r
- struct ext4_inode_ref ref;\r
+ int r;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ struct ext4_directory_search_result result;\r
+ struct ext4_inode_ref ref;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- /*Skip mount point*/\r
- path += strlen(mp->name);\r
+ /*Skip mount point*/\r
+ path += strlen(mp->name);\r
\r
- /*Load root*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &ref);\r
+ /*Load root*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &ref);\r
\r
- if (r != EOK)\r
- return r;\r
+ if (r != EOK)\r
+ return r;\r
\r
- int len = ext4_path_check(path, &is_goal);\r
+ int len = ext4_path_check(path, &is_goal);\r
\r
- while (1) {\r
+ while (1) {\r
\r
- len = ext4_path_check(path, &is_goal);\r
+ len = ext4_path_check(path, &is_goal);\r
\r
- if (!len) {\r
- /*If root open was request.*/\r
- if (is_goal)\r
- r = EINVAL;\r
- else\r
- r = ENOENT;\r
- break;\r
- }\r
+ if (!len) {\r
+ /*If root open was request.*/\r
+ if (is_goal)\r
+ r = EINVAL;\r
+ else\r
+ r = ENOENT;\r
+ break;\r
+ }\r
\r
- r = ext4_dir_find_entry(&result, &ref, path, len);\r
- if (r != EOK) {\r
+ r = ext4_dir_find_entry(&result, &ref, path, len);\r
+ if (r != EOK) {\r
\r
- if (r != ENOENT || !is_goal)\r
- break;\r
+ if (r != ENOENT || !is_goal)\r
+ break;\r
\r
- /*Destroy last result*/\r
- ext4_dir_destroy_result(&ref, &result);\r
+ /*Destroy last result*/\r
+ ext4_dir_destroy_result(&ref, &result);\r
\r
- /*Link with root dir.*/\r
- r = ext4_link(mp, &ref, child_ref, path, len);\r
- break;\r
- }\r
+ /*Link with root dir.*/\r
+ r = ext4_link(mp, &ref, child_ref, path, len);\r
+ break;\r
+ }\r
\r
- next_inode = result.dentry->inode;\r
- inode_type =\r
- ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry);\r
+ next_inode = result.dentry->inode;\r
+ inode_type =\r
+ ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry);\r
\r
- r = ext4_dir_destroy_result(&ref, &result);\r
- if (r != EOK)\r
- break;\r
+ r = ext4_dir_destroy_result(&ref, &result);\r
+ if (r != EOK)\r
+ break;\r
\r
- if (inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE) {\r
- if (is_goal)\r
- r = EEXIST;\r
- else\r
- r = ENOENT;\r
+ if (inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE) {\r
+ if (is_goal)\r
+ r = EEXIST;\r
+ else\r
+ r = ENOENT;\r
\r
- break;\r
- }\r
+ break;\r
+ }\r
\r
- r = ext4_fs_put_inode_ref(&ref);\r
- if (r != EOK)\r
- break;\r
+ r = ext4_fs_put_inode_ref(&ref);\r
+ if (r != EOK)\r
+ break;\r
\r
- r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &ref);\r
- if (r != EOK)\r
- break;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &ref);\r
+ if (r != EOK)\r
+ break;\r
\r
- if (is_goal)\r
- break;\r
+ if (is_goal)\r
+ break;\r
\r
- path += len + 1;\r
- };\r
+ path += len + 1;\r
+ };\r
\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&ref);\r
- return r;\r
- }\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&ref);\r
+ return r;\r
+ }\r
\r
- r = ext4_fs_put_inode_ref(&ref);\r
- return r;\r
+ r = ext4_fs_put_inode_ref(&ref);\r
+ return r;\r
}\r
\r
-static int __ext4_get_inode_ref_remove_hardlink(const char *path, struct ext4_inode_ref *child)\r
+static int __ext4_get_inode_ref_remove_hardlink(const char *path,\r
+ struct ext4_inode_ref *child)\r
{\r
- ext4_file f;\r
- uint32_t parent_inode;\r
- uint32_t name_off;\r
- bool is_goal;\r
- int r;\r
- int len;\r
- struct ext4_inode_ref parent;\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- r = ext4_generic_open2(&f, path, O_RDONLY,\r
- EXT4_DIRECTORY_FILETYPE_UNKNOWN,\r
- &parent_inode, &name_off);\r
- if (r != EOK)\r
- return r;\r
-\r
- /*Load parent*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent);\r
- if (r != EOK) {\r
- return r;\r
- }\r
-\r
- /*We have file to unlink. Load it.*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, f.inode, child);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&parent);\r
- return r;\r
- }\r
-\r
- if (r != EOK)\r
- goto Finish;\r
-\r
- /*Set path*/\r
- path += name_off;\r
-\r
- len = ext4_path_check(path, &is_goal);\r
-\r
- /*Unlink from parent*/\r
- r = ext4_unlink(mp, &parent, child, path, len);\r
- if (r != EOK)\r
- goto Finish;\r
+ ext4_file f;\r
+ uint32_t parent_inode;\r
+ uint32_t name_off;\r
+ bool is_goal;\r
+ int r;\r
+ int len;\r
+ struct ext4_inode_ref parent;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ r = ext4_generic_open2(&f, path, O_RDONLY,\r
+ EXT4_DIRECTORY_FILETYPE_UNKNOWN, &parent_inode,\r
+ &name_off);\r
+ if (r != EOK)\r
+ return r;\r
+\r
+ /*Load parent*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent);\r
+ if (r != EOK) {\r
+ return r;\r
+ }\r
+\r
+ /*We have file to unlink. Load it.*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, f.inode, child);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&parent);\r
+ return r;\r
+ }\r
+\r
+ if (r != EOK)\r
+ goto Finish;\r
+\r
+ /*Set path*/\r
+ path += name_off;\r
+\r
+ len = ext4_path_check(path, &is_goal);\r
+\r
+ /*Unlink from parent*/\r
+ r = ext4_unlink(mp, &parent, child, path, len);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
Finish:\r
- if (r != EOK)\r
- ext4_fs_put_inode_ref(child);\r
+ if (r != EOK)\r
+ ext4_fs_put_inode_ref(child);\r
\r
- ext4_fs_put_inode_ref(&parent);\r
- return r;\r
+ ext4_fs_put_inode_ref(&parent);\r
+ return r;\r
}\r
\r
int ext4_frename(const char *path, const char *new_path)\r
{\r
- int r;\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- struct ext4_inode_ref inode_ref;\r
+ int r;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ struct ext4_inode_ref inode_ref;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
+ EXT4_MP_LOCK(mp);\r
\r
- r = __ext4_get_inode_ref_remove_hardlink(path, &inode_ref);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = __ext4_get_inode_ref_remove_hardlink(path, &inode_ref);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- r = __ext4_create_hardlink(new_path, &inode_ref);\r
- if (r != EOK)\r
- r = __ext4_create_hardlink(path, &inode_ref);\r
+ r = __ext4_create_hardlink(new_path, &inode_ref);\r
+ if (r != EOK)\r
+ r = __ext4_create_hardlink(path, &inode_ref);\r
\r
- ext4_fs_put_inode_ref(&inode_ref);\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
\r
Finish:\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
-\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
/****************************************************************************/\r
\r
int ext4_get_sblock(const char *mount_point, struct ext4_sblock **sb)\r
{\r
- struct ext4_mountpoint *mp = ext4_get_mount(mount_point);\r
+ struct ext4_mountpoint *mp = ext4_get_mount(mount_point);\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- *sb = &mp->fs.sb;\r
- return EOK;\r
+ *sb = &mp->fs.sb;\r
+ return EOK;\r
}\r
\r
int ext4_cache_write_back(const char *path, bool on)\r
{\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
- ext4_block_cache_write_back(mp->fs.bdev, on);\r
- EXT4_MP_UNLOCK(mp);\r
- return EOK;\r
+ EXT4_MP_LOCK(mp);\r
+ ext4_block_cache_write_back(mp->fs.bdev, on);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return EOK;\r
}\r
\r
int ext4_fremove(const char *path)\r
{\r
- ext4_file f;\r
- uint32_t parent_inode;\r
- uint32_t name_off;\r
- bool is_goal;\r
- int r;\r
- int len;\r
- struct ext4_inode_ref child;\r
- struct ext4_inode_ref parent;\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- EXT4_MP_LOCK(mp);\r
- r = ext4_generic_open(&f, path, "r", true, &parent_inode, &name_off);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
-\r
- /*Load parent*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
-\r
- /*We have file to delete. Load it.*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, f.inode, &child);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&parent);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
-\r
- /*Set path*/\r
- path += name_off;\r
-\r
- len = ext4_path_check(path, &is_goal);\r
-\r
- /*Unlink from parent*/\r
- r = ext4_unlink(mp, &parent, &child, path, len);\r
- if (r != EOK)\r
- goto Finish;\r
-\r
- /*Link count is zero, the inode should be freed. */\r
- if (!ext4_inode_get_links_count(child.inode)) {\r
- printf("ttttt\n");\r
- ext4_inode_set_deletion_time(child.inode, 0xFFFFFFFF);\r
- /*Turncate*/\r
- ext4_block_cache_write_back(mp->fs.bdev, 1);\r
- /*Truncate may be IO heavy. Do it writeback cache mode.*/\r
- r = ext4_fs_truncate_inode(&child, 0);\r
- ext4_block_cache_write_back(mp->fs.bdev, 0);\r
-\r
- if (r != EOK)\r
- goto Finish;\r
-\r
- r = ext4_fs_free_inode(&child);\r
- if (r != EOK)\r
- goto Finish;\r
-\r
- }\r
+ ext4_file f;\r
+ uint32_t parent_inode;\r
+ uint32_t name_off;\r
+ bool is_goal;\r
+ int r;\r
+ int len;\r
+ struct ext4_inode_ref child;\r
+ struct ext4_inode_ref parent;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+ r = ext4_generic_open(&f, path, "r", true, &parent_inode, &name_off);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
+\r
+ /*Load parent*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
+\r
+ /*We have file to delete. Load it.*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, f.inode, &child);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&parent);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
+\r
+ /*Set path*/\r
+ path += name_off;\r
+\r
+ len = ext4_path_check(path, &is_goal);\r
+\r
+ /*Unlink from parent*/\r
+ r = ext4_unlink(mp, &parent, &child, path, len);\r
+ if (r != EOK)\r
+ goto Finish;\r
+\r
+ /*Link count is zero, the inode should be freed. */\r
+ if (!ext4_inode_get_links_count(child.inode)) {\r
+ printf("ttttt\n");\r
+ ext4_inode_set_deletion_time(child.inode, 0xFFFFFFFF);\r
+ /*Turncate*/\r
+ ext4_block_cache_write_back(mp->fs.bdev, 1);\r
+ /*Truncate may be IO heavy. Do it writeback cache mode.*/\r
+ r = ext4_fs_truncate_inode(&child, 0);\r
+ ext4_block_cache_write_back(mp->fs.bdev, 0);\r
+\r
+ if (r != EOK)\r
+ goto Finish;\r
+\r
+ r = ext4_fs_free_inode(&child);\r
+ if (r != EOK)\r
+ goto Finish;\r
+ }\r
\r
Finish:\r
- ext4_fs_put_inode_ref(&child);\r
- ext4_fs_put_inode_ref(&parent);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&child);\r
+ ext4_fs_put_inode_ref(&parent);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
-int ext4_fill_raw_inode(const char *mount_point, uint32_t ino, struct ext4_inode *inode)\r
+int ext4_fill_raw_inode(const char *mount_point, uint32_t ino,\r
+ struct ext4_inode *inode)\r
{\r
- int r;\r
- struct ext4_inode_ref inode_ref;\r
- struct ext4_mountpoint *mp = ext4_get_mount(mount_point);\r
+ int r;\r
+ struct ext4_inode_ref inode_ref;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(mount_point);\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
+ EXT4_MP_LOCK(mp);\r
\r
- /*Load parent*/\r
- r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
+ /*Load parent*/\r
+ r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
\r
- memcpy(inode, inode_ref.inode, sizeof(struct ext4_inode));\r
+ memcpy(inode, inode_ref.inode, sizeof(struct ext4_inode));\r
\r
- ext4_fs_put_inode_ref(&inode_ref);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_fopen(ext4_file *f, const char *path, const char *flags)\r
{\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- int r;\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- EXT4_MP_LOCK(mp);\r
- ext4_block_cache_write_back(mp->fs.bdev, 1);\r
- r = ext4_generic_open(f, path, flags, true, 0, 0);\r
- ext4_block_cache_write_back(mp->fs.bdev, 0);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ int r;\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+ ext4_block_cache_write_back(mp->fs.bdev, 1);\r
+ r = ext4_generic_open(f, path, flags, true, 0, 0);\r
+ ext4_block_cache_write_back(mp->fs.bdev, 0);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_fopen2(ext4_file *f, const char *path, int flags, bool file_expect)\r
{\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- int r;\r
- int filetype;\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- if (file_expect == true)\r
- filetype = EXT4_DIRECTORY_FILETYPE_REG_FILE;\r
- else\r
- filetype = EXT4_DIRECTORY_FILETYPE_DIR;\r
-\r
- EXT4_MP_LOCK(mp);\r
- ext4_block_cache_write_back(mp->fs.bdev, 1);\r
- r = ext4_generic_open2(f, path, flags, filetype, 0, 0);\r
- ext4_block_cache_write_back(mp->fs.bdev, 0);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ int r;\r
+ int filetype;\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ if (file_expect == true)\r
+ filetype = EXT4_DIRECTORY_FILETYPE_REG_FILE;\r
+ else\r
+ filetype = EXT4_DIRECTORY_FILETYPE_DIR;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+ ext4_block_cache_write_back(mp->fs.bdev, 1);\r
+ r = ext4_generic_open2(f, path, flags, filetype, 0, 0);\r
+ ext4_block_cache_write_back(mp->fs.bdev, 0);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_fclose(ext4_file *f)\r
{\r
- ext4_assert(f && f->mp);\r
+ ext4_assert(f && f->mp);\r
\r
- f->mp = 0;\r
- f->flags = 0;\r
- f->inode = 0;\r
- f->fpos = f->fsize = 0;\r
+ f->mp = 0;\r
+ f->flags = 0;\r
+ f->inode = 0;\r
+ f->fpos = f->fsize = 0;\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
int ext4_ftruncate(ext4_file *f, uint64_t size)\r
{\r
- struct ext4_inode_ref ref;\r
- int r;\r
+ struct ext4_inode_ref ref;\r
+ int r;\r
\r
+ ext4_assert(f && f->mp);\r
\r
- ext4_assert(f && f->mp);\r
+ if (f->flags & O_RDONLY)\r
+ return EPERM;\r
\r
- if (f->flags & O_RDONLY)\r
- return EPERM;\r
+ EXT4_MP_LOCK(f->mp);\r
\r
- EXT4_MP_LOCK(f->mp);\r
+ r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(f->mp);\r
+ return r;\r
+ }\r
\r
- r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(f->mp);\r
- return r;\r
- }\r
+ /*Sync file size*/\r
+ f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
+ if (f->fsize <= size) {\r
+ r = EOK;\r
+ goto Finish;\r
+ }\r
\r
- /*Sync file size*/\r
- f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
- if (f->fsize <= size) {\r
- r = EOK;\r
- goto Finish;\r
- }\r
+ /*Start write back cache mode.*/\r
+ r = ext4_block_cache_write_back(f->mp->fs.bdev, 1);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- /*Start write back cache mode.*/\r
- r = ext4_block_cache_write_back(f->mp->fs.bdev, 1);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_fs_truncate_inode(&ref, size);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- r = ext4_fs_truncate_inode(&ref, size);\r
- if (r != EOK)\r
- goto Finish;\r
+ f->fsize = size;\r
+ if (f->fpos > size)\r
+ f->fpos = size;\r
\r
- f->fsize = size;\r
- if (f->fpos > size)\r
- f->fpos = size;\r
+ /*Stop write back cache mode*/\r
+ ext4_block_cache_write_back(f->mp->fs.bdev, 0);\r
\r
- /*Stop write back cache mode*/\r
- ext4_block_cache_write_back(f->mp->fs.bdev, 0);\r
-\r
- if (r != EOK)\r
- goto Finish;\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
Finish:\r
- ext4_fs_put_inode_ref(&ref);\r
- EXT4_MP_UNLOCK(f->mp);\r
- return r;\r
-\r
+ ext4_fs_put_inode_ref(&ref);\r
+ EXT4_MP_UNLOCK(f->mp);\r
+ return r;\r
}\r
\r
int ext4_fread(ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)\r
{\r
- uint32_t u;\r
- uint32_t fblock;\r
- uint32_t fblock_start;\r
- uint32_t fblock_cnt;\r
- uint32_t sblock;\r
- uint32_t sblock_end;\r
- uint32_t block_size;\r
- uint8_t *u8_buf = buf;\r
- int r;\r
- struct ext4_block b;\r
- struct ext4_inode_ref ref;\r
+ uint32_t u;\r
+ uint32_t fblock;\r
+ uint32_t fblock_start;\r
+ uint32_t fblock_cnt;\r
+ uint32_t sblock;\r
+ uint32_t sblock_end;\r
+ uint32_t block_size;\r
+ uint8_t *u8_buf = buf;\r
+ int r;\r
+ struct ext4_block b;\r
+ struct ext4_inode_ref ref;\r
\r
- ext4_assert(f && f->mp);\r
+ ext4_assert(f && f->mp);\r
\r
- if (f->flags & O_WRONLY)\r
- return EPERM;\r
+ if (f->flags & O_WRONLY)\r
+ return EPERM;\r
\r
- if (!size)\r
- return EOK;\r
+ if (!size)\r
+ return EOK;\r
\r
- EXT4_MP_LOCK(f->mp);\r
+ EXT4_MP_LOCK(f->mp);\r
\r
- if (rcnt)\r
- *rcnt = 0;\r
+ if (rcnt)\r
+ *rcnt = 0;\r
\r
- r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(f->mp);\r
- return r;\r
- }\r
+ r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(f->mp);\r
+ return r;\r
+ }\r
\r
- /*Sync file size*/\r
- f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
+ /*Sync file size*/\r
+ f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
\r
- block_size = ext4_sb_get_block_size(&f->mp->fs.sb);\r
- size = size > (f->fsize - f->fpos) ? (f->fsize - f->fpos) : size;\r
- sblock = (f->fpos) / block_size;\r
- sblock_end = (f->fpos + size) / block_size;\r
- u = (f->fpos) % block_size;\r
+ block_size = ext4_sb_get_block_size(&f->mp->fs.sb);\r
+ size = size > (f->fsize - f->fpos) ? (f->fsize - f->fpos) : size;\r
+ sblock = (f->fpos) / block_size;\r
+ sblock_end = (f->fpos + size) / block_size;\r
+ u = (f->fpos) % block_size;\r
\r
- if (u) {\r
+ if (u) {\r
\r
- uint32_t ll = size > (block_size - u) ? (block_size - u) : size;\r
+ uint32_t ll = size > (block_size - u) ? (block_size - u) : size;\r
\r
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- memcpy(u8_buf, b.data + u, ll);\r
+ memcpy(u8_buf, b.data + u, ll);\r
\r
- r = ext4_block_set(f->mp->fs.bdev, &b);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_block_set(f->mp->fs.bdev, &b);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- u8_buf += ll;\r
- size -= ll;\r
- f->fpos += ll;\r
+ u8_buf += ll;\r
+ size -= ll;\r
+ f->fpos += ll;\r
\r
- if (rcnt)\r
- *rcnt += ll;\r
+ if (rcnt)\r
+ *rcnt += ll;\r
\r
- sblock++;\r
- }\r
+ sblock++;\r
+ }\r
\r
- fblock_start = 0;\r
- fblock_cnt = 0;\r
- while (size >= block_size) {\r
- while (sblock < sblock_end) {\r
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ fblock_start = 0;\r
+ fblock_cnt = 0;\r
+ while (size >= block_size) {\r
+ while (sblock < sblock_end) {\r
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock,\r
+ &fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- sblock++;\r
+ sblock++;\r
\r
- if (!fblock_start) {\r
- fblock_start = fblock;\r
- }\r
+ if (!fblock_start) {\r
+ fblock_start = fblock;\r
+ }\r
\r
- if ((fblock_start + fblock_cnt) != fblock)\r
- break;\r
+ if ((fblock_start + fblock_cnt) != fblock)\r
+ break;\r
\r
- fblock_cnt++;\r
- }\r
+ fblock_cnt++;\r
+ }\r
\r
- r = ext4_blocks_get_direct(f->mp->fs.bdev, u8_buf, fblock_start,\r
- fblock_cnt);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_blocks_get_direct(f->mp->fs.bdev, u8_buf, fblock_start,\r
+ fblock_cnt);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- size -= block_size * fblock_cnt;\r
- u8_buf += block_size * fblock_cnt;\r
- f->fpos += block_size * fblock_cnt;\r
+ size -= block_size * fblock_cnt;\r
+ u8_buf += block_size * fblock_cnt;\r
+ f->fpos += block_size * fblock_cnt;\r
\r
- if (rcnt)\r
- *rcnt += block_size * fblock_cnt;\r
+ if (rcnt)\r
+ *rcnt += block_size * fblock_cnt;\r
\r
- fblock_start = fblock;\r
- fblock_cnt = 1;\r
- }\r
+ fblock_start = fblock;\r
+ fblock_cnt = 1;\r
+ }\r
\r
- if (size) {\r
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ if (size) {\r
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- memcpy(u8_buf, b.data, size);\r
+ memcpy(u8_buf, b.data, size);\r
\r
- r = ext4_block_set(f->mp->fs.bdev, &b);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_block_set(f->mp->fs.bdev, &b);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- f->fpos += size;\r
+ f->fpos += size;\r
\r
- if (rcnt)\r
- *rcnt += size;\r
- }\r
+ if (rcnt)\r
+ *rcnt += size;\r
+ }\r
\r
Finish:\r
- ext4_fs_put_inode_ref(&ref);\r
- EXT4_MP_UNLOCK(f->mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&ref);\r
+ EXT4_MP_UNLOCK(f->mp);\r
+ return r;\r
}\r
\r
int ext4_fwrite(ext4_file *f, const void *buf, uint32_t size, uint32_t *wcnt)\r
{\r
- uint32_t u;\r
- uint32_t fblock;\r
-\r
- uint32_t sblock;\r
- uint32_t sblock_end;\r
- uint32_t file_blocks;\r
- uint32_t block_size;\r
- uint32_t fblock_start;\r
- uint32_t fblock_cnt;\r
-\r
- struct ext4_block b;\r
- struct ext4_inode_ref ref;\r
- const uint8_t *u8_buf = buf;\r
- int r;\r
+ uint32_t u;\r
+ uint32_t fblock;\r
\r
+ uint32_t sblock;\r
+ uint32_t sblock_end;\r
+ uint32_t file_blocks;\r
+ uint32_t block_size;\r
+ uint32_t fblock_start;\r
+ uint32_t fblock_cnt;\r
\r
- ext4_assert(f && f->mp);\r
+ struct ext4_block b;\r
+ struct ext4_inode_ref ref;\r
+ const uint8_t *u8_buf = buf;\r
+ int r;\r
\r
- if (f->flags & O_RDONLY)\r
- return EPERM;\r
+ ext4_assert(f && f->mp);\r
\r
- if (!size)\r
- return EOK;\r
+ if (f->flags & O_RDONLY)\r
+ return EPERM;\r
\r
- EXT4_MP_LOCK(f->mp);\r
+ if (!size)\r
+ return EOK;\r
\r
- if (wcnt)\r
- *wcnt = 0;\r
+ EXT4_MP_LOCK(f->mp);\r
\r
- r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(f->mp);\r
- return r;\r
- }\r
+ if (wcnt)\r
+ *wcnt = 0;\r
\r
- /*Sync file size*/\r
- f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
+ r = ext4_fs_get_inode_ref(&f->mp->fs, f->inode, &ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(f->mp);\r
+ return r;\r
+ }\r
\r
- block_size = ext4_sb_get_block_size(&f->mp->fs.sb);\r
+ /*Sync file size*/\r
+ f->fsize = ext4_inode_get_size(&f->mp->fs.sb, ref.inode);\r
\r
- sblock_end = (f->fpos + size) > f->fsize ? (f->fpos + size) : f->fsize;\r
- sblock_end /= block_size;\r
- file_blocks = (f->fsize / block_size);\r
+ block_size = ext4_sb_get_block_size(&f->mp->fs.sb);\r
\r
- if (f->fsize % block_size)\r
- file_blocks++;\r
+ sblock_end = (f->fpos + size) > f->fsize ? (f->fpos + size) : f->fsize;\r
+ sblock_end /= block_size;\r
+ file_blocks = (f->fsize / block_size);\r
\r
- sblock = (f->fpos) / block_size;\r
+ if (f->fsize % block_size)\r
+ file_blocks++;\r
\r
- u = (f->fpos) % block_size;\r
+ sblock = (f->fpos) / block_size;\r
\r
- if (u) {\r
- uint32_t ll = size > (block_size - u) ? (block_size - u) : size;\r
+ u = (f->fpos) % block_size;\r
\r
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ if (u) {\r
+ uint32_t ll = size > (block_size - u) ? (block_size - u) : size;\r
\r
- r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- memcpy(b.data + u, u8_buf, ll);\r
- b.dirty = true;\r
+ r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- r = ext4_block_set(f->mp->fs.bdev, &b);\r
- if (r != EOK)\r
- goto Finish;\r
+ memcpy(b.data + u, u8_buf, ll);\r
+ b.dirty = true;\r
\r
- u8_buf += ll;\r
- size -= ll;\r
- f->fpos += ll;\r
+ r = ext4_block_set(f->mp->fs.bdev, &b);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- if (wcnt)\r
- *wcnt += ll;\r
+ u8_buf += ll;\r
+ size -= ll;\r
+ f->fpos += ll;\r
\r
- sblock++;\r
- }\r
+ if (wcnt)\r
+ *wcnt += ll;\r
\r
- /*Start write back cache mode.*/\r
- r = ext4_block_cache_write_back(f->mp->fs.bdev, 1);\r
- if (r != EOK)\r
- goto Finish;\r
+ sblock++;\r
+ }\r
\r
- fblock_start = 0;\r
- fblock_cnt = 0;\r
- while (size >= block_size) {\r
+ /*Start write back cache mode.*/\r
+ r = ext4_block_cache_write_back(f->mp->fs.bdev, 1);\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- while (sblock < sblock_end) {\r
- if (sblock < file_blocks) {\r
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
- if (r != EOK)\r
- break;\r
- } else {\r
- r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);\r
- if (r != EOK)\r
- break;\r
- }\r
+ fblock_start = 0;\r
+ fblock_cnt = 0;\r
+ while (size >= block_size) {\r
\r
- sblock++;\r
+ while (sblock < sblock_end) {\r
+ if (sblock < file_blocks) {\r
+ r = ext4_fs_get_inode_data_block_index(\r
+ &ref, sblock, &fblock);\r
+ if (r != EOK)\r
+ break;\r
+ } else {\r
+ r = ext4_fs_append_inode_block(&ref, &fblock,\r
+ &sblock);\r
+ if (r != EOK)\r
+ break;\r
+ }\r
\r
- if (!fblock_start) {\r
- fblock_start = fblock;\r
- }\r
+ sblock++;\r
\r
- if ((fblock_start + fblock_cnt) != fblock)\r
- break;\r
+ if (!fblock_start) {\r
+ fblock_start = fblock;\r
+ }\r
\r
- fblock_cnt++;\r
- }\r
+ if ((fblock_start + fblock_cnt) != fblock)\r
+ break;\r
\r
- r = ext4_blocks_set_direct(f->mp->fs.bdev, u8_buf, fblock_start,\r
- fblock_cnt);\r
- if (r != EOK)\r
- break;\r
+ fblock_cnt++;\r
+ }\r
\r
- size -= block_size * fblock_cnt;\r
- u8_buf += block_size * fblock_cnt;\r
- f->fpos += block_size * fblock_cnt;\r
+ r = ext4_blocks_set_direct(f->mp->fs.bdev, u8_buf, fblock_start,\r
+ fblock_cnt);\r
+ if (r != EOK)\r
+ break;\r
\r
- if (wcnt)\r
- *wcnt += block_size * fblock_cnt;\r
+ size -= block_size * fblock_cnt;\r
+ u8_buf += block_size * fblock_cnt;\r
+ f->fpos += block_size * fblock_cnt;\r
\r
- fblock_start = fblock;\r
- fblock_cnt = 1;\r
- }\r
+ if (wcnt)\r
+ *wcnt += block_size * fblock_cnt;\r
\r
- /*Stop write back cache mode*/\r
- ext4_block_cache_write_back(f->mp->fs.bdev, 0);\r
+ fblock_start = fblock;\r
+ fblock_cnt = 1;\r
+ }\r
\r
- if (r != EOK)\r
- goto Finish;\r
+ /*Stop write back cache mode*/\r
+ ext4_block_cache_write_back(f->mp->fs.bdev, 0);\r
\r
- if (size) {\r
- if (sblock < file_blocks) {\r
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
- if (r != EOK)\r
- goto Finish;\r
- } else {\r
- r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);\r
- if (r != EOK)\r
- goto Finish;\r
- }\r
+ if (r != EOK)\r
+ goto Finish;\r
\r
- r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
- if (r != EOK)\r
- goto Finish;\r
+ if (size) {\r
+ if (sblock < file_blocks) {\r
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock,\r
+ &fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
+ } else {\r
+ r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
+ }\r
\r
- memcpy(b.data, u8_buf, size);\r
- b.dirty = true;\r
-\r
- r = ext4_block_set(f->mp->fs.bdev, &b);\r
- if (r != EOK)\r
- goto Finish;\r
-\r
- f->fpos += size;\r
-\r
- if (wcnt)\r
- *wcnt += size;\r
- }\r
-\r
- if (f->fpos > f->fsize) {\r
- f->fsize = f->fpos;\r
- ext4_inode_set_size(ref.inode, f->fsize);\r
- ref.dirty = true;\r
- }\r
+ r = ext4_block_get(f->mp->fs.bdev, &b, fblock);\r
+ if (r != EOK)\r
+ goto Finish;\r
+\r
+ memcpy(b.data, u8_buf, size);\r
+ b.dirty = true;\r
+\r
+ r = ext4_block_set(f->mp->fs.bdev, &b);\r
+ if (r != EOK)\r
+ goto Finish;\r
+\r
+ f->fpos += size;\r
+\r
+ if (wcnt)\r
+ *wcnt += size;\r
+ }\r
+\r
+ if (f->fpos > f->fsize) {\r
+ f->fsize = f->fpos;\r
+ ext4_inode_set_size(ref.inode, f->fsize);\r
+ ref.dirty = true;\r
+ }\r
\r
Finish:\r
- ext4_fs_put_inode_ref(&ref);\r
- EXT4_MP_UNLOCK(f->mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&ref);\r
+ EXT4_MP_UNLOCK(f->mp);\r
+ return r;\r
}\r
\r
int ext4_fseek(ext4_file *f, uint64_t offset, uint32_t origin)\r
{\r
- switch (origin) {\r
- case SEEK_SET:\r
- if (offset > f->fsize)\r
- return EINVAL;\r
-\r
- f->fpos = offset;\r
- return EOK;\r
- case SEEK_CUR:\r
- if ((offset + f->fpos) > f->fsize)\r
- return EINVAL;\r
-\r
- f->fpos += offset;\r
- return EOK;\r
- case SEEK_END:\r
- if (offset > f->fsize)\r
- return EINVAL;\r
-\r
- f->fpos = f->fsize - offset;\r
- return EOK;\r
- }\r
- return EINVAL;\r
+ switch (origin) {\r
+ case SEEK_SET:\r
+ if (offset > f->fsize)\r
+ return EINVAL;\r
+\r
+ f->fpos = offset;\r
+ return EOK;\r
+ case SEEK_CUR:\r
+ if ((offset + f->fpos) > f->fsize)\r
+ return EINVAL;\r
+\r
+ f->fpos += offset;\r
+ return EOK;\r
+ case SEEK_END:\r
+ if (offset > f->fsize)\r
+ return EINVAL;\r
+\r
+ f->fpos = f->fsize - offset;\r
+ return EOK;\r
+ }\r
+ return EINVAL;\r
}\r
\r
-uint64_t ext4_ftell(ext4_file *f)\r
-{\r
- return f->fpos;\r
-}\r
+uint64_t ext4_ftell(ext4_file *f) { return f->fpos; }\r
\r
-uint64_t ext4_fsize(ext4_file *f)\r
-{\r
- return f->fsize;\r
-}\r
+uint64_t ext4_fsize(ext4_file *f) { return f->fsize; }\r
\r
int ext4_fchmod(ext4_file *f, uint32_t mode)\r
{\r
- int r;\r
- uint32_t ino;\r
- struct ext4_sblock *sb;\r
- struct ext4_inode_ref inode_ref;\r
- struct ext4_mountpoint *mp = f->mp;\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- EXT4_MP_LOCK(mp);\r
-\r
- ino = f->inode;\r
- r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
-\r
- sb = &f->mp->fs.sb;\r
- ext4_inode_set_mode(sb, inode_ref.inode, mode);\r
- inode_ref.dirty = true;\r
-\r
- ext4_fs_put_inode_ref(&inode_ref);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ int r;\r
+ uint32_t ino;\r
+ struct ext4_sblock *sb;\r
+ struct ext4_inode_ref inode_ref;\r
+ struct ext4_mountpoint *mp = f->mp;\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+\r
+ ino = f->inode;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
+\r
+ sb = &f->mp->fs.sb;\r
+ ext4_inode_set_mode(sb, inode_ref.inode, mode);\r
+ inode_ref.dirty = true;\r
+\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_fchown(ext4_file *f, uint32_t uid, uint32_t gid)\r
{\r
- int r;\r
- uint32_t ino;\r
- struct ext4_inode_ref inode_ref;\r
- struct ext4_mountpoint *mp = f->mp;\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- EXT4_MP_LOCK(mp);\r
-\r
- ino = f->inode;\r
- r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
-\r
- ext4_inode_set_uid(inode_ref.inode, uid);\r
- ext4_inode_set_gid(inode_ref.inode, gid);\r
- inode_ref.dirty = true;\r
-\r
- ext4_fs_put_inode_ref(&inode_ref);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ int r;\r
+ uint32_t ino;\r
+ struct ext4_inode_ref inode_ref;\r
+ struct ext4_mountpoint *mp = f->mp;\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+\r
+ ino = f->inode;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
+\r
+ ext4_inode_set_uid(inode_ref.inode, uid);\r
+ ext4_inode_set_gid(inode_ref.inode, gid);\r
+ inode_ref.dirty = true;\r
+\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_file_set_atime(ext4_file *f, uint32_t atime)\r
{\r
- int r;\r
- uint32_t ino;\r
- struct ext4_inode_ref inode_ref;\r
- struct ext4_mountpoint *mp = f->mp;\r
+ int r;\r
+ uint32_t ino;\r
+ struct ext4_inode_ref inode_ref;\r
+ struct ext4_mountpoint *mp = f->mp;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
+ EXT4_MP_LOCK(mp);\r
\r
- ino = f->inode;\r
- r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
+ ino = f->inode;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
\r
- ext4_inode_set_access_time(inode_ref.inode, atime);\r
- inode_ref.dirty = true;\r
+ ext4_inode_set_access_time(inode_ref.inode, atime);\r
+ inode_ref.dirty = true;\r
\r
- ext4_fs_put_inode_ref(&inode_ref);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_file_set_mtime(ext4_file *f, uint32_t mtime)\r
{\r
- int r;\r
- uint32_t ino;\r
- struct ext4_inode_ref inode_ref;\r
- struct ext4_mountpoint *mp = f->mp;\r
+ int r;\r
+ uint32_t ino;\r
+ struct ext4_inode_ref inode_ref;\r
+ struct ext4_mountpoint *mp = f->mp;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
+ EXT4_MP_LOCK(mp);\r
\r
- ino = f->inode;\r
- r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
+ ino = f->inode;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
\r
- ext4_inode_set_modification_time(inode_ref.inode, mtime);\r
- inode_ref.dirty = true;\r
+ ext4_inode_set_modification_time(inode_ref.inode, mtime);\r
+ inode_ref.dirty = true;\r
\r
- ext4_fs_put_inode_ref(&inode_ref);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_file_set_ctime(ext4_file *f, uint32_t ctime)\r
{\r
- int r;\r
- uint32_t ino;\r
- struct ext4_inode_ref inode_ref;\r
- struct ext4_mountpoint *mp = f->mp;\r
+ int r;\r
+ uint32_t ino;\r
+ struct ext4_inode_ref inode_ref;\r
+ struct ext4_mountpoint *mp = f->mp;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
+ EXT4_MP_LOCK(mp);\r
\r
- ino = f->inode;\r
- r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
+ ino = f->inode;\r
+ r = ext4_fs_get_inode_ref(&mp->fs, ino, &inode_ref);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
\r
- ext4_inode_set_change_inode_time(inode_ref.inode, ctime);\r
- inode_ref.dirty = true;\r
+ ext4_inode_set_change_inode_time(inode_ref.inode, ctime);\r
+ inode_ref.dirty = true;\r
\r
- ext4_fs_put_inode_ref(&inode_ref);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ ext4_fs_put_inode_ref(&inode_ref);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
/*********************************DIRECTORY OPERATION************************/\r
\r
int ext4_dir_rm(const char *path)\r
{\r
- int r;\r
- int len;\r
- ext4_file f;\r
-\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- struct ext4_inode_ref current;\r
- struct ext4_inode_ref child;\r
- struct ext4_directory_iterator it;\r
-\r
- uint32_t name_off;\r
- uint32_t inode_up;\r
- uint32_t inode_current;\r
- uint32_t depth = 1;\r
-\r
- bool has_children;\r
- bool is_goal;\r
- bool dir_end;\r
-\r
- if (!mp)\r
- return ENOENT;\r
-\r
- EXT4_MP_LOCK(mp);\r
-\r
- /*Check if exist.*/\r
- r = ext4_generic_open(&f, path, "r", false, &inode_up, &name_off);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
-\r
- path += name_off;\r
- len = ext4_path_check(path, &is_goal);\r
-\r
- inode_current = f.inode;\r
- dir_end = false;\r
-\r
- ext4_block_cache_write_back(mp->fs.bdev, 1);\r
-\r
- do {\r
- /*Load directory node.*/\r
- r = ext4_fs_get_inode_ref(&f.mp->fs, inode_current, ¤t);\r
- if (r != EOK) {\r
- break;\r
- }\r
-\r
- /*Initialize iterator.*/\r
- r = ext4_dir_iterator_init(&it, ¤t, 0);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(¤t);\r
- break;\r
- }\r
-\r
- while (r == EOK) {\r
-\r
- if (!it.current) {\r
- dir_end = true;\r
- break;\r
- }\r
-\r
- /*Get up directory inode when ".." entry*/\r
- if ((it.current->name_length == 2) &&\r
- ext4_is_dots(it.current->name, it.current->name_length)) {\r
- inode_up = it.current->inode;\r
- }\r
-\r
- /*If directory or file entry, but not "." ".." entry*/\r
- if (!ext4_is_dots(it.current->name, it.current->name_length)) {\r
-\r
- /*Get child inode reference do unlink directory/file.*/\r
- r = ext4_fs_get_inode_ref(&f.mp->fs, it.current->inode, &child);\r
- if (r != EOK)\r
- break;\r
-\r
- /*If directory with no leaf children*/\r
- r = ext4_has_children(&has_children, &child);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&child);\r
- break;\r
- }\r
-\r
- if (has_children) {\r
- /*Has directory children. Go into this directory.*/\r
- inode_up = inode_current;\r
- inode_current = it.current->inode;\r
- depth++;\r
- ext4_fs_put_inode_ref(&child);\r
- break;\r
- }\r
-\r
- /*No children in child directory or file. Just unlink.*/\r
- r = ext4_unlink(f.mp, ¤t, &child,\r
- (char *)it.current->name,\r
- it.current->name_length);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&child);\r
- break;\r
- }\r
-\r
- ext4_inode_set_deletion_time(child.inode, 0xFFFFFFFF);\r
- ext4_inode_set_links_count(child.inode, 0);\r
- child.dirty = true;\r
- /*Turncate*/\r
- r = ext4_fs_truncate_inode(&child, 0);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&child);\r
- break;\r
- }\r
-\r
- r = ext4_fs_free_inode(&child);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&child);\r
- break;\r
- }\r
-\r
-\r
- r = ext4_fs_put_inode_ref(&child);\r
- if (r != EOK)\r
- break;\r
- }\r
-\r
- r = ext4_dir_iterator_next(&it);\r
- }\r
-\r
- if (dir_end) {\r
- /*Directory iterator reached last entry*/\r
- ext4_has_children(&has_children, ¤t);\r
- if (!has_children) {\r
- inode_current = inode_up;\r
- if (depth)\r
- depth--;\r
- }\r
- /*Last unlink*/\r
- if (!depth) {\r
- /*Load parent.*/\r
- struct ext4_inode_ref parent;\r
- r = ext4_fs_get_inode_ref(&f.mp->fs, inode_up, &parent);\r
- if (r != EOK)\r
- goto End;\r
-\r
- /* In this place all directories should be unlinked.\r
- * Last unlink from root of current directory*/\r
- r = ext4_unlink(f.mp, &parent, ¤t, (char *)path, len);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&parent);\r
- goto End;\r
- }\r
-\r
- if (ext4_inode_get_links_count(current.inode) == 2) {\r
- ext4_inode_set_deletion_time(current.inode, 0xFFFFFFFF);\r
- ext4_inode_set_links_count(current.inode, 0);\r
- current.dirty = true;\r
- /*Turncate*/\r
- r = ext4_fs_truncate_inode(¤t, 0);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&parent);\r
- goto End;\r
- }\r
-\r
- r = ext4_fs_free_inode(¤t);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&parent);\r
- goto End;\r
- }\r
-\r
- }\r
-\r
- r = ext4_fs_put_inode_ref(&parent);\r
- if (r != EOK)\r
- goto End;\r
- }\r
- }\r
-\r
- End:\r
- ext4_dir_iterator_fini(&it);\r
- ext4_fs_put_inode_ref(¤t);\r
- dir_end = false;\r
-\r
- /*When something goes wrong. End loop.*/\r
- if (r != EOK)\r
- break;\r
-\r
- } while (depth);\r
-\r
- ext4_block_cache_write_back(mp->fs.bdev, 0);\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ int r;\r
+ int len;\r
+ ext4_file f;\r
+\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ struct ext4_inode_ref current;\r
+ struct ext4_inode_ref child;\r
+ struct ext4_directory_iterator it;\r
+\r
+ uint32_t name_off;\r
+ uint32_t inode_up;\r
+ uint32_t inode_current;\r
+ uint32_t depth = 1;\r
+\r
+ bool has_children;\r
+ bool is_goal;\r
+ bool dir_end;\r
+\r
+ if (!mp)\r
+ return ENOENT;\r
+\r
+ EXT4_MP_LOCK(mp);\r
+\r
+ /*Check if exist.*/\r
+ r = ext4_generic_open(&f, path, "r", false, &inode_up, &name_off);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
+\r
+ path += name_off;\r
+ len = ext4_path_check(path, &is_goal);\r
+\r
+ inode_current = f.inode;\r
+ dir_end = false;\r
+\r
+ ext4_block_cache_write_back(mp->fs.bdev, 1);\r
+\r
+ do {\r
+ /*Load directory node.*/\r
+ r = ext4_fs_get_inode_ref(&f.mp->fs, inode_current, ¤t);\r
+ if (r != EOK) {\r
+ break;\r
+ }\r
+\r
+ /*Initialize iterator.*/\r
+ r = ext4_dir_iterator_init(&it, ¤t, 0);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(¤t);\r
+ break;\r
+ }\r
+\r
+ while (r == EOK) {\r
+\r
+ if (!it.current) {\r
+ dir_end = true;\r
+ break;\r
+ }\r
+\r
+ /*Get up directory inode when ".." entry*/\r
+ if ((it.current->name_length == 2) &&\r
+ ext4_is_dots(it.current->name,\r
+ it.current->name_length)) {\r
+ inode_up = it.current->inode;\r
+ }\r
+\r
+ /*If directory or file entry, but not "." ".." entry*/\r
+ if (!ext4_is_dots(it.current->name,\r
+ it.current->name_length)) {\r
+\r
+ /*Get child inode reference do unlink\r
+ * directory/file.*/\r
+ r = ext4_fs_get_inode_ref(\r
+ &f.mp->fs, it.current->inode, &child);\r
+ if (r != EOK)\r
+ break;\r
+\r
+ /*If directory with no leaf children*/\r
+ r = ext4_has_children(&has_children, &child);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&child);\r
+ break;\r
+ }\r
+\r
+ if (has_children) {\r
+ /*Has directory children. Go into this\r
+ * directory.*/\r
+ inode_up = inode_current;\r
+ inode_current = it.current->inode;\r
+ depth++;\r
+ ext4_fs_put_inode_ref(&child);\r
+ break;\r
+ }\r
+\r
+ /*No children in child directory or file. Just\r
+ * unlink.*/\r
+ r = ext4_unlink(f.mp, ¤t, &child,\r
+ (char *)it.current->name,\r
+ it.current->name_length);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&child);\r
+ break;\r
+ }\r
+\r
+ ext4_inode_set_deletion_time(child.inode,\r
+ 0xFFFFFFFF);\r
+ ext4_inode_set_links_count(child.inode, 0);\r
+ child.dirty = true;\r
+ /*Turncate*/\r
+ r = ext4_fs_truncate_inode(&child, 0);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&child);\r
+ break;\r
+ }\r
+\r
+ r = ext4_fs_free_inode(&child);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&child);\r
+ break;\r
+ }\r
+\r
+ r = ext4_fs_put_inode_ref(&child);\r
+ if (r != EOK)\r
+ break;\r
+ }\r
+\r
+ r = ext4_dir_iterator_next(&it);\r
+ }\r
+\r
+ if (dir_end) {\r
+ /*Directory iterator reached last entry*/\r
+ ext4_has_children(&has_children, ¤t);\r
+ if (!has_children) {\r
+ inode_current = inode_up;\r
+ if (depth)\r
+ depth--;\r
+ }\r
+ /*Last unlink*/\r
+ if (!depth) {\r
+ /*Load parent.*/\r
+ struct ext4_inode_ref parent;\r
+ r = ext4_fs_get_inode_ref(&f.mp->fs, inode_up,\r
+ &parent);\r
+ if (r != EOK)\r
+ goto End;\r
+\r
+ /* In this place all directories should be\r
+ * unlinked.\r
+ * Last unlink from root of current directory*/\r
+ r = ext4_unlink(f.mp, &parent, ¤t,\r
+ (char *)path, len);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&parent);\r
+ goto End;\r
+ }\r
+\r
+ if (ext4_inode_get_links_count(current.inode) ==\r
+ 2) {\r
+ ext4_inode_set_deletion_time(\r
+ current.inode, 0xFFFFFFFF);\r
+ ext4_inode_set_links_count(\r
+ current.inode, 0);\r
+ current.dirty = true;\r
+ /*Turncate*/\r
+ r = ext4_fs_truncate_inode(¤t, 0);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&parent);\r
+ goto End;\r
+ }\r
+\r
+ r = ext4_fs_free_inode(¤t);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&parent);\r
+ goto End;\r
+ }\r
+ }\r
+\r
+ r = ext4_fs_put_inode_ref(&parent);\r
+ if (r != EOK)\r
+ goto End;\r
+ }\r
+ }\r
+\r
+ End:\r
+ ext4_dir_iterator_fini(&it);\r
+ ext4_fs_put_inode_ref(¤t);\r
+ dir_end = false;\r
+\r
+ /*When something goes wrong. End loop.*/\r
+ if (r != EOK)\r
+ break;\r
+\r
+ } while (depth);\r
+\r
+ ext4_block_cache_write_back(mp->fs.bdev, 0);\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_dir_mk(const char *path)\r
{\r
- int r;\r
- ext4_file f;\r
+ int r;\r
+ ext4_file f;\r
\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
+ EXT4_MP_LOCK(mp);\r
\r
- /*Check if exist.*/\r
- r = ext4_generic_open(&f, path, "r", false, 0, 0);\r
- if (r == EOK) {\r
- /*Directory already created*/\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
+ /*Check if exist.*/\r
+ r = ext4_generic_open(&f, path, "r", false, 0, 0);\r
+ if (r == EOK) {\r
+ /*Directory already created*/\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
\r
- /*Create new dir*/\r
- r = ext4_generic_open(&f, path, "w", false, 0, 0);\r
- if (r != EOK) {\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
- }\r
+ /*Create new dir*/\r
+ r = ext4_generic_open(&f, path, "w", false, 0, 0);\r
+ if (r != EOK) {\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
+ }\r
\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_dir_open(ext4_dir *d, const char *path)\r
{\r
- struct ext4_mountpoint *mp = ext4_get_mount(path);\r
- int r;\r
+ struct ext4_mountpoint *mp = ext4_get_mount(path);\r
+ int r;\r
\r
- if (!mp)\r
- return ENOENT;\r
+ if (!mp)\r
+ return ENOENT;\r
\r
- EXT4_MP_LOCK(mp);\r
- r = ext4_generic_open(&d->f, path, "r", false, 0, 0);\r
- d->next_off = 0;\r
- EXT4_MP_UNLOCK(mp);\r
- return r;\r
+ EXT4_MP_LOCK(mp);\r
+ r = ext4_generic_open(&d->f, path, "r", false, 0, 0);\r
+ d->next_off = 0;\r
+ EXT4_MP_UNLOCK(mp);\r
+ return r;\r
}\r
\r
int ext4_dir_close(ext4_dir *d) { return ext4_fclose(&d->f); }\r
{\r
#define EXT4_DIR_ENTRY_OFFSET_TERM (uint64_t)(-1)\r
\r
- int r;\r
- ext4_direntry *de = 0;\r
- struct ext4_inode_ref dir;\r
- struct ext4_directory_iterator it;\r
+ int r;\r
+ ext4_direntry *de = 0;\r
+ struct ext4_inode_ref dir;\r
+ struct ext4_directory_iterator it;\r
\r
- EXT4_MP_LOCK(d->f.mp);\r
+ EXT4_MP_LOCK(d->f.mp);\r
\r
- if (d->next_off == EXT4_DIR_ENTRY_OFFSET_TERM)\r
- return 0;\r
+ if (d->next_off == EXT4_DIR_ENTRY_OFFSET_TERM)\r
+ return 0;\r
\r
- r = ext4_fs_get_inode_ref(&d->f.mp->fs, d->f.inode, &dir);\r
- if (r != EOK) {\r
- goto Finish;\r
- }\r
+ r = ext4_fs_get_inode_ref(&d->f.mp->fs, d->f.inode, &dir);\r
+ if (r != EOK) {\r
+ goto Finish;\r
+ }\r
\r
- r = ext4_dir_iterator_init(&it, &dir, d->next_off);\r
- if (r != EOK) {\r
- ext4_fs_put_inode_ref(&dir);\r
- goto Finish;\r
- }\r
+ r = ext4_dir_iterator_init(&it, &dir, d->next_off);\r
+ if (r != EOK) {\r
+ ext4_fs_put_inode_ref(&dir);\r
+ goto Finish;\r
+ }\r
\r
- memcpy(&d->de, it.current, sizeof(ext4_direntry));\r
- de = &d->de;\r
+ memcpy(&d->de, it.current, sizeof(ext4_direntry));\r
+ de = &d->de;\r
\r
- ext4_dir_iterator_next(&it);\r
+ ext4_dir_iterator_next(&it);\r
\r
- d->next_off = it.current ? it.current_offset : EXT4_DIR_ENTRY_OFFSET_TERM;\r
+ d->next_off =\r
+ it.current ? it.current_offset : EXT4_DIR_ENTRY_OFFSET_TERM;\r
\r
- ext4_dir_iterator_fini(&it);\r
- ext4_fs_put_inode_ref(&dir);\r
+ ext4_dir_iterator_fini(&it);\r
+ ext4_fs_put_inode_ref(&dir);\r
\r
Finish:\r
- EXT4_MP_UNLOCK(d->f.mp);\r
- return de;\r
+ EXT4_MP_UNLOCK(d->f.mp);\r
+ return de;\r
}\r
\r
/**\r
/**@brief OS dependent lock interface.*/\r
struct ext4_lock {\r
\r
- /**@brief Lock access to mount point*/\r
- void (*lock)(void);\r
+ /**@brief Lock access to mount point*/\r
+ void (*lock)(void);\r
\r
- /**@brief Unlock access to mount point*/\r
- void (*unlock)(void);\r
+ /**@brief Unlock access to mount point*/\r
+ void (*unlock)(void);\r
};\r
\r
/********************************FILE DESCRIPTOR*****************************/\r
/**@brief File descriptor*/\r
typedef struct ext4_file {\r
\r
- /**@brief Mount point handle.*/\r
- struct ext4_mountpoint *mp;\r
+ /**@brief Mount point handle.*/\r
+ struct ext4_mountpoint *mp;\r
\r
- /**@brief File inode id*/\r
- uint32_t inode;\r
+ /**@brief File inode id*/\r
+ uint32_t inode;\r
\r
- /**@brief Open flags.*/\r
- uint32_t flags;\r
+ /**@brief Open flags.*/\r
+ uint32_t flags;\r
\r
- /**@brief File size.*/\r
- uint64_t fsize;\r
+ /**@brief File size.*/\r
+ uint64_t fsize;\r
\r
- /**@brief File position*/\r
- uint64_t fpos;\r
+ /**@brief File position*/\r
+ uint64_t fpos;\r
} ext4_file;\r
\r
/*****************************DIRECTORY DESCRIPTOR***************************/\r
/**@brief Directory entry types. Copy from ext4_types.h*/\r
-enum {\r
- EXT4_DIRENTRY_UNKNOWN = 0,\r
- EXT4_DIRENTRY_REG_FILE,\r
- EXT4_DIRENTRY_DIR,\r
- EXT4_DIRENTRY_CHRDEV,\r
- EXT4_DIRENTRY_BLKDEV,\r
- EXT4_DIRENTRY_FIFO,\r
- EXT4_DIRENTRY_SOCK,\r
- EXT4_DIRENTRY_SYMLINK\r
-};\r
+enum { EXT4_DIRENTRY_UNKNOWN = 0,\r
+ EXT4_DIRENTRY_REG_FILE,\r
+ EXT4_DIRENTRY_DIR,\r
+ EXT4_DIRENTRY_CHRDEV,\r
+ EXT4_DIRENTRY_BLKDEV,\r
+ EXT4_DIRENTRY_FIFO,\r
+ EXT4_DIRENTRY_SOCK,\r
+ EXT4_DIRENTRY_SYMLINK };\r
\r
/**@brief Directory entry descriptor. Copy from ext4_types.h*/\r
typedef struct {\r
- uint32_t inode;\r
- uint16_t entry_length;\r
- uint8_t name_length;\r
- uint8_t inode_type;\r
- uint8_t name[255];\r
+ uint32_t inode;\r
+ uint16_t entry_length;\r
+ uint8_t name_length;\r
+ uint8_t inode_type;\r
+ uint8_t name[255];\r
} ext4_direntry;\r
\r
typedef struct {\r
- /**@brief File descriptor*/\r
- ext4_file f;\r
- /**@brief Current directory entry.*/\r
- ext4_direntry de;\r
- /**@brief Next entry offset*/\r
- uint64_t next_off;\r
+ /**@brief File descriptor*/\r
+ ext4_file f;\r
+ /**@brief Current directory entry.*/\r
+ ext4_direntry de;\r
+ /**@brief Next entry offset*/\r
+ uint64_t next_off;\r
} ext4_dir;\r
\r
/********************************MOUNT OPERATIONS****************************/\r
* @param dev_name register name\r
* @param standard error code*/\r
int ext4_device_register(struct ext4_blockdev *bd, struct ext4_bcache *bc,\r
- const char *dev_name);\r
+ const char *dev_name);\r
\r
/**@brief Mount a block device with EXT4 partition to the mount point.\r
* @param dev_name block device name (@ref ext4_device_register)\r
\r
/**@brief Some of the filesystem stats.*/\r
struct ext4_mount_stats {\r
- uint32_t inodes_count;\r
- uint32_t free_inodes_count;\r
- uint64_t blocks_count;\r
- uint64_t free_blocks_count;\r
+ uint32_t inodes_count;\r
+ uint32_t free_inodes_count;\r
+ uint64_t blocks_count;\r
+ uint64_t free_blocks_count;\r
\r
- uint32_t block_size;\r
- uint32_t block_group_count;\r
- uint32_t blocks_per_group;\r
- uint32_t inodes_per_group;\r
+ uint32_t block_size;\r
+ uint32_t block_group_count;\r
+ uint32_t blocks_per_group;\r
+ uint32_t inodes_per_group;\r
\r
- char volume_name[16];\r
+ char volume_name[16];\r
};\r
\r
/**@brief Get file system params.\r
* @param stats ext fs stats\r
* @return standard error code */\r
int ext4_mount_point_stats(const char *mount_point,\r
- struct ext4_mount_stats *stats);\r
+ struct ext4_mount_stats *stats);\r
\r
/**@brief Setup OS lock routines.\r
* @param mount_point mount path\r
* @param locks - lock and unlock functions\r
* @return standard error code */\r
int ext4_mount_setup_locks(const char *mount_point,\r
- const struct ext4_lock *locks);\r
+ const struct ext4_lock *locks);\r
\r
/**@brief Acquire the filesystem superblock pointer of a mp.\r
* @param mount_point mount path\r
* @param inode no.\r
* @param ext4_inode buffer\r
* @return standard error code*/\r
-int ext4_fill_raw_inode(const char *mount_point, uint32_t ino, struct ext4_inode *inode);\r
+int ext4_fill_raw_inode(const char *mount_point, uint32_t ino,\r
+ struct ext4_inode *inode);\r
\r
/**@brief File truncate function.\r
* @param f file handle\r
* @return Block group index
*/
static uint32_t ext4_balloc_get_bgid_of_block(struct ext4_sblock *s,
- uint32_t baddr)
+ uint32_t baddr)
{
- if (ext4_get32(s, first_data_block))
- baddr--;
+ if (ext4_get32(s, first_data_block))
+ baddr--;
- return baddr / ext4_get32(s, blocks_per_group);
+ return baddr / ext4_get32(s, blocks_per_group);
}
uint32_t
ext4_balloc_get_first_data_block_in_group(struct ext4_sblock *s,
- struct ext4_block_group_ref *bg_ref)
+ struct ext4_block_group_ref *bg_ref)
{
- uint32_t block_group_count = ext4_block_group_cnt(s);
- uint32_t inode_table_first_block =
- ext4_bg_get_inode_table_first_block(bg_ref->block_group, s);
- uint32_t block_size = ext4_sb_get_block_size(s);
+ uint32_t block_group_count = ext4_block_group_cnt(s);
+ uint32_t inode_table_first_block =
+ ext4_bg_get_inode_table_first_block(bg_ref->block_group, s);
+ uint32_t block_size = ext4_sb_get_block_size(s);
- uint16_t inode_size = ext4_get16(s, inode_size);
- uint32_t inodes_per_group = ext4_get32(s, inodes_per_group);
+ uint16_t inode_size = ext4_get16(s, inode_size);
+ uint32_t inodes_per_group = ext4_get32(s, inodes_per_group);
- uint32_t inode_table_bytes;
+ uint32_t inode_table_bytes;
- if (bg_ref->index < block_group_count - 1) {
- inode_table_bytes = inodes_per_group * inode_size;
- } else {
- /* Last block group could be smaller */
- uint32_t inodes_count_total = ext4_get32(s, inodes_count);
- inode_table_bytes = (inodes_count_total -
- ((block_group_count - 1) * inodes_per_group)) *
- inode_size;
- }
+ if (bg_ref->index < block_group_count - 1) {
+ inode_table_bytes = inodes_per_group * inode_size;
+ } else {
+ /* Last block group could be smaller */
+ uint32_t inodes_count_total = ext4_get32(s, inodes_count);
+ inode_table_bytes =
+ (inodes_count_total -
+ ((block_group_count - 1) * inodes_per_group)) *
+ inode_size;
+ }
- uint32_t inode_table_blocks = inode_table_bytes / block_size;
+ uint32_t inode_table_blocks = inode_table_bytes / block_size;
- if (inode_table_bytes % block_size)
- inode_table_blocks++;
+ if (inode_table_bytes % block_size)
+ inode_table_blocks++;
- return inode_table_first_block + inode_table_blocks;
+ return inode_table_first_block + inode_table_blocks;
}
int ext4_balloc_free_block(struct ext4_inode_ref *inode_ref, uint32_t baddr)
{
- struct ext4_fs *fs = inode_ref->fs;
- struct ext4_sblock *sb = &fs->sb;
-
- uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, baddr);
- uint32_t index_in_group = ext4_fs_baddr2_index_in_group(sb, baddr);
-
- /* Load block group reference */
- struct ext4_block_group_ref bg_ref;
- int rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);
- if (rc != EOK)
- return rc;
-
- /* Load block with bitmap */
- uint32_t bitmap_block_addr =
- ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
-
- struct ext4_block bitmap_block;
-
- rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- /* Modify bitmap */
- ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
- bitmap_block.dirty = true;
-
- /* Release block with bitmap */
- rc = ext4_block_set(fs->bdev, &bitmap_block);
- if (rc != EOK) {
- /* Error in saving bitmap */
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- uint32_t block_size = ext4_sb_get_block_size(sb);
-
- /* Update superblock free blocks count */
- uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
- sb_free_blocks++;
- ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
-
- /* Update inode blocks count */
- uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
- ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE;
- ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
- inode_ref->dirty = true;
-
- /* Update block group free blocks count */
- uint32_t free_blocks =
- ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
- free_blocks++;
- ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, free_blocks);
-
- bg_ref.dirty = true;
-
- /* Release block group reference */
- return ext4_fs_put_block_group_ref(&bg_ref);
+ struct ext4_fs *fs = inode_ref->fs;
+ struct ext4_sblock *sb = &fs->sb;
+
+ uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, baddr);
+ uint32_t index_in_group = ext4_fs_baddr2_index_in_group(sb, baddr);
+
+ /* Load block group reference */
+ struct ext4_block_group_ref bg_ref;
+ int rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);
+ if (rc != EOK)
+ return rc;
+
+ /* Load block with bitmap */
+ uint32_t bitmap_block_addr =
+ ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
+
+ struct ext4_block bitmap_block;
+
+ rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ /* Modify bitmap */
+ ext4_bmap_bit_clr(bitmap_block.data, index_in_group);
+ bitmap_block.dirty = true;
+
+ /* Release block with bitmap */
+ rc = ext4_block_set(fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ /* Error in saving bitmap */
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+
+ /* Update superblock free blocks count */
+ uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
+ sb_free_blocks++;
+ ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
+
+ /* Update inode blocks count */
+ uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
+ ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE;
+ ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+ inode_ref->dirty = true;
+
+ /* Update block group free blocks count */
+ uint32_t free_blocks =
+ ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+ free_blocks++;
+ ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, free_blocks);
+
+ bg_ref.dirty = true;
+
+ /* Release block group reference */
+ return ext4_fs_put_block_group_ref(&bg_ref);
}
int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, uint32_t first,
- uint32_t count)
+ uint32_t count)
{
- int rc = EOK;
- struct ext4_fs *fs = inode_ref->fs;
- struct ext4_sblock *sb = &fs->sb;
-
- /* Compute indexes */
- uint32_t block_group_first = ext4_balloc_get_bgid_of_block(sb, first);
-
- /* Compute indexes */
- uint32_t block_group_last =
- ext4_balloc_get_bgid_of_block(sb, first + count - 1);
-
- if (!ext4_sb_has_feature_incompatible(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
- /*It is not possible without flex_bg that blocks are continuous
- * and and last block belongs to other bg.*/
- ext4_assert(block_group_first ==
- ext4_balloc_get_bgid_of_block(sb, first + count - 1));
- }
-
- /* Load block group reference */
- struct ext4_block_group_ref bg_ref;
- while (block_group_first <= block_group_last) {
-
- rc = ext4_fs_get_block_group_ref(fs, block_group_first, &bg_ref);
- if (rc != EOK)
- return rc;
-
- uint32_t index_in_group_first =
- ext4_fs_baddr2_index_in_group(sb, first);
-
- /* Load block with bitmap */
- uint32_t bitmap_block_addr =
- ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
-
- struct ext4_block bitmap_block;
-
- rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- uint32_t free_cnt =
- ext4_sb_get_block_size(sb) * 8 - index_in_group_first;
-
- /*If last block, free only count blocks*/
- free_cnt = count > free_cnt ? free_cnt : count;
-
- /* Modify bitmap */
- ext4_bmap_bits_free(bitmap_block.data, index_in_group_first, free_cnt);
- bitmap_block.dirty = true;
-
- count -= free_cnt;
- first += free_cnt;
-
- /* Release block with bitmap */
- rc = ext4_block_set(fs->bdev, &bitmap_block);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- uint32_t block_size = ext4_sb_get_block_size(sb);
-
- /* Update superblock free blocks count */
- uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
- sb_free_blocks += free_cnt;
- ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
-
- /* Update inode blocks count */
- uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
- ino_blocks -= free_cnt * (block_size / EXT4_INODE_BLOCK_SIZE);
- ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
- inode_ref->dirty = true;
-
- /* Update block group free blocks count */
- uint32_t free_blocks =
- ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
- free_blocks += free_cnt;
- ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, free_blocks);
- bg_ref.dirty = true;
-
- /* Release block group reference */
- rc = ext4_fs_put_block_group_ref(&bg_ref);
- if (rc != EOK)
- break;
-
- block_group_first++;
- }
-
- /*All blocks should be released*/
- ext4_assert(count == 0);
- return rc;
+ int rc = EOK;
+ struct ext4_fs *fs = inode_ref->fs;
+ struct ext4_sblock *sb = &fs->sb;
+
+ /* Compute indexes */
+ uint32_t block_group_first = ext4_balloc_get_bgid_of_block(sb, first);
+
+ /* Compute indexes */
+ uint32_t block_group_last =
+ ext4_balloc_get_bgid_of_block(sb, first + count - 1);
+
+ if (!ext4_sb_has_feature_incompatible(sb,
+ EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+ /*It is not possible without flex_bg that blocks are continuous
+ * and and last block belongs to other bg.*/
+ ext4_assert(block_group_first == ext4_balloc_get_bgid_of_block(
+ sb, first + count - 1));
+ }
+
+ /* Load block group reference */
+ struct ext4_block_group_ref bg_ref;
+ while (block_group_first <= block_group_last) {
+
+ rc =
+ ext4_fs_get_block_group_ref(fs, block_group_first, &bg_ref);
+ if (rc != EOK)
+ return rc;
+
+ uint32_t index_in_group_first =
+ ext4_fs_baddr2_index_in_group(sb, first);
+
+ /* Load block with bitmap */
+ uint32_t bitmap_block_addr =
+ ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
+
+ struct ext4_block bitmap_block;
+
+ rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ uint32_t free_cnt =
+ ext4_sb_get_block_size(sb) * 8 - index_in_group_first;
+
+ /*If last block, free only count blocks*/
+ free_cnt = count > free_cnt ? free_cnt : count;
+
+ /* Modify bitmap */
+ ext4_bmap_bits_free(bitmap_block.data, index_in_group_first,
+ free_cnt);
+ bitmap_block.dirty = true;
+
+ count -= free_cnt;
+ first += free_cnt;
+
+ /* Release block with bitmap */
+ rc = ext4_block_set(fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+
+ /* Update superblock free blocks count */
+ uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
+ sb_free_blocks += free_cnt;
+ ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
+
+ /* Update inode blocks count */
+ uint64_t ino_blocks =
+ ext4_inode_get_blocks_count(sb, inode_ref->inode);
+ ino_blocks -= free_cnt * (block_size / EXT4_INODE_BLOCK_SIZE);
+ ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+ inode_ref->dirty = true;
+
+ /* Update block group free blocks count */
+ uint32_t free_blocks =
+ ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+ free_blocks += free_cnt;
+ ext4_bg_set_free_blocks_count(bg_ref.block_group, sb,
+ free_blocks);
+ bg_ref.dirty = true;
+
+ /* Release block group reference */
+ rc = ext4_fs_put_block_group_ref(&bg_ref);
+ if (rc != EOK)
+ break;
+
+ block_group_first++;
+ }
+
+ /*All blocks should be released*/
+ ext4_assert(count == 0);
+ return rc;
}
/**@brief Compute 'goal' for allocation algorithm.
* @return error code
*/
static int ext4_balloc_find_goal(struct ext4_inode_ref *inode_ref,
- uint32_t *goal)
+ uint32_t *goal)
{
- struct ext4_sblock *sb = &inode_ref->fs->sb;
- *goal = 0;
-
- uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
- uint32_t block_size = ext4_sb_get_block_size(sb);
- uint32_t inode_block_count = inode_size / block_size;
-
- if (inode_size % block_size != 0)
- inode_block_count++;
-
- /* If inode has some blocks, get last block address + 1 */
- if (inode_block_count > 0) {
- int rc = ext4_fs_get_inode_data_block_index(
- inode_ref, inode_block_count - 1, goal);
- if (rc != EOK)
- return rc;
-
- if (*goal != 0) {
- (*goal)++;
- return rc;
- }
-
- /* If goal == 0, sparse file -> continue */
- }
-
- /* Identify block group of inode */
-
- uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);
- uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
- block_size = ext4_sb_get_block_size(sb);
-
- /* Load block group reference */
- struct ext4_block_group_ref bg_ref;
- int rc = ext4_fs_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
- if (rc != EOK)
- return rc;
-
- /* Compute indexes */
- uint32_t block_group_count = ext4_block_group_cnt(sb);
- uint32_t inode_table_first_block =
- ext4_bg_get_inode_table_first_block(bg_ref.block_group, sb);
- uint16_t inode_table_item_size = ext4_get16(sb, inode_size);
- uint32_t inode_table_bytes;
-
- /* Check for last block group */
- if (block_group < block_group_count - 1) {
- inode_table_bytes = inodes_per_group * inode_table_item_size;
- } else {
- /* Last block group could be smaller */
- uint32_t inodes_count_total = ext4_get32(sb, inodes_count);
-
- inode_table_bytes = (inodes_count_total -
- ((block_group_count - 1) * inodes_per_group)) *
- inode_table_item_size;
- }
-
- uint32_t inode_table_blocks = inode_table_bytes / block_size;
-
- if (inode_table_bytes % block_size)
- inode_table_blocks++;
-
- *goal = inode_table_first_block + inode_table_blocks;
-
- return ext4_fs_put_block_group_ref(&bg_ref);
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+ *goal = 0;
+
+ uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+ uint32_t inode_block_count = inode_size / block_size;
+
+ if (inode_size % block_size != 0)
+ inode_block_count++;
+
+ /* If inode has some blocks, get last block address + 1 */
+ if (inode_block_count > 0) {
+ int rc = ext4_fs_get_inode_data_block_index(
+ inode_ref, inode_block_count - 1, goal);
+ if (rc != EOK)
+ return rc;
+
+ if (*goal != 0) {
+ (*goal)++;
+ return rc;
+ }
+
+ /* If goal == 0, sparse file -> continue */
+ }
+
+ /* Identify block group of inode */
+
+ uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);
+ uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
+ block_size = ext4_sb_get_block_size(sb);
+
+ /* Load block group reference */
+ struct ext4_block_group_ref bg_ref;
+ int rc =
+ ext4_fs_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
+ if (rc != EOK)
+ return rc;
+
+ /* Compute indexes */
+ uint32_t block_group_count = ext4_block_group_cnt(sb);
+ uint32_t inode_table_first_block =
+ ext4_bg_get_inode_table_first_block(bg_ref.block_group, sb);
+ uint16_t inode_table_item_size = ext4_get16(sb, inode_size);
+ uint32_t inode_table_bytes;
+
+ /* Check for last block group */
+ if (block_group < block_group_count - 1) {
+ inode_table_bytes = inodes_per_group * inode_table_item_size;
+ } else {
+ /* Last block group could be smaller */
+ uint32_t inodes_count_total = ext4_get32(sb, inodes_count);
+
+ inode_table_bytes =
+ (inodes_count_total -
+ ((block_group_count - 1) * inodes_per_group)) *
+ inode_table_item_size;
+ }
+
+ uint32_t inode_table_blocks = inode_table_bytes / block_size;
+
+ if (inode_table_bytes % block_size)
+ inode_table_blocks++;
+
+ *goal = inode_table_first_block + inode_table_blocks;
+
+ return ext4_fs_put_block_group_ref(&bg_ref);
}
int ext4_balloc_alloc_block(struct ext4_inode_ref *inode_ref, uint32_t *fblock)
{
- uint32_t allocated_block = 0;
- uint32_t bitmap_block_addr;
- uint32_t rel_block_idx = 0;
- uint32_t free_blocks;
- uint32_t goal;
- struct ext4_block bitmap_block;
-
- int rc = ext4_balloc_find_goal(inode_ref, &goal);
- if (rc != EOK) {
- /* no goal found => partition is full */
- return rc;
- }
-
- struct ext4_sblock *sb = &inode_ref->fs->sb;
-
- /* Load block group number for goal and relative index */
- uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, goal);
- uint32_t index_in_group = ext4_fs_baddr2_index_in_group(sb, goal);
-
- /* Load block group reference */
- struct ext4_block_group_ref bg_ref;
- rc = ext4_fs_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
- if (rc != EOK)
- return rc;
-
- free_blocks = ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
- if (free_blocks == 0) {
- /* This group has no free blocks */
- goto goal_failed;
- }
-
- /* Compute indexes */
- uint32_t first_in_group =
- ext4_balloc_get_first_data_block_in_group(sb, &bg_ref);
-
- uint32_t first_in_group_index =
- ext4_fs_baddr2_index_in_group(sb, first_in_group);
-
- if (index_in_group < first_in_group_index)
- index_in_group = first_in_group_index;
-
- /* Load block with bitmap */
- bitmap_block_addr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
-
- rc = ext4_block_get(inode_ref->fs->bdev, &bitmap_block, bitmap_block_addr);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- /* Check if goal is free */
- if (ext4_bmap_is_bit_clr(bitmap_block.data, index_in_group)) {
- ext4_bmap_bit_set(bitmap_block.data, index_in_group);
- bitmap_block.dirty = true;
- rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- allocated_block =
- ext4_fs_index_in_group2_baddr(sb, index_in_group, block_group);
-
- goto success;
- }
-
- uint32_t blocks_in_group = ext4_blocks_in_group_cnt(sb, block_group);
-
- uint32_t end_idx = (index_in_group + 63) & ~63;
- if (end_idx > blocks_in_group)
- end_idx = blocks_in_group;
-
- /* Try to find free block near to goal */
- uint32_t tmp_idx;
- for (tmp_idx = index_in_group + 1; tmp_idx < end_idx; ++tmp_idx) {
- if (ext4_bmap_is_bit_clr(bitmap_block.data, tmp_idx)) {
- ext4_bmap_bit_set(bitmap_block.data, tmp_idx);
-
- bitmap_block.dirty = true;
- rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
- if (rc != EOK)
- return rc;
-
- allocated_block =
- ext4_fs_index_in_group2_baddr(sb, tmp_idx, block_group);
-
- goto success;
- }
- }
-
- /* Find free bit in bitmap */
- rc = ext4_bmap_bit_find_clr(bitmap_block.data, index_in_group,
- blocks_in_group, &rel_block_idx);
- if (rc == EOK) {
- ext4_bmap_bit_set(bitmap_block.data, rel_block_idx);
- bitmap_block.dirty = true;
- rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
- if (rc != EOK)
- return rc;
-
- allocated_block =
- ext4_fs_index_in_group2_baddr(sb, rel_block_idx, block_group);
-
- goto success;
- }
-
- /* No free block found yet */
- rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
+ uint32_t allocated_block = 0;
+ uint32_t bitmap_block_addr;
+ uint32_t rel_block_idx = 0;
+ uint32_t free_blocks;
+ uint32_t goal;
+ struct ext4_block bitmap_block;
+
+ int rc = ext4_balloc_find_goal(inode_ref, &goal);
+ if (rc != EOK) {
+ /* no goal found => partition is full */
+ return rc;
+ }
+
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+
+ /* Load block group number for goal and relative index */
+ uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, goal);
+ uint32_t index_in_group = ext4_fs_baddr2_index_in_group(sb, goal);
+
+ /* Load block group reference */
+ struct ext4_block_group_ref bg_ref;
+ rc = ext4_fs_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
+ if (rc != EOK)
+ return rc;
+
+ free_blocks = ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+ if (free_blocks == 0) {
+ /* This group has no free blocks */
+ goto goal_failed;
+ }
+
+ /* Compute indexes */
+ uint32_t first_in_group =
+ ext4_balloc_get_first_data_block_in_group(sb, &bg_ref);
+
+ uint32_t first_in_group_index =
+ ext4_fs_baddr2_index_in_group(sb, first_in_group);
+
+ if (index_in_group < first_in_group_index)
+ index_in_group = first_in_group_index;
+
+ /* Load block with bitmap */
+ bitmap_block_addr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
+
+ rc = ext4_block_get(inode_ref->fs->bdev, &bitmap_block,
+ bitmap_block_addr);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ /* Check if goal is free */
+ if (ext4_bmap_is_bit_clr(bitmap_block.data, index_in_group)) {
+ ext4_bmap_bit_set(bitmap_block.data, index_in_group);
+ bitmap_block.dirty = true;
+ rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ allocated_block = ext4_fs_index_in_group2_baddr(
+ sb, index_in_group, block_group);
+
+ goto success;
+ }
+
+ uint32_t blocks_in_group = ext4_blocks_in_group_cnt(sb, block_group);
+
+ uint32_t end_idx = (index_in_group + 63) & ~63;
+ if (end_idx > blocks_in_group)
+ end_idx = blocks_in_group;
+
+ /* Try to find free block near to goal */
+ uint32_t tmp_idx;
+ for (tmp_idx = index_in_group + 1; tmp_idx < end_idx; ++tmp_idx) {
+ if (ext4_bmap_is_bit_clr(bitmap_block.data, tmp_idx)) {
+ ext4_bmap_bit_set(bitmap_block.data, tmp_idx);
+
+ bitmap_block.dirty = true;
+ rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+ if (rc != EOK)
+ return rc;
+
+ allocated_block = ext4_fs_index_in_group2_baddr(
+ sb, tmp_idx, block_group);
+
+ goto success;
+ }
+ }
+
+ /* Find free bit in bitmap */
+ rc = ext4_bmap_bit_find_clr(bitmap_block.data, index_in_group,
+ blocks_in_group, &rel_block_idx);
+ if (rc == EOK) {
+ ext4_bmap_bit_set(bitmap_block.data, rel_block_idx);
+ bitmap_block.dirty = true;
+ rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+ if (rc != EOK)
+ return rc;
+
+ allocated_block = ext4_fs_index_in_group2_baddr(
+ sb, rel_block_idx, block_group);
+
+ goto success;
+ }
+
+ /* No free block found yet */
+ rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
goal_failed:
- rc = ext4_fs_put_block_group_ref(&bg_ref);
- if (rc != EOK)
- return rc;
+ rc = ext4_fs_put_block_group_ref(&bg_ref);
+ if (rc != EOK)
+ return rc;
- /* Try other block groups */
- uint32_t block_group_count = ext4_block_group_cnt(sb);
+ /* Try other block groups */
+ uint32_t block_group_count = ext4_block_group_cnt(sb);
- uint32_t bgid = (block_group + 1) % block_group_count;
- uint32_t count = block_group_count;
+ uint32_t bgid = (block_group + 1) % block_group_count;
+ uint32_t count = block_group_count;
- while (count > 0) {
- rc = ext4_fs_get_block_group_ref(inode_ref->fs, bgid, &bg_ref);
- if (rc != EOK)
- return rc;
+ while (count > 0) {
+ rc = ext4_fs_get_block_group_ref(inode_ref->fs, bgid, &bg_ref);
+ if (rc != EOK)
+ return rc;
- free_blocks = ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
- if (free_blocks == 0) {
- /* This group has no free blocks */
- goto next_group;
- }
+ free_blocks =
+ ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+ if (free_blocks == 0) {
+ /* This group has no free blocks */
+ goto next_group;
+ }
- /* Load block with bitmap */
- bitmap_block_addr = ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
+ /* Load block with bitmap */
+ bitmap_block_addr =
+ ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
- rc = ext4_block_get(inode_ref->fs->bdev, &bitmap_block,
- bitmap_block_addr);
+ rc = ext4_block_get(inode_ref->fs->bdev, &bitmap_block,
+ bitmap_block_addr);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
- /* Compute indexes */
- first_in_group = ext4_balloc_get_first_data_block_in_group(sb, &bg_ref);
- index_in_group = ext4_fs_baddr2_index_in_group(sb, first_in_group);
- blocks_in_group = ext4_blocks_in_group_cnt(sb, bgid);
+ /* Compute indexes */
+ first_in_group =
+ ext4_balloc_get_first_data_block_in_group(sb, &bg_ref);
+ index_in_group =
+ ext4_fs_baddr2_index_in_group(sb, first_in_group);
+ blocks_in_group = ext4_blocks_in_group_cnt(sb, bgid);
- first_in_group_index =
- ext4_fs_baddr2_index_in_group(sb, first_in_group);
+ first_in_group_index =
+ ext4_fs_baddr2_index_in_group(sb, first_in_group);
- if (index_in_group < first_in_group_index)
- index_in_group = first_in_group_index;
+ if (index_in_group < first_in_group_index)
+ index_in_group = first_in_group_index;
- rc = ext4_bmap_bit_find_clr(bitmap_block.data, index_in_group,
- blocks_in_group, &rel_block_idx);
+ rc = ext4_bmap_bit_find_clr(bitmap_block.data, index_in_group,
+ blocks_in_group, &rel_block_idx);
- if (rc == EOK) {
+ if (rc == EOK) {
- ext4_bmap_bit_set(bitmap_block.data, rel_block_idx);
+ ext4_bmap_bit_set(bitmap_block.data, rel_block_idx);
- bitmap_block.dirty = true;
- rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
+ bitmap_block.dirty = true;
+ rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
- allocated_block =
- ext4_fs_index_in_group2_baddr(sb, rel_block_idx, bgid);
+ allocated_block = ext4_fs_index_in_group2_baddr(
+ sb, rel_block_idx, bgid);
- goto success;
- }
+ goto success;
+ }
- rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
+ rc = ext4_block_set(inode_ref->fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
- next_group:
- rc = ext4_fs_put_block_group_ref(&bg_ref);
- if (rc != EOK) {
- return rc;
- }
+ next_group:
+ rc = ext4_fs_put_block_group_ref(&bg_ref);
+ if (rc != EOK) {
+ return rc;
+ }
- /* Goto next group */
- bgid = (bgid + 1) % block_group_count;
- count--;
- }
+ /* Goto next group */
+ bgid = (bgid + 1) % block_group_count;
+ count--;
+ }
- return ENOSPC;
+ return ENOSPC;
success:
/* Empty command - because of syntax */
;
- uint32_t block_size = ext4_sb_get_block_size(sb);
+ uint32_t block_size = ext4_sb_get_block_size(sb);
- /* Update superblock free blocks count */
- uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
- sb_free_blocks--;
- ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
+ /* Update superblock free blocks count */
+ uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
+ sb_free_blocks--;
+ ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
- /* Update inode blocks (different block size!) count */
- uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
- ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
- ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
- inode_ref->dirty = true;
+ /* Update inode blocks (different block size!) count */
+ uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
+ ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
+ ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+ inode_ref->dirty = true;
- /* Update block group free blocks count */
- uint32_t bg_free_blocks =
- ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
- bg_free_blocks--;
- ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, bg_free_blocks);
+ /* Update block group free blocks count */
+ uint32_t bg_free_blocks =
+ ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+ bg_free_blocks--;
+ ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, bg_free_blocks);
- bg_ref.dirty = true;
+ bg_ref.dirty = true;
- rc = ext4_fs_put_block_group_ref(&bg_ref);
+ rc = ext4_fs_put_block_group_ref(&bg_ref);
- *fblock = allocated_block;
- return rc;
+ *fblock = allocated_block;
+ return rc;
}
int ext4_balloc_try_alloc_block(struct ext4_inode_ref *inode_ref,
- uint32_t baddr, bool *free)
+ uint32_t baddr, bool *free)
{
- int rc;
-
- struct ext4_fs *fs = inode_ref->fs;
- struct ext4_sblock *sb = &fs->sb;
-
- /* Compute indexes */
- uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, baddr);
- uint32_t index_in_group = ext4_fs_baddr2_index_in_group(sb, baddr);
-
- /* Load block group reference */
- struct ext4_block_group_ref bg_ref;
- rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);
- if (rc != EOK)
- return rc;
-
- /* Load block with bitmap */
- uint32_t bitmap_block_addr =
- ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
-
- struct ext4_block bitmap_block;
-
- rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
- if (rc != EOK) {
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- /* Check if block is free */
- *free = ext4_bmap_is_bit_clr(bitmap_block.data, index_in_group);
-
- /* Allocate block if possible */
- if (*free) {
- ext4_bmap_bit_set(bitmap_block.data, index_in_group);
- bitmap_block.dirty = true;
- }
-
- /* Release block with bitmap */
- rc = ext4_block_set(fs->bdev, &bitmap_block);
- if (rc != EOK) {
- /* Error in saving bitmap */
- ext4_fs_put_block_group_ref(&bg_ref);
- return rc;
- }
-
- /* If block is not free, return */
- if (!(*free))
- goto terminate;
-
- uint32_t block_size = ext4_sb_get_block_size(sb);
-
- /* Update superblock free blocks count */
- uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
- sb_free_blocks--;
- ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
-
- /* Update inode blocks count */
- uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
- ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
- ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
- inode_ref->dirty = true;
-
- /* Update block group free blocks count */
- uint32_t free_blocks =
- ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
- free_blocks--;
- ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, free_blocks);
-
- bg_ref.dirty = true;
+ int rc;
+
+ struct ext4_fs *fs = inode_ref->fs;
+ struct ext4_sblock *sb = &fs->sb;
+
+ /* Compute indexes */
+ uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, baddr);
+ uint32_t index_in_group = ext4_fs_baddr2_index_in_group(sb, baddr);
+
+ /* Load block group reference */
+ struct ext4_block_group_ref bg_ref;
+ rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);
+ if (rc != EOK)
+ return rc;
+
+ /* Load block with bitmap */
+ uint32_t bitmap_block_addr =
+ ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
+
+ struct ext4_block bitmap_block;
+
+ rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);
+ if (rc != EOK) {
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ /* Check if block is free */
+ *free = ext4_bmap_is_bit_clr(bitmap_block.data, index_in_group);
+
+ /* Allocate block if possible */
+ if (*free) {
+ ext4_bmap_bit_set(bitmap_block.data, index_in_group);
+ bitmap_block.dirty = true;
+ }
+
+ /* Release block with bitmap */
+ rc = ext4_block_set(fs->bdev, &bitmap_block);
+ if (rc != EOK) {
+ /* Error in saving bitmap */
+ ext4_fs_put_block_group_ref(&bg_ref);
+ return rc;
+ }
+
+ /* If block is not free, return */
+ if (!(*free))
+ goto terminate;
+
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+
+ /* Update superblock free blocks count */
+ uint64_t sb_free_blocks = ext4_sb_get_free_blocks_cnt(sb);
+ sb_free_blocks--;
+ ext4_sb_set_free_blocks_cnt(sb, sb_free_blocks);
+
+ /* Update inode blocks count */
+ uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
+ ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
+ ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
+ inode_ref->dirty = true;
+
+ /* Update block group free blocks count */
+ uint32_t free_blocks =
+ ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
+ free_blocks--;
+ ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, free_blocks);
+
+ bg_ref.dirty = true;
terminate:
- return ext4_fs_put_block_group_ref(&bg_ref);
+ return ext4_fs_put_block_group_ref(&bg_ref);
}
/**
* @return block id of the first datablock in block group*/
uint32_t
ext4_balloc_get_first_data_block_in_group(struct ext4_sblock *s,
- struct ext4_block_group_ref *bg_ref);
+ struct ext4_block_group_ref *bg_ref);
/**@brief Free block from inode.
* @param inode_ref inode reference
* @param baddr block address
* @return standard error code*/
int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, uint32_t first,
- uint32_t count);
+ uint32_t count);
/**@brief Allocate block procedure.
* @param inode_ref inode reference
* @param free if baddr is not allocated
* @return standard error code*/
int ext4_balloc_try_alloc_block(struct ext4_inode_ref *inode_ref,
- uint32_t baddr, bool *free);
+ uint32_t baddr, bool *free);
#endif /* EXT4_BALLOC_H_ */
#include <stdlib.h>\r
\r
int ext4_bcache_init_dynamic(struct ext4_bcache *bc, uint32_t cnt,\r
- uint32_t itemsize)\r
+ uint32_t itemsize)\r
{\r
- ext4_assert(bc && cnt && itemsize);\r
+ ext4_assert(bc && cnt && itemsize);\r
\r
- memset(bc, 0, sizeof(struct ext4_bcache));\r
+ memset(bc, 0, sizeof(struct ext4_bcache));\r
\r
- bc->data = malloc(cnt * itemsize);\r
- if (!bc->data)\r
- goto error;\r
+ bc->data = malloc(cnt * itemsize);\r
+ if (!bc->data)\r
+ goto error;\r
\r
- bc->cnt = cnt;\r
- bc->itemsize = itemsize;\r
- bc->ref_blocks = 0;\r
- bc->max_ref_blocks = 0;\r
+ bc->cnt = cnt;\r
+ bc->itemsize = itemsize;\r
+ bc->ref_blocks = 0;\r
+ bc->max_ref_blocks = 0;\r
\r
- return EOK;\r
+ return EOK;\r
\r
error:\r
\r
- if (bc->data)\r
- free(bc->data);\r
+ if (bc->data)\r
+ free(bc->data);\r
\r
- memset(bc, 0, sizeof(struct ext4_bcache));\r
+ memset(bc, 0, sizeof(struct ext4_bcache));\r
\r
- return ENOMEM;\r
+ return ENOMEM;\r
}\r
\r
int ext4_bcache_fini_dynamic(struct ext4_bcache *bc)\r
{\r
- if (bc->data)\r
- free(bc->data);\r
+ if (bc->data)\r
+ free(bc->data);\r
\r
- memset(bc, 0, sizeof(struct ext4_bcache));\r
+ memset(bc, 0, sizeof(struct ext4_bcache));\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
int ext4_bcache_alloc(struct ext4_bcache *bc, struct ext4_block *b,\r
- bool *is_new)\r
+ bool *is_new)\r
{\r
- uint32_t i;\r
- ext4_assert(bc && b && is_new);\r
+ uint32_t i;\r
+ ext4_assert(bc && b && is_new);\r
\r
- /*Check if valid.*/\r
- ext4_assert(b->lb_id);\r
- if (!b->lb_id) {\r
- ext4_assert(b->lb_id);\r
- }\r
+ /*Check if valid.*/\r
+ ext4_assert(b->lb_id);\r
+ if (!b->lb_id) {\r
+ ext4_assert(b->lb_id);\r
+ }\r
\r
- uint32_t cache_id = bc->cnt;\r
- uint32_t alloc_id = 0;\r
+ uint32_t cache_id = bc->cnt;\r
+ uint32_t alloc_id = 0;\r
\r
- *is_new = false;\r
+ *is_new = false;\r
\r
- /*Find in free blocks (Last Recently Used).*/\r
- for (i = 0; i < bc->cnt; ++i) {\r
+ /*Find in free blocks (Last Recently Used).*/\r
+ for (i = 0; i < bc->cnt; ++i) {\r
\r
- /*Check if block is already in cache*/\r
- if (b->lb_id == bc->lba[i]) {\r
+ /*Check if block is already in cache*/\r
+ if (b->lb_id == bc->lba[i]) {\r
\r
- if (!bc->refctr[i] && !bc->free_delay[i])\r
- bc->ref_blocks++;\r
+ if (!bc->refctr[i] && !bc->free_delay[i])\r
+ bc->ref_blocks++;\r
\r
- /*Update reference counter*/\r
- bc->refctr[i]++;\r
+ /*Update reference counter*/\r
+ bc->refctr[i]++;\r
\r
- /*Update usage marker*/\r
- bc->lru_id[i] = ++bc->lru_ctr;\r
+ /*Update usage marker*/\r
+ bc->lru_id[i] = ++bc->lru_ctr;\r
\r
- /*Set valid cache data and id*/\r
- b->data = bc->data + i * bc->itemsize;\r
- b->cache_id = i;\r
+ /*Set valid cache data and id*/\r
+ b->data = bc->data + i * bc->itemsize;\r
+ b->cache_id = i;\r
\r
- return EOK;\r
- }\r
+ return EOK;\r
+ }\r
\r
- /*Best fit calculations.*/\r
- if (bc->refctr[i])\r
- continue;\r
+ /*Best fit calculations.*/\r
+ if (bc->refctr[i])\r
+ continue;\r
\r
- if (bc->free_delay[i])\r
- continue;\r
+ if (bc->free_delay[i])\r
+ continue;\r
\r
- /*Block is unreferenced, but it may exist block with\r
- * lower usage marker*/\r
+ /*Block is unreferenced, but it may exist block with\r
+ * lower usage marker*/\r
\r
- /*First find.*/\r
- if (cache_id == bc->cnt) {\r
- cache_id = i;\r
- alloc_id = bc->lru_id[i];\r
- continue;\r
- }\r
+ /*First find.*/\r
+ if (cache_id == bc->cnt) {\r
+ cache_id = i;\r
+ alloc_id = bc->lru_id[i];\r
+ continue;\r
+ }\r
\r
- /*Next find*/\r
- if (alloc_id <= bc->lru_id[i])\r
- continue;\r
+ /*Next find*/\r
+ if (alloc_id <= bc->lru_id[i])\r
+ continue;\r
\r
- /*This block has lower alloc id marker*/\r
- cache_id = i;\r
- alloc_id = bc->lru_id[i];\r
- }\r
+ /*This block has lower alloc id marker*/\r
+ cache_id = i;\r
+ alloc_id = bc->lru_id[i];\r
+ }\r
\r
- if (cache_id != bc->cnt) {\r
- /*There was unreferenced block*/\r
- bc->lba[cache_id] = b->lb_id;\r
- bc->refctr[cache_id] = 1;\r
- bc->lru_id[cache_id] = ++bc->lru_ctr;\r
+ if (cache_id != bc->cnt) {\r
+ /*There was unreferenced block*/\r
+ bc->lba[cache_id] = b->lb_id;\r
+ bc->refctr[cache_id] = 1;\r
+ bc->lru_id[cache_id] = ++bc->lru_ctr;\r
\r
- /*Set valid cache data and id*/\r
- b->data = bc->data + cache_id * bc->itemsize;\r
- b->cache_id = cache_id;\r
+ /*Set valid cache data and id*/\r
+ b->data = bc->data + cache_id * bc->itemsize;\r
+ b->cache_id = cache_id;\r
\r
- /*Statistics*/\r
- bc->ref_blocks++;\r
- if (bc->ref_blocks > bc->max_ref_blocks)\r
- bc->max_ref_blocks = bc->ref_blocks;\r
+ /*Statistics*/\r
+ bc->ref_blocks++;\r
+ if (bc->ref_blocks > bc->max_ref_blocks)\r
+ bc->max_ref_blocks = bc->ref_blocks;\r
\r
- /*Block needs to be read.*/\r
- *is_new = true;\r
+ /*Block needs to be read.*/\r
+ *is_new = true;\r
\r
- return EOK;\r
- }\r
+ return EOK;\r
+ }\r
\r
- ext4_dprintf(EXT4_DEBUG_BCACHE,\r
- "ext4_bcache_alloc: FAIL, unable to alloc block cache!\n");\r
- return ENOMEM;\r
+ ext4_dprintf(EXT4_DEBUG_BCACHE,\r
+ "ext4_bcache_alloc: FAIL, unable to alloc block cache!\n");\r
+ return ENOMEM;\r
}\r
\r
int ext4_bcache_free(struct ext4_bcache *bc, struct ext4_block *b,\r
- uint8_t free_delay)\r
+ uint8_t free_delay)\r
{\r
- ext4_assert(bc && b);\r
+ ext4_assert(bc && b);\r
\r
- /*Check if valid.*/\r
- ext4_assert(b->lb_id);\r
+ /*Check if valid.*/\r
+ ext4_assert(b->lb_id);\r
\r
- /*Block should be in cache.*/\r
- ext4_assert(b->cache_id < bc->cnt);\r
+ /*Block should be in cache.*/\r
+ ext4_assert(b->cache_id < bc->cnt);\r
\r
- /*Check if someone don't try free unreferenced block cache.*/\r
- ext4_assert(bc->refctr[b->cache_id]);\r
+ /*Check if someone don't try free unreferenced block cache.*/\r
+ ext4_assert(bc->refctr[b->cache_id]);\r
\r
- /*Just decrease reference counter*/\r
- if (bc->refctr[b->cache_id])\r
- bc->refctr[b->cache_id]--;\r
+ /*Just decrease reference counter*/\r
+ if (bc->refctr[b->cache_id])\r
+ bc->refctr[b->cache_id]--;\r
\r
- if (free_delay)\r
- bc->free_delay[b->cache_id] = free_delay;\r
+ if (free_delay)\r
+ bc->free_delay[b->cache_id] = free_delay;\r
\r
- /*Update statistics*/\r
- if (!bc->refctr[b->cache_id] && !bc->free_delay[b->cache_id])\r
- bc->ref_blocks--;\r
+ /*Update statistics*/\r
+ if (!bc->refctr[b->cache_id] && !bc->free_delay[b->cache_id])\r
+ bc->ref_blocks--;\r
\r
- b->lb_id = 0;\r
- b->data = 0;\r
- b->cache_id = 0;\r
+ b->lb_id = 0;\r
+ b->data = 0;\r
+ b->cache_id = 0;\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
bool ext4_bcache_is_full(struct ext4_bcache *bc)\r
{\r
- return (bc->cnt == bc->ref_blocks);\r
+ return (bc->cnt == bc->ref_blocks);\r
}\r
\r
/**\r
\r
/**@brief Single block descriptor*/\r
struct ext4_block {\r
- /**@brief Dirty flag*/\r
- bool dirty;\r
+ /**@brief Dirty flag*/\r
+ bool dirty;\r
\r
- /**@brief Logical block ID*/\r
- uint64_t lb_id;\r
+ /**@brief Logical block ID*/\r
+ uint64_t lb_id;\r
\r
- /**@brief Cache id*/\r
- uint32_t cache_id;\r
+ /**@brief Cache id*/\r
+ uint32_t cache_id;\r
\r
- /**@brief Data buffer.*/\r
- uint8_t *data;\r
+ /**@brief Data buffer.*/\r
+ uint8_t *data;\r
};\r
\r
/**@brief Block cache descriptor*/\r
struct ext4_bcache {\r
\r
- /**@brief Item count in block cache*/\r
- uint32_t cnt;\r
+ /**@brief Item count in block cache*/\r
+ uint32_t cnt;\r
\r
- /**@brief Item size in block cache*/\r
- uint32_t itemsize;\r
+ /**@brief Item size in block cache*/\r
+ uint32_t itemsize;\r
\r
- /**@brief Last recently used counter*/\r
- uint32_t lru_ctr;\r
+ /**@brief Last recently used counter*/\r
+ uint32_t lru_ctr;\r
\r
- /**@brief Reference count table*/\r
- uint32_t refctr[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
+ /**@brief Reference count table*/\r
+ uint32_t refctr[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
\r
- /**@brief Last recently used ID table*/\r
- uint32_t lru_id[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
+ /**@brief Last recently used ID table*/\r
+ uint32_t lru_id[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
\r
- /**@brief Writeback free delay mode table*/\r
- uint8_t free_delay[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
+ /**@brief Writeback free delay mode table*/\r
+ uint8_t free_delay[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
\r
- /**@brief Logical block table*/\r
- uint64_t lba[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
+ /**@brief Logical block table*/\r
+ uint64_t lba[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
\r
- /**@brief Dirty mark*/\r
- bool dirty[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
+ /**@brief Dirty mark*/\r
+ bool dirty[CONFIG_BLOCK_DEV_CACHE_SIZE];\r
\r
- /**@brief Cache data buffers*/\r
- uint8_t *data;\r
+ /**@brief Cache data buffers*/\r
+ uint8_t *data;\r
\r
- /**@brief Currently referenced datablocks*/\r
- uint32_t ref_blocks;\r
+ /**@brief Currently referenced datablocks*/\r
+ uint32_t ref_blocks;\r
\r
- /**@brief Maximum referenced datablocks*/\r
- uint32_t max_ref_blocks;\r
+ /**@brief Maximum referenced datablocks*/\r
+ uint32_t max_ref_blocks;\r
};\r
\r
/**@brief Static initializer of block cache structure.*/\r
#define EXT4_BCACHE_STATIC_INSTANCE(__name, __cnt, __itemsize) \\r
- static uint8_t __name##_data[(__cnt) * (__itemsize)]; \\r
- static struct ext4_bcache __name = { \\r
- .cnt = __cnt, \\r
- .itemsize = __itemsize, \\r
- .lru_ctr = 0, \\r
- .data = __name##_data, \\r
- }\r
+ static uint8_t __name##_data[(__cnt) * (__itemsize)]; \\r
+ static struct ext4_bcache __name = { \\r
+ .cnt = __cnt, \\r
+ .itemsize = __itemsize, \\r
+ .lru_ctr = 0, \\r
+ .data = __name##_data, \\r
+ }\r
\r
/**@brief Dynamic initialization of block cache.\r
* @param bc block cache descriptor\r
* @param itemsize single item size (in bytes)\r
* @return standard error code*/\r
int ext4_bcache_init_dynamic(struct ext4_bcache *bc, uint32_t cnt,\r
- uint32_t itemsize);\r
+ uint32_t itemsize);\r
\r
/**@brief Dynamic de-initialization of block cache.\r
* @param bc block cache descriptor\r
* @param is_new block is new (needs to be read)\r
* @return standard error code*/\r
int ext4_bcache_alloc(struct ext4_bcache *bc, struct ext4_block *b,\r
- bool *is_new);\r
+ bool *is_new);\r
\r
/**@brief Free block from cache memory (decrement reference counter).\r
* @param bc block cache descriptor\r
* @param cache writeback mode\r
* @return standard error code*/\r
int ext4_bcache_free(struct ext4_bcache *bc, struct ext4_block *b,\r
- uint8_t free_delay);\r
+ uint8_t free_delay);\r
\r
/**@brief Return a full status of block cache.\r
* @param bc block cache descriptor\r
void ext4_bmap_bits_free(uint8_t *bmap, uint32_t sbit, uint32_t bcnt)
{
- uint32_t i = sbit;
-
- while (i & 7) {
-
- if (!bcnt)
- return;
-
- ext4_bmap_bit_clr(bmap, i);
-
- bcnt--;
- i++;
- }
- sbit = i;
- bmap += (sbit >> 3);
-
- while (bcnt >= 32) {
- *(uint32_t *)bmap = 0;
- bmap += 4;
- bcnt -= 32;
- sbit += 32;
- }
-
- while (bcnt >= 16) {
- *(uint16_t *)bmap = 0;
- bmap += 2;
- bcnt -= 16;
- sbit += 16;
- }
-
- while (bcnt >= 8) {
- *bmap = 0;
- bmap += 1;
- bcnt -= 8;
- sbit += 8;
- }
-
- for (i = 0; i < bcnt; ++i) {
- ext4_bmap_bit_clr(bmap, i);
- }
+ uint32_t i = sbit;
+
+ while (i & 7) {
+
+ if (!bcnt)
+ return;
+
+ ext4_bmap_bit_clr(bmap, i);
+
+ bcnt--;
+ i++;
+ }
+ sbit = i;
+ bmap += (sbit >> 3);
+
+ while (bcnt >= 32) {
+ *(uint32_t *)bmap = 0;
+ bmap += 4;
+ bcnt -= 32;
+ sbit += 32;
+ }
+
+ while (bcnt >= 16) {
+ *(uint16_t *)bmap = 0;
+ bmap += 2;
+ bcnt -= 16;
+ sbit += 16;
+ }
+
+ while (bcnt >= 8) {
+ *bmap = 0;
+ bmap += 1;
+ bcnt -= 8;
+ sbit += 8;
+ }
+
+ for (i = 0; i < bcnt; ++i) {
+ ext4_bmap_bit_clr(bmap, i);
+ }
}
int ext4_bmap_bit_find_clr(uint8_t *bmap, uint32_t sbit, uint32_t ebit,
- uint32_t *bit_id)
+ uint32_t *bit_id)
{
- uint32_t i;
- uint32_t bcnt = ebit - sbit;
+ uint32_t i;
+ uint32_t bcnt = ebit - sbit;
- i = sbit;
+ i = sbit;
- while (i & 7) {
+ while (i & 7) {
- if (!bcnt)
- return ENOSPC;
+ if (!bcnt)
+ return ENOSPC;
- if (ext4_bmap_is_bit_clr(bmap, i)) {
- *bit_id = sbit;
- return EOK;
- }
+ if (ext4_bmap_is_bit_clr(bmap, i)) {
+ *bit_id = sbit;
+ return EOK;
+ }
- i++;
- bcnt--;
- }
+ i++;
+ bcnt--;
+ }
- sbit = i;
- bmap += (sbit >> 3);
+ sbit = i;
+ bmap += (sbit >> 3);
- while (bcnt >= 32) {
- if (*(uint32_t *)bmap != 0xFFFFFFFF)
- goto finish_it;
+ while (bcnt >= 32) {
+ if (*(uint32_t *)bmap != 0xFFFFFFFF)
+ goto finish_it;
- bmap += 4;
- bcnt -= 32;
- sbit += 32;
- }
+ bmap += 4;
+ bcnt -= 32;
+ sbit += 32;
+ }
- while (bcnt >= 16) {
- if (*(uint16_t *)bmap != 0xFFFF)
- goto finish_it;
+ while (bcnt >= 16) {
+ if (*(uint16_t *)bmap != 0xFFFF)
+ goto finish_it;
- bmap += 2;
- bcnt -= 16;
- sbit += 16;
- }
+ bmap += 2;
+ bcnt -= 16;
+ sbit += 16;
+ }
finish_it:
- while (bcnt >= 8) {
- if (*bmap != 0xFF) {
- for (i = 0; i < 8; ++i) {
- if (ext4_bmap_is_bit_clr(bmap, i)) {
- *bit_id = sbit + i;
- return EOK;
- }
- }
- }
-
- bmap += 1;
- bcnt -= 8;
- sbit += 8;
- }
-
- for (i = 0; i < bcnt; ++i) {
- if (ext4_bmap_is_bit_clr(bmap, i)) {
- *bit_id = sbit + i;
- return EOK;
- }
- }
-
- return ENOSPC;
+ while (bcnt >= 8) {
+ if (*bmap != 0xFF) {
+ for (i = 0; i < 8; ++i) {
+ if (ext4_bmap_is_bit_clr(bmap, i)) {
+ *bit_id = sbit + i;
+ return EOK;
+ }
+ }
+ }
+
+ bmap += 1;
+ bcnt -= 8;
+ sbit += 8;
+ }
+
+ for (i = 0; i < bcnt; ++i) {
+ if (ext4_bmap_is_bit_clr(bmap, i)) {
+ *bit_id = sbit + i;
+ return EOK;
+ }
+ }
+
+ return ENOSPC;
}
/**
* @param bit bit to set*/
static inline void ext4_bmap_bit_set(uint8_t *bmap, uint32_t bit)
{
- *(bmap + (bit >> 3)) |= (1 << (bit & 7));
+ *(bmap + (bit >> 3)) |= (1 << (bit & 7));
}
/**@brief Clear bitmap bit.
* @param bit bit to clear*/
static inline void ext4_bmap_bit_clr(uint8_t *bmap, uint32_t bit)
{
- *(bmap + (bit >> 3)) &= ~(1 << (bit & 7));
+ *(bmap + (bit >> 3)) &= ~(1 << (bit & 7));
}
/**@brief Check if the bitmap bit is set.
* @param bit bit to check*/
static inline bool ext4_bmap_is_bit_set(uint8_t *bmap, uint32_t bit)
{
- return (*(bmap + (bit >> 3)) & (1 << (bit & 7)));
+ return (*(bmap + (bit >> 3)) & (1 << (bit & 7)));
}
/**@brief Check if the bitmap bit is clear.
* @param bit bit to check*/
static inline bool ext4_bmap_is_bit_clr(uint8_t *bmap, uint32_t bit)
{
- return !ext4_bmap_is_bit_set(bmap, bit);
+ return !ext4_bmap_is_bit_set(bmap, bit);
}
/**@brief Free range of bits in bitmap.
* @param bit_id output parameter (first free bit)
* @return standard error code*/
int ext4_bmap_bit_find_clr(uint8_t *bmap, uint32_t sbit, uint32_t ebit,
- uint32_t *bit_id);
+ uint32_t *bit_id);
#endif /* EXT4_BITMAP_H_ */
uint16_t ext4_bg_crc16(uint16_t crc, const uint8_t *buffer, size_t len)
{
- while (len--)
+ while (len--)
- crc = (((crc >> 8) & 0xffU) ^ crc16_tab[(crc ^ *buffer++) & 0xffU]) &
- 0x0000ffffU;
- return crc;
+ crc = (((crc >> 8) & 0xffU) ^
+ crc16_tab[(crc ^ *buffer++) & 0xffU]) &
+ 0x0000ffffU;
+ return crc;
}
/**
* @return Address of block with block bitmap
*/
static inline uint64_t ext4_bg_get_block_bitmap(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint64_t v = to_le32(bg->block_bitmap_lo);
+ uint64_t v = to_le32(bg->block_bitmap_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint64_t)to_le32(bg->block_bitmap_hi) << 32;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint64_t)to_le32(bg->block_bitmap_hi) << 32;
- return v;
+ return v;
}
/**@brief Get address of block with i-node bitmap.
* @return Address of block with i-node bitmap
*/
static inline uint64_t ext4_bg_get_inode_bitmap(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint64_t v = to_le32(bg->inode_bitmap_lo);
+ uint64_t v = to_le32(bg->inode_bitmap_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint64_t)to_le32(bg->inode_bitmap_hi) << 32;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint64_t)to_le32(bg->inode_bitmap_hi) << 32;
- return v;
+ return v;
}
/**@brief Get address of the first block of the i-node table.
*/
static inline uint64_t
ext4_bg_get_inode_table_first_block(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint64_t v = to_le32(bg->inode_table_first_block_lo);
+ uint64_t v = to_le32(bg->inode_table_first_block_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint64_t)to_le32(bg->inode_table_first_block_hi) << 32;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint64_t)to_le32(bg->inode_table_first_block_hi) << 32;
- return v;
+ return v;
}
/**@brief Get number of free blocks in block group.
* @return Number of free blocks in block group
*/
static inline uint32_t ext4_bg_get_free_blocks_count(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint32_t v = to_le16(bg->free_blocks_count_lo);
+ uint32_t v = to_le16(bg->free_blocks_count_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint32_t)to_le16(bg->free_blocks_count_hi) << 16;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint32_t)to_le16(bg->free_blocks_count_hi) << 16;
- return v;
+ return v;
}
/**@brief Set number of free blocks in block group.
* @param cnt Number of free blocks in block group
*/
static inline void ext4_bg_set_free_blocks_count(struct ext4_bgroup *bg,
- struct ext4_sblock *s,
- uint32_t cnt)
+ struct ext4_sblock *s,
+ uint32_t cnt)
{
- bg->free_blocks_count_lo = to_le16((cnt << 16) >> 16);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- bg->free_blocks_count_hi = to_le16(cnt >> 16);
+ bg->free_blocks_count_lo = to_le16((cnt << 16) >> 16);
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ bg->free_blocks_count_hi = to_le16(cnt >> 16);
}
/**@brief Get number of free i-nodes in block group.
* @return Number of free i-nodes in block group
*/
static inline uint32_t ext4_bg_get_free_inodes_count(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint32_t v = to_le16(bg->free_inodes_count_lo);
+ uint32_t v = to_le16(bg->free_inodes_count_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint32_t)to_le16(bg->free_inodes_count_hi) << 16;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint32_t)to_le16(bg->free_inodes_count_hi) << 16;
- return v;
+ return v;
}
/**@brief Set number of free i-nodes in block group.
* @param cnt Number of free i-nodes in block group
*/
static inline void ext4_bg_set_free_inodes_count(struct ext4_bgroup *bg,
- struct ext4_sblock *s,
- uint32_t cnt)
+ struct ext4_sblock *s,
+ uint32_t cnt)
{
- bg->free_inodes_count_lo = to_le16((cnt << 16) >> 16);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- bg->free_inodes_count_hi = to_le16(cnt >> 16);
+ bg->free_inodes_count_lo = to_le16((cnt << 16) >> 16);
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ bg->free_inodes_count_hi = to_le16(cnt >> 16);
}
/**@brief Get number of used directories in block group.
* @return Number of used directories in block group
*/
static inline uint32_t ext4_bg_get_used_dirs_count(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint32_t v = to_le16(bg->used_dirs_count_lo);
+ uint32_t v = to_le16(bg->used_dirs_count_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint32_t)to_le16(bg->used_dirs_count_hi) << 16;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint32_t)to_le16(bg->used_dirs_count_hi) << 16;
- return v;
+ return v;
}
/**@brief Set number of used directories in block group.
* @param cnt Number of used directories in block group
*/
static inline void ext4_bg_set_used_dirs_count(struct ext4_bgroup *bg,
- struct ext4_sblock *s,
- uint32_t cnt)
+ struct ext4_sblock *s,
+ uint32_t cnt)
{
- bg->used_dirs_count_lo = to_le16((cnt << 16) >> 16);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- bg->used_dirs_count_hi = to_le16(cnt >> 16);
+ bg->used_dirs_count_lo = to_le16((cnt << 16) >> 16);
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ bg->used_dirs_count_hi = to_le16(cnt >> 16);
}
/**@brief Get number of unused i-nodes.
* @return Number of unused i-nodes
*/
static inline uint32_t ext4_bg_get_itable_unused(struct ext4_bgroup *bg,
- struct ext4_sblock *s)
+ struct ext4_sblock *s)
{
- uint32_t v = to_le16(bg->itable_unused_lo);
+ uint32_t v = to_le16(bg->itable_unused_lo);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- v |= (uint32_t)to_le16(bg->itable_unused_hi) << 16;
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ v |= (uint32_t)to_le16(bg->itable_unused_hi) << 16;
- return v;
+ return v;
}
/**@brief Set number of unused i-nodes.
* @param cnt Number of unused i-nodes
*/
static inline void ext4_bg_set_itable_unused(struct ext4_bgroup *bg,
- struct ext4_sblock *s,
- uint32_t cnt)
+ struct ext4_sblock *s,
+ uint32_t cnt)
{
- bg->itable_unused_lo = to_le16((cnt << 16) >> 16);
- if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- bg->itable_unused_hi = to_le16(cnt >> 16);
+ bg->itable_unused_lo = to_le16((cnt << 16) >> 16);
+ if (ext4_sb_get_desc_size(s) > EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ bg->itable_unused_hi = to_le16(cnt >> 16);
}
/**@brief Set checksum of block group.
*/
static inline void ext4_bg_set_checksum(struct ext4_bgroup *bg, uint16_t crc)
{
- bg->checksum = to_le16(crc);
+ bg->checksum = to_le16(crc);
}
/**@brief Check if block group has a flag.
*/
static inline bool ext4_bg_has_flag(struct ext4_bgroup *bg, uint32_t f)
{
- return to_le16(bg->flags) & f;
+ return to_le16(bg->flags) & f;
}
/**@brief Set flag of block group.
*/
static inline void ext4_bg_set_flag(struct ext4_bgroup *bg, uint32_t f)
{
- uint16_t flags = to_le16(bg->flags);
- flags |= f;
- bg->flags = to_le16(flags);
+ uint16_t flags = to_le16(bg->flags);
+ flags |= f;
+ bg->flags = to_le16(flags);
}
/**@brief Clear flag of block group.
*/
static inline void ext4_bg_clear_flag(struct ext4_bgroup *bg, uint32_t f)
{
- uint16_t flags = to_le16(bg->flags);
- flags &= ~f;
- bg->flags = to_le16(flags);
+ uint16_t flags = to_le16(bg->flags);
+ flags &= ~f;
+ bg->flags = to_le16(flags);
}
/**@brief Calculate CRC16 of the block group.
int ext4_block_init(struct ext4_blockdev *bdev)
{
- int rc;
- ext4_assert(bdev);
+ int rc;
+ ext4_assert(bdev);
- ext4_assert(bdev->open && bdev->close && bdev->bread && bdev->bwrite);
+ ext4_assert(bdev->open && bdev->close && bdev->bread && bdev->bwrite);
- /*Low level block init*/
- rc = bdev->open(bdev);
- if (rc != EOK)
- return rc;
+ /*Low level block init*/
+ rc = bdev->open(bdev);
+ if (rc != EOK)
+ return rc;
- bdev->flags |= EXT4_BDEV_INITIALIZED;
+ bdev->flags |= EXT4_BDEV_INITIALIZED;
- return EOK;
+ return EOK;
}
int ext4_block_bind_bcache(struct ext4_blockdev *bdev, struct ext4_bcache *bc)
{
- ext4_assert(bdev && bc);
- bdev->bc = bc;
- return EOK;
+ ext4_assert(bdev && bc);
+ bdev->bc = bc;
+ return EOK;
}
void ext4_block_set_lb_size(struct ext4_blockdev *bdev, uint64_t lb_bsize)
{
- /*Logical block size has to be multiply of physical */
- ext4_assert(!(lb_bsize % bdev->ph_bsize));
+ /*Logical block size has to be multiply of physical */
+ ext4_assert(!(lb_bsize % bdev->ph_bsize));
- bdev->lg_bsize = lb_bsize;
- bdev->lg_bcnt = (bdev->ph_bcnt * bdev->ph_bsize) / lb_bsize;
+ bdev->lg_bsize = lb_bsize;
+ bdev->lg_bcnt = (bdev->ph_bcnt * bdev->ph_bsize) / lb_bsize;
}
int ext4_block_fini(struct ext4_blockdev *bdev)
{
- ext4_assert(bdev);
+ ext4_assert(bdev);
- bdev->flags &= ~(EXT4_BDEV_INITIALIZED);
+ bdev->flags &= ~(EXT4_BDEV_INITIALIZED);
- /*Low level block fini*/
- return bdev->close(bdev);
+ /*Low level block fini*/
+ return bdev->close(bdev);
}
int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
- uint64_t lba)
+ uint64_t lba)
{
- uint64_t pba;
- uint32_t pb_cnt;
- uint32_t i;
- bool is_new;
- int r;
-
- ext4_assert(bdev && b);
-
- if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
- return EIO;
-
- if (!(lba < bdev->lg_bcnt))
- return ERANGE;
-
- b->dirty = 0;
- b->lb_id = lba;
-
- /*If cache is full we have to flush it anyway :(*/
- if (ext4_bcache_is_full(bdev->bc) && bdev->cache_write_back) {
-
- uint32_t free_candidate = bdev->bc->cnt;
- uint32_t min_lru = 0xFFFFFFFF;
-
- for (i = 0; i < bdev->bc->cnt; ++i) {
- /*Check if buffer free was delayed.*/
- if (!bdev->bc->free_delay[i])
- continue;
-
- /*Check reference counter.*/
- if (bdev->bc->refctr[i])
- continue;
-
- if (bdev->bc->lru_id[i] < min_lru) {
- min_lru = bdev->bc->lru_id[i];
- free_candidate = i;
- continue;
- }
- }
-
- if (free_candidate < bdev->bc->cnt) {
- /*Buffer free was delayed and have no reference. Flush it.*/
- r = ext4_blocks_set_direct(
- bdev, bdev->bc->data + bdev->bc->itemsize * free_candidate,
- bdev->bc->lba[free_candidate], 1);
- if (r != EOK)
- return r;
-
- /*No delayed anymore*/
- bdev->bc->free_delay[free_candidate] = 0;
-
- /*Reduce reference counter*/
- bdev->bc->ref_blocks--;
- }
- }
-
- r = ext4_bcache_alloc(bdev->bc, b, &is_new);
- if (r != EOK)
- return r;
-
- if (!is_new) {
- /*Block is in cache. Read from physical device is not required*/
- return EOK;
- }
-
- if (!b->data)
- return ENOMEM;
-
- pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
- pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
-
- r = bdev->bread(bdev, b->data, pba, pb_cnt);
-
- if (r != EOK) {
- ext4_bcache_free(bdev->bc, b, 0);
- b->lb_id = 0;
- return r;
- }
-
- bdev->bread_ctr++;
- return EOK;
+ uint64_t pba;
+ uint32_t pb_cnt;
+ uint32_t i;
+ bool is_new;
+ int r;
+
+ ext4_assert(bdev && b);
+
+ if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
+ return EIO;
+
+ if (!(lba < bdev->lg_bcnt))
+ return ERANGE;
+
+ b->dirty = 0;
+ b->lb_id = lba;
+
+ /*If cache is full we have to flush it anyway :(*/
+ if (ext4_bcache_is_full(bdev->bc) && bdev->cache_write_back) {
+
+ uint32_t free_candidate = bdev->bc->cnt;
+ uint32_t min_lru = 0xFFFFFFFF;
+
+ for (i = 0; i < bdev->bc->cnt; ++i) {
+ /*Check if buffer free was delayed.*/
+ if (!bdev->bc->free_delay[i])
+ continue;
+
+ /*Check reference counter.*/
+ if (bdev->bc->refctr[i])
+ continue;
+
+ if (bdev->bc->lru_id[i] < min_lru) {
+ min_lru = bdev->bc->lru_id[i];
+ free_candidate = i;
+ continue;
+ }
+ }
+
+ if (free_candidate < bdev->bc->cnt) {
+ /*Buffer free was delayed and have no reference. Flush
+ * it.*/
+ r = ext4_blocks_set_direct(
+ bdev, bdev->bc->data +
+ bdev->bc->itemsize * free_candidate,
+ bdev->bc->lba[free_candidate], 1);
+ if (r != EOK)
+ return r;
+
+ /*No delayed anymore*/
+ bdev->bc->free_delay[free_candidate] = 0;
+
+ /*Reduce reference counter*/
+ bdev->bc->ref_blocks--;
+ }
+ }
+
+ r = ext4_bcache_alloc(bdev->bc, b, &is_new);
+ if (r != EOK)
+ return r;
+
+ if (!is_new) {
+ /*Block is in cache. Read from physical device is not required*/
+ return EOK;
+ }
+
+ if (!b->data)
+ return ENOMEM;
+
+ pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
+ pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
+
+ r = bdev->bread(bdev, b->data, pba, pb_cnt);
+
+ if (r != EOK) {
+ ext4_bcache_free(bdev->bc, b, 0);
+ b->lb_id = 0;
+ return r;
+ }
+
+ bdev->bread_ctr++;
+ return EOK;
}
int ext4_block_set(struct ext4_blockdev *bdev, struct ext4_block *b)
{
- uint64_t pba;
- uint32_t pb_cnt;
- int r;
-
- ext4_assert(bdev && b);
-
- if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
- return EIO;
-
- /*No need to write.*/
- if (!b->dirty && !bdev->bc->dirty[b->cache_id]) {
- ext4_bcache_free(bdev->bc, b, 0);
- return EOK;
- }
-
- /*Free cache delay mode*/
- if (bdev->cache_write_back) {
-
- /*Free cache block and mark as free delayed*/
- return ext4_bcache_free(bdev->bc, b, bdev->cache_write_back);
- }
-
- if (bdev->bc->refctr[b->cache_id] > 1) {
- bdev->bc->dirty[b->cache_id] = true;
- return ext4_bcache_free(bdev->bc, b, 0);
- }
-
- pba = (b->lb_id * bdev->lg_bsize) / bdev->ph_bsize;
- pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
-
- r = bdev->bwrite(bdev, b->data, pba, pb_cnt);
- bdev->bc->dirty[b->cache_id] = false;
- if (r != EOK) {
- b->dirty = false;
- ext4_bcache_free(bdev->bc, b, 0);
- return r;
- }
-
- bdev->bwrite_ctr++;
- b->dirty = false;
- ext4_bcache_free(bdev->bc, b, 0);
- return EOK;
+ uint64_t pba;
+ uint32_t pb_cnt;
+ int r;
+
+ ext4_assert(bdev && b);
+
+ if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
+ return EIO;
+
+ /*No need to write.*/
+ if (!b->dirty && !bdev->bc->dirty[b->cache_id]) {
+ ext4_bcache_free(bdev->bc, b, 0);
+ return EOK;
+ }
+
+ /*Free cache delay mode*/
+ if (bdev->cache_write_back) {
+
+ /*Free cache block and mark as free delayed*/
+ return ext4_bcache_free(bdev->bc, b, bdev->cache_write_back);
+ }
+
+ if (bdev->bc->refctr[b->cache_id] > 1) {
+ bdev->bc->dirty[b->cache_id] = true;
+ return ext4_bcache_free(bdev->bc, b, 0);
+ }
+
+ pba = (b->lb_id * bdev->lg_bsize) / bdev->ph_bsize;
+ pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
+
+ r = bdev->bwrite(bdev, b->data, pba, pb_cnt);
+ bdev->bc->dirty[b->cache_id] = false;
+ if (r != EOK) {
+ b->dirty = false;
+ ext4_bcache_free(bdev->bc, b, 0);
+ return r;
+ }
+
+ bdev->bwrite_ctr++;
+ b->dirty = false;
+ ext4_bcache_free(bdev->bc, b, 0);
+ return EOK;
}
int ext4_blocks_get_direct(struct ext4_blockdev *bdev, void *buf, uint64_t lba,
- uint32_t cnt)
+ uint32_t cnt)
{
- uint64_t pba;
- uint32_t pb_cnt;
+ uint64_t pba;
+ uint32_t pb_cnt;
- ext4_assert(bdev && buf);
+ ext4_assert(bdev && buf);
- pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
- pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
+ pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
+ pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
- bdev->bread_ctr++;
- return bdev->bread(bdev, buf, pba, pb_cnt * cnt);
+ bdev->bread_ctr++;
+ return bdev->bread(bdev, buf, pba, pb_cnt * cnt);
}
int ext4_blocks_set_direct(struct ext4_blockdev *bdev, const void *buf,
- uint64_t lba, uint32_t cnt)
+ uint64_t lba, uint32_t cnt)
{
- uint64_t pba;
- uint32_t pb_cnt;
+ uint64_t pba;
+ uint32_t pb_cnt;
- ext4_assert(bdev && buf);
+ ext4_assert(bdev && buf);
- pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
- pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
+ pba = (lba * bdev->lg_bsize) / bdev->ph_bsize;
+ pb_cnt = bdev->lg_bsize / bdev->ph_bsize;
- bdev->bwrite_ctr++;
+ bdev->bwrite_ctr++;
- return bdev->bwrite(bdev, buf, pba, pb_cnt * cnt);
+ return bdev->bwrite(bdev, buf, pba, pb_cnt * cnt);
}
int ext4_block_writebytes(struct ext4_blockdev *bdev, uint64_t off,
- const void *buf, uint32_t len)
+ const void *buf, uint32_t len)
{
- uint64_t block_idx;
- uint64_t block_end;
- uint32_t blen;
- uint32_t unalg;
- int r = EOK;
+ uint64_t block_idx;
+ uint64_t block_end;
+ uint32_t blen;
+ uint32_t unalg;
+ int r = EOK;
- const uint8_t *p = (void *)buf;
+ const uint8_t *p = (void *)buf;
- ext4_assert(bdev && buf);
+ ext4_assert(bdev && buf);
- if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
- return EIO;
+ if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
+ return EIO;
- block_idx = off / bdev->ph_bsize;
- block_end = block_idx + len / bdev->ph_bsize;
+ block_idx = off / bdev->ph_bsize;
+ block_end = block_idx + len / bdev->ph_bsize;
- if (!(block_end < bdev->ph_bcnt))
- return EINVAL; /*Ups. Out of range operation*/
+ if (!(block_end < bdev->ph_bcnt))
+ return EINVAL; /*Ups. Out of range operation*/
- /*OK lets deal with the first possible unaligned block*/
- unalg = (off & (bdev->ph_bsize - 1));
- if (unalg) {
+ /*OK lets deal with the first possible unaligned block*/
+ unalg = (off & (bdev->ph_bsize - 1));
+ if (unalg) {
- uint32_t wlen =
- (bdev->ph_bsize - unalg) > len ? len : (bdev->ph_bsize - unalg);
+ uint32_t wlen = (bdev->ph_bsize - unalg) > len
+ ? len
+ : (bdev->ph_bsize - unalg);
- r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
+ r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
- if (r != EOK)
- return r;
+ if (r != EOK)
+ return r;
- memcpy(bdev->ph_bbuf + unalg, p, wlen);
+ memcpy(bdev->ph_bbuf + unalg, p, wlen);
- r = bdev->bwrite(bdev, bdev->ph_bbuf, block_idx, 1);
- if (r != EOK)
- return r;
+ r = bdev->bwrite(bdev, bdev->ph_bbuf, block_idx, 1);
+ if (r != EOK)
+ return r;
- p += wlen;
- len -= wlen;
- block_idx++;
- }
+ p += wlen;
+ len -= wlen;
+ block_idx++;
+ }
- /*Aligned data*/
- blen = len / bdev->ph_bsize;
- r = bdev->bwrite(bdev, p, block_idx, blen);
+ /*Aligned data*/
+ blen = len / bdev->ph_bsize;
+ r = bdev->bwrite(bdev, p, block_idx, blen);
- if (r != EOK)
- return r;
+ if (r != EOK)
+ return r;
- p += bdev->ph_bsize * blen;
- len -= bdev->ph_bsize * blen;
+ p += bdev->ph_bsize * blen;
+ len -= bdev->ph_bsize * blen;
- block_idx += blen;
+ block_idx += blen;
- /*Rest of the data*/
- if (len) {
- r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
- if (r != EOK)
- return r;
+ /*Rest of the data*/
+ if (len) {
+ r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
+ if (r != EOK)
+ return r;
- memcpy(bdev->ph_bbuf, p, len);
+ memcpy(bdev->ph_bbuf, p, len);
- r = bdev->bwrite(bdev, bdev->ph_bbuf, block_idx, 1);
+ r = bdev->bwrite(bdev, bdev->ph_bbuf, block_idx, 1);
- if (r != EOK)
- return r;
- }
+ if (r != EOK)
+ return r;
+ }
- return r;
+ return r;
}
int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off, void *buf,
- uint32_t len)
+ uint32_t len)
{
- uint64_t block_idx;
- uint64_t block_end;
- uint32_t blen;
- uint32_t unalg;
- int r = EOK;
+ uint64_t block_idx;
+ uint64_t block_end;
+ uint32_t blen;
+ uint32_t unalg;
+ int r = EOK;
- uint8_t *p = (void *)buf;
+ uint8_t *p = (void *)buf;
- ext4_assert(bdev && buf);
+ ext4_assert(bdev && buf);
- if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
- return EIO;
+ if (!(bdev->flags & EXT4_BDEV_INITIALIZED))
+ return EIO;
- block_idx = off / bdev->ph_bsize;
- block_end = block_idx + len / bdev->ph_bsize;
+ block_idx = off / bdev->ph_bsize;
+ block_end = block_idx + len / bdev->ph_bsize;
- if (!(block_end < bdev->ph_bcnt))
- return EINVAL; /*Ups. Out of range operation*/
+ if (!(block_end < bdev->ph_bcnt))
+ return EINVAL; /*Ups. Out of range operation*/
- /*OK lets deal with the first possible unaligned block*/
- unalg = (off & (bdev->ph_bsize - 1));
- if (unalg) {
+ /*OK lets deal with the first possible unaligned block*/
+ unalg = (off & (bdev->ph_bsize - 1));
+ if (unalg) {
- uint32_t rlen =
- (bdev->ph_bsize - unalg) > len ? len : (bdev->ph_bsize - unalg);
+ uint32_t rlen = (bdev->ph_bsize - unalg) > len
+ ? len
+ : (bdev->ph_bsize - unalg);
- r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
- if (r != EOK)
- return r;
+ r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
+ if (r != EOK)
+ return r;
- memcpy(p, bdev->ph_bbuf + unalg, rlen);
+ memcpy(p, bdev->ph_bbuf + unalg, rlen);
- p += rlen;
- len -= rlen;
- block_idx++;
- }
+ p += rlen;
+ len -= rlen;
+ block_idx++;
+ }
- /*Aligned data*/
- blen = len / bdev->ph_bsize;
+ /*Aligned data*/
+ blen = len / bdev->ph_bsize;
- r = bdev->bread(bdev, p, block_idx, blen);
+ r = bdev->bread(bdev, p, block_idx, blen);
- if (r != EOK)
- return r;
+ if (r != EOK)
+ return r;
- p += bdev->ph_bsize * blen;
- len -= bdev->ph_bsize * blen;
+ p += bdev->ph_bsize * blen;
+ len -= bdev->ph_bsize * blen;
- block_idx += blen;
+ block_idx += blen;
- /*Rest of the data*/
- if (len) {
- r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
- if (r != EOK)
- return r;
+ /*Rest of the data*/
+ if (len) {
+ r = bdev->bread(bdev, bdev->ph_bbuf, block_idx, 1);
+ if (r != EOK)
+ return r;
- memcpy(p, bdev->ph_bbuf, len);
- }
+ memcpy(p, bdev->ph_bbuf, len);
+ }
- return r;
+ return r;
}
int ext4_block_cache_write_back(struct ext4_blockdev *bdev, uint8_t on_off)
{
- int r;
- uint32_t i;
-
- if (on_off)
- bdev->cache_write_back++;
-
- if (!on_off && bdev->cache_write_back)
- bdev->cache_write_back--;
-
- /*Flush all delayed cache blocks*/
- if (!bdev->cache_write_back) {
- for (i = 0; i < bdev->bc->cnt; ++i) {
-
- /*Check if buffer free was delayed.*/
- if (!bdev->bc->free_delay[i])
- continue;
-
- /*Check reference counter.*/
- if (bdev->bc->refctr[i])
- continue;
-
- /*Buffer free was delayed and have no reference. Flush it.*/
- r = ext4_blocks_set_direct(bdev,
- bdev->bc->data + bdev->bc->itemsize * i,
- bdev->bc->lba[i], 1);
- if (r != EOK)
- return r;
-
- /*No delayed anymore*/
- bdev->bc->free_delay[i] = 0;
-
- /*Reduce reference counter*/
- bdev->bc->ref_blocks--;
- }
- }
- return EOK;
+ int r;
+ uint32_t i;
+
+ if (on_off)
+ bdev->cache_write_back++;
+
+ if (!on_off && bdev->cache_write_back)
+ bdev->cache_write_back--;
+
+ /*Flush all delayed cache blocks*/
+ if (!bdev->cache_write_back) {
+ for (i = 0; i < bdev->bc->cnt; ++i) {
+
+ /*Check if buffer free was delayed.*/
+ if (!bdev->bc->free_delay[i])
+ continue;
+
+ /*Check reference counter.*/
+ if (bdev->bc->refctr[i])
+ continue;
+
+ /*Buffer free was delayed and have no reference. Flush
+ * it.*/
+ r = ext4_blocks_set_direct(
+ bdev, bdev->bc->data + bdev->bc->itemsize * i,
+ bdev->bc->lba[i], 1);
+ if (r != EOK)
+ return r;
+
+ /*No delayed anymore*/
+ bdev->bc->free_delay[i] = 0;
+
+ /*Reduce reference counter*/
+ bdev->bc->ref_blocks--;
+ }
+ }
+ return EOK;
}
/**
/**@brief Definition of the simple block device.*/
struct ext4_blockdev {
- /**@brief Open device function
- * @param bdev block device.*/
- int (*open)(struct ext4_blockdev *bdev);
+ /**@brief Open device function
+ * @param bdev block device.*/
+ int (*open)(struct ext4_blockdev *bdev);
- /**@brief Block read function.
- * @param bdev block device
- * @param buf output buffer
- * @param blk_id block id
- * @param blk_cnt block count*/
- int (*bread)(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
- uint32_t blk_cnt);
+ /**@brief Block read function.
+ * @param bdev block device
+ * @param buf output buffer
+ * @param blk_id block id
+ * @param blk_cnt block count*/
+ int (*bread)(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
+ uint32_t blk_cnt);
- /**@brief Block write function.
- * @param buf input buffer
- * @param blk_id block id
- * @param blk_cnt block count*/
- int (*bwrite)(struct ext4_blockdev *bdev, const void *buf, uint64_t blk_id,
- uint32_t blk_cnt);
+ /**@brief Block write function.
+ * @param buf input buffer
+ * @param blk_id block id
+ * @param blk_cnt block count*/
+ int (*bwrite)(struct ext4_blockdev *bdev, const void *buf,
+ uint64_t blk_id, uint32_t blk_cnt);
- /**@brief Close device function.
- * @param bdev block device.*/
- int (*close)(struct ext4_blockdev *bdev);
+ /**@brief Close device function.
+ * @param bdev block device.*/
+ int (*close)(struct ext4_blockdev *bdev);
- /**@brief Block cache.*/
- struct ext4_bcache *bc;
+ /**@brief Block cache.*/
+ struct ext4_bcache *bc;
- /**@brief Block size (bytes): physical*/
- uint32_t ph_bsize;
+ /**@brief Block size (bytes): physical*/
+ uint32_t ph_bsize;
- /**@brief Block count: physical*/
- uint64_t ph_bcnt;
+ /**@brief Block count: physical*/
+ uint64_t ph_bcnt;
- /**@brief Block size buffer: physical*/
- uint8_t *ph_bbuf;
+ /**@brief Block size buffer: physical*/
+ uint8_t *ph_bbuf;
- /**@brief Block size (bytes) logical*/
- uint32_t lg_bsize;
+ /**@brief Block size (bytes) logical*/
+ uint32_t lg_bsize;
- /**@brief Block count: physical*/
- uint64_t lg_bcnt;
+ /**@brief Block count: physical*/
+ uint64_t lg_bcnt;
- /**@brief Flags of block device*/
- uint32_t flags;
+ /**@brief Flags of block device*/
+ uint32_t flags;
- /**@brief Cache write back mode reference counter*/
- uint32_t cache_write_back;
+ /**@brief Cache write back mode reference counter*/
+ uint32_t cache_write_back;
- /**@brief Physical read counter*/
- uint32_t bread_ctr;
+ /**@brief Physical read counter*/
+ uint32_t bread_ctr;
- /**@brief Physical write counter*/
- uint32_t bwrite_ctr;
+ /**@brief Physical write counter*/
+ uint32_t bwrite_ctr;
};
/**@brief Static initialization of the block device.*/
#define EXT4_BLOCKDEV_STATIC_INSTANCE(__name, __bsize, __bcnt, __open, \
- __bread, __bwrite, __close) \
- static uint8_t __name##_ph_bbuf[(__bsize)]; \
- static struct ext4_blockdev __name = { \
- .open = __open, \
- .bread = __bread, \
- .bwrite = __bwrite, \
- .close = __close, \
- .ph_bsize = __bsize, \
- .ph_bcnt = __bcnt, \
- .ph_bbuf = __name##_ph_bbuf, \
- }
+ __bread, __bwrite, __close) \
+ static uint8_t __name##_ph_bbuf[(__bsize)]; \
+ static struct ext4_blockdev __name = { \
+ .open = __open, \
+ .bread = __bread, \
+ .bwrite = __bwrite, \
+ .close = __close, \
+ .ph_bsize = __bsize, \
+ .ph_bcnt = __bcnt, \
+ .ph_bbuf = __name##_ph_bbuf, \
+ }
/**@brief Block device initialization.
* @param bdev block device descriptor
* @param lba logical block address
* @return standard error code*/
int ext4_block_get(struct ext4_blockdev *bdev, struct ext4_block *b,
- uint64_t lba);
+ uint64_t lba);
/**@brief Block set procedure (through cache).
* @param bdev block device descriptor
* @param lba logical block address
* @return standard error code*/
int ext4_blocks_get_direct(struct ext4_blockdev *bdev, void *buf, uint64_t lba,
- uint32_t cnt);
+ uint32_t cnt);
/**@brief Block write procedure (without cache)
* @param bdev block device descriptor
* @param lba logical block address
* @return standard error code*/
int ext4_blocks_set_direct(struct ext4_blockdev *bdev, const void *buf,
- uint64_t lba, uint32_t cnt);
+ uint64_t lba, uint32_t cnt);
/**@brief Write to block device (by direct address).
* @param bdev block device descriptor
* @param len length of the write buffer
* @return standard error code*/
int ext4_block_writebytes(struct ext4_blockdev *bdev, uint64_t off,
- const void *buf, uint32_t len);
+ const void *buf, uint32_t len);
/**@brief Read freom block device (by direct address).
* @param bdev block device descriptor
* @param len length of the write buffer
* @return standard error code*/
int ext4_block_readbytes(struct ext4_blockdev *bdev, uint64_t off, void *buf,
- uint32_t len);
+ uint32_t len);
/**@brief Enable/disable write back cache mode
* @param bdev block device descriptor
#define CONFIG_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_SUPP
#define CONFIG_FEATURE_INCOMPAT_SUPP \
- (EXT2_FEATURE_INCOMPAT_SUPP | FEATURE_INCOMPAT_IGNORED)
+ (EXT2_FEATURE_INCOMPAT_SUPP | FEATURE_INCOMPAT_IGNORED)
#define CONFIG_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SUPP
#elif CONFIG_EXT_FEATURE_SET_LVL == F_SET_EXT3
#define CONFIG_FEATURE_COMPAT_SUPP EXT3_FEATURE_COMPAT_SUPP
#define CONFIG_FEATURE_INCOMPAT_SUPP \
- (EXT3_FEATURE_INCOMPAT_SUPP | FEATURE_INCOMPAT_IGNORED)
+ (EXT3_FEATURE_INCOMPAT_SUPP | FEATURE_INCOMPAT_IGNORED)
#define CONFIG_FEATURE_RO_COMPAT_SUPP EXT3_FEATURE_RO_COMPAT_SUPP
#elif CONFIG_EXT_FEATURE_SET_LVL == F_SET_EXT4
#define CONFIG_FEATURE_COMPAT_SUPP EXT4_FEATURE_COMPAT_SUPP
#define CONFIG_FEATURE_INCOMPAT_SUPP \
- (EXT4_FEATURE_INCOMPAT_SUPP | FEATURE_INCOMPAT_IGNORED)
+ (EXT4_FEATURE_INCOMPAT_SUPP | FEATURE_INCOMPAT_IGNORED)
#define CONFIG_FEATURE_RO_COMPAT_SUPP EXT4_FEATURE_RO_COMPAT_SUPP
#else
uint32_t ext4_crc32c(uint32_t crc, const void *buffer, uint32_t length)
{
- const uint8_t *p = buffer;
+ const uint8_t *p = buffer;
- while (length--)
- crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ while (length--)
+ crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
- return crc;
+ return crc;
}
/**
#if CONFIG_DEBUG_PRINTF
/**@brief Debug printf.*/
#define ext4_dprintf(m, ...) \
- do { \
- if (m & ext4_dmask_get()) \
- printf(__VA_ARGS__); \
- fflush(stdout); \
- } while (0)
+ do { \
+ if (m & ext4_dmask_get()) \
+ printf(__VA_ARGS__); \
+ fflush(stdout); \
+ } while (0)
#else
#define ext4_dprintf(m, ...)
#endif
#if CONFIG_DEBUG_ASSERT
/**@brief Debug assertion.*/
#define ext4_assert(_v) \
- do { \
- if (!(_v)) { \
- printf("Assertion failed:\nmodule: %s\nline: %d\n", \
- __FILE__, __LINE__); \
- } \
- } while (0)
+ do { \
+ if (!(_v)) { \
+ printf("Assertion failed:\nmodule: %s\nline: %d\n", \
+ __FILE__, __LINE__); \
+ } \
+ } while (0)
#else
#define ext4_assert(_v)
#endif
* @return Error code\r
*/\r
static int ext4_dir_iterator_set(struct ext4_directory_iterator *it,\r
- uint32_t block_size)\r
+ uint32_t block_size)\r
{\r
- it->current = NULL;\r
+ it->current = NULL;\r
\r
- uint32_t offset_in_block = it->current_offset % block_size;\r
+ uint32_t offset_in_block = it->current_offset % block_size;\r
\r
- /* Ensure proper alignment */\r
- if ((offset_in_block % 4) != 0)\r
- return EIO;\r
+ /* Ensure proper alignment */\r
+ if ((offset_in_block % 4) != 0)\r
+ return EIO;\r
\r
- /* Ensure that the core of the entry does not overflow the block */\r
- if (offset_in_block > block_size - 8)\r
- return EIO;\r
+ /* Ensure that the core of the entry does not overflow the block */\r
+ if (offset_in_block > block_size - 8)\r
+ return EIO;\r
\r
- struct ext4_directory_entry_ll *entry =\r
- (void *)(it->current_block.data + offset_in_block);\r
+ struct ext4_directory_entry_ll *entry =\r
+ (void *)(it->current_block.data + offset_in_block);\r
\r
- /* Ensure that the whole entry does not overflow the block */\r
- uint16_t length = ext4_dir_entry_ll_get_entry_length(entry);\r
- if (offset_in_block + length > block_size)\r
- return EIO;\r
+ /* Ensure that the whole entry does not overflow the block */\r
+ uint16_t length = ext4_dir_entry_ll_get_entry_length(entry);\r
+ if (offset_in_block + length > block_size)\r
+ return EIO;\r
\r
- /* Ensure the name length is not too large */\r
- if (ext4_dir_entry_ll_get_name_length(&it->inode_ref->fs->sb, entry) >\r
- length - 8)\r
- return EIO;\r
+ /* Ensure the name length is not too large */\r
+ if (ext4_dir_entry_ll_get_name_length(&it->inode_ref->fs->sb, entry) >\r
+ length - 8)\r
+ return EIO;\r
\r
- /* Everything OK - "publish" the entry */\r
- it->current = entry;\r
- return EOK;\r
+ /* Everything OK - "publish" the entry */\r
+ it->current = entry;\r
+ return EOK;\r
}\r
\r
/**@brief Seek to next valid directory entry.\r
* @return Error code\r
*/\r
static int ext4_dir_iterator_seek(struct ext4_directory_iterator *it,\r
- uint64_t pos)\r
+ uint64_t pos)\r
{\r
- uint64_t size =\r
- ext4_inode_get_size(&it->inode_ref->fs->sb, it->inode_ref->inode);\r
-\r
- /* The iterator is not valid until we seek to the desired position */\r
- it->current = NULL;\r
-\r
- /* Are we at the end? */\r
- if (pos >= size) {\r
- if (it->current_block.lb_id) {\r
-\r
- int rc =\r
- ext4_block_set(it->inode_ref->fs->bdev, &it->current_block);\r
- it->current_block.lb_id = 0;\r
-\r
- if (rc != EOK)\r
- return rc;\r
- }\r
-\r
- it->current_offset = pos;\r
- return EOK;\r
- }\r
-\r
- /* Compute next block address */\r
- uint32_t block_size = ext4_sb_get_block_size(&it->inode_ref->fs->sb);\r
- uint64_t current_block_idx = it->current_offset / block_size;\r
- uint64_t next_block_idx = pos / block_size;\r
-\r
- /*\r
- * If we don't have a block or are moving across block boundary,\r
- * we need to get another block\r
- */\r
- if ((it->current_block.lb_id == 0) ||\r
- (current_block_idx != next_block_idx)) {\r
- if (it->current_block.lb_id) {\r
- int rc =\r
- ext4_block_set(it->inode_ref->fs->bdev, &it->current_block);\r
- it->current_block.lb_id = 0;\r
-\r
- if (rc != EOK)\r
- return rc;\r
- }\r
-\r
- uint32_t next_block_phys_idx;\r
- int rc = ext4_fs_get_inode_data_block_index(\r
- it->inode_ref, next_block_idx, &next_block_phys_idx);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- rc = ext4_block_get(it->inode_ref->fs->bdev, &it->current_block,\r
- next_block_phys_idx);\r
- if (rc != EOK) {\r
- it->current_block.lb_id = 0;\r
- return rc;\r
- }\r
- }\r
-\r
- it->current_offset = pos;\r
-\r
- return ext4_dir_iterator_set(it, block_size);\r
+ uint64_t size =\r
+ ext4_inode_get_size(&it->inode_ref->fs->sb, it->inode_ref->inode);\r
+\r
+ /* The iterator is not valid until we seek to the desired position */\r
+ it->current = NULL;\r
+\r
+ /* Are we at the end? */\r
+ if (pos >= size) {\r
+ if (it->current_block.lb_id) {\r
+\r
+ int rc = ext4_block_set(it->inode_ref->fs->bdev,\r
+ &it->current_block);\r
+ it->current_block.lb_id = 0;\r
+\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+\r
+ it->current_offset = pos;\r
+ return EOK;\r
+ }\r
+\r
+ /* Compute next block address */\r
+ uint32_t block_size = ext4_sb_get_block_size(&it->inode_ref->fs->sb);\r
+ uint64_t current_block_idx = it->current_offset / block_size;\r
+ uint64_t next_block_idx = pos / block_size;\r
+\r
+ /*\r
+ * If we don't have a block or are moving across block boundary,\r
+ * we need to get another block\r
+ */\r
+ if ((it->current_block.lb_id == 0) ||\r
+ (current_block_idx != next_block_idx)) {\r
+ if (it->current_block.lb_id) {\r
+ int rc = ext4_block_set(it->inode_ref->fs->bdev,\r
+ &it->current_block);\r
+ it->current_block.lb_id = 0;\r
+\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+\r
+ uint32_t next_block_phys_idx;\r
+ int rc = ext4_fs_get_inode_data_block_index(\r
+ it->inode_ref, next_block_idx, &next_block_phys_idx);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ rc = ext4_block_get(it->inode_ref->fs->bdev, &it->current_block,\r
+ next_block_phys_idx);\r
+ if (rc != EOK) {\r
+ it->current_block.lb_id = 0;\r
+ return rc;\r
+ }\r
+ }\r
+\r
+ it->current_offset = pos;\r
+\r
+ return ext4_dir_iterator_set(it, block_size);\r
}\r
\r
int ext4_dir_iterator_init(struct ext4_directory_iterator *it,\r
- struct ext4_inode_ref *inode_ref, uint64_t pos)\r
+ struct ext4_inode_ref *inode_ref, uint64_t pos)\r
{\r
- it->inode_ref = inode_ref;\r
- it->current = 0;\r
- it->current_offset = 0;\r
- it->current_block.lb_id = 0;\r
+ it->inode_ref = inode_ref;\r
+ it->current = 0;\r
+ it->current_offset = 0;\r
+ it->current_block.lb_id = 0;\r
\r
- return ext4_dir_iterator_seek(it, pos);\r
+ return ext4_dir_iterator_seek(it, pos);\r
}\r
\r
int ext4_dir_iterator_next(struct ext4_directory_iterator *it)\r
{\r
- int r = EOK;\r
- uint16_t skip;\r
+ int r = EOK;\r
+ uint16_t skip;\r
\r
- while (r == EOK) {\r
- skip = ext4_dir_entry_ll_get_entry_length(it->current);\r
- r = ext4_dir_iterator_seek(it, it->current_offset + skip);\r
+ while (r == EOK) {\r
+ skip = ext4_dir_entry_ll_get_entry_length(it->current);\r
+ r = ext4_dir_iterator_seek(it, it->current_offset + skip);\r
\r
- if (!it->current)\r
- break;\r
- /*Skip NULL referenced entry*/\r
- if (it->current->inode != 0)\r
- break;\r
- }\r
+ if (!it->current)\r
+ break;\r
+ /*Skip NULL referenced entry*/\r
+ if (it->current->inode != 0)\r
+ break;\r
+ }\r
\r
- return r;\r
+ return r;\r
}\r
\r
int ext4_dir_iterator_fini(struct ext4_directory_iterator *it)\r
{\r
- it->current = 0;\r
+ it->current = 0;\r
\r
- if (it->current_block.lb_id)\r
- return ext4_block_set(it->inode_ref->fs->bdev, &it->current_block);\r
+ if (it->current_block.lb_id)\r
+ return ext4_block_set(it->inode_ref->fs->bdev,\r
+ &it->current_block);\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
void ext4_dir_write_entry(struct ext4_sblock *sb,\r
- struct ext4_directory_entry_ll *entry,\r
- uint16_t entry_len, struct ext4_inode_ref *child,\r
- const char *name, size_t name_len)\r
+ struct ext4_directory_entry_ll *entry,\r
+ uint16_t entry_len, struct ext4_inode_ref *child,\r
+ const char *name, size_t name_len)\r
{\r
- /* Check maximum entry length */\r
- ext4_assert(entry_len <= ext4_sb_get_block_size(sb));\r
-\r
- /* Set basic attributes */\r
- ext4_dir_entry_ll_set_inode(entry, child->index);\r
- ext4_dir_entry_ll_set_entry_length(entry, entry_len);\r
- ext4_dir_entry_ll_set_name_length(sb, entry, name_len);\r
-\r
- /* Write name */\r
- memcpy(entry->name, name, name_len);\r
-\r
- /* Set type of entry */\r
- if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))\r
- ext4_dir_entry_ll_set_inode_type(sb, entry,\r
- EXT4_DIRECTORY_FILETYPE_DIR);\r
- else\r
- ext4_dir_entry_ll_set_inode_type(sb, entry,\r
- EXT4_DIRECTORY_FILETYPE_REG_FILE);\r
+ /* Check maximum entry length */\r
+ ext4_assert(entry_len <= ext4_sb_get_block_size(sb));\r
+\r
+ /* Set basic attributes */\r
+ ext4_dir_entry_ll_set_inode(entry, child->index);\r
+ ext4_dir_entry_ll_set_entry_length(entry, entry_len);\r
+ ext4_dir_entry_ll_set_name_length(sb, entry, name_len);\r
+\r
+ /* Write name */\r
+ memcpy(entry->name, name, name_len);\r
+\r
+ /* Set type of entry */\r
+ if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY))\r
+ ext4_dir_entry_ll_set_inode_type(sb, entry,\r
+ EXT4_DIRECTORY_FILETYPE_DIR);\r
+ else\r
+ ext4_dir_entry_ll_set_inode_type(\r
+ sb, entry, EXT4_DIRECTORY_FILETYPE_REG_FILE);\r
}\r
\r
int ext4_dir_add_entry(struct ext4_inode_ref *parent, const char *name,\r
- uint32_t name_len, struct ext4_inode_ref *child)\r
+ uint32_t name_len, struct ext4_inode_ref *child)\r
{\r
- struct ext4_fs *fs = parent->fs;\r
+ struct ext4_fs *fs = parent->fs;\r
\r
#if CONFIG_DIR_INDEX_ENABLE\r
- /* Index adding (if allowed) */\r
- if ((ext4_sb_has_feature_compatible(&fs->sb,\r
- EXT4_FEATURE_COMPAT_DIR_INDEX)) &&\r
- (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {\r
- int rc = ext4_dir_dx_add_entry(parent, child, name);\r
-\r
- /* Check if index is not corrupted */\r
- if (rc != EXT4_ERR_BAD_DX_DIR) {\r
- if (rc != EOK)\r
- return rc;\r
-\r
- return EOK;\r
- }\r
-\r
- /* Needed to clear dir index flag if corrupted */\r
- ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);\r
- parent->dirty = true;\r
- }\r
+ /* Index adding (if allowed) */\r
+ if ((ext4_sb_has_feature_compatible(&fs->sb,\r
+ EXT4_FEATURE_COMPAT_DIR_INDEX)) &&\r
+ (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {\r
+ int rc = ext4_dir_dx_add_entry(parent, child, name);\r
+\r
+ /* Check if index is not corrupted */\r
+ if (rc != EXT4_ERR_BAD_DX_DIR) {\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ return EOK;\r
+ }\r
+\r
+ /* Needed to clear dir index flag if corrupted */\r
+ ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);\r
+ parent->dirty = true;\r
+ }\r
#endif\r
\r
- /* Linear algorithm */\r
- uint32_t iblock = 0;\r
- uint32_t fblock = 0;\r
- uint32_t block_size = ext4_sb_get_block_size(&fs->sb);\r
- uint32_t inode_size = ext4_inode_get_size(&fs->sb, parent->inode);\r
- uint32_t total_blocks = inode_size / block_size;\r
-\r
- /* Find block, where is space for new entry and try to add */\r
- bool success = false;\r
- for (iblock = 0; iblock < total_blocks; ++iblock) {\r
- int rc = ext4_fs_get_inode_data_block_index(parent, iblock, &fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_block block;\r
- rc = ext4_block_get(fs->bdev, &block, fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* If adding is successful, function can finish */\r
- rc = ext4_dir_try_insert_entry(&fs->sb, &block, child, name, name_len);\r
- if (rc == EOK)\r
- success = true;\r
-\r
- rc = ext4_block_set(fs->bdev, &block);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- if (success)\r
- return EOK;\r
- }\r
-\r
- /* No free block found - needed to allocate next data block */\r
-\r
- iblock = 0;\r
- fblock = 0;\r
- int rc = ext4_fs_append_inode_block(parent, &fblock, &iblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Load new block */\r
- struct ext4_block new_block;\r
-\r
- rc = ext4_block_get(fs->bdev, &new_block, fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Fill block with zeroes */\r
- memset(new_block.data, 0, block_size);\r
- struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;\r
- ext4_dir_write_entry(&fs->sb, block_entry, block_size, child, name,\r
- name_len);\r
-\r
- /* Save new block */\r
- new_block.dirty = true;\r
- rc = ext4_block_set(fs->bdev, &new_block);\r
-\r
- return rc;\r
+ /* Linear algorithm */\r
+ uint32_t iblock = 0;\r
+ uint32_t fblock = 0;\r
+ uint32_t block_size = ext4_sb_get_block_size(&fs->sb);\r
+ uint32_t inode_size = ext4_inode_get_size(&fs->sb, parent->inode);\r
+ uint32_t total_blocks = inode_size / block_size;\r
+\r
+ /* Find block, where is space for new entry and try to add */\r
+ bool success = false;\r
+ for (iblock = 0; iblock < total_blocks; ++iblock) {\r
+ int rc =\r
+ ext4_fs_get_inode_data_block_index(parent, iblock, &fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_block block;\r
+ rc = ext4_block_get(fs->bdev, &block, fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* If adding is successful, function can finish */\r
+ rc = ext4_dir_try_insert_entry(&fs->sb, &block, child, name,\r
+ name_len);\r
+ if (rc == EOK)\r
+ success = true;\r
+\r
+ rc = ext4_block_set(fs->bdev, &block);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ if (success)\r
+ return EOK;\r
+ }\r
+\r
+ /* No free block found - needed to allocate next data block */\r
+\r
+ iblock = 0;\r
+ fblock = 0;\r
+ int rc = ext4_fs_append_inode_block(parent, &fblock, &iblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Load new block */\r
+ struct ext4_block new_block;\r
+\r
+ rc = ext4_block_get(fs->bdev, &new_block, fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Fill block with zeroes */\r
+ memset(new_block.data, 0, block_size);\r
+ struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;\r
+ ext4_dir_write_entry(&fs->sb, block_entry, block_size, child, name,\r
+ name_len);\r
+\r
+ /* Save new block */\r
+ new_block.dirty = true;\r
+ rc = ext4_block_set(fs->bdev, &new_block);\r
+\r
+ return rc;\r
}\r
\r
int ext4_dir_find_entry(struct ext4_directory_search_result *result,\r
- struct ext4_inode_ref *parent, const char *name,\r
- uint32_t name_len)\r
+ struct ext4_inode_ref *parent, const char *name,\r
+ uint32_t name_len)\r
{\r
- struct ext4_sblock *sb = &parent->fs->sb;\r
+ struct ext4_sblock *sb = &parent->fs->sb;\r
\r
#if CONFIG_DIR_INDEX_ENABLE\r
- /* Index search */\r
- if ((ext4_sb_has_feature_compatible(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) &&\r
- (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {\r
- int rc = ext4_dir_dx_find_entry(result, parent, name_len, name);\r
-\r
- /* Check if index is not corrupted */\r
- if (rc != EXT4_ERR_BAD_DX_DIR) {\r
- if (rc != EOK)\r
- return rc;\r
-\r
- return EOK;\r
- }\r
-\r
- /* Needed to clear dir index flag if corrupted */\r
- ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);\r
- parent->dirty = true;\r
- }\r
+ /* Index search */\r
+ if ((ext4_sb_has_feature_compatible(sb,\r
+ EXT4_FEATURE_COMPAT_DIR_INDEX)) &&\r
+ (ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX))) {\r
+ int rc = ext4_dir_dx_find_entry(result, parent, name_len, name);\r
+\r
+ /* Check if index is not corrupted */\r
+ if (rc != EXT4_ERR_BAD_DX_DIR) {\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ return EOK;\r
+ }\r
+\r
+ /* Needed to clear dir index flag if corrupted */\r
+ ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX);\r
+ parent->dirty = true;\r
+ }\r
#endif\r
\r
- /* Linear algorithm */\r
-\r
- uint32_t iblock;\r
- uint32_t fblock;\r
- uint32_t block_size = ext4_sb_get_block_size(sb);\r
- uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);\r
- uint32_t total_blocks = inode_size / block_size;\r
-\r
- /* Walk through all data blocks */\r
- for (iblock = 0; iblock < total_blocks; ++iblock) {\r
- /* Load block address */\r
- int rc = ext4_fs_get_inode_data_block_index(parent, iblock, &fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Load data block */\r
- struct ext4_block block;\r
- rc = ext4_block_get(parent->fs->bdev, &block, fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Try to find entry in block */\r
- struct ext4_directory_entry_ll *res_entry;\r
- rc = ext4_dir_find_in_block(&block, sb, name_len, name, &res_entry);\r
- if (rc == EOK) {\r
- result->block = block;\r
- result->dentry = res_entry;\r
- return EOK;\r
- }\r
-\r
- /* Entry not found - put block and continue to the next block */\r
-\r
- rc = ext4_block_set(parent->fs->bdev, &block);\r
- if (rc != EOK)\r
- return rc;\r
- }\r
-\r
- /* Entry was not found */\r
-\r
- result->block.lb_id = 0;\r
- result->dentry = NULL;\r
-\r
- return ENOENT;\r
+ /* Linear algorithm */\r
+\r
+ uint32_t iblock;\r
+ uint32_t fblock;\r
+ uint32_t block_size = ext4_sb_get_block_size(sb);\r
+ uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);\r
+ uint32_t total_blocks = inode_size / block_size;\r
+\r
+ /* Walk through all data blocks */\r
+ for (iblock = 0; iblock < total_blocks; ++iblock) {\r
+ /* Load block address */\r
+ int rc =\r
+ ext4_fs_get_inode_data_block_index(parent, iblock, &fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Load data block */\r
+ struct ext4_block block;\r
+ rc = ext4_block_get(parent->fs->bdev, &block, fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Try to find entry in block */\r
+ struct ext4_directory_entry_ll *res_entry;\r
+ rc = ext4_dir_find_in_block(&block, sb, name_len, name,\r
+ &res_entry);\r
+ if (rc == EOK) {\r
+ result->block = block;\r
+ result->dentry = res_entry;\r
+ return EOK;\r
+ }\r
+\r
+ /* Entry not found - put block and continue to the next block */\r
+\r
+ rc = ext4_block_set(parent->fs->bdev, &block);\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+\r
+ /* Entry was not found */\r
+\r
+ result->block.lb_id = 0;\r
+ result->dentry = NULL;\r
+\r
+ return ENOENT;\r
}\r
\r
int ext4_dir_remove_entry(struct ext4_inode_ref *parent, const char *name,\r
- uint32_t name_len)\r
+ uint32_t name_len)\r
{\r
- /* Check if removing from directory */\r
- if (!ext4_inode_is_type(&parent->fs->sb, parent->inode,\r
- EXT4_INODE_MODE_DIRECTORY))\r
- return ENOTDIR;\r
-\r
- /* Try to find entry */\r
- struct ext4_directory_search_result result;\r
- int rc = ext4_dir_find_entry(&result, parent, name, name_len);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Invalidate entry */\r
- ext4_dir_entry_ll_set_inode(result.dentry, 0);\r
-\r
- /* Store entry position in block */\r
- uint32_t pos = (uint8_t *)result.dentry - result.block.data;\r
-\r
- /*\r
- * If entry is not the first in block, it must be merged\r
- * with previous entry\r
- */\r
- if (pos != 0) {\r
- uint32_t offset = 0;\r
-\r
- /* Start from the first entry in block */\r
- struct ext4_directory_entry_ll *tmp_dentry = (void *)result.block.data;\r
- uint16_t tmp_dentry_length =\r
- ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
-\r
- /* Find direct predecessor of removed entry */\r
- while ((offset + tmp_dentry_length) < pos) {\r
- offset += ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
- tmp_dentry = (void *)(result.block.data + offset);\r
- tmp_dentry_length = ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
- }\r
-\r
- ext4_assert(tmp_dentry_length + offset == pos);\r
-\r
- /* Add to removed entry length to predecessor's length */\r
- uint16_t del_entry_length =\r
- ext4_dir_entry_ll_get_entry_length(result.dentry);\r
- ext4_dir_entry_ll_set_entry_length(tmp_dentry, tmp_dentry_length +\r
- del_entry_length);\r
- }\r
-\r
- result.block.dirty = true;\r
-\r
- return ext4_dir_destroy_result(parent, &result);\r
+ /* Check if removing from directory */\r
+ if (!ext4_inode_is_type(&parent->fs->sb, parent->inode,\r
+ EXT4_INODE_MODE_DIRECTORY))\r
+ return ENOTDIR;\r
+\r
+ /* Try to find entry */\r
+ struct ext4_directory_search_result result;\r
+ int rc = ext4_dir_find_entry(&result, parent, name, name_len);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Invalidate entry */\r
+ ext4_dir_entry_ll_set_inode(result.dentry, 0);\r
+\r
+ /* Store entry position in block */\r
+ uint32_t pos = (uint8_t *)result.dentry - result.block.data;\r
+\r
+ /*\r
+ * If entry is not the first in block, it must be merged\r
+ * with previous entry\r
+ */\r
+ if (pos != 0) {\r
+ uint32_t offset = 0;\r
+\r
+ /* Start from the first entry in block */\r
+ struct ext4_directory_entry_ll *tmp_dentry =\r
+ (void *)result.block.data;\r
+ uint16_t tmp_dentry_length =\r
+ ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
+\r
+ /* Find direct predecessor of removed entry */\r
+ while ((offset + tmp_dentry_length) < pos) {\r
+ offset +=\r
+ ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
+ tmp_dentry = (void *)(result.block.data + offset);\r
+ tmp_dentry_length =\r
+ ext4_dir_entry_ll_get_entry_length(tmp_dentry);\r
+ }\r
+\r
+ ext4_assert(tmp_dentry_length + offset == pos);\r
+\r
+ /* Add to removed entry length to predecessor's length */\r
+ uint16_t del_entry_length =\r
+ ext4_dir_entry_ll_get_entry_length(result.dentry);\r
+ ext4_dir_entry_ll_set_entry_length(\r
+ tmp_dentry, tmp_dentry_length + del_entry_length);\r
+ }\r
+\r
+ result.block.dirty = true;\r
+\r
+ return ext4_dir_destroy_result(parent, &result);\r
}\r
\r
int ext4_dir_try_insert_entry(struct ext4_sblock *sb,\r
- struct ext4_block *target_block,\r
- struct ext4_inode_ref *child, const char *name,\r
- uint32_t name_len)\r
+ struct ext4_block *target_block,\r
+ struct ext4_inode_ref *child, const char *name,\r
+ uint32_t name_len)\r
{\r
- /* Compute required length entry and align it to 4 bytes */\r
- uint32_t block_size = ext4_sb_get_block_size(sb);\r
- uint16_t required_len = sizeof(struct ext4_fake_directory_entry) + name_len;\r
-\r
- if ((required_len % 4) != 0)\r
- required_len += 4 - (required_len % 4);\r
-\r
- /* Initialize pointers, stop means to upper bound */\r
- struct ext4_directory_entry_ll *dentry = (void *)target_block->data;\r
- struct ext4_directory_entry_ll *stop =\r
- (void *)(target_block->data + block_size);\r
-\r
- /*\r
- * Walk through the block and check for invalid entries\r
- * or entries with free space for new entry\r
- */\r
- while (dentry < stop) {\r
- uint32_t inode = ext4_dir_entry_ll_get_inode(dentry);\r
- uint16_t rec_len = ext4_dir_entry_ll_get_entry_length(dentry);\r
-\r
- /* If invalid and large enough entry, use it */\r
- if ((inode == 0) && (rec_len >= required_len)) {\r
- ext4_dir_write_entry(sb, dentry, rec_len, child, name, name_len);\r
- target_block->dirty = true;\r
-\r
- return EOK;\r
- }\r
-\r
- /* Valid entry, try to split it */\r
- if (inode != 0) {\r
- uint16_t used_name_len =\r
- ext4_dir_entry_ll_get_name_length(sb, dentry);\r
-\r
- uint16_t used_space =\r
- sizeof(struct ext4_fake_directory_entry) + used_name_len;\r
-\r
- if ((used_name_len % 4) != 0)\r
- used_space += 4 - (used_name_len % 4);\r
-\r
- uint16_t free_space = rec_len - used_space;\r
-\r
- /* There is free space for new entry */\r
- if (free_space >= required_len) {\r
- /* Cut tail of current entry */\r
- ext4_dir_entry_ll_set_entry_length(dentry, used_space);\r
- struct ext4_directory_entry_ll *new_entry =\r
- (void *)((uint8_t *)dentry + used_space);\r
- ext4_dir_write_entry(sb, new_entry, free_space, child, name,\r
- name_len);\r
-\r
- target_block->dirty = true;\r
- return EOK;\r
- }\r
- }\r
-\r
- /* Jump to the next entry */\r
- dentry = (void *)((uint8_t *)dentry + rec_len);\r
- }\r
-\r
- /* No free space found for new entry */\r
- return ENOSPC;\r
+ /* Compute required length entry and align it to 4 bytes */\r
+ uint32_t block_size = ext4_sb_get_block_size(sb);\r
+ uint16_t required_len =\r
+ sizeof(struct ext4_fake_directory_entry) + name_len;\r
+\r
+ if ((required_len % 4) != 0)\r
+ required_len += 4 - (required_len % 4);\r
+\r
+ /* Initialize pointers, stop means to upper bound */\r
+ struct ext4_directory_entry_ll *dentry = (void *)target_block->data;\r
+ struct ext4_directory_entry_ll *stop =\r
+ (void *)(target_block->data + block_size);\r
+\r
+ /*\r
+ * Walk through the block and check for invalid entries\r
+ * or entries with free space for new entry\r
+ */\r
+ while (dentry < stop) {\r
+ uint32_t inode = ext4_dir_entry_ll_get_inode(dentry);\r
+ uint16_t rec_len = ext4_dir_entry_ll_get_entry_length(dentry);\r
+\r
+ /* If invalid and large enough entry, use it */\r
+ if ((inode == 0) && (rec_len >= required_len)) {\r
+ ext4_dir_write_entry(sb, dentry, rec_len, child, name,\r
+ name_len);\r
+ target_block->dirty = true;\r
+\r
+ return EOK;\r
+ }\r
+\r
+ /* Valid entry, try to split it */\r
+ if (inode != 0) {\r
+ uint16_t used_name_len =\r
+ ext4_dir_entry_ll_get_name_length(sb, dentry);\r
+\r
+ uint16_t used_space =\r
+ sizeof(struct ext4_fake_directory_entry) +\r
+ used_name_len;\r
+\r
+ if ((used_name_len % 4) != 0)\r
+ used_space += 4 - (used_name_len % 4);\r
+\r
+ uint16_t free_space = rec_len - used_space;\r
+\r
+ /* There is free space for new entry */\r
+ if (free_space >= required_len) {\r
+ /* Cut tail of current entry */\r
+ ext4_dir_entry_ll_set_entry_length(dentry,\r
+ used_space);\r
+ struct ext4_directory_entry_ll *new_entry =\r
+ (void *)((uint8_t *)dentry + used_space);\r
+ ext4_dir_write_entry(sb, new_entry, free_space,\r
+ child, name, name_len);\r
+\r
+ target_block->dirty = true;\r
+ return EOK;\r
+ }\r
+ }\r
+\r
+ /* Jump to the next entry */\r
+ dentry = (void *)((uint8_t *)dentry + rec_len);\r
+ }\r
+\r
+ /* No free space found for new entry */\r
+ return ENOSPC;\r
}\r
\r
int ext4_dir_find_in_block(struct ext4_block *block, struct ext4_sblock *sb,\r
- size_t name_len, const char *name,\r
- struct ext4_directory_entry_ll **res_entry)\r
+ size_t name_len, const char *name,\r
+ struct ext4_directory_entry_ll **res_entry)\r
{\r
- /* Start from the first entry in block */\r
- struct ext4_directory_entry_ll *dentry =\r
- (struct ext4_directory_entry_ll *)block->data;\r
-\r
- /* Set upper bound for cycling */\r
- uint8_t *addr_limit = block->data + ext4_sb_get_block_size(sb);\r
-\r
- /* Walk through the block and check entries */\r
- while ((uint8_t *)dentry < addr_limit) {\r
- /* Termination condition */\r
- if ((uint8_t *)dentry + name_len > addr_limit)\r
- break;\r
-\r
- /* Valid entry - check it */\r
- if (dentry->inode != 0) {\r
- /* For more efficient compare only lengths firstly*/\r
- if (ext4_dir_entry_ll_get_name_length(sb, dentry) == name_len) {\r
- /* Compare names */\r
- if (memcmp((uint8_t *)name, dentry->name, name_len) == 0) {\r
- *res_entry = dentry;\r
- return EOK;\r
- }\r
- }\r
- }\r
-\r
- uint16_t dentry_len = ext4_dir_entry_ll_get_entry_length(dentry);\r
-\r
- /* Corrupted entry */\r
- if (dentry_len == 0)\r
- return EINVAL;\r
-\r
- /* Jump to next entry */\r
- dentry =\r
- (struct ext4_directory_entry_ll *)((uint8_t *)dentry + dentry_len);\r
- }\r
-\r
- /* Entry not found */\r
- return ENOENT;\r
+ /* Start from the first entry in block */\r
+ struct ext4_directory_entry_ll *dentry =\r
+ (struct ext4_directory_entry_ll *)block->data;\r
+\r
+ /* Set upper bound for cycling */\r
+ uint8_t *addr_limit = block->data + ext4_sb_get_block_size(sb);\r
+\r
+ /* Walk through the block and check entries */\r
+ while ((uint8_t *)dentry < addr_limit) {\r
+ /* Termination condition */\r
+ if ((uint8_t *)dentry + name_len > addr_limit)\r
+ break;\r
+\r
+ /* Valid entry - check it */\r
+ if (dentry->inode != 0) {\r
+ /* For more efficient compare only lengths firstly*/\r
+ if (ext4_dir_entry_ll_get_name_length(sb, dentry) ==\r
+ name_len) {\r
+ /* Compare names */\r
+ if (memcmp((uint8_t *)name, dentry->name,\r
+ name_len) == 0) {\r
+ *res_entry = dentry;\r
+ return EOK;\r
+ }\r
+ }\r
+ }\r
+\r
+ uint16_t dentry_len =\r
+ ext4_dir_entry_ll_get_entry_length(dentry);\r
+\r
+ /* Corrupted entry */\r
+ if (dentry_len == 0)\r
+ return EINVAL;\r
+\r
+ /* Jump to next entry */\r
+ dentry = (struct ext4_directory_entry_ll *)((uint8_t *)dentry +\r
+ dentry_len);\r
+ }\r
+\r
+ /* Entry not found */\r
+ return ENOENT;\r
}\r
\r
int ext4_dir_destroy_result(struct ext4_inode_ref *parent,\r
- struct ext4_directory_search_result *result)\r
+ struct ext4_directory_search_result *result)\r
{\r
- if (result->block.lb_id)\r
- return ext4_block_set(parent->fs->bdev, &result->block);\r
+ if (result->block.lb_id)\r
+ return ext4_block_set(parent->fs->bdev, &result->block);\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
/**\r
static inline uint32_t\r
ext4_dir_entry_ll_get_inode(struct ext4_directory_entry_ll *de)\r
{\r
- return to_le32(de->inode);\r
+ return to_le32(de->inode);\r
}\r
\r
/**@brief Set i-node number to directory entry.\r
static inline void\r
ext4_dir_entry_ll_set_inode(struct ext4_directory_entry_ll *de, uint32_t inode)\r
{\r
- de->inode = to_le32(inode);\r
+ de->inode = to_le32(inode);\r
}\r
\r
/**@brief Get directory entry length.\r
static inline uint16_t\r
ext4_dir_entry_ll_get_entry_length(struct ext4_directory_entry_ll *de)\r
{\r
- return to_le16(de->entry_length);\r
+ return to_le16(de->entry_length);\r
}\r
\r
/**@brief Set directory entry length.\r
*/\r
static inline void\r
ext4_dir_entry_ll_set_entry_length(struct ext4_directory_entry_ll *de,\r
- uint16_t len)\r
+ uint16_t len)\r
{\r
- de->entry_length = to_le16(len);\r
+ de->entry_length = to_le16(len);\r
}\r
\r
/**@brief Get directory entry name length.\r
*/\r
static inline uint16_t\r
ext4_dir_entry_ll_get_name_length(struct ext4_sblock *sb,\r
- struct ext4_directory_entry_ll *de)\r
+ struct ext4_directory_entry_ll *de)\r
{\r
- uint16_t v = de->name_length;\r
+ uint16_t v = de->name_length;\r
\r
- if ((ext4_get32(sb, rev_level) == 0) &&\r
- (ext4_get32(sb, minor_rev_level) < 5))\r
- v |= ((uint16_t)de->in.name_length_high) << 8;\r
+ if ((ext4_get32(sb, rev_level) == 0) &&\r
+ (ext4_get32(sb, minor_rev_level) < 5))\r
+ v |= ((uint16_t)de->in.name_length_high) << 8;\r
\r
- return v;\r
+ return v;\r
}\r
\r
/**@brief Set directory entry name length.\r
static inline void ext4_dir_entry_ll_set_name_length(\r
struct ext4_sblock *sb, struct ext4_directory_entry_ll *de, uint16_t len)\r
{\r
- de->name_length = (len << 8) >> 8;\r
+ de->name_length = (len << 8) >> 8;\r
\r
- if ((ext4_get32(sb, rev_level) == 0) &&\r
- (ext4_get32(sb, minor_rev_level) < 5))\r
- de->in.name_length_high = len >> 8;\r
+ if ((ext4_get32(sb, rev_level) == 0) &&\r
+ (ext4_get32(sb, minor_rev_level) < 5))\r
+ de->in.name_length_high = len >> 8;\r
}\r
\r
/**@brief Get i-node type of directory entry.\r
*/\r
static inline uint8_t\r
ext4_dir_entry_ll_get_inode_type(struct ext4_sblock *sb,\r
- struct ext4_directory_entry_ll *de)\r
+ struct ext4_directory_entry_ll *de)\r
{\r
- if ((ext4_get32(sb, rev_level) > 0) ||\r
- (ext4_get32(sb, minor_rev_level) >= 5))\r
- return de->in.inode_type;\r
+ if ((ext4_get32(sb, rev_level) > 0) ||\r
+ (ext4_get32(sb, minor_rev_level) >= 5))\r
+ return de->in.inode_type;\r
\r
- return EXT4_DIRECTORY_FILETYPE_UNKNOWN;\r
+ return EXT4_DIRECTORY_FILETYPE_UNKNOWN;\r
}\r
/**@brief Set i-node type of directory entry.\r
* @param sb Superblock\r
static inline void ext4_dir_entry_ll_set_inode_type(\r
struct ext4_sblock *sb, struct ext4_directory_entry_ll *de, uint8_t type)\r
{\r
- if ((ext4_get32(sb, rev_level) > 0) ||\r
- (ext4_get32(sb, minor_rev_level) >= 5))\r
- de->in.inode_type = type;\r
+ if ((ext4_get32(sb, rev_level) > 0) ||\r
+ (ext4_get32(sb, minor_rev_level) >= 5))\r
+ de->in.inode_type = type;\r
}\r
\r
/**@brief Initialize directory iterator.\r
* @return Error code\r
*/\r
int ext4_dir_iterator_init(struct ext4_directory_iterator *it,\r
- struct ext4_inode_ref *inode_ref, uint64_t pos);\r
+ struct ext4_inode_ref *inode_ref, uint64_t pos);\r
\r
/**@brief Jump to the next valid entry\r
* @param it Initialized iterator\r
* @param name_len Length of entry name\r
*/\r
void ext4_dir_write_entry(struct ext4_sblock *sb,\r
- struct ext4_directory_entry_ll *entry,\r
- uint16_t entry_len, struct ext4_inode_ref *child,\r
- const char *name, size_t name_len);\r
+ struct ext4_directory_entry_ll *entry,\r
+ uint16_t entry_len, struct ext4_inode_ref *child,\r
+ const char *name, size_t name_len);\r
\r
/**@brief Add new entry to the directory.\r
* @param parent Directory i-node\r
* @return Error code\r
*/\r
int ext4_dir_add_entry(struct ext4_inode_ref *parent, const char *name,\r
- uint32_t name_len, struct ext4_inode_ref *child);\r
+ uint32_t name_len, struct ext4_inode_ref *child);\r
\r
/**@brief Find directory entry with passed name.\r
* @param result Result structure to be returned if entry found\r
* @return Error code\r
*/\r
int ext4_dir_find_entry(struct ext4_directory_search_result *result,\r
- struct ext4_inode_ref *parent, const char *name,\r
- uint32_t name_len);\r
+ struct ext4_inode_ref *parent, const char *name,\r
+ uint32_t name_len);\r
\r
/**@brief Remove directory entry.\r
* @param parent Directory i-node\r
* @return Error code\r
*/\r
int ext4_dir_remove_entry(struct ext4_inode_ref *parent, const char *name,\r
- uint32_t name_len);\r
+ uint32_t name_len);\r
\r
/**@brief Try to insert entry to concrete data block.\r
* @param sb Superblock\r
* @return Error code\r
*/\r
int ext4_dir_try_insert_entry(struct ext4_sblock *sb,\r
- struct ext4_block *target_block,\r
- struct ext4_inode_ref *child, const char *name,\r
- uint32_t name_len);\r
+ struct ext4_block *target_block,\r
+ struct ext4_inode_ref *child, const char *name,\r
+ uint32_t name_len);\r
\r
/**@brief Try to find entry in block by name.\r
* @param block Block containing entries\r
* @return Error code\r
*/\r
int ext4_dir_find_in_block(struct ext4_block *block, struct ext4_sblock *sb,\r
- size_t name_len, const char *name,\r
- struct ext4_directory_entry_ll **res_entry);\r
+ size_t name_len, const char *name,\r
+ struct ext4_directory_entry_ll **res_entry);\r
\r
/**@brief Simple function to release allocated data from result.\r
* @param parent Parent inode\r
*\r
*/\r
int ext4_dir_destroy_result(struct ext4_inode_ref *parent,\r
- struct ext4_directory_search_result *result);\r
+ struct ext4_directory_search_result *result);\r
\r
#endif /* EXT4_DIR_H_ */\r
\r
static inline uint8_t ext4_dir_dx_root_info_get_hash_version(\r
struct ext4_directory_dx_root_info *root_info)\r
{\r
- return root_info->hash_version;\r
+ return root_info->hash_version;\r
}\r
\r
/**@brief Set hash version, that will be used in directory index.\r
static inline void ext4_dir_dx_root_info_set_hash_version(\r
struct ext4_directory_dx_root_info *root_info, uint8_t v)\r
{\r
- root_info->hash_version = v;\r
+ root_info->hash_version = v;\r
}\r
\r
/**@brief Get length of root_info structure in bytes.\r
static inline uint8_t ext4_dir_dx_root_info_get_info_length(\r
struct ext4_directory_dx_root_info *root_info)\r
{\r
- return root_info->info_length;\r
+ return root_info->info_length;\r
}\r
\r
/**@brief Set length of root_info structure in bytes.\r
static inline void ext4_dir_dx_root_info_set_info_length(\r
struct ext4_directory_dx_root_info *root_info, uint8_t len)\r
{\r
- root_info->info_length = len;\r
+ root_info->info_length = len;\r
}\r
\r
/**@brief Get number of indirect levels of HTree.\r
static inline uint8_t ext4_dir_dx_root_info_get_indirect_levels(\r
struct ext4_directory_dx_root_info *root_info)\r
{\r
- return root_info->indirect_levels;\r
+ return root_info->indirect_levels;\r
}\r
\r
/**@brief Set number of indirect levels of HTree.\r
static inline void ext4_dir_dx_root_info_set_indirect_levels(\r
struct ext4_directory_dx_root_info *root_info, uint8_t lvl)\r
{\r
- root_info->indirect_levels = lvl;\r
+ root_info->indirect_levels = lvl;\r
}\r
\r
/**@brief Get maximum number of index node entries.\r
static inline uint16_t\r
ext4_dir_dx_countlimit_get_limit(struct ext4_directory_dx_countlimit *climit)\r
{\r
- return to_le16(climit->limit);\r
+ return to_le16(climit->limit);\r
}\r
\r
/**@brief Set maximum number of index node entries.\r
*/\r
static inline void\r
ext4_dir_dx_countlimit_set_limit(struct ext4_directory_dx_countlimit *climit,\r
- uint16_t limit)\r
+ uint16_t limit)\r
{\r
- climit->limit = to_le16(limit);\r
+ climit->limit = to_le16(limit);\r
}\r
\r
/**@brief Get current number of index node entries.\r
static inline uint16_t\r
ext4_dir_dx_countlimit_get_count(struct ext4_directory_dx_countlimit *climit)\r
{\r
- return to_le16(climit->count);\r
+ return to_le16(climit->count);\r
}\r
\r
/**@brief Set current number of index node entries.\r
*/\r
static inline void\r
ext4_dir_dx_countlimit_set_count(struct ext4_directory_dx_countlimit *climit,\r
- uint16_t count)\r
+ uint16_t count)\r
{\r
- climit->count = to_le16(count);\r
+ climit->count = to_le16(count);\r
}\r
\r
/**@brief Get hash value of index entry.\r
static inline uint32_t\r
ext4_dir_dx_entry_get_hash(struct ext4_directory_dx_entry *entry)\r
{\r
- return to_le32(entry->hash);\r
+ return to_le32(entry->hash);\r
}\r
\r
/**@brief Set hash value of index entry.\r
static inline void\r
ext4_dir_dx_entry_set_hash(struct ext4_directory_dx_entry *entry, uint32_t hash)\r
{\r
- entry->hash = to_le32(hash);\r
+ entry->hash = to_le32(hash);\r
}\r
\r
/**@brief Get block address where child node is located.\r
static inline uint32_t\r
ext4_dir_dx_entry_get_block(struct ext4_directory_dx_entry *entry)\r
{\r
- return to_le32(entry->block);\r
+ return to_le32(entry->block);\r
}\r
\r
/**@brief Set block address where child node is located.\r
*/\r
static inline void\r
ext4_dir_dx_entry_set_block(struct ext4_directory_dx_entry *entry,\r
- uint32_t block)\r
+ uint32_t block)\r
{\r
- entry->block = to_le32(block);\r
+ entry->block = to_le32(block);\r
}\r
\r
/**@brief Sort entry item.*/\r
struct ext4_dx_sort_entry {\r
- uint32_t hash;\r
- uint32_t rec_len;\r
- void *dentry;\r
+ uint32_t hash;\r
+ uint32_t rec_len;\r
+ void *dentry;\r
};\r
\r
static int ext4_dir_dx_hash_string(struct ext4_hash_info *hinfo, int len,\r
- const char *name)\r
+ const char *name)\r
{\r
- return ext2_htree_hash(name, len, hinfo->seed, hinfo->hash_version,\r
- &hinfo->hash, &hinfo->minor_hash);\r
+ return ext2_htree_hash(name, len, hinfo->seed, hinfo->hash_version,\r
+ &hinfo->hash, &hinfo->minor_hash);\r
}\r
\r
/****************************************************************************/\r
\r
int ext4_dir_dx_init(struct ext4_inode_ref *dir)\r
{\r
- /* Load block 0, where will be index root located */\r
- uint32_t fblock;\r
- int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_block block;\r
- rc = ext4_block_get(dir->fs->bdev, &block, fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Initialize pointers to data structures */\r
- struct ext4_directory_dx_root *root = (void *)block.data;\r
- struct ext4_directory_dx_root_info *info = &(root->info);\r
-\r
- /* Initialize root info structure */\r
- uint8_t hash_version = ext4_get8(&dir->fs->sb, default_hash_version);\r
-\r
- ext4_dir_dx_root_info_set_hash_version(info, hash_version);\r
- ext4_dir_dx_root_info_set_indirect_levels(info, 0);\r
- ext4_dir_dx_root_info_set_info_length(info, 8);\r
-\r
- /* Set limit and current number of entries */\r
- struct ext4_directory_dx_countlimit *countlimit =\r
- (struct ext4_directory_dx_countlimit *)&root->entries;\r
-\r
- ext4_dir_dx_countlimit_set_count(countlimit, 1);\r
-\r
- uint32_t block_size = ext4_sb_get_block_size(&dir->fs->sb);\r
- uint32_t entry_space = block_size -\r
- 2 * sizeof(struct ext4_directory_dx_dot_entry) -\r
- sizeof(struct ext4_directory_dx_root_info);\r
- uint16_t root_limit = entry_space / sizeof(struct ext4_directory_dx_entry);\r
- ext4_dir_dx_countlimit_set_limit(countlimit, root_limit);\r
-\r
- /* Append new block, where will be new entries inserted in the future */\r
- uint32_t iblock;\r
- rc = ext4_fs_append_inode_block(dir, &fblock, &iblock);\r
- if (rc != EOK) {\r
- ext4_block_set(dir->fs->bdev, &block);\r
- return rc;\r
- }\r
-\r
- struct ext4_block new_block;\r
-\r
- rc = ext4_block_get(dir->fs->bdev, &new_block, fblock);\r
- if (rc != EOK) {\r
- ext4_block_set(dir->fs->bdev, &block);\r
- return rc;\r
- }\r
-\r
- /* Fill the whole block with empty entry */\r
- struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;\r
-\r
- ext4_dir_entry_ll_set_entry_length(block_entry, block_size);\r
- ext4_dir_entry_ll_set_inode(block_entry, 0);\r
-\r
- new_block.dirty = true;\r
- rc = ext4_block_set(dir->fs->bdev, &new_block);\r
- if (rc != EOK) {\r
- ext4_block_set(dir->fs->bdev, &block);\r
- return rc;\r
- }\r
-\r
- /* Connect new block to the only entry in index */\r
- struct ext4_directory_dx_entry *entry = root->entries;\r
- ext4_dir_dx_entry_set_block(entry, iblock);\r
-\r
- block.dirty = true;\r
-\r
- return ext4_block_set(dir->fs->bdev, &block);\r
+ /* Load block 0, where will be index root located */\r
+ uint32_t fblock;\r
+ int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_block block;\r
+ rc = ext4_block_get(dir->fs->bdev, &block, fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Initialize pointers to data structures */\r
+ struct ext4_directory_dx_root *root = (void *)block.data;\r
+ struct ext4_directory_dx_root_info *info = &(root->info);\r
+\r
+ /* Initialize root info structure */\r
+ uint8_t hash_version = ext4_get8(&dir->fs->sb, default_hash_version);\r
+\r
+ ext4_dir_dx_root_info_set_hash_version(info, hash_version);\r
+ ext4_dir_dx_root_info_set_indirect_levels(info, 0);\r
+ ext4_dir_dx_root_info_set_info_length(info, 8);\r
+\r
+ /* Set limit and current number of entries */\r
+ struct ext4_directory_dx_countlimit *countlimit =\r
+ (struct ext4_directory_dx_countlimit *)&root->entries;\r
+\r
+ ext4_dir_dx_countlimit_set_count(countlimit, 1);\r
+\r
+ uint32_t block_size = ext4_sb_get_block_size(&dir->fs->sb);\r
+ uint32_t entry_space = block_size -\r
+ 2 * sizeof(struct ext4_directory_dx_dot_entry) -\r
+ sizeof(struct ext4_directory_dx_root_info);\r
+ uint16_t root_limit =\r
+ entry_space / sizeof(struct ext4_directory_dx_entry);\r
+ ext4_dir_dx_countlimit_set_limit(countlimit, root_limit);\r
+\r
+ /* Append new block, where will be new entries inserted in the future */\r
+ uint32_t iblock;\r
+ rc = ext4_fs_append_inode_block(dir, &fblock, &iblock);\r
+ if (rc != EOK) {\r
+ ext4_block_set(dir->fs->bdev, &block);\r
+ return rc;\r
+ }\r
+\r
+ struct ext4_block new_block;\r
+\r
+ rc = ext4_block_get(dir->fs->bdev, &new_block, fblock);\r
+ if (rc != EOK) {\r
+ ext4_block_set(dir->fs->bdev, &block);\r
+ return rc;\r
+ }\r
+\r
+ /* Fill the whole block with empty entry */\r
+ struct ext4_directory_entry_ll *block_entry = (void *)new_block.data;\r
+\r
+ ext4_dir_entry_ll_set_entry_length(block_entry, block_size);\r
+ ext4_dir_entry_ll_set_inode(block_entry, 0);\r
+\r
+ new_block.dirty = true;\r
+ rc = ext4_block_set(dir->fs->bdev, &new_block);\r
+ if (rc != EOK) {\r
+ ext4_block_set(dir->fs->bdev, &block);\r
+ return rc;\r
+ }\r
+\r
+ /* Connect new block to the only entry in index */\r
+ struct ext4_directory_dx_entry *entry = root->entries;\r
+ ext4_dir_dx_entry_set_block(entry, iblock);\r
+\r
+ block.dirty = true;\r
+\r
+ return ext4_block_set(dir->fs->bdev, &block);\r
}\r
\r
/**@brief Initialize hash info structure necessary for index operations.\r
* @return Standard error code\r
*/\r
static int ext4_dir_hinfo_init(struct ext4_hash_info *hinfo,\r
- struct ext4_block *root_block,\r
- struct ext4_sblock *sb, size_t name_len,\r
- const char *name)\r
+ struct ext4_block *root_block,\r
+ struct ext4_sblock *sb, size_t name_len,\r
+ const char *name)\r
{\r
- struct ext4_directory_dx_root *root =\r
- (struct ext4_directory_dx_root *)root_block->data;\r
-\r
- if ((root->info.hash_version != EXT2_HTREE_LEGACY) &&\r
- (root->info.hash_version != EXT2_HTREE_HALF_MD4) &&\r
- (root->info.hash_version != EXT2_HTREE_TEA))\r
- return EXT4_ERR_BAD_DX_DIR;\r
-\r
- /* Check unused flags */\r
- if (root->info.unused_flags != 0)\r
- return EXT4_ERR_BAD_DX_DIR;\r
-\r
- /* Check indirect levels */\r
- if (root->info.indirect_levels > 1)\r
- return EXT4_ERR_BAD_DX_DIR;\r
-\r
- /* Check if node limit is correct */\r
- uint32_t block_size = ext4_sb_get_block_size(sb);\r
- uint32_t entry_space = block_size;\r
- entry_space -= 2 * sizeof(struct ext4_directory_dx_dot_entry);\r
- entry_space -= sizeof(struct ext4_directory_dx_root_info);\r
- entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);\r
-\r
- uint16_t limit = ext4_dir_dx_countlimit_get_limit(\r
- (struct ext4_directory_dx_countlimit *)&root->entries);\r
- if (limit != entry_space)\r
- return EXT4_ERR_BAD_DX_DIR;\r
-\r
- /* Check hash version and modify if necessary */\r
- hinfo->hash_version = ext4_dir_dx_root_info_get_hash_version(&root->info);\r
- if ((hinfo->hash_version <= EXT2_HTREE_TEA) &&\r
- (ext4_sb_check_flag(sb, EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH))) {\r
- /* Use unsigned hash */\r
- hinfo->hash_version += 3;\r
- }\r
-\r
- /* Load hash seed from superblock */\r
-\r
- hinfo->seed = ext4_get8(sb, hash_seed);\r
-\r
- /* Compute hash value of name */\r
- if (name)\r
- return ext4_dir_dx_hash_string(hinfo, name_len, name);\r
-\r
- return EOK;\r
+ struct ext4_directory_dx_root *root =\r
+ (struct ext4_directory_dx_root *)root_block->data;\r
+\r
+ if ((root->info.hash_version != EXT2_HTREE_LEGACY) &&\r
+ (root->info.hash_version != EXT2_HTREE_HALF_MD4) &&\r
+ (root->info.hash_version != EXT2_HTREE_TEA))\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+\r
+ /* Check unused flags */\r
+ if (root->info.unused_flags != 0)\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+\r
+ /* Check indirect levels */\r
+ if (root->info.indirect_levels > 1)\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+\r
+ /* Check if node limit is correct */\r
+ uint32_t block_size = ext4_sb_get_block_size(sb);\r
+ uint32_t entry_space = block_size;\r
+ entry_space -= 2 * sizeof(struct ext4_directory_dx_dot_entry);\r
+ entry_space -= sizeof(struct ext4_directory_dx_root_info);\r
+ entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);\r
+\r
+ uint16_t limit = ext4_dir_dx_countlimit_get_limit(\r
+ (struct ext4_directory_dx_countlimit *)&root->entries);\r
+ if (limit != entry_space)\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+\r
+ /* Check hash version and modify if necessary */\r
+ hinfo->hash_version =\r
+ ext4_dir_dx_root_info_get_hash_version(&root->info);\r
+ if ((hinfo->hash_version <= EXT2_HTREE_TEA) &&\r
+ (ext4_sb_check_flag(sb, EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH))) {\r
+ /* Use unsigned hash */\r
+ hinfo->hash_version += 3;\r
+ }\r
+\r
+ /* Load hash seed from superblock */\r
+\r
+ hinfo->seed = ext4_get8(sb, hash_seed);\r
+\r
+ /* Compute hash value of name */\r
+ if (name)\r
+ return ext4_dir_dx_hash_string(hinfo, name_len, name);\r
+\r
+ return EOK;\r
}\r
\r
/**@brief Walk through index tree and load leaf with corresponding hash value.\r
* @return Standard error code\r
*/\r
static int ext4_dir_dx_get_leaf(struct ext4_hash_info *hinfo,\r
- struct ext4_inode_ref *inode_ref,\r
- struct ext4_block *root_block,\r
- struct ext4_directory_dx_block **dx_block,\r
- struct ext4_directory_dx_block *dx_blocks)\r
+ struct ext4_inode_ref *inode_ref,\r
+ struct ext4_block *root_block,\r
+ struct ext4_directory_dx_block **dx_block,\r
+ struct ext4_directory_dx_block *dx_blocks)\r
{\r
- struct ext4_directory_dx_block *tmp_dx_block = dx_blocks;\r
- struct ext4_directory_dx_root *root =\r
- (struct ext4_directory_dx_root *)root_block->data;\r
- struct ext4_directory_dx_entry *entries =\r
- (struct ext4_directory_dx_entry *)&root->entries;\r
-\r
- uint16_t limit = ext4_dir_dx_countlimit_get_limit(\r
- (struct ext4_directory_dx_countlimit *)entries);\r
- uint8_t indirect_level =\r
- ext4_dir_dx_root_info_get_indirect_levels(&root->info);\r
-\r
- struct ext4_block *tmp_block = root_block;\r
- struct ext4_directory_dx_entry *p;\r
- struct ext4_directory_dx_entry *q;\r
- struct ext4_directory_dx_entry *m;\r
- struct ext4_directory_dx_entry *at;\r
-\r
- /* Walk through the index tree */\r
- while (true) {\r
- uint16_t count = ext4_dir_dx_countlimit_get_count(\r
- (struct ext4_directory_dx_countlimit *)entries);\r
- if ((count == 0) || (count > limit))\r
- return EXT4_ERR_BAD_DX_DIR;\r
-\r
- /* Do binary search in every node */\r
- p = entries + 1;\r
- q = entries + count - 1;\r
-\r
- while (p <= q) {\r
- m = p + (q - p) / 2;\r
- if (ext4_dir_dx_entry_get_hash(m) > hinfo->hash)\r
- q = m - 1;\r
- else\r
- p = m + 1;\r
- }\r
-\r
- at = p - 1;\r
-\r
- /* Write results */\r
-\r
- memcpy(&tmp_dx_block->block, tmp_block, sizeof(struct ext4_block));\r
- tmp_dx_block->entries = entries;\r
- tmp_dx_block->position = at;\r
-\r
- /* Is algorithm in the leaf? */\r
- if (indirect_level == 0) {\r
- *dx_block = tmp_dx_block;\r
- return EOK;\r
- }\r
-\r
- /* Goto child node */\r
- uint32_t next_block = ext4_dir_dx_entry_get_block(at);\r
-\r
- indirect_level--;\r
-\r
- uint32_t fblock;\r
- int rc =\r
- ext4_fs_get_inode_data_block_index(inode_ref, next_block, &fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- rc = ext4_block_get(inode_ref->fs->bdev, tmp_block, fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- entries = ((struct ext4_directory_dx_node *)tmp_block->data)->entries;\r
- limit = ext4_dir_dx_countlimit_get_limit(\r
- (struct ext4_directory_dx_countlimit *)entries);\r
-\r
- uint16_t entry_space = ext4_sb_get_block_size(&inode_ref->fs->sb) -\r
- sizeof(struct ext4_fake_directory_entry);\r
-\r
- entry_space = entry_space / sizeof(struct ext4_directory_dx_entry);\r
-\r
- if (limit != entry_space) {\r
- ext4_block_set(inode_ref->fs->bdev, tmp_block);\r
- return EXT4_ERR_BAD_DX_DIR;\r
- }\r
-\r
- ++tmp_dx_block;\r
- }\r
-\r
- /* Unreachable */\r
- return EOK;\r
+ struct ext4_directory_dx_block *tmp_dx_block = dx_blocks;\r
+ struct ext4_directory_dx_root *root =\r
+ (struct ext4_directory_dx_root *)root_block->data;\r
+ struct ext4_directory_dx_entry *entries =\r
+ (struct ext4_directory_dx_entry *)&root->entries;\r
+\r
+ uint16_t limit = ext4_dir_dx_countlimit_get_limit(\r
+ (struct ext4_directory_dx_countlimit *)entries);\r
+ uint8_t indirect_level =\r
+ ext4_dir_dx_root_info_get_indirect_levels(&root->info);\r
+\r
+ struct ext4_block *tmp_block = root_block;\r
+ struct ext4_directory_dx_entry *p;\r
+ struct ext4_directory_dx_entry *q;\r
+ struct ext4_directory_dx_entry *m;\r
+ struct ext4_directory_dx_entry *at;\r
+\r
+ /* Walk through the index tree */\r
+ while (true) {\r
+ uint16_t count = ext4_dir_dx_countlimit_get_count(\r
+ (struct ext4_directory_dx_countlimit *)entries);\r
+ if ((count == 0) || (count > limit))\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+\r
+ /* Do binary search in every node */\r
+ p = entries + 1;\r
+ q = entries + count - 1;\r
+\r
+ while (p <= q) {\r
+ m = p + (q - p) / 2;\r
+ if (ext4_dir_dx_entry_get_hash(m) > hinfo->hash)\r
+ q = m - 1;\r
+ else\r
+ p = m + 1;\r
+ }\r
+\r
+ at = p - 1;\r
+\r
+ /* Write results */\r
+\r
+ memcpy(&tmp_dx_block->block, tmp_block,\r
+ sizeof(struct ext4_block));\r
+ tmp_dx_block->entries = entries;\r
+ tmp_dx_block->position = at;\r
+\r
+ /* Is algorithm in the leaf? */\r
+ if (indirect_level == 0) {\r
+ *dx_block = tmp_dx_block;\r
+ return EOK;\r
+ }\r
+\r
+ /* Goto child node */\r
+ uint32_t next_block = ext4_dir_dx_entry_get_block(at);\r
+\r
+ indirect_level--;\r
+\r
+ uint32_t fblock;\r
+ int rc = ext4_fs_get_inode_data_block_index(\r
+ inode_ref, next_block, &fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ rc = ext4_block_get(inode_ref->fs->bdev, tmp_block, fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ entries =\r
+ ((struct ext4_directory_dx_node *)tmp_block->data)->entries;\r
+ limit = ext4_dir_dx_countlimit_get_limit(\r
+ (struct ext4_directory_dx_countlimit *)entries);\r
+\r
+ uint16_t entry_space =\r
+ ext4_sb_get_block_size(&inode_ref->fs->sb) -\r
+ sizeof(struct ext4_fake_directory_entry);\r
+\r
+ entry_space =\r
+ entry_space / sizeof(struct ext4_directory_dx_entry);\r
+\r
+ if (limit != entry_space) {\r
+ ext4_block_set(inode_ref->fs->bdev, tmp_block);\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+ }\r
+\r
+ ++tmp_dx_block;\r
+ }\r
+\r
+ /* Unreachable */\r
+ return EOK;\r
}\r
\r
/**@brief Check if the the next block would be checked during entry search.\r
* @return Standard Error code\r
*/\r
static int ext4_dir_dx_next_block(struct ext4_inode_ref *inode_ref,\r
- uint32_t hash,\r
- struct ext4_directory_dx_block *dx_block,\r
- struct ext4_directory_dx_block *dx_blocks)\r
+ uint32_t hash,\r
+ struct ext4_directory_dx_block *dx_block,\r
+ struct ext4_directory_dx_block *dx_blocks)\r
{\r
- uint32_t num_handles = 0;\r
- struct ext4_directory_dx_block *p = dx_block;\r
-\r
- /* Try to find data block with next bunch of entries */\r
- while (true) {\r
- p->position++;\r
- uint16_t count = ext4_dir_dx_countlimit_get_count(\r
- (struct ext4_directory_dx_countlimit *)p->entries);\r
-\r
- if (p->position < p->entries + count)\r
- break;\r
-\r
- if (p == dx_blocks)\r
- return EOK;\r
-\r
- num_handles++;\r
- p--;\r
- }\r
-\r
- /* Check hash collision (if not occurred - no next block cannot be used)*/\r
- uint32_t current_hash = ext4_dir_dx_entry_get_hash(p->position);\r
- if ((hash & 1) == 0) {\r
- if ((current_hash & ~1) != hash)\r
- return 0;\r
- }\r
-\r
- /* Fill new path */\r
- while (num_handles--) {\r
- uint32_t block_idx = ext4_dir_dx_entry_get_block(p->position);\r
- uint32_t block_addr;\r
-\r
- int rc = ext4_fs_get_inode_data_block_index(inode_ref, block_idx,\r
- &block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_block block;\r
- rc = ext4_block_get(inode_ref->fs->bdev, &block, block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- p++;\r
-\r
- /* Don't forget to put old block (prevent memory leak) */\r
- rc = ext4_block_set(inode_ref->fs->bdev, &p->block);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- memcpy(&p->block, &p->block, sizeof(block));\r
- p->entries = ((struct ext4_directory_dx_node *)block.data)->entries;\r
- p->position = p->entries;\r
- }\r
-\r
- return ENOENT;\r
+ uint32_t num_handles = 0;\r
+ struct ext4_directory_dx_block *p = dx_block;\r
+\r
+ /* Try to find data block with next bunch of entries */\r
+ while (true) {\r
+ p->position++;\r
+ uint16_t count = ext4_dir_dx_countlimit_get_count(\r
+ (struct ext4_directory_dx_countlimit *)p->entries);\r
+\r
+ if (p->position < p->entries + count)\r
+ break;\r
+\r
+ if (p == dx_blocks)\r
+ return EOK;\r
+\r
+ num_handles++;\r
+ p--;\r
+ }\r
+\r
+ /* Check hash collision (if not occurred - no next block cannot be\r
+ * used)*/\r
+ uint32_t current_hash = ext4_dir_dx_entry_get_hash(p->position);\r
+ if ((hash & 1) == 0) {\r
+ if ((current_hash & ~1) != hash)\r
+ return 0;\r
+ }\r
+\r
+ /* Fill new path */\r
+ while (num_handles--) {\r
+ uint32_t block_idx = ext4_dir_dx_entry_get_block(p->position);\r
+ uint32_t block_addr;\r
+\r
+ int rc = ext4_fs_get_inode_data_block_index(\r
+ inode_ref, block_idx, &block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_block block;\r
+ rc = ext4_block_get(inode_ref->fs->bdev, &block, block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ p++;\r
+\r
+ /* Don't forget to put old block (prevent memory leak) */\r
+ rc = ext4_block_set(inode_ref->fs->bdev, &p->block);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ memcpy(&p->block, &p->block, sizeof(block));\r
+ p->entries =\r
+ ((struct ext4_directory_dx_node *)block.data)->entries;\r
+ p->position = p->entries;\r
+ }\r
+\r
+ return ENOENT;\r
}\r
\r
int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,\r
- struct ext4_inode_ref *inode_ref, size_t name_len,\r
- const char *name)\r
+ struct ext4_inode_ref *inode_ref, size_t name_len,\r
+ const char *name)\r
{\r
- /* Load direct block 0 (index root) */\r
- uint32_t root_block_addr;\r
- int rc2;\r
- int rc = ext4_fs_get_inode_data_block_index(inode_ref, 0, &root_block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_fs *fs = inode_ref->fs;\r
-\r
- struct ext4_block root_block;\r
- rc = ext4_block_get(fs->bdev, &root_block, root_block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Initialize hash info (compute hash value) */\r
- struct ext4_hash_info hinfo;\r
- rc = ext4_dir_hinfo_init(&hinfo, &root_block, &fs->sb, name_len, name);\r
- if (rc != EOK) {\r
- ext4_block_set(fs->bdev, &root_block);\r
- return EXT4_ERR_BAD_DX_DIR;\r
- }\r
-\r
- /*\r
- * Hardcoded number 2 means maximum height of index tree,\r
- * specified in the Linux driver.\r
- */\r
- struct ext4_directory_dx_block dx_blocks[2];\r
- struct ext4_directory_dx_block *dx_block;\r
- struct ext4_directory_dx_block *tmp;\r
-\r
- rc = ext4_dir_dx_get_leaf(&hinfo, inode_ref, &root_block, &dx_block,\r
- dx_blocks);\r
- if (rc != EOK) {\r
- ext4_block_set(fs->bdev, &root_block);\r
- return EXT4_ERR_BAD_DX_DIR;\r
- }\r
-\r
- do {\r
- /* Load leaf block */\r
- uint32_t leaf_block_idx =\r
- ext4_dir_dx_entry_get_block(dx_block->position);\r
- uint32_t leaf_block_addr;\r
-\r
- rc = ext4_fs_get_inode_data_block_index(inode_ref, leaf_block_idx,\r
- &leaf_block_addr);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- struct ext4_block leaf_block;\r
- rc = ext4_block_get(fs->bdev, &leaf_block, leaf_block_addr);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- /* Linear search inside block */\r
- struct ext4_directory_entry_ll *res_dentry;\r
- rc = ext4_dir_find_in_block(&leaf_block, &fs->sb, name_len, name,\r
- &res_dentry);\r
-\r
- /* Found => return it */\r
- if (rc == EOK) {\r
- result->block = leaf_block;\r
- result->dentry = res_dentry;\r
- goto cleanup;\r
- }\r
-\r
- /* Not found, leave untouched */\r
- rc2 = ext4_block_set(fs->bdev, &leaf_block);\r
- if (rc2 != EOK)\r
- goto cleanup;\r
-\r
- if (rc != ENOENT)\r
- goto cleanup;\r
-\r
- /* check if the next block could be checked */\r
- rc = ext4_dir_dx_next_block(inode_ref, hinfo.hash, dx_block,\r
- &dx_blocks[0]);\r
- if (rc < 0)\r
- goto cleanup;\r
- } while (rc == ENOENT);\r
-\r
- /* Entry not found */\r
- rc = ENOENT;\r
+ /* Load direct block 0 (index root) */\r
+ uint32_t root_block_addr;\r
+ int rc2;\r
+ int rc =\r
+ ext4_fs_get_inode_data_block_index(inode_ref, 0, &root_block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_fs *fs = inode_ref->fs;\r
+\r
+ struct ext4_block root_block;\r
+ rc = ext4_block_get(fs->bdev, &root_block, root_block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Initialize hash info (compute hash value) */\r
+ struct ext4_hash_info hinfo;\r
+ rc = ext4_dir_hinfo_init(&hinfo, &root_block, &fs->sb, name_len, name);\r
+ if (rc != EOK) {\r
+ ext4_block_set(fs->bdev, &root_block);\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+ }\r
+\r
+ /*\r
+ * Hardcoded number 2 means maximum height of index tree,\r
+ * specified in the Linux driver.\r
+ */\r
+ struct ext4_directory_dx_block dx_blocks[2];\r
+ struct ext4_directory_dx_block *dx_block;\r
+ struct ext4_directory_dx_block *tmp;\r
+\r
+ rc = ext4_dir_dx_get_leaf(&hinfo, inode_ref, &root_block, &dx_block,\r
+ dx_blocks);\r
+ if (rc != EOK) {\r
+ ext4_block_set(fs->bdev, &root_block);\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+ }\r
+\r
+ do {\r
+ /* Load leaf block */\r
+ uint32_t leaf_block_idx =\r
+ ext4_dir_dx_entry_get_block(dx_block->position);\r
+ uint32_t leaf_block_addr;\r
+\r
+ rc = ext4_fs_get_inode_data_block_index(\r
+ inode_ref, leaf_block_idx, &leaf_block_addr);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ struct ext4_block leaf_block;\r
+ rc = ext4_block_get(fs->bdev, &leaf_block, leaf_block_addr);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ /* Linear search inside block */\r
+ struct ext4_directory_entry_ll *res_dentry;\r
+ rc = ext4_dir_find_in_block(&leaf_block, &fs->sb, name_len,\r
+ name, &res_dentry);\r
+\r
+ /* Found => return it */\r
+ if (rc == EOK) {\r
+ result->block = leaf_block;\r
+ result->dentry = res_dentry;\r
+ goto cleanup;\r
+ }\r
+\r
+ /* Not found, leave untouched */\r
+ rc2 = ext4_block_set(fs->bdev, &leaf_block);\r
+ if (rc2 != EOK)\r
+ goto cleanup;\r
+\r
+ if (rc != ENOENT)\r
+ goto cleanup;\r
+\r
+ /* check if the next block could be checked */\r
+ rc = ext4_dir_dx_next_block(inode_ref, hinfo.hash, dx_block,\r
+ &dx_blocks[0]);\r
+ if (rc < 0)\r
+ goto cleanup;\r
+ } while (rc == ENOENT);\r
+\r
+ /* Entry not found */\r
+ rc = ENOENT;\r
\r
cleanup:\r
- /* The whole path must be released (preventing memory leak) */\r
- tmp = dx_blocks;\r
+ /* The whole path must be released (preventing memory leak) */\r
+ tmp = dx_blocks;\r
\r
- while (tmp <= dx_block) {\r
- rc2 = ext4_block_set(fs->bdev, &tmp->block);\r
- if (rc == EOK && rc2 != EOK)\r
- rc = rc2;\r
- ++tmp;\r
- }\r
+ while (tmp <= dx_block) {\r
+ rc2 = ext4_block_set(fs->bdev, &tmp->block);\r
+ if (rc == EOK && rc2 != EOK)\r
+ rc = rc2;\r
+ ++tmp;\r
+ }\r
\r
- return rc;\r
+ return rc;\r
}\r
\r
#if CONFIG_DIR_INDEX_COMB_SORT\r
#define SWAP_ENTRY(se1, se2) \\r
- do { \\r
- struct ext4_dx_sort_entry tmp = se1; \\r
- se1 = se2; \\r
- se2 = tmp; \\r
- \\r
+ do { \\r
+ struct ext4_dx_sort_entry tmp = se1; \\r
+ se1 = se2; \\r
+ se2 = tmp; \\r
+ \\r
} while (0)\r
\r
static void comb_sort(struct ext4_dx_sort_entry *se, uint32_t count)\r
{\r
- struct ext4_dx_sort_entry *p, *q, *top = se + count - 1;\r
- bool more;\r
- /* Combsort */\r
- while (count > 2) {\r
- count = (count * 10) / 13;\r
- if (count - 9 < 2)\r
- count = 11;\r
- for (p = top, q = p - count; q >= se; p--, q--)\r
- if (p->hash < q->hash)\r
- SWAP_ENTRY(*p, *q);\r
- }\r
- /* Bubblesort */\r
- do {\r
- more = 0;\r
- q = top;\r
- while (q-- > se) {\r
- if (q[1].hash >= q[0].hash)\r
- continue;\r
- SWAP_ENTRY(*(q + 1), *q);\r
- more = 1;\r
- }\r
- } while (more);\r
+ struct ext4_dx_sort_entry *p, *q, *top = se + count - 1;\r
+ bool more;\r
+ /* Combsort */\r
+ while (count > 2) {\r
+ count = (count * 10) / 13;\r
+ if (count - 9 < 2)\r
+ count = 11;\r
+ for (p = top, q = p - count; q >= se; p--, q--)\r
+ if (p->hash < q->hash)\r
+ SWAP_ENTRY(*p, *q);\r
+ }\r
+ /* Bubblesort */\r
+ do {\r
+ more = 0;\r
+ q = top;\r
+ while (q-- > se) {\r
+ if (q[1].hash >= q[0].hash)\r
+ continue;\r
+ SWAP_ENTRY(*(q + 1), *q);\r
+ more = 1;\r
+ }\r
+ } while (more);\r
}\r
#else\r
\r
*/\r
static int ext4_dir_dx_entry_comparator(const void *arg1, const void *arg2)\r
{\r
- struct ext4_dx_sort_entry *entry1 = (void *)arg1;\r
- struct ext4_dx_sort_entry *entry2 = (void *)arg2;\r
+ struct ext4_dx_sort_entry *entry1 = (void *)arg1;\r
+ struct ext4_dx_sort_entry *entry2 = (void *)arg2;\r
\r
- if (entry1->hash == entry2->hash)\r
- return 0;\r
+ if (entry1->hash == entry2->hash)\r
+ return 0;\r
\r
- if (entry1->hash < entry2->hash)\r
- return -1;\r
- else\r
- return 1;\r
+ if (entry1->hash < entry2->hash)\r
+ return -1;\r
+ else\r
+ return 1;\r
}\r
#endif\r
\r
*/\r
static void\r
ext4_dir_dx_insert_entry(struct ext4_directory_dx_block *index_block,\r
- uint32_t hash, uint32_t iblock)\r
+ uint32_t hash, uint32_t iblock)\r
{\r
- struct ext4_directory_dx_entry *old_index_entry = index_block->position;\r
- struct ext4_directory_dx_entry *new_index_entry = old_index_entry + 1;\r
+ struct ext4_directory_dx_entry *old_index_entry = index_block->position;\r
+ struct ext4_directory_dx_entry *new_index_entry = old_index_entry + 1;\r
\r
- struct ext4_directory_dx_countlimit *countlimit =\r
- (struct ext4_directory_dx_countlimit *)index_block->entries;\r
- uint32_t count = ext4_dir_dx_countlimit_get_count(countlimit);\r
+ struct ext4_directory_dx_countlimit *countlimit =\r
+ (struct ext4_directory_dx_countlimit *)index_block->entries;\r
+ uint32_t count = ext4_dir_dx_countlimit_get_count(countlimit);\r
\r
- struct ext4_directory_dx_entry *start_index = index_block->entries;\r
- size_t bytes =\r
- (uint8_t *)(start_index + count) - (uint8_t *)(new_index_entry);\r
+ struct ext4_directory_dx_entry *start_index = index_block->entries;\r
+ size_t bytes =\r
+ (uint8_t *)(start_index + count) - (uint8_t *)(new_index_entry);\r
\r
- memmove(new_index_entry + 1, new_index_entry, bytes);\r
+ memmove(new_index_entry + 1, new_index_entry, bytes);\r
\r
- ext4_dir_dx_entry_set_block(new_index_entry, iblock);\r
- ext4_dir_dx_entry_set_hash(new_index_entry, hash);\r
+ ext4_dir_dx_entry_set_block(new_index_entry, iblock);\r
+ ext4_dir_dx_entry_set_hash(new_index_entry, hash);\r
\r
- ext4_dir_dx_countlimit_set_count(countlimit, count + 1);\r
+ ext4_dir_dx_countlimit_set_count(countlimit, count + 1);\r
\r
- index_block->block.dirty = true;\r
+ index_block->block.dirty = true;\r
}\r
\r
/**@brief Split directory entries to two parts preventing node overflow.\r
* @param new_data_block Output value for newly allocated data block\r
*/\r
static int ext4_dir_dx_split_data(struct ext4_inode_ref *inode_ref,\r
- struct ext4_hash_info *hinfo,\r
- struct ext4_block *old_data_block,\r
- struct ext4_directory_dx_block *index_block,\r
- struct ext4_block *new_data_block)\r
+ struct ext4_hash_info *hinfo,\r
+ struct ext4_block *old_data_block,\r
+ struct ext4_directory_dx_block *index_block,\r
+ struct ext4_block *new_data_block)\r
{\r
- int rc = EOK;\r
+ int rc = EOK;\r
\r
- /* Allocate buffer for directory entries */\r
- uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
+ /* Allocate buffer for directory entries */\r
+ uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
\r
- uint8_t *entry_buffer = malloc(block_size);\r
- if (entry_buffer == NULL)\r
- return ENOMEM;\r
+ uint8_t *entry_buffer = malloc(block_size);\r
+ if (entry_buffer == NULL)\r
+ return ENOMEM;\r
\r
- /* dot entry has the smallest size available */\r
- uint32_t max_entry_count =\r
- block_size / sizeof(struct ext4_directory_dx_dot_entry);\r
+ /* dot entry has the smallest size available */\r
+ uint32_t max_entry_count =\r
+ block_size / sizeof(struct ext4_directory_dx_dot_entry);\r
\r
- /* Allocate sort entry */\r
- struct ext4_dx_sort_entry *sort_array =\r
- malloc(max_entry_count * sizeof(struct ext4_dx_sort_entry));\r
+ /* Allocate sort entry */\r
+ struct ext4_dx_sort_entry *sort_array =\r
+ malloc(max_entry_count * sizeof(struct ext4_dx_sort_entry));\r
\r
- if (sort_array == NULL) {\r
- free(entry_buffer);\r
- return ENOMEM;\r
- }\r
+ if (sort_array == NULL) {\r
+ free(entry_buffer);\r
+ return ENOMEM;\r
+ }\r
\r
- uint32_t idx = 0;\r
- uint32_t real_size = 0;\r
+ uint32_t idx = 0;\r
+ uint32_t real_size = 0;\r
\r
- /* Initialize hinfo */\r
- struct ext4_hash_info tmp_hinfo;\r
- memcpy(&tmp_hinfo, hinfo, sizeof(struct ext4_hash_info));\r
+ /* Initialize hinfo */\r
+ struct ext4_hash_info tmp_hinfo;\r
+ memcpy(&tmp_hinfo, hinfo, sizeof(struct ext4_hash_info));\r
\r
- /* Load all valid entries to the buffer */\r
- struct ext4_directory_entry_ll *dentry = (void *)old_data_block->data;\r
- uint8_t *entry_buffer_ptr = entry_buffer;\r
- while ((void *)dentry < (void *)(old_data_block->data + block_size)) {\r
- /* Read only valid entries */\r
- if (ext4_dir_entry_ll_get_inode(dentry) && dentry->name_length) {\r
- uint8_t len =\r
- ext4_dir_entry_ll_get_name_length(&inode_ref->fs->sb, dentry);\r
+ /* Load all valid entries to the buffer */\r
+ struct ext4_directory_entry_ll *dentry = (void *)old_data_block->data;\r
+ uint8_t *entry_buffer_ptr = entry_buffer;\r
+ while ((void *)dentry < (void *)(old_data_block->data + block_size)) {\r
+ /* Read only valid entries */\r
+ if (ext4_dir_entry_ll_get_inode(dentry) &&\r
+ dentry->name_length) {\r
+ uint8_t len = ext4_dir_entry_ll_get_name_length(\r
+ &inode_ref->fs->sb, dentry);\r
\r
- rc = ext4_dir_dx_hash_string(&tmp_hinfo, len, (char *)dentry->name);\r
- if (rc != EOK) {\r
- free(sort_array);\r
- free(entry_buffer);\r
- return rc;\r
- }\r
+ rc = ext4_dir_dx_hash_string(&tmp_hinfo, len,\r
+ (char *)dentry->name);\r
+ if (rc != EOK) {\r
+ free(sort_array);\r
+ free(entry_buffer);\r
+ return rc;\r
+ }\r
\r
- uint32_t rec_len = 8 + len;\r
+ uint32_t rec_len = 8 + len;\r
\r
- if ((rec_len % 4) != 0)\r
- rec_len += 4 - (rec_len % 4);\r
+ if ((rec_len % 4) != 0)\r
+ rec_len += 4 - (rec_len % 4);\r
\r
- memcpy(entry_buffer_ptr, dentry, rec_len);\r
+ memcpy(entry_buffer_ptr, dentry, rec_len);\r
\r
- sort_array[idx].dentry = entry_buffer_ptr;\r
- sort_array[idx].rec_len = rec_len;\r
- sort_array[idx].hash = tmp_hinfo.hash;\r
+ sort_array[idx].dentry = entry_buffer_ptr;\r
+ sort_array[idx].rec_len = rec_len;\r
+ sort_array[idx].hash = tmp_hinfo.hash;\r
\r
- entry_buffer_ptr += rec_len;\r
- real_size += rec_len;\r
- idx++;\r
- }\r
+ entry_buffer_ptr += rec_len;\r
+ real_size += rec_len;\r
+ idx++;\r
+ }\r
\r
- dentry = (void *)((uint8_t *)dentry +\r
- ext4_dir_entry_ll_get_entry_length(dentry));\r
- }\r
+ dentry = (void *)((uint8_t *)dentry +\r
+ ext4_dir_entry_ll_get_entry_length(dentry));\r
+ }\r
\r
/* Sort all entries */\r
#if CONFIG_DIR_INDEX_COMB_SORT\r
- comb_sort(sort_array, idx);\r
+ comb_sort(sort_array, idx);\r
#else\r
- qsort(sort_array, idx, sizeof(struct ext4_dx_sort_entry),\r
- ext4_dir_dx_entry_comparator);\r
+ qsort(sort_array, idx, sizeof(struct ext4_dx_sort_entry),\r
+ ext4_dir_dx_entry_comparator);\r
#endif\r
- /* Allocate new block for store the second part of entries */\r
- uint32_t new_fblock;\r
- uint32_t new_iblock;\r
- rc = ext4_fs_append_inode_block(inode_ref, &new_fblock, &new_iblock);\r
- if (rc != EOK) {\r
- free(sort_array);\r
- free(entry_buffer);\r
- return rc;\r
- }\r
-\r
- /* Load new block */\r
- struct ext4_block new_data_block_tmp;\r
- rc = ext4_block_get(inode_ref->fs->bdev, &new_data_block_tmp, new_fblock);\r
- if (rc != EOK) {\r
- free(sort_array);\r
- free(entry_buffer);\r
- return rc;\r
- }\r
-\r
- /*\r
- * Distribute entries to two blocks (by size)\r
- * - compute the half\r
- */\r
- uint32_t new_hash = 0;\r
- uint32_t current_size = 0;\r
- uint32_t mid = 0;\r
- uint32_t i;\r
- for (i = 0; i < idx; ++i) {\r
- if ((current_size + sort_array[i].rec_len) > (block_size / 2)) {\r
- new_hash = sort_array[i].hash;\r
- mid = i;\r
- break;\r
- }\r
-\r
- current_size += sort_array[i].rec_len;\r
- }\r
-\r
- /* Check hash collision */\r
- uint32_t continued = 0;\r
- if (new_hash == sort_array[mid - 1].hash)\r
- continued = 1;\r
-\r
- uint32_t offset = 0;\r
- void *ptr;\r
-\r
- /* First part - to the old block */\r
- for (i = 0; i < mid; ++i) {\r
- ptr = old_data_block->data + offset;\r
- memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);\r
-\r
- struct ext4_directory_entry_ll *tmp = ptr;\r
- if (i < (mid - 1))\r
- ext4_dir_entry_ll_set_entry_length(tmp, sort_array[i].rec_len);\r
- else\r
- ext4_dir_entry_ll_set_entry_length(tmp, block_size - offset);\r
-\r
- offset += sort_array[i].rec_len;\r
- }\r
-\r
- /* Second part - to the new block */\r
- offset = 0;\r
- for (i = mid; i < idx; ++i) {\r
- ptr = new_data_block_tmp.data + offset;\r
- memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);\r
-\r
- struct ext4_directory_entry_ll *tmp = ptr;\r
- if (i < (idx - 1))\r
- ext4_dir_entry_ll_set_entry_length(tmp, sort_array[i].rec_len);\r
- else\r
- ext4_dir_entry_ll_set_entry_length(tmp, block_size - offset);\r
-\r
- offset += sort_array[i].rec_len;\r
- }\r
-\r
- /* Do some steps to finish operation */\r
- old_data_block->dirty = true;\r
- new_data_block_tmp.dirty = true;\r
-\r
- free(sort_array);\r
- free(entry_buffer);\r
-\r
- ext4_dir_dx_insert_entry(index_block, new_hash + continued, new_iblock);\r
-\r
- *new_data_block = new_data_block_tmp;\r
-\r
- return EOK;\r
+ /* Allocate new block for store the second part of entries */\r
+ uint32_t new_fblock;\r
+ uint32_t new_iblock;\r
+ rc = ext4_fs_append_inode_block(inode_ref, &new_fblock, &new_iblock);\r
+ if (rc != EOK) {\r
+ free(sort_array);\r
+ free(entry_buffer);\r
+ return rc;\r
+ }\r
+\r
+ /* Load new block */\r
+ struct ext4_block new_data_block_tmp;\r
+ rc = ext4_block_get(inode_ref->fs->bdev, &new_data_block_tmp,\r
+ new_fblock);\r
+ if (rc != EOK) {\r
+ free(sort_array);\r
+ free(entry_buffer);\r
+ return rc;\r
+ }\r
+\r
+ /*\r
+ * Distribute entries to two blocks (by size)\r
+ * - compute the half\r
+ */\r
+ uint32_t new_hash = 0;\r
+ uint32_t current_size = 0;\r
+ uint32_t mid = 0;\r
+ uint32_t i;\r
+ for (i = 0; i < idx; ++i) {\r
+ if ((current_size + sort_array[i].rec_len) > (block_size / 2)) {\r
+ new_hash = sort_array[i].hash;\r
+ mid = i;\r
+ break;\r
+ }\r
+\r
+ current_size += sort_array[i].rec_len;\r
+ }\r
+\r
+ /* Check hash collision */\r
+ uint32_t continued = 0;\r
+ if (new_hash == sort_array[mid - 1].hash)\r
+ continued = 1;\r
+\r
+ uint32_t offset = 0;\r
+ void *ptr;\r
+\r
+ /* First part - to the old block */\r
+ for (i = 0; i < mid; ++i) {\r
+ ptr = old_data_block->data + offset;\r
+ memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);\r
+\r
+ struct ext4_directory_entry_ll *tmp = ptr;\r
+ if (i < (mid - 1))\r
+ ext4_dir_entry_ll_set_entry_length(\r
+ tmp, sort_array[i].rec_len);\r
+ else\r
+ ext4_dir_entry_ll_set_entry_length(tmp,\r
+ block_size - offset);\r
+\r
+ offset += sort_array[i].rec_len;\r
+ }\r
+\r
+ /* Second part - to the new block */\r
+ offset = 0;\r
+ for (i = mid; i < idx; ++i) {\r
+ ptr = new_data_block_tmp.data + offset;\r
+ memcpy(ptr, sort_array[i].dentry, sort_array[i].rec_len);\r
+\r
+ struct ext4_directory_entry_ll *tmp = ptr;\r
+ if (i < (idx - 1))\r
+ ext4_dir_entry_ll_set_entry_length(\r
+ tmp, sort_array[i].rec_len);\r
+ else\r
+ ext4_dir_entry_ll_set_entry_length(tmp,\r
+ block_size - offset);\r
+\r
+ offset += sort_array[i].rec_len;\r
+ }\r
+\r
+ /* Do some steps to finish operation */\r
+ old_data_block->dirty = true;\r
+ new_data_block_tmp.dirty = true;\r
+\r
+ free(sort_array);\r
+ free(entry_buffer);\r
+\r
+ ext4_dir_dx_insert_entry(index_block, new_hash + continued, new_iblock);\r
+\r
+ *new_data_block = new_data_block_tmp;\r
+\r
+ return EOK;\r
}\r
\r
/**@brief Split index node and maybe some parent nodes in the tree hierarchy.\r
*/\r
static int\r
ext4_dir_dx_split_index(struct ext4_inode_ref *inode_ref,\r
- struct ext4_directory_dx_block *dx_blocks,\r
- struct ext4_directory_dx_block *dx_block,\r
- struct ext4_directory_dx_block **new_dx_block)\r
+ struct ext4_directory_dx_block *dx_blocks,\r
+ struct ext4_directory_dx_block *dx_block,\r
+ struct ext4_directory_dx_block **new_dx_block)\r
{\r
- struct ext4_directory_dx_entry *entries;\r
-\r
- if (dx_block == dx_blocks)\r
- entries =\r
- ((struct ext4_directory_dx_root *)dx_block->block.data)->entries;\r
- else\r
- entries =\r
- ((struct ext4_directory_dx_node *)dx_block->block.data)->entries;\r
-\r
- struct ext4_directory_dx_countlimit *countlimit =\r
- (struct ext4_directory_dx_countlimit *)entries;\r
-\r
- uint16_t leaf_limit = ext4_dir_dx_countlimit_get_limit(countlimit);\r
- uint16_t leaf_count = ext4_dir_dx_countlimit_get_count(countlimit);\r
-\r
- /* Check if is necessary to split index block */\r
- if (leaf_limit == leaf_count) {\r
- size_t levels = dx_block - dx_blocks;\r
-\r
- struct ext4_directory_dx_entry *root_entries =\r
- ((struct ext4_directory_dx_root *)dx_blocks[0].block.data)->entries;\r
-\r
- struct ext4_directory_dx_countlimit *root_countlimit =\r
- (struct ext4_directory_dx_countlimit *)root_entries;\r
- uint16_t root_limit = ext4_dir_dx_countlimit_get_limit(root_countlimit);\r
- uint16_t root_count = ext4_dir_dx_countlimit_get_count(root_countlimit);\r
-\r
- /* Linux limitation */\r
- if ((levels > 0) && (root_limit == root_count))\r
- return ENOSPC;\r
-\r
- /* Add new block to directory */\r
- uint32_t new_fblock;\r
- uint32_t new_iblock;\r
- int rc =\r
- ext4_fs_append_inode_block(inode_ref, &new_fblock, &new_iblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* load new block */\r
- struct ext4_block new_block;\r
- rc = ext4_block_get(inode_ref->fs->bdev, &new_block, new_fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_directory_dx_node *new_node = (void *)new_block.data;\r
- struct ext4_directory_dx_entry *new_entries = new_node->entries;\r
-\r
- memset(&new_node->fake, 0, sizeof(struct ext4_fake_directory_entry));\r
-\r
- uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
-\r
- new_node->fake.entry_length = block_size;\r
-\r
- /* Split leaf node */\r
- if (levels > 0) {\r
- uint32_t count_left = leaf_count / 2;\r
- uint32_t count_right = leaf_count - count_left;\r
- uint32_t hash_right =\r
- ext4_dir_dx_entry_get_hash(entries + count_left);\r
-\r
- /* Copy data to new node */\r
- memcpy((void *)new_entries, (void *)(entries + count_left),\r
- count_right * sizeof(struct ext4_directory_dx_entry));\r
-\r
- /* Initialize new node */\r
- struct ext4_directory_dx_countlimit *left_countlimit =\r
- (struct ext4_directory_dx_countlimit *)entries;\r
- struct ext4_directory_dx_countlimit *right_countlimit =\r
- (struct ext4_directory_dx_countlimit *)new_entries;\r
-\r
- ext4_dir_dx_countlimit_set_count(left_countlimit, count_left);\r
- ext4_dir_dx_countlimit_set_count(right_countlimit, count_right);\r
-\r
- uint32_t entry_space =\r
- block_size - sizeof(struct ext4_fake_directory_entry);\r
- uint32_t node_limit =\r
- entry_space / sizeof(struct ext4_directory_dx_entry);\r
- ext4_dir_dx_countlimit_set_limit(right_countlimit, node_limit);\r
-\r
- /* Which index block is target for new entry */\r
- uint32_t position_index = (dx_block->position - dx_block->entries);\r
- if (position_index >= count_left) {\r
- dx_block->block.dirty = true;\r
-\r
- struct ext4_block block_tmp = dx_block->block;\r
-\r
- dx_block->block = new_block;\r
-\r
- dx_block->position = new_entries + position_index - count_left;\r
- dx_block->entries = new_entries;\r
-\r
- new_block = block_tmp;\r
- }\r
-\r
- /* Finally insert new entry */\r
- ext4_dir_dx_insert_entry(dx_blocks, hash_right, new_iblock);\r
- dx_blocks[0].block.dirty = true;\r
- dx_blocks[1].block.dirty = true;\r
-\r
- new_block.dirty = true;\r
- return ext4_block_set(inode_ref->fs->bdev, &new_block);\r
- } else {\r
- /* Create second level index */\r
-\r
- /* Copy data from root to child block */\r
- memcpy((void *)new_entries, (void *)entries,\r
- leaf_count * sizeof(struct ext4_directory_dx_entry));\r
-\r
- struct ext4_directory_dx_countlimit *new_countlimit =\r
- (struct ext4_directory_dx_countlimit *)new_entries;\r
-\r
- uint32_t entry_space =\r
- block_size - sizeof(struct ext4_fake_directory_entry);\r
- uint32_t node_limit =\r
- entry_space / sizeof(struct ext4_directory_dx_entry);\r
- ext4_dir_dx_countlimit_set_limit(new_countlimit, node_limit);\r
-\r
- /* Set values in root node */\r
- struct ext4_directory_dx_countlimit *new_root_countlimit =\r
- (struct ext4_directory_dx_countlimit *)entries;\r
-\r
- ext4_dir_dx_countlimit_set_count(new_root_countlimit, 1);\r
- ext4_dir_dx_entry_set_block(entries, new_iblock);\r
-\r
- ((struct ext4_directory_dx_root *)dx_blocks[0].block.data)\r
- ->info.indirect_levels = 1;\r
-\r
- /* Add new entry to the path */\r
- dx_block = dx_blocks + 1;\r
- dx_block->position = dx_blocks->position - entries + new_entries;\r
- dx_block->entries = new_entries;\r
- dx_block->block = new_block;\r
-\r
- *new_dx_block = dx_block;\r
-\r
- dx_blocks[0].block.dirty = true;\r
- dx_blocks[1].block.dirty = true;\r
- }\r
- }\r
-\r
- return EOK;\r
+ struct ext4_directory_dx_entry *entries;\r
+\r
+ if (dx_block == dx_blocks)\r
+ entries =\r
+ ((struct ext4_directory_dx_root *)dx_block->block.data)\r
+ ->entries;\r
+ else\r
+ entries =\r
+ ((struct ext4_directory_dx_node *)dx_block->block.data)\r
+ ->entries;\r
+\r
+ struct ext4_directory_dx_countlimit *countlimit =\r
+ (struct ext4_directory_dx_countlimit *)entries;\r
+\r
+ uint16_t leaf_limit = ext4_dir_dx_countlimit_get_limit(countlimit);\r
+ uint16_t leaf_count = ext4_dir_dx_countlimit_get_count(countlimit);\r
+\r
+ /* Check if is necessary to split index block */\r
+ if (leaf_limit == leaf_count) {\r
+ size_t levels = dx_block - dx_blocks;\r
+\r
+ struct ext4_directory_dx_entry *root_entries =\r
+ ((struct ext4_directory_dx_root *)dx_blocks[0].block.data)\r
+ ->entries;\r
+\r
+ struct ext4_directory_dx_countlimit *root_countlimit =\r
+ (struct ext4_directory_dx_countlimit *)root_entries;\r
+ uint16_t root_limit =\r
+ ext4_dir_dx_countlimit_get_limit(root_countlimit);\r
+ uint16_t root_count =\r
+ ext4_dir_dx_countlimit_get_count(root_countlimit);\r
+\r
+ /* Linux limitation */\r
+ if ((levels > 0) && (root_limit == root_count))\r
+ return ENOSPC;\r
+\r
+ /* Add new block to directory */\r
+ uint32_t new_fblock;\r
+ uint32_t new_iblock;\r
+ int rc = ext4_fs_append_inode_block(inode_ref, &new_fblock,\r
+ &new_iblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* load new block */\r
+ struct ext4_block new_block;\r
+ rc =\r
+ ext4_block_get(inode_ref->fs->bdev, &new_block, new_fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_directory_dx_node *new_node =\r
+ (void *)new_block.data;\r
+ struct ext4_directory_dx_entry *new_entries = new_node->entries;\r
+\r
+ memset(&new_node->fake, 0,\r
+ sizeof(struct ext4_fake_directory_entry));\r
+\r
+ uint32_t block_size =\r
+ ext4_sb_get_block_size(&inode_ref->fs->sb);\r
+\r
+ new_node->fake.entry_length = block_size;\r
+\r
+ /* Split leaf node */\r
+ if (levels > 0) {\r
+ uint32_t count_left = leaf_count / 2;\r
+ uint32_t count_right = leaf_count - count_left;\r
+ uint32_t hash_right =\r
+ ext4_dir_dx_entry_get_hash(entries + count_left);\r
+\r
+ /* Copy data to new node */\r
+ memcpy((void *)new_entries,\r
+ (void *)(entries + count_left),\r
+ count_right *\r
+ sizeof(struct ext4_directory_dx_entry));\r
+\r
+ /* Initialize new node */\r
+ struct ext4_directory_dx_countlimit *left_countlimit =\r
+ (struct ext4_directory_dx_countlimit *)entries;\r
+ struct ext4_directory_dx_countlimit *right_countlimit =\r
+ (struct ext4_directory_dx_countlimit *)new_entries;\r
+\r
+ ext4_dir_dx_countlimit_set_count(left_countlimit,\r
+ count_left);\r
+ ext4_dir_dx_countlimit_set_count(right_countlimit,\r
+ count_right);\r
+\r
+ uint32_t entry_space =\r
+ block_size -\r
+ sizeof(struct ext4_fake_directory_entry);\r
+ uint32_t node_limit =\r
+ entry_space /\r
+ sizeof(struct ext4_directory_dx_entry);\r
+ ext4_dir_dx_countlimit_set_limit(right_countlimit,\r
+ node_limit);\r
+\r
+ /* Which index block is target for new entry */\r
+ uint32_t position_index =\r
+ (dx_block->position - dx_block->entries);\r
+ if (position_index >= count_left) {\r
+ dx_block->block.dirty = true;\r
+\r
+ struct ext4_block block_tmp = dx_block->block;\r
+\r
+ dx_block->block = new_block;\r
+\r
+ dx_block->position =\r
+ new_entries + position_index - count_left;\r
+ dx_block->entries = new_entries;\r
+\r
+ new_block = block_tmp;\r
+ }\r
+\r
+ /* Finally insert new entry */\r
+ ext4_dir_dx_insert_entry(dx_blocks, hash_right,\r
+ new_iblock);\r
+ dx_blocks[0].block.dirty = true;\r
+ dx_blocks[1].block.dirty = true;\r
+\r
+ new_block.dirty = true;\r
+ return ext4_block_set(inode_ref->fs->bdev, &new_block);\r
+ } else {\r
+ /* Create second level index */\r
+\r
+ /* Copy data from root to child block */\r
+ memcpy((void *)new_entries, (void *)entries,\r
+ leaf_count *\r
+ sizeof(struct ext4_directory_dx_entry));\r
+\r
+ struct ext4_directory_dx_countlimit *new_countlimit =\r
+ (struct ext4_directory_dx_countlimit *)new_entries;\r
+\r
+ uint32_t entry_space =\r
+ block_size -\r
+ sizeof(struct ext4_fake_directory_entry);\r
+ uint32_t node_limit =\r
+ entry_space /\r
+ sizeof(struct ext4_directory_dx_entry);\r
+ ext4_dir_dx_countlimit_set_limit(new_countlimit,\r
+ node_limit);\r
+\r
+ /* Set values in root node */\r
+ struct ext4_directory_dx_countlimit\r
+ *new_root_countlimit =\r
+ (struct ext4_directory_dx_countlimit *)entries;\r
+\r
+ ext4_dir_dx_countlimit_set_count(new_root_countlimit,\r
+ 1);\r
+ ext4_dir_dx_entry_set_block(entries, new_iblock);\r
+\r
+ ((struct ext4_directory_dx_root *)dx_blocks[0]\r
+ .block.data)\r
+ ->info.indirect_levels = 1;\r
+\r
+ /* Add new entry to the path */\r
+ dx_block = dx_blocks + 1;\r
+ dx_block->position =\r
+ dx_blocks->position - entries + new_entries;\r
+ dx_block->entries = new_entries;\r
+ dx_block->block = new_block;\r
+\r
+ *new_dx_block = dx_block;\r
+\r
+ dx_blocks[0].block.dirty = true;\r
+ dx_blocks[1].block.dirty = true;\r
+ }\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,\r
- struct ext4_inode_ref *child, const char *name)\r
+ struct ext4_inode_ref *child, const char *name)\r
{\r
- int rc2 = EOK;\r
-\r
- /* Get direct block 0 (index root) */\r
- uint32_t root_block_addr;\r
- int rc = ext4_fs_get_inode_data_block_index(parent, 0, &root_block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_fs *fs = parent->fs;\r
- struct ext4_block root_block;\r
-\r
- rc = ext4_block_get(fs->bdev, &root_block, root_block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Initialize hinfo structure (mainly compute hash) */\r
- uint32_t name_len = strlen(name);\r
- struct ext4_hash_info hinfo;\r
- rc = ext4_dir_hinfo_init(&hinfo, &root_block, &fs->sb, name_len, name);\r
- if (rc != EOK) {\r
- ext4_block_set(fs->bdev, &root_block);\r
- return EXT4_ERR_BAD_DX_DIR;\r
- }\r
-\r
- /*\r
- * Hardcoded number 2 means maximum height of index\r
- * tree defined in Linux.\r
- */\r
- struct ext4_directory_dx_block dx_blocks[2];\r
- struct ext4_directory_dx_block *dx_block;\r
- struct ext4_directory_dx_block *dx_it;\r
-\r
- rc =\r
- ext4_dir_dx_get_leaf(&hinfo, parent, &root_block, &dx_block, dx_blocks);\r
- if (rc != EOK) {\r
- rc = EXT4_ERR_BAD_DX_DIR;\r
- goto release_index;\r
- }\r
-\r
- /* Try to insert to existing data block */\r
- uint32_t leaf_block_idx = ext4_dir_dx_entry_get_block(dx_block->position);\r
- uint32_t leaf_block_addr;\r
- rc = ext4_fs_get_inode_data_block_index(parent, leaf_block_idx,\r
- &leaf_block_addr);\r
- if (rc != EOK)\r
- goto release_index;\r
-\r
- /*\r
- * Check if there is needed to split index node\r
- * (and recursively also parent nodes)\r
- */\r
- rc = ext4_dir_dx_split_index(parent, dx_blocks, dx_block, &dx_block);\r
- if (rc != EOK)\r
- goto release_target_index;\r
-\r
- struct ext4_block target_block;\r
- rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);\r
- if (rc != EOK)\r
- goto release_index;\r
-\r
- /* Check if insert operation passed */\r
- rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child, name,\r
- name_len);\r
- if (rc == EOK)\r
- goto release_target_index;\r
-\r
- /* Split entries to two blocks (includes sorting by hash value) */\r
- struct ext4_block new_block;\r
- rc = ext4_dir_dx_split_data(parent, &hinfo, &target_block, dx_block,\r
- &new_block);\r
- if (rc != EOK) {\r
- rc2 = rc;\r
- goto release_target_index;\r
- }\r
-\r
- /* Where to save new entry */\r
- uint32_t new_block_hash =\r
- ext4_dir_dx_entry_get_hash(dx_block->position + 1);\r
- if (hinfo.hash >= new_block_hash)\r
- rc = ext4_dir_try_insert_entry(&fs->sb, &new_block, child, name,\r
- name_len);\r
- else\r
- rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child, name,\r
- name_len);\r
-\r
- /* Cleanup */\r
- rc = ext4_block_set(fs->bdev, &new_block);\r
- if (rc != EOK)\r
- return rc;\r
+ int rc2 = EOK;\r
+\r
+ /* Get direct block 0 (index root) */\r
+ uint32_t root_block_addr;\r
+ int rc =\r
+ ext4_fs_get_inode_data_block_index(parent, 0, &root_block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_fs *fs = parent->fs;\r
+ struct ext4_block root_block;\r
+\r
+ rc = ext4_block_get(fs->bdev, &root_block, root_block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Initialize hinfo structure (mainly compute hash) */\r
+ uint32_t name_len = strlen(name);\r
+ struct ext4_hash_info hinfo;\r
+ rc = ext4_dir_hinfo_init(&hinfo, &root_block, &fs->sb, name_len, name);\r
+ if (rc != EOK) {\r
+ ext4_block_set(fs->bdev, &root_block);\r
+ return EXT4_ERR_BAD_DX_DIR;\r
+ }\r
+\r
+ /*\r
+ * Hardcoded number 2 means maximum height of index\r
+ * tree defined in Linux.\r
+ */\r
+ struct ext4_directory_dx_block dx_blocks[2];\r
+ struct ext4_directory_dx_block *dx_block;\r
+ struct ext4_directory_dx_block *dx_it;\r
+\r
+ rc = ext4_dir_dx_get_leaf(&hinfo, parent, &root_block, &dx_block,\r
+ dx_blocks);\r
+ if (rc != EOK) {\r
+ rc = EXT4_ERR_BAD_DX_DIR;\r
+ goto release_index;\r
+ }\r
+\r
+ /* Try to insert to existing data block */\r
+ uint32_t leaf_block_idx =\r
+ ext4_dir_dx_entry_get_block(dx_block->position);\r
+ uint32_t leaf_block_addr;\r
+ rc = ext4_fs_get_inode_data_block_index(parent, leaf_block_idx,\r
+ &leaf_block_addr);\r
+ if (rc != EOK)\r
+ goto release_index;\r
+\r
+ /*\r
+ * Check if there is needed to split index node\r
+ * (and recursively also parent nodes)\r
+ */\r
+ rc = ext4_dir_dx_split_index(parent, dx_blocks, dx_block, &dx_block);\r
+ if (rc != EOK)\r
+ goto release_target_index;\r
+\r
+ struct ext4_block target_block;\r
+ rc = ext4_block_get(fs->bdev, &target_block, leaf_block_addr);\r
+ if (rc != EOK)\r
+ goto release_index;\r
+\r
+ /* Check if insert operation passed */\r
+ rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child, name,\r
+ name_len);\r
+ if (rc == EOK)\r
+ goto release_target_index;\r
+\r
+ /* Split entries to two blocks (includes sorting by hash value) */\r
+ struct ext4_block new_block;\r
+ rc = ext4_dir_dx_split_data(parent, &hinfo, &target_block, dx_block,\r
+ &new_block);\r
+ if (rc != EOK) {\r
+ rc2 = rc;\r
+ goto release_target_index;\r
+ }\r
+\r
+ /* Where to save new entry */\r
+ uint32_t new_block_hash =\r
+ ext4_dir_dx_entry_get_hash(dx_block->position + 1);\r
+ if (hinfo.hash >= new_block_hash)\r
+ rc = ext4_dir_try_insert_entry(&fs->sb, &new_block, child, name,\r
+ name_len);\r
+ else\r
+ rc = ext4_dir_try_insert_entry(&fs->sb, &target_block, child,\r
+ name, name_len);\r
+\r
+ /* Cleanup */\r
+ rc = ext4_block_set(fs->bdev, &new_block);\r
+ if (rc != EOK)\r
+ return rc;\r
\r
/* Cleanup operations */\r
\r
release_target_index:\r
- rc2 = rc;\r
+ rc2 = rc;\r
\r
- rc = ext4_block_set(fs->bdev, &target_block);\r
- if (rc != EOK)\r
- return rc;\r
+ rc = ext4_block_set(fs->bdev, &target_block);\r
+ if (rc != EOK)\r
+ return rc;\r
\r
release_index:\r
- if (rc != EOK)\r
- rc2 = rc;\r
+ if (rc != EOK)\r
+ rc2 = rc;\r
\r
- dx_it = dx_blocks;\r
+ dx_it = dx_blocks;\r
\r
- while (dx_it <= dx_block) {\r
- rc = ext4_block_set(fs->bdev, &dx_it->block);\r
- if (rc != EOK)\r
- return rc;\r
+ while (dx_it <= dx_block) {\r
+ rc = ext4_block_set(fs->bdev, &dx_it->block);\r
+ if (rc != EOK)\r
+ return rc;\r
\r
- dx_it++;\r
- }\r
+ dx_it++;\r
+ }\r
\r
- return rc2;\r
+ return rc2;\r
}\r
\r
/**\r
* @return Error code\r
*/\r
int ext4_dir_dx_find_entry(struct ext4_directory_search_result *result,\r
- struct ext4_inode_ref *inode_ref, size_t name_len,\r
- const char *name);\r
+ struct ext4_inode_ref *inode_ref, size_t name_len,\r
+ const char *name);\r
\r
/**@brief Add new entry to indexed directory\r
* @param parent Directory i-node\r
* @return Error code\r
*/\r
int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,\r
- struct ext4_inode_ref *child, const char *name);\r
+ struct ext4_inode_ref *child, const char *name);\r
\r
#endif /* EXT4_DIR_IDX_H_ */\r
\r
\r
uint32_t ext4_extent_get_first_block(struct ext4_extent *extent)\r
{\r
- return to_le32(extent->first_block);\r
+ return to_le32(extent->first_block);\r
}\r
\r
void ext4_extent_set_first_block(struct ext4_extent *extent, uint32_t iblock)\r
{\r
- extent->first_block = to_le32(iblock);\r
+ extent->first_block = to_le32(iblock);\r
}\r
\r
uint16_t ext4_extent_get_block_count(struct ext4_extent *extent)\r
{\r
- return to_le16(extent->block_count);\r
+ return to_le16(extent->block_count);\r
}\r
\r
void ext4_extent_set_block_count(struct ext4_extent *extent, uint16_t count)\r
{\r
- extent->block_count = to_le16(count);\r
+ extent->block_count = to_le16(count);\r
}\r
\r
uint64_t ext4_extent_get_start(struct ext4_extent *extent)\r
{\r
- return ((uint64_t)to_le16(extent->start_hi)) << 32 |\r
- ((uint64_t)to_le32(extent->start_lo));\r
+ return ((uint64_t)to_le16(extent->start_hi)) << 32 |\r
+ ((uint64_t)to_le32(extent->start_lo));\r
}\r
\r
void ext4_extent_set_start(struct ext4_extent *extent, uint64_t fblock)\r
{\r
- extent->start_lo = to_le32((fblock << 32) >> 32);\r
- extent->start_hi = to_le16((uint16_t)(fblock >> 32));\r
+ extent->start_lo = to_le32((fblock << 32) >> 32);\r
+ extent->start_hi = to_le16((uint16_t)(fblock >> 32));\r
}\r
\r
uint32_t ext4_extent_index_get_first_block(struct ext4_extent_index *index)\r
{\r
- return to_le32(index->first_block);\r
+ return to_le32(index->first_block);\r
}\r
\r
void ext4_extent_index_set_first_block(struct ext4_extent_index *index,\r
- uint32_t iblock)\r
+ uint32_t iblock)\r
{\r
- index->first_block = to_le32(iblock);\r
+ index->first_block = to_le32(iblock);\r
}\r
\r
uint64_t ext4_extent_index_get_leaf(struct ext4_extent_index *index)\r
{\r
- return ((uint64_t)to_le16(index->leaf_hi)) << 32 |\r
- ((uint64_t)to_le32(index->leaf_lo));\r
+ return ((uint64_t)to_le16(index->leaf_hi)) << 32 |\r
+ ((uint64_t)to_le32(index->leaf_lo));\r
}\r
\r
void ext4_extent_index_set_leaf(struct ext4_extent_index *index,\r
- uint64_t fblock)\r
+ uint64_t fblock)\r
{\r
- index->leaf_lo = to_le32((fblock << 32) >> 32);\r
- index->leaf_hi = to_le16((uint16_t)(fblock >> 32));\r
+ index->leaf_lo = to_le32((fblock << 32) >> 32);\r
+ index->leaf_hi = to_le16((uint16_t)(fblock >> 32));\r
}\r
\r
uint16_t ext4_extent_header_get_magic(struct ext4_extent_header *header)\r
{\r
- return to_le16(header->magic);\r
+ return to_le16(header->magic);\r
}\r
\r
void ext4_extent_header_set_magic(struct ext4_extent_header *header,\r
- uint16_t magic)\r
+ uint16_t magic)\r
{\r
- header->magic = to_le16(magic);\r
+ header->magic = to_le16(magic);\r
}\r
\r
uint16_t ext4_extent_header_get_entries_count(struct ext4_extent_header *header)\r
{\r
- return to_le16(header->entries_count);\r
+ return to_le16(header->entries_count);\r
}\r
\r
void ext4_extent_header_set_entries_count(struct ext4_extent_header *header,\r
- uint16_t count)\r
+ uint16_t count)\r
{\r
- header->entries_count = to_le16(count);\r
+ header->entries_count = to_le16(count);\r
}\r
\r
uint16_t\r
ext4_extent_header_get_max_entries_count(struct ext4_extent_header *header)\r
{\r
- return to_le16(header->max_entries_count);\r
+ return to_le16(header->max_entries_count);\r
}\r
\r
void ext4_extent_header_set_max_entries_count(struct ext4_extent_header *header,\r
- uint16_t max_count)\r
+ uint16_t max_count)\r
{\r
- header->max_entries_count = to_le16(max_count);\r
+ header->max_entries_count = to_le16(max_count);\r
}\r
\r
uint16_t ext4_extent_header_get_depth(struct ext4_extent_header *header)\r
{\r
- return to_le16(header->depth);\r
+ return to_le16(header->depth);\r
}\r
\r
void ext4_extent_header_set_depth(struct ext4_extent_header *header,\r
- uint16_t depth)\r
+ uint16_t depth)\r
{\r
- header->depth = to_le16(depth);\r
+ header->depth = to_le16(depth);\r
}\r
\r
uint32_t ext4_extent_header_get_generation(struct ext4_extent_header *header)\r
{\r
- return to_le32(header->generation);\r
+ return to_le32(header->generation);\r
}\r
\r
void ext4_extent_header_set_generation(struct ext4_extent_header *header,\r
- uint32_t generation)\r
+ uint32_t generation)\r
{\r
- header->generation = to_le32(generation);\r
+ header->generation = to_le32(generation);\r
}\r
\r
/**@brief Binary search in extent index node.\r
* @param index Output value - found index will be set here\r
* @param iblock Logical block number to find in index node */\r
static void ext4_extent_binsearch_idx(struct ext4_extent_header *header,\r
- struct ext4_extent_index **index,\r
- uint32_t iblock)\r
+ struct ext4_extent_index **index,\r
+ uint32_t iblock)\r
{\r
- struct ext4_extent_index *r;\r
- struct ext4_extent_index *l;\r
- struct ext4_extent_index *m;\r
+ struct ext4_extent_index *r;\r
+ struct ext4_extent_index *l;\r
+ struct ext4_extent_index *m;\r
\r
- uint16_t entries_count = ext4_extent_header_get_entries_count(header);\r
+ uint16_t entries_count = ext4_extent_header_get_entries_count(header);\r
\r
- /* Initialize bounds */\r
- l = EXT4_EXTENT_FIRST_INDEX(header) + 1;\r
- r = EXT4_EXTENT_FIRST_INDEX(header) + entries_count - 1;\r
+ /* Initialize bounds */\r
+ l = EXT4_EXTENT_FIRST_INDEX(header) + 1;\r
+ r = EXT4_EXTENT_FIRST_INDEX(header) + entries_count - 1;\r
\r
- /* Do binary search */\r
- while (l <= r) {\r
- m = l + (r - l) / 2;\r
- uint32_t first_block = ext4_extent_index_get_first_block(m);\r
+ /* Do binary search */\r
+ while (l <= r) {\r
+ m = l + (r - l) / 2;\r
+ uint32_t first_block = ext4_extent_index_get_first_block(m);\r
\r
- if (iblock < first_block)\r
- r = m - 1;\r
- else\r
- l = m + 1;\r
- }\r
+ if (iblock < first_block)\r
+ r = m - 1;\r
+ else\r
+ l = m + 1;\r
+ }\r
\r
- /* Set output value */\r
- *index = l - 1;\r
+ /* Set output value */\r
+ *index = l - 1;\r
}\r
\r
/**@brief Binary search in extent leaf node.\r
* or NULL if node is empty\r
* @param iblock Logical block number to find in leaf node */\r
static void ext4_extent_binsearch(struct ext4_extent_header *header,\r
- struct ext4_extent **extent, uint32_t iblock)\r
+ struct ext4_extent **extent, uint32_t iblock)\r
{\r
- struct ext4_extent *r;\r
- struct ext4_extent *l;\r
- struct ext4_extent *m;\r
-\r
- uint16_t entries_count = ext4_extent_header_get_entries_count(header);\r
-\r
- if (entries_count == 0) {\r
- /* this leaf is empty */\r
- *extent = NULL;\r
- return;\r
- }\r
-\r
- /* Initialize bounds */\r
- l = EXT4_EXTENT_FIRST(header) + 1;\r
- r = EXT4_EXTENT_FIRST(header) + entries_count - 1;\r
-\r
- /* Do binary search */\r
- while (l <= r) {\r
- m = l + (r - l) / 2;\r
- uint32_t first_block = ext4_extent_get_first_block(m);\r
-\r
- if (iblock < first_block)\r
- r = m - 1;\r
- else\r
- l = m + 1;\r
- }\r
-\r
- /* Set output value */\r
- *extent = l - 1;\r
+ struct ext4_extent *r;\r
+ struct ext4_extent *l;\r
+ struct ext4_extent *m;\r
+\r
+ uint16_t entries_count = ext4_extent_header_get_entries_count(header);\r
+\r
+ if (entries_count == 0) {\r
+ /* this leaf is empty */\r
+ *extent = NULL;\r
+ return;\r
+ }\r
+\r
+ /* Initialize bounds */\r
+ l = EXT4_EXTENT_FIRST(header) + 1;\r
+ r = EXT4_EXTENT_FIRST(header) + entries_count - 1;\r
+\r
+ /* Do binary search */\r
+ while (l <= r) {\r
+ m = l + (r - l) / 2;\r
+ uint32_t first_block = ext4_extent_get_first_block(m);\r
+\r
+ if (iblock < first_block)\r
+ r = m - 1;\r
+ else\r
+ l = m + 1;\r
+ }\r
+\r
+ /* Set output value */\r
+ *extent = l - 1;\r
}\r
\r
int ext4_extent_find_block(struct ext4_inode_ref *inode_ref, uint32_t iblock,\r
- uint32_t *fblock)\r
+ uint32_t *fblock)\r
{\r
- int rc;\r
- /* Compute bound defined by i-node size */\r
- uint64_t inode_size =\r
- ext4_inode_get_size(&inode_ref->fs->sb, inode_ref->inode);\r
-\r
- uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
-\r
- uint32_t last_idx = (inode_size - 1) / block_size;\r
-\r
- /* Check if requested iblock is not over size of i-node */\r
- if (iblock > last_idx) {\r
- *fblock = 0;\r
- return EOK;\r
- }\r
-\r
- struct ext4_block block;\r
- block.lb_id = 0;\r
-\r
- /* Walk through extent tree */\r
- struct ext4_extent_header *header =\r
- ext4_inode_get_extent_header(inode_ref->inode);\r
-\r
- while (ext4_extent_header_get_depth(header) != 0) {\r
- /* Search index in node */\r
- struct ext4_extent_index *index;\r
- ext4_extent_binsearch_idx(header, &index, iblock);\r
-\r
- /* Load child node and set values for the next iteration */\r
- uint64_t child = ext4_extent_index_get_leaf(index);\r
-\r
- if (block.lb_id) {\r
- rc = ext4_block_set(inode_ref->fs->bdev, &block);\r
- if (rc != EOK)\r
- return rc;\r
- }\r
-\r
- int rc = ext4_block_get(inode_ref->fs->bdev, &block, child);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- header = (struct ext4_extent_header *)block.data;\r
- }\r
-\r
- /* Search extent in the leaf block */\r
- struct ext4_extent *extent = NULL;\r
- ext4_extent_binsearch(header, &extent, iblock);\r
-\r
- /* Prevent empty leaf */\r
- if (extent == NULL) {\r
- *fblock = 0;\r
- } else {\r
- /* Compute requested physical block address */\r
- uint32_t phys_block;\r
- uint32_t first = ext4_extent_get_first_block(extent);\r
- phys_block = ext4_extent_get_start(extent) + iblock - first;\r
-\r
- *fblock = phys_block;\r
- }\r
-\r
- /* Cleanup */\r
- if (block.lb_id) {\r
- rc = ext4_block_set(inode_ref->fs->bdev, &block);\r
- if (rc != EOK)\r
- return rc;\r
- }\r
-\r
- return EOK;\r
+ int rc;\r
+ /* Compute bound defined by i-node size */\r
+ uint64_t inode_size =\r
+ ext4_inode_get_size(&inode_ref->fs->sb, inode_ref->inode);\r
+\r
+ uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
+\r
+ uint32_t last_idx = (inode_size - 1) / block_size;\r
+\r
+ /* Check if requested iblock is not over size of i-node */\r
+ if (iblock > last_idx) {\r
+ *fblock = 0;\r
+ return EOK;\r
+ }\r
+\r
+ struct ext4_block block;\r
+ block.lb_id = 0;\r
+\r
+ /* Walk through extent tree */\r
+ struct ext4_extent_header *header =\r
+ ext4_inode_get_extent_header(inode_ref->inode);\r
+\r
+ while (ext4_extent_header_get_depth(header) != 0) {\r
+ /* Search index in node */\r
+ struct ext4_extent_index *index;\r
+ ext4_extent_binsearch_idx(header, &index, iblock);\r
+\r
+ /* Load child node and set values for the next iteration */\r
+ uint64_t child = ext4_extent_index_get_leaf(index);\r
+\r
+ if (block.lb_id) {\r
+ rc = ext4_block_set(inode_ref->fs->bdev, &block);\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+\r
+ int rc = ext4_block_get(inode_ref->fs->bdev, &block, child);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ header = (struct ext4_extent_header *)block.data;\r
+ }\r
+\r
+ /* Search extent in the leaf block */\r
+ struct ext4_extent *extent = NULL;\r
+ ext4_extent_binsearch(header, &extent, iblock);\r
+\r
+ /* Prevent empty leaf */\r
+ if (extent == NULL) {\r
+ *fblock = 0;\r
+ } else {\r
+ /* Compute requested physical block address */\r
+ uint32_t phys_block;\r
+ uint32_t first = ext4_extent_get_first_block(extent);\r
+ phys_block = ext4_extent_get_start(extent) + iblock - first;\r
+\r
+ *fblock = phys_block;\r
+ }\r
+\r
+ /* Cleanup */\r
+ if (block.lb_id) {\r
+ rc = ext4_block_set(inode_ref->fs->bdev, &block);\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
/**@brief Find extent for specified iblock.\r
* @param ret_path Output value for loaded path from extent tree\r
* @return Error code */\r
static int ext4_extent_find_extent(struct ext4_inode_ref *inode_ref,\r
- uint32_t iblock,\r
- struct ext4_extent_path **ret_path)\r
+ uint32_t iblock,\r
+ struct ext4_extent_path **ret_path)\r
{\r
- struct ext4_extent_header *eh =\r
- ext4_inode_get_extent_header(inode_ref->inode);\r
+ struct ext4_extent_header *eh =\r
+ ext4_inode_get_extent_header(inode_ref->inode);\r
\r
- uint16_t depth = ext4_extent_header_get_depth(eh);\r
- uint16_t i;\r
- struct ext4_extent_path *tmp_path;\r
+ uint16_t depth = ext4_extent_header_get_depth(eh);\r
+ uint16_t i;\r
+ struct ext4_extent_path *tmp_path;\r
\r
- /* Added 2 for possible tree growing */\r
- tmp_path = malloc(sizeof(struct ext4_extent_path) * (depth + 2));\r
- if (tmp_path == NULL)\r
- return ENOMEM;\r
+ /* Added 2 for possible tree growing */\r
+ tmp_path = malloc(sizeof(struct ext4_extent_path) * (depth + 2));\r
+ if (tmp_path == NULL)\r
+ return ENOMEM;\r
\r
- /* Initialize structure for algorithm start */\r
- tmp_path[0].block = inode_ref->block;\r
- tmp_path[0].header = eh;\r
+ /* Initialize structure for algorithm start */\r
+ tmp_path[0].block = inode_ref->block;\r
+ tmp_path[0].header = eh;\r
\r
- /* Walk through the extent tree */\r
- uint16_t pos = 0;\r
- int rc;\r
- while (ext4_extent_header_get_depth(eh) != 0) {\r
- /* Search index in index node by iblock */\r
- ext4_extent_binsearch_idx(tmp_path[pos].header, &tmp_path[pos].index,\r
- iblock);\r
+ /* Walk through the extent tree */\r
+ uint16_t pos = 0;\r
+ int rc;\r
+ while (ext4_extent_header_get_depth(eh) != 0) {\r
+ /* Search index in index node by iblock */\r
+ ext4_extent_binsearch_idx(tmp_path[pos].header,\r
+ &tmp_path[pos].index, iblock);\r
\r
- tmp_path[pos].depth = depth;\r
- tmp_path[pos].extent = NULL;\r
+ tmp_path[pos].depth = depth;\r
+ tmp_path[pos].extent = NULL;\r
\r
- ext4_assert(tmp_path[pos].index != 0);\r
+ ext4_assert(tmp_path[pos].index != 0);\r
\r
- /* Load information for the next iteration */\r
- uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);\r
+ /* Load information for the next iteration */\r
+ uint64_t fblock =\r
+ ext4_extent_index_get_leaf(tmp_path[pos].index);\r
\r
- struct ext4_block block;\r
- rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);\r
- if (rc != EOK)\r
- goto cleanup;\r
+ struct ext4_block block;\r
+ rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
\r
- pos++;\r
+ pos++;\r
\r
- eh = (struct ext4_extent_header *)block.data;\r
- tmp_path[pos].block = block;\r
- tmp_path[pos].header = eh;\r
- }\r
+ eh = (struct ext4_extent_header *)block.data;\r
+ tmp_path[pos].block = block;\r
+ tmp_path[pos].header = eh;\r
+ }\r
\r
- tmp_path[pos].depth = 0;\r
- tmp_path[pos].extent = NULL;\r
- tmp_path[pos].index = NULL;\r
+ tmp_path[pos].depth = 0;\r
+ tmp_path[pos].extent = NULL;\r
+ tmp_path[pos].index = NULL;\r
\r
- /* Find extent in the leaf node */\r
- ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent, iblock);\r
- *ret_path = tmp_path;\r
+ /* Find extent in the leaf node */\r
+ ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent,\r
+ iblock);\r
+ *ret_path = tmp_path;\r
\r
- return EOK;\r
+ return EOK;\r
\r
cleanup:\r
- /*\r
- * Put loaded blocks\r
- * From 1: 0 is a block with inode data\r
- */\r
- for (i = 1; i < tmp_path->depth; ++i) {\r
- if (tmp_path[i].block.lb_id) {\r
- int r = ext4_block_set(inode_ref->fs->bdev, &tmp_path[i].block);\r
- if (r != EOK)\r
- rc = r;\r
- }\r
- }\r
-\r
- /* Destroy temporary data structure */\r
- free(tmp_path);\r
-\r
- return rc;\r
+ /*\r
+ * Put loaded blocks\r
+ * From 1: 0 is a block with inode data\r
+ */\r
+ for (i = 1; i < tmp_path->depth; ++i) {\r
+ if (tmp_path[i].block.lb_id) {\r
+ int r = ext4_block_set(inode_ref->fs->bdev,\r
+ &tmp_path[i].block);\r
+ if (r != EOK)\r
+ rc = r;\r
+ }\r
+ }\r
+\r
+ /* Destroy temporary data structure */\r
+ free(tmp_path);\r
+\r
+ return rc;\r
}\r
\r
/**@brief Release extent and all data blocks covered by the extent.\r
* @param extent Extent to release\r
* @return Error code */\r
static int ext4_extent_release(struct ext4_inode_ref *inode_ref,\r
- struct ext4_extent *extent)\r
+ struct ext4_extent *extent)\r
{\r
- /* Compute number of the first physical block to release */\r
- uint64_t start = ext4_extent_get_start(extent);\r
- uint16_t block_count = ext4_extent_get_block_count(extent);\r
+ /* Compute number of the first physical block to release */\r
+ uint64_t start = ext4_extent_get_start(extent);\r
+ uint16_t block_count = ext4_extent_get_block_count(extent);\r
\r
- return ext4_balloc_free_blocks(inode_ref, start, block_count);\r
+ return ext4_balloc_free_blocks(inode_ref, start, block_count);\r
}\r
\r
/** Recursively release the whole branch of the extent tree.\r
* with the whole subtree\r
* @return Error code */\r
static int ext4_extent_release_branch(struct ext4_inode_ref *inode_ref,\r
- struct ext4_extent_index *index)\r
+ struct ext4_extent_index *index)\r
{\r
- uint32_t fblock = ext4_extent_index_get_leaf(index);\r
- uint32_t i;\r
- struct ext4_block block;\r
- int rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_extent_header *header = (void *)block.data;\r
-\r
- if (ext4_extent_header_get_depth(header)) {\r
- /* The node is non-leaf, do recursion */\r
- struct ext4_extent_index *idx = EXT4_EXTENT_FIRST_INDEX(header);\r
-\r
- /* Release all subbranches */\r
- for (i = 0; i < ext4_extent_header_get_entries_count(header);\r
- ++i, ++idx) {\r
- rc = ext4_extent_release_branch(inode_ref, idx);\r
- if (rc != EOK)\r
- return rc;\r
- }\r
- } else {\r
- /* Leaf node reached */\r
- struct ext4_extent *ext = EXT4_EXTENT_FIRST(header);\r
-\r
- /* Release all extents and stop recursion */\r
- for (i = 0; i < ext4_extent_header_get_entries_count(header);\r
- ++i, ++ext) {\r
- rc = ext4_extent_release(inode_ref, ext);\r
- if (rc != EOK)\r
- return rc;\r
- }\r
- }\r
-\r
- /* Release data block where the node was stored */\r
-\r
- rc = ext4_block_set(inode_ref->fs->bdev, &block);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- return ext4_balloc_free_block(inode_ref, fblock);\r
+ uint32_t fblock = ext4_extent_index_get_leaf(index);\r
+ uint32_t i;\r
+ struct ext4_block block;\r
+ int rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_extent_header *header = (void *)block.data;\r
+\r
+ if (ext4_extent_header_get_depth(header)) {\r
+ /* The node is non-leaf, do recursion */\r
+ struct ext4_extent_index *idx = EXT4_EXTENT_FIRST_INDEX(header);\r
+\r
+ /* Release all subbranches */\r
+ for (i = 0; i < ext4_extent_header_get_entries_count(header);\r
+ ++i, ++idx) {\r
+ rc = ext4_extent_release_branch(inode_ref, idx);\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+ } else {\r
+ /* Leaf node reached */\r
+ struct ext4_extent *ext = EXT4_EXTENT_FIRST(header);\r
+\r
+ /* Release all extents and stop recursion */\r
+ for (i = 0; i < ext4_extent_header_get_entries_count(header);\r
+ ++i, ++ext) {\r
+ rc = ext4_extent_release(inode_ref, ext);\r
+ if (rc != EOK)\r
+ return rc;\r
+ }\r
+ }\r
+\r
+ /* Release data block where the node was stored */\r
+\r
+ rc = ext4_block_set(inode_ref->fs->bdev, &block);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ return ext4_balloc_free_block(inode_ref, fblock);\r
}\r
\r
int ext4_extent_release_blocks_from(struct ext4_inode_ref *inode_ref,\r
- uint32_t iblock_from)\r
+ uint32_t iblock_from)\r
{\r
- /* Find the first extent to modify */\r
- struct ext4_extent_path *path;\r
- uint16_t i;\r
- int rc = ext4_extent_find_extent(inode_ref, iblock_from, &path);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Jump to last item of the path (extent) */\r
- struct ext4_extent_path *path_ptr = path;\r
- while (path_ptr->depth != 0)\r
- path_ptr++;\r
-\r
- ext4_assert(path_ptr->extent != NULL);\r
-\r
- /* First extent maybe released partially */\r
- uint32_t first_iblock = ext4_extent_get_first_block(path_ptr->extent);\r
- uint32_t first_fblock =\r
- ext4_extent_get_start(path_ptr->extent) + iblock_from - first_iblock;\r
-\r
- uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);\r
-\r
- uint16_t delete_count =\r
- block_count - (ext4_extent_get_start(path_ptr->extent) - first_fblock);\r
-\r
- /* Release all blocks */\r
- rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- /* Correct counter */\r
- block_count -= delete_count;\r
- ext4_extent_set_block_count(path_ptr->extent, block_count);\r
-\r
- /* Initialize the following loop */\r
- uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);\r
- struct ext4_extent *tmp_ext = path_ptr->extent + 1;\r
- struct ext4_extent *stop_ext =\r
- EXT4_EXTENT_FIRST(path_ptr->header) + entries;\r
-\r
- /* If first extent empty, release it */\r
- if (block_count == 0)\r
- entries--;\r
-\r
- /* Release all successors of the first extent in the same node */\r
- while (tmp_ext < stop_ext) {\r
- first_fblock = ext4_extent_get_start(tmp_ext);\r
- delete_count = ext4_extent_get_block_count(tmp_ext);\r
-\r
- rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- entries--;\r
- tmp_ext++;\r
- }\r
-\r
- ext4_extent_header_set_entries_count(path_ptr->header, entries);\r
- path_ptr->block.dirty = true;\r
-\r
- /* If leaf node is empty, parent entry must be modified */\r
- bool remove_parent_record = false;\r
-\r
- /* Don't release root block (including inode data) !!! */\r
- if ((path_ptr != path) && (entries == 0)) {\r
- rc = ext4_balloc_free_block(inode_ref, path_ptr->block.lb_id);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- remove_parent_record = true;\r
- }\r
-\r
- /* Jump to the parent */\r
- --path_ptr;\r
-\r
- /* Release all successors in all tree levels */\r
- while (path_ptr >= path) {\r
- entries = ext4_extent_header_get_entries_count(path_ptr->header);\r
- struct ext4_extent_index *index = path_ptr->index + 1;\r
- struct ext4_extent_index *stop =\r
- EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;\r
-\r
- /* Correct entries count because of changes in the previous iteration */\r
- if (remove_parent_record)\r
- entries--;\r
-\r
- /* Iterate over all entries and release the whole subtrees */\r
- while (index < stop) {\r
- rc = ext4_extent_release_branch(inode_ref, index);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- ++index;\r
- --entries;\r
- }\r
-\r
- ext4_extent_header_set_entries_count(path_ptr->header, entries);\r
- path_ptr->block.dirty = true;\r
-\r
- /* Free the node if it is empty */\r
- if ((entries == 0) && (path_ptr != path)) {\r
- rc = ext4_balloc_free_block(inode_ref, path_ptr->block.lb_id);\r
- if (rc != EOK)\r
- goto cleanup;\r
-\r
- /* Mark parent to be checked */\r
- remove_parent_record = true;\r
- } else\r
- remove_parent_record = false;\r
-\r
- --path_ptr;\r
- }\r
-\r
- if (!entries)\r
- ext4_extent_header_set_depth(path->header, 0);\r
+ /* Find the first extent to modify */\r
+ struct ext4_extent_path *path;\r
+ uint16_t i;\r
+ int rc = ext4_extent_find_extent(inode_ref, iblock_from, &path);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Jump to last item of the path (extent) */\r
+ struct ext4_extent_path *path_ptr = path;\r
+ while (path_ptr->depth != 0)\r
+ path_ptr++;\r
+\r
+ ext4_assert(path_ptr->extent != NULL);\r
+\r
+ /* First extent maybe released partially */\r
+ uint32_t first_iblock = ext4_extent_get_first_block(path_ptr->extent);\r
+ uint32_t first_fblock = ext4_extent_get_start(path_ptr->extent) +\r
+ iblock_from - first_iblock;\r
+\r
+ uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);\r
+\r
+ uint16_t delete_count =\r
+ block_count -\r
+ (ext4_extent_get_start(path_ptr->extent) - first_fblock);\r
+\r
+ /* Release all blocks */\r
+ rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ /* Correct counter */\r
+ block_count -= delete_count;\r
+ ext4_extent_set_block_count(path_ptr->extent, block_count);\r
+\r
+ /* Initialize the following loop */\r
+ uint16_t entries =\r
+ ext4_extent_header_get_entries_count(path_ptr->header);\r
+ struct ext4_extent *tmp_ext = path_ptr->extent + 1;\r
+ struct ext4_extent *stop_ext =\r
+ EXT4_EXTENT_FIRST(path_ptr->header) + entries;\r
+\r
+ /* If first extent empty, release it */\r
+ if (block_count == 0)\r
+ entries--;\r
+\r
+ /* Release all successors of the first extent in the same node */\r
+ while (tmp_ext < stop_ext) {\r
+ first_fblock = ext4_extent_get_start(tmp_ext);\r
+ delete_count = ext4_extent_get_block_count(tmp_ext);\r
+\r
+ rc = ext4_balloc_free_blocks(inode_ref, first_fblock,\r
+ delete_count);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ entries--;\r
+ tmp_ext++;\r
+ }\r
+\r
+ ext4_extent_header_set_entries_count(path_ptr->header, entries);\r
+ path_ptr->block.dirty = true;\r
+\r
+ /* If leaf node is empty, parent entry must be modified */\r
+ bool remove_parent_record = false;\r
+\r
+ /* Don't release root block (including inode data) !!! */\r
+ if ((path_ptr != path) && (entries == 0)) {\r
+ rc = ext4_balloc_free_block(inode_ref, path_ptr->block.lb_id);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ remove_parent_record = true;\r
+ }\r
+\r
+ /* Jump to the parent */\r
+ --path_ptr;\r
+\r
+ /* Release all successors in all tree levels */\r
+ while (path_ptr >= path) {\r
+ entries =\r
+ ext4_extent_header_get_entries_count(path_ptr->header);\r
+ struct ext4_extent_index *index = path_ptr->index + 1;\r
+ struct ext4_extent_index *stop =\r
+ EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;\r
+\r
+ /* Correct entries count because of changes in the previous\r
+ * iteration */\r
+ if (remove_parent_record)\r
+ entries--;\r
+\r
+ /* Iterate over all entries and release the whole subtrees */\r
+ while (index < stop) {\r
+ rc = ext4_extent_release_branch(inode_ref, index);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ ++index;\r
+ --entries;\r
+ }\r
+\r
+ ext4_extent_header_set_entries_count(path_ptr->header, entries);\r
+ path_ptr->block.dirty = true;\r
+\r
+ /* Free the node if it is empty */\r
+ if ((entries == 0) && (path_ptr != path)) {\r
+ rc = ext4_balloc_free_block(inode_ref,\r
+ path_ptr->block.lb_id);\r
+ if (rc != EOK)\r
+ goto cleanup;\r
+\r
+ /* Mark parent to be checked */\r
+ remove_parent_record = true;\r
+ } else\r
+ remove_parent_record = false;\r
+\r
+ --path_ptr;\r
+ }\r
+\r
+ if (!entries)\r
+ ext4_extent_header_set_depth(path->header, 0);\r
\r
cleanup:\r
- /*\r
- * Put loaded blocks\r
- * starting from 1: 0 is a block with inode data\r
- */\r
- for (i = 1; i <= path->depth; ++i) {\r
- if (path[i].block.lb_id) {\r
- int r = ext4_block_set(inode_ref->fs->bdev, &path[i].block);\r
- if (r != EOK)\r
- rc = r;\r
- }\r
- }\r
-\r
- /* Destroy temporary data structure */\r
- free(path);\r
-\r
- return rc;\r
+ /*\r
+ * Put loaded blocks\r
+ * starting from 1: 0 is a block with inode data\r
+ */\r
+ for (i = 1; i <= path->depth; ++i) {\r
+ if (path[i].block.lb_id) {\r
+ int r =\r
+ ext4_block_set(inode_ref->fs->bdev, &path[i].block);\r
+ if (r != EOK)\r
+ rc = r;\r
+ }\r
+ }\r
+\r
+ /* Destroy temporary data structure */\r
+ free(path);\r
+\r
+ return rc;\r
}\r
\r
/**@brief Append new extent to the i-node and do some splitting if necessary.\r
* @param iblock Logical index of block to append extent for\r
* @return Error code */\r
static int ext4_extent_append_extent(struct ext4_inode_ref *inode_ref,\r
- struct ext4_extent_path *path,\r
- uint32_t iblock)\r
+ struct ext4_extent_path *path,\r
+ uint32_t iblock)\r
{\r
- struct ext4_extent_path *path_ptr = path + path->depth;\r
-\r
- uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
-\r
- /* Start splitting */\r
- while (path_ptr > path) {\r
- uint16_t entries =\r
- ext4_extent_header_get_entries_count(path_ptr->header);\r
- uint16_t limit =\r
- ext4_extent_header_get_max_entries_count(path_ptr->header);\r
-\r
- if (entries == limit) {\r
- /* Full node - allocate block for new one */\r
- uint32_t fblock;\r
- int rc = ext4_balloc_alloc_block(inode_ref, &fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_block block;\r
- rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);\r
- if (rc != EOK) {\r
- ext4_balloc_free_block(inode_ref, fblock);\r
- return rc;\r
- }\r
-\r
- /* Put back not modified old block */\r
- rc = ext4_block_set(inode_ref->fs->bdev, &path_ptr->block);\r
- if (rc != EOK) {\r
- ext4_balloc_free_block(inode_ref, fblock);\r
- return rc;\r
- }\r
-\r
- /* Initialize newly allocated block and remember it */\r
- memset(block.data, 0, block_size);\r
- path_ptr->block = block;\r
-\r
- /* Update pointers in extent path structure */\r
- path_ptr->header = (void *)block.data;\r
- if (path_ptr->depth) {\r
- path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header);\r
- ext4_extent_index_set_first_block(path_ptr->index, iblock);\r
- ext4_extent_index_set_leaf(path_ptr->index,\r
- (path_ptr + 1)->block.lb_id);\r
- limit = (block_size - sizeof(struct ext4_extent_header)) /\r
- sizeof(struct ext4_extent_index);\r
- } else {\r
- path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header);\r
- ext4_extent_set_first_block(path_ptr->extent, iblock);\r
- limit = (block_size - sizeof(struct ext4_extent_header)) /\r
- sizeof(struct ext4_extent);\r
- }\r
-\r
- /* Initialize on-disk structure (header) */\r
- ext4_extent_header_set_entries_count(path_ptr->header, 1);\r
- ext4_extent_header_set_max_entries_count(path_ptr->header, limit);\r
- ext4_extent_header_set_magic(path_ptr->header, EXT4_EXTENT_MAGIC);\r
- ext4_extent_header_set_depth(path_ptr->header, path_ptr->depth);\r
- ext4_extent_header_set_generation(path_ptr->header, 0);\r
-\r
- path_ptr->block.dirty = true;\r
-\r
- /* Jump to the preceding item */\r
- path_ptr--;\r
- } else {\r
- /* Node with free space */\r
- if (path_ptr->depth) {\r
- path_ptr->index =\r
- EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;\r
- ext4_extent_index_set_first_block(path_ptr->index, iblock);\r
- ext4_extent_index_set_leaf(path_ptr->index,\r
- (path_ptr + 1)->block.lb_id);\r
- } else {\r
- path_ptr->extent =\r
- EXT4_EXTENT_FIRST(path_ptr->header) + entries;\r
- ext4_extent_set_first_block(path_ptr->extent, iblock);\r
- }\r
-\r
- ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);\r
- path_ptr->block.dirty = true;\r
-\r
- /* No more splitting needed */\r
- return EOK;\r
- }\r
- }\r
-\r
- ext4_assert(path_ptr == path);\r
-\r
- /* Should be the root split too? */\r
-\r
- uint16_t entries = ext4_extent_header_get_entries_count(path->header);\r
- uint16_t limit = ext4_extent_header_get_max_entries_count(path->header);\r
-\r
- if (entries == limit) {\r
- uint32_t new_fblock;\r
- int rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_block block;\r
- rc = ext4_block_get(inode_ref->fs->bdev, &block, new_fblock);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Initialize newly allocated block */\r
- memset(block.data, 0, block_size);\r
-\r
- /* Move data from root to the new block */\r
- memcpy(block.data, inode_ref->inode->blocks,\r
- EXT4_INODE_BLOCKS * sizeof(uint32_t));\r
-\r
- /* Data block is initialized */\r
-\r
- struct ext4_block *root_block = &path->block;\r
- uint16_t root_depth = path->depth;\r
- struct ext4_extent_header *root_header = path->header;\r
-\r
- /* Make space for tree growing */\r
- struct ext4_extent_path *new_root = path;\r
- struct ext4_extent_path *old_root = path + 1;\r
-\r
- size_t nbytes = sizeof(struct ext4_extent_path) * (path->depth + 1);\r
- memmove(old_root, new_root, nbytes);\r
- memset(new_root, 0, sizeof(struct ext4_extent_path));\r
-\r
- /* Update old root structure */\r
- old_root->block = block;\r
- old_root->header = (struct ext4_extent_header *)block.data;\r
-\r
- /* Add new entry and update limit for entries */\r
- if (old_root->depth) {\r
- limit = (block_size - sizeof(struct ext4_extent_header)) /\r
- sizeof(struct ext4_extent_index);\r
- old_root->index =\r
- EXT4_EXTENT_FIRST_INDEX(old_root->header) + entries;\r
- ext4_extent_index_set_first_block(old_root->index, iblock);\r
- ext4_extent_index_set_leaf(old_root->index,\r
- (old_root + 1)->block.lb_id);\r
- old_root->extent = NULL;\r
- } else {\r
- limit = (block_size - sizeof(struct ext4_extent_header)) /\r
- sizeof(struct ext4_extent);\r
- old_root->extent = EXT4_EXTENT_FIRST(old_root->header) + entries;\r
- ext4_extent_set_first_block(old_root->extent, iblock);\r
- old_root->index = NULL;\r
- }\r
-\r
- ext4_extent_header_set_entries_count(old_root->header, entries + 1);\r
- ext4_extent_header_set_max_entries_count(old_root->header, limit);\r
-\r
- old_root->block.dirty = true;\r
-\r
- /* Re-initialize new root metadata */\r
- new_root->depth = root_depth + 1;\r
- new_root->block = *root_block;\r
- new_root->header = root_header;\r
- new_root->extent = NULL;\r
- new_root->index = EXT4_EXTENT_FIRST_INDEX(new_root->header);\r
-\r
- ext4_extent_header_set_depth(new_root->header, new_root->depth);\r
-\r
- /* Create new entry in root */\r
- ext4_extent_header_set_entries_count(new_root->header, 1);\r
- ext4_extent_index_set_first_block(new_root->index, 0);\r
- ext4_extent_index_set_leaf(new_root->index, new_fblock);\r
-\r
- new_root->block.dirty = true;\r
- } else {\r
- if (path->depth) {\r
- path->index = EXT4_EXTENT_FIRST_INDEX(path->header) + entries;\r
- ext4_extent_index_set_first_block(path->index, iblock);\r
- ext4_extent_index_set_leaf(path->index, (path + 1)->block.lb_id);\r
- } else {\r
- path->extent = EXT4_EXTENT_FIRST(path->header) + entries;\r
- ext4_extent_set_first_block(path->extent, iblock);\r
- }\r
-\r
- ext4_extent_header_set_entries_count(path->header, entries + 1);\r
- path->block.dirty = true;\r
- }\r
-\r
- return EOK;\r
+ struct ext4_extent_path *path_ptr = path + path->depth;\r
+\r
+ uint32_t block_size = ext4_sb_get_block_size(&inode_ref->fs->sb);\r
+\r
+ /* Start splitting */\r
+ while (path_ptr > path) {\r
+ uint16_t entries =\r
+ ext4_extent_header_get_entries_count(path_ptr->header);\r
+ uint16_t limit =\r
+ ext4_extent_header_get_max_entries_count(path_ptr->header);\r
+\r
+ if (entries == limit) {\r
+ /* Full node - allocate block for new one */\r
+ uint32_t fblock;\r
+ int rc = ext4_balloc_alloc_block(inode_ref, &fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_block block;\r
+ rc =\r
+ ext4_block_get(inode_ref->fs->bdev, &block, fblock);\r
+ if (rc != EOK) {\r
+ ext4_balloc_free_block(inode_ref, fblock);\r
+ return rc;\r
+ }\r
+\r
+ /* Put back not modified old block */\r
+ rc = ext4_block_set(inode_ref->fs->bdev,\r
+ &path_ptr->block);\r
+ if (rc != EOK) {\r
+ ext4_balloc_free_block(inode_ref, fblock);\r
+ return rc;\r
+ }\r
+\r
+ /* Initialize newly allocated block and remember it */\r
+ memset(block.data, 0, block_size);\r
+ path_ptr->block = block;\r
+\r
+ /* Update pointers in extent path structure */\r
+ path_ptr->header = (void *)block.data;\r
+ if (path_ptr->depth) {\r
+ path_ptr->index =\r
+ EXT4_EXTENT_FIRST_INDEX(path_ptr->header);\r
+ ext4_extent_index_set_first_block(\r
+ path_ptr->index, iblock);\r
+ ext4_extent_index_set_leaf(\r
+ path_ptr->index,\r
+ (path_ptr + 1)->block.lb_id);\r
+ limit = (block_size -\r
+ sizeof(struct ext4_extent_header)) /\r
+ sizeof(struct ext4_extent_index);\r
+ } else {\r
+ path_ptr->extent =\r
+ EXT4_EXTENT_FIRST(path_ptr->header);\r
+ ext4_extent_set_first_block(path_ptr->extent,\r
+ iblock);\r
+ limit = (block_size -\r
+ sizeof(struct ext4_extent_header)) /\r
+ sizeof(struct ext4_extent);\r
+ }\r
+\r
+ /* Initialize on-disk structure (header) */\r
+ ext4_extent_header_set_entries_count(path_ptr->header,\r
+ 1);\r
+ ext4_extent_header_set_max_entries_count(\r
+ path_ptr->header, limit);\r
+ ext4_extent_header_set_magic(path_ptr->header,\r
+ EXT4_EXTENT_MAGIC);\r
+ ext4_extent_header_set_depth(path_ptr->header,\r
+ path_ptr->depth);\r
+ ext4_extent_header_set_generation(path_ptr->header, 0);\r
+\r
+ path_ptr->block.dirty = true;\r
+\r
+ /* Jump to the preceding item */\r
+ path_ptr--;\r
+ } else {\r
+ /* Node with free space */\r
+ if (path_ptr->depth) {\r
+ path_ptr->index =\r
+ EXT4_EXTENT_FIRST_INDEX(path_ptr->header) +\r
+ entries;\r
+ ext4_extent_index_set_first_block(\r
+ path_ptr->index, iblock);\r
+ ext4_extent_index_set_leaf(\r
+ path_ptr->index,\r
+ (path_ptr + 1)->block.lb_id);\r
+ } else {\r
+ path_ptr->extent =\r
+ EXT4_EXTENT_FIRST(path_ptr->header) +\r
+ entries;\r
+ ext4_extent_set_first_block(path_ptr->extent,\r
+ iblock);\r
+ }\r
+\r
+ ext4_extent_header_set_entries_count(path_ptr->header,\r
+ entries + 1);\r
+ path_ptr->block.dirty = true;\r
+\r
+ /* No more splitting needed */\r
+ return EOK;\r
+ }\r
+ }\r
+\r
+ ext4_assert(path_ptr == path);\r
+\r
+ /* Should be the root split too? */\r
+\r
+ uint16_t entries = ext4_extent_header_get_entries_count(path->header);\r
+ uint16_t limit = ext4_extent_header_get_max_entries_count(path->header);\r
+\r
+ if (entries == limit) {\r
+ uint32_t new_fblock;\r
+ int rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_block block;\r
+ rc = ext4_block_get(inode_ref->fs->bdev, &block, new_fblock);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Initialize newly allocated block */\r
+ memset(block.data, 0, block_size);\r
+\r
+ /* Move data from root to the new block */\r
+ memcpy(block.data, inode_ref->inode->blocks,\r
+ EXT4_INODE_BLOCKS * sizeof(uint32_t));\r
+\r
+ /* Data block is initialized */\r
+\r
+ struct ext4_block *root_block = &path->block;\r
+ uint16_t root_depth = path->depth;\r
+ struct ext4_extent_header *root_header = path->header;\r
+\r
+ /* Make space for tree growing */\r
+ struct ext4_extent_path *new_root = path;\r
+ struct ext4_extent_path *old_root = path + 1;\r
+\r
+ size_t nbytes =\r
+ sizeof(struct ext4_extent_path) * (path->depth + 1);\r
+ memmove(old_root, new_root, nbytes);\r
+ memset(new_root, 0, sizeof(struct ext4_extent_path));\r
+\r
+ /* Update old root structure */\r
+ old_root->block = block;\r
+ old_root->header = (struct ext4_extent_header *)block.data;\r
+\r
+ /* Add new entry and update limit for entries */\r
+ if (old_root->depth) {\r
+ limit =\r
+ (block_size - sizeof(struct ext4_extent_header)) /\r
+ sizeof(struct ext4_extent_index);\r
+ old_root->index =\r
+ EXT4_EXTENT_FIRST_INDEX(old_root->header) + entries;\r
+ ext4_extent_index_set_first_block(old_root->index,\r
+ iblock);\r
+ ext4_extent_index_set_leaf(old_root->index,\r
+ (old_root + 1)->block.lb_id);\r
+ old_root->extent = NULL;\r
+ } else {\r
+ limit =\r
+ (block_size - sizeof(struct ext4_extent_header)) /\r
+ sizeof(struct ext4_extent);\r
+ old_root->extent =\r
+ EXT4_EXTENT_FIRST(old_root->header) + entries;\r
+ ext4_extent_set_first_block(old_root->extent, iblock);\r
+ old_root->index = NULL;\r
+ }\r
+\r
+ ext4_extent_header_set_entries_count(old_root->header,\r
+ entries + 1);\r
+ ext4_extent_header_set_max_entries_count(old_root->header,\r
+ limit);\r
+\r
+ old_root->block.dirty = true;\r
+\r
+ /* Re-initialize new root metadata */\r
+ new_root->depth = root_depth + 1;\r
+ new_root->block = *root_block;\r
+ new_root->header = root_header;\r
+ new_root->extent = NULL;\r
+ new_root->index = EXT4_EXTENT_FIRST_INDEX(new_root->header);\r
+\r
+ ext4_extent_header_set_depth(new_root->header, new_root->depth);\r
+\r
+ /* Create new entry in root */\r
+ ext4_extent_header_set_entries_count(new_root->header, 1);\r
+ ext4_extent_index_set_first_block(new_root->index, 0);\r
+ ext4_extent_index_set_leaf(new_root->index, new_fblock);\r
+\r
+ new_root->block.dirty = true;\r
+ } else {\r
+ if (path->depth) {\r
+ path->index =\r
+ EXT4_EXTENT_FIRST_INDEX(path->header) + entries;\r
+ ext4_extent_index_set_first_block(path->index, iblock);\r
+ ext4_extent_index_set_leaf(path->index,\r
+ (path + 1)->block.lb_id);\r
+ } else {\r
+ path->extent =\r
+ EXT4_EXTENT_FIRST(path->header) + entries;\r
+ ext4_extent_set_first_block(path->extent, iblock);\r
+ }\r
+\r
+ ext4_extent_header_set_entries_count(path->header, entries + 1);\r
+ path->block.dirty = true;\r
+ }\r
+\r
+ return EOK;\r
}\r
\r
int ext4_extent_append_block(struct ext4_inode_ref *inode_ref, uint32_t *iblock,\r
- uint32_t *fblock, bool update_size)\r
+ uint32_t *fblock, bool update_size)\r
{\r
- uint16_t i;\r
- struct ext4_sblock *sb = &inode_ref->fs->sb;\r
- uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);\r
- uint32_t block_size = ext4_sb_get_block_size(sb);\r
-\r
- /* Calculate number of new logical block */\r
- uint32_t new_block_idx = 0;\r
- if (inode_size > 0) {\r
- if ((inode_size % block_size) != 0)\r
- inode_size += block_size - (inode_size % block_size);\r
-\r
- new_block_idx = inode_size / block_size;\r
- }\r
-\r
- /* Load the nearest leaf (with extent) */\r
- struct ext4_extent_path *path;\r
- int rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Jump to last item of the path (extent) */\r
- struct ext4_extent_path *path_ptr = path;\r
- while (path_ptr->depth != 0)\r
- path_ptr++;\r
-\r
- /* Add new extent to the node if not present */\r
- if (path_ptr->extent == NULL)\r
- goto append_extent;\r
-\r
- uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);\r
- uint16_t block_limit = (1 << 15);\r
-\r
- uint32_t phys_block = 0;\r
- if (block_count < block_limit) {\r
- /* There is space for new block in the extent */\r
- if (block_count == 0) {\r
- /* Existing extent is empty */\r
- rc = ext4_balloc_alloc_block(inode_ref, &phys_block);\r
- if (rc != EOK)\r
- goto finish;\r
-\r
- /* Initialize extent */\r
- ext4_extent_set_first_block(path_ptr->extent, new_block_idx);\r
- ext4_extent_set_start(path_ptr->extent, phys_block);\r
- ext4_extent_set_block_count(path_ptr->extent, 1);\r
-\r
- /* Update i-node */\r
- if (update_size) {\r
- ext4_inode_set_size(inode_ref->inode, inode_size + block_size);\r
- inode_ref->dirty = true;\r
- }\r
-\r
- path_ptr->block.dirty = true;\r
-\r
- goto finish;\r
- } else {\r
- /* Existing extent contains some blocks */\r
- phys_block = ext4_extent_get_start(path_ptr->extent);\r
- phys_block += ext4_extent_get_block_count(path_ptr->extent);\r
-\r
- /* Check if the following block is free for allocation */\r
- bool free;\r
- rc = ext4_balloc_try_alloc_block(inode_ref, phys_block, &free);\r
- if (rc != EOK)\r
- goto finish;\r
-\r
- if (!free) {\r
- /* Target is not free, new block must be appended to new extent\r
- */\r
- goto append_extent;\r
- }\r
-\r
- /* Update extent */\r
- ext4_extent_set_block_count(path_ptr->extent, block_count + 1);\r
-\r
- /* Update i-node */\r
- if (update_size) {\r
- ext4_inode_set_size(inode_ref->inode, inode_size + block_size);\r
- inode_ref->dirty = true;\r
- }\r
-\r
- path_ptr->block.dirty = true;\r
-\r
- goto finish;\r
- }\r
- }\r
+ uint16_t i;\r
+ struct ext4_sblock *sb = &inode_ref->fs->sb;\r
+ uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);\r
+ uint32_t block_size = ext4_sb_get_block_size(sb);\r
+\r
+ /* Calculate number of new logical block */\r
+ uint32_t new_block_idx = 0;\r
+ if (inode_size > 0) {\r
+ if ((inode_size % block_size) != 0)\r
+ inode_size += block_size - (inode_size % block_size);\r
+\r
+ new_block_idx = inode_size / block_size;\r
+ }\r
+\r
+ /* Load the nearest leaf (with extent) */\r
+ struct ext4_extent_path *path;\r
+ int rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Jump to last item of the path (extent) */\r
+ struct ext4_extent_path *path_ptr = path;\r
+ while (path_ptr->depth != 0)\r
+ path_ptr++;\r
+\r
+ /* Add new extent to the node if not present */\r
+ if (path_ptr->extent == NULL)\r
+ goto append_extent;\r
+\r
+ uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);\r
+ uint16_t block_limit = (1 << 15);\r
+\r
+ uint32_t phys_block = 0;\r
+ if (block_count < block_limit) {\r
+ /* There is space for new block in the extent */\r
+ if (block_count == 0) {\r
+ /* Existing extent is empty */\r
+ rc = ext4_balloc_alloc_block(inode_ref, &phys_block);\r
+ if (rc != EOK)\r
+ goto finish;\r
+\r
+ /* Initialize extent */\r
+ ext4_extent_set_first_block(path_ptr->extent,\r
+ new_block_idx);\r
+ ext4_extent_set_start(path_ptr->extent, phys_block);\r
+ ext4_extent_set_block_count(path_ptr->extent, 1);\r
+\r
+ /* Update i-node */\r
+ if (update_size) {\r
+ ext4_inode_set_size(inode_ref->inode,\r
+ inode_size + block_size);\r
+ inode_ref->dirty = true;\r
+ }\r
+\r
+ path_ptr->block.dirty = true;\r
+\r
+ goto finish;\r
+ } else {\r
+ /* Existing extent contains some blocks */\r
+ phys_block = ext4_extent_get_start(path_ptr->extent);\r
+ phys_block +=\r
+ ext4_extent_get_block_count(path_ptr->extent);\r
+\r
+ /* Check if the following block is free for allocation\r
+ */\r
+ bool free;\r
+ rc = ext4_balloc_try_alloc_block(inode_ref, phys_block,\r
+ &free);\r
+ if (rc != EOK)\r
+ goto finish;\r
+\r
+ if (!free) {\r
+ /* Target is not free, new block must be\r
+ * appended to new extent\r
+ */\r
+ goto append_extent;\r
+ }\r
+\r
+ /* Update extent */\r
+ ext4_extent_set_block_count(path_ptr->extent,\r
+ block_count + 1);\r
+\r
+ /* Update i-node */\r
+ if (update_size) {\r
+ ext4_inode_set_size(inode_ref->inode,\r
+ inode_size + block_size);\r
+ inode_ref->dirty = true;\r
+ }\r
+\r
+ path_ptr->block.dirty = true;\r
+\r
+ goto finish;\r
+ }\r
+ }\r
\r
append_extent:\r
- /* Append new extent to the tree */\r
- phys_block = 0;\r
+ /* Append new extent to the tree */\r
+ phys_block = 0;\r
\r
- /* Allocate new data block */\r
- rc = ext4_balloc_alloc_block(inode_ref, &phys_block);\r
- if (rc != EOK)\r
- goto finish;\r
+ /* Allocate new data block */\r
+ rc = ext4_balloc_alloc_block(inode_ref, &phys_block);\r
+ if (rc != EOK)\r
+ goto finish;\r
\r
- /* Append extent for new block (includes tree splitting if needed) */\r
- rc = ext4_extent_append_extent(inode_ref, path, new_block_idx);\r
- if (rc != EOK) {\r
- ext4_balloc_free_block(inode_ref, phys_block);\r
- goto finish;\r
- }\r
+ /* Append extent for new block (includes tree splitting if needed) */\r
+ rc = ext4_extent_append_extent(inode_ref, path, new_block_idx);\r
+ if (rc != EOK) {\r
+ ext4_balloc_free_block(inode_ref, phys_block);\r
+ goto finish;\r
+ }\r
\r
- uint32_t tree_depth = ext4_extent_header_get_depth(path->header);\r
- path_ptr = path + tree_depth;\r
+ uint32_t tree_depth = ext4_extent_header_get_depth(path->header);\r
+ path_ptr = path + tree_depth;\r
\r
- /* Initialize newly created extent */\r
- ext4_extent_set_block_count(path_ptr->extent, 1);\r
- ext4_extent_set_first_block(path_ptr->extent, new_block_idx);\r
- ext4_extent_set_start(path_ptr->extent, phys_block);\r
+ /* Initialize newly created extent */\r
+ ext4_extent_set_block_count(path_ptr->extent, 1);\r
+ ext4_extent_set_first_block(path_ptr->extent, new_block_idx);\r
+ ext4_extent_set_start(path_ptr->extent, phys_block);\r
\r
- /* Update i-node */\r
- if (update_size) {\r
- ext4_inode_set_size(inode_ref->inode, inode_size + block_size);\r
- inode_ref->dirty = true;\r
- }\r
+ /* Update i-node */\r
+ if (update_size) {\r
+ ext4_inode_set_size(inode_ref->inode, inode_size + block_size);\r
+ inode_ref->dirty = true;\r
+ }\r
\r
- path_ptr->block.dirty = true;\r
+ path_ptr->block.dirty = true;\r
\r
finish:\r
- /* Set return values */\r
- *iblock = new_block_idx;\r
- *fblock = phys_block;\r
-\r
- /*\r
- * Put loaded blocks\r
- * starting from 1: 0 is a block with inode data\r
- */\r
- for (i = 1; i <= path->depth; ++i) {\r
- if (path[i].block.lb_id) {\r
- int r = ext4_block_set(inode_ref->fs->bdev, &path[i].block);\r
- if (r != EOK)\r
- rc = r;\r
- }\r
- }\r
-\r
- /* Destroy temporary data structure */\r
- free(path);\r
-\r
- return rc;\r
+ /* Set return values */\r
+ *iblock = new_block_idx;\r
+ *fblock = phys_block;\r
+\r
+ /*\r
+ * Put loaded blocks\r
+ * starting from 1: 0 is a block with inode data\r
+ */\r
+ for (i = 1; i <= path->depth; ++i) {\r
+ if (path[i].block.lb_id) {\r
+ int r =\r
+ ext4_block_set(inode_ref->fs->bdev, &path[i].block);\r
+ if (r != EOK)\r
+ rc = r;\r
+ }\r
+ }\r
+\r
+ /* Destroy temporary data structure */\r
+ free(path);\r
+\r
+ return rc;\r
}\r
\r
/**\r
* @param index Extent index to set number to\r
* @param iblock Logical number of the first block covered by extent index */\r
void ext4_extent_index_set_first_block(struct ext4_extent_index *index,\r
- uint32_t iblock);\r
+ uint32_t iblock);\r
\r
/**@brief Get physical number of block where the child node is located.\r
* @param index Extent index to load number from\r
* @param index Extent index to set number to\r
* @param fblock Ohysical number of the block with child node */\r
void ext4_extent_index_set_leaf(struct ext4_extent_index *index,\r
- uint64_t fblock);\r
+ uint64_t fblock);\r
\r
/**@brief Get magic value from extent header.\r
* @param header Extent header to load value from\r
* @param header Extent header to set value to\r
* @param magic Magic value of extent header */\r
void ext4_extent_header_set_magic(struct ext4_extent_header *header,\r
- uint16_t magic);\r
+ uint16_t magic);\r
\r
/**@brief Get number of entries from extent header\r
* @param header Extent header to get value from\r
* @param header Extent header to set value to\r
* @param count Number of entries covered by extent header */\r
void ext4_extent_header_set_entries_count(struct ext4_extent_header *header,\r
- uint16_t count);\r
+ uint16_t count);\r
\r
/**@brief Get maximum number of entries from extent header\r
* @param header Extent header to get value from\r
* @param header Extent header to set value to\r
* @param max_count Maximum number of entries covered by extent header */\r
void ext4_extent_header_set_max_entries_count(struct ext4_extent_header *header,\r
- uint16_t max_count);\r
+ uint16_t max_count);\r
\r
/**@brief Get depth of extent subtree.\r
* @param header Extent header to get value from\r
* @param header Extent header to set value to\r
* @param depth Depth of extent subtree */\r
void ext4_extent_header_set_depth(struct ext4_extent_header *header,\r
- uint16_t depth);\r
+ uint16_t depth);\r
\r
/**@brief Get generation from extent header\r
* @param header Extent header to get value from\r
* @param header Extent header to set value to\r
* @param generation Generation */\r
void ext4_extent_header_set_generation(struct ext4_extent_header *header,\r
- uint32_t generation);\r
+ uint32_t generation);\r
\r
/**@brief Find physical block in the extent tree by logical block number.\r
* There is no need to save path in the tree during this algorithm.\r
* @param fblock Output value for physical block number\r
* @return Error code*/\r
int ext4_extent_find_block(struct ext4_inode_ref *inode_ref, uint32_t iblock,\r
- uint32_t *fblock);\r
+ uint32_t *fblock);\r
\r
/**@brief Release all data blocks starting from specified logical block.\r
* @param inode_ref I-node to release blocks from\r
* @param iblock_from First logical block to release\r
* @return Error code */\r
int ext4_extent_release_blocks_from(struct ext4_inode_ref *inode_ref,\r
- uint32_t iblock_from);\r
+ uint32_t iblock_from);\r
\r
/**@brief Append data block to the i-node.\r
* This function allocates data block, tries to append it\r
*\r
* @return Error code*/\r
int ext4_extent_append_block(struct ext4_inode_ref *inode_ref, uint32_t *iblock,\r
- uint32_t *fblock, bool update_size);\r
+ uint32_t *fblock, bool update_size);\r
\r
#endif /* EXT4_EXTENT_H_ */\r
/**\r
- * @}\r
- */\r
+ * @}\r
+ */\r
int ext4_fs_init(struct ext4_fs *fs, struct ext4_blockdev *bdev)
{
- int r, i;
- uint16_t tmp;
- uint32_t bsize;
- bool read_only = false;
+ int r, i;
+ uint16_t tmp;
+ uint32_t bsize;
+ bool read_only = false;
- ext4_assert(fs && bdev);
+ ext4_assert(fs && bdev);
- fs->bdev = bdev;
+ fs->bdev = bdev;
- r = ext4_sb_read(fs->bdev, &fs->sb);
- if (r != EOK)
- return r;
+ r = ext4_sb_read(fs->bdev, &fs->sb);
+ if (r != EOK)
+ return r;
- if (!ext4_sb_check(&fs->sb))
- return ENOTSUP;
+ if (!ext4_sb_check(&fs->sb))
+ return ENOTSUP;
- bsize = ext4_sb_get_block_size(&fs->sb);
- if (bsize > EXT4_MAX_BLOCK_SIZE)
- return ENXIO;
+ bsize = ext4_sb_get_block_size(&fs->sb);
+ if (bsize > EXT4_MAX_BLOCK_SIZE)
+ return ENXIO;
- r = ext4_fs_check_features(fs, &read_only);
- if (r != EOK)
- return r;
+ r = ext4_fs_check_features(fs, &read_only);
+ if (r != EOK)
+ return r;
- if (read_only)
- return ENOTSUP;
+ if (read_only)
+ return ENOTSUP;
- /* Compute limits for indirect block levels */
- uint32_t blocks_id = bsize / sizeof(uint32_t);
+ /* Compute limits for indirect block levels */
+ uint32_t blocks_id = bsize / sizeof(uint32_t);
- fs->inode_block_limits[0] = EXT4_INODE_DIRECT_BLOCK_COUNT;
- fs->inode_blocks_per_level[0] = 1;
+ fs->inode_block_limits[0] = EXT4_INODE_DIRECT_BLOCK_COUNT;
+ fs->inode_blocks_per_level[0] = 1;
- for (i = 1; i < 4; i++) {
- fs->inode_blocks_per_level[i] =
- fs->inode_blocks_per_level[i - 1] * blocks_id;
- fs->inode_block_limits[i] =
- fs->inode_block_limits[i - 1] + fs->inode_blocks_per_level[i];
- }
+ for (i = 1; i < 4; i++) {
+ fs->inode_blocks_per_level[i] =
+ fs->inode_blocks_per_level[i - 1] * blocks_id;
+ fs->inode_block_limits[i] = fs->inode_block_limits[i - 1] +
+ fs->inode_blocks_per_level[i];
+ }
- /*Validate FS*/
- tmp = ext4_get16(&fs->sb, state);
- if (tmp & EXT4_SUPERBLOCK_STATE_ERROR_FS) {
- ext4_dprintf(EXT4_DEBUG_FS, "last umount error\n");
- }
+ /*Validate FS*/
+ tmp = ext4_get16(&fs->sb, state);
+ if (tmp & EXT4_SUPERBLOCK_STATE_ERROR_FS) {
+ ext4_dprintf(EXT4_DEBUG_FS, "last umount error\n");
+ }
- /* Mark system as mounted */
- ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_ERROR_FS);
- r = ext4_sb_write(fs->bdev, &fs->sb);
- if (r != EOK)
- return r;
+ /* Mark system as mounted */
+ ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_ERROR_FS);
+ r = ext4_sb_write(fs->bdev, &fs->sb);
+ if (r != EOK)
+ return r;
- /*Update mount count*/
- ext4_set16(&fs->sb, mount_count, ext4_get16(&fs->sb, mount_count) + 1);
+ /*Update mount count*/
+ ext4_set16(&fs->sb, mount_count, ext4_get16(&fs->sb, mount_count) + 1);
- return r;
+ return r;
}
int ext4_fs_fini(struct ext4_fs *fs)
{
- ext4_assert(fs);
+ ext4_assert(fs);
- /*Set superblock state*/
- ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_VALID_FS);
+ /*Set superblock state*/
+ ext4_set16(&fs->sb, state, EXT4_SUPERBLOCK_STATE_VALID_FS);
- return ext4_sb_write(fs->bdev, &fs->sb);
+ return ext4_sb_write(fs->bdev, &fs->sb);
}
static void ext4_fs_debug_features_incomp(uint32_t features_incompatible)
{
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_COMPRESSION) {
- ext4_dprintf(EXT4_DEBUG_FS, "compression\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_FILETYPE) {
- ext4_dprintf(EXT4_DEBUG_FS, "filetype\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_RECOVER) {
- ext4_dprintf(EXT4_DEBUG_FS, "recover\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_JOURNAL_DEV) {
- ext4_dprintf(EXT4_DEBUG_FS, "journal_dev\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_META_BG) {
- ext4_dprintf(EXT4_DEBUG_FS, "meta_bg\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_EXTENTS) {
- ext4_dprintf(EXT4_DEBUG_FS, "extents\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_64BIT) {
- ext4_dprintf(EXT4_DEBUG_FS, "64bit\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_MMP) {
- ext4_dprintf(EXT4_DEBUG_FS, "mnp\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
- ext4_dprintf(EXT4_DEBUG_FS, "flex_bg\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_EA_INODE) {
- ext4_dprintf(EXT4_DEBUG_FS, "ea_inode\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_DIRDATA) {
- ext4_dprintf(EXT4_DEBUG_FS, "dirdata\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM) {
- ext4_dprintf(EXT4_DEBUG_FS, "meta_csum\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_LARGEDIR) {
- ext4_dprintf(EXT4_DEBUG_FS, "largedir\n");
- }
- if (features_incompatible & EXT4_FEATURE_INCOMPAT_INLINE_DATA) {
- ext4_dprintf(EXT4_DEBUG_FS, "inline_data\n");
- }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_COMPRESSION) {
+ ext4_dprintf(EXT4_DEBUG_FS, "compression\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_FILETYPE) {
+ ext4_dprintf(EXT4_DEBUG_FS, "filetype\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_RECOVER) {
+ ext4_dprintf(EXT4_DEBUG_FS, "recover\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_JOURNAL_DEV) {
+ ext4_dprintf(EXT4_DEBUG_FS, "journal_dev\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_META_BG) {
+ ext4_dprintf(EXT4_DEBUG_FS, "meta_bg\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_EXTENTS) {
+ ext4_dprintf(EXT4_DEBUG_FS, "extents\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_64BIT) {
+ ext4_dprintf(EXT4_DEBUG_FS, "64bit\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_MMP) {
+ ext4_dprintf(EXT4_DEBUG_FS, "mnp\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+ ext4_dprintf(EXT4_DEBUG_FS, "flex_bg\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_EA_INODE) {
+ ext4_dprintf(EXT4_DEBUG_FS, "ea_inode\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_DIRDATA) {
+ ext4_dprintf(EXT4_DEBUG_FS, "dirdata\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM) {
+ ext4_dprintf(EXT4_DEBUG_FS, "meta_csum\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_LARGEDIR) {
+ ext4_dprintf(EXT4_DEBUG_FS, "largedir\n");
+ }
+ if (features_incompatible & EXT4_FEATURE_INCOMPAT_INLINE_DATA) {
+ ext4_dprintf(EXT4_DEBUG_FS, "inline_data\n");
+ }
}
static void ext4_fs_debug_features_comp(uint32_t features_compatible)
{
- if (features_compatible & EXT4_FEATURE_COMPAT_DIR_PREALLOC) {
- ext4_dprintf(EXT4_DEBUG_FS, " dir_prealloc\n");
- }
- if (features_compatible & EXT4_FEATURE_COMPAT_IMAGIC_INODES) {
- ext4_dprintf(EXT4_DEBUG_FS, "imagic_inodes\n");
- }
- if (features_compatible & EXT4_FEATURE_COMPAT_HAS_JOURNAL) {
- ext4_dprintf(EXT4_DEBUG_FS, "has_journal\n");
- }
- if (features_compatible & EXT4_FEATURE_COMPAT_EXT_ATTR) {
- ext4_dprintf(EXT4_DEBUG_FS, "ext_attr\n");
- }
- if (features_compatible & EXT4_FEATURE_COMPAT_RESIZE_INODE) {
- ext4_dprintf(EXT4_DEBUG_FS, "resize_inode\n");
- }
- if (features_compatible & EXT4_FEATURE_COMPAT_DIR_INDEX) {
- ext4_dprintf(EXT4_DEBUG_FS, "dir_index\n");
- }
+ if (features_compatible & EXT4_FEATURE_COMPAT_DIR_PREALLOC) {
+ ext4_dprintf(EXT4_DEBUG_FS, " dir_prealloc\n");
+ }
+ if (features_compatible & EXT4_FEATURE_COMPAT_IMAGIC_INODES) {
+ ext4_dprintf(EXT4_DEBUG_FS, "imagic_inodes\n");
+ }
+ if (features_compatible & EXT4_FEATURE_COMPAT_HAS_JOURNAL) {
+ ext4_dprintf(EXT4_DEBUG_FS, "has_journal\n");
+ }
+ if (features_compatible & EXT4_FEATURE_COMPAT_EXT_ATTR) {
+ ext4_dprintf(EXT4_DEBUG_FS, "ext_attr\n");
+ }
+ if (features_compatible & EXT4_FEATURE_COMPAT_RESIZE_INODE) {
+ ext4_dprintf(EXT4_DEBUG_FS, "resize_inode\n");
+ }
+ if (features_compatible & EXT4_FEATURE_COMPAT_DIR_INDEX) {
+ ext4_dprintf(EXT4_DEBUG_FS, "dir_index\n");
+ }
}
static void ext4_fs_debug_features_ro(uint32_t features_ro)
{
- if (features_ro & EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) {
- ext4_dprintf(EXT4_DEBUG_FS, "sparse_super\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_LARGE_FILE) {
- ext4_dprintf(EXT4_DEBUG_FS, "large_file\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_BTREE_DIR) {
- ext4_dprintf(EXT4_DEBUG_FS, "btree_dir\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) {
- ext4_dprintf(EXT4_DEBUG_FS, "huge_file\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
- ext4_dprintf(EXT4_DEBUG_FS, "gtd_csum\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) {
- ext4_dprintf(EXT4_DEBUG_FS, "dir_nlink\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) {
- ext4_dprintf(EXT4_DEBUG_FS, "extra_isize\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_QUOTA) {
- ext4_dprintf(EXT4_DEBUG_FS, "quota\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
- ext4_dprintf(EXT4_DEBUG_FS, "bigalloc\n");
- }
- if (features_ro & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
- ext4_dprintf(EXT4_DEBUG_FS, "metadata_csum\n");
- }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) {
+ ext4_dprintf(EXT4_DEBUG_FS, "sparse_super\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_LARGE_FILE) {
+ ext4_dprintf(EXT4_DEBUG_FS, "large_file\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_BTREE_DIR) {
+ ext4_dprintf(EXT4_DEBUG_FS, "btree_dir\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) {
+ ext4_dprintf(EXT4_DEBUG_FS, "huge_file\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+ ext4_dprintf(EXT4_DEBUG_FS, "gtd_csum\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_DIR_NLINK) {
+ ext4_dprintf(EXT4_DEBUG_FS, "dir_nlink\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE) {
+ ext4_dprintf(EXT4_DEBUG_FS, "extra_isize\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_QUOTA) {
+ ext4_dprintf(EXT4_DEBUG_FS, "quota\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+ ext4_dprintf(EXT4_DEBUG_FS, "bigalloc\n");
+ }
+ if (features_ro & EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+ ext4_dprintf(EXT4_DEBUG_FS, "metadata_csum\n");
+ }
}
int ext4_fs_check_features(struct ext4_fs *fs, bool *read_only)
{
- ext4_assert(fs && read_only);
- uint32_t v;
- if (ext4_get32(&fs->sb, rev_level) == 0) {
- *read_only = false;
- return EOK;
- }
-
- ext4_dprintf(EXT4_DEBUG_FS, "\nSB features_incompatible:\n");
- ext4_fs_debug_features_incomp(ext4_get32(&fs->sb, features_incompatible));
-
- ext4_dprintf(EXT4_DEBUG_FS, "\nSB features_compatible:\n");
- ext4_fs_debug_features_comp(ext4_get32(&fs->sb, features_compatible));
-
- ext4_dprintf(EXT4_DEBUG_FS, "\nSB features_read_only:\n");
- ext4_fs_debug_features_ro(ext4_get32(&fs->sb, features_read_only));
-
- /*Check features_incompatible*/
- v = (ext4_get32(&fs->sb, features_incompatible) &
- (~CONFIG_FEATURE_INCOMPAT_SUPP));
- if (v) {
- ext4_dprintf(EXT4_DEBUG_FS, "SB features_incompatible: fail\n");
- ext4_fs_debug_features_incomp(v);
- return ENOTSUP;
- }
-
- /*Check features_read_only*/
- v = (ext4_get32(&fs->sb, features_read_only) &
- (~CONFIG_FEATURE_RO_COMPAT_SUPP));
- if (v) {
- ext4_dprintf(EXT4_DEBUG_FS,
- "\nERROR sblock features_read_only . Unsupported:\n");
- ext4_fs_debug_features_incomp(v);
-
- *read_only = true;
- return EOK;
- }
- *read_only = false;
-
- return EOK;
+ ext4_assert(fs && read_only);
+ uint32_t v;
+ if (ext4_get32(&fs->sb, rev_level) == 0) {
+ *read_only = false;
+ return EOK;
+ }
+
+ ext4_dprintf(EXT4_DEBUG_FS, "\nSB features_incompatible:\n");
+ ext4_fs_debug_features_incomp(
+ ext4_get32(&fs->sb, features_incompatible));
+
+ ext4_dprintf(EXT4_DEBUG_FS, "\nSB features_compatible:\n");
+ ext4_fs_debug_features_comp(ext4_get32(&fs->sb, features_compatible));
+
+ ext4_dprintf(EXT4_DEBUG_FS, "\nSB features_read_only:\n");
+ ext4_fs_debug_features_ro(ext4_get32(&fs->sb, features_read_only));
+
+ /*Check features_incompatible*/
+ v = (ext4_get32(&fs->sb, features_incompatible) &
+ (~CONFIG_FEATURE_INCOMPAT_SUPP));
+ if (v) {
+ ext4_dprintf(EXT4_DEBUG_FS, "SB features_incompatible: fail\n");
+ ext4_fs_debug_features_incomp(v);
+ return ENOTSUP;
+ }
+
+ /*Check features_read_only*/
+ v = (ext4_get32(&fs->sb, features_read_only) &
+ (~CONFIG_FEATURE_RO_COMPAT_SUPP));
+ if (v) {
+ ext4_dprintf(
+ EXT4_DEBUG_FS,
+ "\nERROR sblock features_read_only . Unsupported:\n");
+ ext4_fs_debug_features_incomp(v);
+
+ *read_only = true;
+ return EOK;
+ }
+ *read_only = false;
+
+ return EOK;
}
/**@brief Initialize block bitmap in block group.
*/
static int ext4_fs_init_block_bitmap(struct ext4_block_group_ref *bg_ref)
{
- uint32_t i;
- uint32_t bitmap_block_addr =
- ext4_bg_get_block_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
+ uint32_t i;
+ uint32_t bitmap_block_addr =
+ ext4_bg_get_block_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
- struct ext4_block block_bitmap;
- int rc = ext4_block_get(bg_ref->fs->bdev, &block_bitmap, bitmap_block_addr);
- if (rc != EOK)
- return rc;
+ struct ext4_block block_bitmap;
+ int rc =
+ ext4_block_get(bg_ref->fs->bdev, &block_bitmap, bitmap_block_addr);
+ if (rc != EOK)
+ return rc;
- memset(block_bitmap.data, 0, ext4_sb_get_block_size(&bg_ref->fs->sb));
+ memset(block_bitmap.data, 0, ext4_sb_get_block_size(&bg_ref->fs->sb));
- /* Determine first block and first data block in group */
- uint32_t first_idx = 0;
+ /* Determine first block and first data block in group */
+ uint32_t first_idx = 0;
- uint32_t first_data =
- ext4_balloc_get_first_data_block_in_group(&bg_ref->fs->sb, bg_ref);
- uint32_t first_data_idx =
- ext4_fs_baddr2_index_in_group(&bg_ref->fs->sb, first_data);
+ uint32_t first_data =
+ ext4_balloc_get_first_data_block_in_group(&bg_ref->fs->sb, bg_ref);
+ uint32_t first_data_idx =
+ ext4_fs_baddr2_index_in_group(&bg_ref->fs->sb, first_data);
- /*Set bits from to first block to first data block - 1 to one (allocated)*/
- /*TODO: Optimize it*/
- for (i = first_idx; i < first_data_idx; ++i)
- ext4_bmap_bit_set(block_bitmap.data, i);
+ /*Set bits from to first block to first data block - 1 to one
+ * (allocated)*/
+ /*TODO: Optimize it*/
+ for (i = first_idx; i < first_data_idx; ++i)
+ ext4_bmap_bit_set(block_bitmap.data, i);
- block_bitmap.dirty = true;
+ block_bitmap.dirty = true;
- /* Save bitmap */
- return ext4_block_set(bg_ref->fs->bdev, &block_bitmap);
+ /* Save bitmap */
+ return ext4_block_set(bg_ref->fs->bdev, &block_bitmap);
}
/**@brief Initialize i-node bitmap in block group.
*/
static int ext4_fs_init_inode_bitmap(struct ext4_block_group_ref *bg_ref)
{
- /* Load bitmap */
- uint32_t bitmap_block_addr =
- ext4_bg_get_inode_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
+ /* Load bitmap */
+ uint32_t bitmap_block_addr =
+ ext4_bg_get_inode_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
- struct ext4_block block_bitmap;
- int rc = ext4_block_get(bg_ref->fs->bdev, &block_bitmap, bitmap_block_addr);
- if (rc != EOK)
- return rc;
+ struct ext4_block block_bitmap;
+ int rc =
+ ext4_block_get(bg_ref->fs->bdev, &block_bitmap, bitmap_block_addr);
+ if (rc != EOK)
+ return rc;
- /* Initialize all bitmap bits to zero */
- uint32_t block_size = ext4_sb_get_block_size(&bg_ref->fs->sb);
- uint32_t inodes_per_group = ext4_get32(&bg_ref->fs->sb, inodes_per_group);
+ /* Initialize all bitmap bits to zero */
+ uint32_t block_size = ext4_sb_get_block_size(&bg_ref->fs->sb);
+ uint32_t inodes_per_group =
+ ext4_get32(&bg_ref->fs->sb, inodes_per_group);
- memset(block_bitmap.data, 0, (inodes_per_group + 7) / 8);
+ memset(block_bitmap.data, 0, (inodes_per_group + 7) / 8);
- uint32_t start_bit = inodes_per_group;
- uint32_t end_bit = block_size * 8;
+ uint32_t start_bit = inodes_per_group;
+ uint32_t end_bit = block_size * 8;
- uint32_t i;
- for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
- ext4_bmap_bit_set(block_bitmap.data, i);
+ uint32_t i;
+ for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
+ ext4_bmap_bit_set(block_bitmap.data, i);
- if (i < end_bit)
- memset(block_bitmap.data + (i >> 3), 0xff, (end_bit - i) >> 3);
+ if (i < end_bit)
+ memset(block_bitmap.data + (i >> 3), 0xff, (end_bit - i) >> 3);
- block_bitmap.dirty = true;
+ block_bitmap.dirty = true;
- /* Save bitmap */
- return ext4_block_set(bg_ref->fs->bdev, &block_bitmap);
+ /* Save bitmap */
+ return ext4_block_set(bg_ref->fs->bdev, &block_bitmap);
}
/**@brief Initialize i-node table in block group.
*/
static int ext4_fs_init_inode_table(struct ext4_block_group_ref *bg_ref)
{
- struct ext4_sblock *sb = &bg_ref->fs->sb;
+ struct ext4_sblock *sb = &bg_ref->fs->sb;
- uint32_t inode_size = ext4_get32(sb, inode_size);
- uint32_t block_size = ext4_sb_get_block_size(sb);
- uint32_t inodes_per_block = block_size / inode_size;
- uint32_t inodes_in_group = ext4_inodes_in_group_cnt(sb, bg_ref->index);
- uint32_t table_blocks = inodes_in_group / inodes_per_block;
- uint32_t fblock;
+ uint32_t inode_size = ext4_get32(sb, inode_size);
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+ uint32_t inodes_per_block = block_size / inode_size;
+ uint32_t inodes_in_group = ext4_inodes_in_group_cnt(sb, bg_ref->index);
+ uint32_t table_blocks = inodes_in_group / inodes_per_block;
+ uint32_t fblock;
- if (inodes_in_group % inodes_per_block)
- table_blocks++;
+ if (inodes_in_group % inodes_per_block)
+ table_blocks++;
- /* Compute initialization bounds */
- uint32_t first_block =
- ext4_bg_get_inode_table_first_block(bg_ref->block_group, sb);
+ /* Compute initialization bounds */
+ uint32_t first_block =
+ ext4_bg_get_inode_table_first_block(bg_ref->block_group, sb);
- uint32_t last_block = first_block + table_blocks - 1;
+ uint32_t last_block = first_block + table_blocks - 1;
- /* Initialization of all itable blocks */
- for (fblock = first_block; fblock <= last_block; ++fblock) {
+ /* Initialization of all itable blocks */
+ for (fblock = first_block; fblock <= last_block; ++fblock) {
- struct ext4_block block;
- int rc = ext4_block_get(bg_ref->fs->bdev, &block, fblock);
- if (rc != EOK)
- return rc;
+ struct ext4_block block;
+ int rc = ext4_block_get(bg_ref->fs->bdev, &block, fblock);
+ if (rc != EOK)
+ return rc;
- memset(block.data, 0, block_size);
- block.dirty = true;
+ memset(block.data, 0, block_size);
+ block.dirty = true;
- ext4_block_set(bg_ref->fs->bdev, &block);
- if (rc != EOK)
- return rc;
- }
+ ext4_block_set(bg_ref->fs->bdev, &block);
+ if (rc != EOK)
+ return rc;
+ }
- return EOK;
+ return EOK;
}
static uint64_t ext4_fs_get_descriptor_block(struct ext4_sblock *s,
- uint32_t bgid,
- uint32_t dsc_per_block)
+ uint32_t bgid,
+ uint32_t dsc_per_block)
{
- uint32_t first_meta_bg, dsc_id;
+ uint32_t first_meta_bg, dsc_id;
- int has_super = 0;
+ int has_super = 0;
- dsc_id = bgid / dsc_per_block;
- first_meta_bg = ext4_sb_first_meta_bg(s);
+ dsc_id = bgid / dsc_per_block;
+ first_meta_bg = ext4_sb_first_meta_bg(s);
- if (!ext4_sb_has_feature_incompatible(s, EXT4_FEATURE_INCOMPAT_META_BG) ||
- dsc_id < first_meta_bg)
- return ext4_get32(s, first_data_block) + dsc_id + 1;
+ if (!ext4_sb_has_feature_incompatible(s,
+ EXT4_FEATURE_INCOMPAT_META_BG) ||
+ dsc_id < first_meta_bg)
+ return ext4_get32(s, first_data_block) + dsc_id + 1;
- if (ext4_sb_is_super_in_bg(s, bgid))
- has_super = 1;
+ if (ext4_sb_is_super_in_bg(s, bgid))
+ has_super = 1;
- return (has_super + ext4_fs_first_bg_block_no(s, bgid));
+ return (has_super + ext4_fs_first_bg_block_no(s, bgid));
}
int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid,
- struct ext4_block_group_ref *ref)
+ struct ext4_block_group_ref *ref)
{
- /* Compute number of descriptors, that fits in one data block */
- uint32_t dsc_per_block =
- ext4_sb_get_block_size(&fs->sb) / ext4_sb_get_desc_size(&fs->sb);
-
- /* Block group descriptor table starts at the next block after superblock */
- uint64_t block_id =
- ext4_fs_get_descriptor_block(&fs->sb, bgid, dsc_per_block);
-
- uint32_t offset = (bgid % dsc_per_block) * ext4_sb_get_desc_size(&fs->sb);
-
- int rc = ext4_block_get(fs->bdev, &ref->block, block_id);
- if (rc != EOK)
- return rc;
-
- ref->block_group = (void *)(ref->block.data + offset);
- ref->fs = fs;
- ref->index = bgid;
- ref->dirty = false;
-
- if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) {
- rc = ext4_fs_init_block_bitmap(ref);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &ref->block);
- return rc;
- }
- ext4_bg_clear_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT);
-
- ref->dirty = true;
- }
-
- if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) {
- rc = ext4_fs_init_inode_bitmap(ref);
- if (rc != EOK) {
- ext4_block_set(ref->fs->bdev, &ref->block);
- return rc;
- }
-
- ext4_bg_clear_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT);
-
- if (!ext4_bg_has_flag(ref->block_group,
- EXT4_BLOCK_GROUP_ITABLE_ZEROED)) {
- rc = ext4_fs_init_inode_table(ref);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &ref->block);
- return rc;
- }
-
- ext4_bg_set_flag(ref->block_group, EXT4_BLOCK_GROUP_ITABLE_ZEROED);
- }
-
- ref->dirty = true;
- }
-
- return EOK;
+ /* Compute number of descriptors, that fits in one data block */
+ uint32_t dsc_per_block =
+ ext4_sb_get_block_size(&fs->sb) / ext4_sb_get_desc_size(&fs->sb);
+
+ /* Block group descriptor table starts at the next block after
+ * superblock */
+ uint64_t block_id =
+ ext4_fs_get_descriptor_block(&fs->sb, bgid, dsc_per_block);
+
+ uint32_t offset =
+ (bgid % dsc_per_block) * ext4_sb_get_desc_size(&fs->sb);
+
+ int rc = ext4_block_get(fs->bdev, &ref->block, block_id);
+ if (rc != EOK)
+ return rc;
+
+ ref->block_group = (void *)(ref->block.data + offset);
+ ref->fs = fs;
+ ref->index = bgid;
+ ref->dirty = false;
+
+ if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) {
+ rc = ext4_fs_init_block_bitmap(ref);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &ref->block);
+ return rc;
+ }
+ ext4_bg_clear_flag(ref->block_group,
+ EXT4_BLOCK_GROUP_BLOCK_UNINIT);
+
+ ref->dirty = true;
+ }
+
+ if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) {
+ rc = ext4_fs_init_inode_bitmap(ref);
+ if (rc != EOK) {
+ ext4_block_set(ref->fs->bdev, &ref->block);
+ return rc;
+ }
+
+ ext4_bg_clear_flag(ref->block_group,
+ EXT4_BLOCK_GROUP_INODE_UNINIT);
+
+ if (!ext4_bg_has_flag(ref->block_group,
+ EXT4_BLOCK_GROUP_ITABLE_ZEROED)) {
+ rc = ext4_fs_init_inode_table(ref);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &ref->block);
+ return rc;
+ }
+
+ ext4_bg_set_flag(ref->block_group,
+ EXT4_BLOCK_GROUP_ITABLE_ZEROED);
+ }
+
+ ref->dirty = true;
+ }
+
+ return EOK;
}
/**@brief Compute checksum of block group descriptor.
* @return Checksum value
*/
static uint16_t ext4_fs_bg_checksum(struct ext4_sblock *sb, uint32_t bgid,
- struct ext4_bgroup *bg)
+ struct ext4_bgroup *bg)
{
- /* If checksum not supported, 0 will be returned */
- uint16_t crc = 0;
+ /* If checksum not supported, 0 will be returned */
+ uint16_t crc = 0;
- /* Compute the checksum only if the filesystem supports it */
- if (ext4_sb_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
- uint8_t *base = (uint8_t *)bg;
- uint8_t *checksum = (uint8_t *)&bg->checksum;
+ /* Compute the checksum only if the filesystem supports it */
+ if (ext4_sb_has_feature_read_only(sb,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ uint8_t *base = (uint8_t *)bg;
+ uint8_t *checksum = (uint8_t *)&bg->checksum;
- uint32_t offset = (uint32_t)(checksum - base);
+ uint32_t offset = (uint32_t)(checksum - base);
- /* Convert block group index to little endian */
- uint32_t le_group = to_le32(bgid);
+ /* Convert block group index to little endian */
+ uint32_t le_group = to_le32(bgid);
- /* Initialization */
- crc = ext4_bg_crc16(~0, sb->uuid, sizeof(sb->uuid));
+ /* Initialization */
+ crc = ext4_bg_crc16(~0, sb->uuid, sizeof(sb->uuid));
- /* Include index of block group */
- crc = ext4_bg_crc16(crc, (uint8_t *)&le_group, sizeof(le_group));
+ /* Include index of block group */
+ crc =
+ ext4_bg_crc16(crc, (uint8_t *)&le_group, sizeof(le_group));
- /* Compute crc from the first part (stop before checksum field) */
- crc = ext4_bg_crc16(crc, (uint8_t *)bg, offset);
+ /* Compute crc from the first part (stop before checksum field)
+ */
+ crc = ext4_bg_crc16(crc, (uint8_t *)bg, offset);
- /* Skip checksum */
- offset += sizeof(bg->checksum);
+ /* Skip checksum */
+ offset += sizeof(bg->checksum);
- /* Checksum of the rest of block group descriptor */
- if ((ext4_sb_has_feature_incompatible(sb,
- EXT4_FEATURE_INCOMPAT_64BIT)) &&
- (offset < ext4_sb_get_desc_size(sb)))
+ /* Checksum of the rest of block group descriptor */
+ if ((ext4_sb_has_feature_incompatible(
+ sb, EXT4_FEATURE_INCOMPAT_64BIT)) &&
+ (offset < ext4_sb_get_desc_size(sb)))
- crc = ext4_bg_crc16(crc, ((uint8_t *)bg) + offset,
- ext4_sb_get_desc_size(sb) - offset);
- }
- return crc;
+ crc = ext4_bg_crc16(crc, ((uint8_t *)bg) + offset,
+ ext4_sb_get_desc_size(sb) - offset);
+ }
+ return crc;
}
int ext4_fs_put_block_group_ref(struct ext4_block_group_ref *ref)
{
- /* Check if reference modified */
- if (ref->dirty) {
- /* Compute new checksum of block group */
- uint16_t checksum =
- ext4_fs_bg_checksum(&ref->fs->sb, ref->index, ref->block_group);
+ /* Check if reference modified */
+ if (ref->dirty) {
+ /* Compute new checksum of block group */
+ uint16_t checksum = ext4_fs_bg_checksum(
+ &ref->fs->sb, ref->index, ref->block_group);
- ref->block_group->checksum = to_le16(checksum);
+ ref->block_group->checksum = to_le16(checksum);
- /* Mark block dirty for writing changes to physical device */
- ref->block.dirty = true;
- }
+ /* Mark block dirty for writing changes to physical device */
+ ref->block.dirty = true;
+ }
- /* Put back block, that contains block group descriptor */
- return ext4_block_set(ref->fs->bdev, &ref->block);
+ /* Put back block, that contains block group descriptor */
+ return ext4_block_set(ref->fs->bdev, &ref->block);
}
int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index,
- struct ext4_inode_ref *ref)
+ struct ext4_inode_ref *ref)
{
- /* Compute number of i-nodes, that fits in one data block */
- uint32_t inodes_per_group = ext4_get32(&fs->sb, inodes_per_group);
-
- /*
- * Inode numbers are 1-based, but it is simpler to work with 0-based
- * when computing indices
- */
- index -= 1;
- uint32_t block_group = index / inodes_per_group;
- uint32_t offset_in_group = index % inodes_per_group;
-
- /* Load block group, where i-node is located */
- struct ext4_block_group_ref bg_ref;
-
- int rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);
- if (rc != EOK) {
- return rc;
- }
-
- /* Load block address, where i-node table is located */
- uint32_t inode_table_start =
- ext4_bg_get_inode_table_first_block(bg_ref.block_group, &fs->sb);
-
- /* Put back block group reference (not needed more) */
- rc = ext4_fs_put_block_group_ref(&bg_ref);
- if (rc != EOK) {
- return rc;
- }
-
- /* Compute position of i-node in the block group */
- uint16_t inode_size = ext4_get16(&fs->sb, inode_size);
- uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
- uint32_t byte_offset_in_group = offset_in_group * inode_size;
-
- /* Compute block address */
- uint64_t block_id = inode_table_start + (byte_offset_in_group / block_size);
-
- rc = ext4_block_get(fs->bdev, &ref->block, block_id);
- if (rc != EOK) {
- return rc;
- }
-
- /* Compute position of i-node in the data block */
- uint32_t offset_in_block = byte_offset_in_group % block_size;
- ref->inode = (struct ext4_inode *)(ref->block.data + offset_in_block);
-
- /* We need to store the original value of index in the reference */
- ref->index = index + 1;
- ref->fs = fs;
- ref->dirty = false;
-
- return EOK;
+ /* Compute number of i-nodes, that fits in one data block */
+ uint32_t inodes_per_group = ext4_get32(&fs->sb, inodes_per_group);
+
+ /*
+ * Inode numbers are 1-based, but it is simpler to work with 0-based
+ * when computing indices
+ */
+ index -= 1;
+ uint32_t block_group = index / inodes_per_group;
+ uint32_t offset_in_group = index % inodes_per_group;
+
+ /* Load block group, where i-node is located */
+ struct ext4_block_group_ref bg_ref;
+
+ int rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);
+ if (rc != EOK) {
+ return rc;
+ }
+
+ /* Load block address, where i-node table is located */
+ uint32_t inode_table_start =
+ ext4_bg_get_inode_table_first_block(bg_ref.block_group, &fs->sb);
+
+ /* Put back block group reference (not needed more) */
+ rc = ext4_fs_put_block_group_ref(&bg_ref);
+ if (rc != EOK) {
+ return rc;
+ }
+
+ /* Compute position of i-node in the block group */
+ uint16_t inode_size = ext4_get16(&fs->sb, inode_size);
+ uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
+ uint32_t byte_offset_in_group = offset_in_group * inode_size;
+
+ /* Compute block address */
+ uint64_t block_id =
+ inode_table_start + (byte_offset_in_group / block_size);
+
+ rc = ext4_block_get(fs->bdev, &ref->block, block_id);
+ if (rc != EOK) {
+ return rc;
+ }
+
+ /* Compute position of i-node in the data block */
+ uint32_t offset_in_block = byte_offset_in_group % block_size;
+ ref->inode = (struct ext4_inode *)(ref->block.data + offset_in_block);
+
+ /* We need to store the original value of index in the reference */
+ ref->index = index + 1;
+ ref->fs = fs;
+ ref->dirty = false;
+
+ return EOK;
}
int ext4_fs_put_inode_ref(struct ext4_inode_ref *ref)
{
- /* Check if reference modified */
- if (ref->dirty) {
- /* Mark block dirty for writing changes to physical device */
- ref->block.dirty = true;
- }
-
- /* Put back block, that contains i-node */
- return ext4_block_set(ref->fs->bdev, &ref->block);
+ /* Check if reference modified */
+ if (ref->dirty) {
+ /* Mark block dirty for writing changes to physical device */
+ ref->block.dirty = true;
+ }
+
+ /* Put back block, that contains i-node */
+ return ext4_block_set(ref->fs->bdev, &ref->block);
}
int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref,
- bool is_directory)
+ bool is_directory)
{
- /* Check if newly allocated i-node will be a directory */
- uint32_t i;
- bool is_dir;
-
- is_dir = is_directory;
-
- /* Allocate inode by allocation algorithm */
- uint32_t index;
- int rc = ext4_ialloc_alloc_inode(fs, &index, is_dir);
- if (rc != EOK)
- return rc;
-
- /* Load i-node from on-disk i-node table */
- rc = ext4_fs_get_inode_ref(fs, index, inode_ref);
- if (rc != EOK) {
- ext4_ialloc_free_inode(fs, index, is_dir);
- return rc;
- }
-
- /* Initialize i-node */
- struct ext4_inode *inode = inode_ref->inode;
-
- uint16_t mode;
- if (is_dir) {
- /*
- * Default directory permissions to be compatible with other systems
- * 0777 (octal) == rwxrwxrwx
- */
-
- mode = 0777;
- mode |= EXT4_INODE_MODE_DIRECTORY;
- ext4_inode_set_mode(&fs->sb, inode, mode);
- } else {
- /*
- * Default file permissions to be compatible with other systems
- * 0666 (octal) == rw-rw-rw-
- */
-
- mode = 0666;
- mode |= EXT4_INODE_MODE_FILE;
- ext4_inode_set_mode(&fs->sb, inode, mode);
- }
-
- ext4_inode_set_links_count(inode, 0);
- ext4_inode_set_uid(inode, 0);
- ext4_inode_set_gid(inode, 0);
- ext4_inode_set_size(inode, 0);
- ext4_inode_set_access_time(inode, 0);
- ext4_inode_set_change_inode_time(inode, 0);
- ext4_inode_set_modification_time(inode, 0);
- ext4_inode_set_deletion_time(inode, 0);
- ext4_inode_set_blocks_count(&fs->sb, inode, 0);
- ext4_inode_set_flags(inode, 0);
- ext4_inode_set_generation(inode, 0);
-
- /* Reset blocks array */
- for (i = 0; i < EXT4_INODE_BLOCKS; i++)
- inode->blocks[i] = 0;
+ /* Check if newly allocated i-node will be a directory */
+ uint32_t i;
+ bool is_dir;
+
+ is_dir = is_directory;
+
+ /* Allocate inode by allocation algorithm */
+ uint32_t index;
+ int rc = ext4_ialloc_alloc_inode(fs, &index, is_dir);
+ if (rc != EOK)
+ return rc;
+
+ /* Load i-node from on-disk i-node table */
+ rc = ext4_fs_get_inode_ref(fs, index, inode_ref);
+ if (rc != EOK) {
+ ext4_ialloc_free_inode(fs, index, is_dir);
+ return rc;
+ }
+
+ /* Initialize i-node */
+ struct ext4_inode *inode = inode_ref->inode;
+
+ uint16_t mode;
+ if (is_dir) {
+ /*
+ * Default directory permissions to be compatible with other
+ * systems
+ * 0777 (octal) == rwxrwxrwx
+ */
+
+ mode = 0777;
+ mode |= EXT4_INODE_MODE_DIRECTORY;
+ ext4_inode_set_mode(&fs->sb, inode, mode);
+ } else {
+ /*
+ * Default file permissions to be compatible with other systems
+ * 0666 (octal) == rw-rw-rw-
+ */
+
+ mode = 0666;
+ mode |= EXT4_INODE_MODE_FILE;
+ ext4_inode_set_mode(&fs->sb, inode, mode);
+ }
+
+ ext4_inode_set_links_count(inode, 0);
+ ext4_inode_set_uid(inode, 0);
+ ext4_inode_set_gid(inode, 0);
+ ext4_inode_set_size(inode, 0);
+ ext4_inode_set_access_time(inode, 0);
+ ext4_inode_set_change_inode_time(inode, 0);
+ ext4_inode_set_modification_time(inode, 0);
+ ext4_inode_set_deletion_time(inode, 0);
+ ext4_inode_set_blocks_count(&fs->sb, inode, 0);
+ ext4_inode_set_flags(inode, 0);
+ ext4_inode_set_generation(inode, 0);
+
+ /* Reset blocks array */
+ for (i = 0; i < EXT4_INODE_BLOCKS; i++)
+ inode->blocks[i] = 0;
#if CONFIG_EXTENT_ENABLE
- /* Initialize extents if needed */
- if (ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FEATURE_INCOMPAT_EXTENTS)) {
- ext4_inode_set_flag(inode, EXT4_INODE_FLAG_EXTENTS);
-
- /* Initialize extent root header */
- struct ext4_extent_header *header = ext4_inode_get_extent_header(inode);
- ext4_extent_header_set_depth(header, 0);
- ext4_extent_header_set_entries_count(header, 0);
- ext4_extent_header_set_generation(header, 0);
- ext4_extent_header_set_magic(header, EXT4_EXTENT_MAGIC);
-
- uint16_t max_entries = (EXT4_INODE_BLOCKS * sizeof(uint32_t) -
- sizeof(struct ext4_extent_header)) /
- sizeof(struct ext4_extent);
-
- ext4_extent_header_set_max_entries_count(header, max_entries);
- }
+ /* Initialize extents if needed */
+ if (ext4_sb_has_feature_incompatible(&fs->sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+ ext4_inode_set_flag(inode, EXT4_INODE_FLAG_EXTENTS);
+
+ /* Initialize extent root header */
+ struct ext4_extent_header *header =
+ ext4_inode_get_extent_header(inode);
+ ext4_extent_header_set_depth(header, 0);
+ ext4_extent_header_set_entries_count(header, 0);
+ ext4_extent_header_set_generation(header, 0);
+ ext4_extent_header_set_magic(header, EXT4_EXTENT_MAGIC);
+
+ uint16_t max_entries = (EXT4_INODE_BLOCKS * sizeof(uint32_t) -
+ sizeof(struct ext4_extent_header)) /
+ sizeof(struct ext4_extent);
+
+ ext4_extent_header_set_max_entries_count(header, max_entries);
+ }
#endif
- inode_ref->dirty = true;
+ inode_ref->dirty = true;
- return EOK;
+ return EOK;
}
int ext4_fs_free_inode(struct ext4_inode_ref *inode_ref)
{
- struct ext4_fs *fs = inode_ref->fs;
- uint32_t offset;
- uint32_t suboffset;
+ struct ext4_fs *fs = inode_ref->fs;
+ uint32_t offset;
+ uint32_t suboffset;
#if CONFIG_EXTENT_ENABLE
- /* For extents must be data block destroyed by other way */
- if ((ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
- (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
- /* Data structures are released during truncate operation... */
- goto finish;
- }
+ /* For extents must be data block destroyed by other way */
+ if ((ext4_sb_has_feature_incompatible(&fs->sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+ (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+ /* Data structures are released during truncate operation... */
+ goto finish;
+ }
#endif
- /* Release all indirect (no data) blocks */
-
- /* 1) Single indirect */
- uint32_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
- if (fblock != 0) {
- int rc = ext4_balloc_free_block(inode_ref, fblock);
- if (rc != EOK)
- return rc;
-
- ext4_inode_set_indirect_block(inode_ref->inode, 0, 0);
- }
-
- uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
- uint32_t count = block_size / sizeof(uint32_t);
-
- struct ext4_block block;
-
- /* 2) Double indirect */
- fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1);
- if (fblock != 0) {
- int rc = ext4_block_get(fs->bdev, &block, fblock);
- if (rc != EOK)
- return rc;
-
- uint32_t ind_block;
- for (offset = 0; offset < count; ++offset) {
- ind_block = to_le32(((uint32_t *)block.data)[offset]);
-
- if (ind_block != 0) {
- rc = ext4_balloc_free_block(inode_ref, ind_block);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
- }
- }
-
- ext4_block_set(fs->bdev, &block);
- rc = ext4_balloc_free_block(inode_ref, fblock);
- if (rc != EOK)
- return rc;
-
- ext4_inode_set_indirect_block(inode_ref->inode, 1, 0);
- }
-
- /* 3) Tripple indirect */
- struct ext4_block subblock;
- fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2);
- if (fblock != 0) {
- int rc = ext4_block_get(fs->bdev, &block, fblock);
- if (rc != EOK)
- return rc;
-
- uint32_t ind_block;
- for (offset = 0; offset < count; ++offset) {
- ind_block = to_le32(((uint32_t *)block.data)[offset]);
-
- if (ind_block != 0) {
- rc = ext4_block_get(fs->bdev, &subblock, ind_block);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
-
- uint32_t ind_subblock;
- for (suboffset = 0; suboffset < count; ++suboffset) {
- ind_subblock =
- to_le32(((uint32_t *)subblock.data)[suboffset]);
-
- if (ind_subblock != 0) {
- rc = ext4_balloc_free_block(inode_ref, ind_subblock);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &subblock);
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
- }
- }
-
- ext4_block_set(fs->bdev, &subblock);
-
- rc = ext4_balloc_free_block(inode_ref, ind_block);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
- }
- }
-
- ext4_block_set(fs->bdev, &block);
- rc = ext4_balloc_free_block(inode_ref, fblock);
- if (rc != EOK)
- return rc;
-
- ext4_inode_set_indirect_block(inode_ref->inode, 2, 0);
- }
+ /* Release all indirect (no data) blocks */
+
+ /* 1) Single indirect */
+ uint32_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
+ if (fblock != 0) {
+ int rc = ext4_balloc_free_block(inode_ref, fblock);
+ if (rc != EOK)
+ return rc;
+
+ ext4_inode_set_indirect_block(inode_ref->inode, 0, 0);
+ }
+
+ uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
+ uint32_t count = block_size / sizeof(uint32_t);
+
+ struct ext4_block block;
+
+ /* 2) Double indirect */
+ fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1);
+ if (fblock != 0) {
+ int rc = ext4_block_get(fs->bdev, &block, fblock);
+ if (rc != EOK)
+ return rc;
+
+ uint32_t ind_block;
+ for (offset = 0; offset < count; ++offset) {
+ ind_block = to_le32(((uint32_t *)block.data)[offset]);
+
+ if (ind_block != 0) {
+ rc = ext4_balloc_free_block(inode_ref,
+ ind_block);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+ }
+ }
+
+ ext4_block_set(fs->bdev, &block);
+ rc = ext4_balloc_free_block(inode_ref, fblock);
+ if (rc != EOK)
+ return rc;
+
+ ext4_inode_set_indirect_block(inode_ref->inode, 1, 0);
+ }
+
+ /* 3) Tripple indirect */
+ struct ext4_block subblock;
+ fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2);
+ if (fblock != 0) {
+ int rc = ext4_block_get(fs->bdev, &block, fblock);
+ if (rc != EOK)
+ return rc;
+
+ uint32_t ind_block;
+ for (offset = 0; offset < count; ++offset) {
+ ind_block = to_le32(((uint32_t *)block.data)[offset]);
+
+ if (ind_block != 0) {
+ rc = ext4_block_get(fs->bdev, &subblock,
+ ind_block);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+
+ uint32_t ind_subblock;
+ for (suboffset = 0; suboffset < count;
+ ++suboffset) {
+ ind_subblock = to_le32(
+ ((uint32_t *)
+ subblock.data)[suboffset]);
+
+ if (ind_subblock != 0) {
+ rc = ext4_balloc_free_block(
+ inode_ref, ind_subblock);
+ if (rc != EOK) {
+ ext4_block_set(
+ fs->bdev,
+ &subblock);
+ ext4_block_set(fs->bdev,
+ &block);
+ return rc;
+ }
+ }
+ }
+
+ ext4_block_set(fs->bdev, &subblock);
+
+ rc = ext4_balloc_free_block(inode_ref,
+ ind_block);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+ }
+ }
+
+ ext4_block_set(fs->bdev, &block);
+ rc = ext4_balloc_free_block(inode_ref, fblock);
+ if (rc != EOK)
+ return rc;
+
+ ext4_inode_set_indirect_block(inode_ref->inode, 2, 0);
+ }
#if CONFIG_EXTENT_ENABLE
finish:
#endif
- /* Mark inode dirty for writing to the physical device */
- inode_ref->dirty = true;
-
- /* Free block with extended attributes if present */
- uint32_t xattr_block = ext4_inode_get_file_acl(inode_ref->inode, &fs->sb);
- if (xattr_block) {
- int rc = ext4_balloc_free_block(inode_ref, xattr_block);
- if (rc != EOK)
- return rc;
-
- ext4_inode_set_file_acl(inode_ref->inode, &fs->sb, 0);
- }
-
- /* Free inode by allocator */
- int rc;
- if (ext4_inode_is_type(&fs->sb, inode_ref->inode,
- EXT4_INODE_MODE_DIRECTORY))
- rc = ext4_ialloc_free_inode(fs, inode_ref->index, true);
- else
- rc = ext4_ialloc_free_inode(fs, inode_ref->index, false);
-
- return rc;
+ /* Mark inode dirty for writing to the physical device */
+ inode_ref->dirty = true;
+
+ /* Free block with extended attributes if present */
+ uint32_t xattr_block =
+ ext4_inode_get_file_acl(inode_ref->inode, &fs->sb);
+ if (xattr_block) {
+ int rc = ext4_balloc_free_block(inode_ref, xattr_block);
+ if (rc != EOK)
+ return rc;
+
+ ext4_inode_set_file_acl(inode_ref->inode, &fs->sb, 0);
+ }
+
+ /* Free inode by allocator */
+ int rc;
+ if (ext4_inode_is_type(&fs->sb, inode_ref->inode,
+ EXT4_INODE_MODE_DIRECTORY))
+ rc = ext4_ialloc_free_inode(fs, inode_ref->index, true);
+ else
+ rc = ext4_ialloc_free_inode(fs, inode_ref->index, false);
+
+ return rc;
}
int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref, uint64_t new_size)
{
- struct ext4_sblock *sb = &inode_ref->fs->sb;
- uint32_t i;
-
- /* Check flags, if i-node can be truncated */
- if (!ext4_inode_can_truncate(sb, inode_ref->inode))
- return EINVAL;
-
- /* If sizes are equal, nothing has to be done. */
- uint64_t old_size = ext4_inode_get_size(sb, inode_ref->inode);
- if (old_size == new_size)
- return EOK;
-
- /* It's not supported to make the larger file by truncate operation */
- if (old_size < new_size)
- return EINVAL;
-
- /* Compute how many blocks will be released */
- uint64_t size_diff = old_size - new_size;
- uint32_t block_size = ext4_sb_get_block_size(sb);
- uint32_t diff_blocks_count = size_diff / block_size;
- if (size_diff % block_size != 0)
- diff_blocks_count++;
-
- uint32_t old_blocks_count = old_size / block_size;
- if (old_size % block_size != 0)
- old_blocks_count++;
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+ uint32_t i;
+
+ /* Check flags, if i-node can be truncated */
+ if (!ext4_inode_can_truncate(sb, inode_ref->inode))
+ return EINVAL;
+
+ /* If sizes are equal, nothing has to be done. */
+ uint64_t old_size = ext4_inode_get_size(sb, inode_ref->inode);
+ if (old_size == new_size)
+ return EOK;
+
+ /* It's not supported to make the larger file by truncate operation */
+ if (old_size < new_size)
+ return EINVAL;
+
+ /* Compute how many blocks will be released */
+ uint64_t size_diff = old_size - new_size;
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+ uint32_t diff_blocks_count = size_diff / block_size;
+ if (size_diff % block_size != 0)
+ diff_blocks_count++;
+
+ uint32_t old_blocks_count = old_size / block_size;
+ if (old_size % block_size != 0)
+ old_blocks_count++;
#if CONFIG_EXTENT_ENABLE
- if ((ext4_sb_has_feature_incompatible(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
- (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
-
- /* Extents require special operation */
- int rc = ext4_extent_release_blocks_from(
- inode_ref, old_blocks_count - diff_blocks_count);
- if (rc != EOK)
- return rc;
- } else
+ if ((ext4_sb_has_feature_incompatible(sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+ (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+
+ /* Extents require special operation */
+ int rc = ext4_extent_release_blocks_from(
+ inode_ref, old_blocks_count - diff_blocks_count);
+ if (rc != EOK)
+ return rc;
+ } else
#endif
- {
- /* Release data blocks from the end of file */
-
- /* Starting from 1 because of logical blocks are numbered from 0 */
- for (i = 1; i <= diff_blocks_count; ++i) {
- int rc =
- ext4_fs_release_inode_block(inode_ref, old_blocks_count - i);
- if (rc != EOK)
- return rc;
- }
- }
-
- /* Update i-node */
- ext4_inode_set_size(inode_ref->inode, new_size);
- inode_ref->dirty = true;
-
- return EOK;
+ {
+ /* Release data blocks from the end of file */
+
+ /* Starting from 1 because of logical blocks are numbered from 0
+ */
+ for (i = 1; i <= diff_blocks_count; ++i) {
+ int rc = ext4_fs_release_inode_block(
+ inode_ref, old_blocks_count - i);
+ if (rc != EOK)
+ return rc;
+ }
+ }
+
+ /* Update i-node */
+ ext4_inode_set_size(inode_ref->inode, new_size);
+ inode_ref->dirty = true;
+
+ return EOK;
}
int ext4_fs_get_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock)
+ uint64_t iblock, uint32_t *fblock)
{
- struct ext4_fs *fs = inode_ref->fs;
+ struct ext4_fs *fs = inode_ref->fs;
- /* For empty file is situation simple */
- if (ext4_inode_get_size(&fs->sb, inode_ref->inode) == 0) {
- *fblock = 0;
- return EOK;
- }
+ /* For empty file is situation simple */
+ if (ext4_inode_get_size(&fs->sb, inode_ref->inode) == 0) {
+ *fblock = 0;
+ return EOK;
+ }
- uint32_t current_block;
+ uint32_t current_block;
#if CONFIG_EXTENT_ENABLE
- /* Handle i-node using extents */
- if ((ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
- (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
-
- int rc = ext4_extent_find_block(inode_ref, iblock, ¤t_block);
- if (rc != EOK)
- return rc;
-
- *fblock = current_block;
- return EOK;
- }
+ /* Handle i-node using extents */
+ if ((ext4_sb_has_feature_incompatible(&fs->sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+ (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+
+ int rc =
+ ext4_extent_find_block(inode_ref, iblock, ¤t_block);
+ if (rc != EOK)
+ return rc;
+
+ *fblock = current_block;
+ return EOK;
+ }
#endif
- struct ext4_inode *inode = inode_ref->inode;
-
- /* Direct block are read directly from array in i-node structure */
- if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
- current_block = ext4_inode_get_direct_block(inode, (uint32_t)iblock);
- *fblock = current_block;
- return EOK;
- }
-
- /* Determine indirection level of the target block */
- unsigned int level = 0;
- unsigned int i;
- for (i = 1; i < 4; i++) {
- if (iblock < fs->inode_block_limits[i]) {
- level = i;
- break;
- }
- }
-
- if (level == 0)
- return EIO;
-
- /* Compute offsets for the topmost level */
- uint64_t block_offset_in_level = iblock - fs->inode_block_limits[level - 1];
- current_block = ext4_inode_get_indirect_block(inode, level - 1);
- uint32_t offset_in_block =
- block_offset_in_level / fs->inode_blocks_per_level[level - 1];
-
- /* Sparse file */
- if (current_block == 0) {
- *fblock = 0;
- return EOK;
- }
-
- struct ext4_block block;
-
- /*
- * Navigate through other levels, until we find the block number
- * or find null reference meaning we are dealing with sparse file
- */
- while (level > 0) {
- /* Load indirect block */
- int rc = ext4_block_get(fs->bdev, &block, current_block);
- if (rc != EOK)
- return rc;
-
- /* Read block address from indirect block */
- current_block = to_le32(((uint32_t *)block.data)[offset_in_block]);
-
- /* Put back indirect block untouched */
- rc = ext4_block_set(fs->bdev, &block);
- if (rc != EOK)
- return rc;
-
- /* Check for sparse file */
- if (current_block == 0) {
- *fblock = 0;
- return EOK;
- }
-
- /* Jump to the next level */
- level--;
-
- /* Termination condition - we have address of data block loaded */
- if (level == 0)
- break;
-
- /* Visit the next level */
- block_offset_in_level %= fs->inode_blocks_per_level[level];
- offset_in_block =
- block_offset_in_level / fs->inode_blocks_per_level[level - 1];
- }
-
- *fblock = current_block;
-
- return EOK;
+ struct ext4_inode *inode = inode_ref->inode;
+
+ /* Direct block are read directly from array in i-node structure */
+ if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
+ current_block =
+ ext4_inode_get_direct_block(inode, (uint32_t)iblock);
+ *fblock = current_block;
+ return EOK;
+ }
+
+ /* Determine indirection level of the target block */
+ unsigned int level = 0;
+ unsigned int i;
+ for (i = 1; i < 4; i++) {
+ if (iblock < fs->inode_block_limits[i]) {
+ level = i;
+ break;
+ }
+ }
+
+ if (level == 0)
+ return EIO;
+
+ /* Compute offsets for the topmost level */
+ uint64_t block_offset_in_level =
+ iblock - fs->inode_block_limits[level - 1];
+ current_block = ext4_inode_get_indirect_block(inode, level - 1);
+ uint32_t offset_in_block =
+ block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+
+ /* Sparse file */
+ if (current_block == 0) {
+ *fblock = 0;
+ return EOK;
+ }
+
+ struct ext4_block block;
+
+ /*
+ * Navigate through other levels, until we find the block number
+ * or find null reference meaning we are dealing with sparse file
+ */
+ while (level > 0) {
+ /* Load indirect block */
+ int rc = ext4_block_get(fs->bdev, &block, current_block);
+ if (rc != EOK)
+ return rc;
+
+ /* Read block address from indirect block */
+ current_block =
+ to_le32(((uint32_t *)block.data)[offset_in_block]);
+
+ /* Put back indirect block untouched */
+ rc = ext4_block_set(fs->bdev, &block);
+ if (rc != EOK)
+ return rc;
+
+ /* Check for sparse file */
+ if (current_block == 0) {
+ *fblock = 0;
+ return EOK;
+ }
+
+ /* Jump to the next level */
+ level--;
+
+ /* Termination condition - we have address of data block loaded
+ */
+ if (level == 0)
+ break;
+
+ /* Visit the next level */
+ block_offset_in_level %= fs->inode_blocks_per_level[level];
+ offset_in_block = block_offset_in_level /
+ fs->inode_blocks_per_level[level - 1];
+ }
+
+ *fblock = current_block;
+
+ return EOK;
}
int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t fblock)
+ uint64_t iblock, uint32_t fblock)
{
- struct ext4_fs *fs = inode_ref->fs;
+ struct ext4_fs *fs = inode_ref->fs;
#if CONFIG_EXTENT_ENABLE
- /* Handle inode using extents */
- if ((ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
- (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
- /* Not reachable */
- return ENOTSUP;
- }
+ /* Handle inode using extents */
+ if ((ext4_sb_has_feature_incompatible(&fs->sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+ (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+ /* Not reachable */
+ return ENOTSUP;
+ }
#endif
- /* Handle simple case when we are dealing with direct reference */
- if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
- ext4_inode_set_direct_block(inode_ref->inode, (uint32_t)iblock, fblock);
- inode_ref->dirty = true;
-
- return EOK;
- }
-
- /* Determine the indirection level needed to get the desired block */
- unsigned int level = 0;
- unsigned int i;
- for (i = 1; i < 4; i++) {
- if (iblock < fs->inode_block_limits[i]) {
- level = i;
- break;
- }
- }
-
- if (level == 0)
- return EIO;
-
- uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
-
- /* Compute offsets for the topmost level */
- uint64_t block_offset_in_level = iblock - fs->inode_block_limits[level - 1];
- uint32_t current_block =
- ext4_inode_get_indirect_block(inode_ref->inode, level - 1);
- uint32_t offset_in_block =
- block_offset_in_level / fs->inode_blocks_per_level[level - 1];
-
- uint32_t new_block_addr;
-
- struct ext4_block block;
- struct ext4_block new_block;
-
- /* Is needed to allocate indirect block on the i-node level */
- if (current_block == 0) {
- /* Allocate new indirect block */
- int rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
- if (rc != EOK)
- return rc;
-
- /* Update i-node */
- ext4_inode_set_indirect_block(inode_ref->inode, level - 1,
- new_block_addr);
- inode_ref->dirty = true;
-
- /* Load newly allocated block */
- rc = ext4_block_get(fs->bdev, &new_block, new_block_addr);
- if (rc != EOK) {
- ext4_balloc_free_block(inode_ref, new_block_addr);
- return rc;
- }
-
- /* Initialize new block */
- memset(new_block.data, 0, block_size);
- new_block.dirty = true;
-
- /* Put back the allocated block */
- rc = ext4_block_set(fs->bdev, &new_block);
- if (rc != EOK)
- return rc;
-
- current_block = new_block_addr;
- }
-
- /*
- * Navigate through other levels, until we find the block number
- * or find null reference meaning we are dealing with sparse file
- */
- while (level > 0) {
- int rc = ext4_block_get(fs->bdev, &block, current_block);
- if (rc != EOK)
- return rc;
-
- current_block = to_le32(((uint32_t *)block.data)[offset_in_block]);
-
- if ((level > 1) && (current_block == 0)) {
- /* Allocate new block */
- rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
-
- /* Load newly allocated block */
- rc = ext4_block_get(fs->bdev, &new_block, new_block_addr);
-
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
-
- /* Initialize allocated block */
- memset(new_block.data, 0, block_size);
- new_block.dirty = true;
-
- rc = ext4_block_set(fs->bdev, &new_block);
- if (rc != EOK) {
- ext4_block_set(fs->bdev, &block);
- return rc;
- }
-
- /* Write block address to the parent */
- ((uint32_t *)block.data)[offset_in_block] = to_le32(new_block_addr);
- block.dirty = true;
- current_block = new_block_addr;
- }
-
- /* Will be finished, write the fblock address */
- if (level == 1) {
- ((uint32_t *)block.data)[offset_in_block] = to_le32(fblock);
- block.dirty = true;
- }
-
- rc = ext4_block_set(fs->bdev, &block);
- if (rc != EOK)
- return rc;
-
- level--;
-
- /*
- * If we are on the last level, break here as
- * there is no next level to visit
- */
- if (level == 0)
- break;
-
- /* Visit the next level */
- block_offset_in_level %= fs->inode_blocks_per_level[level];
- offset_in_block =
- block_offset_in_level / fs->inode_blocks_per_level[level - 1];
- }
-
- return EOK;
+ /* Handle simple case when we are dealing with direct reference */
+ if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
+ ext4_inode_set_direct_block(inode_ref->inode, (uint32_t)iblock,
+ fblock);
+ inode_ref->dirty = true;
+
+ return EOK;
+ }
+
+ /* Determine the indirection level needed to get the desired block */
+ unsigned int level = 0;
+ unsigned int i;
+ for (i = 1; i < 4; i++) {
+ if (iblock < fs->inode_block_limits[i]) {
+ level = i;
+ break;
+ }
+ }
+
+ if (level == 0)
+ return EIO;
+
+ uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
+
+ /* Compute offsets for the topmost level */
+ uint64_t block_offset_in_level =
+ iblock - fs->inode_block_limits[level - 1];
+ uint32_t current_block =
+ ext4_inode_get_indirect_block(inode_ref->inode, level - 1);
+ uint32_t offset_in_block =
+ block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+
+ uint32_t new_block_addr;
+
+ struct ext4_block block;
+ struct ext4_block new_block;
+
+ /* Is needed to allocate indirect block on the i-node level */
+ if (current_block == 0) {
+ /* Allocate new indirect block */
+ int rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
+ if (rc != EOK)
+ return rc;
+
+ /* Update i-node */
+ ext4_inode_set_indirect_block(inode_ref->inode, level - 1,
+ new_block_addr);
+ inode_ref->dirty = true;
+
+ /* Load newly allocated block */
+ rc = ext4_block_get(fs->bdev, &new_block, new_block_addr);
+ if (rc != EOK) {
+ ext4_balloc_free_block(inode_ref, new_block_addr);
+ return rc;
+ }
+
+ /* Initialize new block */
+ memset(new_block.data, 0, block_size);
+ new_block.dirty = true;
+
+ /* Put back the allocated block */
+ rc = ext4_block_set(fs->bdev, &new_block);
+ if (rc != EOK)
+ return rc;
+
+ current_block = new_block_addr;
+ }
+
+ /*
+ * Navigate through other levels, until we find the block number
+ * or find null reference meaning we are dealing with sparse file
+ */
+ while (level > 0) {
+ int rc = ext4_block_get(fs->bdev, &block, current_block);
+ if (rc != EOK)
+ return rc;
+
+ current_block =
+ to_le32(((uint32_t *)block.data)[offset_in_block]);
+
+ if ((level > 1) && (current_block == 0)) {
+ /* Allocate new block */
+ rc =
+ ext4_balloc_alloc_block(inode_ref, &new_block_addr);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+
+ /* Load newly allocated block */
+ rc = ext4_block_get(fs->bdev, &new_block,
+ new_block_addr);
+
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+
+ /* Initialize allocated block */
+ memset(new_block.data, 0, block_size);
+ new_block.dirty = true;
+
+ rc = ext4_block_set(fs->bdev, &new_block);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+
+ /* Write block address to the parent */
+ ((uint32_t *)block.data)[offset_in_block] =
+ to_le32(new_block_addr);
+ block.dirty = true;
+ current_block = new_block_addr;
+ }
+
+ /* Will be finished, write the fblock address */
+ if (level == 1) {
+ ((uint32_t *)block.data)[offset_in_block] =
+ to_le32(fblock);
+ block.dirty = true;
+ }
+
+ rc = ext4_block_set(fs->bdev, &block);
+ if (rc != EOK)
+ return rc;
+
+ level--;
+
+ /*
+ * If we are on the last level, break here as
+ * there is no next level to visit
+ */
+ if (level == 0)
+ break;
+
+ /* Visit the next level */
+ block_offset_in_level %= fs->inode_blocks_per_level[level];
+ offset_in_block = block_offset_in_level /
+ fs->inode_blocks_per_level[level - 1];
+ }
+
+ return EOK;
}
int ext4_fs_release_inode_block(struct ext4_inode_ref *inode_ref,
- uint32_t iblock)
+ uint32_t iblock)
{
- uint32_t fblock;
-
- struct ext4_fs *fs = inode_ref->fs;
-
- /* Extents are handled otherwise = there is not support in this function */
- ext4_assert(
- !(ext4_sb_has_feature_incompatible(&fs->sb,
- EXT4_FEATURE_INCOMPAT_EXTENTS) &&
- (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))));
-
- struct ext4_inode *inode = inode_ref->inode;
-
- /* Handle simple case when we are dealing with direct reference */
- if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
- fblock = ext4_inode_get_direct_block(inode, iblock);
-
- /* Sparse file */
- if (fblock == 0)
- return EOK;
-
- ext4_inode_set_direct_block(inode, iblock, 0);
- return ext4_balloc_free_block(inode_ref, fblock);
- }
-
- /* Determine the indirection level needed to get the desired block */
- unsigned int level = 0;
- unsigned int i;
- for (i = 1; i < 4; i++) {
- if (iblock < fs->inode_block_limits[i]) {
- level = i;
- break;
- }
- }
-
- if (level == 0)
- return EIO;
-
- /* Compute offsets for the topmost level */
- uint64_t block_offset_in_level = iblock - fs->inode_block_limits[level - 1];
- uint32_t current_block = ext4_inode_get_indirect_block(inode, level - 1);
- uint32_t offset_in_block =
- block_offset_in_level / fs->inode_blocks_per_level[level - 1];
-
- /*
- * Navigate through other levels, until we find the block number
- * or find null reference meaning we are dealing with sparse file
- */
- struct ext4_block block;
-
- while (level > 0) {
-
- /* Sparse check */
- if (current_block == 0)
- return EOK;
-
- int rc = ext4_block_get(fs->bdev, &block, current_block);
- if (rc != EOK)
- return rc;
-
- current_block = to_le32(((uint32_t *)block.data)[offset_in_block]);
-
- /* Set zero if physical data block address found */
- if (level == 1) {
- ((uint32_t *)block.data)[offset_in_block] = to_le32(0);
- block.dirty = true;
- }
-
- rc = ext4_block_set(fs->bdev, &block);
- if (rc != EOK)
- return rc;
-
- level--;
-
- /*
- * If we are on the last level, break here as
- * there is no next level to visit
- */
- if (level == 0)
- break;
-
- /* Visit the next level */
- block_offset_in_level %= fs->inode_blocks_per_level[level];
- offset_in_block =
- block_offset_in_level / fs->inode_blocks_per_level[level - 1];
- }
-
- fblock = current_block;
- if (fblock == 0)
- return EOK;
-
- /* Physical block is not referenced, it can be released */
- return ext4_balloc_free_block(inode_ref, fblock);
+ uint32_t fblock;
+
+ struct ext4_fs *fs = inode_ref->fs;
+
+ /* Extents are handled otherwise = there is not support in this function
+ */
+ ext4_assert(!(
+ ext4_sb_has_feature_incompatible(&fs->sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS) &&
+ (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))));
+
+ struct ext4_inode *inode = inode_ref->inode;
+
+ /* Handle simple case when we are dealing with direct reference */
+ if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
+ fblock = ext4_inode_get_direct_block(inode, iblock);
+
+ /* Sparse file */
+ if (fblock == 0)
+ return EOK;
+
+ ext4_inode_set_direct_block(inode, iblock, 0);
+ return ext4_balloc_free_block(inode_ref, fblock);
+ }
+
+ /* Determine the indirection level needed to get the desired block */
+ unsigned int level = 0;
+ unsigned int i;
+ for (i = 1; i < 4; i++) {
+ if (iblock < fs->inode_block_limits[i]) {
+ level = i;
+ break;
+ }
+ }
+
+ if (level == 0)
+ return EIO;
+
+ /* Compute offsets for the topmost level */
+ uint64_t block_offset_in_level =
+ iblock - fs->inode_block_limits[level - 1];
+ uint32_t current_block =
+ ext4_inode_get_indirect_block(inode, level - 1);
+ uint32_t offset_in_block =
+ block_offset_in_level / fs->inode_blocks_per_level[level - 1];
+
+ /*
+ * Navigate through other levels, until we find the block number
+ * or find null reference meaning we are dealing with sparse file
+ */
+ struct ext4_block block;
+
+ while (level > 0) {
+
+ /* Sparse check */
+ if (current_block == 0)
+ return EOK;
+
+ int rc = ext4_block_get(fs->bdev, &block, current_block);
+ if (rc != EOK)
+ return rc;
+
+ current_block =
+ to_le32(((uint32_t *)block.data)[offset_in_block]);
+
+ /* Set zero if physical data block address found */
+ if (level == 1) {
+ ((uint32_t *)block.data)[offset_in_block] = to_le32(0);
+ block.dirty = true;
+ }
+
+ rc = ext4_block_set(fs->bdev, &block);
+ if (rc != EOK)
+ return rc;
+
+ level--;
+
+ /*
+ * If we are on the last level, break here as
+ * there is no next level to visit
+ */
+ if (level == 0)
+ break;
+
+ /* Visit the next level */
+ block_offset_in_level %= fs->inode_blocks_per_level[level];
+ offset_in_block = block_offset_in_level /
+ fs->inode_blocks_per_level[level - 1];
+ }
+
+ fblock = current_block;
+ if (fblock == 0)
+ return EOK;
+
+ /* Physical block is not referenced, it can be released */
+ return ext4_balloc_free_block(inode_ref, fblock);
}
int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref,
- uint32_t *fblock, uint32_t *iblock)
+ uint32_t *fblock, uint32_t *iblock)
{
#if CONFIG_EXTENT_ENABLE
- /* Handle extents separately */
- if ((ext4_sb_has_feature_incompatible(&inode_ref->fs->sb,
- EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
- (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
- return ext4_extent_append_block(inode_ref, iblock, fblock, true);
- }
+ /* Handle extents separately */
+ if ((ext4_sb_has_feature_incompatible(&inode_ref->fs->sb,
+ EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
+ (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
+ return ext4_extent_append_block(inode_ref, iblock, fblock,
+ true);
+ }
#endif
- struct ext4_sblock *sb = &inode_ref->fs->sb;
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
- /* Compute next block index and allocate data block */
- uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
- uint32_t block_size = ext4_sb_get_block_size(sb);
+ /* Compute next block index and allocate data block */
+ uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
+ uint32_t block_size = ext4_sb_get_block_size(sb);
- /* Align size i-node size */
- if ((inode_size % block_size) != 0)
- inode_size += block_size - (inode_size % block_size);
+ /* Align size i-node size */
+ if ((inode_size % block_size) != 0)
+ inode_size += block_size - (inode_size % block_size);
- /* Logical blocks are numbered from 0 */
- uint32_t new_block_idx = inode_size / block_size;
+ /* Logical blocks are numbered from 0 */
+ uint32_t new_block_idx = inode_size / block_size;
- /* Allocate new physical block */
- uint32_t phys_block;
- int rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
- if (rc != EOK)
- return rc;
+ /* Allocate new physical block */
+ uint32_t phys_block;
+ int rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+ if (rc != EOK)
+ return rc;
- /* Add physical block address to the i-node */
- rc = ext4_fs_set_inode_data_block_index(inode_ref, new_block_idx,
- phys_block);
- if (rc != EOK) {
- ext4_balloc_free_block(inode_ref, phys_block);
- return rc;
- }
+ /* Add physical block address to the i-node */
+ rc = ext4_fs_set_inode_data_block_index(inode_ref, new_block_idx,
+ phys_block);
+ if (rc != EOK) {
+ ext4_balloc_free_block(inode_ref, phys_block);
+ return rc;
+ }
- /* Update i-node */
- ext4_inode_set_size(inode_ref->inode, inode_size + block_size);
- inode_ref->dirty = true;
+ /* Update i-node */
+ ext4_inode_set_size(inode_ref->inode, inode_size + block_size);
+ inode_ref->dirty = true;
- *fblock = phys_block;
- *iblock = new_block_idx;
+ *fblock = phys_block;
+ *iblock = new_block_idx;
- return EOK;
+ return EOK;
}
void ext4_fs_inode_links_count_inc(struct ext4_inode_ref *inode_ref)
{
- uint16_t link;
-
- link = ext4_inode_get_links_count(inode_ref->inode);
- link++;
- ext4_inode_set_links_count(inode_ref->inode, link);
-
- bool is_dx = ext4_sb_has_feature_compatible(
- &inode_ref->fs->sb, EXT4_FEATURE_COMPAT_DIR_INDEX) &&
- ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_INDEX);
-
- if (is_dx && link > 1) {
- if (link >= EXT4_LINK_MAX || link == 2) {
- ext4_inode_set_links_count(inode_ref->inode, 1);
-
- uint32_t v = ext4_get32(&inode_ref->fs->sb, features_read_only);
- v |= EXT4_FEATURE_RO_COMPAT_DIR_NLINK;
- ext4_set32(&inode_ref->fs->sb, features_read_only, v);
- }
- }
+ uint16_t link;
+
+ link = ext4_inode_get_links_count(inode_ref->inode);
+ link++;
+ ext4_inode_set_links_count(inode_ref->inode, link);
+
+ bool is_dx =
+ ext4_sb_has_feature_compatible(&inode_ref->fs->sb,
+ EXT4_FEATURE_COMPAT_DIR_INDEX) &&
+ ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_INDEX);
+
+ if (is_dx && link > 1) {
+ if (link >= EXT4_LINK_MAX || link == 2) {
+ ext4_inode_set_links_count(inode_ref->inode, 1);
+
+ uint32_t v =
+ ext4_get32(&inode_ref->fs->sb, features_read_only);
+ v |= EXT4_FEATURE_RO_COMPAT_DIR_NLINK;
+ ext4_set32(&inode_ref->fs->sb, features_read_only, v);
+ }
+ }
}
void ext4_fs_inode_links_count_dec(struct ext4_inode_ref *inode_ref)
{
- uint16_t links = ext4_inode_get_links_count(inode_ref->inode);
- if (!ext4_inode_is_type(&inode_ref->fs->sb, inode_ref->inode,
- EXT4_INODE_MODE_DIRECTORY)) {
- if (links > 0)
- ext4_inode_set_links_count(inode_ref->inode, links - 1);
- return;
- }
-
- if (links > 2)
- ext4_inode_set_links_count(inode_ref->inode, links - 1);
+ uint16_t links = ext4_inode_get_links_count(inode_ref->inode);
+ if (!ext4_inode_is_type(&inode_ref->fs->sb, inode_ref->inode,
+ EXT4_INODE_MODE_DIRECTORY)) {
+ if (links > 0)
+ ext4_inode_set_links_count(inode_ref->inode, links - 1);
+ return;
+ }
+
+ if (links > 2)
+ ext4_inode_set_links_count(inode_ref->inode, links - 1);
}
/**
* @return Relative number of block
*/
static inline uint32_t ext4_fs_baddr2_index_in_group(struct ext4_sblock *s,
- uint32_t baddr)
+ uint32_t baddr)
{
- ext4_assert(baddr);
- if (ext4_get32(s, first_data_block))
- baddr--;
+ ext4_assert(baddr);
+ if (ext4_get32(s, first_data_block))
+ baddr--;
- return baddr % ext4_get32(s, blocks_per_group);
+ return baddr % ext4_get32(s, blocks_per_group);
}
/**@brief Convert relative block address in group to absolute address.
* @return Absolute block address
*/
static inline uint32_t ext4_fs_index_in_group2_baddr(struct ext4_sblock *s,
- uint32_t index,
- uint32_t bgid)
+ uint32_t index,
+ uint32_t bgid)
{
- if (ext4_get32(s, first_data_block))
- index++;
+ if (ext4_get32(s, first_data_block))
+ index++;
- return ext4_get32(s, blocks_per_group) * bgid + index;
+ return ext4_get32(s, blocks_per_group) * bgid + index;
}
/**@brief TODO: */
static inline uint64_t ext4_fs_first_bg_block_no(struct ext4_sblock *s,
- uint32_t bgid)
+ uint32_t bgid)
{
- return (uint64_t)bgid * ext4_get32(s, blocks_per_group) +
- ext4_get32(s, first_data_block);
+ return (uint64_t)bgid * ext4_get32(s, blocks_per_group) +
+ ext4_get32(s, first_data_block);
}
/**@brief Initialize filesystem and read all needed data.
* @return Error code
*/
int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid,
- struct ext4_block_group_ref *ref);
+ struct ext4_block_group_ref *ref);
/**@brief Put reference to block group.
* @param ref Pointer for reference to be put back
* @return Error code
*/
int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index,
- struct ext4_inode_ref *ref);
+ struct ext4_inode_ref *ref);
/**@brief Put reference to i-node.
* @param ref Pointer for reference to be put back
* @return Error code
*/
int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref,
- bool is_directory);
+ bool is_directory);
/**@brief Release i-node and mark it as free.
* @param inode_ref I-node to be released
* @return Error code
*/
int ext4_fs_get_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock);
+ uint64_t iblock, uint32_t *fblock);
/**@brief Set physical block address for the block logical address into the
* i-node.
* @return Error code
*/
int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t fblock);
+ uint64_t iblock, uint32_t fblock);
/**@brief Release data block from i-node
* @param inode_ref I-node to release block from
* @return Error code
*/
int ext4_fs_release_inode_block(struct ext4_inode_ref *inode_ref,
- uint32_t iblock);
+ uint32_t iblock);
/**@brief Append following logical block to the i-node.
* @param inode_ref I-node to append block to
* @return Error code
*/
int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref,
- uint32_t *fblock, uint32_t *iblock);
+ uint32_t *fblock, uint32_t *iblock);
/**@brief Increment inode link count.
* @param inode none handle
* Rotation is separated from addition to prevent recomputation.\r
*/\r
#define FF(a, b, c, d, x, s) \\r
- { \\r
- (a) += F((b), (c), (d)) + (x); \\r
- (a) = ROTATE_LEFT((a), (s)); \\r
- \\r
+ { \\r
+ (a) += F((b), (c), (d)) + (x); \\r
+ (a) = ROTATE_LEFT((a), (s)); \\r
+ \\r
}\r
\r
#define GG(a, b, c, d, x, s) \\r
- { \\r
- (a) += G((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \\r
- (a) = ROTATE_LEFT((a), (s)); \\r
- \\r
+ { \\r
+ (a) += G((b), (c), (d)) + (x) + (uint32_t)0x5A827999; \\r
+ (a) = ROTATE_LEFT((a), (s)); \\r
+ \\r
}\r
\r
#define HH(a, b, c, d, x, s) \\r
- { \\r
- (a) += H((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \\r
- (a) = ROTATE_LEFT((a), (s)); \\r
- \\r
+ { \\r
+ (a) += H((b), (c), (d)) + (x) + (uint32_t)0x6ED9EBA1; \\r
+ (a) = ROTATE_LEFT((a), (s)); \\r
+ \\r
}\r
\r
/*\r
*/\r
static void ext2_half_md4(uint32_t hash[4], uint32_t data[8])\r
{\r
- uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3];\r
-\r
- /* Round 1 */\r
- FF(a, b, c, d, data[0], 3);\r
- FF(d, a, b, c, data[1], 7);\r
- FF(c, d, a, b, data[2], 11);\r
- FF(b, c, d, a, data[3], 19);\r
- FF(a, b, c, d, data[4], 3);\r
- FF(d, a, b, c, data[5], 7);\r
- FF(c, d, a, b, data[6], 11);\r
- FF(b, c, d, a, data[7], 19);\r
-\r
- /* Round 2 */\r
- GG(a, b, c, d, data[1], 3);\r
- GG(d, a, b, c, data[3], 5);\r
- GG(c, d, a, b, data[5], 9);\r
- GG(b, c, d, a, data[7], 13);\r
- GG(a, b, c, d, data[0], 3);\r
- GG(d, a, b, c, data[2], 5);\r
- GG(c, d, a, b, data[4], 9);\r
- GG(b, c, d, a, data[6], 13);\r
-\r
- /* Round 3 */\r
- HH(a, b, c, d, data[3], 3);\r
- HH(d, a, b, c, data[7], 9);\r
- HH(c, d, a, b, data[2], 11);\r
- HH(b, c, d, a, data[6], 15);\r
- HH(a, b, c, d, data[1], 3);\r
- HH(d, a, b, c, data[5], 9);\r
- HH(c, d, a, b, data[0], 11);\r
- HH(b, c, d, a, data[4], 15);\r
-\r
- hash[0] += a;\r
- hash[1] += b;\r
- hash[2] += c;\r
- hash[3] += d;\r
+ uint32_t a = hash[0], b = hash[1], c = hash[2], d = hash[3];\r
+\r
+ /* Round 1 */\r
+ FF(a, b, c, d, data[0], 3);\r
+ FF(d, a, b, c, data[1], 7);\r
+ FF(c, d, a, b, data[2], 11);\r
+ FF(b, c, d, a, data[3], 19);\r
+ FF(a, b, c, d, data[4], 3);\r
+ FF(d, a, b, c, data[5], 7);\r
+ FF(c, d, a, b, data[6], 11);\r
+ FF(b, c, d, a, data[7], 19);\r
+\r
+ /* Round 2 */\r
+ GG(a, b, c, d, data[1], 3);\r
+ GG(d, a, b, c, data[3], 5);\r
+ GG(c, d, a, b, data[5], 9);\r
+ GG(b, c, d, a, data[7], 13);\r
+ GG(a, b, c, d, data[0], 3);\r
+ GG(d, a, b, c, data[2], 5);\r
+ GG(c, d, a, b, data[4], 9);\r
+ GG(b, c, d, a, data[6], 13);\r
+\r
+ /* Round 3 */\r
+ HH(a, b, c, d, data[3], 3);\r
+ HH(d, a, b, c, data[7], 9);\r
+ HH(c, d, a, b, data[2], 11);\r
+ HH(b, c, d, a, data[6], 15);\r
+ HH(a, b, c, d, data[1], 3);\r
+ HH(d, a, b, c, data[5], 9);\r
+ HH(c, d, a, b, data[0], 11);\r
+ HH(b, c, d, a, data[4], 15);\r
+\r
+ hash[0] += a;\r
+ hash[1] += b;\r
+ hash[2] += c;\r
+ hash[3] += d;\r
}\r
\r
/*\r
*/\r
static void ext2_tea(uint32_t hash[4], uint32_t data[8])\r
{\r
- uint32_t tea_delta = 0x9E3779B9;\r
- uint32_t sum;\r
- uint32_t x = hash[0], y = hash[1];\r
- int n = 16;\r
- int i = 1;\r
-\r
- while (n-- > 0) {\r
- sum = i * tea_delta;\r
- x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]);\r
- y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]);\r
- i++;\r
- }\r
-\r
- hash[0] += x;\r
- hash[1] += y;\r
+ uint32_t tea_delta = 0x9E3779B9;\r
+ uint32_t sum;\r
+ uint32_t x = hash[0], y = hash[1];\r
+ int n = 16;\r
+ int i = 1;\r
+\r
+ while (n-- > 0) {\r
+ sum = i * tea_delta;\r
+ x += ((y << 4) + data[0]) ^ (y + sum) ^ ((y >> 5) + data[1]);\r
+ y += ((x << 4) + data[2]) ^ (x + sum) ^ ((x >> 5) + data[3]);\r
+ i++;\r
+ }\r
+\r
+ hash[0] += x;\r
+ hash[1] += y;\r
}\r
\r
static uint32_t ext2_legacy_hash(const char *name, int len, int unsigned_char)\r
{\r
- uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9;\r
- uint32_t multi = 0x6D22F5;\r
- const unsigned char *uname = (const unsigned char *)name;\r
- const signed char *sname = (const signed char *)name;\r
- int val, i;\r
-\r
- for (i = 0; i < len; i++) {\r
- if (unsigned_char)\r
- val = (unsigned int)*uname++;\r
- else\r
- val = (int)*sname++;\r
-\r
- h0 = h2 + (h1 ^ (val * multi));\r
- if (h0 & 0x80000000)\r
- h0 -= 0x7FFFFFFF;\r
- h2 = h1;\r
- h1 = h0;\r
- }\r
-\r
- return (h1 << 1);\r
+ uint32_t h0, h1 = 0x12A3FE2D, h2 = 0x37ABE8F9;\r
+ uint32_t multi = 0x6D22F5;\r
+ const unsigned char *uname = (const unsigned char *)name;\r
+ const signed char *sname = (const signed char *)name;\r
+ int val, i;\r
+\r
+ for (i = 0; i < len; i++) {\r
+ if (unsigned_char)\r
+ val = (unsigned int)*uname++;\r
+ else\r
+ val = (int)*sname++;\r
+\r
+ h0 = h2 + (h1 ^ (val * multi));\r
+ if (h0 & 0x80000000)\r
+ h0 -= 0x7FFFFFFF;\r
+ h2 = h1;\r
+ h1 = h0;\r
+ }\r
+\r
+ return (h1 << 1);\r
}\r
\r
static void ext2_prep_hashbuf(const char *src, uint32_t slen, uint32_t *dst,\r
- int dlen, int unsigned_char)\r
+ int dlen, int unsigned_char)\r
{\r
- uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24);\r
- uint32_t buf_val;\r
- int len, i;\r
- int buf_byte;\r
- const unsigned char *ubuf = (const unsigned char *)src;\r
- const signed char *sbuf = (const signed char *)src;\r
-\r
- if (slen > (uint32_t)dlen)\r
- len = dlen;\r
- else\r
- len = slen;\r
-\r
- buf_val = padding;\r
-\r
- for (i = 0; i < len; i++) {\r
- if (unsigned_char)\r
- buf_byte = (unsigned int)ubuf[i];\r
- else\r
- buf_byte = (int)sbuf[i];\r
-\r
- if ((i % 4) == 0)\r
- buf_val = padding;\r
-\r
- buf_val <<= 8;\r
- buf_val += buf_byte;\r
-\r
- if ((i % 4) == 3) {\r
- *dst++ = buf_val;\r
- dlen -= sizeof(uint32_t);\r
- buf_val = padding;\r
- }\r
- }\r
-\r
- dlen -= sizeof(uint32_t);\r
- if (dlen >= 0)\r
- *dst++ = buf_val;\r
-\r
- dlen -= sizeof(uint32_t);\r
- while (dlen >= 0) {\r
- *dst++ = padding;\r
- dlen -= sizeof(uint32_t);\r
- }\r
+ uint32_t padding = slen | (slen << 8) | (slen << 16) | (slen << 24);\r
+ uint32_t buf_val;\r
+ int len, i;\r
+ int buf_byte;\r
+ const unsigned char *ubuf = (const unsigned char *)src;\r
+ const signed char *sbuf = (const signed char *)src;\r
+\r
+ if (slen > (uint32_t)dlen)\r
+ len = dlen;\r
+ else\r
+ len = slen;\r
+\r
+ buf_val = padding;\r
+\r
+ for (i = 0; i < len; i++) {\r
+ if (unsigned_char)\r
+ buf_byte = (unsigned int)ubuf[i];\r
+ else\r
+ buf_byte = (int)sbuf[i];\r
+\r
+ if ((i % 4) == 0)\r
+ buf_val = padding;\r
+\r
+ buf_val <<= 8;\r
+ buf_val += buf_byte;\r
+\r
+ if ((i % 4) == 3) {\r
+ *dst++ = buf_val;\r
+ dlen -= sizeof(uint32_t);\r
+ buf_val = padding;\r
+ }\r
+ }\r
+\r
+ dlen -= sizeof(uint32_t);\r
+ if (dlen >= 0)\r
+ *dst++ = buf_val;\r
+\r
+ dlen -= sizeof(uint32_t);\r
+ while (dlen >= 0) {\r
+ *dst++ = padding;\r
+ dlen -= sizeof(uint32_t);\r
+ }\r
}\r
\r
int ext2_htree_hash(const char *name, int len, const uint32_t *hash_seed,\r
- int hash_version, uint32_t *hash_major,\r
- uint32_t *hash_minor)\r
+ int hash_version, uint32_t *hash_major,\r
+ uint32_t *hash_minor)\r
{\r
- uint32_t hash[4];\r
- uint32_t data[8];\r
- uint32_t major = 0, minor = 0;\r
- int unsigned_char = 0;\r
-\r
- if (!name || !hash_major)\r
- return (-1);\r
-\r
- if (len < 1 || len > 255)\r
- goto error;\r
-\r
- hash[0] = 0x67452301;\r
- hash[1] = 0xEFCDAB89;\r
- hash[2] = 0x98BADCFE;\r
- hash[3] = 0x10325476;\r
-\r
- if (hash_seed)\r
- memcpy(hash, hash_seed, sizeof(hash));\r
-\r
- switch (hash_version) {\r
- case EXT2_HTREE_TEA_UNSIGNED:\r
- unsigned_char = 1;\r
- case EXT2_HTREE_TEA:\r
- while (len > 0) {\r
- ext2_prep_hashbuf(name, len, data, 16, unsigned_char);\r
- ext2_tea(hash, data);\r
- len -= 16;\r
- name += 16;\r
- }\r
- major = hash[0];\r
- minor = hash[1];\r
- break;\r
- case EXT2_HTREE_LEGACY_UNSIGNED:\r
- unsigned_char = 1;\r
- case EXT2_HTREE_LEGACY:\r
- major = ext2_legacy_hash(name, len, unsigned_char);\r
- break;\r
- case EXT2_HTREE_HALF_MD4_UNSIGNED:\r
- unsigned_char = 1;\r
- case EXT2_HTREE_HALF_MD4:\r
- while (len > 0) {\r
- ext2_prep_hashbuf(name, len, data, 32, unsigned_char);\r
- ext2_half_md4(hash, data);\r
- len -= 32;\r
- name += 32;\r
- }\r
- major = hash[1];\r
- minor = hash[2];\r
- break;\r
- default:\r
- goto error;\r
- }\r
-\r
- major &= ~1;\r
- if (major == (EXT2_HTREE_EOF << 1))\r
- major = (EXT2_HTREE_EOF - 1) << 1;\r
- *hash_major = major;\r
- if (hash_minor)\r
- *hash_minor = minor;\r
-\r
- return EOK;\r
+ uint32_t hash[4];\r
+ uint32_t data[8];\r
+ uint32_t major = 0, minor = 0;\r
+ int unsigned_char = 0;\r
+\r
+ if (!name || !hash_major)\r
+ return (-1);\r
+\r
+ if (len < 1 || len > 255)\r
+ goto error;\r
+\r
+ hash[0] = 0x67452301;\r
+ hash[1] = 0xEFCDAB89;\r
+ hash[2] = 0x98BADCFE;\r
+ hash[3] = 0x10325476;\r
+\r
+ if (hash_seed)\r
+ memcpy(hash, hash_seed, sizeof(hash));\r
+\r
+ switch (hash_version) {\r
+ case EXT2_HTREE_TEA_UNSIGNED:\r
+ unsigned_char = 1;\r
+ case EXT2_HTREE_TEA:\r
+ while (len > 0) {\r
+ ext2_prep_hashbuf(name, len, data, 16, unsigned_char);\r
+ ext2_tea(hash, data);\r
+ len -= 16;\r
+ name += 16;\r
+ }\r
+ major = hash[0];\r
+ minor = hash[1];\r
+ break;\r
+ case EXT2_HTREE_LEGACY_UNSIGNED:\r
+ unsigned_char = 1;\r
+ case EXT2_HTREE_LEGACY:\r
+ major = ext2_legacy_hash(name, len, unsigned_char);\r
+ break;\r
+ case EXT2_HTREE_HALF_MD4_UNSIGNED:\r
+ unsigned_char = 1;\r
+ case EXT2_HTREE_HALF_MD4:\r
+ while (len > 0) {\r
+ ext2_prep_hashbuf(name, len, data, 32, unsigned_char);\r
+ ext2_half_md4(hash, data);\r
+ len -= 32;\r
+ name += 32;\r
+ }\r
+ major = hash[1];\r
+ minor = hash[2];\r
+ break;\r
+ default:\r
+ goto error;\r
+ }\r
+\r
+ major &= ~1;\r
+ if (major == (EXT2_HTREE_EOF << 1))\r
+ major = (EXT2_HTREE_EOF - 1) << 1;\r
+ *hash_major = major;\r
+ if (hash_minor)\r
+ *hash_minor = minor;\r
+\r
+ return EOK;\r
\r
error:\r
- *hash_major = 0;\r
- if (hash_minor)\r
- *hash_minor = 0;\r
- return ENOTSUP;\r
+ *hash_major = 0;\r
+ if (hash_minor)\r
+ *hash_minor = 0;\r
+ return ENOTSUP;\r
}\r
\r
/**\r
* @param hash_major output value\r
* @return standard error code*/\r
int ext2_htree_hash(const char *name, int len, const uint32_t *hash_seed,\r
- int hash_version, uint32_t *hash_major,\r
- uint32_t *hash_minor);\r
+ int hash_version, uint32_t *hash_major,\r
+ uint32_t *hash_minor);\r
\r
#endif /* EXT4_HASH_H_ */\r
\r
* @return Index of the i-node in the block group\r
*/\r
static uint32_t ext4_ialloc_inode2index_in_group(struct ext4_sblock *sb,\r
- uint32_t inode)\r
+ uint32_t inode)\r
{\r
- uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);\r
- return (inode - 1) % inodes_per_group;\r
+ uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);\r
+ return (inode - 1) % inodes_per_group;\r
}\r
\r
/**@brief Convert relative index of i-node to absolute i-node number.\r
*\r
*/\r
static uint32_t ext4_ialloc_index_in_group2inode(struct ext4_sblock *sb,\r
- uint32_t index, uint32_t bgid)\r
+ uint32_t index, uint32_t bgid)\r
{\r
- uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);\r
- return bgid * inodes_per_group + (index + 1);\r
+ uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);\r
+ return bgid * inodes_per_group + (index + 1);\r
}\r
\r
/**@brief Compute block group number from the i-node number.\r
* @return Block group number computed from i-node number\r
*/\r
static uint32_t ext4_ialloc_get_bgid_of_inode(struct ext4_sblock *sb,\r
- uint32_t inode)\r
+ uint32_t inode)\r
{\r
- uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);\r
- return (inode - 1) / inodes_per_group;\r
+ uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);\r
+ return (inode - 1) / inodes_per_group;\r
}\r
\r
int ext4_ialloc_free_inode(struct ext4_fs *fs, uint32_t index, bool is_dir)\r
{\r
- struct ext4_sblock *sb = &fs->sb;\r
-\r
- /* Compute index of block group and load it */\r
- uint32_t block_group = ext4_ialloc_get_bgid_of_inode(sb, index);\r
-\r
- struct ext4_block_group_ref bg_ref;\r
- int rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Load i-node bitmap */\r
- uint32_t bitmap_block_addr =\r
- ext4_bg_get_inode_bitmap(bg_ref.block_group, sb);\r
-\r
- struct ext4_block bitmap_block;\r
- rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Free i-node in the bitmap */\r
- uint32_t index_in_group = ext4_ialloc_inode2index_in_group(sb, index);\r
- ext4_bmap_bit_clr(bitmap_block.data, index_in_group);\r
- bitmap_block.dirty = true;\r
-\r
- /* Put back the block with bitmap */\r
- rc = ext4_block_set(fs->bdev, &bitmap_block);\r
- if (rc != EOK) {\r
- /* Error in saving bitmap */\r
- ext4_fs_put_block_group_ref(&bg_ref);\r
- return rc;\r
- }\r
-\r
- /* If released i-node is a directory, decrement used directories count */\r
- if (is_dir) {\r
- uint32_t bg_used_dirs =\r
- ext4_bg_get_used_dirs_count(bg_ref.block_group, sb);\r
- bg_used_dirs--;\r
- ext4_bg_set_used_dirs_count(bg_ref.block_group, sb, bg_used_dirs);\r
- }\r
-\r
- /* Update block group free inodes count */\r
- uint32_t free_inodes =\r
- ext4_bg_get_free_inodes_count(bg_ref.block_group, sb);\r
- free_inodes++;\r
- ext4_bg_set_free_inodes_count(bg_ref.block_group, sb, free_inodes);\r
-\r
- bg_ref.dirty = true;\r
-\r
- /* Put back the modified block group */\r
- rc = ext4_fs_put_block_group_ref(&bg_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Update superblock free inodes count */\r
- ext4_set32(sb, free_inodes_count, ext4_get32(sb, free_inodes_count) + 1);\r
-\r
- return EOK;\r
+ struct ext4_sblock *sb = &fs->sb;\r
+\r
+ /* Compute index of block group and load it */\r
+ uint32_t block_group = ext4_ialloc_get_bgid_of_inode(sb, index);\r
+\r
+ struct ext4_block_group_ref bg_ref;\r
+ int rc = ext4_fs_get_block_group_ref(fs, block_group, &bg_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Load i-node bitmap */\r
+ uint32_t bitmap_block_addr =\r
+ ext4_bg_get_inode_bitmap(bg_ref.block_group, sb);\r
+\r
+ struct ext4_block bitmap_block;\r
+ rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Free i-node in the bitmap */\r
+ uint32_t index_in_group = ext4_ialloc_inode2index_in_group(sb, index);\r
+ ext4_bmap_bit_clr(bitmap_block.data, index_in_group);\r
+ bitmap_block.dirty = true;\r
+\r
+ /* Put back the block with bitmap */\r
+ rc = ext4_block_set(fs->bdev, &bitmap_block);\r
+ if (rc != EOK) {\r
+ /* Error in saving bitmap */\r
+ ext4_fs_put_block_group_ref(&bg_ref);\r
+ return rc;\r
+ }\r
+\r
+ /* If released i-node is a directory, decrement used directories count\r
+ */\r
+ if (is_dir) {\r
+ uint32_t bg_used_dirs =\r
+ ext4_bg_get_used_dirs_count(bg_ref.block_group, sb);\r
+ bg_used_dirs--;\r
+ ext4_bg_set_used_dirs_count(bg_ref.block_group, sb,\r
+ bg_used_dirs);\r
+ }\r
+\r
+ /* Update block group free inodes count */\r
+ uint32_t free_inodes =\r
+ ext4_bg_get_free_inodes_count(bg_ref.block_group, sb);\r
+ free_inodes++;\r
+ ext4_bg_set_free_inodes_count(bg_ref.block_group, sb, free_inodes);\r
+\r
+ bg_ref.dirty = true;\r
+\r
+ /* Put back the modified block group */\r
+ rc = ext4_fs_put_block_group_ref(&bg_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Update superblock free inodes count */\r
+ ext4_set32(sb, free_inodes_count,\r
+ ext4_get32(sb, free_inodes_count) + 1);\r
+\r
+ return EOK;\r
}\r
\r
int ext4_ialloc_alloc_inode(struct ext4_fs *fs, uint32_t *index, bool is_dir)\r
{\r
- struct ext4_sblock *sb = &fs->sb;\r
-\r
- uint32_t bgid = fs->last_inode_bg_id;\r
- uint32_t bg_count = ext4_block_group_cnt(sb);\r
- uint32_t sb_free_inodes = ext4_get32(sb, free_inodes_count);\r
- bool rewind = false;\r
-\r
- /* Try to find free i-node in all block groups */\r
- while (bgid <= bg_count) {\r
-\r
- if (bgid == bg_count) {\r
- if (rewind)\r
- break;\r
- bg_count = fs->last_inode_bg_id;\r
- bgid = 0;\r
- rewind = true;\r
- continue;\r
- }\r
-\r
- /* Load block group to check */\r
- struct ext4_block_group_ref bg_ref;\r
- int rc = ext4_fs_get_block_group_ref(fs, bgid, &bg_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- struct ext4_bgroup *bg = bg_ref.block_group;\r
-\r
- /* Read necessary values for algorithm */\r
- uint32_t free_inodes = ext4_bg_get_free_inodes_count(bg, sb);\r
- uint32_t used_dirs = ext4_bg_get_used_dirs_count(bg, sb);\r
-\r
- /* Check if this block group is good candidate for allocation */\r
- if (free_inodes > 0) {\r
- /* Load block with bitmap */\r
- uint32_t bitmap_block_addr =\r
- ext4_bg_get_inode_bitmap(bg_ref.block_group, sb);\r
-\r
- struct ext4_block bitmap_block;\r
- rc = ext4_block_get(fs->bdev, &bitmap_block, bitmap_block_addr);\r
- if (rc != EOK) {\r
- ext4_fs_put_block_group_ref(&bg_ref);\r
- return rc;\r
- }\r
-\r
- /* Try to allocate i-node in the bitmap */\r
- uint32_t inodes_in_group = ext4_inodes_in_group_cnt(sb, bgid);\r
- uint32_t index_in_group;\r
-\r
- rc = ext4_bmap_bit_find_clr(bitmap_block.data, 0, inodes_in_group,\r
- &index_in_group);\r
- /* Block group has not any free i-node */\r
- if (rc == ENOSPC) {\r
- rc = ext4_block_set(fs->bdev, &bitmap_block);\r
- if (rc != EOK) {\r
- ext4_fs_put_block_group_ref(&bg_ref);\r
- return rc;\r
- }\r
-\r
- rc = ext4_fs_put_block_group_ref(&bg_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- continue;\r
- }\r
-\r
- ext4_bmap_bit_set(bitmap_block.data, index_in_group);\r
-\r
- /* Free i-node found, save the bitmap */\r
- bitmap_block.dirty = true;\r
-\r
- ext4_block_set(fs->bdev, &bitmap_block);\r
- if (rc != EOK) {\r
- ext4_fs_put_block_group_ref(&bg_ref);\r
- return rc;\r
- }\r
-\r
- /* Modify filesystem counters */\r
- free_inodes--;\r
- ext4_bg_set_free_inodes_count(bg, sb, free_inodes);\r
-\r
- /* Increment used directories counter */\r
- if (is_dir) {\r
- used_dirs++;\r
- ext4_bg_set_used_dirs_count(bg, sb, used_dirs);\r
- }\r
-\r
- /* Decrease unused inodes count */\r
- if (ext4_bg_has_flag(bg, EXT4_BLOCK_GROUP_ITABLE_ZEROED)) {\r
- uint32_t unused = ext4_bg_get_itable_unused(bg, sb);\r
-\r
- uint32_t inodes_in_group = ext4_inodes_in_group_cnt(sb, bgid);\r
-\r
- uint32_t free = inodes_in_group - unused;\r
-\r
- if (index_in_group >= free) {\r
- unused = inodes_in_group - (index_in_group + 1);\r
- ext4_bg_set_itable_unused(bg, sb, unused);\r
- }\r
- }\r
-\r
- /* Save modified block group */\r
- bg_ref.dirty = true;\r
-\r
- rc = ext4_fs_put_block_group_ref(&bg_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- /* Update superblock */\r
- sb_free_inodes--;\r
- ext4_set32(sb, free_inodes_count, sb_free_inodes);\r
-\r
- /* Compute the absolute i-nodex number */\r
- *index = ext4_ialloc_index_in_group2inode(sb, index_in_group, bgid);\r
-\r
- fs->last_inode_bg_id = bgid;\r
-\r
- return EOK;\r
- }\r
-\r
- /* Block group not modified, put it and jump to the next block group */\r
- ext4_fs_put_block_group_ref(&bg_ref);\r
- if (rc != EOK)\r
- return rc;\r
-\r
- ++bgid;\r
- }\r
-\r
- return ENOSPC;\r
+ struct ext4_sblock *sb = &fs->sb;\r
+\r
+ uint32_t bgid = fs->last_inode_bg_id;\r
+ uint32_t bg_count = ext4_block_group_cnt(sb);\r
+ uint32_t sb_free_inodes = ext4_get32(sb, free_inodes_count);\r
+ bool rewind = false;\r
+\r
+ /* Try to find free i-node in all block groups */\r
+ while (bgid <= bg_count) {\r
+\r
+ if (bgid == bg_count) {\r
+ if (rewind)\r
+ break;\r
+ bg_count = fs->last_inode_bg_id;\r
+ bgid = 0;\r
+ rewind = true;\r
+ continue;\r
+ }\r
+\r
+ /* Load block group to check */\r
+ struct ext4_block_group_ref bg_ref;\r
+ int rc = ext4_fs_get_block_group_ref(fs, bgid, &bg_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ struct ext4_bgroup *bg = bg_ref.block_group;\r
+\r
+ /* Read necessary values for algorithm */\r
+ uint32_t free_inodes = ext4_bg_get_free_inodes_count(bg, sb);\r
+ uint32_t used_dirs = ext4_bg_get_used_dirs_count(bg, sb);\r
+\r
+ /* Check if this block group is good candidate for allocation */\r
+ if (free_inodes > 0) {\r
+ /* Load block with bitmap */\r
+ uint32_t bitmap_block_addr =\r
+ ext4_bg_get_inode_bitmap(bg_ref.block_group, sb);\r
+\r
+ struct ext4_block bitmap_block;\r
+ rc = ext4_block_get(fs->bdev, &bitmap_block,\r
+ bitmap_block_addr);\r
+ if (rc != EOK) {\r
+ ext4_fs_put_block_group_ref(&bg_ref);\r
+ return rc;\r
+ }\r
+\r
+ /* Try to allocate i-node in the bitmap */\r
+ uint32_t inodes_in_group =\r
+ ext4_inodes_in_group_cnt(sb, bgid);\r
+ uint32_t index_in_group;\r
+\r
+ rc = ext4_bmap_bit_find_clr(bitmap_block.data, 0,\r
+ inodes_in_group,\r
+ &index_in_group);\r
+ /* Block group has not any free i-node */\r
+ if (rc == ENOSPC) {\r
+ rc = ext4_block_set(fs->bdev, &bitmap_block);\r
+ if (rc != EOK) {\r
+ ext4_fs_put_block_group_ref(&bg_ref);\r
+ return rc;\r
+ }\r
+\r
+ rc = ext4_fs_put_block_group_ref(&bg_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ continue;\r
+ }\r
+\r
+ ext4_bmap_bit_set(bitmap_block.data, index_in_group);\r
+\r
+ /* Free i-node found, save the bitmap */\r
+ bitmap_block.dirty = true;\r
+\r
+ ext4_block_set(fs->bdev, &bitmap_block);\r
+ if (rc != EOK) {\r
+ ext4_fs_put_block_group_ref(&bg_ref);\r
+ return rc;\r
+ }\r
+\r
+ /* Modify filesystem counters */\r
+ free_inodes--;\r
+ ext4_bg_set_free_inodes_count(bg, sb, free_inodes);\r
+\r
+ /* Increment used directories counter */\r
+ if (is_dir) {\r
+ used_dirs++;\r
+ ext4_bg_set_used_dirs_count(bg, sb, used_dirs);\r
+ }\r
+\r
+ /* Decrease unused inodes count */\r
+ if (ext4_bg_has_flag(bg,\r
+ EXT4_BLOCK_GROUP_ITABLE_ZEROED)) {\r
+ uint32_t unused =\r
+ ext4_bg_get_itable_unused(bg, sb);\r
+\r
+ uint32_t inodes_in_group =\r
+ ext4_inodes_in_group_cnt(sb, bgid);\r
+\r
+ uint32_t free = inodes_in_group - unused;\r
+\r
+ if (index_in_group >= free) {\r
+ unused = inodes_in_group -\r
+ (index_in_group + 1);\r
+ ext4_bg_set_itable_unused(bg, sb,\r
+ unused);\r
+ }\r
+ }\r
+\r
+ /* Save modified block group */\r
+ bg_ref.dirty = true;\r
+\r
+ rc = ext4_fs_put_block_group_ref(&bg_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ /* Update superblock */\r
+ sb_free_inodes--;\r
+ ext4_set32(sb, free_inodes_count, sb_free_inodes);\r
+\r
+ /* Compute the absolute i-nodex number */\r
+ *index = ext4_ialloc_index_in_group2inode(\r
+ sb, index_in_group, bgid);\r
+\r
+ fs->last_inode_bg_id = bgid;\r
+\r
+ return EOK;\r
+ }\r
+\r
+ /* Block group not modified, put it and jump to the next block\r
+ * group */\r
+ ext4_fs_put_block_group_ref(&bg_ref);\r
+ if (rc != EOK)\r
+ return rc;\r
+\r
+ ++bgid;\r
+ }\r
+\r
+ return ENOSPC;\r
}\r
\r
/**\r
*/\r
static uint32_t ext4_inode_block_bits_count(uint32_t block_size)\r
{\r
- uint32_t bits = 8;\r
- uint32_t size = block_size;\r
+ uint32_t bits = 8;\r
+ uint32_t size = block_size;\r
\r
- do {\r
- bits++;\r
- size = size >> 1;\r
- } while (size > 256);\r
+ do {\r
+ bits++;\r
+ size = size >> 1;\r
+ } while (size > 256);\r
\r
- return bits;\r
+ return bits;\r
}\r
\r
uint32_t ext4_inode_get_mode(struct ext4_sblock *sb, struct ext4_inode *inode)\r
{\r
- uint32_t v = to_le16(inode->mode);\r
+ uint32_t v = to_le16(inode->mode);\r
\r
- if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_HURD) {\r
- v |= ((uint32_t)to_le16(inode->osd2.hurd2.mode_high)) << 16;\r
- }\r
+ if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_HURD) {\r
+ v |= ((uint32_t)to_le16(inode->osd2.hurd2.mode_high)) << 16;\r
+ }\r
\r
- return v;\r
+ return v;\r
}\r
\r
void ext4_inode_set_mode(struct ext4_sblock *sb, struct ext4_inode *inode,\r
- uint32_t mode)\r
+ uint32_t mode)\r
{\r
- inode->mode = to_le16((mode << 16) >> 16);\r
+ inode->mode = to_le16((mode << 16) >> 16);\r
\r
- if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_HURD)\r
- inode->osd2.hurd2.mode_high = to_le16(mode >> 16);\r
+ if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_HURD)\r
+ inode->osd2.hurd2.mode_high = to_le16(mode >> 16);\r
}\r
\r
uint32_t ext4_inode_get_uid(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->uid);\r
+ return to_le32(inode->uid);\r
}\r
\r
void ext4_inode_set_uid(struct ext4_inode *inode, uint32_t uid)\r
{\r
- inode->uid = to_le32(uid);\r
+ inode->uid = to_le32(uid);\r
}\r
\r
uint64_t ext4_inode_get_size(struct ext4_sblock *sb, struct ext4_inode *inode)\r
{\r
- uint64_t v = to_le32(inode->size_lo);\r
+ uint64_t v = to_le32(inode->size_lo);\r
\r
- if ((ext4_get32(sb, rev_level) > 0) &&\r
- (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))\r
- v |= ((uint64_t)to_le32(inode->size_hi)) << 32;\r
+ if ((ext4_get32(sb, rev_level) > 0) &&\r
+ (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))\r
+ v |= ((uint64_t)to_le32(inode->size_hi)) << 32;\r
\r
- return v;\r
+ return v;\r
}\r
\r
void ext4_inode_set_size(struct ext4_inode *inode, uint64_t size)\r
{\r
- inode->size_lo = to_le32((size << 32) >> 32);\r
- inode->size_hi = to_le32(size >> 32);\r
+ inode->size_lo = to_le32((size << 32) >> 32);\r
+ inode->size_hi = to_le32(size >> 32);\r
}\r
\r
uint32_t ext4_inode_get_access_time(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->access_time);\r
+ return to_le32(inode->access_time);\r
}\r
void ext4_inode_set_access_time(struct ext4_inode *inode, uint32_t time)\r
{\r
- inode->access_time = to_le32(time);\r
+ inode->access_time = to_le32(time);\r
}\r
\r
uint32_t ext4_inode_get_change_inode_time(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->change_inode_time);\r
+ return to_le32(inode->change_inode_time);\r
}\r
void ext4_inode_set_change_inode_time(struct ext4_inode *inode, uint32_t time)\r
{\r
- inode->change_inode_time = to_le32(time);\r
+ inode->change_inode_time = to_le32(time);\r
}\r
\r
uint32_t ext4_inode_get_modification_time(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->modification_time);\r
+ return to_le32(inode->modification_time);\r
}\r
\r
void ext4_inode_set_modification_time(struct ext4_inode *inode, uint32_t time)\r
{\r
- inode->modification_time = to_le32(time);\r
+ inode->modification_time = to_le32(time);\r
}\r
\r
uint32_t ext4_inode_get_deletion_time(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->deletion_time);\r
+ return to_le32(inode->deletion_time);\r
}\r
\r
void ext4_inode_set_deletion_time(struct ext4_inode *inode, uint32_t time)\r
{\r
- inode->deletion_time = to_le32(time);\r
+ inode->deletion_time = to_le32(time);\r
}\r
\r
uint32_t ext4_inode_get_gid(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->gid);\r
+ return to_le32(inode->gid);\r
}\r
void ext4_inode_set_gid(struct ext4_inode *inode, uint32_t gid)\r
{\r
- inode->gid = to_le32(gid);\r
+ inode->gid = to_le32(gid);\r
}\r
\r
uint16_t ext4_inode_get_links_count(struct ext4_inode *inode)\r
{\r
- return to_le16(inode->links_count);\r
+ return to_le16(inode->links_count);\r
}\r
void ext4_inode_set_links_count(struct ext4_inode *inode, uint16_t cnt)\r
{\r
- inode->links_count = to_le16(cnt);\r
+ inode->links_count = to_le16(cnt);\r
}\r
\r
uint64_t ext4_inode_get_blocks_count(struct ext4_sblock *sb,\r
- struct ext4_inode *inode)\r
+ struct ext4_inode *inode)\r
{\r
- uint64_t count = to_le32(inode->blocks_count_lo);\r
+ uint64_t count = to_le32(inode->blocks_count_lo);\r
\r
- if (ext4_sb_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {\r
+ if (ext4_sb_has_feature_read_only(sb,\r
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {\r
\r
- /* 48-bit field */\r
- count |= ((uint64_t)to_le16(inode->osd2.linux2.blocks_high)) << 32;\r
+ /* 48-bit field */\r
+ count |= ((uint64_t)to_le16(inode->osd2.linux2.blocks_high))\r
+ << 32;\r
\r
- if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {\r
+ if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {\r
\r
- uint32_t block_bits =\r
- ext4_inode_block_bits_count(ext4_sb_get_block_size(sb));\r
- return count << (block_bits - 9);\r
- }\r
- }\r
+ uint32_t block_bits = ext4_inode_block_bits_count(\r
+ ext4_sb_get_block_size(sb));\r
+ return count << (block_bits - 9);\r
+ }\r
+ }\r
\r
- return count;\r
+ return count;\r
}\r
\r
int ext4_inode_set_blocks_count(struct ext4_sblock *sb,\r
- struct ext4_inode *inode, uint64_t count)\r
+ struct ext4_inode *inode, uint64_t count)\r
{\r
- /* 32-bit maximum */\r
- uint64_t max = 0;\r
- max = ~max >> 32;\r
+ /* 32-bit maximum */\r
+ uint64_t max = 0;\r
+ max = ~max >> 32;\r
\r
- if (count <= max) {\r
- inode->blocks_count_lo = to_le32(count);\r
- inode->osd2.linux2.blocks_high = 0;\r
- ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
+ if (count <= max) {\r
+ inode->blocks_count_lo = to_le32(count);\r
+ inode->osd2.linux2.blocks_high = 0;\r
+ ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
\r
- return EOK;\r
- }\r
+ return EOK;\r
+ }\r
\r
- /* Check if there can be used huge files (many blocks) */\r
- if (!ext4_sb_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE))\r
- return EINVAL;\r
+ /* Check if there can be used huge files (many blocks) */\r
+ if (!ext4_sb_has_feature_read_only(sb,\r
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE))\r
+ return EINVAL;\r
\r
- /* 48-bit maximum */\r
- max = 0;\r
- max = ~max >> 16;\r
+ /* 48-bit maximum */\r
+ max = 0;\r
+ max = ~max >> 16;\r
\r
- if (count <= max) {\r
- inode->blocks_count_lo = to_le32(count);\r
- inode->osd2.linux2.blocks_high = to_le16(count >> 32);\r
- ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
- } else {\r
- uint32_t block_bits =\r
- ext4_inode_block_bits_count(ext4_sb_get_block_size(sb));\r
+ if (count <= max) {\r
+ inode->blocks_count_lo = to_le32(count);\r
+ inode->osd2.linux2.blocks_high = to_le16(count >> 32);\r
+ ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
+ } else {\r
+ uint32_t block_bits =\r
+ ext4_inode_block_bits_count(ext4_sb_get_block_size(sb));\r
\r
- ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
- count = count >> (block_bits - 9);\r
- inode->blocks_count_lo = to_le32(count);\r
- inode->osd2.linux2.blocks_high = to_le16(count >> 32);\r
- }\r
+ ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
+ count = count >> (block_bits - 9);\r
+ inode->blocks_count_lo = to_le32(count);\r
+ inode->osd2.linux2.blocks_high = to_le16(count >> 32);\r
+ }\r
\r
- return EOK;\r
+ return EOK;\r
}\r
\r
uint32_t ext4_inode_get_flags(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->flags);\r
+ return to_le32(inode->flags);\r
}\r
void ext4_inode_set_flags(struct ext4_inode *inode, uint32_t flags)\r
{\r
- inode->flags = to_le32(flags);\r
+ inode->flags = to_le32(flags);\r
}\r
\r
uint32_t ext4_inode_get_generation(struct ext4_inode *inode)\r
{\r
- return to_le32(inode->generation);\r
+ return to_le32(inode->generation);\r
}\r
void ext4_inode_set_generation(struct ext4_inode *inode, uint32_t gen)\r
{\r
- inode->generation = to_le32(gen);\r
+ inode->generation = to_le32(gen);\r
}\r
\r
uint64_t ext4_inode_get_file_acl(struct ext4_inode *inode,\r
- struct ext4_sblock *sb)\r
+ struct ext4_sblock *sb)\r
{\r
- /*TODO: Verify it*/\r
- uint64_t v = to_le32(inode->file_acl_lo);\r
+ /*TODO: Verify it*/\r
+ uint64_t v = to_le32(inode->file_acl_lo);\r
\r
- if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_LINUX)\r
- v |= ((uint32_t)to_le16(inode->osd2.linux2.file_acl_high)) << 16;\r
+ if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_LINUX)\r
+ v |= ((uint32_t)to_le16(inode->osd2.linux2.file_acl_high))\r
+ << 16;\r
\r
- return v;\r
+ return v;\r
}\r
\r
void ext4_inode_set_file_acl(struct ext4_inode *inode, struct ext4_sblock *sb,\r
- uint64_t acl)\r
+ uint64_t acl)\r
{\r
- /*TODO: Verify it*/\r
- inode->file_acl_lo = to_le32((acl << 32) >> 32);\r
+ /*TODO: Verify it*/\r
+ inode->file_acl_lo = to_le32((acl << 32) >> 32);\r
\r
- if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_LINUX)\r
- inode->osd2.linux2.file_acl_high = to_le16(acl >> 32);\r
+ if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_LINUX)\r
+ inode->osd2.linux2.file_acl_high = to_le16(acl >> 32);\r
}\r
\r
uint32_t ext4_inode_get_direct_block(struct ext4_inode *inode, uint32_t idx)\r
{\r
- return to_le32(inode->blocks[idx]);\r
+ return to_le32(inode->blocks[idx]);\r
}\r
void ext4_inode_set_direct_block(struct ext4_inode *inode, uint32_t idx,\r
- uint32_t block)\r
+ uint32_t block)\r
{\r
- inode->blocks[idx] = to_le32(block);\r
+ inode->blocks[idx] = to_le32(block);\r
}\r
\r
uint32_t ext4_inode_get_indirect_block(struct ext4_inode *inode, uint32_t idx)\r
{\r
- return to_le32(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);\r
+ return to_le32(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);\r
}\r
\r
void ext4_inode_set_indirect_block(struct ext4_inode *inode, uint32_t idx,\r
- uint32_t block)\r
+ uint32_t block)\r
{\r
- inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] = to_le32(block);\r
+ inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] = to_le32(block);\r
}\r
\r
bool ext4_inode_is_type(struct ext4_sblock *sb, struct ext4_inode *inode,\r
- uint32_t type)\r
+ uint32_t type)\r
{\r
- return (ext4_inode_get_mode(sb, inode) & EXT4_INODE_MODE_TYPE_MASK) == type;\r
+ return (ext4_inode_get_mode(sb, inode) & EXT4_INODE_MODE_TYPE_MASK) ==\r
+ type;\r
}\r
\r
bool ext4_inode_has_flag(struct ext4_inode *inode, uint32_t f)\r
{\r
- return ext4_inode_get_flags(inode) & f;\r
+ return ext4_inode_get_flags(inode) & f;\r
}\r
\r
void ext4_inode_clear_flag(struct ext4_inode *inode, uint32_t f)\r
{\r
- uint32_t flags = ext4_inode_get_flags(inode);\r
- flags = flags & (~f);\r
- ext4_inode_set_flags(inode, flags);\r
+ uint32_t flags = ext4_inode_get_flags(inode);\r
+ flags = flags & (~f);\r
+ ext4_inode_set_flags(inode, flags);\r
}\r
\r
void ext4_inode_set_flag(struct ext4_inode *inode, uint32_t f)\r
{\r
- uint32_t flags = ext4_inode_get_flags(inode);\r
- flags = flags | f;\r
- ext4_inode_set_flags(inode, flags);\r
+ uint32_t flags = ext4_inode_get_flags(inode);\r
+ flags = flags | f;\r
+ ext4_inode_set_flags(inode, flags);\r
}\r
\r
bool ext4_inode_can_truncate(struct ext4_sblock *sb, struct ext4_inode *inode)\r
{\r
- if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||\r
- (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))\r
- return false;\r
+ if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||\r
+ (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))\r
+ return false;\r
\r
- if ((ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) ||\r
- (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)))\r
- return true;\r
+ if ((ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) ||\r
+ (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)))\r
+ return true;\r
\r
- return false;\r
+ return false;\r
}\r
\r
struct ext4_extent_header *\r
ext4_inode_get_extent_header(struct ext4_inode *inode)\r
{\r
- return (struct ext4_extent_header *)inode->blocks;\r
+ return (struct ext4_extent_header *)inode->blocks;\r
}\r
\r
/**\r
* @param mode Mode to set to i-node\r
*/\r
void ext4_inode_set_mode(struct ext4_sblock *sb, struct ext4_inode *inode,\r
- uint32_t mode);\r
+ uint32_t mode);\r
\r
/**@brief Get ID of the i-node owner (user id).\r
* @param inode I-node to load uid from\r
* @return Number of 512-bytes blocks\r
*/\r
uint64_t ext4_inode_get_blocks_count(struct ext4_sblock *sb,\r
- struct ext4_inode *inode);\r
+ struct ext4_inode *inode);\r
\r
/**@brief Set number of 512-bytes blocks used for i-node.\r
* @param sb Superblock\r
* @return Error code\r
*/\r
int ext4_inode_set_blocks_count(struct ext4_sblock *sb,\r
- struct ext4_inode *inode, uint64_t cnt);\r
+ struct ext4_inode *inode, uint64_t cnt);\r
\r
/**@brief Get flags (features) of i-node.\r
* @param inode I-node to get flags from\r
* @return Block address\r
*/\r
uint64_t ext4_inode_get_file_acl(struct ext4_inode *inode,\r
- struct ext4_sblock *sb);\r
+ struct ext4_sblock *sb);\r
\r
/**@brief Set address of block, where are extended attributes located.\r
* @param inode I-node\r
* @param file_acl Block address\r
*/\r
void ext4_inode_set_file_acl(struct ext4_inode *inode, struct ext4_sblock *sb,\r
- uint64_t acl);\r
+ uint64_t acl);\r
\r
/**@brief Get block address of specified direct block.\r
* @param inode I-node to load block from\r
* @param fblock Physical block address\r
*/\r
void ext4_inode_set_direct_block(struct ext4_inode *inode, uint32_t idx,\r
- uint32_t block);\r
+ uint32_t block);\r
\r
/**@brief Get block address of specified indirect block.\r
* @param inode I-node to get block address from\r
* @param fblock Physical block address\r
*/\r
void ext4_inode_set_indirect_block(struct ext4_inode *inode, uint32_t idx,\r
- uint32_t block);\r
+ uint32_t block);\r
\r
/**@brief Check if i-node has specified type.\r
* @param sb Superblock\r
* @return Result of check operation\r
*/\r
bool ext4_inode_is_type(struct ext4_sblock *sb, struct ext4_inode *inode,\r
- uint32_t type);\r
+ uint32_t type);\r
\r
/**@brief Check if i-node has specified flag.\r
* @param inode I-node to check flags of\r
uint32_t ext4_block_group_cnt(struct ext4_sblock *s)
{
- uint64_t blocks_count = ext4_sb_get_blocks_cnt(s);
- uint32_t blocks_per_group = ext4_get32(s, blocks_per_group);
+ uint64_t blocks_count = ext4_sb_get_blocks_cnt(s);
+ uint32_t blocks_per_group = ext4_get32(s, blocks_per_group);
- uint32_t block_groups_count = blocks_count / blocks_per_group;
+ uint32_t block_groups_count = blocks_count / blocks_per_group;
- if (blocks_count % blocks_per_group)
- block_groups_count++;
+ if (blocks_count % blocks_per_group)
+ block_groups_count++;
- return block_groups_count;
+ return block_groups_count;
}
uint32_t ext4_blocks_in_group_cnt(struct ext4_sblock *s, uint32_t bgid)
{
- uint32_t block_group_count = ext4_block_group_cnt(s);
- uint32_t blocks_per_group = ext4_get32(s, blocks_per_group);
- uint64_t total_blocks = ext4_sb_get_blocks_cnt(s);
+ uint32_t block_group_count = ext4_block_group_cnt(s);
+ uint32_t blocks_per_group = ext4_get32(s, blocks_per_group);
+ uint64_t total_blocks = ext4_sb_get_blocks_cnt(s);
- if (bgid < block_group_count - 1)
- return blocks_per_group;
+ if (bgid < block_group_count - 1)
+ return blocks_per_group;
- return (total_blocks - ((block_group_count - 1) * blocks_per_group));
+ return (total_blocks - ((block_group_count - 1) * blocks_per_group));
}
uint32_t ext4_inodes_in_group_cnt(struct ext4_sblock *s, uint32_t bgid)
{
- uint32_t block_group_count = ext4_block_group_cnt(s);
- uint32_t inodes_per_group = ext4_get32(s, inodes_per_group);
- uint32_t total_inodes = ext4_get32(s, inodes_count);
+ uint32_t block_group_count = ext4_block_group_cnt(s);
+ uint32_t inodes_per_group = ext4_get32(s, inodes_per_group);
+ uint32_t total_inodes = ext4_get32(s, inodes_count);
- if (bgid < block_group_count - 1)
- return inodes_per_group;
+ if (bgid < block_group_count - 1)
+ return inodes_per_group;
- return (total_inodes - ((block_group_count - 1) * inodes_per_group));
+ return (total_inodes - ((block_group_count - 1) * inodes_per_group));
}
int ext4_sb_write(struct ext4_blockdev *bdev, struct ext4_sblock *s)
{
- return ext4_block_writebytes(bdev, EXT4_SUPERBLOCK_OFFSET, s,
- EXT4_SUPERBLOCK_SIZE);
+ return ext4_block_writebytes(bdev, EXT4_SUPERBLOCK_OFFSET, s,
+ EXT4_SUPERBLOCK_SIZE);
}
int ext4_sb_read(struct ext4_blockdev *bdev, struct ext4_sblock *s)
{
- return ext4_block_readbytes(bdev, EXT4_SUPERBLOCK_OFFSET, s,
- EXT4_SUPERBLOCK_SIZE);
+ return ext4_block_readbytes(bdev, EXT4_SUPERBLOCK_OFFSET, s,
+ EXT4_SUPERBLOCK_SIZE);
}
bool ext4_sb_check(struct ext4_sblock *s)
{
- if (ext4_get16(s, magic) != EXT4_SUPERBLOCK_MAGIC)
- return false;
+ if (ext4_get16(s, magic) != EXT4_SUPERBLOCK_MAGIC)
+ return false;
- if (ext4_get32(s, inodes_count) == 0)
- return false;
+ if (ext4_get32(s, inodes_count) == 0)
+ return false;
- if (ext4_sb_get_blocks_cnt(s) == 0)
- return false;
+ if (ext4_sb_get_blocks_cnt(s) == 0)
+ return false;
- if (ext4_get32(s, blocks_per_group) == 0)
- return false;
+ if (ext4_get32(s, blocks_per_group) == 0)
+ return false;
- if (ext4_get32(s, inodes_per_group) == 0)
- return false;
+ if (ext4_get32(s, inodes_per_group) == 0)
+ return false;
- if (ext4_get16(s, inode_size) < 128)
- return false;
+ if (ext4_get16(s, inode_size) < 128)
+ return false;
- if (ext4_get32(s, first_inode) < 11)
- return false;
+ if (ext4_get32(s, first_inode) < 11)
+ return false;
- if (ext4_sb_get_desc_size(s) < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
- return false;
+ if (ext4_sb_get_desc_size(s) < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ return false;
- if (ext4_sb_get_desc_size(s) > EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE)
- return false;
+ if (ext4_sb_get_desc_size(s) > EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE)
+ return false;
- return true;
+ return true;
}
static inline int is_multiple(uint32_t a, uint32_t b)
{
- while (1) {
- if (a < b)
- return 0;
- if (a == b)
- return 1;
- if ((a % b) != 0)
- return 0;
- a = a / b;
- }
+ while (1) {
+ if (a < b)
+ return 0;
+ if (a == b)
+ return 1;
+ if ((a % b) != 0)
+ return 0;
+ a = a / b;
+ }
}
static int ext4_sb_sparse(uint32_t group)
{
- if (group <= 1)
- return 1;
+ if (group <= 1)
+ return 1;
- if (!(group & 1))
- return 0;
+ if (!(group & 1))
+ return 0;
- return (is_multiple(group, 7) || is_multiple(group, 5) ||
- is_multiple(group, 3));
+ return (is_multiple(group, 7) || is_multiple(group, 5) ||
+ is_multiple(group, 3));
}
bool ext4_sb_is_super_in_bg(struct ext4_sblock *s, uint32_t group)
{
- if (ext4_sb_has_feature_read_only(s, EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
- !ext4_sb_sparse(group))
- return false;
- return true;
+ if (ext4_sb_has_feature_read_only(
+ s, EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
+ !ext4_sb_sparse(group))
+ return false;
+ return true;
}
static uint32_t ext4_bg_num_gdb_meta(struct ext4_sblock *s, uint32_t group)
{
- uint32_t dsc_per_block =
- ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
+ uint32_t dsc_per_block =
+ ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
- uint32_t metagroup = group / dsc_per_block;
- uint32_t first = metagroup * dsc_per_block;
- uint32_t last = first + dsc_per_block - 1;
+ uint32_t metagroup = group / dsc_per_block;
+ uint32_t first = metagroup * dsc_per_block;
+ uint32_t last = first + dsc_per_block - 1;
- if (group == first || group == first + 1 || group == last)
- return 1;
- return 0;
+ if (group == first || group == first + 1 || group == last)
+ return 1;
+ return 0;
}
static uint32_t ext4_bg_num_gdb_nometa(struct ext4_sblock *s, uint32_t group)
{
- if (!ext4_sb_is_super_in_bg(s, group))
- return 0;
- uint32_t dsc_per_block =
- ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
+ if (!ext4_sb_is_super_in_bg(s, group))
+ return 0;
+ uint32_t dsc_per_block =
+ ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
- uint32_t db_count =
- (ext4_block_group_cnt(s) + dsc_per_block - 1) / dsc_per_block;
+ uint32_t db_count =
+ (ext4_block_group_cnt(s) + dsc_per_block - 1) / dsc_per_block;
- if (ext4_sb_has_feature_incompatible(s, EXT4_FEATURE_INCOMPAT_META_BG))
- return ext4_sb_first_meta_bg(s);
+ if (ext4_sb_has_feature_incompatible(s, EXT4_FEATURE_INCOMPAT_META_BG))
+ return ext4_sb_first_meta_bg(s);
- return db_count;
+ return db_count;
}
uint32_t ext4_bg_num_gdb(struct ext4_sblock *s, uint32_t group)
{
- uint32_t dsc_per_block =
- ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
- uint32_t first_meta_bg = ext4_sb_first_meta_bg(s);
- uint32_t metagroup = group / dsc_per_block;
+ uint32_t dsc_per_block =
+ ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
+ uint32_t first_meta_bg = ext4_sb_first_meta_bg(s);
+ uint32_t metagroup = group / dsc_per_block;
- if (!ext4_sb_has_feature_incompatible(s, EXT4_FEATURE_INCOMPAT_META_BG) ||
- metagroup < first_meta_bg)
- return ext4_bg_num_gdb_nometa(s, group);
+ if (!ext4_sb_has_feature_incompatible(s,
+ EXT4_FEATURE_INCOMPAT_META_BG) ||
+ metagroup < first_meta_bg)
+ return ext4_bg_num_gdb_nometa(s, group);
- return ext4_bg_num_gdb_meta(s, group);
+ return ext4_bg_num_gdb_meta(s, group);
}
uint32_t ext4_num_base_meta_clusters(struct ext4_sblock *s,
- uint32_t block_group)
+ uint32_t block_group)
{
- uint32_t num;
- uint32_t dsc_per_block =
- ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
-
- num = ext4_sb_is_super_in_bg(s, block_group);
-
- if (!ext4_sb_has_feature_incompatible(s, EXT4_FEATURE_INCOMPAT_META_BG) ||
- block_group < ext4_sb_first_meta_bg(s) * dsc_per_block) {
- if (num) {
- num += ext4_bg_num_gdb(s, block_group);
- num += ext4_get16(s, s_reserved_gdt_blocks);
- }
- } else {
- num += ext4_bg_num_gdb(s, block_group);
- }
-
- uint32_t clustersize = 1024 << ext4_get32(s, log_cluster_size);
- uint32_t cluster_ratio = clustersize / ext4_sb_get_block_size(s);
- uint32_t v = (num + cluster_ratio - 1) >> ext4_get32(s, log_cluster_size);
-
- return v;
+ uint32_t num;
+ uint32_t dsc_per_block =
+ ext4_sb_get_block_size(s) / ext4_sb_get_desc_size(s);
+
+ num = ext4_sb_is_super_in_bg(s, block_group);
+
+ if (!ext4_sb_has_feature_incompatible(s,
+ EXT4_FEATURE_INCOMPAT_META_BG) ||
+ block_group < ext4_sb_first_meta_bg(s) * dsc_per_block) {
+ if (num) {
+ num += ext4_bg_num_gdb(s, block_group);
+ num += ext4_get16(s, s_reserved_gdt_blocks);
+ }
+ } else {
+ num += ext4_bg_num_gdb(s, block_group);
+ }
+
+ uint32_t clustersize = 1024 << ext4_get32(s, log_cluster_size);
+ uint32_t cluster_ratio = clustersize / ext4_sb_get_block_size(s);
+ uint32_t v =
+ (num + cluster_ratio - 1) >> ext4_get32(s, log_cluster_size);
+
+ return v;
}
/**
* @return count of blocks*/
static inline uint64_t ext4_sb_get_blocks_cnt(struct ext4_sblock *s)
{
- return ((uint64_t)to_le32(s->blocks_count_hi) << 32) |
- to_le32(s->blocks_count_lo);
+ return ((uint64_t)to_le32(s->blocks_count_hi) << 32) |
+ to_le32(s->blocks_count_lo);
}
/**@brief Free blocks count get stored in superblock.
* @return free blocks*/
static inline uint64_t ext4_sb_get_free_blocks_cnt(struct ext4_sblock *s)
{
- return ((uint64_t)to_le32(s->free_blocks_count_hi) << 32) |
- to_le32(s->free_blocks_count_lo);
+ return ((uint64_t)to_le32(s->free_blocks_count_hi) << 32) |
+ to_le32(s->free_blocks_count_lo);
}
/**@brief Free blocks count set.
* @param s superblock descriptor
* @param cnt new value of free blocks*/
static inline void ext4_sb_set_free_blocks_cnt(struct ext4_sblock *s,
- uint64_t cnt)
+ uint64_t cnt)
{
- s->free_blocks_count_lo = to_le32((cnt << 32) >> 32);
- s->free_blocks_count_hi = to_le32(cnt >> 32);
+ s->free_blocks_count_lo = to_le32((cnt << 32) >> 32);
+ s->free_blocks_count_hi = to_le32(cnt >> 32);
}
/**@brief Block size get from superblock.
* @return block size in bytes*/
static inline uint32_t ext4_sb_get_block_size(struct ext4_sblock *s)
{
- return 1024 << to_le32(s->log_block_size);
+ return 1024 << to_le32(s->log_block_size);
}
/**@brief Block group descriptor size.
* @return block group descriptor size in bytes*/
static inline uint16_t ext4_sb_get_desc_size(struct ext4_sblock *s)
{
- uint16_t size = to_le16(s->desc_size);
+ uint16_t size = to_le16(s->desc_size);
- return size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE
- ? EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE
- : size;
+ return size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE
+ ? EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE
+ : size;
}
/*************************Flags and features*********************************/
* @return true if flag is supported*/
static inline bool ext4_sb_check_flag(struct ext4_sblock *s, uint32_t v)
{
- return to_le32(s->flags) & v;
+ return to_le32(s->flags) & v;
}
/**@brief Support check of feature compatible.
* @param v feature to check
* @return true if feature is supported*/
static inline bool ext4_sb_has_feature_compatible(struct ext4_sblock *s,
- uint32_t v)
+ uint32_t v)
{
- return to_le32(s->features_compatible) & v;
+ return to_le32(s->features_compatible) & v;
}
/**@brief Support check of feature incompatible.
* @param v feature to check
* @return true if feature is supported*/
static inline bool ext4_sb_has_feature_incompatible(struct ext4_sblock *s,
- uint32_t v)
+ uint32_t v)
{
- return to_le32(s->features_incompatible) & v;
+ return to_le32(s->features_incompatible) & v;
}
/**@brief Support check of read only flag.
* @param v flag to check
* @return true if flag is supported*/
static inline bool ext4_sb_has_feature_read_only(struct ext4_sblock *s,
- uint32_t v)
+ uint32_t v)
{
- return to_le32(s->features_read_only) & v;
+ return to_le32(s->features_read_only) & v;
}
/**@brief Block group to flex group.
* @param block_group block group
* @return flex group id*/
static inline uint32_t ext4_sb_bg_to_flex(struct ext4_sblock *s,
- uint32_t block_group)
+ uint32_t block_group)
{
- return block_group >> to_le32(s->log_groups_per_flex);
+ return block_group >> to_le32(s->log_groups_per_flex);
}
/**@brief Flex block group size.
* @return flex bg size*/
static inline uint32_t ext4_sb_flex_bg_size(struct ext4_sblock *s)
{
- return 1 << to_le32(s->log_groups_per_flex);
+ return 1 << to_le32(s->log_groups_per_flex);
}
/**@brief Return first meta block group id.
* @return first meta_bg id */
static inline uint32_t ext4_sb_first_meta_bg(struct ext4_sblock *s)
{
- return to_le32(s->first_meta_bg);
+ return to_le32(s->first_meta_bg);
}
/**************************More complex functions****************************/
/**@brief TODO:*/
uint32_t ext4_num_base_meta_clusters(struct ext4_sblock *s,
- uint32_t block_group);
+ uint32_t block_group);
#endif /* EXT4_SUPER_H_ */
* Structure of the super block
*/
struct ext4_sblock {
- uint32_t inodes_count; /* I-nodes count */
- uint32_t blocks_count_lo; /* Blocks count */
- uint32_t reserved_blocks_count_lo; /* Reserved blocks count */
- uint32_t free_blocks_count_lo; /* Free blocks count */
- uint32_t free_inodes_count; /* Free inodes count */
- uint32_t first_data_block; /* First Data Block */
- uint32_t log_block_size; /* Block size */
- uint32_t log_cluster_size; /* Obsoleted fragment size */
- uint32_t blocks_per_group; /* Number of blocks per group */
- uint32_t frags_per_group; /* Obsoleted fragments per group */
- uint32_t inodes_per_group; /* Number of inodes per group */
- uint32_t mount_time; /* Mount time */
- uint32_t write_time; /* Write time */
- uint16_t mount_count; /* Mount count */
- uint16_t max_mount_count; /* Maximal mount count */
- uint16_t magic; /* Magic signature */
- uint16_t state; /* File system state */
- uint16_t errors; /* Behavior when detecting errors */
- uint16_t minor_rev_level; /* Minor revision level */
- uint32_t last_check_time; /* Time of last check */
- uint32_t check_interval; /* Maximum time between checks */
- uint32_t creator_os; /* Creator OS */
- uint32_t rev_level; /* Revision level */
- uint16_t def_resuid; /* Default uid for reserved blocks */
- uint16_t def_resgid; /* Default gid for reserved blocks */
-
- /* Fields for EXT4_DYNAMIC_REV superblocks only. */
- uint32_t first_inode; /* First non-reserved inode */
- uint16_t inode_size; /* Size of inode structure */
- uint16_t block_group_index; /* Block group index of this superblock */
- uint32_t features_compatible; /* Compatible feature set */
- uint32_t features_incompatible; /* Incompatible feature set */
- uint32_t features_read_only; /* Readonly-compatible feature set */
- uint8_t uuid[16]; /* 128-bit uuid for volume */
- char volume_name[16]; /* Volume name */
- char last_mounted[64]; /* Directory where last mounted */
- uint32_t algorithm_usage_bitmap; /* For compression */
-
- /*
- * Performance hints. Directory preallocation should only
- * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
- */
- uint8_t s_prealloc_blocks; /* Number of blocks to try to preallocate */
- uint8_t s_prealloc_dir_blocks; /* Number to preallocate for dirs */
- uint16_t s_reserved_gdt_blocks; /* Per group desc for online growth */
-
- /*
- * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
- */
- uint8_t journal_uuid[16]; /* UUID of journal superblock */
- uint32_t journal_inode_number; /* Inode number of journal file */
- uint32_t journal_dev; /* Device number of journal file */
- uint32_t last_orphan; /* Head of list of inodes to delete */
- uint32_t hash_seed[4]; /* HTREE hash seed */
- uint8_t default_hash_version; /* Default hash version to use */
- uint8_t journal_backup_type;
- uint16_t desc_size; /* Size of group descriptor */
- uint32_t default_mount_opts; /* Default mount options */
- uint32_t first_meta_bg; /* First metablock block group */
- uint32_t mkfs_time; /* When the filesystem was created */
- uint32_t journal_blocks[17]; /* Backup of the journal inode */
-
- /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
- uint32_t blocks_count_hi; /* Blocks count */
- uint32_t reserved_blocks_count_hi; /* Reserved blocks count */
- uint32_t free_blocks_count_hi; /* Free blocks count */
- uint16_t min_extra_isize; /* All inodes have at least # bytes */
- uint16_t want_extra_isize; /* New inodes should reserve # bytes */
- uint32_t flags; /* Miscellaneous flags */
- uint16_t raid_stride; /* RAID stride */
- uint16_t mmp_interval; /* # seconds to wait in MMP checking */
- uint64_t mmp_block; /* Block for multi-mount protection */
- uint32_t raid_stripe_width; /* Blocks on all data disks (N * stride) */
- uint8_t log_groups_per_flex; /* FLEX_BG group size */
- uint8_t reserved_char_pad;
- uint16_t reserved_pad;
- uint64_t kbytes_written; /* Number of lifetime kilobytes written */
- uint32_t snapshot_inum; /* I-node number of active snapshot */
- uint32_t snapshot_id; /* Sequential ID of active snapshot */
- uint64_t snapshot_r_blocks_count; /* Reserved blocks for active snapshot's
- future use */
- uint32_t snapshot_list; /* I-node number of the head of the on-disk snapshot
- list */
- uint32_t error_count; /* Number of file system errors */
- uint32_t first_error_time; /* First time an error happened */
- uint32_t first_error_ino; /* I-node involved in first error */
- uint64_t first_error_block; /* Block involved of first error */
- uint8_t first_error_func[32]; /* Function where the error happened */
- uint32_t first_error_line; /* Line number where error happened */
- uint32_t last_error_time; /* Most recent time of an error */
- uint32_t last_error_ino; /* I-node involved in last error */
- uint32_t last_error_line; /* Line number where error happened */
- uint64_t last_error_block; /* Block involved of last error */
- uint8_t last_error_func[32]; /* Function where the error happened */
- uint8_t mount_opts[64];
- uint32_t padding[112]; /* Padding to the end of the block */
+ uint32_t inodes_count; /* I-nodes count */
+ uint32_t blocks_count_lo; /* Blocks count */
+ uint32_t reserved_blocks_count_lo; /* Reserved blocks count */
+ uint32_t free_blocks_count_lo; /* Free blocks count */
+ uint32_t free_inodes_count; /* Free inodes count */
+ uint32_t first_data_block; /* First Data Block */
+ uint32_t log_block_size; /* Block size */
+ uint32_t log_cluster_size; /* Obsoleted fragment size */
+ uint32_t blocks_per_group; /* Number of blocks per group */
+ uint32_t frags_per_group; /* Obsoleted fragments per group */
+ uint32_t inodes_per_group; /* Number of inodes per group */
+ uint32_t mount_time; /* Mount time */
+ uint32_t write_time; /* Write time */
+ uint16_t mount_count; /* Mount count */
+ uint16_t max_mount_count; /* Maximal mount count */
+ uint16_t magic; /* Magic signature */
+ uint16_t state; /* File system state */
+ uint16_t errors; /* Behavior when detecting errors */
+ uint16_t minor_rev_level; /* Minor revision level */
+ uint32_t last_check_time; /* Time of last check */
+ uint32_t check_interval; /* Maximum time between checks */
+ uint32_t creator_os; /* Creator OS */
+ uint32_t rev_level; /* Revision level */
+ uint16_t def_resuid; /* Default uid for reserved blocks */
+ uint16_t def_resgid; /* Default gid for reserved blocks */
+
+ /* Fields for EXT4_DYNAMIC_REV superblocks only. */
+ uint32_t first_inode; /* First non-reserved inode */
+ uint16_t inode_size; /* Size of inode structure */
+ uint16_t block_group_index; /* Block group index of this superblock */
+ uint32_t features_compatible; /* Compatible feature set */
+ uint32_t features_incompatible; /* Incompatible feature set */
+ uint32_t features_read_only; /* Readonly-compatible feature set */
+ uint8_t uuid[16]; /* 128-bit uuid for volume */
+ char volume_name[16]; /* Volume name */
+ char last_mounted[64]; /* Directory where last mounted */
+ uint32_t algorithm_usage_bitmap; /* For compression */
+
+ /*
+ * Performance hints. Directory preallocation should only
+ * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
+ */
+ uint8_t s_prealloc_blocks; /* Number of blocks to try to preallocate */
+ uint8_t s_prealloc_dir_blocks; /* Number to preallocate for dirs */
+ uint16_t s_reserved_gdt_blocks; /* Per group desc for online growth */
+
+ /*
+ * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
+ */
+ uint8_t journal_uuid[16]; /* UUID of journal superblock */
+ uint32_t journal_inode_number; /* Inode number of journal file */
+ uint32_t journal_dev; /* Device number of journal file */
+ uint32_t last_orphan; /* Head of list of inodes to delete */
+ uint32_t hash_seed[4]; /* HTREE hash seed */
+ uint8_t default_hash_version; /* Default hash version to use */
+ uint8_t journal_backup_type;
+ uint16_t desc_size; /* Size of group descriptor */
+ uint32_t default_mount_opts; /* Default mount options */
+ uint32_t first_meta_bg; /* First metablock block group */
+ uint32_t mkfs_time; /* When the filesystem was created */
+ uint32_t journal_blocks[17]; /* Backup of the journal inode */
+
+ /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
+ uint32_t blocks_count_hi; /* Blocks count */
+ uint32_t reserved_blocks_count_hi; /* Reserved blocks count */
+ uint32_t free_blocks_count_hi; /* Free blocks count */
+ uint16_t min_extra_isize; /* All inodes have at least # bytes */
+ uint16_t want_extra_isize; /* New inodes should reserve # bytes */
+ uint32_t flags; /* Miscellaneous flags */
+ uint16_t raid_stride; /* RAID stride */
+ uint16_t mmp_interval; /* # seconds to wait in MMP checking */
+ uint64_t mmp_block; /* Block for multi-mount protection */
+ uint32_t raid_stripe_width; /* Blocks on all data disks (N * stride) */
+ uint8_t log_groups_per_flex; /* FLEX_BG group size */
+ uint8_t reserved_char_pad;
+ uint16_t reserved_pad;
+ uint64_t kbytes_written; /* Number of lifetime kilobytes written */
+ uint32_t snapshot_inum; /* I-node number of active snapshot */
+ uint32_t snapshot_id; /* Sequential ID of active snapshot */
+ uint64_t
+ snapshot_r_blocks_count; /* Reserved blocks for active snapshot's
+ future use */
+ uint32_t
+ snapshot_list; /* I-node number of the head of the on-disk snapshot
+ list */
+ uint32_t error_count; /* Number of file system errors */
+ uint32_t first_error_time; /* First time an error happened */
+ uint32_t first_error_ino; /* I-node involved in first error */
+ uint64_t first_error_block; /* Block involved of first error */
+ uint8_t first_error_func[32]; /* Function where the error happened */
+ uint32_t first_error_line; /* Line number where error happened */
+ uint32_t last_error_time; /* Most recent time of an error */
+ uint32_t last_error_ino; /* I-node involved in last error */
+ uint32_t last_error_line; /* Line number where error happened */
+ uint64_t last_error_block; /* Block involved of last error */
+ uint8_t last_error_func[32]; /* Function where the error happened */
+ uint8_t mount_opts[64];
+ uint32_t padding[112]; /* Padding to the end of the block */
} __attribute__((packed));
#define EXT4_SUPERBLOCK_MAGIC 0xEF53
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
-#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */
-#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */
+#define EXT4_FEATURE_INCOMPAT_EA_INODE 0x0400 /* EA in inode */
+#define EXT4_FEATURE_INCOMPAT_DIRDATA 0x1000 /* data in dirent */
#define EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM 0x2000 /* use crc32c for bg */
-#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */
+#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */
#define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */
/*
#define EXT2_FEATURE_COMPAT_SUPP 0x0000
#define EXT2_FEATURE_INCOMPAT_SUPP \
- (EXT4_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_META_BG)
+ (EXT4_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_META_BG)
#define EXT2_FEATURE_RO_COMPAT_SUPP \
- (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | EXT4_FEATURE_RO_COMPAT_LARGE_FILE | \
- EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
+ (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | \
+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE | EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
/*
* EXT3 supported feature set
#define EXT3_FEATURE_COMPAT_SUPP (EXT4_FEATURE_COMPAT_DIR_INDEX)
#define EXT3_FEATURE_INCOMPAT_SUPP \
- (EXT4_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_META_BG)
+ (EXT4_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_META_BG)
#define EXT3_FEATURE_RO_COMPAT_SUPP \
- (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | EXT4_FEATURE_RO_COMPAT_LARGE_FILE | \
- EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
+ (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | \
+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE | EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
/*
* EXT4 supported feature set
#define EXT4_FEATURE_COMPAT_SUPP (EXT4_FEATURE_COMPAT_DIR_INDEX)
#define EXT4_FEATURE_INCOMPAT_SUPP \
- (EXT4_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_META_BG | \
- EXT4_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_FLEX_BG | \
- EXT4_FEATURE_INCOMPAT_64BIT)
+ (EXT4_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_META_BG | \
+ EXT4_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_FLEX_BG | \
+ EXT4_FEATURE_INCOMPAT_64BIT)
#define EXT4_FEATURE_RO_COMPAT_SUPP \
- (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | EXT4_FEATURE_RO_COMPAT_LARGE_FILE | \
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM | EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
- EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | EXT4_FEATURE_RO_COMPAT_BTREE_DIR | \
- EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+ (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | \
+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE | EXT4_FEATURE_RO_COMPAT_GDT_CSUM | \
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \
+ EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \
+ EXT4_FEATURE_RO_COMPAT_BTREE_DIR | EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
/*Ignored features:
* RECOVER - journaling in lwext4 is not supported
* MMP - multi-mout protection (impossible scenario)
* */
#define FEATURE_INCOMPAT_IGNORED \
- EXT4_FEATURE_INCOMPAT_RECOVER | EXT4_FEATURE_INCOMPAT_MMP
+ EXT4_FEATURE_INCOMPAT_RECOVER | EXT4_FEATURE_INCOMPAT_MMP
#if 0
/*TODO: Features incompatible to implement*/
#endif
struct ext4_fs {
- struct ext4_blockdev *bdev;
- struct ext4_sblock sb;
+ struct ext4_blockdev *bdev;
+ struct ext4_sblock sb;
- uint64_t inode_block_limits[4];
- uint64_t inode_blocks_per_level[4];
+ uint64_t inode_block_limits[4];
+ uint64_t inode_blocks_per_level[4];
- uint32_t last_inode_bg_id;
+ uint32_t last_inode_bg_id;
};
/* Inode table/bitmap not in use */
* Structure of a blocks group descriptor
*/
struct ext4_bgroup {
- uint32_t block_bitmap_lo; /* Blocks bitmap block */
- uint32_t inode_bitmap_lo; /* Inodes bitmap block */
- uint32_t inode_table_first_block_lo; /* Inodes table block */
- uint16_t free_blocks_count_lo; /* Free blocks count */
- uint16_t free_inodes_count_lo; /* Free inodes count */
- uint16_t used_dirs_count_lo; /* Directories count */
- uint16_t flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
- uint32_t exclude_bitmap_lo; /* Exclude bitmap for snapshots */
- uint16_t block_bitmap_csum_lo; /* crc32c(s_uuid+grp_num+bbitmap) LE */
- uint16_t inode_bitmap_csum_lo; /* crc32c(s_uuid+grp_num+ibitmap) LE */
- uint16_t itable_unused_lo; /* Unused inodes count */
- uint16_t checksum; /* crc16(sb_uuid+group+desc) */
-
- uint32_t block_bitmap_hi; /* Blocks bitmap block MSB */
- uint32_t inode_bitmap_hi; /* I-nodes bitmap block MSB */
- uint32_t inode_table_first_block_hi; /* I-nodes table block MSB */
- uint16_t free_blocks_count_hi; /* Free blocks count MSB */
- uint16_t free_inodes_count_hi; /* Free i-nodes count MSB */
- uint16_t used_dirs_count_hi; /* Directories count MSB */
- uint16_t itable_unused_hi; /* Unused inodes count MSB */
- uint32_t exclude_bitmap_hi; /* Exclude bitmap block MSB */
- uint16_t block_bitmap_csum_hi; /* crc32c(s_uuid+grp_num+bbitmap) BE */
- uint16_t inode_bitmap_csum_hi; /* crc32c(s_uuid+grp_num+ibitmap) BE */
- uint32_t reserved; /* Padding */
+ uint32_t block_bitmap_lo; /* Blocks bitmap block */
+ uint32_t inode_bitmap_lo; /* Inodes bitmap block */
+ uint32_t inode_table_first_block_lo; /* Inodes table block */
+ uint16_t free_blocks_count_lo; /* Free blocks count */
+ uint16_t free_inodes_count_lo; /* Free inodes count */
+ uint16_t used_dirs_count_lo; /* Directories count */
+ uint16_t flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
+ uint32_t exclude_bitmap_lo; /* Exclude bitmap for snapshots */
+ uint16_t block_bitmap_csum_lo; /* crc32c(s_uuid+grp_num+bbitmap) LE */
+ uint16_t inode_bitmap_csum_lo; /* crc32c(s_uuid+grp_num+ibitmap) LE */
+ uint16_t itable_unused_lo; /* Unused inodes count */
+ uint16_t checksum; /* crc16(sb_uuid+group+desc) */
+
+ uint32_t block_bitmap_hi; /* Blocks bitmap block MSB */
+ uint32_t inode_bitmap_hi; /* I-nodes bitmap block MSB */
+ uint32_t inode_table_first_block_hi; /* I-nodes table block MSB */
+ uint16_t free_blocks_count_hi; /* Free blocks count MSB */
+ uint16_t free_inodes_count_hi; /* Free i-nodes count MSB */
+ uint16_t used_dirs_count_hi; /* Directories count MSB */
+ uint16_t itable_unused_hi; /* Unused inodes count MSB */
+ uint32_t exclude_bitmap_hi; /* Exclude bitmap block MSB */
+ uint16_t block_bitmap_csum_hi; /* crc32c(s_uuid+grp_num+bbitmap) BE */
+ uint16_t inode_bitmap_csum_hi; /* crc32c(s_uuid+grp_num+ibitmap) BE */
+ uint32_t reserved; /* Padding */
};
struct ext4_block_group_ref {
- struct ext4_block block;
- struct ext4_bgroup *block_group;
- struct ext4_fs *fs;
- uint32_t index;
- bool dirty;
+ struct ext4_block block;
+ struct ext4_bgroup *block_group;
+ struct ext4_fs *fs;
+ uint32_t index;
+ bool dirty;
};
#define EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE 32
#define EXT4_INODE_TRIPPLE_INDIRECT_BLOCK (EXT4_INODE_DOUBLE_INDIRECT_BLOCK + 1)
#define EXT4_INODE_BLOCKS (EXT4_INODE_TRIPPLE_INDIRECT_BLOCK + 1)
#define EXT4_INODE_INDIRECT_BLOCK_COUNT \
- (EXT4_INODE_BLOCKS - EXT4_INODE_DIRECT_BLOCK_COUNT)
+ (EXT4_INODE_BLOCKS - EXT4_INODE_DIRECT_BLOCK_COUNT)
/*
* Structure of an inode on the disk
*/
struct ext4_inode {
- uint16_t mode; /* File mode */
- uint16_t uid; /* Low 16 bits of owner uid */
- uint32_t size_lo; /* Size in bytes */
- uint32_t access_time; /* Access time */
- uint32_t change_inode_time; /* I-node change time */
- uint32_t modification_time; /* Modification time */
- uint32_t deletion_time; /* Deletion time */
- uint16_t gid; /* Low 16 bits of group id */
- uint16_t links_count; /* Links count */
- uint32_t blocks_count_lo; /* Blocks count */
- uint32_t flags; /* File flags */
- uint32_t unused_osd1; /* OS dependent - not used in HelenOS */
- uint32_t blocks[EXT4_INODE_BLOCKS]; /* Pointers to blocks */
- uint32_t generation; /* File version (for NFS) */
- uint32_t file_acl_lo; /* File ACL */
- uint32_t size_hi;
- uint32_t obso_faddr; /* Obsoleted fragment address */
-
- union {
- struct {
- uint16_t blocks_high;
- uint16_t file_acl_high;
- uint16_t uid_high;
- uint16_t gid_high;
- uint32_t reserved2;
- } linux2;
- struct {
- uint16_t reserved1;
- uint16_t mode_high;
- uint16_t uid_high;
- uint16_t gid_high;
- uint32_t author;
- } hurd2;
- } __attribute__((packed)) osd2;
-
- uint16_t extra_isize;
- uint16_t pad1;
- uint32_t ctime_extra; /* Extra change time (nsec << 2 | epoch) */
- uint32_t mtime_extra; /* Extra Modification time (nsec << 2 | epoch) */
- uint32_t atime_extra; /* Extra Access time (nsec << 2 | epoch) */
- uint32_t crtime; /* File creation time */
- uint32_t crtime_extra; /* Extra file creation time (nsec << 2 | epoch) */
- uint32_t version_hi; /* High 32 bits for 64-bit version */
+ uint16_t mode; /* File mode */
+ uint16_t uid; /* Low 16 bits of owner uid */
+ uint32_t size_lo; /* Size in bytes */
+ uint32_t access_time; /* Access time */
+ uint32_t change_inode_time; /* I-node change time */
+ uint32_t modification_time; /* Modification time */
+ uint32_t deletion_time; /* Deletion time */
+ uint16_t gid; /* Low 16 bits of group id */
+ uint16_t links_count; /* Links count */
+ uint32_t blocks_count_lo; /* Blocks count */
+ uint32_t flags; /* File flags */
+ uint32_t unused_osd1; /* OS dependent - not used in HelenOS */
+ uint32_t blocks[EXT4_INODE_BLOCKS]; /* Pointers to blocks */
+ uint32_t generation; /* File version (for NFS) */
+ uint32_t file_acl_lo; /* File ACL */
+ uint32_t size_hi;
+ uint32_t obso_faddr; /* Obsoleted fragment address */
+
+ union {
+ struct {
+ uint16_t blocks_high;
+ uint16_t file_acl_high;
+ uint16_t uid_high;
+ uint16_t gid_high;
+ uint32_t reserved2;
+ } linux2;
+ struct {
+ uint16_t reserved1;
+ uint16_t mode_high;
+ uint16_t uid_high;
+ uint16_t gid_high;
+ uint32_t author;
+ } hurd2;
+ } __attribute__((packed)) osd2;
+
+ uint16_t extra_isize;
+ uint16_t pad1;
+ uint32_t ctime_extra; /* Extra change time (nsec << 2 | epoch) */
+ uint32_t mtime_extra; /* Extra Modification time (nsec << 2 | epoch) */
+ uint32_t atime_extra; /* Extra Access time (nsec << 2 | epoch) */
+ uint32_t crtime; /* File creation time */
+ uint32_t
+ crtime_extra; /* Extra file creation time (nsec << 2 | epoch) */
+ uint32_t version_hi; /* High 32 bits for 64-bit version */
} __attribute__((packed));
#define EXT4_INODE_MODE_FIFO 0x1000
/* Compression flags */
#define EXT4_INODE_FLAG_DIRTY 0x00000100
#define EXT4_INODE_FLAG_COMPRBLK \
- 0x00000200 /* One or more compressed clusters */
+ 0x00000200 /* One or more compressed clusters */
#define EXT4_INODE_FLAG_NOCOMPR 0x00000400 /* Don't compress */
#define EXT4_INODE_FLAG_ECOMPR 0x00000800 /* Compression error */
#define EXT4_INODE_FLAG_INDEX 0x00001000 /* hash-indexed directory */
#define EXT4_INODE_FLAG_IMAGIC 0x00002000 /* AFS directory */
#define EXT4_INODE_FLAG_JOURNAL_DATA \
- 0x00004000 /* File data should be journaled */
+ 0x00004000 /* File data should be journaled */
#define EXT4_INODE_FLAG_NOTAIL 0x00008000 /* File tail should not be merged */
#define EXT4_INODE_FLAG_DIRSYNC \
- 0x00010000 /* Dirsync behaviour (directories only) */
+ 0x00010000 /* Dirsync behaviour (directories only) */
#define EXT4_INODE_FLAG_TOPDIR 0x00020000 /* Top of directory hierarchies */
#define EXT4_INODE_FLAG_HUGE_FILE 0x00040000 /* Set to each huge file */
#define EXT4_INODE_FLAG_EXTENTS 0x00080000 /* Inode uses extents */
#define EXT4_INODE_ROOT_INDEX 2
struct ext4_inode_ref {
- struct ext4_block block;
- struct ext4_inode *inode;
- struct ext4_fs *fs;
- uint32_t index;
- bool dirty;
+ struct ext4_block block;
+ struct ext4_inode *inode;
+ struct ext4_fs *fs;
+ uint32_t index;
+ bool dirty;
};
#define EXT4_DIRECTORY_FILENAME_LEN 255
#define EXT4_DIRECTORY_FILETYPE_SYMLINK 7
union ext4_directory_entry_ll_internal {
- uint8_t name_length_high; /* Higher 8 bits of name length */
- uint8_t inode_type; /* Type of referenced inode (in rev >= 0.5) */
+ uint8_t name_length_high; /* Higher 8 bits of name length */
+ uint8_t inode_type; /* Type of referenced inode (in rev >= 0.5) */
} __attribute__((packed));
/**
* Linked list directory entry structure
*/
struct ext4_directory_entry_ll {
- uint32_t inode; /* I-node for the entry */
- uint16_t entry_length; /* Distance to the next directory entry */
- uint8_t name_length; /* Lower 8 bits of name length */
+ uint32_t inode; /* I-node for the entry */
+ uint16_t entry_length; /* Distance to the next directory entry */
+ uint8_t name_length; /* Lower 8 bits of name length */
- union ext4_directory_entry_ll_internal in;
+ union ext4_directory_entry_ll_internal in;
- uint8_t name[EXT4_DIRECTORY_FILENAME_LEN]; /* Entry name */
+ uint8_t name[EXT4_DIRECTORY_FILENAME_LEN]; /* Entry name */
} __attribute__((packed));
struct ext4_directory_iterator {
- struct ext4_inode_ref *inode_ref;
- struct ext4_block current_block;
- uint64_t current_offset;
- struct ext4_directory_entry_ll *current;
+ struct ext4_inode_ref *inode_ref;
+ struct ext4_block current_block;
+ uint64_t current_offset;
+ struct ext4_directory_entry_ll *current;
};
struct ext4_directory_search_result {
- struct ext4_block block;
- struct ext4_directory_entry_ll *dentry;
+ struct ext4_block block;
+ struct ext4_directory_entry_ll *dentry;
};
/* Structures for indexed directory */
struct ext4_directory_dx_countlimit {
- uint16_t limit;
- uint16_t count;
+ uint16_t limit;
+ uint16_t count;
};
struct ext4_directory_dx_dot_entry {
- uint32_t inode;
- uint16_t entry_length;
- uint8_t name_length;
- uint8_t inode_type;
- uint8_t name[4];
+ uint32_t inode;
+ uint16_t entry_length;
+ uint8_t name_length;
+ uint8_t inode_type;
+ uint8_t name[4];
};
struct ext4_directory_dx_root_info {
- uint32_t reserved_zero;
- uint8_t hash_version;
- uint8_t info_length;
- uint8_t indirect_levels;
- uint8_t unused_flags;
+ uint32_t reserved_zero;
+ uint8_t hash_version;
+ uint8_t info_length;
+ uint8_t indirect_levels;
+ uint8_t unused_flags;
};
struct ext4_directory_dx_entry {
- uint32_t hash;
- uint32_t block;
+ uint32_t hash;
+ uint32_t block;
};
struct ext4_directory_dx_root {
- struct ext4_directory_dx_dot_entry dots[2];
- struct ext4_directory_dx_root_info info;
- struct ext4_directory_dx_entry entries[];
+ struct ext4_directory_dx_dot_entry dots[2];
+ struct ext4_directory_dx_root_info info;
+ struct ext4_directory_dx_entry entries[];
};
struct ext4_fake_directory_entry {
- uint32_t inode;
- uint16_t entry_length;
- uint8_t name_length;
- uint8_t inode_type;
+ uint32_t inode;
+ uint16_t entry_length;
+ uint8_t name_length;
+ uint8_t inode_type;
};
struct ext4_directory_dx_node {
- struct ext4_fake_directory_entry fake;
- struct ext4_directory_dx_entry entries[];
+ struct ext4_fake_directory_entry fake;
+ struct ext4_directory_dx_entry entries[];
};
struct ext4_directory_dx_block {
- struct ext4_block block;
- struct ext4_directory_dx_entry *entries;
- struct ext4_directory_dx_entry *position;
+ struct ext4_block block;
+ struct ext4_directory_dx_entry *entries;
+ struct ext4_directory_dx_entry *position;
};
#define EXT4_ERR_BAD_DX_DIR (-25000)
* It's used at the bottom of the tree.
*/
struct ext4_extent {
- uint32_t first_block; /* First logical block extent covers */
- uint16_t block_count; /* Number of blocks covered by extent */
- uint16_t start_hi; /* High 16 bits of physical block */
- uint32_t start_lo; /* Low 32 bits of physical block */
+ uint32_t first_block; /* First logical block extent covers */
+ uint16_t block_count; /* Number of blocks covered by extent */
+ uint16_t start_hi; /* High 16 bits of physical block */
+ uint32_t start_lo; /* Low 32 bits of physical block */
};
/*
* It's used at all the levels except the bottom.
*/
struct ext4_extent_index {
- uint32_t first_block; /* Index covers logical blocks from 'block' */
-
- /**
- * Pointer to the physical block of the next
- * level. leaf or next index could be there
- * high 16 bits of physical block
- */
- uint32_t leaf_lo;
- uint16_t leaf_hi;
- uint16_t padding;
+ uint32_t first_block; /* Index covers logical blocks from 'block' */
+
+ /**
+ * Pointer to the physical block of the next
+ * level. leaf or next index could be there
+ * high 16 bits of physical block
+ */
+ uint32_t leaf_lo;
+ uint16_t leaf_hi;
+ uint16_t padding;
};
/*
* Each block (leaves and indexes), even inode-stored has header.
*/
struct ext4_extent_header {
- uint16_t magic;
- uint16_t entries_count; /* Number of valid entries */
- uint16_t max_entries_count; /* Capacity of store in entries */
- uint16_t depth; /* Has tree real underlying blocks? */
- uint32_t generation; /* generation of the tree */
+ uint16_t magic;
+ uint16_t entries_count; /* Number of valid entries */
+ uint16_t max_entries_count; /* Capacity of store in entries */
+ uint16_t depth; /* Has tree real underlying blocks? */
+ uint32_t generation; /* generation of the tree */
};
struct ext4_extent_path {
- struct ext4_block block;
- uint16_t depth;
- struct ext4_extent_header *header;
- struct ext4_extent_index *index;
- struct ext4_extent *extent;
+ struct ext4_block block;
+ uint16_t depth;
+ struct ext4_extent_header *header;
+ struct ext4_extent_index *index;
+ struct ext4_extent *extent;
};
#define EXT4_EXTENT_MAGIC 0xF30A
#define EXT4_EXTENT_FIRST(header) \
- ((struct ext4_extent *)(((char *)(header)) + \
- sizeof(struct ext4_extent_header)))
+ ((struct ext4_extent *)(((char *)(header)) + \
+ sizeof(struct ext4_extent_header)))
#define EXT4_EXTENT_FIRST_INDEX(header) \
- ((struct ext4_extent_index *)(((char *)(header)) + \
- sizeof(struct ext4_extent_header)))
+ ((struct ext4_extent_index *)(((char *)(header)) + \
+ sizeof(struct ext4_extent_header)))
/* EXT3 HTree directory indexing */
#define EXT2_HTREE_LEGACY 0
#define EXT2_HTREE_EOF 0x7FFFFFFFUL
struct ext4_hash_info {
- uint32_t hash;
- uint32_t minor_hash;
- uint32_t hash_version;
- const uint32_t *seed;
+ uint32_t hash;
+ uint32_t minor_hash;
+ uint32_t hash_version;
+ const uint32_t *seed;
};
/*****************************************************************************/
#ifdef CONFIG_BIG_ENDIAN
static inline uint64_t to_le64(uint64_t n)
{
- return ((n & 0xff) << 56) | ((n & 0xff00) << 40) | ((n & 0xff0000) << 24) |
- ((n & 0xff000000LL) << 8) | ((n & 0xff00000000LL) >> 8) |
- ((n & 0xff0000000000LL) >> 24) | ((n & 0xff000000000000LL) >> 40) |
- ((n & 0xff00000000000000LL) >> 56);
+ return ((n & 0xff) << 56) | ((n & 0xff00) << 40) |
+ ((n & 0xff0000) << 24) | ((n & 0xff000000LL) << 8) |
+ ((n & 0xff00000000LL) >> 8) | ((n & 0xff0000000000LL) >> 24) |
+ ((n & 0xff000000000000LL) >> 40) |
+ ((n & 0xff00000000000000LL) >> 56);
}
static inline uint32_t to_le32(uint32_t n)
{
- return ((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) |
- ((n & 0xff000000) >> 24);
+ return ((n & 0xff) << 24) | ((n & 0xff00) << 8) |
+ ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24);
}
static inline uint16_t to_le16(uint16_t n)
{
- return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
+ return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}
#else
#define ext4_get8(s, f) (s)->f
#define ext4_set32(s, f, v) \
- do { \
- (s)->f = to_le32(v); \
- } while (0)
+ do { \
+ (s)->f = to_le32(v); \
+ } while (0)
#define ext4_set16(s, f, v) \
- do { \
- (s)->f = to_le16(v); \
- } while (0)
+ do { \
+ (s)->f = to_le16(v); \
+ } while (0)
#define ext4_set8 \
- (s, f, v) do { (s)->f = (v); } \
- while (0)
+ (s, f, v) do { (s)->f = (v); } \
+ while (0)
#endif /* EXT4_TYPES_H_ */