码迷,mamicode.com
首页 > 其他好文 > 详细

storage trim or discard or unmap

时间:2015-07-26 06:21:50      阅读:947      评论:0      收藏:0      [点我收藏+]

标签:trim or discard or unmap

trim 是ata 的一个指令,对应scsi指令是unmap,那么什么是trim呢?

trim就是OS发送给ssd  or other type controller, 告诉它哪些数据对应的LBA地址是无效的。之后trim就不做什么其他操作了。后续的事情由GC来进行。

Secure erase是一则ATA安全擦除命令,用户清除磁盘上的所有数据。这则命令可以理解为主控的返厂状态命令。 


trim对于传统磁盘来讲没有什么意义,因为磁介质是可以覆盖写的。而在flash stroage上,由于nand一个天生的特性,写之前必须擦干净,也就是要释放掉flash里面的电子。

所以trim是flash必须支持的特性。


在用户态如果不发起trim,那么flash设备是不会trim掉相应的数据,只有LBA地址重复时,才会标记数据为脏。那么对于块设备的使用者,可以明确哪些块不使用时,可以直接把数据删除掉,而不必等着LBA重复地址写,标记为脏块。

带来的好处是,用户不要的数据,及时被清理掉。这样有效数据块减少,GC的效率也提高了。

这样OP空间及时释放,有利于提高性能。(空间及时释放,OP并不是单独分离的空间)

SSD是以块为单位进行擦除的,大小通常是512KB,这意味着如果某个块上的一个页面发生了变化,整个SSD都需要重写,重写过程需要经历漫长的“读-修改-擦除-写”周期,“读”通常指的是将块上的所有数据读入到缓存中,接着将“修改的”数据和缓存中已有的数据合并,然后“擦除”那个块上的全部数据,最后将缓存中的新数据“回写”到已被擦除的块上。

SSD的擦除速度要比读取速度慢好多倍,导致整个“读-修改-擦除-写”周期花费的总时间变长。更糟糕的是,“读-修改-擦除-写”周期会产生一个所谓的写放大系数,它指的是即使是块上单个页面发生变化或更新,也会导致使用额外的写周期,理想情况下,写放大系数应等于1,即向存储介质写入数据时,不需要额外的写周期,如果写放大系数大于1,则意味着向存储介质写入数据时,不止发生一次写入操作。

一种技术叫做写合并,控制器将多个写操作收集到一起,然后一次性将这些数据写入到SSD的块上。合并的目标是将多个小的写操作合并成一个大的写操作,大多数时候,相邻页面的数据会同时发生变化,这些页面很可能属于同一个文件。通过写合并技术,写放大系数大大减小了,SSD的性能也显著提高了,但这也与发送数据的方式,以及数据块是否同属于同一个文件,或是否在同一时间发生变化有关。



当你在电脑里删除一个文件的时候,操作系统并不会真正的去删除它。操作系统只是把这个文件的地址标记为“空”,让它可以被再次使用,这表示这个文件所占的地址已经“无效”

对于linux的文件系统,可能仅仅把inode节点释放掉。也可能只是仅仅标记为可回收的inode。


对于块设备的使用者有两种情况,直接操作块设备,另一种是通过文件系统间接来操作。

对于块设备,可以通过ioctl的方式,发送trim。

对于ext4文件系统通过mount时加入discard参数,当用户删除文件时,会自动触发trim操作。

另外文件系统格式化时也会trim。

那么对于trim操作,flash firmware真的就是立即去擦除吗?这个不一定,和其实现的机制有关系。


另外一个问题是,trim一次的大小是什么?


这设计到nand操作的块大小,和擦除块大小的不同。

SSD:一个page为4K或8K或16K,将多个page作为一个block来使用。一个block一般为512K到1M。一些block构成一个plane。一些plane构成die。

读写以page为单位。擦除以block为单位,把所有的cell都变为1.


对于scsi块设备,sg3_utils工具可以发送trim

scsi trim:

dd if=./sg_requests.c of=/dev/sdb //表示写入一些数据

hexdump -C -n 512 /dev/sdb //表示已16进制的方式读取写入的数据,读取512byte

./sg_unmap --lba=0x0 --num=1 /dev/sdb //从lba 0开始擦除一个sector,当然nand是没有扇区的概念的,完全是为传统磁盘里的概念

hexdump -C -n 512 /dev/sdb //查看刚才写入的数据,这里可能为全0,也可能不是,有的实现机制是重启os,flash擦除。


关于hexdump的说明

使用hexdump以16进制查看内容

有时候需要查看一些二进制文件的内容,比如二进制文件中包含的某些字符串。这个时候可以用hexdump工具看查看。
常用参数: hexdump -C -n length -s skip file_name
-C 定义了导出的格式,-s skip 指定了从文件头跳过多少字节,或者说是偏移量,默认是十进制。如果是0x开头,则是十六进制。-n 指定了导出多少长度



那么我们来看一下trim在linux内核里是怎么实现的呢?


看一下sg3 sg_unmap是如何发送trim cmd的。

ioctl(fd, SG_IO, &ptp->io_hdr)


Hdparm 可以使用下面的参数发送trim给ssd

 --trim-sector-ranges        Tell SSD firmware to discard unneeded data sectors: lba:count ..

 --trim-sector-ranges-stdin  Same as above, but reads lba:count pairs from stdin


看一下FIO是如何发送trim的

DDIR_TRIM

通过ioengine发送trim do_io_u_trim(td, io_u)

static inline int os_trim(int fd, unsigned long long start,
  unsigned long long len)
{
uint64_t range[2];
range[0] = start;
range[1] = len;
if (!ioctl(fd, BLKDISCARD, range))
return 0;
return errno;
}

通过block ioctl发送到dev中。然后调用到blkdev_ioctl中。

case BLKDISCARD:
case BLKSECDISCARD: {
uint64_t range[2];
if (!(mode & FMODE_WRITE))
return -EBADF;
if (copy_from_user(range, (void __user *)arg, sizeof(range)))
return -EFAULT;
return blk_ioctl_discard(bdev, range[0], range[1],
 cmd == BLKSECDISCARD);
}

在blkdev_issue_discard中封装一个bio,send到块设备上。

本文出自 “Storage” 博客,请务必保留此出处http://xmwang.blog.51cto.com/9889672/1678350

storage trim or discard or unmap

标签:trim or discard or unmap

原文地址:http://xmwang.blog.51cto.com/9889672/1678350

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!