aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth/hci_ll.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bluetooth/hci_ll.c')
0 files changed, 0 insertions, 0 deletions
n class='sha1'>1da177e4c3f4
1da177e4c3f4
0b1b213fcf3a
3ed3a4343b79
6898811459ff
a4fbe6ab1e7a

a27bb332c04c
5a0e3ad6af86
1da177e4c3f4
10ce444428c2
1da177e4c3f4

0b1b213fcf3a
f51623b21fe3


f51623b21fe3



20cb52ebd1b5
f51623b21fe3


20cb52ebd1b5
f51623b21fe3





6214ed4461f1

046f1685bb52
6214ed4461f1
046f1685bb52
6214ed4461f1

71ddabb94a62
6214ed4461f1




0829c3602f4d
f6d6d4fcd180




0829c3602f4d



f6d6d4fcd180



7d04a335b6b2
f6d6d4fcd180
583fa586f0e4
0829c3602f4d



fc0063c44745







281627df3eb5









3d3c8b5222b9
281627df3eb5







437a255aa237
d9457dc05624




281627df3eb5






fc0063c44745
2813d682e8e6
ba87ea699ebd
281627df3eb5
ba87ea699ebd
aa6bf01d3919
ba87ea699ebd
aa6bf01d3919
281627df3eb5
ba87ea699ebd
ba87ea699ebd
281627df3eb5
437a255aa237


281627df3eb5

437a255aa237

281627df3eb5
aa6bf01d3919
6923e686f19c
281627df3eb5



ba87ea699ebd

281627df3eb5






77d7a0c2eeb2


209fb87a259e
fc0063c44745


77d7a0c2eeb2


209fb87a259e
77d7a0c2eeb2

aa6bf01d3919

0d882a360b90
aa6bf01d3919
437a255aa237

aa6bf01d3919
fc0063c44745

77d7a0c2eeb2
ba87ea699ebd


5ec4fabb02fc
f6d6d4fcd180

5ec4fabb02fc
77d7a0c2eeb2
0829c3602f4d
77d7a0c2eeb2

694189328a7e
ba87ea699ebd
04f658ee229f
810627d9a6d0
04f658ee229f




5ec4fabb02fc



0d882a360b90
437a255aa237


281627df3eb5
437a255aa237






281627df3eb5
437a255aa237

04f658ee229f
437a255aa237
281627df3eb5

84803fb78237
281627df3eb5
5ec4fabb02fc
ba87ea699ebd
04f658ee229f
437a255aa237
2451337dd043
aa6bf01d3919
c626d174cfe3


209fb87a259e










0829c3602f4d






f6d6d4fcd180

0829c3602f4d










281627df3eb5
7d04a335b6b2
f6d6d4fcd180

b677c210cec0
c1a073bdff99
f6d6d4fcd180
0829c3602f4d

281627df3eb5
0829c3602f4d
5ec4fabb02fc
0829c3602f4d


1da177e4c3f4



207d041602ce
a206c817c864

1da177e4c3f4
a206c817c864

ed1e7b7e484d
a206c817c864

a206c817c864



b474c7ae4395
a206c817c864
0d882a360b90
a206c817c864
8ff2957d5815


b474c7ae4395
8ff2957d5815
a206c817c864

8ff2957d5815

d2c281911717
8ff2957d5815
d2c281911717

a206c817c864

5c8ed2021ff2

8ff2957d5815
a206c817c864
8ff2957d5815
2451337dd043
a206c817c864
0d882a360b90
8ff2957d5815
0799a3e808e5
a206c817c864

2451337dd043
a206c817c864

8ff2957d5815
0d882a360b90
8ff2957d5815







1da177e4c3f4

b8f82a4a6fc7
558e6891693f
8699bb0a4801
207d041602ce
558e6891693f
1da177e4c3f4
558e6891693f
8699bb0a4801
558e6891693f

1da177e4c3f4

f6d6d4fcd180


782e3b3b3804
f6d6d4fcd180

f6d6d4fcd180



f6d6d4fcd180
7d04a335b6b2
f6d6d4fcd180

f6d6d4fcd180

f6d6d4fcd180
7d04a335b6b2
209fb87a259e
f6d6d4fcd180



06342cf8adb2


f6d6d4fcd180

f6d6d4fcd180

721a9602e660
f6d6d4fcd180





f6d6d4fcd180
221cb2517e8f
f6d6d4fcd180

4f024f3797c4
f6d6d4fcd180
f6d6d4fcd180



















f6d6d4fcd180




f6d6d4fcd180
921320210bd2

f6d6d4fcd180
1f7decf6d9f0

f6d6d4fcd180
f6d6d4fcd180

c7c1a7d8bb45
f6d6d4fcd180




d88992f66093













c41564b5af32
7bf7f3521942




f6d6d4fcd180


06342cf8adb2
7bf7f3521942

f6d6d4fcd180
d88992f66093
f6d6d4fcd180




d88992f66093


221cb2517e8f
d88992f66093
d88992f66093



f6d6d4fcd180



7bf7f3521942






2451337dd043
7bf7f3521942



f6d6d4fcd180
f6d6d4fcd180




06342cf8adb2
f6d6d4fcd180


c7c1a7d8bb45
06342cf8adb2
f6d6d4fcd180





06342cf8adb2
209fb87a259e
f6d6d4fcd180























f6d6d4fcd180













7336cea8c273
f6d6d4fcd180







f6d6d4fcd180
f6d6d4fcd180















1da177e4c3f4
87cbc49cd4b7
046f1685bb52
87cbc49cd4b7
207d041602ce
046f1685bb52
87cbc49cd4b7

8699bb0a4801
207d041602ce

87cbc49cd4b7
207d041602ce

87cbc49cd4b7
e513182d4d7e
8699bb0a4801
87cbc49cd4b7
046f1685bb52
87cbc49cd4b7





1da177e4c3f4
046f1685bb52
1da177e4c3f4
207d041602ce
046f1685bb52
1da177e4c3f4
207d041602ce

1da177e4c3f4
207d041602ce
1da177e4c3f4

f6d6d4fcd180
1da177e4c3f4


a49935f200e2



1da177e4c3f4
a49935f200e2
6ffc4db5de61
10ce444428c2
a49935f200e2

1da177e4c3f4
a49935f200e2

1da177e4c3f4
a49935f200e2





1da177e4c3f4
a49935f200e2





805eeb8e0470
a49935f200e2

805eeb8e0470
a49935f200e2

1da177e4c3f4
a49935f200e2



1da177e4c3f4
a49935f200e2
1da177e4c3f4

1da177e4c3f4





f6d6d4fcd180
1da177e4c3f4


10ce444428c2
207d041602ce
f6d6d4fcd180
2fa24f92530e
1da177e4c3f4
f6d6d4fcd180
9260dc6b2ee0

f6d6d4fcd180
24e17b5fb99d
f6d6d4fcd180
9260dc6b2ee0
1da177e4c3f4
10ce444428c2

529ae9aaa083
10ce444428c2




a49935f200e2
10ce444428c2

24e17b5fb99d

c41564b5af32
9260dc6b2ee0








24e17b5fb99d
9260dc6b2ee0



480d7467e4aa


















24e17b5fb99d
9260dc6b2ee0



24e17b5fb99d
a49935f200e2








1da177e4c3f4

9260dc6b2ee0
1da177e4c3f4
f6d6d4fcd180



a49935f200e2
f6d6d4fcd180

2fa24f92530e

9260dc6b2ee0
0d882a360b90
2fa24f92530e
0d882a360b90
2fa24f92530e
0d882a360b90
9260dc6b2ee0
a49935f200e2




9260dc6b2ee0
ecff71e677c6
0d882a360b90
2fa24f92530e
89f3b363967a


9260dc6b2ee0


2fa24f92530e
a49935f200e2
1da177e4c3f4
7336cea8c273
1da177e4c3f4
f6d6d4fcd180


89f3b363967a
efceab1d5631

89f3b363967a
1da177e4c3f4
89f3b363967a
f6d6d4fcd180

10ce444428c2



1da177e4c3f4









207d041602ce
f6d6d4fcd180
1da177e4c3f4
1da177e4c3f4

10ce444428c2

1da177e4c3f4
10ce444428c2




1da177e4c3f4
10ce444428c2


2fa24f92530e
10ce444428c2





1da177e4c3f4


3ed3a4343b79


d47992f86b30

3ed3a4343b79
34097dfe8850


3ed3a4343b79

























3ed3a4343b79
a49935f200e2
3ed3a4343b79

e8c3753ce4cd


4f10700a2e4b
3ed3a4343b79





3ed3a4343b79
c726de4409a8
3ed3a4343b79



c726de4409a8

3ed3a4343b79

e8c3753ce4cd
4f10700a2e4b
3ed3a4343b79
e8c3753ce4cd
3ed3a4343b79


c726de4409a8
3ed3a4343b79




d47992f86b30
3ed3a4343b79


1da177e4c3f4
89f3b363967a




89f3b363967a
1da177e4c3f4
1da177e4c3f4
89f3b363967a


