-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfile_system.txt
814 lines (591 loc) · 49.8 KB
/
file_system.txt
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
// 文件系统
1、inode号可以重复吗?
2、不同的文件描述符 怎样可以操作同一文件?
3、简单描述下 ext2 ext3 ext4 文件系统
4、简单描述下 VFS
5、简单描述下 文件系统挂载的实现
6、简单描述下 内核中的文件路径解析
7、bio层的功能简单描述下?
8、什么是超级块?
9、简单描述下 ext2 文件系统支持的最大单个文件大小的算法?(提示:考虑一级间接块,二级间接块,三级间接块)
10、简单描述下 什么是格式化?
11、ext2 使用的块分配算法是什么?ext3 ext4 又是怎么改进的?
12、ext3 和 ext4 通过什么方法提高数据的可靠性的?
13、readahead 的作用是什么? 简单描述下文件系统预读操作?
14、 pipe 创建的管道在调用exec系列函数后是否仍然可用?
15、 O_CLOSEXEC 标志有什么用?
16、文件的 atime mtime ctime 分别表示什么?
17、怎样获取文件的创建时间?
18、简单描述下inotify机制
19、简单描述下 tail -f 命令的实现?
20、简单描述下电梯调度算法?
21、DIRECT I/O 和 SYNC I/O 的区别是什么?
22、free 命令的显示中 buffer 和 cache 分别代表什么?
(tips:现在buffer 和 cache统一都由page cache实现,只不过buffer是比较特殊的直接操作设备文件产生的空间占用,
例如,直接读取 /dev/ 设备
cache 包括了page cache 和 slab中的可回收部分,其中cache的计算中已经减去了buffer 和 swap用到的page)
23、文件的覆盖写和追加写有什么区别?
24、文件覆盖写时,如果没有进行4096对齐,会产生什么问题?
(tips:写入时,还要进行剩余数据的读取,造成的一个现象就是写入时伴随着大量的读取操作)
25、文件系统视角下块设备最小操作单位是多少?(以ext文件系统为例)
26、磁盘视角下设备最小操作单位是多少?
27、多个I/O 操作能保证顺序吗?为什么?
28、在采用机械磁盘存储文件时,数据的具体存放位置有什么策略?
(tips:优先同磁道,其次同柱面,然后就不同磁道了)
29、系统启动盘一般在内圈磁道还是外圈磁道,为什么?
30、描述下SSD盘的写入放大问题?
31、ext2文件系统对于目录的组织采用什么数据结构?ext3文件系统呢?为什么?
32、分别描述下RAID1 RAID4 RAID6?分别解决了什么问题?
33、什么是NAS?
34、什么是SAN?
35、什么是SPDK,解决了什么问题?
36、以append标志打开的文件读写是原子的吗?
37、EXT4 的journal 级别有哪些?
38、RAID技术有哪些缺点?
39、影响SSD性能的点都有哪些?
40、SSD有使用预读策略吗?
41、什么是RDMA?在使用中有哪些问题?
42、简单介绍下 RoCE 的实现?
43、SLC MLC TLC 分别表示什么类型的SSD?哪种性能最好?
44、什么是 Open-Channel SSD?
45、什么是文件系统的链式写,什么是扇出写(又叫星型写)?
46、一个进程正在读一个文件,另一个进程删除这个文件,会发生什么?
47、使用 vim或者cat查看文件后,再用 ls -lu 查看文件的atime 并没有改变,为什么?
48、文件系统挂载时的选项 noatime nodiratime 表示什么意思,为什么要这样做?
49、struct file 结构中的 address_space 表示什么?
50、什么是反向映射?解决什么问题?
(tips:找到用户空间映射某一页面的所有进程,不是内核映射)
51、存meta信息的页在 address_space 中吗?
52、task_struct 结构中 prio,static_prio,normal_prio,rt_prio 字段分别表示什么意思?
(tips:prio表示的是真实的优先级,static_prio和nice的操作关系密切,normal_prio表示的静态优先级的概念,fork时,子进程的static_prio=父进程的normal_prio
nice操作通过修改static_prio来影响优先级,进而计算进程对应的weight值,weight值呢又影响了CFS调度中vruntime增加的速度,联想对应PDF中不同nice值的进程
的vruntime增长速度)
53、nice的操作是怎样影响CFS调度器行为的?
54、O_NONBLOCK 标志对普通文件有效果吗?
(tips:没效果)
55、ext2 文件系统的fast symbol link是怎么实现的?
56、readahead 对 dir的影响?
57、ext3 和 ext4 允许的子目录数分别在什么量级?
(tips:查看 112 的解释)
58、ext4 multi-block allocation、extents和delayed allocation分表表示什么?有什么作用?
59、/proc/$PID/fd 目录下的各个文件表示什么?
60、SSD写入时,采用write back还是write through,为什么?怎么应对掉电?
(tips:使用write back,SSD本身有大电容,可以保证掉电Cache中数据不丢失)
61、SSD中TRIM指令的作用是?
(tips:回收不再使用的LBA地址)
62、普通文件系统的垃圾回收机制对SSD为什么有时不生效,反而会使得SSD速度变慢?
(tips:LBA到真正的块地址映射关系和普通机械硬盘不同,将LBA调整为连续可能引起多余的数据擦除和拷贝)
63、SSD的预留空间对于文件系统可见吗?
(tips:不可见,不同厂家的预留空间占总存储比例不同)
预留空间被称为OP(Over-Provision),是为了应对写放大问题,如果OP空间大,那么适合于写密集型应用
64、机械硬盘和SSD的Cache采用的是?
(tips:SRAM)
65、都有哪些常见的zero copy技术?
(tips:mmap,sendfile)
66、BIO 在执行前有两次合并过程,具体在哪一层?
(tips:第一次是在 I/O 调度器层,第二次是在低层驱动层再做一次合并过程)
67、内核里面表示一次文件操作的 request 和 request_queue 结构分别表示什么?
68、I/O 调度算法都有哪些?
69、SSD常使用的调度算法是哪个?为什么?
70、CFQ算法怎么保证公平性的?
71、deadline调度算法分发请求时,优先处理读请求还是写请求?
(tips:优先处理读请求,但是也会考虑deadline时间)
72、deadline调度算法使用了几个队列,作用分别是?
(tips:四个队列,读写操作分别对应有调度队列和派发队列两个队列;
I/O调度算法的执行过程中,潜在使用了调度队列来存放未经过处理的请求,
而派发队列则为真正下一步要执行的请求)
73、什么是屏障I/O?
(tips:这里可以联想CPU中的内存屏障指令的作用,即保证在屏障I/O前的请求的顺序)
74、屏障I/O的用户层接口是?
(tips:这里还有待学习,把用户态的请求和内核的具体处理联系起来)
75、kintegrityd 内核线程的作用是?
(tips:校验读请求返回的数据是否完整?)
76、内核中自带的数据完整性校验功能是怎么实现的?
(tips:在每一个512扇区之后,利用之前不可见的8字节数据,
存储CRC16计算出来的checksum,写入时计算,读取时校验数据,数据
不一致时报错)
77、Multi-Disk模块表示?
(tips:Linux软件RAID)
78、同一个设备,允许在不同的挂载点,挂载两次吗?
(tips:允许,内核中有一个super block,但是对应不同的vfsmount)
79、libaio的实现原理?
(tips:封装了内核原生支持的5个异步io系统调用,glibc的实现中是用线程池来模拟异步操作)
80、aio的实现原理?
(tips:内部实现了一个队列,ring buffer,然后通过状态机来记录各个状态的io操作)
81、aio相比同步io优点?
(tips:增加了queue size,增加了流水线处理,异步完成io)
82、libaio的缺点有哪些?
(tips:1、需要O_DIRECT支持,在不支持O_DIRECT的文件系统或设备上,不能使用
2、不支持sync语义
3、不能支持socket文件)
83、dirty page怎么同步回磁盘?
(tips:通过pdflush内核线程,刚开始pdflush是根据dirty page的数量多少来创建,
后面修改为一个BDI(backing device info)磁盘设备一个pdflush)
84、dirty page什么时候刷回磁盘?
(tips:有两个参数,一个是时间,一个是/proc/sys/vm/dirty_ratio参数)
85、怎么查看磁盘设备的 major minor 号?
(tips:在 /dev 目录下 ls 一下,输出中就有major minor号)
86、O_SYNC fsync fdatasync有什么区别?
(tips:三个都表示数据同步,第一个是在一次写入中完成,第二个和第一个操作过程类似,
但是要多一次额外的函数调用,第三个较为轻量,只同步数据,不同步meta data)
87、Ext4 extents的作用是?
(tips:将同一文件的数据临近存放,减少之前间接块索引导致的多次读取元数据,
同时增加预读效果,加快truncate操作
单个extent最多包括32768个block,即128M的空间,如果当前文件系统开启了extent属性,
那么在写入时就会按照extent的规则来写,同时 ioctl也支持从块指针的方式转为extent)
88、Ext4 multiblock allocation概念?
(tips:之前的ext文件系统分配文件block时是一次分配一个block,性能较低)
89、SSD的page 、block分别指?
(tips:page是读写的最小单位,一般为4KB,block由一组page构成,是erase操作的单位)
90、SSD中的page可以overwrite吗?
(tips:不能,如果要修改原page中的数据,需要先找到一个处于clean状态的page,
然后拷贝原数据,再写入新的page中,原page装填置为stale)
91、SSD 中 wear leveling 作用是?
(tips:SSD中每一个cell都有固定的寿命,如果频繁操作某一些cell,会加快这些cell的失效,
wear leveling 的作用就是尽可能的将读写操作分布于整个SSD中,而不是集中于某一些cell
算法实现上有两种
(1)动态WL
在一个空白池子中选择待写入的块;但是有一个问题是,空白块往往是PE比较高的块,
在某种程度上会加剧磨损不均衡
(2)静态WL
动态的记录某一个block的PE值,尽可能区分冷热数据,然后进行选择性写入
算法实现上的一些问题:
(1)记录的PE值需要动态的去收集,本身就有开销
(2)底层去分析上层的IO pattern本身就有难度
(3)注意,WL也可能占用硬件带宽
在某些实现中,可能倾向于反磨损均衡(某些固态盘阵列),预期就是这些盘一块块的坏掉替换
而不是在某个时刻批量的不可用)
92、SSD中,怎么回收处于stale状态的page?
(tips:TODO)
93、SSD中TRIM操作提出的背景?
(tips:文件系统级数据删除了,但是SSD控制器并没有感知到,可能会影响到后续的文件读写)
94、e2fsck在1EB大小的文件系统上,需要119年才能完成
95、Ext系列文件系统中 block group 对于文件系统整体大小的限制?
(tips:一个block group 128M,一个block group描述符64B,那么一个block group 可以放 128M/64个描述符,
再乘以128M,整个文件系统的大小就为 128M/64 * 128M)
96、Ext4 文件系统中单文件16TB的限制怎么来的?
(tips:之前stat的结果中,i_blocks表示的是以512字节为单位的扇区数量,现在改为4KBpage的数量,
那么单个文件的大小就是 2^32 * 4KB)
97、Ext4 文件系统inode number多少位?
(tips:32位)
98、Ext3 文件系统的目录组织结构是?
(tips:有论文指出,ext3文件系统仍然沿用了ext2文件的目录组织结构,即链式结构,
这个还需要考证,因为有其他论文在描述ext3对ext2的优化时提到ext3已经使用了hash的方法
通过读代码,确认默认是通过链式结构组织,但是可以通过tunefs 工具修改为HTree结构)
99、Ext4 文件系统的 preallocation?
(tips:对于数据库这种需要持续写入的数据的应用,如果文件系统层能提前分配好写入文件数据需要的block,
那么会提高上层应用性能)
100、fallocate 函数作用?
(tips:显示的调用preallocate过程,提前分配数据块)
101、Ext4 文件系统提供了纳秒级的时间戳
102、ext2/3 文件系统中磁盘上inode大小为 128字节,ext4 文件系统磁盘上inode大小为256字节
103、iCache 和 dCache的作用分别是什么?Cache的 key 是什么?
104、简单描述下FUSE?
(tips:FUSE是一个用户态文件系统实现,由内核模块和libfuse组成,内核模块抽象了一个fuse文件系统和特殊的/dev/fuse文件,
用户态的操作通过VFS导向fuse实现,再封装为对应的fuse请求数据写入/dev/fuse,用户态的libfuse轮询读取/dev/fuse文件,
解析出对应的操作类型和数据,再调用用户自己实现的各个FUSE接口,如open,read,write等,用户态程序返回后,再将结果返回给内核模块,
内核模块再将结果返回给最初的用户态)
105、快速符号链接原理是?
(tips:其实还是符号链接,只不过链接的具体数据不存放在文件block中,而是inode中,
这样减少了数据从磁盘的读取操作,更加快速)
106、Ext4中,一个文件的多个Extent使用什么数据结构保存?
(tips:如果文件的extents少于3个,那么以数组的形式保存在inode中,如果再增加,则保存为BTree like的结构,
这个BTree高度现在固定为2,但也有patch在考虑将这个限制放到3)
107、Btrfs 文件系统的一个亮点是提供了文件系统级的快照功能。
108、SSD盘对于原子写的支持?
(tips:IO请求的路径较长,就算从驱动层发给了硬件,之前的硬件也没有提供原子写的支持
这里是SSD硬件对于一定长度,一定数据地址对齐的请求,保证了原子的写入支持。)
109、Ext3 和 Ext4 文件中Journal的实现和文件系统的实现是两个模块,文件系统本身不知道Journal的存在,文件系统唯一知道的是Transaction的概念
(tips:对应代码中就是Journal单独实现了JBD)
110、文件系统内各个Journal的提交顺序没有严格的保证,更新文件的meta,也是先commit log,然后更新磁盘上对应数据
111、如果文件系统Recover时Crash,那么数据会不一致吗?不会,因为Recover过程中,只是按照log重新操作磁盘上的文件数据,这个操作是幂等的。
112、Ext3 文件系统在代码中指定了一个目录最大的链接数是 32000,也就是说,去掉 . 和 .. 两个特殊目录,那么一个目录下就只能有 31998 个子目录
这个是在代码中写死的,综合考虑了如果使用链式结构来存储子目录的查找性能。
113、Ext4 对于 Ext3 的改进之一是在 Journal层 添加了checksum 机制,利用CRC32 来校验数据的完整性。
114、Ext3 中文件名的最大长度是 254。
115、文件系统中的碎片有哪几种形式?
(tips:single file fragmentation 、 relevant file fragmentation 、 fress space fragmentation)
116、fdatasync 是只同步数据,不同步meta吗?
(tips:fdatasync也要同步meta,如果meta中只有mtime等不影响真正数据一致性的修改,则会忽略)
117、《Kernel support for stack file system》 1、数据的一致性,尤其是底层的文件系统数据有更新时,怎么通知上层的文件系统
118、AuFS多个文件系统文件名冲突时,只显示最上层的文件系统,下层的文件系统文件隐藏,可以通过将底层文件系统设置为RO,
然后上层文件系统为RDWR,那么利用AuFS的Copy-On-Write特性,可以构建一个类似代码版本管理的系统,
新的文件都将拷贝到上层文件系统中,而底层的文件系统并没有改变。
119、AuFS的删除策略,不同于其他操作,删除操作先删除底层文件系统中的文件,然后再删除上层,因为要避免上层的文件删除成功,
底层的文件删除失败,导致底层的文件变成visible,引起歧义。
120、AuFS为使用带来方便,但是性能是有损失的,尤其是有多个branch时
121、写入文件分配block时,尽量让data block靠近indoe所在的block,让新的indoe和父indoe靠近
122、Ext3 有锁的改进,增加Journal间的并发度
123、Ext3早期版本解决Perallocation的方案是每一个inode维护了一个range,且各个inode之间的range隔离,这个range信息是在内存中保存,
而不是磁盘上,这样解决了Ext2上的预分配导致的Crash恢复时数据的不一致问题
124、Ext4 Extent 树高最高为 5
(tips:实际上不大于2)
125、fsync在保证当前文件本身的数据落盘的同时,对于包含这个文件的文件夹的更新则没有保证
126、fsync的man page中有说明,如果磁盘开启了write buffer,则当fsync函数返回时,无法保证数据落盘
127、126中的问题怎么解决?
(tips:在mount时,添加 barrier 挂载参数,确保在每一次sync时,flush磁盘本身的write buffer
这个也和具体的硬盘实现有关,需要了解硬件参数和配置)
128、blk-mq sheduler?
(tips:内核为了提高SSD盘的吞吐量而设计的I/O调度器,其核心思想是,每个CPU核都有自己单独的request-queue,
之前的merge逻辑不变,硬件层也同样有多个dispatch queue,然后尽可能的匹配SSD的处理能力,尤其是 NVMe SSD)
129、I/O polling?
(tips:接上一条,如果外部存储设备的延迟够低,那么可以不用现在的基于中断的模式,而是polling,等待直到I/O完成,
减少中断次数;如果采用这种技术,那么应用层应该尽可能的少用Non-blocking,因为这又引入了异步模式,需要额外的操作来
确保命令已经执行完,
IO polling 有一个问题就是CPU消耗,试想如果一个IO需要10us完成,在submit_bio之后就立即polling,那么
刚开始的几us相当于在做无用功,所以内核引入了 hybrid poll机制,即,在任务提交后,sleep一段时间,然后再
polling设备,以降低CPU消耗)
130、接上一条,有的SSD本身具有中断聚合功能,即尽可能少的中断CPU执行,批量提交I/O完成信息
131、ramfs 和 tempfs 有什么区别和联系?
(tips:首先,这两个文件系统使用的都是内存,free命令中 cache 部分
不同的是,tmpfs可以限制使用的总大小,且可以通过df 命令查看现在的使用量
挂载命令 mount -t tmpfs -osize=100M tmpfs /your/mount/point)
132、fuse 中实现的non-privileged mount 概念?
133、当挂载多个fuse实例时,怎样区分发送的消息给不同的user process?
(tips:各个挂载点的super block不一样,而super block中实现了不同的request queue)
134、用户态close一个文件,为什么需要调用 fuse flush和release接口?
(tips: TODO)
135、vmtouch的实现原理?
(tips:核心实现调用了mincore函数,在调用这个函数之前需要调用mmap将文件映射到内存中,
然后判断文件的内容是否在内存中)
136、写入文件时,提示磁盘满,排查步骤
(tips:1、df -Th 检查磁盘空间是否满,2、df -i 检查inode空间是否满
3、查看目录是否有 dir_index特性,且当前目录下存在千万级文件,4、确认当前文件系统没有在恢复中)
137、Ext4 中 HTree 数据结构中 怎么处理 hash值相同的情况?
(tips:并没有进行特殊的处理,还是按照二分查找法处理)
138、Ext4 中单目录下 子目录最多 65000个,对应 112 问题中的 Ext3的实现
(tips:这里65000是指 文件的 hard link数量限制,适用于目录及普通文件,如果ext4开启了 dir_nlink 特性,
则子目录数量没有限制)
139、indoe结构中的 i_nlink 字段的含义是?
(tips:参照 112 和 138 问题的子目录数量)
140、Ext4 实现的 HTree 目录结构中,树高固定为 2,在 4.12 版内核之后,可以通过开启 largedir 特性来将树高 调到3
(tips:如果树高为2,那么单个目录下的最大文件数在 千万 级别,还和 文件名大小有关)
141、通过文件系统读写数据时的读写惩罚是指?
(tips:要随机修改1字节的数据,让然要读取page大小的数据到page cache中,然后进行修改,
再将4096大小的数据写回,这里面就有4095大小的冗余数据流量,
企业级存储产品针对这个特性有做优化,实现类似于针对设备中的扇区进行hash,然后识别扇区的数据修改,
将数据修改的粒度缩小到扇区级别,减少冗余数据)
142、企业级存储产品的功能优化有?
(tips:SafeCache,大容量的SSD缓存,异步将数据更新刷回后端存储,
HotZone,主动识别热点数据区域,将数据同步到前端SSD缓存中,
SED,Service Enable Device功能实现的存储虚拟化产品的逃生模式和数据迁移支持,
逃生模式是将之前通过虚拟化设备的IO数据流量透传给后端的存储设备,而不至于业务中断,
这就需要虚拟化设备不能在内部修改或者重映射后端存储设备的信息)
143、Stretched Cluster功能和云上服务提供的 Data Replicate Service 很像,都是提供了异地的数据容灾
144、写内核线程正在刷回磁盘的页面会有什么结果?
(tips:内核线程会对正在写回的页面加写保护,当有后续的写入时,会触发写保护,调用do_page_fault,
后续会等到内核线程将数据刷回了才能再次写入对应页面)
145、多个进程打开相同文件,page cache 中会缓存多份数据吗?
146、EC编码在什么情况下会出现性能问题?
(tips:首先,EC码通过矩阵运算得到,这一步会消耗CPU,
其次,在更新EC编码的文件时,需要先读出part data,然后计算校验和,
再写入,这一步也会有开销,已3+1 模式为例,会有4倍的数据流量)
147、EC编码和RAID技术的比较?
(tips:RAID技术不适用于大容量存储中,RAID5 5个9 RAID6 8个9的数据安全性
RAID5 采用 n+1 的编码模式,即允许坏一块盘,且校验码打散在各个盘上
RAID6 采用 n+2 的编码模式,允许坏两块盘,校验码打散在各个盘上)
148、磁盘静默错误怎么解决?
(tips:使用 DIX/DIF在每一个扇区后追加校验字段来解决,
也可以由业务开发校验程序)
149、vm.dirty_ratio 作用是什么?
(tips:系统中脏页面所占内存的最大比例,如果高于这个比例,新的I/O请求将阻塞,
直到之前的脏页面写回)
150、vm.dirty_background_ratio 作用是什么?
(tips:系统中脏页面能占系统内存的最大比例,与上面参数不同的是,
这里的限制更像是软限制,当超过这个值时,后台的flush线程启动)
151、文件系统Snapshot原理是?
(tips:简单实现就是拷贝磁盘上的所有数据,这在RAID1中已有实现;
但是考虑到需要拷贝的数据量和拷贝的同时需要停止其他I/O,所以说需要其他实现;
另一种实现思路是只拷贝元数据,数据量很少,可以很快完成,后面数据的持续修改,
有CoFW 和 RoFW两种实现方式,FW代表 First Write
CoFW:当有数据更新需求时,将原数据拷贝一份出来,这时snapshot中的元数据指向的是老数据,
然后将原地更新老数据,这里只更新一次,如果下次还有同样位置的数据更新,那么就不需要再拷贝数据
RoFW:当有数据更新需求时,将数据更新地址重定向到另外的空闲块,这样减少了数据拷贝,
但是后面的数据读取操作需要计算重定向信息
CoFW需要拷贝数据,有一定的I/O开销,但是对源文件系统没有侵入,
后续的读取不需要计算重定向信息,且之前的大块预读仍然可以继续;
但RoFW因为后续的修改导致数据可能较分散,读取时需要计算重定向信息)
152、Overwrite 系统 和 Append 系统?
(tips:Overwrite系统指数据在原位置更新,即新数据覆盖老数据,
Append系统则是新数据在新位置,老的数据依赖于GC功能删除)
153、直写EC有什么问题?
(tips:如果是大块写,那么在数据写入时计算EC码,并且刷盘是没问题的,
但是如果是小块写,考虑到数据安全性,不够一个大块的数据需要填充,然后仍然计算校验和、刷盘,
后面有数据到来时,考虑到 146 中提到的流量放大问题,写入效率低。
FusionStorage为了解决这个问题,做了一层缓存,对外是直写EC,但是由缓存将小块写转为大块写)
154、fio 工具中的 iodepth参数表示什么?
(tips:iodepth在同步IO中不起作用,在使用异步引擎时,表示针对一个同时发起的IO数量)
155、iostat 命令中 avgrq-sz 和 avgqu-sz表示什么意思?
(tips:avgrq-sz 表示平均 request大小,单位为 sector
avgqu-sz表示发送给设备的requests队列长度,
这里有个问题就是iostat的输出和dd或fio工具命令行中的bs大小不一致,
从上面的描述中可以看到,avgrq-sz表示的是 request 结构所表示的io请求大小,
所以在用户层面的写入后,(1)在 writeback page_cache时;
(2)在block层的 plug机制 (3)io 调度器的merge机制 会尝试合并请求,
所以会看到avgrq-sz比较大;
avgrq-sz的最大值为 /sys/block/sdx/queue/max_sectors_kb ,单位为kb,
如果取值 256,则avgrq-sz的最大值为 512,
且需要注意,这里统计的是读请求和写请求的和)
156、EAGAIN 和 EWOULDBLOCK 两个错误码有什么区别?
(tips:在Linux上,这两个错误码的定义数值是相同的,
通过查看 man 2 read 和 man 2 write,不会返回 EWOULDBLOCK
返回EAGAIN表示在 Non-Blocking I/O 中,资源暂时不可用)
157、Ext4 中的 write barrier 作用?
(tips:在开启Journal时,对于元数据的修改需要先写log,再commit,再修改对应文件的meta,
但是在block层有请求re-order逻辑,如果commit先写,log后写,就会出现不一致的log data,
write barrier 的作用和CPU中的barrier指令类似,保证barrier之前的写操作完成之后,
后面的写操作才能执行)
158、Ext4 默认开启barrier特性,且 Journal中有校验 checksum,如果乱序写入,且transaction中断,
那么后续的校验将不通过,本次操作会abort;在高端存储磁盘有 battery-backend时,可以考虑关闭
barrier以提高性能
(barrier之前是通过drain request_queue 然后再发送一个flush请求实现的,这样虽然可以达到预期效果,
但是会影响性能)
159、fsync 函数返回EIO错误时,如果直接进行重试,fsync会 clear之前有出错标志的page,
这会潜在的导致数据丢失,Pg数据库目前的做法是fsync返回EIO时,直接panic
160、iostat 命令中的 rKB/s 或 wKB/s表示?
(tips:表示每秒 读取 或 写入的数据量)
r/s 和 w/s 分别表示什么
(tips:表示完成merge后的读写请求request数量,对应内核中的request,注意,是merge后的)
161、产品宣传时提到 IOPS 的数据时,也要同样考虑 IO 的 latency 数据,
这两个同步提高了,才能说明从硬件到软件都有优化
162、磁盘常见的写入静默错误有Lost Write,即没有写入数据,就报告写入成功了,
Torn Write指磁头只写入了部分数据就返回成功。
Misdirect Write是指写入时,定位不准,将内容写到了目标扇区旁边的扇区中
163、DIF的实现基于将磁盘低级格式化为520字节 一个扇区,这样,每个扇区中有8字节来保存DIF信息,
还有另外两种方法,就是不特殊对待DIF,将8字节直接追加到数据内容后面,但是这样会导致读一个扇区的完整数据
需要读两个扇区
另一种方法是64个扇区的DIF信息组成一个特殊的扇区(64*8=512),但是这样也有问题,就是需要磁头额外的移动
164、DIF 怎么解决上面提到的磁盘静默错误?
(tips:针对Lost Write,需要校验DIF数据中的tag域,校验文件inode或LUN号等信息
针对Torn Write,则需要判断校验码是否一致,然后通过RAID等手段来尝试恢复数据
针对Misdirect Write,则需要记录写入的LUN地址)
165、FC磁盘 SAS磁盘表示?
(tips:相对高端的磁盘,转速高,磁盘本身高端,接口转换速率更高
FC 表示光纤通道仲裁环接口
SAS表示 串行连接 SCSI接口
SATA表示 串行连接 ATA接口)
166、文件去重使用Hash算法,解决Hash冲突的办法是 使用多重hash
167、文件 block 级去重有如下问题,需要额外的指针来记录dedup后的block
另,dedup后,上层文件系统没有感知节省下来的block,这样就会导致磁盘利用率并没有提高
168、GPT 和 MBR(MSDOS) 分区格式有什么区别?
(tips:MBR是 Master Boot Record 格式,有一个分区用来启动系统,且只能有4个主分区,
其他的分区要以扩展分区的形式存在,且分区容量不能大于2TB
GPT则是为每个partition分配一个UID,Boot信息存储了多个备份,且有CRC校验,
分区个数没有限制(可能操作系统级有限制),分区大小也没有限制)
169、之前看 群主的书中有提到,当page cache中的page write back时,再次写入会block等待,直到写入完成,
这里其实是 EXT4 实现的 stable page的概念;具体参考内核中 grab_cache_page_write_begin 函数
170、上面 169 中提到的 stable page的引入是为了解决应用层写入数据然后计算校验码,
但是随后的写入有可能改变内存中的数据,这就导致数据不一致。解决办法如上描述,
当page 正在write back,则block当前的写入,直到之前的写入完成
171、什么是读惩罚,什么是写惩罚?
(tips:读惩罚是指当要读取的内容没有按照底层磁盘的sector对齐,
则一次读取512字节需要读取2个sector;写惩罚也类似,不过写惩罚需要先读出数据,
再写回)
172、direct I/O写入的数据不对齐,会有什么影响?
173、什么是 NCQ?
(tips:NCQ指 native command queuing,是一种在HDD和SSD上都可以用的优化技术,
驱动使用它来重新排序上层发送的请求,对于HDD来说,这可以减少磁头的移动次数;
对于SSD来说,这可以将随机I/O转化为顺序I/O,提高SSD性能)
174、企业级SSD测试的IOPS都是 满盘测试,而消费级的SSD则使用的是空盘的IOPS数据;
且企业级SSD更加看重稳定性,DWPD(Drive Write Per Day,每天的满盘写入次数) 和 MTBF 数据,
TBW(Total Bytes Writen)
TBW = Total Capacity * 擦写次数/写放大率
关于TBW,网上还有另一种单位,TeraBytes Written,与之对应的还有 PBW,即SSD可以写入的总PB数据量
175、查看磁盘空间时,需要明确文件系统有预留空间,inode table 也会占用空间
需要使用 tune2fs -l /dev/sda 查看下 super block的信息,确认空间占用
176、overlayfs中upper layer是可写的,lower layer是只读的,如果有修改,
会把文件拷贝到上层再修改。如果两个原始目录中文件名有冲突,那么只展示upper layer的文件,
lower layer的文件会被隐藏。
它的实现是在内核中加入了重定向功能,即对overlayfs目录下文件的操作在内核中会重定向到实际的文件。
这样系统的page-cache 也只需要保留一份。
177、JBOD一种为各个磁盘单独控制,且结合RAID技术;另一种则是简单的将多个磁盘抽象为一个大空间,
iops等和一个磁盘相同,且操作系统或文件系统的元数据在第一个盘上,
如果第一个盘损坏,则整个数据将不可读。
178、du 和 df 展示的结果不同,数据对不上,这是因为du基于stat系统调用,看到的是一个文件的数据;
df 使用的是 statvfs 系统调用,是展示整个系统或分区的角度来获取数据;du可能还要考虑follow
symlink或 hard link的重复计算,而 df 可能还需要考虑系统预留空间,inode的inline data,
journal 的预留空间等
179、ext系文件系统为什么要有块组的概念?
(tips:如果没有块组,那么所有的磁盘数据块只存在于一个大的块组中,
对应的,block bitmap也比较大,查询空闲数据块的耗时将增加,解决这个问题的办法就是把磁盘空间
再划分为对应的块组,拿到inode number或者block number,只需要进行一个除法运算就可以快速确认
属于哪个块组)
180、每一个块组中inode bitmap占一个block,一个block按 4096 bytes计算,则,一个块组中可以包括
4096*8 = 32768 个 inode。
但是用 mke2fs等工具格式化磁盘时,整个分区的indoe数量 按照 每 16KB 一个indoe的方式来计算,目的是为了
节省空间,因为一个inode需要占用 256 bytes空间(super block中存储了一个块组中有几个inode)。
使用 mke2fs -N 可以扩大inode数量,但是仍然没有突破 inode bitmap占一个block,只不过inode table数量变大。
181、ext4文件系统中,如果当前的Journal模式为JOURNAL_DATA_MODE,即数据也要写入Journal,
那么不支持DirectIO;如果当前文件有inline data,那么也会切回buffer IO模式。
182、在进行DirectIO写入后,需要invalid对应的page cache中的page,这样才能保证在下次buffer I/O操作中
拿到最新的数据
183、iostat的数据源来自于/proc/diskstats文件,里面记录了raw data,iostat读取这些数据,
然后展示出来。
(avgrq-sz是用 读写成功的 bytes/读写请求次数,前者和一个request相关,后者则和这个request里面的bio
数量一一对应,虽然在scheduler层会对bio进行merge(merge时需要位置严格相邻),将bio链接
到request的bio_tail链表中,整体上bio num不变。
在使用 dd if of bs=4K count=1000 oflag=direct 进行测试时,发现 avgrq-sz 为8,刚好为4K,
实现为 direct 绕开了 page cache,就不会在生成bio之前对 请求进行merge,所以提交到 request 链表中的
都是 4K 的bio,这样在 plug 或 io scheduler merge之后,bio数量没变,所以用 total_bytes/bio_num = 8*512
即8个 sector)
184、free命令会显示cache/buffer,其实现在的buffer也是通过page cache实现的,而buffer在内核中的表示是
buffer_head 结构,这个struct之前用来表示block_device中的block在内存中的数据,也是老的系统中文件系统
访问底层的结构,不过现在被bio结构取代,但是在 直接 mmap /dev/下的设备时,仍然有使用,这也就对应了
有的文章说 现在的buffer只是对应了裸设备的数据映射。
同样的,之前也有文章说 直接 mmap /dev/ 然后再通过其他普通文件系统 read 同一份数据,page cache中有两份
这是因为 两者使用了不同的文件系统,对应了不同的inode,也就对应了不同的address_space,这样数据就有了两份,
如果修改其中一份数据,另一份不会直接同步。
185、BIO结构完成了从page cache内存地址到dev中sector地址的转换,每一个bio中代表一段连续的地址空间,
里面有可能包括多个bio_vec,一个bio_vec表示一个file system block。
以16KB连续数据为例,需要一个bio结构,里面包括了4个bio_vec;如果数据不连续,则需要多个bio结构
186、使用 echo '' > file 这一步,其实是在open中传入了O_TRUNC标志,进而在打开文件时完成文件长度修改。
(tips:O_TRUNC的实现中,首先对inode->i_mutex加锁,然后修改inode->i_size,再invalid page cache,
这时有一个特殊的点,就是如果这个page mmap到用户态,则需要修改页表,用户的下次访问需要走page fault的流程,
重新读取文件内容
这次还验证了一个场景,一个进程读文件,另一个后台进程覆盖文件内容,那么第一个线程会读取到新内容,
所以说,文件系统并没有保证一致性)
187、在 /etc/mke2fs.conf 文件中有创建文件系统时的默认配置,通过这些配置可以熟悉了解文件系统都实现了哪些功能,
有哪些常用feature
188、debugfs 命令还有个交互模式,里面有一些很有用的命令,可以用于查看磁盘上的数据
189、网友测试中遇到了一个场景,用 dd if=/dev/zero oflag=direct 写入nvme SSD,速度比默认使用buffer快很多,
自己找了测试环境验证了下,确实是这样。
使用 direct 写入sata HDD,速度和使用 sync 模式差不多,但是nvme快很多。
看了对应的代码有如下可能原因:
(1)direct IO 直接使用了 用户态buffer 对应的 page,没有数据的拷贝,这在写入场景下同样适用
(2)direct IO 直接将request提交到了对应device的 request queue,HDD通常是单队列,
但是,nvme SSD队列数可以非常多,处理的速度也比较快
(3)nvme SSD 和 HDD设备侧使用的调度算法不同,nvme由于处理速度快,更多的使用noop,
HDD常使用CFQ
190、direct I/O 有什么好处?
direct I/O 有如下几个好处:
(1) 减少CPU利用率,因为如果使用buffered I/O,那么需要将用户空间的数据拷贝到page cache中,
相当于执行memcpy
(2) 使用buffered I/O 会增加系统内存压力,有可能导致其他cache 命中率较高的文件提前刷回,
在下次访问时,又需要读回,即减少page cache整体的抖动。很多数据库产品都是在用户态实现文件的内容缓存,
写入数据时采用direct。
但是,在采用direct时,需要注意,read/write调用的执行时间可能会增加,这是由direct的执行特点决定的,
具体需要考虑direct是将请求一直要发送到通用块层才返回的。而buffered I/O只需要到page cache层就结束了。
191、如果文件之前已经通过buffered I/O访问过,那么direct I/O 的写请求会同步更新page cache。
192、怎么增加磁盘的队列深度?
(tips:
1、使用异步IO
2、多线程并发提交IO任务
3、每次写入大块数据,块层会自动按照内核的配置将一个任务切分为多个子任务
在压测磁盘时,需要增大磁盘的队列深度,也就是说有积压的任务在等待处理,从而提交dist util)
193、对于SSD设备,因为可以并行处理IO请求,所以iostat的工具输出中 util% 和 svctm% 不能表达出真实的情况
这一点与磁盘设备不同。
194、rename这个函数,新的文件路径和旧的文件路径必须位于同一文件系统下,否则会报错。
从其实现上讲,rename其实就是修改inode指向,同时inode里包含了文件操作相关的operation指针,
文件系统不同,这些函数实现不同,所以不能直接修改。
195、现在的磁盘都采用的ZBR(Zoned Bit Recording),将磁盘划分为zone,zone内部扇区数量相同,zone间,
扇区数可以不一样。这样,当磁盘转速一定,那么外圈的磁头单位时间的线速度将更高,能读取的扇区数更大。
以前的磁盘,内圈和外圈的扇区数一样,这样磁盘的空间小,利用率不高。
196、在使用df看磁盘的使用率时,会遇到磁盘空间满,但是du 得到的占用和df结果不匹配的情况。
这种情况下,可以使用lsof | grep deleted,看下是否存在文件被删除,但是进程仍然持有
file handle的情况,这时删除文件的空间还没有被操作系统回收,所以df显示磁盘满。
197、DAX(direct access)访问文件时,绕过了page cache,直接访问硬件上的数据,在NVMDIMM等设备上使用较多。
与O_DIRECT的软件实现不同,DAX是一种硬件特性,且内部实现了一整套的访问(内核代码中的各种operation实现),
包括page fault的处理,硬件驱动的支持等。其本身实现的基础就是高端存储硬件提供直接的访问支持。
现在支持DAX的文件系统有XFS和EXT4
198、NVMDIMM是一种结合了DRAM和FLASH的硬件,它本身提供了电容,保证了掉电时DRAM中的数据可以写回FLASH,
电力恢复后,再将FLASH中的数据加载到系统内存中。
199、AEP(Apache Pass)是intel Optane产品的代称,是一种以3D XPoint介质为基础实现的非易失性存储介质,
它提供的数据访问带宽比内存低,但是比FLASH高,同时具有持久化功能,可以用来实现更快速的缓存系统
200、lsof的输出中,FD列中的显示中,mem表示mmap的文件,mmap表示内存映射的设备,txt表示二进制可执行文件,
数字后面跟 r w u,其中,数字表示进程中fd number,r w u分别表示读 写 混合读写
201、在调查磁盘读写高时,除了考虑常用的 read/write 调用,其他还有 mmap 需要考虑,
还有一个就是libaio的使用,这在需要trace系统调用的场景下尤其需要注意
(tips:libaio并没有增加新的读写接口,数据还是要通过file_operation中的接口来完成读取,
所以在某些 trace 工具中,通过hook generic_read/generate_write来统计除mmap以外的读写
是可行的)
202、binary的text section加载进内存后,page属性会被标记为 executable,且禁止写入,那么在内存紧张时,
这部分内存会被回收,带来的问题就是可以看到进程在不停的读磁盘文件,其实是加载binary的文件内容到
内存中,这个现象和swap有点像,但还不一样,因为clean page是可以直接被回收的,没开启swap时,
也不同执行swap out
203、ext3/ext4 文件系统在文件删除后,会清除inode中的size 和 block pointer字段。如果需要恢复被删除的文件,
则需要读取文件系统 journal 中记录的日志来undo对应的操作。
文件系统的journal并不是一个普通的文件,对用户不可见,但是文件系统可以对它进行读写。debugfs 工具的logdump
可以看到文件内容。
网上说 ext2 在文件被删除后只是将inode标记为 deleted,没有清楚对应的block pointer等字段,但是在1.12的代码中
看到是会清楚 block pointer,所以这里待进一步确定!
204、内部ext4 挂载时都用了 nodelalloc选项来关闭delay alloc。delay alloc的作用是在buffer I/O中,数据写入
page cache时不立即进行磁盘快的分配,而是等到上层调用fsync或定时写回时才分配。
但是在文件写入时(不管是写入page cache,还是写入磁盘),要持有一把锁,一般情况下,写入很快完成;但是
delay alloc 因为将块的分配推后,等到真正需要分配时,需要的块有可能很多,导致延迟增加,进一步影响
应用的响应。
delay alloc的优点有减少分配块次数,单次的写入延迟降低;且批量分配能将文件内容尽可能存放在连续的磁盘块上,
有利于后续的I/O;
缺点就是:有可能某一次的写入延迟增加,且存在page cache内容准备刷回磁盘发现磁盘没有空间这种情况。
205、lsof的输出 或者 ls -l /proc/$PID/fd/ 结果中有 anon_inode,这是内核中的anon_inodefs伪文件系统下面的
inode,一般多用于eventfd,signalfd,timerfd等,这类文件描述符并没有真正对应inode,但是为了保持语义一致,
内核会为对应的fd分配inode。
/proc/$PID/fd/ 输出格式一般为 type:[inode number],如果type为socket,那么通过inode number可以在
/proc/net/ 目录下的 tcp/udp/unix 等文件中找到详细信息
206、当磁盘开启了write cache时,数据写入磁盘上的DRAM后,立即向上层返回成功,保证了顺序写和随机写性能,
但是存在数据掉电丢失的问题。如果关闭write cache,那么可以保证数据安全。
现在有PWC技术,可以保证在掉电时,仍然能写入少量数据(M级别)
使用 hdparm -W /dev/sda 命令可以查看磁盘的write cache是否打开
207、/proc/$PID/io 文件里面的rchar表示read或pread系统调用中传入的参数之和,对应的wchar表示write或pwrite
传入的参数之和;read_bytes 表示真正从后端设备读取的数据量,统计发生在submit_io这一层,write_bytes则
表示page-cache写回后端设备的数据量
iotop命令中,total 列统计的就是各个process的rchar和wchar
而actual 列统计的则是/proc/vmstat中的pgpgin 和 pgpgout,单位为KB
对于读操作,pgpgin 和 read_bytes 保持同步更新,但是写操作在submit_bio层更新pgpgout,在__set_page_dirty调用
中更新write_bytes
208、磁盘控制器频繁的下发SMART指令,也会对性能产生影响,一般都是分钟级的采样。
这也就带来一个问题,上层怎么快速的发现磁盘的问题,这就要用一些写入测试来辅助,
例如现在在用的 write_test 方法等
209、磁盘的低级格式化主要是将盘片划分出磁道,柱面,扇区,且通常由磁盘厂商完成。
磁盘的高级格式化主要是文件系统相关的元数据的从新划分,例如,重新初始化空闲块位图,
inode位图等。
(tips:磁盘寻址使用CHS地址,即C 柱面,Head 磁头,S 扇区
CHS寻址方式受限于地址存储位长,当前的大容量磁盘采用LBA方式寻址,
CHS只留给磁盘驱动来处理)
210、磁盘读写操作的最小单位是扇区,写入时如果不按照扇区大小(512字节)对齐,那么下次的写入只能
另外找空闲扇区来写。
普通的read/write是buffer写的,数据先写入page cache,由于内存的随机读写特性,数据可以以任意单位写入,随后由
内核线程写回磁盘。
另外,由于direct模式的写入对buffer地址,file offset,写入大小都要求以512对齐,所以,就避免了扇区浪费。
(之前还想着写个程序,每次以direct模式追加写入1字节,这样就可以快速的占满磁盘,但是有了上述的限制,
就没法实现了)
211、/etc/fstab 文件中记录了在机器启动时需要挂载的磁盘信息;
/etc/mtab 文件中记录了当前机器上已经挂载的磁盘信息
212、遇到 Disk quota exceed 报错时,先 df -hi 查看对应磁盘的inode使用情况;
如果没有超;那么查看/etc/mtab文件查看对应挂载点的挂载属性中是否有 usrquota/grpquota,
如果有,那么可以使用 edquota -u $USER 或 edquota -u $GROUP 来查看当前为用户/组设置的quota
设置quota可以使用 setquota 命令。
edquota命令查看不到设置的quota时,可以使用 repquota -g or repquota -u mount_point来确认
对应目录是否有设置quota
213、getfattr -d -m '-' /some/file 命令可以获取文件的所有扩展属性,EXT系列文件支持这一属性。
大小限制可以 man 5 attr 查看
214、什么是 last write win?
(tips:last write win是一种在并发写入场景下的数据版本决策策略,服务端以时间序,选择最后一写入的
数据来作为最新版本
为什么不是客户端看到的顺序,因为在分布式系统下,很难做到客户端和服务端时钟的一致性(例如,客户端网络卡顿),
要做到,可能得启用更重的分布式一致性协议,但这又会导致整体QPS低。
以分布式对象存储为例,就选择应用lww 原则)
215、看文章有人遇到访问/proc下文件慢,先用strace发现耗时长的调用,进而使用公司内部的分析工具确认
耗时调用栈。这里有个问题,外部如何确认调用栈(pstack? SystemTap?)
最后问题怀疑点是 /procy 文件系统实现时有一把全局的mutex,怀疑大并发访问导致锁争用
sysak 貌似开源了
// block layer
1、io_submit调用理论上是非阻塞的,但是如果执行sync写入,或者有meta data I/O,或者,设备中能提供的
request数量有限,如果超过这个限制,也只能阻塞进入等待。
2、怎么确保文件系统下发的写入操作返回时,数据真正落盘呢?
(tips:使用SCSI中的FUA命令,可以将磁盘的缓存模式调整为write through,这样当磁盘驱动器向操作系统返回写入成功信号时,
数据就真正落盘了)
3、Linux系统中,文件系统下发的bio可以带 REQ_PREFLUSH 和 REQ_FUA两个flag,前者保证在处理bio之前将磁盘cache写回,
后者的作用如2所述。block layer不用关注这两个flag的底层实现逻辑,磁盘驱动需要实现这两个功能,
如果磁盘没有non-volatile buffer,REQ_PREFLUSH不作任何操作。
如果物理磁盘不支持FUA,那么可以将FUA操作模拟为一个写入+FLUSH
// trace
1、通过iostat看到某个磁盘util高,怎么确认是哪个进程在进行I/O?
(tips:首先通过df查看磁盘挂载在哪个目录,然后通过lsof输出对应目录下所有打开的文件,参考文件打开模式,
然后过滤进程,利用 pidstat -d -p $PID,查看具体某个进程的IO量,同时,也可以通过strace查看read和mmap
系统调用的使用情况,进一步确定是在读写哪个文件,有时存在一种情况,使用iostat或iotop可以看到读写流量,
但是trace并没有发现有read/write,那么有一种情况就是进程在频繁的调用fsync,需要使用其他工具来trace sync
类的调用)
2、怎么确认某块硬盘状态是正常的?
(tips:现在的硬盘,包括SSD都支持SMART特性,所以可以使用smartctl --all 或 smartctl -H dev 命令来查看对应盘的信息
如果确认磁盘发生了错误,可以使用badblocks命令来扫盘,以确认具体哪个block损坏;
执行检查时,可能需要辅助使用 fdisk -l 或 dumpe2fs -h dev 命令来确认一些硬件或文件系统元数据)