forked from RamezesDong/ssdsim-1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pagemap.c
1434 lines (1264 loc) · 72.2 KB
/
pagemap.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*****************************************************************************************************************************
This project was supported by the National Basic Research 973 Program of China under Grant No.2011CB302301
Huazhong University of Science and Technology (HUST) Wuhan National Laboratory for Optoelectronics
FileName: pagemap.h
Author: Hu Yang Version: 2.1 Date:2011/12/02
Description:
History:
<contributor> <time> <version> <desc> <e-mail>
Yang Hu 2009/09/25 1.0 Creat SSDsim [email protected]
2010/05/01 2.x Change
Zhiming Zhu 2011/07/01 2.0 Change [email protected]
Shuangwu Zhang 2011/11/01 2.1 Change [email protected]
Chao Ren 2011/07/01 2.0 Change [email protected]
Hao Luo 2011/01/01 2.0 Change [email protected]
*****************************************************************************************************************************/
#define _CRTDBG_MAP_ALLOC
#include "pagemap.h"
/************************************************
*断言,当打开文件失败时,输出“open 文件名 error”
*************************************************/
void file_assert(int error,char *s)
{
if(error == 0) return;
printf("open %s error\n",s);
getchar();
exit(-1);
}
/*****************************************************
*断言,当申请内存空间失败时,输出“malloc 变量名 error”
******************************************************/
void alloc_assert(void *p,char *s)//断言
{
if(p!=NULL) return;
printf("malloc %s error\n",s);
getchar();
exit(-1);
}
/*********************************************************************************
*断言
*A,读到的time_t,device,lsn,size,ope都<0时,输出“trace error:.....”
*B,读到的time_t,device,lsn,size,ope都=0时,输出“probable read a blank line”
**********************************************************************************/
void trace_assert(int64_t time_t,int device,unsigned int lsn,int size,int ope)//断言
{
if(time_t <0 || device < 0 || lsn < 0 || size < 0 || ope < 0)
{
printf("trace error:%lld %d %d %d %d\n",time_t,device,lsn,size,ope);
getchar();
exit(-1);
}
if(time_t == 0 && device == 0 && lsn == 0 && size == 0 && ope == 0)
{
printf("probable read a blank line\n");
getchar();
}
}
/************************************************************************************
*函数的功能是根据物理页号ppn查找该物理页所在的channel,chip,die,plane,block,page
*得到的channel,chip,die,plane,block,page放在结构location中并作为返回值
*************************************************************************************/
struct local *find_location(struct ssd_info *ssd,unsigned int ppn)
{
struct local *location=NULL;
unsigned int i=0;
int pn,ppn_value=ppn;
int page_plane=0,page_die=0,page_chip=0,page_channel=0;
pn = ppn;
#ifdef DEBUG
printf("enter find_location\n");
#endif
location=(struct local *)malloc(sizeof(struct local));
alloc_assert(location,"location");
memset(location,0, sizeof(struct local));
page_plane=ssd->parameter->page_block*ssd->parameter->block_plane;
page_die=page_plane*ssd->parameter->plane_die;
page_chip=page_die*ssd->parameter->die_chip;
page_channel=page_chip*ssd->parameter->chip_channel[0];
/*******************************************************************************
*page_channel是一个channel中page的数目, ppn/page_channel就得到了在哪个channel中
*用同样的办法可以得到chip,die,plane,block,page
********************************************************************************/
location->channel = ppn/page_channel;
location->chip = (ppn%page_channel)/page_chip;
location->die = ((ppn%page_channel)%page_chip)/page_die;
location->plane = (((ppn%page_channel)%page_chip)%page_die)/page_plane;
location->block = ((((ppn%page_channel)%page_chip)%page_die)%page_plane)/ssd->parameter->page_block;
location->page = (((((ppn%page_channel)%page_chip)%page_die)%page_plane)%ssd->parameter->page_block)%ssd->parameter->page_block;
return location;
}
/*****************************************************************************
*这个函数的功能是根据参数channel,chip,die,plane,block,page,找到该物理页号
*函数的返回值就是这个物理页号
******************************************************************************/
unsigned int find_ppn(struct ssd_info * ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,unsigned int block,unsigned int page)
{
unsigned int ppn=0;
unsigned int i=0;
int page_plane=0,page_die=0,page_chip=0;
int page_channel[100]; /*这个数组存放的是每个channel的page数目*/
#ifdef DEBUG
printf("enter find_psn,channel:%d, chip:%d, die:%d, plane:%d, block:%d, page:%d\n",channel,chip,die,plane,block,page);
#endif
/*********************************************
*计算出plane,die,chip,channel中的page的数目
**********************************************/
page_plane=ssd->parameter->page_block*ssd->parameter->block_plane;
page_die=page_plane*ssd->parameter->plane_die;
page_chip=page_die*ssd->parameter->die_chip;
while(i<ssd->parameter->channel_number)
{
page_channel[i]=ssd->parameter->chip_channel[i]*page_chip;
i++;
}
/****************************************************************************
*计算物理页号ppn,ppn是channel,chip,die,plane,block,page中page个数的总和
*****************************************************************************/
i=0;
while(i<channel)
{
ppn=ppn+page_channel[i];
i++;
}
ppn=ppn+page_chip*chip+page_die*die+page_plane*plane+block*ssd->parameter->page_block+page;
return ppn;
}
/********************************
*函数功能是获得一个读子请求的状态
*********************************/
int set_entry_state(struct ssd_info *ssd,unsigned int lsn,unsigned int size)
{
int temp,state,move;
temp=~(0xffffffff<<size);
move=lsn%ssd->parameter->subpage_page;
state=temp<<move;
return state;
}
/**************************************************
*读请求预处理函数,当读请求所读得页里面没有数据时,
*需要预处理网该页里面写数据,以保证能读到数据
***************************************************/
struct ssd_info *pre_process_page(struct ssd_info *ssd)
{
int fl=0;
unsigned int device,lsn,size,ope,lpn,full_page;
unsigned int largest_lsn,sub_size,ppn,add_size=0;
unsigned int i=0,j,k;
int map_entry_new,map_entry_old,modify;
int flag=0;
char buffer_request[200];
struct local *location;
int64_t time;
printf("\n");
printf("begin pre_process_page.................\n");
ssd->tracefile=fopen(ssd->tracefilename,"r");
if(ssd->tracefile == NULL ) /*打开trace文件从中读取请求*/
{
printf("the trace file can't open\n");
return NULL;
}
full_page=~(0xffffffff<<(ssd->parameter->subpage_page));
/*计算出这个ssd的最大逻辑扇区号*/
largest_lsn=(unsigned int )((ssd->parameter->chip_num*ssd->parameter->die_chip*ssd->parameter->plane_die*ssd->parameter->block_plane*ssd->parameter->page_block*ssd->parameter->subpage_page)*(1-ssd->parameter->overprovide));
while(fgets(buffer_request,200,ssd->tracefile))
{
sscanf(buffer_request,"%lld %d %d %d %d",&time,&device,&lsn,&size,&ope);
fl++;
trace_assert(time,device,lsn,size,ope); /*断言,当读到的time,device,lsn,size,ope不合法时就会处理*/
add_size=0; /*add_size是这个请求已经预处理的大小*/
if(ope==1) /*这里只是读请求的预处理,需要提前将相应位置的信息进行相应修改*/
{
while(add_size<size)
{
lsn=lsn%largest_lsn; /*防止获得的lsn比最大的lsn还大*/
sub_size=ssd->parameter->subpage_page-(lsn%ssd->parameter->subpage_page);
if(add_size+sub_size>=size) /*只有当一个请求的大小小于一个page的大小时或者是处理一个请求的最后一个page时会出现这种情况*/
{
sub_size=size-add_size;
add_size+=sub_size;
}
if((sub_size>ssd->parameter->subpage_page)||(add_size>size))/*当预处理一个子大小时,这个大小大于一个page或是已经处理的大小大于size就报错*/
{
printf("pre_process sub_size:%d\n",sub_size);
}
/*******************************************************************************************************
*利用逻辑扇区号lsn计算出逻辑页号lpn
*判断这个dram中映射表map中在lpn位置的状态
*A,这个状态==0,表示以前没有写过,现在需要直接将ub_size大小的子页写进去写进去
*B,这个状态>0,表示,以前有写过,这需要进一步比较状态,因为新写的状态可以与以前的状态有重叠的扇区的地方
********************************************************************************************************/
lpn=lsn/ssd->parameter->subpage_page;
if(ssd->dram->map->map_entry[lpn].state==0) /*状态为0的情况*/
{
/**************************************************************
*获得利用get_ppn_for_pre_process函数获得ppn,再得到location
*修改ssd的相关参数,dram的映射表map,以及location下的page的状态
***************************************************************/
ppn=get_ppn_for_pre_process(ssd,lsn);
location=find_location(ssd,ppn);
ssd->program_count++;
ssd->channel_head[location->channel].program_count++;
ssd->channel_head[location->channel].chip_head[location->chip].program_count++;
ssd->dram->map->map_entry[lpn].pn=ppn;
ssd->dram->map->map_entry[lpn].state=set_entry_state(ssd,lsn,sub_size); //0001
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn=lpn;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state=ssd->dram->map->map_entry[lpn].state;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state=((~ssd->dram->map->map_entry[lpn].state)&full_page);
free(location);
location=NULL;
}//if(ssd->dram->map->map_entry[lpn].state==0)
else if(ssd->dram->map->map_entry[lpn].state>0) /*状态不为0的情况*/
{
map_entry_new=set_entry_state(ssd,lsn,sub_size); /*得到新的状态,并与原来的状态相或的到一个状态*/
map_entry_old=ssd->dram->map->map_entry[lpn].state;
modify=map_entry_new|map_entry_old;
ppn=ssd->dram->map->map_entry[lpn].pn;
location=find_location(ssd,ppn);
ssd->program_count++;
ssd->channel_head[location->channel].program_count++;
ssd->channel_head[location->channel].chip_head[location->chip].program_count++;
ssd->dram->map->map_entry[lsn/ssd->parameter->subpage_page].state=modify;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state=modify;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state=((~modify)&full_page);
free(location);
location=NULL;
}//else if(ssd->dram->map->map_entry[lpn].state>0)
lsn=lsn+sub_size; /*下个子请求的起始位置*/
add_size+=sub_size; /*已经处理了的add_size大小变化*/
}//while(add_size<size)
}//if(ope==1)
}
printf("\n");
printf("pre_process is complete!\n");
fclose(ssd->tracefile);
for(i=0;i<ssd->parameter->channel_number;i++)
for(j=0;j<ssd->parameter->die_chip;j++)
for(k=0;k<ssd->parameter->plane_die;k++)
{
fprintf(ssd->outputfile,"chip:%d,die:%d,plane:%d have free page: %d\n",i,j,k,ssd->channel_head[i].chip_head[0].die_head[j].plane_head[k].free_page);
fflush(ssd->outputfile);
}
return ssd;
}
/**************************************
*函数功能是为预处理函数获取物理页号ppn
*获取页号分为动态获取和静态获取
**************************************/
unsigned int get_ppn_for_pre_process(struct ssd_info *ssd,unsigned int lsn)
{
unsigned int channel=0,chip=0,die=0,plane=0;
unsigned int ppn,lpn;
unsigned int active_block;
unsigned int channel_num=0,chip_num=0,die_num=0,plane_num=0;
#ifdef DEBUG
printf("enter get_psn_for_pre_process\n");
#endif
channel_num=ssd->parameter->channel_number;
chip_num=ssd->parameter->chip_channel[0];
die_num=ssd->parameter->die_chip;
plane_num=ssd->parameter->plane_die;
lpn=lsn/ssd->parameter->subpage_page;
if (ssd->parameter->allocation_scheme==0) /*动态方式下获取ppn*/
{
if (ssd->parameter->dynamic_allocation==0) /*表示全动态方式下,也就是channel,chip,die,plane,block等都是动态分配*/
{
channel=ssd->token;
ssd->token=(ssd->token+1)%ssd->parameter->channel_number;
chip=ssd->channel_head[channel].token;
ssd->channel_head[channel].token=(chip+1)%ssd->parameter->chip_channel[0];
die=ssd->channel_head[channel].chip_head[chip].token;
ssd->channel_head[channel].chip_head[chip].token=(die+1)%ssd->parameter->die_chip;
plane=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane+1)%ssd->parameter->plane_die;
}
else if (ssd->parameter->dynamic_allocation==1) /*表示半动态方式,channel静态给出,package,die,plane动态分配*/
{
channel=lpn%ssd->parameter->channel_number;
chip=ssd->channel_head[channel].token;
ssd->channel_head[channel].token=(chip+1)%ssd->parameter->chip_channel[0];
die=ssd->channel_head[channel].chip_head[chip].token;
ssd->channel_head[channel].chip_head[chip].token=(die+1)%ssd->parameter->die_chip;
plane=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane+1)%ssd->parameter->plane_die;
}
}
else if (ssd->parameter->allocation_scheme==1) /*表示静态分配,同时也有0,1,2,3,4,5这6中不同静态分配方式*/
{
switch (ssd->parameter->static_allocation)
{
case 0:
{
channel=(lpn/(plane_num*die_num*chip_num))%channel_num;
chip=lpn%chip_num;
die=(lpn/chip_num)%die_num;
plane=(lpn/(die_num*chip_num))%plane_num;
break;
}
case 1:
{
channel=lpn%channel_num;
chip=(lpn/channel_num)%chip_num;
die=(lpn/(chip_num*channel_num))%die_num;
plane=(lpn/(die_num*chip_num*channel_num))%plane_num;
break;
}
case 2:
{
channel=lpn%channel_num;
chip=(lpn/(plane_num*channel_num))%chip_num;
die=(lpn/(plane_num*chip_num*channel_num))%die_num;
plane=(lpn/channel_num)%plane_num;
break;
}
case 3:
{
channel=lpn%channel_num;
chip=(lpn/(die_num*channel_num))%chip_num;
die=(lpn/channel_num)%die_num;
plane=(lpn/(die_num*chip_num*channel_num))%plane_num;
break;
}
case 4:
{
channel=lpn%channel_num;
chip=(lpn/(plane_num*die_num*channel_num))%chip_num;
die=(lpn/(plane_num*channel_num))%die_num;
plane=(lpn/channel_num)%plane_num;
break;
}
case 5:
{
channel=lpn%channel_num;
chip=(lpn/(plane_num*die_num*channel_num))%chip_num;
die=(lpn/channel_num)%die_num;
plane=(lpn/(die_num*channel_num))%plane_num;
break;
}
default : return 0;
}
}
/******************************************************************************
*根据上述分配方法找到channel,chip,die,plane后,再在这个里面找到active_block
*接着获得ppn
******************************************************************************/
if(find_active_block(ssd,channel,chip,die,plane)==FAILURE)
{
printf("the read operation is expand the capacity of SSD\n");
return 0;
}
active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;
if(write_page(ssd,channel,chip,die,plane,active_block,&ppn)==ERROR)
{
return 0;
}
return ppn;
}
/***************************************************************************************************
*函数功能是在所给的channel,chip,die,plane里面找到一个active_block然后再在这个block里面找到一个页,
*再利用find_ppn找到ppn。
****************************************************************************************************/
struct ssd_info *get_ppn(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,struct sub_request *sub)
{
int old_ppn=-1;
unsigned int ppn,lpn,full_page;
unsigned int active_block;
unsigned int block;
unsigned int page,flag=0,flag1=0;
unsigned int old_state=0,state=0,copy_subpage=0;
struct local *location;
struct direct_erase *direct_erase_node,*new_direct_erase;
struct gc_operation *gc_node;
unsigned int i=0,j=0,k=0,l=0,m=0,n=0;
#ifdef DEBUG
printf("enter get_ppn,channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
#endif
full_page=~(0xffffffff<<(ssd->parameter->subpage_page));
lpn=sub->lpn;
/*************************************************************************************
*利用函数find_active_block在channel,chip,die,plane找到活跃block
*并且修改这个channel,chip,die,plane,active_block下的last_write_page和free_page_num
**************************************************************************************/
if(find_active_block(ssd,channel,chip,die,plane)==FAILURE)
{
printf("ERROR :there is no free page in channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
return ssd;
}
active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num--;
if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page>63)
{
printf("error! the last write page larger than 64!!\n");
while(1){}
}
block=active_block;
page=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page;
if(ssd->dram->map->map_entry[lpn].state==0) /*this is the first logical page*/
{
if(ssd->dram->map->map_entry[lpn].pn!=0)
{
printf("Error in get_ppn()\n");
}
ssd->dram->map->map_entry[lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
ssd->dram->map->map_entry[lpn].state=sub->state;
}
else /*这个逻辑页进行了更新,需要将原来的页置为失效*/
{
ppn=ssd->dram->map->map_entry[lpn].pn;
location=find_location(ssd,ppn);
if( ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn!=lpn)
{
printf("\nError in get_ppn()\n");
}
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state=0; /*表示某一页失效,同时标记valid和free状态都为0*/
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state=0; /*表示某一页失效,同时标记valid和free状态都为0*/
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn=0;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num++;
/*******************************************************************************************
*该block中全是invalid的页,可以直接删除,就在创建一个可擦除的节点,挂在location下的plane下面
********************************************************************************************/
if (ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num==ssd->parameter->page_block)
{
new_direct_erase=(struct direct_erase *)malloc(sizeof(struct direct_erase));
alloc_assert(new_direct_erase,"new_direct_erase");
memset(new_direct_erase,0, sizeof(struct direct_erase));
new_direct_erase->block=location->block;
new_direct_erase->next_node=NULL;
direct_erase_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
if (direct_erase_node==NULL)
{
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
}
else
{
new_direct_erase->next_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
}
}
free(location);
location=NULL;
ssd->dram->map->map_entry[lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
ssd->dram->map->map_entry[lpn].state=(ssd->dram->map->map_entry[lpn].state|sub->state);
}
sub->ppn=ssd->dram->map->map_entry[lpn].pn; /*修改sub子请求的ppn,location等变量*/
sub->location->channel=channel;
sub->location->chip=chip;
sub->location->die=die;
sub->location->plane=plane;
sub->location->block=active_block;
sub->location->page=page;
ssd->program_count++; /*修改ssd的program_count,free_page等变量*/
ssd->channel_head[channel].program_count++;
ssd->channel_head[channel].chip_head[chip].program_count++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].lpn=lpn;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].valid_state=sub->state;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].free_state=((~(sub->state))&full_page);
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].written_count++;
ssd->write_flash_count++;
if (ssd->parameter->active_write==0) /*如果没有主动策略,只采用gc_hard_threshold,并且无法中断GC过程*/
{ /*如果plane中的free_page的数目少于gc_hard_threshold所设定的阈值就产生gc操作*/
if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page<(ssd->parameter->page_block*ssd->parameter->block_plane*ssd->parameter->gc_hard_threshold))
{
gc_node=(struct gc_operation *)malloc(sizeof(struct gc_operation));
alloc_assert(gc_node,"gc_node");
memset(gc_node,0, sizeof(struct gc_operation));
gc_node->next_node=NULL;
gc_node->chip=chip;
gc_node->die=die;
gc_node->plane=plane;
gc_node->block=0xffffffff;
gc_node->page=0;
gc_node->state=GC_WAIT;
gc_node->priority=GC_UNINTERRUPT;
gc_node->next_node=ssd->channel_head[channel].gc_command;
ssd->channel_head[channel].gc_command=gc_node;
ssd->gc_request++;
}
}
return ssd;
}
/*****************************************************************************************
*这个函数功能是为gc操作寻找新的ppn,因为在gc操作中需要找到新的物理块存放原来物理块上的数据
*在gc中寻找新物理块的函数,不会引起循环的gc操作
******************************************************************************************/
unsigned int get_ppn_for_gc(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane)
{
unsigned int ppn;
unsigned int active_block,block,page;
#ifdef DEBUG
printf("enter get_ppn_for_gc,channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
#endif
if(find_active_block(ssd,channel,chip,die,plane)!=SUCCESS)
{
printf("\n\n Error int get_ppn_for_gc().\n");
return 0xffffffff;
}
active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num--;
if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page>63)
{
printf("error! the last write page larger than 64!!\n");
while(1){}
}
block=active_block;
page=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page;
ppn=find_ppn(ssd,channel,chip,die,plane,block,page);
ssd->program_count++;
ssd->channel_head[channel].program_count++;
ssd->channel_head[channel].chip_head[chip].program_count++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].written_count++;
ssd->write_flash_count++;
return ppn;
}
/*********************************************************************************************************************
* 朱志明 于2011年7月28日修改
*函数的功能就是erase_operation擦除操作,把channel,chip,die,plane下的block擦除掉
*也就是初始化这个block的相关参数,eg:free_page_num=page_block,invalid_page_num=0,last_write_page=-1,erase_count++
*还有这个block下面的每个page的相关参数也要修改。
*********************************************************************************************************************/
Status erase_operation(struct ssd_info * ssd,unsigned int channel ,unsigned int chip ,unsigned int die ,unsigned int plane ,unsigned int block)
{
unsigned int i=0;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].free_page_num=ssd->parameter->page_block;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].invalid_page_num=0;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].last_write_page=-1;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].erase_count++;
for (i=0;i<ssd->parameter->page_block;i++)
{
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[i].free_state=PG_SUB;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[i].valid_state=0;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[i].lpn=-1;
}
ssd->erase_count++;
ssd->channel_head[channel].erase_count++;
ssd->channel_head[channel].chip_head[chip].erase_count++;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page+=ssd->parameter->page_block;
return SUCCESS;
}
/**************************************************************************************
*这个函数的功能是处理INTERLEAVE_TWO_PLANE,INTERLEAVE,TWO_PLANE,NORMAL下的擦除的操作。
***************************************************************************************/
Status erase_planes(struct ssd_info * ssd, unsigned int channel, unsigned int chip, unsigned int die1, unsigned int plane1,unsigned int command)
{
unsigned int die=0;
unsigned int plane=0;
unsigned int block=0;
struct direct_erase *direct_erase_node=NULL;
unsigned int block0=0xffffffff;
unsigned int block1=0;
if((ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane1].erase_node==NULL)||
((command!=INTERLEAVE_TWO_PLANE)&&(command!=INTERLEAVE)&&(command!=TWO_PLANE)&&(command!=NORMAL))) /*如果没有擦除操作,或者command不对,返回错误*/
{
return ERROR;
}
/************************************************************************************************************
*处理擦除操作时,首先要传送擦除命令,这是channel,chip处于传送命令的状态,即CHANNEL_TRANSFER,CHIP_ERASE_BUSY
*下一状态是CHANNEL_IDLE,CHIP_IDLE。
*************************************************************************************************************/
block1=ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane1].erase_node->block;
ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
ssd->channel_head[channel].current_time=ssd->current_time;
ssd->channel_head[channel].next_state=CHANNEL_IDLE;
ssd->channel_head[channel].chip_head[chip].current_state=CHIP_ERASE_BUSY;
ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
if(command==INTERLEAVE_TWO_PLANE) /*高级命令INTERLEAVE_TWO_PLANE的处理*/
{
for(die=0;die<ssd->parameter->die_chip;die++)
{
block0=0xffffffff;
if(die==die1)
{
block0=block1;
}
for (plane=0;plane<ssd->parameter->plane_die;plane++)
{
direct_erase_node=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node;
if(direct_erase_node!=NULL)
{
block=direct_erase_node->block;
if(block0==0xffffffff)
{
block0=block;
}
else
{
if(block!=block0)
{
continue;
}
}
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node=direct_erase_node->next_node;
erase_operation(ssd,channel,chip,die,plane,block); /*真实的擦除操作的处理*/
free(direct_erase_node);
direct_erase_node=NULL;
ssd->direct_erase_count++;
}
}
}
ssd->interleave_mplane_erase_count++; /*发送了一个interleave two plane erase命令,并计算这个处理的时间,以及下一个状态的时间*/
ssd->channel_head[channel].next_state_predict_time=ssd->current_time+18*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tWB;
ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time-9*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tBERS;
}
else if(command==INTERLEAVE) /*高级命令INTERLEAVE的处理*/
{
for(die=0;die<ssd->parameter->die_chip;die++)
{
for (plane=0;plane<ssd->parameter->plane_die;plane++)
{
if(die==die1)
{
plane=plane1;
}
direct_erase_node=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node;
if(direct_erase_node!=NULL)
{
block=direct_erase_node->block;
ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node=direct_erase_node->next_node;
erase_operation(ssd,channel,chip,die,plane,block);
free(direct_erase_node);
direct_erase_node=NULL;
ssd->direct_erase_count++;
break;
}
}
}
ssd->interleave_erase_count++;
ssd->channel_head[channel].next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tBERS;
}
else if(command==TWO_PLANE) /*高级命令TWO_PLANE的处理*/
{
for(plane=0;plane<ssd->parameter->plane_die;plane++)
{
direct_erase_node=ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane].erase_node;
if((direct_erase_node!=NULL))
{
block=direct_erase_node->block;
if(block==block1)
{
ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane].erase_node=direct_erase_node->next_node;
erase_operation(ssd,channel,chip,die1,plane,block);
free(direct_erase_node);
direct_erase_node=NULL;
ssd->direct_erase_count++;
}
}
}
ssd->mplane_erase_conut++;
ssd->channel_head[channel].next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tBERS;
}
else if(command==NORMAL) /*普通命令NORMAL的处理*/
{
direct_erase_node=ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane1].erase_node;
block=direct_erase_node->block;
ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane1].erase_node=direct_erase_node->next_node;
free(direct_erase_node);
direct_erase_node=NULL;
erase_operation(ssd,channel,chip,die1,plane1,block);
ssd->direct_erase_count++;
ssd->channel_head[channel].next_state_predict_time=ssd->current_time+5*ssd->parameter->time_characteristics.tWC;
ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tWB+ssd->parameter->time_characteristics.tBERS;
}
else
{
return ERROR;
}
direct_erase_node=ssd->channel_head[channel].chip_head[chip].die_head[die1].plane_head[plane1].erase_node;
if(((direct_erase_node)!=NULL)&&(direct_erase_node->block==block1))
{
return FAILURE;
}
else
{
return SUCCESS;
}
}
/*******************************************************************************************************************
*GC操作由某个plane的free块少于阈值进行触发,当某个plane被触发时,GC操作占据这个plane所在的die,因为die是一个独立单元。
*对一个die的GC操作,尽量做到四个plane同时erase,利用interleave erase操作。GC操作应该做到可以随时停止(移动数据和擦除
*时不行,但是间隙时间可以停止GC操作),以服务新到达的请求,当请求服务完后,利用请求间隙时间,继续GC操作。可以设置两个
*GC阈值,一个软阈值,一个硬阈值。软阈值表示到达该阈值后,可以开始主动的GC操作,利用间歇时间,GC可以被新到的请求中断;
*当到达硬阈值后,强制性执行GC操作,且此GC操作不能被中断,直到回到硬阈值以上。
*在这个函数里面,找出这个die所有的plane中,有没有可以直接删除的block,要是有的话,利用interleave two plane命令,删除
*这些block,否则有多少plane有这种直接删除的block就同时删除,不行的话,最差就是单独这个plane进行删除,连这也不满足的话,
*直接跳出,到gc_parallelism函数进行进一步GC操作。该函数寻找全部为invalid的块,直接删除,找到可直接删除的返回1,没有找
*到返回-1。
*********************************************************************************************************************/
int gc_direct_erase(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane)
{
unsigned int lv_die=0,lv_plane=0; /*为避免重名而使用的局部变量 Local variables*/
unsigned int interleaver_flag=FALSE,muilt_plane_flag=FALSE;
unsigned int normal_erase_flag=TRUE;
struct direct_erase * direct_erase_node1=NULL;
struct direct_erase * direct_erase_node2=NULL;
direct_erase_node1=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node;
if (direct_erase_node1==NULL)
{
return FAILURE;
}
/********************************************************************************************************
*当能处理TWOPLANE高级命令时,就在相应的channel,chip,die中两个不同的plane找到可以执行TWOPLANE操作的block
*并置muilt_plane_flag为TRUE
*********************************************************************************************************/
if((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE)
{
for(lv_plane=0;lv_plane<ssd->parameter->plane_die;lv_plane++)
{
direct_erase_node2=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node;
if((lv_plane!=plane)&&(direct_erase_node2!=NULL))
{
if((direct_erase_node1->block)==(direct_erase_node2->block))
{
muilt_plane_flag=TRUE;
break;
}
}
}
}
/***************************************************************************************
*当能处理INTERLEAVE高级命令时,就在相应的channel,chip找到可以执行INTERLEAVE的两个block
*并置interleaver_flag为TRUE
****************************************************************************************/
if((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE)
{
for(lv_die=0;lv_die<ssd->parameter->die_chip;lv_die++)
{
if(lv_die!=die)
{
for(lv_plane=0;lv_plane<ssd->parameter->plane_die;lv_plane++)
{
if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node!=NULL)
{
interleaver_flag=TRUE;
break;
}
}
}
if(interleaver_flag==TRUE)
{
break;
}
}
}
/************************************************************************************************************************
*A,如果既可以执行twoplane的两个block又有可以执行interleaver的两个block,那么就执行INTERLEAVE_TWO_PLANE的高级命令擦除操作
*B,如果只有能执行interleaver的两个block,那么就执行INTERLEAVE高级命令的擦除操作
*C,如果只有能执行TWO_PLANE的两个block,那么就执行TWO_PLANE高级命令的擦除操作
*D,没有上述这些情况,那么就只能够执行普通的擦除操作了
*************************************************************************************************************************/
if ((muilt_plane_flag==TRUE)&&(interleaver_flag==TRUE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE)&&((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE))
{
if(erase_planes(ssd,channel,chip,die,plane,INTERLEAVE_TWO_PLANE)==SUCCESS)
{
return SUCCESS;
}
}
else if ((interleaver_flag==TRUE)&&((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE))
{
if(erase_planes(ssd,channel,chip,die,plane,INTERLEAVE)==SUCCESS)
{
return SUCCESS;
}
}
else if ((muilt_plane_flag==TRUE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE))
{
if(erase_planes(ssd,channel,chip,die,plane,TWO_PLANE)==SUCCESS)
{
return SUCCESS;
}
}
if ((normal_erase_flag==TRUE)) /*不是每个plane都有可以直接删除的block,只对当前plane进行普通的erase操作,或者只能执行普通命令*/
{
if (erase_planes(ssd,channel,chip,die,plane,NORMAL)==SUCCESS)
{
return SUCCESS;
}
else
{
return FAILURE; /*目标的plane没有可以直接删除的block,需要寻找目标擦除块后在实施擦除操作*/
}
}
return SUCCESS;
}
Status move_page(struct ssd_info * ssd, struct local *location, unsigned int * transfer_size)
{
struct local *new_location=NULL;
unsigned int free_state=0,valid_state=0;
unsigned int lpn=0,old_ppn=0,ppn=0;
lpn=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn;
valid_state=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state;
free_state=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state;
old_ppn=find_ppn(ssd,location->channel,location->chip,location->die,location->plane,location->block,location->page); /*记录这个有效移动页的ppn,对比map或者额外映射关系中的ppn,进行删除和添加操作*/
ppn=get_ppn_for_gc(ssd,location->channel,location->chip,location->die,location->plane); /*找出来的ppn一定是在发生gc操作的plane中,才能使用copyback操作,为gc操作获取ppn*/
new_location=find_location(ssd,ppn); /*根据新获得的ppn获取new_location*/
if ((ssd->parameter->advanced_commands&AD_COPYBACK)==AD_COPYBACK)
{
if (ssd->parameter->greed_CB_ad==1) /*贪婪地使用高级命令*/
{
ssd->copy_back_count++;
ssd->gc_copy_back++;
while (old_ppn%2!=ppn%2)
{
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].free_state=0;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].lpn=0;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].valid_state=0;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].invalid_page_num++;
free(new_location);
new_location=NULL;
ppn=get_ppn_for_gc(ssd,location->channel,location->chip,location->die,location->plane); /*找出来的ppn一定是在发生gc操作的plane中,并且满足奇偶地址限制,才能使用copyback操作*/
ssd->program_count--;
ssd->write_flash_count--;
ssd->waste_page_count++;
}
if(new_location==NULL)
{
new_location=find_location(ssd,ppn);
}
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].free_state=free_state;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].lpn=lpn;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].valid_state=valid_state;
}
else
{
if (old_ppn%2!=ppn%2)
{
(* transfer_size)+=size(valid_state);
}
else
{
ssd->copy_back_count++;
ssd->gc_copy_back++;
}
}
}
else
{
(* transfer_size)+=size(valid_state);
}
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].free_state=free_state;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].lpn=lpn;
ssd->channel_head[new_location->channel].chip_head[new_location->chip].die_head[new_location->die].plane_head[new_location->plane].blk_head[new_location->block].page_head[new_location->page].valid_state=valid_state;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state=0;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn=0;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state=0;
ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num++;
if (old_ppn==ssd->dram->map->map_entry[lpn].pn) /*修改映射表*/
{
ssd->dram->map->map_entry[lpn].pn=ppn;
}
free(new_location);
new_location=NULL;
return SUCCESS;
}
/*******************************************************************************************************************************************
*目标的plane没有可以直接删除的block,需要寻找目标擦除块后在实施擦除操作,用在不能中断的gc操作中,成功删除一个块,返回1,没有删除一个块返回-1
*在这个函数中,不用考虑目标channel,die是否是空闲的,擦除invalid_page_num最多的block
********************************************************************************************************************************************/
int uninterrupt_gc(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane)
{
unsigned int i=0,invalid_page=0;
unsigned int block,active_block,transfer_size,free_page,page_move_count=0; /*记录失效页最多的块号*/
struct local * location=NULL;
unsigned int total_invalid_page_num=0;
if(find_active_block(ssd,channel,chip,die,plane)!=SUCCESS) /*获取活跃块*/
{
printf("\n\n Error in uninterrupt_gc().\n");
return ERROR;
}
active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;