1da177e4c3f4
89f3b363967a
f6d6d4fcd180
207d041602ce
f6d6d4fcd180
1da177e4c3f4
f6d6d4fcd180
1da177e4c3f4
bd1556a146d4
ed1e7b7e484d
a206c817c864
89f3b363967a
a206c817c864
89f3b363967a
34097dfe8850
89f3b363967a
20cb52ebd1b5

89f3b363967a


d4f7a5cbd544


89f3b363967a
94054fa3fca1

89f3b363967a
94054fa3fca1

b5420f235953
1da177e4c3f4
89f3b363967a
680a647b49fa

89f3b363967a
448011e2ab1c
b5420f235953
89f3b363967a
1da177e4c3f4



8695d27ec34b

























6b7a03f03a2f


ff9a28f6c25d



8695d27ec34b










6b7a03f03a2f
8695d27ec34b

ff9a28f6c25d
6b7a03f03a2f




8695d27ec34b
6b7a03f03a2f



8695d27ec34b


1da177e4c3f4

24e17b5fb99d
24e17b5fb99d
24e17b5fb99d
f6d6d4fcd180
0d882a360b90
a206c817c864
dbcdde3e76f4
a206c817c864
f6d6d4fcd180
1da177e4c3f4
6ac7248ec5f2

1da177e4c3f4



1da177e4c3f4
3d9b02e3c765
ece413f59f25



3d9b02e3c765

3d9b02e3c765



aeea1b1f8180
0d882a360b90

aeea1b1f8180
1da177e4c3f4
aeea1b1f8180
0d882a360b90

aeea1b1f8180
1da177e4c3f4
89f3b363967a
0d882a360b90

85da94c6b466

aeea1b1f8180
7d0fa3ecba2f
aeea1b1f8180
7d0fa3ecba2f






aeea1b1f8180

d5cb48aaac5b
aeea1b1f8180


















ecff71e677c6
0d882a360b90
aeea1b1f8180



1da177e4c3f4
f6d6d4fcd180




1da177e4c3f4



89f3b363967a
1da177e4c3f4
7bf7f3521942











bd1556a146d4












8699bb0a4801
207d041602ce
2fa24f92530e
1da177e4c3f4

281627df3eb5
7bf7f3521942







f6d6d4fcd180
89f3b363967a
1da177e4c3f4

f6d6d4fcd180

1da177e4c3f4
b5420f235953


20cb52ebd1b5
89f3b363967a

1da177e4c3f4
f51623b21fe3
b5420f235953
f51623b21fe3


f51623b21fe3

7d4fb40ad7ef




b3aea4edc290
7d4fb40ad7ef


f51623b21fe3

89f3b363967a
f51623b21fe3

89f3b363967a
f51623b21fe3

238f4c546865
f51623b21fe3


20cb52ebd1b5
f51623b21fe3
34097dfe8850
238f4c546865
20cb52ebd1b5
f51623b21fe3
448011e2ab1c
f51623b21fe3
448011e2ab1c
f51623b21fe3

f51623b21fe3


1da177e4c3f4
c25366680bab
1da177e4c3f4

1da177e4c3f4

f2bde9b89b4d
1da177e4c3f4
a206c817c864




207d041602ce
a206c817c864
fdc7ed75c08d

207d041602ce
a206c817c864

b474c7ae4395
1da177e4c3f4
fdc7ed75c08d
c25366680bab

364f358a734d



507630b29f13







a206c817c864


309ecac8e7c9
a206c817c864
f2bde9b89b4d
d2c281911717


a206c817c864


5c8ed2021ff2

1da177e4c3f4
a206c817c864





aff3a9edb708
507630b29f13






a206c817c864

507630b29f13
2451337dd043
d3bc815afb54
a206c817c864
507630b29f13

d3bc815afb54




507630b29f13
d3bc815afb54

a206c817c864
507630b29f13



a206c817c864
a206c817c864



507630b29f13
a206c817c864



1da177e4c3f4
207d041602ce

87cbc49cd4b7

1da177e4c3f4

207d041602ce


7b7a8665edd8
1da177e4c3f4
7b7a8665edd8

1da177e4c3f4
1da177e4c3f4


c25366680bab



046f1685bb52
1da177e4c3f4
c25366680bab
549054afadae






1da177e4c3f4


549054afadae
207d041602ce
1da177e4c3f4
1da177e4c3f4
207d041602ce
1da177e4c3f4







2b8f12b7e438


0e1f789d0dc3







2b8f12b7e438
c25366680bab
2b8f12b7e438







0e1f789d0dc3





2b8f12b7e438



1da177e4c3f4


a206c817c864


2451337dd043
1da177e4c3f4


c25366680bab
1da177e4c3f4




f2bde9b89b4d
1da177e4c3f4


e4c573bb6a84
1da177e4c3f4

1da177e4c3f4


f2bde9b89b4d
1da177e4c3f4

209fb87a259e





25985edcedea
209fb87a259e



f09738638d3b
209fb87a259e



7b7a8665edd8
f09738638d3b
209fb87a259e
f09738638d3b

2813d682e8e6








209fb87a259e


f09738638d3b
209fb87a259e

ba87ea699ebd

209fb87a259e
0d882a360b90
209fb87a259e
7b7a8665edd8
f09738638d3b

1da177e4c3f4
e4c573bb6a84
1da177e4c3f4

d8d3d94b80aa

1da177e4c3f4
209fb87a259e

281627df3eb5
209fb87a259e


a6cbcd4a4a85
281627df3eb5

437a255aa237



281627df3eb5
0d882a360b90
437a255aa237
281627df3eb5
209fb87a259e
31b140398ce5

9862f62faba8

209fb87a259e
437a255aa237
209fb87a259e
31b140398ce5

eafdc7d190a9
209fb87a259e
f09738638d3b
f09738638d3b
281627df3eb5
281627df3eb5


1da177e4c3f4

d3bc815afb54



































fa9b227e9019

d3bc815afb54



fa9b227e9019
58e59854a3df
d3bc815afb54




fa9b227e9019
58e59854a3df












d3bc815afb54
c726de4409a8
d3bc815afb54





c726de4409a8
d3bc815afb54















4ab9ed578e82









fa9b227e9019
d3bc815afb54
fa9b227e9019

d3bc815afb54





f51623b21fe3
d79689c7038e
f51623b21fe3
d79689c7038e





f51623b21fe3
d3bc815afb54


155130a4f784
d3bc815afb54

ad22c7a043c2
d3bc815afb54





72ab70a19b4e
d3bc815afb54



72ab70a19b4e









d3bc815afb54






fa9b227e9019

d3bc815afb54
aad3f3755e7f





d3bc815afb54
fa9b227e9019










155130a4f784
d3bc815afb54

fa9b227e9019
d3bc815afb54





aad3f3755e7f


d3bc815afb54
aad3f3755e7f
d3bc815afb54

155130a4f784
f51623b21fe3
1da177e4c3f4

e4c573bb6a84
1da177e4c3f4



739bfb2a7dfa
1da177e4c3f4
cca28fb83d9e
126468b11562
4bc1ea6b8ddd
126468b11562
c25366680bab
1da177e4c3f4


e4c573bb6a84
1da177e4c3f4


c25366680bab
1da177e4c3f4


e4c573bb6a84
1da177e4c3f4




c25366680bab
1da177e4c3f4

f5e54d6e53a2
e4c573bb6a84


7d4fb40ad7ef
238f4c546865

d79689c7038e
fa9b227e9019
e4c573bb6a84

