|

楼主 |
发表于 2024-1-8 08:15:39
|
显示全部楼层
关于固态存储设备TRIM功能的一些研究
- * ext4_trim_fs() -- trim ioctl handle function
- * @sb: superblock for filesystem
- * @range: fstrim_range structure
- *
- * start: First Byte to trim
- * len: number of Bytes to trim from start
- * minlen: minimum extent length in Bytes
- * ext4_trim_fs goes through all allocation groups containing Bytes from
- * start to start+len. For each such a group ext4_trim_all_free function
- * is invoked to trim all free space.
- */
- int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range);
复制代码 有注释省得看代码了 内核将指定(len)文件系统的区域进行了扫描,并且调用ext4_trim_all_free函数:
- /**
- * ext4_trim_all_free -- function to trim all free space in alloc. group
- * @sb: super block for file system
- * @group: group to be trimmed
- * @start: first group block to examine
- * @max: last group block to examine
- * @minblocks: minimum extent block count
- *
- * ext4_trim_all_free walks through group's buddy bitmap searching for free
- * extents. When the free block is found, ext4_trim_extent is called to TRIM
- * the extent.
- *
- *
- * ext4_trim_all_free walks through group's block bitmap searching for free
- * extents. When the free extent is found, mark it as used in group buddy
- * bitmap. Then issue a TRIM command on this extent and free the extent in
- * the group buddy bitmap. This is done until whole group is scanned.
- */
- static ext4_grpblk_t
- ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
- ext4_grpblk_t start, ext4_grpblk_t max,
- ext4_grpblk_t minblocks);
复制代码 文件系统将无用块标记,然后向磁盘发送trim命令来清除这些块的数据。楼主是mmc设备,所以追溯到mmc设备的驱动实现:
- static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
- {
- struct mmc_blk_data *md = mq->blkdata;
- struct mmc_card *card = md->queue.card;
- unsigned int from, nr;
- int err = 0, type = MMC_BLK_DISCARD;
- blk_status_t status = BLK_STS_OK;
- if (!mmc_can_erase(card)) {
- status = BLK_STS_NOTSUPP;
- goto fail;
- }
- from = blk_rq_pos(req);
- nr = blk_rq_sectors(req);
- do {
- unsigned int erase_arg = card->erase_arg;
- if (mmc_card_broken_sd_discard(card))
- erase_arg = SD_ERASE_ARG;
- err = 0;
- if (card->quirks & MMC_QUIRK_INAND_CMD38) {
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- INAND_CMD38_ARG_EXT_CSD,
- card->erase_arg == MMC_TRIM_ARG ?
- INAND_CMD38_ARG_TRIM :
- INAND_CMD38_ARG_ERASE,
- card->ext_csd.generic_cmd6_time);
- }
- if (!err)
- err = mmc_erase(card, from, nr, erase_arg);
- } while (err == -EIO && !mmc_blk_reset(md, card->host, type));
- if (err)
- status = BLK_STS_IOERR;
- else
- mmc_blk_reset_success(md, type);
- fail:
- blk_mq_end_request(req, status);
- }
复制代码 这里就可以发现是发送了INAND_CMD38_ARG_TRIM或者是INAND_CMD38_ARG_ERASE命令给mmc设备,然后mmc进入内置固件的TRIM处理逻辑。而固件这玩意儿又没有源码,所以最多只能追溯到这里了。
然后简单验证一下TRIM:
先随便搞一个二进制文件:
- dd if=/dev/urandom of=test.bin bs=1 count=16
- 输入了 16+0 块记录
- 输出了 16+0 块记录
- 16 字节已复制,0.000342409 s,46.7 kB/s
复制代码
生成了一个test.bin,用hexdump看一看内容:
- hexdump -C test.bin
- 00000000 3c 73 d1 0e 6f 23 54 d1 6d 51 68 88 c3 24 26 49 |<s..o#T.mQh..$&I|
- 00000010
复制代码- sudo hdparm --fibmap test.bin
- test.bin:
- filesystem blocksize 4096, begins at LBA 2158592; assuming 512 byte sectors.
- byte_offset begin_LBA end_LBA sectors
- 0 6815240 6815247 8
复制代码- hexdump -C --skip 3489402880 --length 16 /dev/mmcblk0
- cffc1000 3c 73 d1 0e 6f 23 54 d1 6d 51 68 88 c3 24 26 49 |<s..o#T.mQh..$&I|
- cffc1010
复制代码
再次使用hexdump读取相应位置的数据:
- hexdump -C --skip 3489402880 --length 16 /dev/mmcblk0
- cffc1000 3c 73 d1 0e 6f 23 54 d1 6d 51 68 88 c3 24 26 49 |<s..o#T.mQh..$&I|
- cffc1010
复制代码
可以看见,数据还在原位。大概是因为mmc设备的原因吧,我用手机测试,两小时就把删掉的文件块给TRIM了。
欢迎大家探讨
|
|