ATA TRIM命令是文件系统用来通知设备哪些逻辑地址不再被占用,可以被设备回收为空闲空间,在ATA命令集中,TRIM命令只是DATAMANAGEMENT SET(DMS)命令的一个子命令,DMS命令是专门用来做设备优化的(The DATA SET MANAGEMENT command provides information for deviceoptimization (e.g., file system information),如图1所示,当DMS的feature属性最低位置1,发送的就是TRIM命令。
TRIM命令的传送过程中,通过入口的方式传递需要告诉设备的LBA地址,比如需要告诉设备第11至18个block可以回收,在DMA的写buffer中共需8个字节,高16bit为len值8, 低48位为LBA起始地址11。 每个入口的长度因为用2个字节16bits表示,然后全0的reserved,所以每个入口最多可以表示65535个blocks,如需单次通知设备更多地址,就会再相应增加一个入口。

图1. DMS命令ATA格式
发送ata_trim命令的代码如下,需要把它放到一个和内核一起编译的模块中,通过/proc/变量的值输入进行调用。 感兴趣的话,可以一起讨论喔
int ata_trim(uint block, uint n_block)
{
struct ata_queued_cmd *qc=NULL;
struct ata_taskfile *tf =NULL;
struct sg_table *table=kmalloc(sizeof(struct sg_table),GFP_ATOMIC);
int rc=0, nents=1; //entry(sg list) number of scatter/gathering list in sg_table
struct page *pg_pt;
u32 size;
void *buf; //transfer buffer to send lba addresses...
if(ata_dev_lookup())
goto error_exit;
/*allocate an ata cmd structure from the ata port*/
qc = ata_qc_new_init(dev);
if(unlikely(!qc))
goto error_exit;
/*allocate sg_table and sg list*/
allocate_mempool();
rc = __sg_alloc_table(table, nents, SCSI_MAX_SG_SEGMENTS,GFP_ATOMIC, scsi_sg_alloc);
if (unlikely(rc)){
__sg_free_table(table, SCSI_MAX_SG_SEGMENTS,scsi_sg_free);
goto error_exit;
}
pg_pt=alloc_pages(GFP_ATOMIC,0); //allocate 1page: 4k dataspace...
if(!pg_pt)
goto error_exit;
printk("\nStarting block is : %lu , blocks count is : %d \n\n", block, n_block);
sg_set_page(table->sgl, pg_pt, 8, 0); // 8 bytes for 1 trim entry
table->nents=1;
table->orig_nents=1;
ata_sg_init(qc,table->sgl,1);
qc->scsidone=my_scsidone;
qc->complete_fn=my_ata_scsi_qc_complete;
//orignally for write_same of multiple areas... now to transfer only one LBA...
buf = page_address(sg_page(table->sgl));
if(!buf)
goto error_exit;
//size is the used bytes and it is the size for DMA to transfer
size = ata_set_lba_range_entries(buf, 4096, block, n_block);
qc->dma_dir=DMA_TO_DEVICE;
qc->nbytes=size; //data size in bytes to be transfered
tf=&qc->tf;
tf->protocol = ATA_PROT_DMA;
tf->hob_feature = 0;
tf->feature = ATA_DSM_TRIM;
tf->hob_nsect = (size / 512) >> 8;
tf->nsect = size / 512;
tf->command = ATA_CMD_DSM;
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 |
ATA_TFLAG_WRITE;
if(!qc->sg || !qc->n_elem || !qc->nbytes)
goto error_exit;
ata_qc_issue(qc);
mdelay(800);
qc_error_disp(qc->err_mask);
return 0;
error_exit:
printk("\n\nTO client--------------Getting Resources failed----------------- \n\n");
return 1;
}

本文探讨了ATA TRIM命令的作用,它用于通知设备哪些逻辑地址已释放,以便设备能回收为空闲空间。TRIM是DATA SET MANAGEMENT (DMS)命令的一部分,用于设备优化。内容涉及TRIM命令的传输细节,包括如何通过入口传递LBA地址信息,以及如何构建发送ATA_TRIM命令的代码。文章适合对存储系统优化感兴趣的读者。
463

被折叠的 条评论
为什么被折叠?