e965f9630c65
bddaafa11a54
aa261f549d76
1da177e4c3f4
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
  

                                                 
  

                                                                 

                                             



                                                                   
  


                                                                       
   
                
                       


                           
                   
                   
                      
                      
                      
                           
                      
                      
                      
                      
                     
                          

                           
                      
                      
                        
                          

                            
    


                                          



                                           
                                   


                                       
                                         





                                                 

                            
                                       
 
                                                   

                                                  
                                      




                                                  
  




                                                         



                                       



                                                         
                                                   
         
 



                                            







                                                                          









                                                                      
                                                                    







                                        
                                                                             




                                                                                 






                                                                       
  
                                                                   
   
          
                
                                       
 
                                                             
                                                             
                                      
 
          


                                                                                

                                                            

                                                                                
 
                                      
                                                                   



                                                

         






                                                                    


  
                                                                


                                                                        


                 
                                       

                                                        

                                                                              
                                                       
                                                                               

                                                                            
                                                                          

                                                 
         


  
                       

           
           
                                 
 

                                                                          
                                  
 
                                               
                                       




                            



                                                                           
                                                 


                                                                       
                  






                                                                                
                   

                                                           
                                  
                                               

                                               
                
                                                    
         
 
     
                  
                                        
                                 


  










                                                                              






                                                                     

                                       










                                                                     
                               
                            

                              
                                
                                     
                                     

                             
                                      
 
                                               


                     



                                       
                                      

                                            
 

                                                   
                                                              

                                                    



                                                               
                            
 
                                     
                                                 


                                                      
                                       
                                                

         

                                                           
                                                  
 

                                                         

                                                                 

                                                                    
                                          
 
                  
                             
 
                                      
                                                                 
                                                                   

                                                                                  
                             

         
            
                                       







                                                                          

 
          
               
                                       
                                      
                                       
 
                                    
 

                                                                 

 


                                          
           

                                     



                                                         
                                               
                                                                             

                                                              

                               
                     
 
                                



                     


                                       

                                         

                                     
                                                                            





                                    
                                                                    
                                                                  

                                        
                                                                   
                                  



















                                      




                                            
                        

                                              
                          

                                                                         
                                         

 
                                                                             




                                                                        













                                                                               
                                                                 




                                                                               


                 
                                      

                                       
 
                                              




                                              


                                      
                                                                        
                                                       



                                         



                                      






                                                                               
                                               



                                                
                                                                          




                                                                    
                                                                      


                                           
                                                                        
                                                                      





                                                  
                                                              
                                        























                                                              













                                                                    
                                       







                                                             
 















                                                      
           
               
                                       
                                    
                                      
                                       

                                   
                                                           

                                                                                            
 

                                                       
 
                                                         
                                                            
 
                                                          





                              
                  
                                       
                                    
                                      
                                       
 

                                                       
 
                                                

                               
                                   


  



                                                                                
   
           
                    
                                      

                                                  
 

                                      
 





                                    
 





                                                     
                                                    

                                                                   
                                                     

                                            
 



                                                                                
 
                     

 





                                                                      
          


                                       
                                       
                                      
                                         
                                      
 
                                           

                                           
                                     
                                                
                                                                  
                                                           
 

                                  
                                




                                              
                                                                  

                                      

                                                                        
                                                                         








                                                                            
           



                                                                         


















                                                                                
                                    



                                                                           
 








                                                                              

                                       
                                         
                              



                                                                   
                              

                 

                                                               
                                                 
                                                        
                                                  
                                                       
                            
                                                        
 




                                                                           
 
                                        
                                                     
                                                                           


                                                                 


                                     
                                 
                              
                 
                                                                
 


                                      
                    

                                                   
                                 
         
                                                           

                    



                          









                                                                       
                                      
                                         
                                      

                                      

                                            
 




                                                                                
                              


                                                                               
                                                           





                                       


         


                                      

                                       
 


                                                                   

























                                                                               
 
                                                              

                                    


                                             
                              





                                                                      
                                      
                                          



                                         

                                                                        

                                                          
                                                                
                                                      
                                                                           
                         


                              
                                                




                                                 
                                                        


               
  




                                                                         
                                                                     
   
          


                                      
 
                                                             
                                           
                                     
                                                              
                                       
                                     
                                           
                                                      
                                    
                                                                  
                                          
                                                
 
                                               
 

                                       


                                                                              


                                                                                
          

                                                                            
           

                                                                      
                             
 
          

                                                                          
           
                                                      
                             
 



                                                      

























                                                                              


                                                                           



                                                                              










                                                                                
                   

                                                                        
                                     




                                                                               
                                                                         



                                                                              


                                                              

         
                                    
 
                                       
                                   
                                
 
                                           
                                
 
            

                                  



                                         
 
                  



                                                                            

                                                                



                                       
                                           

                                                        
                                               
                         
                                              

                                                       
                                               
                         
                                                 

                                                        

                                               
                        
                                               
                                                          






                                                                        

                                 
 


















                                                                               
                                        
                                                     



                                                                            
                 




                                                                  



                                      
                                                 
 











                                                                                












                                                                  
 
                                                                        
                                                  

         
 







                                                                             
 
                 

      

                                         
 


                             
                                    

                                
                   
 
        


                                              

 




                                         
                                                               


                                                

                                                              
                                                              

                                  
                                                       

          
                   


                                         
                                                    
 
                                                               
 
                                                          
 
                                   
                         
                                    

                         


                                         
          
                 

                                       

                                           
                                       
 




                                                    
                                     
                                           

                                       
                                        

                                    
                            
 
                                                       

                                                             



                                                              







                                                                           


                                          
                                                         
         
 


                                                        


                                                                

                                                                    
                  





                                                        
                                                       






                                                                               

                                                                        
                                  
                                             
                                
                        

                                                                              




                                                                                
                           

                                                                           
                                                                               



                                                  
                 



                                                                       
                                          



                                                                
 

                                                    

                                                                        

                                                                         


                                                                        
                                     
                                                             

                                                                       
                                                        


                 



                                                                         
                                                           
 
          






                                                                               


                                                                          
                                              
                                          
                                          
 
                                                    







                                                       


                                                                            







                                                                                
           
                                                       







                                                                              





                                                                              



                                                 


                 


                                  
                     


   
               




                                           
                                                                     


          
                      

                                       


                                           
                                                                     

 





                                                                             
                                                                     



                                                                        
           



                                       
                                         
 
                                                       

          








                                                                            


                                                                    
           

                             

                                  
                                
                                                  
 
                                     

 
              
                 

                                      

                                       
 

                                                                        
                                              


                                    
                                                   

                  



                                                                              
                   
                                                                              
                                                              
                                               
 

                                                                          

                                                                          
                                                         
                                               
                

                                                                          
                                                           
         
 
                   
 


                                 

 



































                                                                                

                    



                                       
 
                                             




                                                                   
 












                                                                           
                                           
 





                                                                
 















                                                                         









                                                                              
         
 

 





                                                                                
          
                   
                                      





                                         
 


                                                                
 

                                       
                                                                  





                                                                     
                                                           



                                                           









                                                                           






                                         

 
  





                                                                              
   










                                         
 

                                       
                                                                               





                                                           


                                                                       
                                                                     
                                                                   

                 
                   
 

               
            



                                                                       
                                                   
 
                                        
                                         
                                        
                                           
                                                                  


          
                


                                        
                                                    


          
                 




                                         
                                                                         

 
                                                                      


                                                   
                                                    

                                                        
                                                     
                                                   

                                                   
                                                      
                                                              
                                                            
  
/*
 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "xfs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_mount.h"
#include "xfs_inode.h"
#include "xfs_trans.h"
#include "xfs_inode_item.h"
#include "xfs_alloc.h"
#include "xfs_error.h"
#include "xfs_iomap.h"
#include "xfs_trace.h"
#include "xfs_bmap.h"
#include "xfs_bmap_util.h"
#include "xfs_bmap_btree.h"
#include "xfs_dinode.h"
#include <linux/aio.h>
#include <linux/gfp.h>
#include <linux/mpage.h>
#include <linux/pagevec.h>
#include <linux/writeback.h>

void
xfs_count_page_state(
	struct page		*page,
	int			*delalloc,
	int			*unwritten)
{
	struct buffer_head	*bh, *head;

	*delalloc = *unwritten = 0;

	bh = head = page_buffers(page);
	do {
		if (buffer_unwritten(bh))
			(*unwritten) = 1;
		else if (buffer_delay(bh))
			(*delalloc) = 1;
	} while ((bh = bh->b_this_page) != head);
}

STATIC struct block_device *
xfs_find_bdev_for_inode(
	struct inode		*inode)
{
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_mount	*mp = ip->i_mount;

	if (XFS_IS_REALTIME_INODE(ip))
		return mp->m_rtdev_targp->bt_bdev;
	else
		return mp->m_ddev_targp->bt_bdev;
}

/*
 * We're now finished for good with this ioend structure.
 * Update the page state via the associated buffer_heads,
 * release holds on the inode and bio, and finally free
 * up memory.  Do not use the ioend after this.
 */
STATIC void
xfs_destroy_ioend(
	xfs_ioend_t		*ioend)
{
	struct buffer_head	*bh, *next;

	for (bh = ioend->io_buffer_head; bh; bh = next) {
		next = bh->b_private;
		bh->b_end_io(bh, !ioend->io_error);
	}

	mempool_free(ioend, xfs_ioend_pool);
}

/*
 * Fast and loose check if this write could update the on-disk inode size.
 */
static inline bool xfs_ioend_is_append(struct xfs_ioend *ioend)
{
	return ioend->io_offset + ioend->io_size >
		XFS_I(ioend->io_inode)->i_d.di_size;
}

STATIC int
xfs_setfilesize_trans_alloc(
	struct xfs_ioend	*ioend)
{
	struct xfs_mount	*mp = XFS_I(ioend->io_inode)->i_mount;
	struct xfs_trans	*tp;
	int			error;

	tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);

	error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0);
	if (error) {
		xfs_trans_cancel(tp, 0);
		return error;
	}

	ioend->io_append_trans = tp;

	/*
	 * We may pass freeze protection with a transaction.  So tell lockdep
	 * we released it.
	 */
	rwsem_release(&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
		      1, _THIS_IP_);
	/*
	 * We hand off the transaction to the completion thread now, so
	 * clear the flag here.
	 */
	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
	return 0;
}

/*
 * Update on-disk file size now that data has been written to disk.
 */
STATIC int
xfs_setfilesize(
	struct xfs_ioend	*ioend)
{
	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
	struct xfs_trans	*tp = ioend->io_append_trans;
	xfs_fsize_t		isize;

	/*
	 * The transaction may have been allocated in the I/O submission thread,
	 * thus we need to mark ourselves as beeing in a transaction manually.
	 * Similarly for freeze protection.
	 */
	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
	rwsem_acquire_read(&VFS_I(ip)->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
			   0, 1, _THIS_IP_);

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	isize = xfs_new_eof(ip, ioend->io_offset + ioend->io_size);
	if (!isize) {
		xfs_iunlock(ip, XFS_ILOCK_EXCL);
		xfs_trans_cancel(tp, 0);
		return 0;
	}

	trace_xfs_setfilesize(ip, ioend->io_offset, ioend->io_size);

	ip->i_d.di_size = isize;
	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

	return xfs_trans_commit(tp, 0);
}

/*
 * Schedule IO completion handling on the final put of an ioend.
 *
 * If there is no work to do we might as well call it a day and free the
 * ioend right now.
 */
STATIC void
xfs_finish_ioend(
	struct xfs_ioend	*ioend)
{
	if (atomic_dec_and_test(&ioend->io_remaining)) {
		struct xfs_mount	*mp = XFS_I(ioend->io_inode)->i_mount;

		if (ioend->io_type == XFS_IO_UNWRITTEN)
			queue_work(mp->m_unwritten_workqueue, &ioend->io_work);
		else if (ioend->io_append_trans ||
			 (ioend->io_isdirect && xfs_ioend_is_append(ioend)))
			queue_work(mp->m_data_workqueue, &ioend->io_work);
		else
			xfs_destroy_ioend(ioend);
	}
}

/*
 * IO write completion.
 */
STATIC void
xfs_end_io(
	struct work_struct *work)
{
	xfs_ioend_t	*ioend = container_of(work, xfs_ioend_t, io_work);
	struct xfs_inode *ip = XFS_I(ioend->io_inode);
	int		error = 0;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
		ioend->io_error = -EIO;
		goto done;
	}
	if (ioend->io_error)
		goto done;

	/*
	 * For unwritten extents we need to issue transactions to convert a
	 * range to normal written extens after the data I/O has finished.
	 */
	if (ioend->io_type == XFS_IO_UNWRITTEN) {
		error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
						  ioend->io_size);
	} else if (ioend->io_isdirect && xfs_ioend_is_append(ioend)) {
		/*
		 * For direct I/O we do not know if we need to allocate blocks
		 * or not so we can't preallocate an append transaction as that
		 * results in nested reservations and log space deadlocks. Hence
		 * allocate the transaction here. While this is sub-optimal and
		 * can block IO completion for some time, we're stuck with doing
		 * it this way until we can pass the ioend to the direct IO
		 * allocation callbacks and avoid nesting that way.
		 */
		error = xfs_setfilesize_trans_alloc(ioend);
		if (error)
			goto done;
		error = xfs_setfilesize(ioend);
	} else if (ioend->io_append_trans) {
		error = xfs_setfilesize(ioend);
	} else {
		ASSERT(!xfs_ioend_is_append(ioend));
	}

done:
	if (error)
		ioend->io_error = error;
	xfs_destroy_ioend(ioend);
}

/*
 * Call IO completion handling in caller context on the final put of an ioend.
 */
STATIC void
xfs_finish_ioend_sync(
	struct xfs_ioend	*ioend)
{
	if (atomic_dec_and_test(&ioend->io_remaining))
		xfs_end_io(&ioend->io_work);
}

/*
 * Allocate and initialise an IO completion structure.
 * We need to track unwritten extent write completion here initially.
 * We'll need to extend this for updating the ondisk inode size later
 * (vs. incore size).
 */
STATIC xfs_ioend_t *
xfs_alloc_ioend(
	struct inode		*inode,
	unsigned int		type)
{
	xfs_ioend_t		*ioend;

	ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS);

	/*
	 * Set the count to 1 initially, which will prevent an I/O
	 * completion callback from happening before we have started
	 * all the I/O from calling the completion routine too early.
	 */
	atomic_set(&ioend->io_remaining, 1);
	ioend->io_isdirect = 0;
	ioend->io_error = 0;
	ioend->io_list = NULL;
	ioend->io_type = type;
	ioend->io_inode = inode;
	ioend->io_buffer_head = NULL;
	ioend->io_buffer_tail = NULL;
	ioend->io_offset = 0;
	ioend->io_size = 0;
	ioend->io_append_trans = NULL;

	INIT_WORK(&ioend->io_work, xfs_end_io);
	return ioend;
}

STATIC int
xfs_map_blocks(
	struct inode		*inode,
	loff_t			offset,
	struct xfs_bmbt_irec	*imap,
	int			type,
	int			nonblocking)
{
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_mount	*mp = ip->i_mount;
	ssize_t			count = 1 << inode->i_blkbits;
	xfs_fileoff_t		offset_fsb, end_fsb;
	int			error = 0;
	int			bmapi_flags = XFS_BMAPI_ENTIRE;
	int			nimaps = 1;

	if (XFS_FORCED_SHUTDOWN(mp))
		return -EIO;

	if (type == XFS_IO_UNWRITTEN)
		bmapi_flags |= XFS_BMAPI_IGSTATE;

	if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) {
		if (nonblocking)
			return -EAGAIN;
		xfs_ilock(ip, XFS_ILOCK_SHARED);
	}

	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
	       (ip->i_df.if_flags & XFS_IFEXTENTS));
	ASSERT(offset <= mp->m_super->s_maxbytes);

	if (offset + count > mp->m_super->s_maxbytes)
		count = mp->m_super->s_maxbytes - offset;
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);
	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
				imap, &nimaps, bmapi_flags);
	xfs_iunlock(ip, XFS_ILOCK_SHARED);

	if (error)
		return error;

	if (type == XFS_IO_DELALLOC &&
	    (!nimaps || isnullstartblock(imap->br_startblock))) {
		error = xfs_iomap_write_allocate(ip, offset, imap);
		if (!error)
			trace_xfs_map_blocks_alloc(ip, offset, count, type, imap);
		return error;
	}

#ifdef DEBUG
	if (type == XFS_IO_UNWRITTEN) {
		ASSERT(nimaps);
		ASSERT(imap->br_startblock != HOLESTARTBLOCK);
		ASSERT(imap->br_startblock != DELAYSTARTBLOCK);
	}
#endif
	if (nimaps)
		trace_xfs_map_blocks_found(ip, offset, count, type, imap);
	return 0;
}

STATIC int
xfs_imap_valid(
	struct inode		*inode,
	struct xfs_bmbt_irec	*imap,
	xfs_off_t		offset)
{
	offset >>= inode->i_blkbits;

	return offset >= imap->br_startoff &&
		offset < imap->br_startoff + imap->br_blockcount;
}

/*
 * BIO completion handler for buffered IO.
 */
STATIC void
xfs_end_bio(
	struct bio		*bio,
	int			error)
{
	xfs_ioend_t		*ioend = bio->bi_private;

	ASSERT(atomic_read(&bio->bi_cnt) >= 1);
	ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;

	/* Toss bio and pass work off to an xfsdatad thread */
	bio->bi_private = NULL;
	bio->bi_end_io = NULL;
	bio_put(bio);

	xfs_finish_ioend(ioend);
}

STATIC void
xfs_submit_ioend_bio(
	struct writeback_control *wbc,
	xfs_ioend_t		*ioend,
	struct bio		*bio)
{
	atomic_inc(&ioend->io_remaining);
	bio->bi_private = ioend;
	bio->bi_end_io = xfs_end_bio;
	submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio);
}

STATIC struct bio *
xfs_alloc_ioend_bio(
	struct buffer_head	*bh)
{
	int			nvecs = bio_get_nr_vecs(bh->b_bdev);
	struct bio		*bio = bio_alloc(GFP_NOIO, nvecs);

	ASSERT(bio->bi_private == NULL);
	bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
	bio->bi_bdev = bh->b_bdev;
	return bio;
}

STATIC void
xfs_start_buffer_writeback(
	struct buffer_head	*bh)
{
	ASSERT(buffer_mapped(bh));
	ASSERT(buffer_locked(bh));
	ASSERT(!buffer_delay(bh));
	ASSERT(!buffer_unwritten(bh));

	mark_buffer_async_write(bh);
	set_buffer_uptodate(bh);
	clear_buffer_dirty(bh);
}

STATIC void
xfs_start_page_writeback(
	struct page		*page,
	int			clear_dirty,
	int			buffers)
{
	ASSERT(PageLocked(page));
	ASSERT(!PageWriteback(page));
	if (clear_dirty)
		clear_page_dirty_for_io(page);
	set_page_writeback(page);
	unlock_page(page);
	/* If no buffers on the page are to be written, finish it here */
	if (!buffers)
		end_page_writeback(page);
}

static inline int xfs_bio_add_buffer(struct bio *bio, struct buffer_head *bh)
{
	return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh));
}

/*
 * Submit all of the bios for all of the ioends we have saved up, covering the
 * initial writepage page and also any probed pages.
 *
 * Because we may have multiple ioends spanning a page, we need to start
 * writeback on all the buffers before we submit them for I/O. If we mark the
 * buffers as we got, then we can end up with a page that only has buffers
 * marked async write and I/O complete on can occur before we mark the other
 * buffers async write.
 *
 * The end result of this is that we trip a bug in end_page_writeback() because
 * we call it twice for the one page as the code in end_buffer_async_write()
 * assumes that all buffers on the page are started at the same time.
 *
 * The fix is two passes across the ioend list - one to start writeback on the
 * buffer_heads, and then submit them for I/O on the second pass.
 *
 * If @fail is non-zero, it means that we have a situation where some part of
 * the submission process has failed after we have marked paged for writeback
 * and unlocked them. In this situation, we need to fail the ioend chain rather
 * than submit it to IO. This typically only happens on a filesystem shutdown.
 */
STATIC void
xfs_submit_ioend(
	struct writeback_control *wbc,
	xfs_ioend_t		*ioend,
	int			fail)
{
	xfs_ioend_t		*head = ioend;
	xfs_ioend_t		*next;
	struct buffer_head	*bh;
	struct bio		*bio;
	sector_t		lastblock = 0;

	/* Pass 1 - start writeback */
	do {
		next = ioend->io_list;
		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private)
			xfs_start_buffer_writeback(bh);
	} while ((ioend = next) != NULL);

	/* Pass 2 - submit I/O */
	ioend = head;
	do {
		next = ioend->io_list;
		bio = NULL;

		/*
		 * If we are failing the IO now, just mark the ioend with an
		 * error and finish it. This will run IO completion immediately
		 * as there is only one reference to the ioend at this point in
		 * time.
		 */
		if (fail) {
			ioend->io_error = fail;
			xfs_finish_ioend(ioend);
			continue;
		}

		for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {

			if (!bio) {
 retry:
				bio = xfs_alloc_ioend_bio(bh);
			} else if (bh->b_blocknr != lastblock + 1) {
				xfs_submit_ioend_bio(wbc, ioend, bio);
				goto retry;
			}

			if (xfs_bio_add_buffer(bio, bh) != bh->b_size) {
				xfs_submit_ioend_bio(wbc, ioend, bio);
				goto retry;
			}

			lastblock = bh->b_blocknr;
		}
		if (bio)
			xfs_submit_ioend_bio(wbc, ioend, bio);
		xfs_finish_ioend(ioend);
	} while ((ioend = next) != NULL);
}

/*
 * Cancel submission of all buffer_heads so far in this endio.
 * Toss the endio too.  Only ever called for the initial page
 * in a writepage request, so only ever one page.
 */
STATIC void
xfs_cancel_ioend(
	xfs_ioend_t		*ioend)
{
	xfs_ioend_t		*next;
	struct buffer_head	*bh, *next_bh;

	do {
		next = ioend->io_list;
		bh = ioend->io_buffer_head;
		do {
			next_bh = bh->b_private;
			clear_buffer_async_write(bh);
			unlock_buffer(bh);
		} while ((bh = next_bh) != NULL);

		mempool_free(ioend, xfs_ioend_pool);
	} while ((ioend = next) != NULL);
}

/*
 * Test to see if we've been building up a completion structure for
 * earlier buffers -- if so, we try to append to this ioend if we
 * can, otherwise we finish off any current ioend and start another.
 * Return true if we've finished the given ioend.
 */
STATIC void
xfs_add_to_ioend(
	struct inode		*inode,
	struct buffer_head	*bh,
	xfs_off_t		offset,
	unsigned int		type,
	xfs_ioend_t		**result,
	int			need_ioend)
{
	xfs_ioend_t		*ioend = *result;

	if (!ioend || need_ioend || type != ioend->io_type) {
		xfs_ioend_t	*previous = *result;

		ioend = xfs_alloc_ioend(inode, type);
		ioend->io_offset = offset;
		ioend->io_buffer_head = bh;
		ioend->io_buffer_tail = bh;
		if (previous)
			previous->io_list = ioend;
		*result = ioend;
	} else {
		ioend->io_buffer_tail->b_private = bh;
		ioend->io_buffer_tail = bh;
	}

	bh->b_private = NULL;
	ioend->io_size += bh->b_size;
}

STATIC void
xfs_map_buffer(
	struct inode		*inode,
	struct buffer_head	*bh,
	struct xfs_bmbt_irec	*imap,
	xfs_off_t		offset)
{
	sector_t		bn;
	struct xfs_mount	*m = XFS_I(inode)->i_mount;
	xfs_off_t		iomap_offset = XFS_FSB_TO_B(m, imap->br_startoff);
	xfs_daddr_t		iomap_bn = xfs_fsb_to_db(XFS_I(inode), imap->br_startblock);

	ASSERT(imap->br_startblock != HOLESTARTBLOCK);
	ASSERT(imap->br_startblock != DELAYSTARTBLOCK);

	bn = (iomap_bn >> (inode->i_blkbits - BBSHIFT)) +
	      ((offset - iomap_offset) >> inode->i_blkbits);

	ASSERT(bn || XFS_IS_REALTIME_INODE(XFS_I(inode)));

	bh->b_blocknr = bn;
	set_buffer_mapped(bh);
}

STATIC void
xfs_map_at_offset(
	struct inode		*inode,
	struct buffer_head	*bh,
	struct xfs_bmbt_irec	*imap,
	xfs_off_t		offset)
{
	ASSERT(imap->br_startblock != HOLESTARTBLOCK);
	ASSERT(imap->br_startblock != DELAYSTARTBLOCK);

	xfs_map_buffer(inode, bh, imap, offset);
	set_buffer_mapped(bh);
	clear_buffer_delay(bh);
	clear_buffer_unwritten(bh);
}

/*
 * Test if a given page contains at least one buffer of a given @type.
 * If @check_all_buffers is true, then we walk all the buffers in the page to
 * try to find one of the type passed in. If it is not set, then the caller only
 * needs to check the first buffer on the page for a match.
 */
STATIC bool
xfs_check_page_type(
	struct page		*page,
	unsigned int		type,
	bool			check_all_buffers)
{
	struct buffer_head	*bh;
	struct buffer_head	*head;

	if (PageWriteback(page))
		return false;
	if (!page->mapping)
		return false;
	if (!page_has_buffers(page))
		return false;

	bh = head = page_buffers(page);
	do {
		if (buffer_unwritten(bh)) {
			if (type == XFS_IO_UNWRITTEN)
				return true;
		} else if (buffer_delay(bh)) {
			if (type == XFS_IO_DELALLOC)
				return true;
		} else if (buffer_dirty(bh) && buffer_mapped(bh)) {
			if (type == XFS_IO_OVERWRITE)
				return true;
		}

		/* If we are only checking the first buffer, we are done now. */
		if (!check_all_buffers)
			break;
	} while ((bh = bh->b_this_page) != head);

	return false;
}

/*
 * Allocate & map buffers for page given the extent map. Write it out.
 * except for the original page of a writepage, this is called on
 * delalloc/unwritten pages only, for the original page it is possible
 * that the page has no mapping at all.
 */
STATIC int
xfs_convert_page(
	struct inode		*inode,
	struct page		*page,
	loff_t			tindex,
	struct xfs_bmbt_irec	*imap,
	xfs_ioend_t		**ioendp,
	struct writeback_control *wbc)
{
	struct buffer_head	*bh, *head;
	xfs_off_t		end_offset;
	unsigned long		p_offset;
	unsigned int		type;
	int			len, page_dirty;
	int			count = 0, done = 0, uptodate = 1;
 	xfs_off_t		offset = page_offset(page);

	if (page->index != tindex)
		goto fail;
	if (!trylock_page(page))
		goto fail;
	if (PageWriteback(page))
		goto fail_unlock_page;
	if (page->mapping != inode->i_mapping)
		goto fail_unlock_page;
	if (!xfs_check_page_type(page, (*ioendp)->io_type, false))
		goto fail_unlock_page;

	/*
	 * page_dirty is initially a count of buffers on the page before
	 * EOF and is decremented as we move each into a cleanable state.
	 *
	 * Derivation:
	 *
	 * End offset is the highest offset that this page should represent.
	 * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1))
	 * will evaluate non-zero and be less than PAGE_CACHE_SIZE and
	 * hence give us the correct page_dirty count. On any other page,
	 * it will be zero and in that case we need page_dirty to be the
	 * count of buffers on the page.
	 */
	end_offset = min_t(unsigned long long,
			(xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT,
			i_size_read(inode));

	/*
	 * If the current map does not span the entire page we are about to try
	 * to write, then give up. The only way we can write a page that spans
	 * multiple mappings in a single writeback iteration is via the
	 * xfs_vm_writepage() function. Data integrity writeback requires the
	 * entire page to be written in a single attempt, otherwise the part of
	 * the page we don't write here doesn't get written as part of the data
	 * integrity sync.
	 *
	 * For normal writeback, we also don't attempt to write partial pages
	 * here as it simply means that write_cache_pages() will see it under
	 * writeback and ignore the page until some point in the future, at
	 * which time this will be the only page in the file that needs
	 * writeback.  Hence for more optimal IO patterns, we should always
	 * avoid partial page writeback due to multiple mappings on a page here.
	 */
	if (!xfs_imap_valid(inode, imap, end_offset))
		goto fail_unlock_page;

	len = 1 << inode->i_blkbits;
	p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1),
					PAGE_CACHE_SIZE);
	p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE;
	page_dirty = p_offset / len;

	/*
	 * The moment we find a buffer that doesn't match our current type
	 * specification or can't be written, abort the loop and start
	 * writeback. As per the above xfs_imap_valid() check, only
	 * xfs_vm_writepage() can handle partial page writeback fully - we are
	 * limited here to the buffers that are contiguous with the current
	 * ioend, and hence a buffer we can't write breaks that contiguity and
	 * we have to defer the rest of the IO to xfs_vm_writepage().
	 */
	bh = head = page_buffers(page);
	do {
		if (offset >= end_offset)
			break;
		if (!buffer_uptodate(bh))
			uptodate = 0;
		if (!(PageUptodate(page) || buffer_uptodate(bh))) {
			done = 1;
			break;
		}

		if (buffer_unwritten(bh) || buffer_delay(bh) ||
		    buffer_mapped(bh)) {
			if (buffer_unwritten(bh))
				type = XFS_IO_UNWRITTEN;
			else if (buffer_delay(bh))
				type = XFS_IO_DELALLOC;
			else
				type = XFS_IO_OVERWRITE;

			/*
			 * imap should always be valid because of the above
			 * partial page end_offset check on the imap.
			 */
			ASSERT(xfs_imap_valid(inode, imap, offset));

			lock_buffer(bh);
			if (type != XFS_IO_OVERWRITE)
				xfs_map_at_offset(inode, bh, imap, offset);
			xfs_add_to_ioend(inode, bh, offset, type,
					 ioendp, done);

			page_dirty--;
			count++;
		} else {
			done = 1;
			break;
		}
	} while (offset += len, (bh = bh->b_this_page) != head);

	if (uptodate && bh == head)
		SetPageUptodate(page);

	if (count) {
		if (--wbc->nr_to_write <= 0 &&
		    wbc->sync_mode == WB_SYNC_NONE)
			done = 1;
	}
	xfs_start_page_writeback(page, !page_dirty, count);

	return done;
 fail_unlock_page:
	unlock_page(page);
 fail:
	return 1;
}

/*
 * Convert & write out a cluster of pages in the same extent as defined
 * by mp and following the start page.
 */
STATIC void
xfs_cluster_write(
	struct inode		*inode,
	pgoff_t			tindex,
	struct xfs_bmbt_irec	*imap,
	xfs_ioend_t		**ioendp,
	struct writeback_control *wbc,
	pgoff_t			tlast)
{
	struct pagevec		pvec;
	int			done = 0, i;

	pagevec_init(&pvec, 0);
	while (!done && tindex <= tlast) {
		unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1);

		if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len))
			break;

		for (i = 0; i < pagevec_count(&pvec); i++) {
			done = xfs_convert_page(inode, pvec.pages[i], tindex++,
					imap, ioendp, wbc);
			if (done)
				break;
		}

		pagevec_release(&pvec);
		cond_resched();
	}
}

STATIC void
xfs_vm_invalidatepage(
	struct page		*page,
	unsigned int		offset,
	unsigned int		length)
{
	trace_xfs_invalidatepage(page->mapping->host, page, offset,
				 length);
	block_invalidatepage(page, offset, length);
}

/*
 * If the page has delalloc buffers on it, we need to punch them out before we
 * invalidate the page. If we don't, we leave a stale delalloc mapping on the
 * inode that can trip a BUG() in xfs_get_blocks() later on if a direct IO read
 * is done on that same region - the delalloc extent is returned when none is
 * supposed to be there.
 *
 * We prevent this by truncating away the delalloc regions on the page before
 * invalidating it. Because they are delalloc, we can do this without needing a
 * transaction. Indeed - if we get ENOSPC errors, we have to be able to do this
 * truncation without a transaction as there is no space left for block
 * reservation (typically why we see a ENOSPC in writeback).
 *
 * This is not a performance critical path, so for now just do the punching a
 * buffer head at a time.
 */
STATIC void
xfs_aops_discard_page(
	struct page		*page)
{
	struct inode		*inode = page->mapping->host;
	struct xfs_inode	*ip = XFS_I(inode);
	struct buffer_head	*bh, *head;
	loff_t			offset = page_offset(page);

	if (!xfs_check_page_type(page, XFS_IO_DELALLOC, true))
		goto out_invalidate;

	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
		goto out_invalidate;

	xfs_alert(ip->i_mount,
		"page discard on page %p, inode 0x%llx, offset %llu.",
			page, ip->i_ino, offset);

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	bh = head = page_buffers(page);
	do {
		int		error;
		xfs_fileoff_t	start_fsb;

		if (!buffer_delay(bh))
			goto next_buffer;

		start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
		error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1);
		if (error) {
			/* something screwed, just bail */
			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
				xfs_alert(ip->i_mount,
			"page discard unable to remove delalloc mapping.");
			}
			break;
		}
next_buffer:
		offset += 1 << inode->i_blkbits;

	} while ((bh = bh->b_this_page) != head);

	xfs_iunlock(ip, XFS_ILOCK_EXCL);
out_invalidate:
	xfs_vm_invalidatepage(page, 0, PAGE_CACHE_SIZE);
	return;
}

/*
 * Write out a dirty page.
 *
 * For delalloc space on the page we need to allocate space and flush it.
 * For unwritten space on the page we need to start the conversion to
 * regular allocated space.
 * For any other dirty buffer heads on the page we should flush them.
 */
STATIC int
xfs_vm_writepage(
	struct page		*page,
	struct writeback_control *wbc)
{
	struct inode		*inode = page->mapping->host;
	struct buffer_head	*bh, *head;
	struct xfs_bmbt_irec	imap;
	xfs_ioend_t		*ioend = NULL, *iohead = NULL;
	loff_t			offset;
	unsigned int		type;
	__uint64_t              end_offset;
	pgoff_t                 end_index, last_index;
	ssize_t			len;
	int			err, imap_valid = 0, uptodate = 1;
	int			count = 0;
	int			nonblocking = 0;

	trace_xfs_writepage(inode, page, 0, 0);

	ASSERT(page_has_buffers(page));

	/*
	 * Refuse to write the page out if we are called from reclaim context.
	 *
	 * This avoids stack overflows when called from deeply used stacks in
	 * random callers for direct reclaim or memcg reclaim.  We explicitly
	 * allow reclaim from kswapd as the stack usage there is relatively low.
	 *
	 * This should never happen except in the case of a VM regression so
	 * warn about it.
	 */
	if (WARN_ON_ONCE((current->flags & (PF_MEMALLOC|PF_KSWAPD)) ==
			PF_MEMALLOC))
		goto redirty;

	/*
	 * Given that we do not allow direct reclaim to call us, we should
	 * never be called while in a filesystem transaction.
	 */
	if (WARN_ON_ONCE(current->flags & PF_FSTRANS))
		goto redirty;

	/* Is this page beyond the end of the file? */
	offset = i_size_read(inode);
	end_index = offset >> PAGE_CACHE_SHIFT;
	last_index = (offset - 1) >> PAGE_CACHE_SHIFT;

	/*
	 * The page index is less than the end_index, adjust the end_offset
	 * to the highest offset that this page should represent.
	 * -----------------------------------------------------
	 * |			file mapping	       | <EOF> |
	 * -----------------------------------------------------
	 * | Page ... | Page N-2 | Page N-1 |  Page N  |       |
	 * ^--------------------------------^----------|--------
	 * |     desired writeback range    |      see else    |
	 * ---------------------------------^------------------|
	 */
	if (page->index < end_index)
		end_offset = (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT;
	else {
		/*
		 * Check whether the page to write out is beyond or straddles
		 * i_size or not.
		 * -------------------------------------------------------
		 * |		file mapping		        | <EOF>  |
		 * -------------------------------------------------------
		 * | Page ... | Page N-2 | Page N-1 |  Page N   | Beyond |
		 * ^--------------------------------^-----------|---------
		 * |				    |      Straddles     |
		 * ---------------------------------^-----------|--------|
		 */
		unsigned offset_into_page = offset & (PAGE_CACHE_SIZE - 1);

		/*
		 * Skip the page if it is fully outside i_size, e.g. due to a
		 * truncate operation that is in progress. We must redirty the
		 * page so that reclaim stops reclaiming it. Otherwise
		 * xfs_vm_releasepage() is called on it and gets confused.
		 *
		 * Note that the end_index is unsigned long, it would overflow
		 * if the given offset is greater than 16TB on 32-bit system
		 * and if we do check the page is fully outside i_size or not
		 * via "if (page->index >= end_index + 1)" as "end_index + 1"
		 * will be evaluated to 0.  Hence this page will be redirtied
		 * and be written out repeatedly which would result in an
		 * infinite loop, the user program that perform this operation
		 * will hang.  Instead, we can verify this situation by checking
		 * if the page to write is totally beyond the i_size or if it's
		 * offset is just equal to the EOF.
		 */
		if (page->index > end_index ||
		    (page->index == end_index && offset_into_page == 0))
			goto redirty;

		/*
		 * The page straddles i_size.  It must be zeroed out on each
		 * and every writepage invocation because it may be mmapped.
		 * "A file is mapped in multiples of the page size.  For a file
		 * that is not a multiple of the page size, the remaining
		 * memory is zeroed when mapped, and writes to that region are
		 * not written out to the file."
		 */
		zero_user_segment(page, offset_into_page, PAGE_CACHE_SIZE);

		/* Adjust the end_offset to the end of file */
		end_offset = offset;
	}

	len = 1 << inode->i_blkbits;

	bh = head = page_buffers(page);
	offset = page_offset(page);
	type = XFS_IO_OVERWRITE;

	if (wbc->sync_mode == WB_SYNC_NONE)
		nonblocking = 1;

	do {
		int new_ioend = 0;

		if (offset >= end_offset)
			break;
		if (!buffer_uptodate(bh))
			uptodate = 0;

		/*
		 * set_page_dirty dirties all buffers in a page, independent
		 * of their state.  The dirty state however is entirely
		 * meaningless for holes (!mapped && uptodate), so skip
		 * buffers covering holes here.
		 */
		if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
			imap_valid = 0;
			continue;
		}

		if (buffer_unwritten(bh)) {
			if (type != XFS_IO_UNWRITTEN) {
				type = XFS_IO_UNWRITTEN;
				imap_valid = 0;
			}
		} else if (buffer_delay(bh)) {
			if (type != XFS_IO_DELALLOC) {
				type = XFS_IO_DELALLOC;
				imap_valid = 0;
			}
		} else if (buffer_uptodate(bh)) {
			if (type != XFS_IO_OVERWRITE) {
				type = XFS_IO_OVERWRITE;
				imap_valid = 0;
			}
		} else {
			if (PageUptodate(page))
				ASSERT(buffer_mapped(bh));
			/*
			 * This buffer is not uptodate and will not be
			 * written to disk.  Ensure that we will put any
			 * subsequent writeable buffers into a new
			 * ioend.
			 */
			imap_valid = 0;
			continue;
		}

		if (imap_valid)
			imap_valid = xfs_imap_valid(inode, &imap, offset);
		if (!imap_valid) {
			/*
			 * If we didn't have a valid mapping then we need to
			 * put the new mapping into a separate ioend structure.
			 * This ensures non-contiguous extents always have
			 * separate ioends, which is particularly important
			 * for unwritten extent conversion at I/O completion
			 * time.
			 */
			new_ioend = 1;
			err = xfs_map_blocks(inode, offset, &imap, type,
					     nonblocking);
			if (err)
				goto error;
			imap_valid = xfs_imap_valid(inode, &imap, offset);
		}
		if (imap_valid) {
			lock_buffer(bh);
			if (type != XFS_IO_OVERWRITE)
				xfs_map_at_offset(inode, bh, &imap, offset);
			xfs_add_to_ioend(inode, bh, offset, type, &ioend,
					 new_ioend);
			count++;
		}

		if (!iohead)
			iohead = ioend;

	} while (offset += len, ((bh = bh->b_this_page) != head));

	if (uptodate && bh == head)
		SetPageUptodate(page);

	xfs_start_page_writeback(page, 1, count);

	/* if there is no IO to be submitted for this page, we are done */
	if (!ioend)
		return 0;

	ASSERT(iohead);

	/*
	 * Any errors from this point onwards need tobe reported through the IO
	 * completion path as we have marked the initial page as under writeback
	 * and unlocked it.
	 */
	if (imap_valid) {
		xfs_off_t		end_index;

		end_index = imap.br_startoff + imap.br_blockcount;

		/* to bytes */
		end_index <<= inode->i_blkbits;

		/* to pages */
		end_index = (end_index - 1) >> PAGE_CACHE_SHIFT;

		/* check against file size */
		if (end_index > last_index)
			end_index = last_index;

		xfs_cluster_write(inode, page->index + 1, &imap, &ioend,
				  wbc, end_index);
	}


	/*
	 * Reserve log space if we might write beyond the on-disk inode size.
	 */
	err = 0;
	if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
		err = xfs_setfilesize_trans_alloc(ioend);

	xfs_submit_ioend(wbc, iohead, err);

	return 0;

error:
	if (iohead)
		xfs_cancel_ioend(iohead);

	if (err == -EAGAIN)
		goto redirty;

	xfs_aops_discard_page(page);
	ClearPageUptodate(page);
	unlock_page(page);
	return err;

redirty:
	redirty_page_for_writepage(wbc, page);
	unlock_page(page);
	return 0;
}

STATIC int
xfs_vm_writepages(
	struct address_space	*mapping,
	struct writeback_control *wbc)
{
	xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
	return generic_writepages(mapping, wbc);
}

/*
 * Called to move a page into cleanable state - and from there
 * to be released. The page should already be clean. We always
 * have buffer heads in this call.
 *
 * Returns 1 if the page is ok to release, 0 otherwise.
 */
STATIC int
xfs_vm_releasepage(
	struct page		*page,
	gfp_t			gfp_mask)
{
	int			delalloc, unwritten;

	trace_xfs_releasepage(page->mapping->host, page, 0, 0);

	xfs_count_page_state(page, &delalloc, &unwritten);

	if (WARN_ON_ONCE(delalloc))
		return 0;
	if (WARN_ON_ONCE(unwritten))
		return 0;

	return try_to_free_buffers(page);
}

STATIC int
__xfs_get_blocks(
	struct inode		*inode,
	sector_t		iblock,
	struct buffer_head	*bh_result,
	int			create,
	int			direct)
{
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_mount	*mp = ip->i_mount;
	xfs_fileoff_t		offset_fsb, end_fsb;
	int			error = 0;
	int			lockmode = 0;
	struct xfs_bmbt_irec	imap;
	int			nimaps = 1;
	xfs_off_t		offset;
	ssize_t			size;
	int			new = 0;

	if (XFS_FORCED_SHUTDOWN(mp))
		return -EIO;

	offset = (xfs_off_t)iblock << inode->i_blkbits;
	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
	size = bh_result->b_size;

	if (!create && direct && offset >= i_size_read(inode))
		return 0;

	/*
	 * Direct I/O is usually done on preallocated files, so try getting
	 * a block mapping without an exclusive lock first.  For buffered
	 * writes we already have the exclusive iolock anyway, so avoiding
	 * a lock roundtrip here by taking the ilock exclusive from the
	 * beginning is a useful micro optimization.
	 */
	if (create && !direct) {
		lockmode = XFS_ILOCK_EXCL;
		xfs_ilock(ip, lockmode);
	} else {
		lockmode = xfs_ilock_data_map_shared(ip);
	}

	ASSERT(offset <= mp->m_super->s_maxbytes);
	if (offset + size > mp->m_super->s_maxbytes)
		size = mp->m_super->s_maxbytes - offset;
	end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size);
	offset_fsb = XFS_B_TO_FSBT(mp, offset);

	error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
				&imap, &nimaps, XFS_BMAPI_ENTIRE);
	if (error)
		goto out_unlock;

	if (create &&
	    (!nimaps ||
	     (imap.br_startblock == HOLESTARTBLOCK ||
	      imap.br_startblock == DELAYSTARTBLOCK))) {
		if (direct || xfs_get_extsz_hint(ip)) {
			/*
			 * Drop the ilock in preparation for starting the block
			 * allocation transaction.  It will be retaken
			 * exclusively inside xfs_iomap_write_direct for the
			 * actual allocation.
			 */
			xfs_iunlock(ip, lockmode);
			error = xfs_iomap_write_direct(ip, offset, size,
						       &imap, nimaps);
			if (error)
				return error;
			new = 1;
		} else {
			/*
			 * Delalloc reservations do not require a transaction,
			 * we can go on without dropping the lock here. If we
			 * are allocating a new delalloc block, make sure that
			 * we set the new flag so that we mark the buffer new so
			 * that we know that it is newly allocated if the write
			 * fails.
			 */
			if (nimaps && imap.br_startblock == HOLESTARTBLOCK)
				new = 1;
			error = xfs_iomap_write_delay(ip, offset, size, &imap);
			if (error)
				goto out_unlock;

			xfs_iunlock(ip, lockmode);
		}

		trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap);
	} else if (nimaps) {
		trace_xfs_get_blocks_found(ip, offset, size, 0, &imap);
		xfs_iunlock(ip, lockmode);
	} else {
		trace_xfs_get_blocks_notfound(ip, offset, size);
		goto out_unlock;
	}

	if (imap.br_startblock != HOLESTARTBLOCK &&
	    imap.br_startblock != DELAYSTARTBLOCK) {
		/*
		 * For unwritten extents do not report a disk address on
		 * the read case (treat as if we're reading into a hole).
		 */
		if (create || !ISUNWRITTEN(&imap))
			xfs_map_buffer(inode, bh_result, &imap, offset);
		if (create && ISUNWRITTEN(&imap)) {
			if (direct) {
				bh_result->b_private = inode;
				set_buffer_defer_completion(bh_result);
			}
			set_buffer_unwritten(bh_result);
		}
	}

	/*
	 * If this is a realtime file, data may be on a different device.
	 * to that pointed to from the buffer_head b_bdev currently.
	 */
	bh_result->b_bdev = xfs_find_bdev_for_inode(inode);

	/*
	 * If we previously allocated a block out beyond eof and we are now
	 * coming back to use it then we will need to flag it as new even if it
	 * has a disk address.
	 *
	 * With sub-block writes into unwritten extents we also need to mark
	 * the buffer as new so that the unwritten parts of the buffer gets
	 * correctly zeroed.
	 */
	if (create &&
	    ((!buffer_mapped(bh_result) && !buffer_uptodate(bh_result)) ||
	     (offset >= i_size_read(inode)) ||
	     (new || ISUNWRITTEN(&imap))))
		set_buffer_new(bh_result);

	if (imap.br_startblock == DELAYSTARTBLOCK) {
		BUG_ON(direct);
		if (create) {
			set_buffer_uptodate(bh_result);
			set_buffer_mapped(bh_result);
			set_buffer_delay(bh_result);
		}
	}

	/*
	 * If this is O_DIRECT or the mpage code calling tell them how large
	 * the mapping is, so that we can avoid repeated get_blocks calls.
	 *
	 * If the mapping spans EOF, then we have to break the mapping up as the
	 * mapping for blocks beyond EOF must be marked new so that sub block
	 * regions can be correctly zeroed. We can't do this for mappings within
	 * EOF unless the mapping was just allocated or is unwritten, otherwise
	 * the callers would overwrite existing data with zeros. Hence we have
	 * to split the mapping into a range up to and including EOF, and a
	 * second mapping for beyond EOF.
	 */
	if (direct || size > (1 << inode->i_blkbits)) {
		xfs_off_t		mapping_size;

		mapping_size = imap.br_startoff + imap.br_blockcount - iblock;
		mapping_size <<= inode->i_blkbits;

		ASSERT(mapping_size > 0);
		if (mapping_size > size)
			mapping_size = size;
		if (offset < i_size_read(inode) &&
		    offset + mapping_size >= i_size_read(inode)) {
			/* limit mapping to block that spans EOF */
			mapping_size = roundup_64(i_size_read(inode) - offset,
						  1 << inode->i_blkbits);
		}
		if (mapping_size > LONG_MAX)
			mapping_size = LONG_MAX;

		bh_result->b_size = mapping_size;
	}

	return 0;

out_unlock:
	xfs_iunlock(ip, lockmode);
	return error;
}

int
xfs_get_blocks(
	struct inode		*inode,
	sector_t		iblock,
	struct buffer_head	*bh_result,
	int			create)
{
	return __xfs_get_blocks(inode, iblock, bh_result, create, 0);
}

STATIC int
xfs_get_blocks_direct(
	struct inode		*inode,
	sector_t		iblock,
	struct buffer_head	*bh_result,
	int			create)
{
	return __xfs_get_blocks(inode, iblock, bh_result, create, 1);
}

/*
 * Complete a direct I/O write request.
 *
 * If the private argument is non-NULL __xfs_get_blocks signals us that we
 * need to issue a transaction to convert the range from unwritten to written
 * extents.  In case this is regular synchronous I/O we just call xfs_end_io
 * to do this and we are done.  But in case this was a successful AIO
 * request this handler is called from interrupt context, from which we
 * can't start transactions.  In that case offload the I/O completion to
 * the workqueues we also use for buffered I/O completion.
 */
STATIC void
xfs_end_io_direct_write(
	struct kiocb		*iocb,
	loff_t			offset,
	ssize_t			size,
	void			*private)
{
	struct xfs_ioend	*ioend = iocb->private;

	/*
	 * While the generic direct I/O code updates the inode size, it does
	 * so only after the end_io handler is called, which means our
	 * end_io handler thinks the on-disk size is outside the in-core
	 * size.  To prevent this just update it a little bit earlier here.
	 */
	if (offset + size > i_size_read(ioend->io_inode))
		i_size_write(ioend->io_inode, offset + size);

	/*
	 * blockdev_direct_IO can return an error even after the I/O
	 * completion handler was called.  Thus we need to protect
	 * against double-freeing.
	 */
	iocb->private = NULL;

	ioend->io_offset = offset;
	ioend->io_size = size;
	if (private && size > 0)
		ioend->io_type = XFS_IO_UNWRITTEN;

	xfs_finish_ioend_sync(ioend);
}

STATIC ssize_t
xfs_vm_direct_IO(
	int			rw,
	struct kiocb		*iocb,
	struct iov_iter		*iter,
	loff_t			offset)
{
	struct inode		*inode = iocb->ki_filp->f_mapping->host;
	struct block_device	*bdev = xfs_find_bdev_for_inode(inode);
	struct xfs_ioend	*ioend = NULL;
	ssize_t			ret;

	if (rw & WRITE) {
		size_t size = iov_iter_count(iter);

		/*
		 * We cannot preallocate a size update transaction here as we
		 * don't know whether allocation is necessary or not. Hence we
		 * can only tell IO completion that one is necessary if we are
		 * not doing unwritten extent conversion.
		 */
		iocb->private = ioend = xfs_alloc_ioend(inode, XFS_IO_DIRECT);
		if (offset + size > XFS_I(inode)->i_d.di_size)
			ioend->io_isdirect = 1;

		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
					    offset, xfs_get_blocks_direct,
					    xfs_end_io_direct_write, NULL,
					    DIO_ASYNC_EXTEND);
		if (ret != -EIOCBQUEUED && iocb->private)
			goto out_destroy_ioend;
	} else {
		ret = __blockdev_direct_IO(rw, iocb, inode, bdev, iter,
					    offset, xfs_get_blocks_direct,
					    NULL, NULL, 0);
	}

	return ret;

out_destroy_ioend:
	xfs_destroy_ioend(ioend);
	return ret;
}

/*
 * Punch out the delalloc blocks we have already allocated.
 *
 * Don't bother with xfs_setattr given that nothing can have made it to disk yet
 * as the page is still locked at this point.
 */
STATIC void
xfs_vm_kill_delalloc_range(
	struct inode		*inode,
	loff_t			start,
	loff_t			end)
{
	struct xfs_inode	*ip = XFS_I(inode);
	xfs_fileoff_t		start_fsb;
	xfs_fileoff_t		end_fsb;
	int			error;

	start_fsb = XFS_B_TO_FSB(ip->i_mount, start);
	end_fsb = XFS_B_TO_FSB(ip->i_mount, end);
	if (end_fsb <= start_fsb)
		return;

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	error = xfs_bmap_punch_delalloc_range(ip, start_fsb,
						end_fsb - start_fsb);
	if (error) {
		/* something screwed, just bail */
		if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
			xfs_alert(ip->i_mount,
		"xfs_vm_write_failed: unable to clean up ino %lld",
					ip->i_ino);
		}
	}
	xfs_iunlock(ip, XFS_ILOCK_EXCL);
}

STATIC void
xfs_vm_write_failed(
	struct inode		*inode,
	struct page		*page,
	loff_t			pos,
	unsigned		len)
{
	loff_t			block_offset;
	loff_t			block_start;
	loff_t			block_end;
	loff_t			from = pos & (PAGE_CACHE_SIZE - 1);
	loff_t			to = from + len;
	struct buffer_head	*bh, *head;

	/*
	 * The request pos offset might be 32 or 64 bit, this is all fine
	 * on 64-bit platform.  However, for 64-bit pos request on 32-bit
	 * platform, the high 32-bit will be masked off if we evaluate the
	 * block_offset via (pos & PAGE_MASK) because the PAGE_MASK is
	 * 0xfffff000 as an unsigned long, hence the result is incorrect
	 * which could cause the following ASSERT failed in most cases.
	 * In order to avoid this, we can evaluate the block_offset of the
	 * start of the page by using shifts rather than masks the mismatch
	 * problem.
	 */
	block_offset = (pos >> PAGE_CACHE_SHIFT) << PAGE_CACHE_SHIFT;

	ASSERT(block_offset + from == pos);

	head = page_buffers(page);
	block_start = 0;
	for (bh = head; bh != head || !block_start;
	     bh = bh->b_this_page, block_start = block_end,
				   block_offset += bh->b_size) {
		block_end = block_start + bh->b_size;

		/* skip buffers before the write */
		if (block_end <= from)
			continue;

		/* if the buffer is after the write, we're done */
		if (block_start >= to)
			break;

		if (!buffer_delay(bh))