|
root / base / usr / src / uts / common / sys / fs
fs Plain Text 13550 lines 430.4 KB
    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
 1771
 1772
 1773
 1774
 1775
 1776
 1777
 1778
 1779
 1780
 1781
 1782
 1783
 1784
 1785
 1786
 1787
 1788
 1789
 1790
 1791
 1792
 1793
 1794
 1795
 1796
 1797
 1798
 1799
 1800
 1801
 1802
 1803
 1804
 1805
 1806
 1807
 1808
 1809
 1810
 1811
 1812
 1813
 1814
 1815
 1816
 1817
 1818
 1819
 1820
 1821
 1822
 1823
 1824
 1825
 1826
 1827
 1828
 1829
 1830
 1831
 1832
 1833
 1834
 1835
 1836
 1837
 1838
 1839
 1840
 1841
 1842
 1843
 1844
 1845
 1846
 1847
 1848
 1849
 1850
 1851
 1852
 1853
 1854
 1855
 1856
 1857
 1858
 1859
 1860
 1861
 1862
 1863
 1864
 1865
 1866
 1867
 1868
 1869
 1870
 1871
 1872
 1873
 1874
 1875
 1876
 1877
 1878
 1879
 1880
 1881
 1882
 1883
 1884
 1885
 1886
 1887
 1888
 1889
 1890
 1891
 1892
 1893
 1894
 1895
 1896
 1897
 1898
 1899
 1900
 1901
 1902
 1903
 1904
 1905
 1906
 1907
 1908
 1909
 1910
 1911
 1912
 1913
 1914
 1915
 1916
 1917
 1918
 1919
 1920
 1921
 1922
 1923
 1924
 1925
 1926
 1927
 1928
 1929
 1930
 1931
 1932
 1933
 1934
 1935
 1936
 1937
 1938
 1939
 1940
 1941
 1942
 1943
 1944
 1945
 1946
 1947
 1948
 1949
 1950
 1951
 1952
 1953
 1954
 1955
 1956
 1957
 1958
 1959
 1960
 1961
 1962
 1963
 1964
 1965
 1966
 1967
 1968
 1969
 1970
 1971
 1972
 1973
 1974
 1975
 1976
 1977
 1978
 1979
 1980
 1981
 1982
 1983
 1984
 1985
 1986
 1987
 1988
 1989
 1990
 1991
 1992
 1993
 1994
 1995
 1996
 1997
 1998
 1999
 2000
 2001
 2002
 2003
 2004
 2005
 2006
 2007
 2008
 2009
 2010
 2011
 2012
 2013
 2014
 2015
 2016
 2017
 2018
 2019
 2020
 2021
 2022
 2023
 2024
 2025
 2026
 2027
 2028
 2029
 2030
 2031
 2032
 2033
 2034
 2035
 2036
 2037
 2038
 2039
 2040
 2041
 2042
 2043
 2044
 2045
 2046
 2047
 2048
 2049
 2050
 2051
 2052
 2053
 2054
 2055
 2056
 2057
 2058
 2059
 2060
 2061
 2062
 2063
 2064
 2065
 2066
 2067
 2068
 2069
 2070
 2071
 2072
 2073
 2074
 2075
 2076
 2077
 2078
 2079
 2080
 2081
 2082
 2083
 2084
 2085
 2086
 2087
 2088
 2089
 2090
 2091
 2092
 2093
 2094
 2095
 2096
 2097
 2098
 2099
 2100
 2101
 2102
 2103
 2104
 2105
 2106
 2107
 2108
 2109
 2110
 2111
 2112
 2113
 2114
 2115
 2116
 2117
 2118
 2119
 2120
 2121
 2122
 2123
 2124
 2125
 2126
 2127
 2128
 2129
 2130
 2131
 2132
 2133
 2134
 2135
 2136
 2137
 2138
 2139
 2140
 2141
 2142
 2143
 2144
 2145
 2146
 2147
 2148
 2149
 2150
 2151
 2152
 2153
 2154
 2155
 2156
 2157
 2158
 2159
 2160
 2161
 2162
 2163
 2164
 2165
 2166
 2167
 2168
 2169
 2170
 2171
 2172
 2173
 2174
 2175
 2176
 2177
 2178
 2179
 2180
 2181
 2182
 2183
 2184
 2185
 2186
 2187
 2188
 2189
 2190
 2191
 2192
 2193
 2194
 2195
 2196
 2197
 2198
 2199
 2200
 2201
 2202
 2203
 2204
 2205
 2206
 2207
 2208
 2209
 2210
 2211
 2212
 2213
 2214
 2215
 2216
 2217
 2218
 2219
 2220
 2221
 2222
 2223
 2224
 2225
 2226
 2227
 2228
 2229
 2230
 2231
 2232
 2233
 2234
 2235
 2236
 2237
 2238
 2239
 2240
 2241
 2242
 2243
 2244
 2245
 2246
 2247
 2248
 2249
 2250
 2251
 2252
 2253
 2254
 2255
 2256
 2257
 2258
 2259
 2260
 2261
 2262
 2263
 2264
 2265
 2266
 2267
 2268
 2269
 2270
 2271
 2272
 2273
 2274
 2275
 2276
 2277
 2278
 2279
 2280
 2281
 2282
 2283
 2284
 2285
 2286
 2287
 2288
 2289
 2290
 2291
 2292
 2293
 2294
 2295
 2296
 2297
 2298
 2299
 2300
 2301
 2302
 2303
 2304
 2305
 2306
 2307
 2308
 2309
 2310
 2311
 2312
 2313
 2314
 2315
 2316
 2317
 2318
 2319
 2320
 2321
 2322
 2323
 2324
 2325
 2326
 2327
 2328
 2329
 2330
 2331
 2332
 2333
 2334
 2335
 2336
 2337
 2338
 2339
 2340
 2341
 2342
 2343
 2344
 2345
 2346
 2347
 2348
 2349
 2350
 2351
 2352
 2353
 2354
 2355
 2356
 2357
 2358
 2359
 2360
 2361
 2362
 2363
 2364
 2365
 2366
 2367
 2368
 2369
 2370
 2371
 2372
 2373
 2374
 2375
 2376
 2377
 2378
 2379
 2380
 2381
 2382
 2383
 2384
 2385
 2386
 2387
 2388
 2389
 2390
 2391
 2392
 2393
 2394
 2395
 2396
 2397
 2398
 2399
 2400
 2401
 2402
 2403
 2404
 2405
 2406
 2407
 2408
 2409
 2410
 2411
 2412
 2413
 2414
 2415
 2416
 2417
 2418
 2419
 2420
 2421
 2422
 2423
 2424
 2425
 2426
 2427
 2428
 2429
 2430
 2431
 2432
 2433
 2434
 2435
 2436
 2437
 2438
 2439
 2440
 2441
 2442
 2443
 2444
 2445
 2446
 2447
 2448
 2449
 2450
 2451
 2452
 2453
 2454
 2455
 2456
 2457
 2458
 2459
 2460
 2461
 2462
 2463
 2464
 2465
 2466
 2467
 2468
 2469
 2470
 2471
 2472
 2473
 2474
 2475
 2476
 2477
 2478
 2479
 2480
 2481
 2482
 2483
 2484
 2485
 2486
 2487
 2488
 2489
 2490
 2491
 2492
 2493
 2494
 2495
 2496
 2497
 2498
 2499
 2500
 2501
 2502
 2503
 2504
 2505
 2506
 2507
 2508
 2509
 2510
 2511
 2512
 2513
 2514
 2515
 2516
 2517
 2518
 2519
 2520
 2521
 2522
 2523
 2524
 2525
 2526
 2527
 2528
 2529
 2530
 2531
 2532
 2533
 2534
 2535
 2536
 2537
 2538
 2539
 2540
 2541
 2542
 2543
 2544
 2545
 2546
 2547
 2548
 2549
 2550
 2551
 2552
 2553
 2554
 2555
 2556
 2557
 2558
 2559
 2560
 2561
 2562
 2563
 2564
 2565
 2566
 2567
 2568
 2569
 2570
 2571
 2572
 2573
 2574
 2575
 2576
 2577
 2578
 2579
 2580
 2581
 2582
 2583
 2584
 2585
 2586
 2587
 2588
 2589
 2590
 2591
 2592
 2593
 2594
 2595
 2596
 2597
 2598
 2599
 2600
 2601
 2602
 2603
 2604
 2605
 2606
 2607
 2608
 2609
 2610
 2611
 2612
 2613
 2614
 2615
 2616
 2617
 2618
 2619
 2620
 2621
 2622
 2623
 2624
 2625
 2626
 2627
 2628
 2629
 2630
 2631
 2632
 2633
 2634
 2635
 2636
 2637
 2638
 2639
 2640
 2641
 2642
 2643
 2644
 2645
 2646
 2647
 2648
 2649
 2650
 2651
 2652
 2653
 2654
 2655
 2656
 2657
 2658
 2659
 2660
 2661
 2662
 2663
 2664
 2665
 2666
 2667
 2668
 2669
 2670
 2671
 2672
 2673
 2674
 2675
 2676
 2677
 2678
 2679
 2680
 2681
 2682
 2683
 2684
 2685
 2686
 2687
 2688
 2689
 2690
 2691
 2692
 2693
 2694
 2695
 2696
 2697
 2698
 2699
 2700
 2701
 2702
 2703
 2704
 2705
 2706
 2707
 2708
 2709
 2710
 2711
 2712
 2713
 2714
 2715
 2716
 2717
 2718
 2719
 2720
 2721
 2722
 2723
 2724
 2725
 2726
 2727
 2728
 2729
 2730
 2731
 2732
 2733
 2734
 2735
 2736
 2737
 2738
 2739
 2740
 2741
 2742
 2743
 2744
 2745
 2746
 2747
 2748
 2749
 2750
 2751
 2752
 2753
 2754
 2755
 2756
 2757
 2758
 2759
 2760
 2761
 2762
 2763
 2764
 2765
 2766
 2767
 2768
 2769
 2770
 2771
 2772
 2773
 2774
 2775
 2776
 2777
 2778
 2779
 2780
 2781
 2782
 2783
 2784
 2785
 2786
 2787
 2788
 2789
 2790
 2791
 2792
 2793
 2794
 2795
 2796
 2797
 2798
 2799
 2800
 2801
 2802
 2803
 2804
 2805
 2806
 2807
 2808
 2809
 2810
 2811
 2812
 2813
 2814
 2815
 2816
 2817
 2818
 2819
 2820
 2821
 2822
 2823
 2824
 2825
 2826
 2827
 2828
 2829
 2830
 2831
 2832
 2833
 2834
 2835
 2836
 2837
 2838
 2839
 2840
 2841
 2842
 2843
 2844
 2845
 2846
 2847
 2848
 2849
 2850
 2851
 2852
 2853
 2854
 2855
 2856
 2857
 2858
 2859
 2860
 2861
 2862
 2863
 2864
 2865
 2866
 2867
 2868
 2869
 2870
 2871
 2872
 2873
 2874
 2875
 2876
 2877
 2878
 2879
 2880
 2881
 2882
 2883
 2884
 2885
 2886
 2887
 2888
 2889
 2890
 2891
 2892
 2893
 2894
 2895
 2896
 2897
 2898
 2899
 2900
 2901
 2902
 2903
 2904
 2905
 2906
 2907
 2908
 2909
 2910
 2911
 2912
 2913
 2914
 2915
 2916
 2917
 2918
 2919
 2920
 2921
 2922
 2923
 2924
 2925
 2926
 2927
 2928
 2929
 2930
 2931
 2932
 2933
 2934
 2935
 2936
 2937
 2938
 2939
 2940
 2941
 2942
 2943
 2944
 2945
 2946
 2947
 2948
 2949
 2950
 2951
 2952
 2953
 2954
 2955
 2956
 2957
 2958
 2959
 2960
 2961
 2962
 2963
 2964
 2965
 2966
 2967
 2968
 2969
 2970
 2971
 2972
 2973
 2974
 2975
 2976
 2977
 2978
 2979
 2980
 2981
 2982
 2983
 2984
 2985
 2986
 2987
 2988
 2989
 2990
 2991
 2992
 2993
 2994
 2995
 2996
 2997
 2998
 2999
 3000
 3001
 3002
 3003
 3004
 3005
 3006
 3007
 3008
 3009
 3010
 3011
 3012
 3013
 3014
 3015
 3016
 3017
 3018
 3019
 3020
 3021
 3022
 3023
 3024
 3025
 3026
 3027
 3028
 3029
 3030
 3031
 3032
 3033
 3034
 3035
 3036
 3037
 3038
 3039
 3040
 3041
 3042
 3043
 3044
 3045
 3046
 3047
 3048
 3049
 3050
 3051
 3052
 3053
 3054
 3055
 3056
 3057
 3058
 3059
 3060
 3061
 3062
 3063
 3064
 3065
 3066
 3067
 3068
 3069
 3070
 3071
 3072
 3073
 3074
 3075
 3076
 3077
 3078
 3079
 3080
 3081
 3082
 3083
 3084
 3085
 3086
 3087
 3088
 3089
 3090
 3091
 3092
 3093
 3094
 3095
 3096
 3097
 3098
 3099
 3100
 3101
 3102
 3103
 3104
 3105
 3106
 3107
 3108
 3109
 3110
 3111
 3112
 3113
 3114
 3115
 3116
 3117
 3118
 3119
 3120
 3121
 3122
 3123
 3124
 3125
 3126
 3127
 3128
 3129
 3130
 3131
 3132
 3133
 3134
 3135
 3136
 3137
 3138
 3139
 3140
 3141
 3142
 3143
 3144
 3145
 3146
 3147
 3148
 3149
 3150
 3151
 3152
 3153
 3154
 3155
 3156
 3157
 3158
 3159
 3160
 3161
 3162
 3163
 3164
 3165
 3166
 3167
 3168
 3169
 3170
 3171
 3172
 3173
 3174
 3175
 3176
 3177
 3178
 3179
 3180
 3181
 3182
 3183
 3184
 3185
 3186
 3187
 3188
 3189
 3190
 3191
 3192
 3193
 3194
 3195
 3196
 3197
 3198
 3199
 3200
 3201
 3202
 3203
 3204
 3205
 3206
 3207
 3208
 3209
 3210
 3211
 3212
 3213
 3214
 3215
 3216
 3217
 3218
 3219
 3220
 3221
 3222
 3223
 3224
 3225
 3226
 3227
 3228
 3229
 3230
 3231
 3232
 3233
 3234
 3235
 3236
 3237
 3238
 3239
 3240
 3241
 3242
 3243
 3244
 3245
 3246
 3247
 3248
 3249
 3250
 3251
 3252
 3253
 3254
 3255
 3256
 3257
 3258
 3259
 3260
 3261
 3262
 3263
 3264
 3265
 3266
 3267
 3268
 3269
 3270
 3271
 3272
 3273
 3274
 3275
 3276
 3277
 3278
 3279
 3280
 3281
 3282
 3283
 3284
 3285
 3286
 3287
 3288
 3289
 3290
 3291
 3292
 3293
 3294
 3295
 3296
 3297
 3298
 3299
 3300
 3301
 3302
 3303
 3304
 3305
 3306
 3307
 3308
 3309
 3310
 3311
 3312
 3313
 3314
 3315
 3316
 3317
 3318
 3319
 3320
 3321
 3322
 3323
 3324
 3325
 3326
 3327
 3328
 3329
 3330
 3331
 3332
 3333
 3334
 3335
 3336
 3337
 3338
 3339
 3340
 3341
 3342
 3343
 3344
 3345
 3346
 3347
 3348
 3349
 3350
 3351
 3352
 3353
 3354
 3355
 3356
 3357
 3358
 3359
 3360
 3361
 3362
 3363
 3364
 3365
 3366
 3367
 3368
 3369
 3370
 3371
 3372
 3373
 3374
 3375
 3376
 3377
 3378
 3379
 3380
 3381
 3382
 3383
 3384
 3385
 3386
 3387
 3388
 3389
 3390
 3391
 3392
 3393
 3394
 3395
 3396
 3397
 3398
 3399
 3400
 3401
 3402
 3403
 3404
 3405
 3406
 3407
 3408
 3409
 3410
 3411
 3412
 3413
 3414
 3415
 3416
 3417
 3418
 3419
 3420
 3421
 3422
 3423
 3424
 3425
 3426
 3427
 3428
 3429
 3430
 3431
 3432
 3433
 3434
 3435
 3436
 3437
 3438
 3439
 3440
 3441
 3442
 3443
 3444
 3445
 3446
 3447
 3448
 3449
 3450
 3451
 3452
 3453
 3454
 3455
 3456
 3457
 3458
 3459
 3460
 3461
 3462
 3463
 3464
 3465
 3466
 3467
 3468
 3469
 3470
 3471
 3472
 3473
 3474
 3475
 3476
 3477
 3478
 3479
 3480
 3481
 3482
 3483
 3484
 3485
 3486
 3487
 3488
 3489
 3490
 3491
 3492
 3493
 3494
 3495
 3496
 3497
 3498
 3499
 3500
 3501
 3502
 3503
 3504
 3505
 3506
 3507
 3508
 3509
 3510
 3511
 3512
 3513
 3514
 3515
 3516
 3517
 3518
 3519
 3520
 3521
 3522
 3523
 3524
 3525
 3526
 3527
 3528
 3529
 3530
 3531
 3532
 3533
 3534
 3535
 3536
 3537
 3538
 3539
 3540
 3541
 3542
 3543
 3544
 3545
 3546
 3547
 3548
 3549
 3550
 3551
 3552
 3553
 3554
 3555
 3556
 3557
 3558
 3559
 3560
 3561
 3562
 3563
 3564
 3565
 3566
 3567
 3568
 3569
 3570
 3571
 3572
 3573
 3574
 3575
 3576
 3577
 3578
 3579
 3580
 3581
 3582
 3583
 3584
 3585
 3586
 3587
 3588
 3589
 3590
 3591
 3592
 3593
 3594
 3595
 3596
 3597
 3598
 3599
 3600
 3601
 3602
 3603
 3604
 3605
 3606
 3607
 3608
 3609
 3610
 3611
 3612
 3613
 3614
 3615
 3616
 3617
 3618
 3619
 3620
 3621
 3622
 3623
 3624
 3625
 3626
 3627
 3628
 3629
 3630
 3631
 3632
 3633
 3634
 3635
 3636
 3637
 3638
 3639
 3640
 3641
 3642
 3643
 3644
 3645
 3646
 3647
 3648
 3649
 3650
 3651
 3652
 3653
 3654
 3655
 3656
 3657
 3658
 3659
 3660
 3661
 3662
 3663
 3664
 3665
 3666
 3667
 3668
 3669
 3670
 3671
 3672
 3673
 3674
 3675
 3676
 3677
 3678
 3679
 3680
 3681
 3682
 3683
 3684
 3685
 3686
 3687
 3688
 3689
 3690
 3691
 3692
 3693
 3694
 3695
 3696
 3697
 3698
 3699
 3700
 3701
 3702
 3703
 3704
 3705
 3706
 3707
 3708
 3709
 3710
 3711
 3712
 3713
 3714
 3715
 3716
 3717
 3718
 3719
 3720
 3721
 3722
 3723
 3724
 3725
 3726
 3727
 3728
 3729
 3730
 3731
 3732
 3733
 3734
 3735
 3736
 3737
 3738
 3739
 3740
 3741
 3742
 3743
 3744
 3745
 3746
 3747
 3748
 3749
 3750
 3751
 3752
 3753
 3754
 3755
 3756
 3757
 3758
 3759
 3760
 3761
 3762
 3763
 3764
 3765
 3766
 3767
 3768
 3769
 3770
 3771
 3772
 3773
 3774
 3775
 3776
 3777
 3778
 3779
 3780
 3781
 3782
 3783
 3784
 3785
 3786
 3787
 3788
 3789
 3790
 3791
 3792
 3793
 3794
 3795
 3796
 3797
 3798
 3799
 3800
 3801
 3802
 3803
 3804
 3805
 3806
 3807
 3808
 3809
 3810
 3811
 3812
 3813
 3814
 3815
 3816
 3817
 3818
 3819
 3820
 3821
 3822
 3823
 3824
 3825
 3826
 3827
 3828
 3829
 3830
 3831
 3832
 3833
 3834
 3835
 3836
 3837
 3838
 3839
 3840
 3841
 3842
 3843
 3844
 3845
 3846
 3847
 3848
 3849
 3850
 3851
 3852
 3853
 3854
 3855
 3856
 3857
 3858
 3859
 3860
 3861
 3862
 3863
 3864
 3865
 3866
 3867
 3868
 3869
 3870
 3871
 3872
 3873
 3874
 3875
 3876
 3877
 3878
 3879
 3880
 3881
 3882
 3883
 3884
 3885
 3886
 3887
 3888
 3889
 3890
 3891
 3892
 3893
 3894
 3895
 3896
 3897
 3898
 3899
 3900
 3901
 3902
 3903
 3904
 3905
 3906
 3907
 3908
 3909
 3910
 3911
 3912
 3913
 3914
 3915
 3916
 3917
 3918
 3919
 3920
 3921
 3922
 3923
 3924
 3925
 3926
 3927
 3928
 3929
 3930
 3931
 3932
 3933
 3934
 3935
 3936
 3937
 3938
 3939
 3940
 3941
 3942
 3943
 3944
 3945
 3946
 3947
 3948
 3949
 3950
 3951
 3952
 3953
 3954
 3955
 3956
 3957
 3958
 3959
 3960
 3961
 3962
 3963
 3964
 3965
 3966
 3967
 3968
 3969
 3970
 3971
 3972
 3973
 3974
 3975
 3976
 3977
 3978
 3979
 3980
 3981
 3982
 3983
 3984
 3985
 3986
 3987
 3988
 3989
 3990
 3991
 3992
 3993
 3994
 3995
 3996
 3997
 3998
 3999
 4000
 4001
 4002
 4003
 4004
 4005
 4006
 4007
 4008
 4009
 4010
 4011
 4012
 4013
 4014
 4015
 4016
 4017
 4018
 4019
 4020
 4021
 4022
 4023
 4024
 4025
 4026
 4027
 4028
 4029
 4030
 4031
 4032
 4033
 4034
 4035
 4036
 4037
 4038
 4039
 4040
 4041
 4042
 4043
 4044
 4045
 4046
 4047
 4048
 4049
 4050
 4051
 4052
 4053
 4054
 4055
 4056
 4057
 4058
 4059
 4060
 4061
 4062
 4063
 4064
 4065
 4066
 4067
 4068
 4069
 4070
 4071
 4072
 4073
 4074
 4075
 4076
 4077
 4078
 4079
 4080
 4081
 4082
 4083
 4084
 4085
 4086
 4087
 4088
 4089
 4090
 4091
 4092
 4093
 4094
 4095
 4096
 4097
 4098
 4099
 4100
 4101
 4102
 4103
 4104
 4105
 4106
 4107
 4108
 4109
 4110
 4111
 4112
 4113
 4114
 4115
 4116
 4117
 4118
 4119
 4120
 4121
 4122
 4123
 4124
 4125
 4126
 4127
 4128
 4129
 4130
 4131
 4132
 4133
 4134
 4135
 4136
 4137
 4138
 4139
 4140
 4141
 4142
 4143
 4144
 4145
 4146
 4147
 4148
 4149
 4150
 4151
 4152
 4153
 4154
 4155
 4156
 4157
 4158
 4159
 4160
 4161
 4162
 4163
 4164
 4165
 4166
 4167
 4168
 4169
 4170
 4171
 4172
 4173
 4174
 4175
 4176
 4177
 4178
 4179
 4180
 4181
 4182
 4183
 4184
 4185
 4186
 4187
 4188
 4189
 4190
 4191
 4192
 4193
 4194
 4195
 4196
 4197
 4198
 4199
 4200
 4201
 4202
 4203
 4204
 4205
 4206
 4207
 4208
 4209
 4210
 4211
 4212
 4213
 4214
 4215
 4216
 4217
 4218
 4219
 4220
 4221
 4222
 4223
 4224
 4225
 4226
 4227
 4228
 4229
 4230
 4231
 4232
 4233
 4234
 4235
 4236
 4237
 4238
 4239
 4240
 4241
 4242
 4243
 4244
 4245
 4246
 4247
 4248
 4249
 4250
 4251
 4252
 4253
 4254
 4255
 4256
 4257
 4258
 4259
 4260
 4261
 4262
 4263
 4264
 4265
 4266
 4267
 4268
 4269
 4270
 4271
 4272
 4273
 4274
 4275
 4276
 4277
 4278
 4279
 4280
 4281
 4282
 4283
 4284
 4285
 4286
 4287
 4288
 4289
 4290
 4291
 4292
 4293
 4294
 4295
 4296
 4297
 4298
 4299
 4300
 4301
 4302
 4303
 4304
 4305
 4306
 4307
 4308
 4309
 4310
 4311
 4312
 4313
 4314
 4315
 4316
 4317
 4318
 4319
 4320
 4321
 4322
 4323
 4324
 4325
 4326
 4327
 4328
 4329
 4330
 4331
 4332
 4333
 4334
 4335
 4336
 4337
 4338
 4339
 4340
 4341
 4342
 4343
 4344
 4345
 4346
 4347
 4348
 4349
 4350
 4351
 4352
 4353
 4354
 4355
 4356
 4357
 4358
 4359
 4360
 4361
 4362
 4363
 4364
 4365
 4366
 4367
 4368
 4369
 4370
 4371
 4372
 4373
 4374
 4375
 4376
 4377
 4378
 4379
 4380
 4381
 4382
 4383
 4384
 4385
 4386
 4387
 4388
 4389
 4390
 4391
 4392
 4393
 4394
 4395
 4396
 4397
 4398
 4399
 4400
 4401
 4402
 4403
 4404
 4405
 4406
 4407
 4408
 4409
 4410
 4411
 4412
 4413
 4414
 4415
 4416
 4417
 4418
 4419
 4420
 4421
 4422
 4423
 4424
 4425
 4426
 4427
 4428
 4429
 4430
 4431
 4432
 4433
 4434
 4435
 4436
 4437
 4438
 4439
 4440
 4441
 4442
 4443
 4444
 4445
 4446
 4447
 4448
 4449
 4450
 4451
 4452
 4453
 4454
 4455
 4456
 4457
 4458
 4459
 4460
 4461
 4462
 4463
 4464
 4465
 4466
 4467
 4468
 4469
 4470
 4471
 4472
 4473
 4474
 4475
 4476
 4477
 4478
 4479
 4480
 4481
 4482
 4483
 4484
 4485
 4486
 4487
 4488
 4489
 4490
 4491
 4492
 4493
 4494
 4495
 4496
 4497
 4498
 4499
 4500
 4501
 4502
 4503
 4504
 4505
 4506
 4507
 4508
 4509
 4510
 4511
 4512
 4513
 4514
 4515
 4516
 4517
 4518
 4519
 4520
 4521
 4522
 4523
 4524
 4525
 4526
 4527
 4528
 4529
 4530
 4531
 4532
 4533
 4534
 4535
 4536
 4537
 4538
 4539
 4540
 4541
 4542
 4543
 4544
 4545
 4546
 4547
 4548
 4549
 4550
 4551
 4552
 4553
 4554
 4555
 4556
 4557
 4558
 4559
 4560
 4561
 4562
 4563
 4564
 4565
 4566
 4567
 4568
 4569
 4570
 4571
 4572
 4573
 4574
 4575
 4576
 4577
 4578
 4579
 4580
 4581
 4582
 4583
 4584
 4585
 4586
 4587
 4588
 4589
 4590
 4591
 4592
 4593
 4594
 4595
 4596
 4597
 4598
 4599
 4600
 4601
 4602
 4603
 4604
 4605
 4606
 4607
 4608
 4609
 4610
 4611
 4612
 4613
 4614
 4615
 4616
 4617
 4618
 4619
 4620
 4621
 4622
 4623
 4624
 4625
 4626
 4627
 4628
 4629
 4630
 4631
 4632
 4633
 4634
 4635
 4636
 4637
 4638
 4639
 4640
 4641
 4642
 4643
 4644
 4645
 4646
 4647
 4648
 4649
 4650
 4651
 4652
 4653
 4654
 4655
 4656
 4657
 4658
 4659
 4660
 4661
 4662
 4663
 4664
 4665
 4666
 4667
 4668
 4669
 4670
 4671
 4672
 4673
 4674
 4675
 4676
 4677
 4678
 4679
 4680
 4681
 4682
 4683
 4684
 4685
 4686
 4687
 4688
 4689
 4690
 4691
 4692
 4693
 4694
 4695
 4696
 4697
 4698
 4699
 4700
 4701
 4702
 4703
 4704
 4705
 4706
 4707
 4708
 4709
 4710
 4711
 4712
 4713
 4714
 4715
 4716
 4717
 4718
 4719
 4720
 4721
 4722
 4723
 4724
 4725
 4726
 4727
 4728
 4729
 4730
 4731
 4732
 4733
 4734
 4735
 4736
 4737
 4738
 4739
 4740
 4741
 4742
 4743
 4744
 4745
 4746
 4747
 4748
 4749
 4750
 4751
 4752
 4753
 4754
 4755
 4756
 4757
 4758
 4759
 4760
 4761
 4762
 4763
 4764
 4765
 4766
 4767
 4768
 4769
 4770
 4771
 4772
 4773
 4774
 4775
 4776
 4777
 4778
 4779
 4780
 4781
 4782
 4783
 4784
 4785
 4786
 4787
 4788
 4789
 4790
 4791
 4792
 4793
 4794
 4795
 4796
 4797
 4798
 4799
 4800
 4801
 4802
 4803
 4804
 4805
 4806
 4807
 4808
 4809
 4810
 4811
 4812
 4813
 4814
 4815
 4816
 4817
 4818
 4819
 4820
 4821
 4822
 4823
 4824
 4825
 4826
 4827
 4828
 4829
 4830
 4831
 4832
 4833
 4834
 4835
 4836
 4837
 4838
 4839
 4840
 4841
 4842
 4843
 4844
 4845
 4846
 4847
 4848
 4849
 4850
 4851
 4852
 4853
 4854
 4855
 4856
 4857
 4858
 4859
 4860
 4861
 4862
 4863
 4864
 4865
 4866
 4867
 4868
 4869
 4870
 4871
 4872
 4873
 4874
 4875
 4876
 4877
 4878
 4879
 4880
 4881
 4882
 4883
 4884
 4885
 4886
 4887
 4888
 4889
 4890
 4891
 4892
 4893
 4894
 4895
 4896
 4897
 4898
 4899
 4900
 4901
 4902
 4903
 4904
 4905
 4906
 4907
 4908
 4909
 4910
 4911
 4912
 4913
 4914
 4915
 4916
 4917
 4918
 4919
 4920
 4921
 4922
 4923
 4924
 4925
 4926
 4927
 4928
 4929
 4930
 4931
 4932
 4933
 4934
 4935
 4936
 4937
 4938
 4939
 4940
 4941
 4942
 4943
 4944
 4945
 4946
 4947
 4948
 4949
 4950
 4951
 4952
 4953
 4954
 4955
 4956
 4957
 4958
 4959
 4960
 4961
 4962
 4963
 4964
 4965
 4966
 4967
 4968
 4969
 4970
 4971
 4972
 4973
 4974
 4975
 4976
 4977
 4978
 4979
 4980
 4981
 4982
 4983
 4984
 4985
 4986
 4987
 4988
 4989
 4990
 4991
 4992
 4993
 4994
 4995
 4996
 4997
 4998
 4999
 5000
 5001
 5002
 5003
 5004
 5005
 5006
 5007
 5008
 5009
 5010
 5011
 5012
 5013
 5014
 5015
 5016
 5017
 5018
 5019
 5020
 5021
 5022
 5023
 5024
 5025
 5026
 5027
 5028
 5029
 5030
 5031
 5032
 5033
 5034
 5035
 5036
 5037
 5038
 5039
 5040
 5041
 5042
 5043
 5044
 5045
 5046
 5047
 5048
 5049
 5050
 5051
 5052
 5053
 5054
 5055
 5056
 5057
 5058
 5059
 5060
 5061
 5062
 5063
 5064
 5065
 5066
 5067
 5068
 5069
 5070
 5071
 5072
 5073
 5074
 5075
 5076
 5077
 5078
 5079
 5080
 5081
 5082
 5083
 5084
 5085
 5086
 5087
 5088
 5089
 5090
 5091
 5092
 5093
 5094
 5095
 5096
 5097
 5098
 5099
 5100
 5101
 5102
 5103
 5104
 5105
 5106
 5107
 5108
 5109
 5110
 5111
 5112
 5113
 5114
 5115
 5116
 5117
 5118
 5119
 5120
 5121
 5122
 5123
 5124
 5125
 5126
 5127
 5128
 5129
 5130
 5131
 5132
 5133
 5134
 5135
 5136
 5137
 5138
 5139
 5140
 5141
 5142
 5143
 5144
 5145
 5146
 5147
 5148
 5149
 5150
 5151
 5152
 5153
 5154
 5155
 5156
 5157
 5158
 5159
 5160
 5161
 5162
 5163
 5164
 5165
 5166
 5167
 5168
 5169
 5170
 5171
 5172
 5173
 5174
 5175
 5176
 5177
 5178
 5179
 5180
 5181
 5182
 5183
 5184
 5185
 5186
 5187
 5188
 5189
 5190
 5191
 5192
 5193
 5194
 5195
 5196
 5197
 5198
 5199
 5200
 5201
 5202
 5203
 5204
 5205
 5206
 5207
 5208
 5209
 5210
 5211
 5212
 5213
 5214
 5215
 5216
 5217
 5218
 5219
 5220
 5221
 5222
 5223
 5224
 5225
 5226
 5227
 5228
 5229
 5230
 5231
 5232
 5233
 5234
 5235
 5236
 5237
 5238
 5239
 5240
 5241
 5242
 5243
 5244
 5245
 5246
 5247
 5248
 5249
 5250
 5251
 5252
 5253
 5254
 5255
 5256
 5257
 5258
 5259
 5260
 5261
 5262
 5263
 5264
 5265
 5266
 5267
 5268
 5269
 5270
 5271
 5272
 5273
 5274
 5275
 5276
 5277
 5278
 5279
 5280
 5281
 5282
 5283
 5284
 5285
 5286
 5287
 5288
 5289
 5290
 5291
 5292
 5293
 5294
 5295
 5296
 5297
 5298
 5299
 5300
 5301
 5302
 5303
 5304
 5305
 5306
 5307
 5308
 5309
 5310
 5311
 5312
 5313
 5314
 5315
 5316
 5317
 5318
 5319
 5320
 5321
 5322
 5323
 5324
 5325
 5326
 5327
 5328
 5329
 5330
 5331
 5332
 5333
 5334
 5335
 5336
 5337
 5338
 5339
 5340
 5341
 5342
 5343
 5344
 5345
 5346
 5347
 5348
 5349
 5350
 5351
 5352
 5353
 5354
 5355
 5356
 5357
 5358
 5359
 5360
 5361
 5362
 5363
 5364
 5365
 5366
 5367
 5368
 5369
 5370
 5371
 5372
 5373
 5374
 5375
 5376
 5377
 5378
 5379
 5380
 5381
 5382
 5383
 5384
 5385
 5386
 5387
 5388
 5389
 5390
 5391
 5392
 5393
 5394
 5395
 5396
 5397
 5398
 5399
 5400
 5401
 5402
 5403
 5404
 5405
 5406
 5407
 5408
 5409
 5410
 5411
 5412
 5413
 5414
 5415
 5416
 5417
 5418
 5419
 5420
 5421
 5422
 5423
 5424
 5425
 5426
 5427
 5428
 5429
 5430
 5431
 5432
 5433
 5434
 5435
 5436
 5437
 5438
 5439
 5440
 5441
 5442
 5443
 5444
 5445
 5446
 5447
 5448
 5449
 5450
 5451
 5452
 5453
 5454
 5455
 5456
 5457
 5458
 5459
 5460
 5461
 5462
 5463
 5464
 5465
 5466
 5467
 5468
 5469
 5470
 5471
 5472
 5473
 5474
 5475
 5476
 5477
 5478
 5479
 5480
 5481
 5482
 5483
 5484
 5485
 5486
 5487
 5488
 5489
 5490
 5491
 5492
 5493
 5494
 5495
 5496
 5497
 5498
 5499
 5500
 5501
 5502
 5503
 5504
 5505
 5506
 5507
 5508
 5509
 5510
 5511
 5512
 5513
 5514
 5515
 5516
 5517
 5518
 5519
 5520
 5521
 5522
 5523
 5524
 5525
 5526
 5527
 5528
 5529
 5530
 5531
 5532
 5533
 5534
 5535
 5536
 5537
 5538
 5539
 5540
 5541
 5542
 5543
 5544
 5545
 5546
 5547
 5548
 5549
 5550
 5551
 5552
 5553
 5554
 5555
 5556
 5557
 5558
 5559
 5560
 5561
 5562
 5563
 5564
 5565
 5566
 5567
 5568
 5569
 5570
 5571
 5572
 5573
 5574
 5575
 5576
 5577
 5578
 5579
 5580
 5581
 5582
 5583
 5584
 5585
 5586
 5587
 5588
 5589
 5590
 5591
 5592
 5593
 5594
 5595
 5596
 5597
 5598
 5599
 5600
 5601
 5602
 5603
 5604
 5605
 5606
 5607
 5608
 5609
 5610
 5611
 5612
 5613
 5614
 5615
 5616
 5617
 5618
 5619
 5620
 5621
 5622
 5623
 5624
 5625
 5626
 5627
 5628
 5629
 5630
 5631
 5632
 5633
 5634
 5635
 5636
 5637
 5638
 5639
 5640
 5641
 5642
 5643
 5644
 5645
 5646
 5647
 5648
 5649
 5650
 5651
 5652
 5653
 5654
 5655
 5656
 5657
 5658
 5659
 5660
 5661
 5662
 5663
 5664
 5665
 5666
 5667
 5668
 5669
 5670
 5671
 5672
 5673
 5674
 5675
 5676
 5677
 5678
 5679
 5680
 5681
 5682
 5683
 5684
 5685
 5686
 5687
 5688
 5689
 5690
 5691
 5692
 5693
 5694
 5695
 5696
 5697
 5698
 5699
 5700
 5701
 5702
 5703
 5704
 5705
 5706
 5707
 5708
 5709
 5710
 5711
 5712
 5713
 5714
 5715
 5716
 5717
 5718
 5719
 5720
 5721
 5722
 5723
 5724
 5725
 5726
 5727
 5728
 5729
 5730
 5731
 5732
 5733
 5734
 5735
 5736
 5737
 5738
 5739
 5740
 5741
 5742
 5743
 5744
 5745
 5746
 5747
 5748
 5749
 5750
 5751
 5752
 5753
 5754
 5755
 5756
 5757
 5758
 5759
 5760
 5761
 5762
 5763
 5764
 5765
 5766
 5767
 5768
 5769
 5770
 5771
 5772
 5773
 5774
 5775
 5776
 5777
 5778
 5779
 5780
 5781
 5782
 5783
 5784
 5785
 5786
 5787
 5788
 5789
 5790
 5791
 5792
 5793
 5794
 5795
 5796
 5797
 5798
 5799
 5800
 5801
 5802
 5803
 5804
 5805
 5806
 5807
 5808
 5809
 5810
 5811
 5812
 5813
 5814
 5815
 5816
 5817
 5818
 5819
 5820
 5821
 5822
 5823
 5824
 5825
 5826
 5827
 5828
 5829
 5830
 5831
 5832
 5833
 5834
 5835
 5836
 5837
 5838
 5839
 5840
 5841
 5842
 5843
 5844
 5845
 5846
 5847
 5848
 5849
 5850
 5851
 5852
 5853
 5854
 5855
 5856
 5857
 5858
 5859
 5860
 5861
 5862
 5863
 5864
 5865
 5866
 5867
 5868
 5869
 5870
 5871
 5872
 5873
 5874
 5875
 5876
 5877
 5878
 5879
 5880
 5881
 5882
 5883
 5884
 5885
 5886
 5887
 5888
 5889
 5890
 5891
 5892
 5893
 5894
 5895
 5896
 5897
 5898
 5899
 5900
 5901
 5902
 5903
 5904
 5905
 5906
 5907
 5908
 5909
 5910
 5911
 5912
 5913
 5914
 5915
 5916
 5917
 5918
 5919
 5920
 5921
 5922
 5923
 5924
 5925
 5926
 5927
 5928
 5929
 5930
 5931
 5932
 5933
 5934
 5935
 5936
 5937
 5938
 5939
 5940
 5941
 5942
 5943
 5944
 5945
 5946
 5947
 5948
 5949
 5950
 5951
 5952
 5953
 5954
 5955
 5956
 5957
 5958
 5959
 5960
 5961
 5962
 5963
 5964
 5965
 5966
 5967
 5968
 5969
 5970
 5971
 5972
 5973
 5974
 5975
 5976
 5977
 5978
 5979
 5980
 5981
 5982
 5983
 5984
 5985
 5986
 5987
 5988
 5989
 5990
 5991
 5992
 5993
 5994
 5995
 5996
 5997
 5998
 5999
 6000
 6001
 6002
 6003
 6004
 6005
 6006
 6007
 6008
 6009
 6010
 6011
 6012
 6013
 6014
 6015
 6016
 6017
 6018
 6019
 6020
 6021
 6022
 6023
 6024
 6025
 6026
 6027
 6028
 6029
 6030
 6031
 6032
 6033
 6034
 6035
 6036
 6037
 6038
 6039
 6040
 6041
 6042
 6043
 6044
 6045
 6046
 6047
 6048
 6049
 6050
 6051
 6052
 6053
 6054
 6055
 6056
 6057
 6058
 6059
 6060
 6061
 6062
 6063
 6064
 6065
 6066
 6067
 6068
 6069
 6070
 6071
 6072
 6073
 6074
 6075
 6076
 6077
 6078
 6079
 6080
 6081
 6082
 6083
 6084
 6085
 6086
 6087
 6088
 6089
 6090
 6091
 6092
 6093
 6094
 6095
 6096
 6097
 6098
 6099
 6100
 6101
 6102
 6103
 6104
 6105
 6106
 6107
 6108
 6109
 6110
 6111
 6112
 6113
 6114
 6115
 6116
 6117
 6118
 6119
 6120
 6121
 6122
 6123
 6124
 6125
 6126
 6127
 6128
 6129
 6130
 6131
 6132
 6133
 6134
 6135
 6136
 6137
 6138
 6139
 6140
 6141
 6142
 6143
 6144
 6145
 6146
 6147
 6148
 6149
 6150
 6151
 6152
 6153
 6154
 6155
 6156
 6157
 6158
 6159
 6160
 6161
 6162
 6163
 6164
 6165
 6166
 6167
 6168
 6169
 6170
 6171
 6172
 6173
 6174
 6175
 6176
 6177
 6178
 6179
 6180
 6181
 6182
 6183
 6184
 6185
 6186
 6187
 6188
 6189
 6190
 6191
 6192
 6193
 6194
 6195
 6196
 6197
 6198
 6199
 6200
 6201
 6202
 6203
 6204
 6205
 6206
 6207
 6208
 6209
 6210
 6211
 6212
 6213
 6214
 6215
 6216
 6217
 6218
 6219
 6220
 6221
 6222
 6223
 6224
 6225
 6226
 6227
 6228
 6229
 6230
 6231
 6232
 6233
 6234
 6235
 6236
 6237
 6238
 6239
 6240
 6241
 6242
 6243
 6244
 6245
 6246
 6247
 6248
 6249
 6250
 6251
 6252
 6253
 6254
 6255
 6256
 6257
 6258
 6259
 6260
 6261
 6262
 6263
 6264
 6265
 6266
 6267
 6268
 6269
 6270
 6271
 6272
 6273
 6274
 6275
 6276
 6277
 6278
 6279
 6280
 6281
 6282
 6283
 6284
 6285
 6286
 6287
 6288
 6289
 6290
 6291
 6292
 6293
 6294
 6295
 6296
 6297
 6298
 6299
 6300
 6301
 6302
 6303
 6304
 6305
 6306
 6307
 6308
 6309
 6310
 6311
 6312
 6313
 6314
 6315
 6316
 6317
 6318
 6319
 6320
 6321
 6322
 6323
 6324
 6325
 6326
 6327
 6328
 6329
 6330
 6331
 6332
 6333
 6334
 6335
 6336
 6337
 6338
 6339
 6340
 6341
 6342
 6343
 6344
 6345
 6346
 6347
 6348
 6349
 6350
 6351
 6352
 6353
 6354
 6355
 6356
 6357
 6358
 6359
 6360
 6361
 6362
 6363
 6364
 6365
 6366
 6367
 6368
 6369
 6370
 6371
 6372
 6373
 6374
 6375
 6376
 6377
 6378
 6379
 6380
 6381
 6382
 6383
 6384
 6385
 6386
 6387
 6388
 6389
 6390
 6391
 6392
 6393
 6394
 6395
 6396
 6397
 6398
 6399
 6400
 6401
 6402
 6403
 6404
 6405
 6406
 6407
 6408
 6409
 6410
 6411
 6412
 6413
 6414
 6415
 6416
 6417
 6418
 6419
 6420
 6421
 6422
 6423
 6424
 6425
 6426
 6427
 6428
 6429
 6430
 6431
 6432
 6433
 6434
 6435
 6436
 6437
 6438
 6439
 6440
 6441
 6442
 6443
 6444
 6445
 6446
 6447
 6448
 6449
 6450
 6451
 6452
 6453
 6454
 6455
 6456
 6457
 6458
 6459
 6460
 6461
 6462
 6463
 6464
 6465
 6466
 6467
 6468
 6469
 6470
 6471
 6472
 6473
 6474
 6475
 6476
 6477
 6478
 6479
 6480
 6481
 6482
 6483
 6484
 6485
 6486
 6487
 6488
 6489
 6490
 6491
 6492
 6493
 6494
 6495
 6496
 6497
 6498
 6499
 6500
 6501
 6502
 6503
 6504
 6505
 6506
 6507
 6508
 6509
 6510
 6511
 6512
 6513
 6514
 6515
 6516
 6517
 6518
 6519
 6520
 6521
 6522
 6523
 6524
 6525
 6526
 6527
 6528
 6529
 6530
 6531
 6532
 6533
 6534
 6535
 6536
 6537
 6538
 6539
 6540
 6541
 6542
 6543
 6544
 6545
 6546
 6547
 6548
 6549
 6550
 6551
 6552
 6553
 6554
 6555
 6556
 6557
 6558
 6559
 6560
 6561
 6562
 6563
 6564
 6565
 6566
 6567
 6568
 6569
 6570
 6571
 6572
 6573
 6574
 6575
 6576
 6577
 6578
 6579
 6580
 6581
 6582
 6583
 6584
 6585
 6586
 6587
 6588
 6589
 6590
 6591
 6592
 6593
 6594
 6595
 6596
 6597
 6598
 6599
 6600
 6601
 6602
 6603
 6604
 6605
 6606
 6607
 6608
 6609
 6610
 6611
 6612
 6613
 6614
 6615
 6616
 6617
 6618
 6619
 6620
 6621
 6622
 6623
 6624
 6625
 6626
 6627
 6628
 6629
 6630
 6631
 6632
 6633
 6634
 6635
 6636
 6637
 6638
 6639
 6640
 6641
 6642
 6643
 6644
 6645
 6646
 6647
 6648
 6649
 6650
 6651
 6652
 6653
 6654
 6655
 6656
 6657
 6658
 6659
 6660
 6661
 6662
 6663
 6664
 6665
 6666
 6667
 6668
 6669
 6670
 6671
 6672
 6673
 6674
 6675
 6676
 6677
 6678
 6679
 6680
 6681
 6682
 6683
 6684
 6685
 6686
 6687
 6688
 6689
 6690
 6691
 6692
 6693
 6694
 6695
 6696
 6697
 6698
 6699
 6700
 6701
 6702
 6703
 6704
 6705
 6706
 6707
 6708
 6709
 6710
 6711
 6712
 6713
 6714
 6715
 6716
 6717
 6718
 6719
 6720
 6721
 6722
 6723
 6724
 6725
 6726
 6727
 6728
 6729
 6730
 6731
 6732
 6733
 6734
 6735
 6736
 6737
 6738
 6739
 6740
 6741
 6742
 6743
 6744
 6745
 6746
 6747
 6748
 6749
 6750
 6751
 6752
 6753
 6754
 6755
 6756
 6757
 6758
 6759
 6760
 6761
 6762
 6763
 6764
 6765
 6766
 6767
 6768
 6769
 6770
 6771
 6772
 6773
 6774
 6775
 6776
 6777
 6778
 6779
 6780
 6781
 6782
 6783
 6784
 6785
 6786
 6787
 6788
 6789
 6790
 6791
 6792
 6793
 6794
 6795
 6796
 6797
 6798
 6799
 6800
 6801
 6802
 6803
 6804
 6805
 6806
 6807
 6808
 6809
 6810
 6811
 6812
 6813
 6814
 6815
 6816
 6817
 6818
 6819
 6820
 6821
 6822
 6823
 6824
 6825
 6826
 6827
 6828
 6829
 6830
 6831
 6832
 6833
 6834
 6835
 6836
 6837
 6838
 6839
 6840
 6841
 6842
 6843
 6844
 6845
 6846
 6847
 6848
 6849
 6850
 6851
 6852
 6853
 6854
 6855
 6856
 6857
 6858
 6859
 6860
 6861
 6862
 6863
 6864
 6865
 6866
 6867
 6868
 6869
 6870
 6871
 6872
 6873
 6874
 6875
 6876
 6877
 6878
 6879
 6880
 6881
 6882
 6883
 6884
 6885
 6886
 6887
 6888
 6889
 6890
 6891
 6892
 6893
 6894
 6895
 6896
 6897
 6898
 6899
 6900
 6901
 6902
 6903
 6904
 6905
 6906
 6907
 6908
 6909
 6910
 6911
 6912
 6913
 6914
 6915
 6916
 6917
 6918
 6919
 6920
 6921
 6922
 6923
 6924
 6925
 6926
 6927
 6928
 6929
 6930
 6931
 6932
 6933
 6934
 6935
 6936
 6937
 6938
 6939
 6940
 6941
 6942
 6943
 6944
 6945
 6946
 6947
 6948
 6949
 6950
 6951
 6952
 6953
 6954
 6955
 6956
 6957
 6958
 6959
 6960
 6961
 6962
 6963
 6964
 6965
 6966
 6967
 6968
 6969
 6970
 6971
 6972
 6973
 6974
 6975
 6976
 6977
 6978
 6979
 6980
 6981
 6982
 6983
 6984
 6985
 6986
 6987
 6988
 6989
 6990
 6991
 6992
 6993
 6994
 6995
 6996
 6997
 6998
 6999
 7000
 7001
 7002
 7003
 7004
 7005
 7006
 7007
 7008
 7009
 7010
 7011
 7012
 7013
 7014
 7015
 7016
 7017
 7018
 7019
 7020
 7021
 7022
 7023
 7024
 7025
 7026
 7027
 7028
 7029
 7030
 7031
 7032
 7033
 7034
 7035
 7036
 7037
 7038
 7039
 7040
 7041
 7042
 7043
 7044
 7045
 7046
 7047
 7048
 7049
 7050
 7051
 7052
 7053
 7054
 7055
 7056
 7057
 7058
 7059
 7060
 7061
 7062
 7063
 7064
 7065
 7066
 7067
 7068
 7069
 7070
 7071
 7072
 7073
 7074
 7075
 7076
 7077
 7078
 7079
 7080
 7081
 7082
 7083
 7084
 7085
 7086
 7087
 7088
 7089
 7090
 7091
 7092
 7093
 7094
 7095
 7096
 7097
 7098
 7099
 7100
 7101
 7102
 7103
 7104
 7105
 7106
 7107
 7108
 7109
 7110
 7111
 7112
 7113
 7114
 7115
 7116
 7117
 7118
 7119
 7120
 7121
 7122
 7123
 7124
 7125
 7126
 7127
 7128
 7129
 7130
 7131
 7132
 7133
 7134
 7135
 7136
 7137
 7138
 7139
 7140
 7141
 7142
 7143
 7144
 7145
 7146
 7147
 7148
 7149
 7150
 7151
 7152
 7153
 7154
 7155
 7156
 7157
 7158
 7159
 7160
 7161
 7162
 7163
 7164
 7165
 7166
 7167
 7168
 7169
 7170
 7171
 7172
 7173
 7174
 7175
 7176
 7177
 7178
 7179
 7180
 7181
 7182
 7183
 7184
 7185
 7186
 7187
 7188
 7189
 7190
 7191
 7192
 7193
 7194
 7195
 7196
 7197
 7198
 7199
 7200
 7201
 7202
 7203
 7204
 7205
 7206
 7207
 7208
 7209
 7210
 7211
 7212
 7213
 7214
 7215
 7216
 7217
 7218
 7219
 7220
 7221
 7222
 7223
 7224
 7225
 7226
 7227
 7228
 7229
 7230
 7231
 7232
 7233
 7234
 7235
 7236
 7237
 7238
 7239
 7240
 7241
 7242
 7243
 7244
 7245
 7246
 7247
 7248
 7249
 7250
 7251
 7252
 7253
 7254
 7255
 7256
 7257
 7258
 7259
 7260
 7261
 7262
 7263
 7264
 7265
 7266
 7267
 7268
 7269
 7270
 7271
 7272
 7273
 7274
 7275
 7276
 7277
 7278
 7279
 7280
 7281
 7282
 7283
 7284
 7285
 7286
 7287
 7288
 7289
 7290
 7291
 7292
 7293
 7294
 7295
 7296
 7297
 7298
 7299
 7300
 7301
 7302
 7303
 7304
 7305
 7306
 7307
 7308
 7309
 7310
 7311
 7312
 7313
 7314
 7315
 7316
 7317
 7318
 7319
 7320
 7321
 7322
 7323
 7324
 7325
 7326
 7327
 7328
 7329
 7330
 7331
 7332
 7333
 7334
 7335
 7336
 7337
 7338
 7339
 7340
 7341
 7342
 7343
 7344
 7345
 7346
 7347
 7348
 7349
 7350
 7351
 7352
 7353
 7354
 7355
 7356
 7357
 7358
 7359
 7360
 7361
 7362
 7363
 7364
 7365
 7366
 7367
 7368
 7369
 7370
 7371
 7372
 7373
 7374
 7375
 7376
 7377
 7378
 7379
 7380
 7381
 7382
 7383
 7384
 7385
 7386
 7387
 7388
 7389
 7390
 7391
 7392
 7393
 7394
 7395
 7396
 7397
 7398
 7399
 7400
 7401
 7402
 7403
 7404
 7405
 7406
 7407
 7408
 7409
 7410
 7411
 7412
 7413
 7414
 7415
 7416
 7417
 7418
 7419
 7420
 7421
 7422
 7423
 7424
 7425
 7426
 7427
 7428
 7429
 7430
 7431
 7432
 7433
 7434
 7435
 7436
 7437
 7438
 7439
 7440
 7441
 7442
 7443
 7444
 7445
 7446
 7447
 7448
 7449
 7450
 7451
 7452
 7453
 7454
 7455
 7456
 7457
 7458
 7459
 7460
 7461
 7462
 7463
 7464
 7465
 7466
 7467
 7468
 7469
 7470
 7471
 7472
 7473
 7474
 7475
 7476
 7477
 7478
 7479
 7480
 7481
 7482
 7483
 7484
 7485
 7486
 7487
 7488
 7489
 7490
 7491
 7492
 7493
 7494
 7495
 7496
 7497
 7498
 7499
 7500
 7501
 7502
 7503
 7504
 7505
 7506
 7507
 7508
 7509
 7510
 7511
 7512
 7513
 7514
 7515
 7516
 7517
 7518
 7519
 7520
 7521
 7522
 7523
 7524
 7525
 7526
 7527
 7528
 7529
 7530
 7531
 7532
 7533
 7534
 7535
 7536
 7537
 7538
 7539
 7540
 7541
 7542
 7543
 7544
 7545
 7546
 7547
 7548
 7549
 7550
 7551
 7552
 7553
 7554
 7555
 7556
 7557
 7558
 7559
 7560
 7561
 7562
 7563
 7564
 7565
 7566
 7567
 7568
 7569
 7570
 7571
 7572
 7573
 7574
 7575
 7576
 7577
 7578
 7579
 7580
 7581
 7582
 7583
 7584
 7585
 7586
 7587
 7588
 7589
 7590
 7591
 7592
 7593
 7594
 7595
 7596
 7597
 7598
 7599
 7600
 7601
 7602
 7603
 7604
 7605
 7606
 7607
 7608
 7609
 7610
 7611
 7612
 7613
 7614
 7615
 7616
 7617
 7618
 7619
 7620
 7621
 7622
 7623
 7624
 7625
 7626
 7627
 7628
 7629
 7630
 7631
 7632
 7633
 7634
 7635
 7636
 7637
 7638
 7639
 7640
 7641
 7642
 7643
 7644
 7645
 7646
 7647
 7648
 7649
 7650
 7651
 7652
 7653
 7654
 7655
 7656
 7657
 7658
 7659
 7660
 7661
 7662
 7663
 7664
 7665
 7666
 7667
 7668
 7669
 7670
 7671
 7672
 7673
 7674
 7675
 7676
 7677
 7678
 7679
 7680
 7681
 7682
 7683
 7684
 7685
 7686
 7687
 7688
 7689
 7690
 7691
 7692
 7693
 7694
 7695
 7696
 7697
 7698
 7699
 7700
 7701
 7702
 7703
 7704
 7705
 7706
 7707
 7708
 7709
 7710
 7711
 7712
 7713
 7714
 7715
 7716
 7717
 7718
 7719
 7720
 7721
 7722
 7723
 7724
 7725
 7726
 7727
 7728
 7729
 7730
 7731
 7732
 7733
 7734
 7735
 7736
 7737
 7738
 7739
 7740
 7741
 7742
 7743
 7744
 7745
 7746
 7747
 7748
 7749
 7750
 7751
 7752
 7753
 7754
 7755
 7756
 7757
 7758
 7759
 7760
 7761
 7762
 7763
 7764
 7765
 7766
 7767
 7768
 7769
 7770
 7771
 7772
 7773
 7774
 7775
 7776
 7777
 7778
 7779
 7780
 7781
 7782
 7783
 7784
 7785
 7786
 7787
 7788
 7789
 7790
 7791
 7792
 7793
 7794
 7795
 7796
 7797
 7798
 7799
 7800
 7801
 7802
 7803
 7804
 7805
 7806
 7807
 7808
 7809
 7810
 7811
 7812
 7813
 7814
 7815
 7816
 7817
 7818
 7819
 7820
 7821
 7822
 7823
 7824
 7825
 7826
 7827
 7828
 7829
 7830
 7831
 7832
 7833
 7834
 7835
 7836
 7837
 7838
 7839
 7840
 7841
 7842
 7843
 7844
 7845
 7846
 7847
 7848
 7849
 7850
 7851
 7852
 7853
 7854
 7855
 7856
 7857
 7858
 7859
 7860
 7861
 7862
 7863
 7864
 7865
 7866
 7867
 7868
 7869
 7870
 7871
 7872
 7873
 7874
 7875
 7876
 7877
 7878
 7879
 7880
 7881
 7882
 7883
 7884
 7885
 7886
 7887
 7888
 7889
 7890
 7891
 7892
 7893
 7894
 7895
 7896
 7897
 7898
 7899
 7900
 7901
 7902
 7903
 7904
 7905
 7906
 7907
 7908
 7909
 7910
 7911
 7912
 7913
 7914
 7915
 7916
 7917
 7918
 7919
 7920
 7921
 7922
 7923
 7924
 7925
 7926
 7927
 7928
 7929
 7930
 7931
 7932
 7933
 7934
 7935
 7936
 7937
 7938
 7939
 7940
 7941
 7942
 7943
 7944
 7945
 7946
 7947
 7948
 7949
 7950
 7951
 7952
 7953
 7954
 7955
 7956
 7957
 7958
 7959
 7960
 7961
 7962
 7963
 7964
 7965
 7966
 7967
 7968
 7969
 7970
 7971
 7972
 7973
 7974
 7975
 7976
 7977
 7978
 7979
 7980
 7981
 7982
 7983
 7984
 7985
 7986
 7987
 7988
 7989
 7990
 7991
 7992
 7993
 7994
 7995
 7996
 7997
 7998
 7999
 8000
 8001
 8002
 8003
 8004
 8005
 8006
 8007
 8008
 8009
 8010
 8011
 8012
 8013
 8014
 8015
 8016
 8017
 8018
 8019
 8020
 8021
 8022
 8023
 8024
 8025
 8026
 8027
 8028
 8029
 8030
 8031
 8032
 8033
 8034
 8035
 8036
 8037
 8038
 8039
 8040
 8041
 8042
 8043
 8044
 8045
 8046
 8047
 8048
 8049
 8050
 8051
 8052
 8053
 8054
 8055
 8056
 8057
 8058
 8059
 8060
 8061
 8062
 8063
 8064
 8065
 8066
 8067
 8068
 8069
 8070
 8071
 8072
 8073
 8074
 8075
 8076
 8077
 8078
 8079
 8080
 8081
 8082
 8083
 8084
 8085
 8086
 8087
 8088
 8089
 8090
 8091
 8092
 8093
 8094
 8095
 8096
 8097
 8098
 8099
 8100
 8101
 8102
 8103
 8104
 8105
 8106
 8107
 8108
 8109
 8110
 8111
 8112
 8113
 8114
 8115
 8116
 8117
 8118
 8119
 8120
 8121
 8122
 8123
 8124
 8125
 8126
 8127
 8128
 8129
 8130
 8131
 8132
 8133
 8134
 8135
 8136
 8137
 8138
 8139
 8140
 8141
 8142
 8143
 8144
 8145
 8146
 8147
 8148
 8149
 8150
 8151
 8152
 8153
 8154
 8155
 8156
 8157
 8158
 8159
 8160
 8161
 8162
 8163
 8164
 8165
 8166
 8167
 8168
 8169
 8170
 8171
 8172
 8173
 8174
 8175
 8176
 8177
 8178
 8179
 8180
 8181
 8182
 8183
 8184
 8185
 8186
 8187
 8188
 8189
 8190
 8191
 8192
 8193
 8194
 8195
 8196
 8197
 8198
 8199
 8200
 8201
 8202
 8203
 8204
 8205
 8206
 8207
 8208
 8209
 8210
 8211
 8212
 8213
 8214
 8215
 8216
 8217
 8218
 8219
 8220
 8221
 8222
 8223
 8224
 8225
 8226
 8227
 8228
 8229
 8230
 8231
 8232
 8233
 8234
 8235
 8236
 8237
 8238
 8239
 8240
 8241
 8242
 8243
 8244
 8245
 8246
 8247
 8248
 8249
 8250
 8251
 8252
 8253
 8254
 8255
 8256
 8257
 8258
 8259
 8260
 8261
 8262
 8263
 8264
 8265
 8266
 8267
 8268
 8269
 8270
 8271
 8272
 8273
 8274
 8275
 8276
 8277
 8278
 8279
 8280
 8281
 8282
 8283
 8284
 8285
 8286
 8287
 8288
 8289
 8290
 8291
 8292
 8293
 8294
 8295
 8296
 8297
 8298
 8299
 8300
 8301
 8302
 8303
 8304
 8305
 8306
 8307
 8308
 8309
 8310
 8311
 8312
 8313
 8314
 8315
 8316
 8317
 8318
 8319
 8320
 8321
 8322
 8323
 8324
 8325
 8326
 8327
 8328
 8329
 8330
 8331
 8332
 8333
 8334
 8335
 8336
 8337
 8338
 8339
 8340
 8341
 8342
 8343
 8344
 8345
 8346
 8347
 8348
 8349
 8350
 8351
 8352
 8353
 8354
 8355
 8356
 8357
 8358
 8359
 8360
 8361
 8362
 8363
 8364
 8365
 8366
 8367
 8368
 8369
 8370
 8371
 8372
 8373
 8374
 8375
 8376
 8377
 8378
 8379
 8380
 8381
 8382
 8383
 8384
 8385
 8386
 8387
 8388
 8389
 8390
 8391
 8392
 8393
 8394
 8395
 8396
 8397
 8398
 8399
 8400
 8401
 8402
 8403
 8404
 8405
 8406
 8407
 8408
 8409
 8410
 8411
 8412
 8413
 8414
 8415
 8416
 8417
 8418
 8419
 8420
 8421
 8422
 8423
 8424
 8425
 8426
 8427
 8428
 8429
 8430
 8431
 8432
 8433
 8434
 8435
 8436
 8437
 8438
 8439
 8440
 8441
 8442
 8443
 8444
 8445
 8446
 8447
 8448
 8449
 8450
 8451
 8452
 8453
 8454
 8455
 8456
 8457
 8458
 8459
 8460
 8461
 8462
 8463
 8464
 8465
 8466
 8467
 8468
 8469
 8470
 8471
 8472
 8473
 8474
 8475
 8476
 8477
 8478
 8479
 8480
 8481
 8482
 8483
 8484
 8485
 8486
 8487
 8488
 8489
 8490
 8491
 8492
 8493
 8494
 8495
 8496
 8497
 8498
 8499
 8500
 8501
 8502
 8503
 8504
 8505
 8506
 8507
 8508
 8509
 8510
 8511
 8512
 8513
 8514
 8515
 8516
 8517
 8518
 8519
 8520
 8521
 8522
 8523
 8524
 8525
 8526
 8527
 8528
 8529
 8530
 8531
 8532
 8533
 8534
 8535
 8536
 8537
 8538
 8539
 8540
 8541
 8542
 8543
 8544
 8545
 8546
 8547
 8548
 8549
 8550
 8551
 8552
 8553
 8554
 8555
 8556
 8557
 8558
 8559
 8560
 8561
 8562
 8563
 8564
 8565
 8566
 8567
 8568
 8569
 8570
 8571
 8572
 8573
 8574
 8575
 8576
 8577
 8578
 8579
 8580
 8581
 8582
 8583
 8584
 8585
 8586
 8587
 8588
 8589
 8590
 8591
 8592
 8593
 8594
 8595
 8596
 8597
 8598
 8599
 8600
 8601
 8602
 8603
 8604
 8605
 8606
 8607
 8608
 8609
 8610
 8611
 8612
 8613
 8614
 8615
 8616
 8617
 8618
 8619
 8620
 8621
 8622
 8623
 8624
 8625
 8626
 8627
 8628
 8629
 8630
 8631
 8632
 8633
 8634
 8635
 8636
 8637
 8638
 8639
 8640
 8641
 8642
 8643
 8644
 8645
 8646
 8647
 8648
 8649
 8650
 8651
 8652
 8653
 8654
 8655
 8656
 8657
 8658
 8659
 8660
 8661
 8662
 8663
 8664
 8665
 8666
 8667
 8668
 8669
 8670
 8671
 8672
 8673
 8674
 8675
 8676
 8677
 8678
 8679
 8680
 8681
 8682
 8683
 8684
 8685
 8686
 8687
 8688
 8689
 8690
 8691
 8692
 8693
 8694
 8695
 8696
 8697
 8698
 8699
 8700
 8701
 8702
 8703
 8704
 8705
 8706
 8707
 8708
 8709
 8710
 8711
 8712
 8713
 8714
 8715
 8716
 8717
 8718
 8719
 8720
 8721
 8722
 8723
 8724
 8725
 8726
 8727
 8728
 8729
 8730
 8731
 8732
 8733
 8734
 8735
 8736
 8737
 8738
 8739
 8740
 8741
 8742
 8743
 8744
 8745
 8746
 8747
 8748
 8749
 8750
 8751
 8752
 8753
 8754
 8755
 8756
 8757
 8758
 8759
 8760
 8761
 8762
 8763
 8764
 8765
 8766
 8767
 8768
 8769
 8770
 8771
 8772
 8773
 8774
 8775
 8776
 8777
 8778
 8779
 8780
 8781
 8782
 8783
 8784
 8785
 8786
 8787
 8788
 8789
 8790
 8791
 8792
 8793
 8794
 8795
 8796
 8797
 8798
 8799
 8800
 8801
 8802
 8803
 8804
 8805
 8806
 8807
 8808
 8809
 8810
 8811
 8812
 8813
 8814
 8815
 8816
 8817
 8818
 8819
 8820
 8821
 8822
 8823
 8824
 8825
 8826
 8827
 8828
 8829
 8830
 8831
 8832
 8833
 8834
 8835
 8836
 8837
 8838
 8839
 8840
 8841
 8842
 8843
 8844
 8845
 8846
 8847
 8848
 8849
 8850
 8851
 8852
 8853
 8854
 8855
 8856
 8857
 8858
 8859
 8860
 8861
 8862
 8863
 8864
 8865
 8866
 8867
 8868
 8869
 8870
 8871
 8872
 8873
 8874
 8875
 8876
 8877
 8878
 8879
 8880
 8881
 8882
 8883
 8884
 8885
 8886
 8887
 8888
 8889
 8890
 8891
 8892
 8893
 8894
 8895
 8896
 8897
 8898
 8899
 8900
 8901
 8902
 8903
 8904
 8905
 8906
 8907
 8908
 8909
 8910
 8911
 8912
 8913
 8914
 8915
 8916
 8917
 8918
 8919
 8920
 8921
 8922
 8923
 8924
 8925
 8926
 8927
 8928
 8929
 8930
 8931
 8932
 8933
 8934
 8935
 8936
 8937
 8938
 8939
 8940
 8941
 8942
 8943
 8944
 8945
 8946
 8947
 8948
 8949
 8950
 8951
 8952
 8953
 8954
 8955
 8956
 8957
 8958
 8959
 8960
 8961
 8962
 8963
 8964
 8965
 8966
 8967
 8968
 8969
 8970
 8971
 8972
 8973
 8974
 8975
 8976
 8977
 8978
 8979
 8980
 8981
 8982
 8983
 8984
 8985
 8986
 8987
 8988
 8989
 8990
 8991
 8992
 8993
 8994
 8995
 8996
 8997
 8998
 8999
 9000
 9001
 9002
 9003
 9004
 9005
 9006
 9007
 9008
 9009
 9010
 9011
 9012
 9013
 9014
 9015
 9016
 9017
 9018
 9019
 9020
 9021
 9022
 9023
 9024
 9025
 9026
 9027
 9028
 9029
 9030
 9031
 9032
 9033
 9034
 9035
 9036
 9037
 9038
 9039
 9040
 9041
 9042
 9043
 9044
 9045
 9046
 9047
 9048
 9049
 9050
 9051
 9052
 9053
 9054
 9055
 9056
 9057
 9058
 9059
 9060
 9061
 9062
 9063
 9064
 9065
 9066
 9067
 9068
 9069
 9070
 9071
 9072
 9073
 9074
 9075
 9076
 9077
 9078
 9079
 9080
 9081
 9082
 9083
 9084
 9085
 9086
 9087
 9088
 9089
 9090
 9091
 9092
 9093
 9094
 9095
 9096
 9097
 9098
 9099
 9100
 9101
 9102
 9103
 9104
 9105
 9106
 9107
 9108
 9109
 9110
 9111
 9112
 9113
 9114
 9115
 9116
 9117
 9118
 9119
 9120
 9121
 9122
 9123
 9124
 9125
 9126
 9127
 9128
 9129
 9130
 9131
 9132
 9133
 9134
 9135
 9136
 9137
 9138
 9139
 9140
 9141
 9142
 9143
 9144
 9145
 9146
 9147
 9148
 9149
 9150
 9151
 9152
 9153
 9154
 9155
 9156
 9157
 9158
 9159
 9160
 9161
 9162
 9163
 9164
 9165
 9166
 9167
 9168
 9169
 9170
 9171
 9172
 9173
 9174
 9175
 9176
 9177
 9178
 9179
 9180
 9181
 9182
 9183
 9184
 9185
 9186
 9187
 9188
 9189
 9190
 9191
 9192
 9193
 9194
 9195
 9196
 9197
 9198
 9199
 9200
 9201
 9202
 9203
 9204
 9205
 9206
 9207
 9208
 9209
 9210
 9211
 9212
 9213
 9214
 9215
 9216
 9217
 9218
 9219
 9220
 9221
 9222
 9223
 9224
 9225
 9226
 9227
 9228
 9229
 9230
 9231
 9232
 9233
 9234
 9235
 9236
 9237
 9238
 9239
 9240
 9241
 9242
 9243
 9244
 9245
 9246
 9247
 9248
 9249
 9250
 9251
 9252
 9253
 9254
 9255
 9256
 9257
 9258
 9259
 9260
 9261
 9262
 9263
 9264
 9265
 9266
 9267
 9268
 9269
 9270
 9271
 9272
 9273
 9274
 9275
 9276
 9277
 9278
 9279
 9280
 9281
 9282
 9283
 9284
 9285
 9286
 9287
 9288
 9289
 9290
 9291
 9292
 9293
 9294
 9295
 9296
 9297
 9298
 9299
 9300
 9301
 9302
 9303
 9304
 9305
 9306
 9307
 9308
 9309
 9310
 9311
 9312
 9313
 9314
 9315
 9316
 9317
 9318
 9319
 9320
 9321
 9322
 9323
 9324
 9325
 9326
 9327
 9328
 9329
 9330
 9331
 9332
 9333
 9334
 9335
 9336
 9337
 9338
 9339
 9340
 9341
 9342
 9343
 9344
 9345
 9346
 9347
 9348
 9349
 9350
 9351
 9352
 9353
 9354
 9355
 9356
 9357
 9358
 9359
 9360
 9361
 9362
 9363
 9364
 9365
 9366
 9367
 9368
 9369
 9370
 9371
 9372
 9373
 9374
 9375
 9376
 9377
 9378
 9379
 9380
 9381
 9382
 9383
 9384
 9385
 9386
 9387
 9388
 9389
 9390
 9391
 9392
 9393
 9394
 9395
 9396
 9397
 9398
 9399
 9400
 9401
 9402
 9403
 9404
 9405
 9406
 9407
 9408
 9409
 9410
 9411
 9412
 9413
 9414
 9415
 9416
 9417
 9418
 9419
 9420
 9421
 9422
 9423
 9424
 9425
 9426
 9427
 9428
 9429
 9430
 9431
 9432
 9433
 9434
 9435
 9436
 9437
 9438
 9439
 9440
 9441
 9442
 9443
 9444
 9445
 9446
 9447
 9448
 9449
 9450
 9451
 9452
 9453
 9454
 9455
 9456
 9457
 9458
 9459
 9460
 9461
 9462
 9463
 9464
 9465
 9466
 9467
 9468
 9469
 9470
 9471
 9472
 9473
 9474
 9475
 9476
 9477
 9478
 9479
 9480
 9481
 9482
 9483
 9484
 9485
 9486
 9487
 9488
 9489
 9490
 9491
 9492
 9493
 9494
 9495
 9496
 9497
 9498
 9499
 9500
 9501
 9502
 9503
 9504
 9505
 9506
 9507
 9508
 9509
 9510
 9511
 9512
 9513
 9514
 9515
 9516
 9517
 9518
 9519
 9520
 9521
 9522
 9523
 9524
 9525
 9526
 9527
 9528
 9529
 9530
 9531
 9532
 9533
 9534
 9535
 9536
 9537
 9538
 9539
 9540
 9541
 9542
 9543
 9544
 9545
 9546
 9547
 9548
 9549
 9550
 9551
 9552
 9553
 9554
 9555
 9556
 9557
 9558
 9559
 9560
 9561
 9562
 9563
 9564
 9565
 9566
 9567
 9568
 9569
 9570
 9571
 9572
 9573
 9574
 9575
 9576
 9577
 9578
 9579
 9580
 9581
 9582
 9583
 9584
 9585
 9586
 9587
 9588
 9589
 9590
 9591
 9592
 9593
 9594
 9595
 9596
 9597
 9598
 9599
 9600
 9601
 9602
 9603
 9604
 9605
 9606
 9607
 9608
 9609
 9610
 9611
 9612
 9613
 9614
 9615
 9616
 9617
 9618
 9619
 9620
 9621
 9622
 9623
 9624
 9625
 9626
 9627
 9628
 9629
 9630
 9631
 9632
 9633
 9634
 9635
 9636
 9637
 9638
 9639
 9640
 9641
 9642
 9643
 9644
 9645
 9646
 9647
 9648
 9649
 9650
 9651
 9652
 9653
 9654
 9655
 9656
 9657
 9658
 9659
 9660
 9661
 9662
 9663
 9664
 9665
 9666
 9667
 9668
 9669
 9670
 9671
 9672
 9673
 9674
 9675
 9676
 9677
 9678
 9679
 9680
 9681
 9682
 9683
 9684
 9685
 9686
 9687
 9688
 9689
 9690
 9691
 9692
 9693
 9694
 9695
 9696
 9697
 9698
 9699
 9700
 9701
 9702
 9703
 9704
 9705
 9706
 9707
 9708
 9709
 9710
 9711
 9712
 9713
 9714
 9715
 9716
 9717
 9718
 9719
 9720
 9721
 9722
 9723
 9724
 9725
 9726
 9727
 9728
 9729
 9730
 9731
 9732
 9733
 9734
 9735
 9736
 9737
 9738
 9739
 9740
 9741
 9742
 9743
 9744
 9745
 9746
 9747
 9748
 9749
 9750
 9751
 9752
 9753
 9754
 9755
 9756
 9757
 9758
 9759
 9760
 9761
 9762
 9763
 9764
 9765
 9766
 9767
 9768
 9769
 9770
 9771
 9772
 9773
 9774
 9775
 9776
 9777
 9778
 9779
 9780
 9781
 9782
 9783
 9784
 9785
 9786
 9787
 9788
 9789
 9790
 9791
 9792
 9793
 9794
 9795
 9796
 9797
 9798
 9799
 9800
 9801
 9802
 9803
 9804
 9805
 9806
 9807
 9808
 9809
 9810
 9811
 9812
 9813
 9814
 9815
 9816
 9817
 9818
 9819
 9820
 9821
 9822
 9823
 9824
 9825
 9826
 9827
 9828
 9829
 9830
 9831
 9832
 9833
 9834
 9835
 9836
 9837
 9838
 9839
 9840
 9841
 9842
 9843
 9844
 9845
 9846
 9847
 9848
 9849
 9850
 9851
 9852
 9853
 9854
 9855
 9856
 9857
 9858
 9859
 9860
 9861
 9862
 9863
 9864
 9865
 9866
 9867
 9868
 9869
 9870
 9871
 9872
 9873
 9874
 9875
 9876
 9877
 9878
 9879
 9880
 9881
 9882
 9883
 9884
 9885
 9886
 9887
 9888
 9889
 9890
 9891
 9892
 9893
 9894
 9895
 9896
 9897
 9898
 9899
 9900
 9901
 9902
 9903
 9904
 9905
 9906
 9907
 9908
 9909
 9910
 9911
 9912
 9913
 9914
 9915
 9916
 9917
 9918
 9919
 9920
 9921
 9922
 9923
 9924
 9925
 9926
 9927
 9928
 9929
 9930
 9931
 9932
 9933
 9934
 9935
 9936
 9937
 9938
 9939
 9940
 9941
 9942
 9943
 9944
 9945
 9946
 9947
 9948
 9949
 9950
 9951
 9952
 9953
 9954
 9955
 9956
 9957
 9958
 9959
 9960
 9961
 9962
 9963
 9964
 9965
 9966
 9967
 9968
 9969
 9970
 9971
 9972
 9973
 9974
 9975
 9976
 9977
 9978
 9979
 9980
 9981
 9982
 9983
 9984
 9985
 9986
 9987
 9988
 9989
 9990
 9991
 9992
 9993
 9994
 9995
 9996
 9997
 9998
 9999
10000
10001
10002
10003
10004
10005
10006
10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070
10071
10072
10073
10074
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151
10152
10153
10154
10155
10156
10157
10158
10159
10160
10161
10162
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176
10177
10178
10179
10180
10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203
10204
10205
10206
10207
10208
10209
10210
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
10258
10259
10260
10261
10262
10263
10264
10265
10266
10267
10268
10269
10270
10271
10272
10273
10274
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284
10285
10286
10287
10288
10289
10290
10291
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335
10336
10337
10338
10339
10340
10341
10342
10343
10344
10345
10346
10347
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361
10362
10363
10364
10365
10366
10367
10368
10369
10370
10371
10372
10373
10374
10375
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441
10442
10443
10444
10445
10446
10447
10448
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487
10488
10489
10490
10491
10492
10493
10494
10495
10496
10497
10498
10499
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
10536
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606
10607
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
10711
10712
10713
10714
10715
10716
10717
10718
10719
10720
10721
10722
10723
10724
10725
10726
10727
10728
10729
10730
10731
10732
10733
10734
10735
10736
10737
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749
10750
10751
10752
10753
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800
10801
10802
10803
10804
10805
10806
10807
10808
10809
10810
10811
10812
10813
10814
10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863
10864
10865
10866
10867
10868
10869
10870
10871
10872
10873
10874
10875
10876
10877
10878
10879
10880
10881
10882
10883
10884
10885
10886
10887
10888
10889
10890
10891
10892
10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091
11092
11093
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104
11105
11106
11107
11108
11109
11110
11111
11112
11113
11114
11115
11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180
11181
11182
11183
11184
11185
11186
11187
11188
11189
11190
11191
11192
11193
11194
11195
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214
11215
11216
11217
11218
11219
11220
11221
11222
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233
11234
11235
11236
11237
11238
11239
11240
11241
11242
11243
11244
11245
11246
11247
11248
11249
11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354
11355
11356
11357
11358
11359
11360
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698
11699
11700
11701
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728
11729
11730
11731
11732
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976
11977
11978
11979
11980
11981
11982
11983
11984
11985
11986
11987
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044
12045
12046
12047
12048
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058
12059
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
12419
12420
12421
12422
12423
12424
12425
12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487
12488
12489
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519
12520
12521
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537
12538
12539
12540
12541
12542
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589
12590
12591
12592
12593
12594
12595
12596
12597
12598
12599
12600
12601
12602
12603
12604
12605
12606
12607
12608
12609
12610
12611
12612
12613
12614
12615
12616
12617
12618
12619
12620
12621
12622
12623
12624
12625
12626
12627
12628
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640
12641
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663
12664
12665
12666
12667
12668
12669
12670
12671
12672
12673
12674
12675
12676
12677
12678
12679
12680
12681
12682
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702
12703
12704
12705
12706
12707
12708
12709
12710
12711
12712
12713
12714
12715
12716
12717
12718
12719
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737
12738
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748
12749
12750
12751
12752
12753
12754
12755
12756
12757
12758
12759
12760
12761
12762
12763
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781
12782
12783
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802
12803
12804
12805
12806
12807
12808
12809
12810
12811
12812
12813
12814
12815
12816
12817
12818
12819
12820
12821
12822
12823
12824
12825
12826
12827
12828
12829
12830
12831
12832
12833
12834
12835
12836
12837
12838
12839
12840
12841
12842
12843
12844
12845
12846
12847
12848
12849
12850
12851
12852
12853
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882
12883
12884
12885
12886
12887
12888
12889
12890
12891
12892
12893
12894
12895
12896
12897
12898
12899
12900
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911
12912
12913
12914
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924
12925
12926
12927
12928
12929
12930
12931
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
12954
12955
12956
12957
12958
12959
12960
12961
12962
12963
12964
12965
12966
12967
12968
12969
12970
12971
12972
12973
12974
12975
12976
12977
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987
12988
12989
12990
12991
12992
12993
12994
12995
12996
12997
12998
12999
13000
13001
13002
13003
13004
13005
13006
13007
13008
13009
13010
13011
13012
13013
13014
13015
13016
13017
13018
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
13041
13042
13043
13044
13045
13046
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157
13158
13159
13160
13161
13162
13163
13164
13165
13166
13167
13168
13169
13170
13171
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186
13187
13188
13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265
13266
13267
13268
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297
13298
13299
13300
13301
13302
13303
13304
13305
13306
13307
13308
13309
13310
13311
13312
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358
13359
13360
13361
13362
13363
13364
13365
13366
13367
13368
13369
13370
13371
13372
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385
13386
13387
13388
13389
13390
13391
13392
13393
13394
13395
13396
13397
13398
13399
13400
13401
13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435
13436
13437
13438
13439
13440
13441
13442
13443
13444
13445
13446
13447
13448
13449
13450
13451
13452
13453
13454
13455
13456
13457
13458
13459
13460
13461
13462
13463
13464
13465
13466
13467
13468
13469
13470
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481
13482
13483
13484
13485
13486
13487
13488
13489
13490
13491
13492
13493
13494
13495
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545
13546
13547
13548
13549
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	_SYS_FS_AUTOFS_H
#define	_SYS_FS_AUTOFS_H

#include <rpc/clnt.h>
#include <gssapi/gssapi.h>
#include <sys/vfs.h>
#include <sys/dirent.h>
#include <sys/types.h>
#include <sys/types32.h>
#include <sys/note.h>
#include <sys/time_impl.h>
#include <sys/mntent.h>
#include <nfs/mount.h>
#include <rpc/rpcsec_gss.h>
#include <sys/zone.h>
#include <sys/door.h>
#include <rpcsvc/autofs_prot.h>

#ifdef _KERNEL
#include <sys/vfs_opreg.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif


#ifdef	_KERNEL


/*
 * Tracing macro; expands to nothing for non-debug kernels.
 */
#ifndef DEBUG
#define	AUTOFS_DPRINT(x)
#else
#define	AUTOFS_DPRINT(x)	auto_dprint x
#endif

/*
 * Per AUTOFS mountpoint information.
 */
typedef struct fninfo {
	struct vfs	*fi_mountvfs;		/* mounted-here VFS */
	struct vnode	*fi_rootvp;		/* root vnode */
	struct knetconfig fi_knconf;		/* netconfig */
	struct netbuf	fi_addr;		/* daemon address */
	char		*fi_path;		/* autofs mountpoint */
	char 		*fi_map;		/* context/map-name */
	char		*fi_subdir;		/* subdir within map */
	char		*fi_key;		/* key to use on direct maps */
	char		*fi_opts;		/* default mount options */
	int		fi_pathlen;		/* autofs mountpoint len */
	int		fi_maplen;		/* size of context */
	int		fi_subdirlen;
	int		fi_keylen;
	int		fi_optslen;		/* default mount options len */
	int		fi_refcnt;		/* reference count */
	int		fi_flags;
	int		fi_mount_to;
	int		fi_rpc_to;
	zoneid_t	fi_zoneid;		/* zone mounted in */
} fninfo_t;

/*
 * The AUTOFS locking scheme:
 *
 * The locks:
 * 	fn_lock: protects the fn_node. It must be grabbed to change any
 *		 field on the fn_node, except for those protected by
 *		 fn_rwlock.
 *
 * 	fn_rwlock: readers/writers lock to protect the subdirectory and
 *		   top level list traversal.
 *		   Protects: fn_dirents
 *			     fn_next
 *		             fn_size
 *		             fn_linkcnt
 *                 - Grab readers when checking if certain fn_node exists
 *                   under fn_dirents.
 *		   - Grab readers when attempting to reference a node
 *                   pointed to by fn_dirents, fn_next, and fn_parent.
 *                 - Grab writers to add a new fnnode under fn_dirents and
 *		     to remove a node pointed to by fn_dirents or fn_next.
 *
 *	Lock ordering:
 *		fn_rwlock > fn_lock
 *
 * The flags:
 *	MF_INPROG:
 *		- Indicates a mount request has been sent to the daemon.
 *		- If this flag is set, the thread sets MF_WAITING on the
 *                fnnode and sleeps.
 *
 *	MF_WAITING:
 *		- Set by a thread when it puts itself to sleep waiting for
 *		  the ongoing operation on this fnnode to be done.
 *
 * 	MF_LOOKUP:
 * 		- Indicates a lookup request has been sent to the daemon.
 *		- If this flag is set, the thread sets MF_WAITING on the
 *                fnnode and sleeps.
 *
 *	MF_IK_MOUNT:
 *		- This flag is set to indicate the mount was done in the
 *		  kernel, and so should the unmount.
 *
 *	MF_DIRECT:
 *		- Direct mountpoint if set, indirect otherwise.
 *
 *	MF_TRIGGER:
 *		- This is a trigger node.
 *
 *	MF_THISUID_MATCH_RQD:
 *		- User-relative context binding kind of node.
 *		- Node with this flag set requires a name match as well
 *		  as a cred match in order to be returned from the directory
 *		  hierarchy.
 *
 * 	MF_MOUNTPOINT:
 * 		- At some point automountd mounted a filesystem on this node.
 * 		If fn_trigger is non-NULL, v_vfsmountedhere is NULL and this
 * 		flag is set then the filesystem must have been forcibly
 * 		unmounted.
 */

/*
 * The inode of AUTOFS
 */
typedef struct fnnode {
	char		*fn_name;
	char		*fn_symlink;		/* if VLNK, this is what it */
						/* points to */
	int		fn_namelen;
	int		fn_symlinklen;
	uint_t		fn_linkcnt;		/* link count */
	mode_t		fn_mode;		/* file mode bits */
	uid_t		fn_uid;			/* owner's uid */
	gid_t		fn_gid;			/* group's uid */
	int		fn_error;		/* mount/lookup error */
	ino_t		fn_nodeid;
	off_t		fn_offset;		/* offset into directory */
	int		fn_flags;
	uint_t		fn_size;		/* size of directory */
	struct vnode	*fn_vnode;
	struct fnnode	*fn_parent;
	struct fnnode	*fn_next;		/* sibling */
	struct fnnode	*fn_dirents;		/* children */
	struct fnnode	*fn_trigger; 		/* pointer to next level */
						/* AUTOFS trigger nodes */
	struct action_list *fn_alp;		/* Pointer to mount info */
						/* used for remounting */
						/* trigger nodes */
	cred_t		*fn_cred;		/* pointer to cred, used for */
						/* "thisuser" processing */
	krwlock_t	fn_rwlock;		/* protects list traversal */
	kmutex_t	fn_lock;		/* protects the fnnode */
	timestruc_t	fn_atime;
	timestruc_t	fn_mtime;
	timestruc_t	fn_ctime;
	time_t		fn_ref_time;		/* time last referenced */
	time_t		fn_unmount_ref_time;	/* last time unmount was done */
	kcondvar_t	fn_cv_mount;		/* mount blocking variable */
	struct vnode	*fn_seen;		/* vnode already traversed */
	kthread_t	*fn_thread;		/* thread that has currently */
						/* modified fn_seen */
	struct autofs_globals *fn_globals;	/* global variables */
} fnnode_t;


#define	vntofn(vp)	((struct fnnode *)((vp)->v_data))
#define	fntovn(fnp)	(((fnp)->fn_vnode))
#define	vfstofni(vfsp)	((struct fninfo *)((vfsp)->vfs_data))

#define	MF_DIRECT	0x001
#define	MF_INPROG	0x002		/* Mount in progress */
#define	MF_WAITING	0x004
#define	MF_LOOKUP	0x008		/* Lookup in progress */
#define	MF_ATTR_WAIT	0x010
#define	MF_IK_MOUNT	0x040
#define	MF_TRIGGER	0x080
#define	MF_THISUID_MATCH_RQD	0x100	/* UID match required for this node */
					/* required for thisuser kind of */
					/* nodes */
#define	MF_MOUNTPOINT	0x200		/* Node is/was a mount point */

#define	AUTOFS_MODE		0555
#define	AUTOFS_BLOCKSIZE	1024

struct autofs_callargs {
	fnnode_t	*fnc_fnp;	/* fnnode */
	char		*fnc_name;	/* path to lookup/mount */
	kthread_t	*fnc_origin;	/* thread that fired up this thread */
					/* used for debugging purposes */
	cred_t		*fnc_cred;
};

struct autofs_globals {
	fnnode_t		*fng_rootfnnodep;
	int			fng_fnnode_count;
	int			fng_printed_not_running_msg;
	kmutex_t		fng_unmount_threads_lock;
	int			fng_unmount_threads;
	int			fng_verbose;
	zoneid_t		fng_zoneid;
	pid_t			fng_autofs_pid;
	kmutex_t		fng_autofs_daemon_lock;
	/*
	 * autofs_daemon_lock protects fng_autofs_daemon_dh
	 */
	door_handle_t		fng_autofs_daemon_dh;
};

extern kmutex_t autofs_minor_lock;
extern zone_key_t autofs_key;

/*
 * Sets the MF_INPROG flag on this fnnode.
 * fnp->fn_lock should be held before this macro is called,
 * operation is either MF_INPROG or MF_LOOKUP.
 */
#define	AUTOFS_BLOCK_OTHERS(fnp, operation)	{ \
	ASSERT(MUTEX_HELD(&(fnp)->fn_lock)); \
	ASSERT(!((fnp)->fn_flags & operation)); \
	(fnp)->fn_flags |= (operation); \
}

#define	AUTOFS_UNBLOCK_OTHERS(fnp, operation)	{ \
	auto_unblock_others((fnp), (operation)); \
}

extern struct vnodeops *auto_vnodeops;
extern const struct fs_operation_def auto_vnodeops_template[];

/*
 * Utility routines
 */
extern int auto_search(fnnode_t *, char *, fnnode_t **, cred_t *);
extern int auto_enter(fnnode_t *, char *, fnnode_t **, cred_t *);
extern void auto_unblock_others(fnnode_t *, uint_t);
extern int auto_wait4mount(fnnode_t *);
extern fnnode_t *auto_makefnnode(vtype_t, vfs_t *, char *, cred_t *,
    struct autofs_globals *);
extern void auto_freefnnode(fnnode_t *);
extern void auto_disconnect(fnnode_t *, fnnode_t *);
extern void auto_do_unmount(struct autofs_globals *);
/*PRINTFLIKE4*/
extern void auto_log(int verbose, zoneid_t zoneid, int level,
	const char *fmt, ...)
    __KPRINTFLIKE(4);
/*PRINTFLIKE2*/
extern void auto_dprint(int level, const char *fmt, ...)
    __KPRINTFLIKE(2);
extern int auto_calldaemon(zoneid_t, int, xdrproc_t, void *, xdrproc_t,
	void *, int, bool_t);
extern int auto_lookup_aux(fnnode_t *, char *, cred_t *);
extern void auto_new_mount_thread(fnnode_t *, char *, cred_t *);
extern int auto_nobrowse_option(char *);

extern int unmount_subtree(fnnode_t *, boolean_t);
extern void unmount_tree(struct autofs_globals *, boolean_t);
extern void autofs_free_globals(struct autofs_globals *);
extern void autofs_shutdown_zone(struct autofs_globals *);

#endif	/* _KERNEL */

/*
 * autofs structures and defines needed for use with doors.
 */
#define	AUTOFS_NULL	0
#define	AUTOFS_MOUNT	1
#define	AUTOFS_UNMOUNT	2
#define	AUTOFS_READDIR	3
#define	AUTOFS_LOOKUP	4
#define	AUTOFS_SRVINFO	5
#define	AUTOFS_MNTINFO	6

/*
 * autofs_door_args is a generic structure used to grab the command
 * from any of the argument structures passed in.
 */

typedef struct {
	int cmd;
	int xdr_len;
	char xdr_arg[1];	/* buffer holding xdr encoded data */
} autofs_door_args_t;


typedef struct {
	int res_status;
	int xdr_len;
	char xdr_res[1];	/* buffer holding xdr encoded data */
} autofs_door_res_t;

typedef enum autofs_res autofs_res_t;
typedef enum autofs_stat autofs_stat_t;
typedef enum autofs_action autofs_action_t;

typedef struct {
	void *	atsd_buf;
	size_t	atsd_len;
} autofs_tsd_t;

typedef struct sec_desdata {
	int		nd_sec_syncaddr_len;
	int		nd_sec_knc_semantics;
	int		nd_sec_netnamelen;
	uint64_t	nd_sec_knc_rdev;
	int		nd_sec_knc_unused[8];
} sec_desdata_t;

typedef struct sec_gssdata {
	int			element_length;
	rpc_gss_service_t	service;
	char			uname[MAX_NAME_LEN];
	char			inst[MAX_NAME_LEN];
	char			realm[MAX_NAME_LEN];
	uint_t			qop;
} sec_gssdata_t;

typedef struct nfs_secdata  {
	sec_desdata_t	nfs_des_clntdata;
	sec_gssdata_t	nfs_gss_clntdata;
} nfs_secdata_t;

/*
 * Comma separated list of mntoptions which are inherited when the
 * "restrict" option is present.  The RESTRICT option must be first!
 * This define is shared between the kernel and the automount daemon.
 */
#define	RESTRICTED_MNTOPTS	\
	MNTOPT_RESTRICT, MNTOPT_NOSUID, MNTOPT_NOSETUID, MNTOPT_NODEVICES

/*
 * AUTOFS syscall entry point
 */
enum autofssys_op { AUTOFS_UNMOUNTALL, AUTOFS_SETDOOR };

#ifdef	_KERNEL
extern int autofssys(enum autofssys_op, uintptr_t);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_AUTOFS_H */
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright (c) 2014 Joyent, Inc.  All rights reserved.
 */

#ifndef _SYS_FS_BOOTFS_IMPL_H
#define	_SYS_FS_BOOTFS_IMPL_H

#include <sys/types.h>
#include <sys/list.h>
#include <sys/avl.h>
#include <sys/vnode.h>
#include <sys/vfs_opreg.h>
#include <sys/kstat.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * The bootfs node is the file system specific version of the vnode for the
 * bootfs file system. Because the bootfs file system is entirely a read-only
 * file system, this structure requires no locking as the contents are
 * immutable.
 */
typedef struct bootfs_node {
	char			*bvn_name;	/* entry name */
	struct vnode		*bvn_vnp;	/* Corresponding vnode */
	avl_tree_t		bvn_dir;	/* directory entries, if VDIR */
	avl_node_t		bvn_link;	/* dirent link */
	list_node_t		bvn_alink;	/* link for all nodes */
	uint64_t		bvn_addr;	/* Address in pmem */
	uint64_t		bvn_size;	/* Size of the file */
	struct bootfs_node	*bvn_parent;	/* .. */
	vattr_t			bvn_attr;	/* attributes for the node */
} bootfs_node_t;

typedef struct bootfs_stat {
	kstat_named_t	bfss_nfiles;
	kstat_named_t	bfss_ndirs;
	kstat_named_t	bfss_nbytes;
	kstat_named_t	bfss_ndups;
	kstat_named_t	bfss_ndiscards;
} bootfs_stat_t;

typedef struct bootfs {
	vfs_t			*bfs_vfsp;
	char			*bfs_mntpath;
	bootfs_node_t		*bfs_rootvn;
	kstat_t			*bfs_kstat;
	list_t			bfs_nodes;
	minor_t			bfs_minor;
	uint_t			bfs_ninode;
	bootfs_stat_t		bfs_stat;
} bootfs_t;

extern void bootfs_construct(bootfs_t *);
extern void bootfs_destruct(bootfs_t *);
extern int bootfs_node_constructor(void *, void *, int);
extern void bootfs_node_destructor(void *, void *);

extern struct vnodeops *bootfs_vnodeops;
extern const fs_operation_def_t bootfs_vnodeops_template[];
extern kmem_cache_t *bootfs_node_cache;
extern major_t bootfs_major;

#ifdef __cplusplus
}
#endif

#endif /* _SYS_FS_BOOTFS_IMPL_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_DECOMP_H
#define	_SYS_DECOMP_H

#ifdef	__cplusplus
extern "C" {
#endif

#define	CH_MAGIC_ZLIB	0x5a636d70	/* ZLIB compression */
#define	CH_MAGIC_GZIP	0x8B1F		/* GZIP compression */

#define	CH_VERSION	1

#define	CH_ALG_ZLIB	1

struct comphdr {
	uint64_t	ch_magic;
	uint64_t	ch_version;
	uint64_t	ch_algorithm;
	uint64_t	ch_fsize;
	uint64_t	ch_blksize;
	uint64_t	ch_blkmap[1];
};

#define	ZMAXBUF(n)	((n) + ((n) / 1000) + 12)

#ifdef	_KERNEL

struct dcnode {
	struct vnode	*dc_vp;
	struct vnode	*dc_subvp;
	struct kmem_cache *dc_bufcache;
	kmutex_t	dc_lock;
	struct dcnode	*dc_hash;
	struct dcnode	*dc_lrunext;
	struct dcnode	*dc_lruprev;
	struct comphdr	*dc_hdr;
	size_t		dc_hdrsize;
	size_t		dc_zmax;
	int		dc_mapcnt;
};

#define	VTODC(vp)	((struct dcnode *)(vp)->v_data)
#define	DCTOV(dp)	((dp)->dc_vp)

struct vnode	*decompvp(struct vnode *, struct cred *, caller_context_t *);

#endif

#ifdef	__cplusplus
}
#endif
#endif	/* _SYS_DECOMP_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_DV_NODE_H
#define	_SYS_DV_NODE_H

/*
 * dv_nodes are the file-system specific part of the
 * vnodes for the device filesystem.
 *
 * The device filesystem exports two node types:
 *
 * VDIR	nodes		to represent nexus drivers
 * VCHR & VBLK nodes	to represent devices
 */

#include <sys/dirent.h>
#include <sys/sunddi.h>
#include <sys/devops.h>
#include <sys/ddi_impldefs.h>
#include <sys/fs/sdev_impl.h>
#include <sys/devpolicy.h>
#include <sys/avl.h>

#ifdef _KERNEL
#include <sys/vfs_opreg.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _KERNEL


/*
 * Here's the focal point of this filesystem
 */
typedef struct dv_node {
	char		*dv_name;	/* pointer to name */
	size_t		dv_namelen;	/* strlen(dv_name) */
	struct vnode	*dv_vnode;	/* vnode for this dv_node */

	/*
	 * The dv_contents lock should be held (read) before looking at
	 * any of the fields below, and held (write) before modifying them.
	 */
	krwlock_t	dv_contents;	/* held while anything is changing */

	dev_info_t	*dv_devi;	/* VDIR: underlying devinfo node */
					/* has ndi_devi_hold on device */

	struct dv_node	*dv_dotdot;	/* parent: my parent dv_node */
	avl_tree_t	dv_entries;	/* VDIR: contents as avl tree */
	avl_node_t	dv_avllink;	/* avl node linkage */

	struct vnode	*dv_attrvp;	/* persistent attribute store */
	struct vattr	*dv_attr;	/* attributes not yet persistent */

	ino64_t		dv_ino;		/* fake inode */
	int		dv_flags;	/* state bits and stuff */
	uint_t		dv_nlink;	/* link count */
	uint_t		dv_busy;	/* directory busy count */
	devplcy_t	*dv_priv;	/* access privilege */
	mode_t		dv_dflt_mode;	/* create_priv_minor_node mode */
	struct sdev_dv	*dv_sdev;	/* sdev node[s] if exists */
} dvnode_t;

#define	DV_BUILD	0x1		/* directory out-of-date */
#define	DV_NO_FSPERM	0x2		/* ignore fs permissions */
#define	DV_INTERNAL	0x04		/* internal node */
#define	DV_ACL		0x08		/* node has acl */
#define	DV_DFLT_MODE	0x010		/* dv_dflt_mode set */

#define	DV_ROOTINO	((ino_t)2)	/* root inode no. for devfs */

#define	DVTOV(n)	((struct vnode *)(n)->dv_vnode)
#define	VTODV(vp)	((struct dv_node *)(vp)->v_data)
#define	DV_STALE(dv)	(dv->dv_devi == NULL)

#define	DV_UID_DEFAULT	0	/* default uid for devs and dirs */
#define	DV_GID_DEFAULT	3	/* default gid for devs and dirs */
#define	DV_DIRMODE_DEFAULT	(S_IFDIR | 0755)	/* directories */
#define	DV_DEVMODE_DEFAULT	(0600)			/* special files */
#define	DV_DEVMODE_PRIV		(0666)		/* priv based access only */

/* flags for devfs_clean() */
#define	DV_CLEAN_FORCE	0x01	/* force clean of refed directories */
#define	DV_RESET_PERM	0x02	/* force resetting of node permission */
#define	DV_CLEANDIR_LCK	0x04	/* dv_contents already held */

struct devfs_data {
	struct	dv_node	*devfs_root;
	struct	vfs	*devfs_vfsp;
};

#define	VFSTODVFS(vfsp)	((struct devfs_data *)((vfsp)->vfs_data))

/* dv_fid overlays the fid structure (for VFS_VGET) */
struct dv_fid {
	uint16_t	dvfid_len;
	ino32_t		dvfid_ino;
	int32_t		dvfid_gen;
};

/*
 * Compare a vattr's and mperm_t's minor permissions (uid, gid & mode)
 */
#define	VATTRP_MP_CMP(attrp, mp)				\
	(!((attrp->va_uid == mp.mp_uid) &&			\
	(attrp->va_gid == mp.mp_gid) &&				\
	((attrp->va_mode & S_IAMB) == (mp.mp_mode & S_IAMB))))

/*
 * Merge an mperm_t's minor permissions into a vattr
 */
#define	VATTR_MP_MERGE(attr, mp)				\
	attr.va_uid = mp.mp_uid;				\
	attr.va_gid = mp.mp_gid;				\
	attr.va_mode = 						\
	    (attr.va_mode & ~S_IAMB) | (mp.mp_mode & S_IAMB);

#define	VATTRP_MP_MERGE(attrp, mp)				\
	attrp->va_uid = mp.mp_uid;				\
	attrp->va_gid = mp.mp_gid;				\
	attrp->va_mode = 					\
	    (attrp->va_mode & ~S_IAMB) | (mp.mp_mode & S_IAMB);

/*
 * dv_shadow_node flags
 */
#define	DV_SHADOW_CREATE	0x01		/* create attribute node */
#define	DV_SHADOW_WRITE_HELD	0x02		/* dv_contents write held */

/*
 * Directory tree traversal
 */
#define	DV_FIRST_ENTRY(ddv)	avl_first(&(ddv)->dv_entries)
#define	DV_NEXT_ENTRY(ddv, dv)	AVL_NEXT(&(ddv)->dv_entries, (dv))

extern uint_t devfs_clean_key;	/* tsd key */
extern const char dvnm[];	/* share some space.. */
extern struct dv_node *dvroot;	/* devfs root node */

extern void dv_node_cache_init(void);
extern void dv_node_cache_fini(void);
extern struct dv_node *dv_mkdir(struct dv_node *, dev_info_t *, char *);
extern struct dv_node *dv_mkroot(struct vfs *, dev_t);
extern void dv_destroy(struct dv_node *, uint_t);
extern void dv_insert(struct dv_node *, struct dv_node *);
extern void dv_shadow_node(struct vnode *, char *nm, struct vnode *,
    struct pathname *, struct vnode *, struct cred *, int);
extern int dv_find(struct dv_node *, char *, struct vnode **,
    struct pathname *, struct vnode *, struct cred *, uint_t);
extern void dv_filldir(struct dv_node *);
extern int dv_cleandir(struct dv_node *, char *, uint_t);
extern void dv_vattr_merge(struct dv_node *, struct vattr *);
extern void dv_walk(struct dv_node *, char *,
    void (*f)(struct dv_node *, void *), void *);

extern int devfs_clean(dev_info_t *, char *, uint_t);
extern int devfs_lookupname(char *, vnode_t **, vnode_t **);
extern int devfs_walk(char *, void (*f)(struct dv_node *, void *), void *);
extern int devfs_devpolicy(vnode_t *, devplcy_t **);
extern void devfs_get_defattr(vnode_t *, struct vattr *, int *);

extern struct dv_node *devfs_dip_to_dvnode(dev_info_t *);
extern int devfs_reset_perm(uint_t);
extern int devfs_remdrv_cleanup(const char *, const char *);

extern struct vnodeops *dv_vnodeops;
extern const struct fs_operation_def dv_vnodeops_template[];


#ifdef DEBUG
extern int devfs_debug;
#define	DV_DEBUG	0x01
#define	DV_DEBUG2	0x02
#define	DV_DEBUG3	0x04
#define	DV_DEBUG4	0x08
#define	DV_DEBUG5	0x10
#define	DV_SYSERR	0x1000
#define	DV_SYSTRACE	0x2000
#define	dcmn_err(args) if (devfs_debug & DV_DEBUG) printf args
#define	dcmn_err2(args) if (devfs_debug & DV_DEBUG2) printf args
#define	dcmn_err3(args) if (devfs_debug & DV_DEBUG3) printf args
#define	dcmn_err4(args) if (devfs_debug & DV_DEBUG4) printf args
#define	dcmn_err5(args) if (devfs_debug & DV_DEBUG5) printf args

#define	dsysdebug(err, args)				\
	if ((err && (devfs_debug & DV_SYSERR)) ||	\
	    (devfs_debug & DV_SYSTRACE)) printf args
#else
#define	dcmn_err(args) /* nothing */
#define	dcmn_err2(args) /* nothing */
#define	dcmn_err3(args) /* nothing */
#define	dcmn_err4(args) /* nothing */
#define	dcmn_err5(args) /* nothing */
#define	dsysdebug(err, args) /* nothing */
#endif


#endif	/* _KERNEL */

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_DV_NODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/


#ifndef	_SYS_FS_FIFONODE_H
#define	_SYS_FS_FIFONODE_H

#if defined(_KERNEL)
#include <sys/vfs_opreg.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif


/*
 * Each FIFOFS object is identified by a struct fifonode/vnode pair.
 * This is also the hierarchy
 * flk_lock protects:
 *		fn_mp
 *		fn_tail
 *		fn_count
 *		fn_flag
 *		fn_wcnt
 *		fn_rcnt
 *		fn_open
 *		fn_rsynccnt
 *		fn_wsynccnt
 *		fn_wwaitcnt
 *		fn_atime
 *		fn_mtime
 *		fn_ctime
 *		fn_insync
 *		flk_ref
 *		flk_ocsync
 * ftable lock protects		- actually this is independent
 *		fifoalloc[]
 *		fn_nextp
 *		fn_backp
 */
typedef struct fifolock {
	kmutex_t	flk_lock;	/* fifo lock */
	int		flk_ref;	/* number of fifonodes using this */
	short		flk_ocsync;	/* sync open/close */
	kcondvar_t	flk_wait_cv;	/* conditional for flk_ocsync */
	uint_t		flk_fill[4];	/* cache align lock structure */
} fifolock_t;

typedef struct fifonode fifonode_t;

struct fifonode {
	struct vnode	*fn_vnode;	/* represents the fifo/pipe */
	struct vnode	*fn_realvp;	/* node being shadowed by fifo */
	ino_t		fn_ino;		/* node id for pipes */
	fifonode_t	*fn_dest;	/* the other end of a pipe */
	struct msgb	*fn_mp;		/* message waiting to be read */
	struct msgb	*fn_tail;	/* last message to read */
	fifolock_t	*fn_lock;	/* pointer to per fifo lock */
	uint_t		fn_count;	/* Number of bytes on fn_mp */
	kcondvar_t	fn_wait_cv;	/* fifo conditional variable */
	ushort_t	fn_wcnt;	/* number of writers */
	ushort_t	fn_rcnt;	/* number of readers */
	ushort_t	fn_open;	/* open count of node */
	ushort_t	fn_wsynccnt;	/* fifos waiting for open write sync */
	ushort_t	fn_rsynccnt;	/* fifos waiting for open read sync */
	ushort_t	fn_wwaitcnt;	/* threads waiting to write data */
	timestruc_t	fn_atime;	/* access times */
	timestruc_t	fn_mtime;	/* modification time */
	timestruc_t	fn_ctime;	/* change time */
	fifonode_t	*fn_nextp;	/* next link in the linked list */
	fifonode_t	*fn_backp;	/* back link in linked list */
	struct cred	*fn_pcredp;	/* credential associated with peer */
	pid_t		fn_cpid;	/* original peer pid */
	int		fn_insync;
	uint_t		fn_flag;	/* flags as defined below */
};


typedef struct fifodata {
	fifolock_t	fifo_lock;
	fifonode_t	fifo_fnode[2];
} fifodata_t;

/*
 * Valid flags for fifonodes.
 */
#define	ISPIPE		0x0001	/* fifonode is that of a pipe */
#define	FIFOSEND	0x0002	/* file descriptor at stream head of pipe */
#define	FIFOOPEN	0x0004	/* fifo is opening */
#define	FIFOCLOSE	0x0008	/* fifo is closing */
#define	FIFOCONNLD	0x0010	/* connld pushed on pipe */
#define	FIFOFAST	0x0020	/* FIFO in fast mode */
#define	FIFOWANTR	0x0040	/* reader waiting for data */
#define	FIFOWANTW	0x0080	/* writer waiting to write */
#define	FIFOSETSIG	0x0100	/* I_SETSIG ioctl was issued */
#define	FIFOHIWATW	0x0200	/* We have gone over hi water mark */
#define	FIFORWBUSY	0x0400	/* Fifo is busy in read or write */
#define	FIFOPOLLW	0x0800	/* process waiting on poll write */
#define	FIFOPOLLR	0x1000	/* process waiting on poll read */
#define	FIFOISOPEN	0x2000	/* pipe is open */
#define	FIFOSYNC	0x4000	/* FIFO is waiting for open sync */
#define	FIFOWOCR	0x8000	/* Write open occurred */
#define	FIFOROCR	0x10000	/* Read open occurred */
/*
 * process waiting on poll read on band data
 * this can only occur if we go to streams
 * mode
 */
#define	FIFOPOLLRBAND	0x20000
#define	FIFOSTAYFAST	0x40000	/* don't turn into stream mode */
#define	FIFOWAITMODE	0x80000	/* waiting for the possibility to change mode */

#define	FIFOHIWAT	(16 * 1024)
#define	FIFOLOWAT	(0)

/*
 * Macros to convert a vnode to a fifnode, and vice versa.
 */
#define	VTOF(vp) ((struct fifonode *)((vp)->v_data))
#define	FTOV(fp) ((fp)->fn_vnode)

#if defined(_KERNEL)

/*
 * Fifohiwat defined as a variable is to allow tuning of the high
 * water mark if needed. It is not meant to be released.
 */
#if FIFODEBUG
extern int Fifohiwat;
#else /* FIFODEBUG */
#define	Fifohiwat	FIFOHIWAT
#endif /* FIFODEBUG */

extern struct vnodeops *fifo_vnodeops;
extern const struct fs_operation_def fifo_vnodeops_template[];
extern struct kmem_cache *fnode_cache;
extern struct kmem_cache *pipe_cache;

struct vfssw;
struct queue;

extern int	fifoinit(int, char *);
extern int	fifo_stropen(vnode_t **, int, cred_t *, int, int);
extern int	fifo_open(vnode_t **, int, cred_t *, caller_context_t *);
extern int	fifo_close(vnode_t *, int, int, offset_t, cred_t *,
			caller_context_t *);
extern void	fifo_cleanup(vnode_t *, int);
extern void	fiforemove(fifonode_t *);
extern ino_t	fifogetid(void);
extern vnode_t	*fifovp(vnode_t *, cred_t *);
extern void	makepipe(vnode_t **, vnode_t **);
extern void	fifo_fastflush(fifonode_t *);
extern void	fifo_vfastoff(vnode_t *);
extern void	fifo_fastoff(fifonode_t *);
extern struct streamtab *fifo_getinfo();
extern void	fifo_wakereader(fifonode_t *, fifolock_t *);
extern void	fifo_wakewriter(fifonode_t *, fifolock_t *);

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_FIFONODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * High Sierra filesystem internal routine definitions.
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_IMPL_H
#define	_SYS_FS_HSFS_IMPL_H

#include <sys/vfs_opreg.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * global routines.
 */

extern int hsfs_putapage(vnode_t *, page_t *, u_offset_t *, size_t *, int,
	cred_t *);
/* read a sector */
extern int hs_readsector(struct vnode *vp, uint_t secno, uchar_t *ptr);
/* lookup/construct an hsnode/vnode */
extern struct vnode *hs_makenode(struct hs_direntry *dp,
	uint_t lbn, uint_t off, struct vfs *vfsp);
/* make hsnode from directory lbn/off */
extern int hs_remakenode(uint_t lbn, uint_t off, struct vfs *vfsp,
	struct vnode **vpp);
/* lookup name in directory */
extern int hs_dirlook(struct vnode *dvp, char *name, int namlen,
	struct vnode **vpp, struct cred *cred);
/* find an hsnode in the hash list */
extern struct vnode *hs_findhash(ino64_t nodeid, uint_t lbn, uint_t off,
	struct vfs *vfsp);
/* destroy an hsnode */
extern void hs_freenode(vnode_t *vp, struct hsfs *fsp, int nopage);
/* parse a directory entry */
extern int hs_parsedir(struct hsfs *fsp, uchar_t *dirp,
	struct hs_direntry *hdp, char *dnp, int *dnlen, int last_offset);
/* convert d-characters */
extern int hs_namecopy(char *from, char *to, int size, ulong_t flags);
extern int hs_jnamecopy(char *from, char *to, int size, int maxsize,
	ulong_t flags);
extern int hs_joliet_cp(char *from, char *to, int size);
/* destroy the incore hnode table */
extern void hs_filldirent(struct vnode *vp, struct hs_direntry *hdp);
/* check vnode protection */
extern int hs_access(struct vnode *vp, mode_t m, struct cred *cred);

extern int hs_synchash(struct vfs *vfsp);

extern void hs_parse_dirdate(uchar_t *dp, struct timeval *tvp);
extern void hs_parse_longdate(uchar_t *dp, struct timeval *tvp);
extern int hs_uppercase_copy(char *from, char *to, int size);
extern void hs_log_bogus_disk_warning(struct hsfs *fsp, int errtype,
	uint_t data);
extern int hsfs_valid_dir(struct hs_direntry *hd);
extern void hs_init_hsnode_cache(void);
extern void hs_fini_hsnode_cache(void);

/*
 * Global data structures
 */
extern const struct fs_operation_def hsfs_vnodeops_template[];
extern struct vnodeops *hsfs_vnodeops;
extern kmutex_t hs_mounttab_lock;
extern struct hsfs *hs_mounttab;

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_IMPL_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_ISOSPEC_H
#define	_SYS_FS_HSFS_ISOSPEC_H

/*
 * ISO 9660 filesystem specification
 */

#ifdef	__cplusplus
extern "C" {
#endif

/* macros to parse binary integers */
#define	ZERO(x)		(uint_t)(((uchar_t *)(x))[0])
#define	ONE(x)		(uint_t)(((uchar_t *)(x))[1])
#define	TWO(x)		(uint_t)(((uchar_t *)(x))[2])
#define	THREE(x)	(uint_t)(((uchar_t *)(x))[3])

#define	MSB_INT(x) \
	((((((ZERO(x) << 8) | ONE(x)) << 8) | TWO(x)) << 8) | THREE(x))
#define	LSB_INT(x) \
	((((((THREE(x) << 8) | TWO(x)) << 8) | ONE(x)) << 8) | ZERO(x))
#define	MSB_SHORT(x)	((ZERO(x) << 8) | ONE(x))
#define	LSB_SHORT(x)	((ONE(x) << 8) | ZERO(x))

#if defined(__i386) || defined(__amd64)
#define	BOTH_SHORT(x)	(short)*((short *)x)
#define	BOTH_INT(x)	(int)*((int *)x)
#elif defined(__sparc)
/*
 * SPARC machines require that integers must
 * be aligned on a full word boundary.	CD-ROM data aligns
 * to even word boundary only.	Because of this mismatch,
 * we have to move integer data from CD-ROM to memory one
 * byte at a time.  LSB data starts first. We therefore
 * use this to do byte by byte copying.
 */
#define	BOTH_SHORT(x)	LSB_SHORT(x)
#define	BOTH_INT(x)	LSB_INT(x)
#endif

/*
 * The following describes actual on-disk structures.
 * To achieve portability, all structures are #defines
 * rather than a structure definition.	Macros are provided
 * to get either the data or address of individual fields.
 */

/* Overall High Sierra disk structure */
#define	ISO_SECTOR_SIZE	2048		/* bytes per logical sector */
#define	ISO_SECTOR_SHIFT	11		/* sector<->byte shift count */
#define	ISO_SEC_PER_PAGE	(PAGESIZE/HS_SECTOR_SIZE)
							/* sectors per page */
#define	ISO_SYSAREA_SEC	0		/* 1st sector of system area */
#define	ISO_VOLDESC_SEC	16		/* 1st sector of volume descriptors */
#define	MAXISOOFFSET (ISO_SECTOR_SIZE - 1)
#define	MAXISOMASK   (~MAXISOOFFSET)


/* Standard File Structure Volume Descriptor */

enum iso_voldesc_type {
	ISO_VD_BOOT = 0, ISO_VD_PVD = 1, ISO_VD_SVD = 2, ISO_VD_VPD = 3,
	ISO_VD_UNIX = 4,		/* UNIX extension */
	ISO_VD_EOV = 255
};
#define	ISO_ID_STRING	"CD001"		/* ISO_std_id field */
#define	ISO_ID_STRLEN	5		/* ISO_std_id field length */
#define	ISO_ID_VER	1		/* ISO_std_ver field ISO-9660:1988 */
#define	ISO_ID_VER2	2		/* ISO_std_ver field ISO-9660:1999 */
#define	ISO_FILE_STRUCT_ID_VER	1	/* ISO_file structure version  field */
#define	ISO_SYS_ID_STRLEN	32
#define	ISO_VOL_ID_STRLEN	32
#define	ISO_VOL_SET_ID_STRLEN	128
#define	ISO_PUB_ID_STRLEN	128
#define	ISO_PREP_ID_STRLEN	128
#define	ISO_APPL_ID_STRLEN	128
#define	ISO_COPYR_ID_STRLEN	37
#define	ISO_ABSTR_ID_STRLEN	37
#define	ISO_SHORT_DATE_LEN	7
#define	ISO_DATE_LEN		17



/* macros to get the address of each field */
#define	ISO_desc_type(x)	(&((uchar_t *)x)[0])
#define	ISO_std_id(x)		(&((uchar_t *)x)[1])
#define	ISO_std_ver(x)		(&((uchar_t *)x)[6])
#define	ISO_sys_id(x)		(&((uchar_t *)x)[8])
#define	ISO_vol_id(x)		(&((uchar_t *)x)[40])
#define	ISO_vol_size(x)		(&((uchar_t *)x)[80])
#define	ISO_svd_esc(x)		(&((uchar_t *)x)[88])	/* Supplemental VD */
#define	ISO_set_size(x)		(&((uchar_t *)x)[120])
#define	ISO_set_seq(x)		(&((uchar_t *)x)[124])
#define	ISO_blk_size(x)		(&((uchar_t *)x)[128])
#define	ISO_ptbl_size(x)	(&((uchar_t *)x)[132])
#define	ISO_ptbl_man_ls(x)	(&((uchar_t *)x)[140])
#define	ISO_ptbl_opt_ls1(x)	(&((uchar_t *)x)[144])
#define	ISO_ptbl_man_ms(x)	(&((uchar_t *)x)[148])
#define	ISO_ptbl_opt_ms1(x)	(&((uchar_t *)x)[152])
#define	ISO_root_dir(x)		(&((uchar_t *)x)[156])
#define	ISO_vol_set_id(x)	(&((uchar_t *)x)[190])
#define	ISO_pub_id(x)		(&((uchar_t *)x)[318])
#define	ISO_prep_id(x)		(&((uchar_t *)x)[446])
#define	ISO_appl_id(x)		(&((uchar_t *)x)[574])
#define	ISO_copyr_id(x)		(&((uchar_t *)x)[702])
#define	ISO_abstr_id(x)		(&((uchar_t *)x)[739])
#define	ISO_bibli_id(x)		(&((uchar_t *)x)[776])
#define	ISO_cre_date(x)		(&((uchar_t *)x)[813])
#define	ISO_mod_date(x)		(&((uchar_t *)x)[830])
#define	ISO_exp_date(x)		(&((uchar_t *)x)[847])
#define	ISO_eff_date(x)		(&((uchar_t *)x)[864])
#define	ISO_file_struct_ver(x)	(&((uchar_t *)x)[881])

/* macros to get the values of each field (strings are returned as ptrs) */
#define	ISO_DESC_TYPE(x)	((enum iso_voldesc_type)*(ISO_desc_type(x)))
#define	ISO_STD_ID(x)		ISO_std_id(x)
#define	ISO_STD_VER(x)		*(ISO_std_ver(x))
#define	ISO_SYS_ID(x)		ISO_sys_id(x)
#define	ISO_VOL_ID(x)		ISO_vol_id(x)
#define	ISO_VOL_SIZE(x)		BOTH_INT(ISO_vol_size(x))
#define	ISO_SET_SIZE(x)		BOTH_SHORT(ISO_set_size(x))
#define	ISO_SET_SEQ(x)		BOTH_SHORT(ISO_set_seq(x))
#define	ISO_BLK_SIZE(x)		BOTH_SHORT(ISO_blk_size(x))
#define	ISO_PTBL_SIZE(x)	BOTH_INT(ISO_ptbl_size(x))
#define	ISO_PTBL_MAN_LS(x)	LSB_INT(ISO_ptbl_man_ls(x))
#define	ISO_PTBL_OPT_LS1(x)	LSB_INT(ISO_ptbl_opt_ls1(x))
#define	ISO_PTBL_MAN_MS(x)	MSB_INT(ISO_ptbl_man_ms(x))
#define	ISO_PTBL_OPT_MS1(x)	MSB_INT(ISO_ptbl_opt_ms1(x))
#define	ISO_ROOT_DIR(x)		ISO_root_dir(x)
#define	ISO_VOL_SET_ID(x)	ISO_vol_set_id(x)
#define	ISO_PUB_ID(x)		ISO_pub_id(x)
#define	ISO_PREP_ID(x)		ISO_prep_id(x)
#define	ISO_APPL_ID(x)		ISO_appl_id(x)
#define	ISO_COPYR_ID(x)		ISO_copyr_id(x)
#define	ISO_ABSTR_ID(x)		ISO_abstr_id(x)
#define	ISO_BIBLI_ID(x)		ISO_bibli_id(x)
#define	ISO_CRE_DATE(x)		HSV_cre_date(x)
#define	ISO_MOD_DATE(x)		HSV_mod_date(x)
#define	ISO_EXP_DATE(x)		HSV_exp_date(x)
#define	ISO_EFF_DATE(x)		HSV_eff_date(x)
#define	ISO_FILE_STRUCT_VER(x)	*(ISO_file_struct_ver(x))

/* Standard File Structure Volume Descriptor date fields */
#define	ISO_DATE_2DIG(x)	((((x)[0] - '0') * 10) +		\
					((x)[1] - '0'))
#define	ISO_DATE_4DIG(x)	((((x)[0] - '0') * 1000) +		\
					(((x)[1] - '0') * 100) +	\
					(((x)[2] - '0') * 10) +		\
					((x)[3] - '0'))
#define	ISO_DATE_YEAR(x)	ISO_DATE_4DIG(&((uchar_t *)x)[0])
#define	ISO_DATE_MONTH(x)	ISO_DATE_2DIG(&((uchar_t *)x)[4])
#define	ISO_DATE_DAY(x)		ISO_DATE_2DIG(&((uchar_t *)x)[6])
#define	ISO_DATE_HOUR(x)	ISO_DATE_2DIG(&((uchar_t *)x)[8])
#define	ISO_DATE_MIN(x)		ISO_DATE_2DIG(&((uchar_t *)x)[10])
#define	ISO_DATE_SEC(x)		ISO_DATE_2DIG(&((uchar_t *)x)[12])
#define	ISO_DATE_HSEC(x)	ISO_DATE_2DIG(&((uchar_t *)x)[14])
#define	ISO_DATE_GMTOFF(x)	(((char *)x)[16])



/* Directory Entry (Directory Record) */
#define	IDE_ROOT_DIR_REC_SIZE	34	/* size of root directory record */
#define	IDE_FDESIZE		33	/* fixed size for hsfs directory area */
					/* max size of a name */
#define	IDE_MAX_NAME_LEN	(255 - IDE_FDESIZE)


/* macros to get the address of each field */
#define	IDE_dir_len(x)		(&((uchar_t *)x)[0])
#define	IDE_xar_len(x)		(&((uchar_t *)x)[1])
#define	IDE_ext_lbn(x)		(&((uchar_t *)x)[2])
#define	IDE_ext_size(x)		(&((uchar_t *)x)[10])
#define	IDE_cdate(x)		(&((uchar_t *)x)[18])
#define	IDE_flags(x)		(&((uchar_t *)x)[25])
#define	IDE_intrlv_size(x)	(&((uchar_t *)x)[26])
#define	IDE_intrlv_skip(x)	(&((uchar_t *)x)[27])
#define	IDE_vol_set(x)		(&((uchar_t *)x)[28])
#define	IDE_name_len(x)		(&((uchar_t *)x)[32])
#define	IDE_name(x)		(&((uchar_t *)x)[33])
#define	IDE_sys_use_area(x)	(&((uchar_t *)x)[IDE_NAME_LEN(x) + \
				IDE_PAD_LEN(x)] + IDE_FDESIZE)

/* macros to get the values of each field (strings are returned as ptrs) */
#define	IDE_DIR_LEN(x)		*(IDE_dir_len(x))
#define	IDE_XAR_LEN(x)		*(IDE_xar_len(x))
#define	IDE_EXT_LBN(x)		BOTH_INT(IDE_ext_lbn(x))
#define	IDE_EXT_SIZE(x)		BOTH_INT(IDE_ext_size(x))
#define	IDE_CDATE(x)		IDE_cdate(x)
#define	IDE_FLAGS(x)		*(IDE_flags(x))
#define	IDE_INTRLV_SIZE(x)	*(IDE_intrlv_size(x))
#define	IDE_INTRLV_SKIP(x)	*(IDE_intrlv_skip(x))
#define	IDE_VOL_SET(x)		BOTH_SHORT(IDE_vol_set(x))
#define	IDE_NAME_LEN(x)		*(IDE_name_len(x))
#define	IDE_NAME(x)		IDE_name(x)
#define	IDE_PAD_LEN(x)		((IDE_NAME_LEN(x) % 2) ? 0 : 1)
#define	IDE_SUA_LEN(x)		((int)(IDE_DIR_LEN(x)) - (int)(IDE_FDESIZE) - \
				(int)(IDE_NAME_LEN(x)) - (int)(IDE_PAD_LEN(x)))

/* mask bits for IDE_FLAGS */
#define	IDE_EXISTENCE		0x01	/* zero if file exists */
#define	IDE_DIRECTORY		0x02	/* zero if file is not a directory */
#define	IDE_ASSOCIATED		0x04	/* zero if file is not Associated */
#define	IDE_RECORD		0x08	/* zero if no record attributes */
#define	IDE_PROTECTION		0x10	/* zero if no protection attributes */
#define	IDE_UNUSED_FLAGS	0x60
#define	IDE_LAST_EXTENT		0x80	/* zero if last extent in file */
#define	IDE_PROHIBITED	(IDE_DIRECTORY | IDE_RECORD | \
				IDE_LAST_EXTENT | IDE_UNUSED_FLAGS)

/* Directory Record date fields */
#define	IDE_DATE_YEAR(x)	(((uchar_t *)x)[0] + 1900)
#define	IDE_DATE_MONTH(x)	(((uchar_t *)x)[1])
#define	IDE_DATE_DAY(x)		(((uchar_t *)x)[2])
#define	IDE_DATE_HOUR(x)	(((uchar_t *)x)[3])
#define	IDE_DATE_MIN(x)		(((uchar_t *)x)[4])
#define	IDE_DATE_SEC(x)		(((uchar_t *)x)[5])
#define	IDE_DATE_GMTOFF(x)	(((char *)x)[6])

/* tests for Interchange Levels 1 & 2 file types */
#define	IDE_REGULAR_FILE(x)	(((x) & IDE_PROHIBITED) == 0)
#define	IDE_REGULAR_DIR(x)	(((x) & IDE_PROHIBITED) == IDE_DIRECTORY)

/*
 * A ISO filename is: "ABCDE.EEE;1" -> <filename> '.' <ext> ';' <version #>
 *
 * The ISO-9660:1988 (Version 1) maximum needed string length is:
 *	30 chars (filename + ext)
 * +	 2 chars ('.' + ';')
 * +	   strlen("32767")
 * +	   null byte
 * ================================
 * =	38 chars
 *
 * ISO_DIR_NAMELEN counts 30 chars + '.'
 */
#define	ISO_DIR_NAMELEN		31	/* max length of a directory name */
#define	ISO_FILE_NAMELEN	31	/* max length of a filename, */
					/* excluding ";" and version num */
#define	ISO_NAMELEN_V2		207	/* ISOv2: 254 - 33 - 14 (XA Record) */
#define	ISO_NAMELEN_V2_MAX	221	/* max length, ignorig ISOv2 */
#define	JOLIET_NAMELEN		64	/* Joliet file name length (spec) */
#define	JOLIET_NAMELEN_MAX	110	/* max Joliet file name length  */

/* Path table enry */
/* fix size of path table entry */
#define	IPE_FPESIZE		8
/* macros to get the address of each field */
#define	IPE_name_len(x)		(&((uchar_t *)x)[0])
#define	IPE_xar_len(x)		(&((uchar_t *)x)[1])
#define	IPE_ext_lbn(x)		(&((uchar_t *)x)[2])
#define	IPE_parent_no(x)	(&((uchar_t *)x)[6])
#define	IPE_name(x)		(&((uchar_t *)x)[8])

/* macros to get the values of each field */
#define	IPE_EXT_LBN(x)		(MSB_INT(IPE_ext_lbn(x)))
#define	IPE_XAR_LEN(x)		*(IPE_xar_len(x))
#define	IPE_NAME_LEN(x)		*(IPE_name_len(x))
#define	IPE_PARENT_NO(x)	*(short *)(IPE_parent_no(x))
#define	IPE_NAME(x)		IPE_name(x)

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_ISOSPEC_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * High Sierra filesystem structure definitions
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_NODE_H
#define	_SYS_FS_HSFS_NODE_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/taskq.h>

struct	hs_direntry {
	uint_t		ext_lbn;	/* LBN of start of extent */
	uint_t		ext_size;    	/* no. of data bytes in extent */
	struct timeval	cdate;		/* creation date */
	struct timeval	mdate;		/* last modification date */
	struct timeval	adate;		/* last access date */
	enum vtype	type;		/* file type */
	mode_t		mode;		/* mode and type of file (UNIX) */
	uint_t		nlink;		/* no. of links to file */
	uid_t		uid;		/* owner's user id */
	gid_t		gid;		/* owner's group id */
	ino64_t		inode;		/* inode number from rrip data */
	dev_t		r_dev;		/* major/minor device numbers */
	uint_t		xar_prot :1;	/* 1 if protection in XAR */
	uchar_t		xar_len;	/* no. of Logical blocks in XAR */
	uchar_t		intlf_sz;	/* intleaving size */
	uchar_t		intlf_sk;	/* intleaving skip factor */
	ushort_t	sym_link_flag;	/* flags for sym link */
	char		*sym_link; 	/* path of sym link for readlink() */
};

struct	ptable {
	uchar_t	filler[7];		/* filler */
	uchar_t	dname_len;		/* length of directory name */
	uchar_t	dname[HS_DIR_NAMELEN+1];	/* directory name */
};

struct ptable_idx {
	struct ptable_idx *idx_pptbl_idx; /* parent's path table index entry */
	struct ptable	*idx_mptbl;	/* path table entry for myself */
	ushort_t idx_nochild;		/* no. of children */
	ushort_t idx_childid;		/* directory no of first child */
};

/*
 * hsnode structure:
 *
 * hs_offset, hs_ptbl_idx, base  apply to VDIR type only
 *
 * nodeid uniquely identifies an hsnode, ISO9660 means
 * nodeid can be very big.
 * For directories it is the disk address of
 * the data extent of the dir (the directory itself,
 * ".", and ".." all point to same data extent).
 * For non-directories, it is the disk address of the
 * directory entry for the file; note that this does
 * not permit hard links, as it assumes a single dir
 * entry per file.
 */

struct  hsnode {
	struct hsnode	*hs_hash;	/* next hsnode in hash list */
	struct hsnode	*hs_freef;	/* next hsnode in free list */
	struct hsnode	*hs_freeb;	/* previous hsnode in free list */
	struct vnode	*hs_vnode;	/* the real vnode for the file */
	struct hs_direntry hs_dirent;	/* the directory entry for this file */
	ino64_t		hs_nodeid;	/* "inode" number for hsnode */
	uint_t		hs_dir_lbn;	/* LBN of directory entry */
	uint_t		hs_dir_off;	/* offset in LBN of directory entry */
	struct ptable_idx	*hs_ptbl_idx;	/* path table index */
	uint_t		hs_offset;	/* start offset in dir for searching */
	long		hs_mapcnt;	/* mappings to file pages */
	uint_t		hs_seq;		/* sequence number */
	uint_t		hs_flags;	/* (see below) */
	u_offset_t	hs_prev_offset; /* Last read end offset (readahead) */
	int		hs_num_contig;  /* Count of contiguous reads */
	int		hs_ra_bytes;    /* Bytes to readahead */
	kmutex_t	hs_contents_lock;	/* protects hsnode contents */
						/* 	except hs_offset */
};

/* hs_flags */
#define	HREF	1			/* hsnode is referenced */

/* hs_modes */

#define	HFDIR	0040000			/* directory */
#define	HFREG	0100000			/* regular file */

struct  hsfid {
	ushort_t	hf_len;		/* length of fid */
	ushort_t	hf_dir_off;	/* offset in LBN of directory entry */
	uint_t		hf_dir_lbn;	/* LBN of directory */
	uint32_t	hf_ino;		/* The inode number or HS_DUMMY_INO */
};


/*
 * All of the fields in the hs_volume are read-only once they have been
 * initialized.
 */
struct	hs_volume {
	ulong_t		vol_size; 	/* no. of Logical blocks in Volume */
	uint_t		lbn_size;	/* no. of bytes in a block */
	uint_t		lbn_shift;	/* shift to convert lbn to bytes */
	uint_t		lbn_secshift;	/* shift to convert lbn to sec */
	uint_t		lbn_maxoffset;	/* max lbn-relative offset and mask */
	uchar_t		file_struct_ver; /* version of directory structure */
	uid_t		vol_uid;	/* uid of volume */
	gid_t		vol_gid;	/* gid of volume */
	uint_t		vol_prot;	/* protection (mode) of volume */
	struct timeval	cre_date;	/* volume creation time */
	struct timeval	mod_date;	/* volume modification time */
	struct	hs_direntry root_dir;	/* dir entry for Root Directory */
	ushort_t	ptbl_len;	/* number of bytes in Path Table */
	uint_t		ptbl_lbn;	/* logical block no of Path Table */
	ushort_t	vol_set_size;	/* number of CD in this vol set */
	ushort_t	vol_set_seq;	/* the sequence number of this CD */
	char		vol_id[32];		/* volume id in PVD */
};

/*
 * The hsnode table is no longer fixed in size but grows
 * and shrinks dynamically. However a cache of nodes is still maintained
 * for efficiency. This cache size (nhsnode) is a tunable which
 * is either specified in /etc/system or calculated as the number
 * that will fit into the number of bytes defined by HS_HSNODESPACE (below).
 */
#define	HS_HASHSIZE	32		/* hsnode hash table size */
#define	HS_HSNODESPACE	16384		/* approx. space used for hsnodes */

/*
 * We usually use the starting extent LBA for the inode numbers of files and
 * directories. As this will not work for zero sized files, we assign a dummy
 * inode number to all zero sized files. We use the number 16 as this is the
 * LBA for the PVD, this number cannot be a valid starting extent LBA for a
 * file. In case that the node number is the HS_DUMMY_INO, we use the LBA and
 * offset of the directory entry of this file (which is what we used before
 * we started to support correct hard links).
 */
#define	HS_DUMMY_INO	16	/* dummy inode number for empty files */

/*
 * Hsfs I/O Scheduling parameters and data structures.
 * Deadline for reads is set at 5000 usec.
 */
#define	HSFS_READ_DEADLINE 5000
#define	HSFS_NORMAL 0x0

/*
 * This structure holds information for a read request that is enqueued
 * for processing by the scheduling function. An AVL tree is used to
 * access the read requests in a sorted manner.
 */
struct hio {
	struct buf	*bp;		/* The buf for this read */
	struct hio	*contig_chain;  /* Next adjacent read if any */
	offset_t	io_lblkno;	/* Starting disk block of io */
	u_offset_t	nblocks;	/* # disk blocks */
	uint64_t	io_timestamp;	/* usec timestamp for deadline */
	ksema_t		*sema;		/* Completion flag */
	avl_node_t	io_offset_node; /* Avl tree requirements */
	avl_node_t	io_deadline_node;
};

/*
 * This structure holds information about all the read requests issued
 * during a read-ahead invocation. This is then enqueued on a task-queue
 * for processing by a background thread that takes this read-ahead to
 * completion and cleans up.
 */
struct hio_info {
	struct buf	*bufs;	/* array of bufs issued for this R/A */
	caddr_t		*vas;	/* The kmem_alloced chunk for the bufs */
	ksema_t		*sema;	/* Semaphores used in the bufs */
	uint_t		bufsused; /* # of bufs actually used */
	uint_t		bufcnt;   /* Tot bufs allocated. */
	struct page	*pp;	  /* The list of I/O locked pages */
	struct hsfs	*fsp; /* The filesystem structure */
};

/*
 * This is per-filesystem structure that stores toplevel data structures for
 * the I/O scheduler.
 */
struct hsfs_queue {
	/*
	 * A dummy hio holding the LBN of the last read processed. Easy
	 * to use in AVL_NEXT for Circular Look behavior.
	 */
	struct hio	*next;

	/*
	 * A pre-allocated buf for issuing coalesced reads. The scheduling
	 * function is mostly single threaded by necessity.
	 */
	struct buf	*nbuf;
	kmutex_t	hsfs_queue_lock; /* Protects the AVL trees */

	/*
	 * Makes most of the scheduling function Single-threaded.
	 */
	kmutex_t	strategy_lock;
	avl_tree_t	read_tree;	 /* Reads ordered by LBN */
	avl_tree_t	deadline_tree;	 /* Reads ordered by timestamp */
	taskq_t		*ra_task;	 /* Read-ahead Q */
	int		max_ra_bytes;	 /* Max read-ahead quantum */

	/* Device Max Transfer size in DEV_BSIZE */
	uint_t		dev_maxtransfer;
};

/*
 * High Sierra filesystem structure.
 * There is one of these for each mounted High Sierra filesystem.
 */
enum hs_vol_type {
	HS_VOL_TYPE_HS = 0, HS_VOL_TYPE_ISO = 1, HS_VOL_TYPE_ISO_V2 = 2,
	HS_VOL_TYPE_JOLIET = 3
};
#define	HSFS_MAGIC 0x03095500
struct hsfs {
	struct hsfs	*hsfs_next;	/* ptr to next entry in linked list */
	long		hsfs_magic;	/* should be HSFS_MAGIC */
	struct vfs	*hsfs_vfs;	/* vfs for this fs */
	struct vnode	*hsfs_rootvp;	/* vnode for root of filesystem */
	struct vnode	*hsfs_devvp;	/* device mounted on */
	enum hs_vol_type hsfs_vol_type; /* see above */
	struct hs_volume hsfs_vol;	/* File Structure Volume Descriptor */
	struct ptable	*hsfs_ptbl;	/* pointer to incore Path Table */
	int		hsfs_ptbl_size;	/* size of incore path table */
	struct ptable_idx *hsfs_ptbl_idx; /* pointer to path table index */
	int		hsfs_ptbl_idx_size;	/* no. of path table index */
	ulong_t		hsfs_ext_impl;	/* ext. information bits */
	ushort_t	hsfs_sua_off;	/* the SUA offset */
	ushort_t	hsfs_namemax;	/* maximum file name length */
	ushort_t	hsfs_namelen;	/* "official" max. file name length */
	ulong_t		hsfs_err_flags;	/* ways in which fs is non-conformant */
	char		*hsfs_fsmnt;	/* name mounted on */
	ulong_t		hsfs_flags;	/* hsfs-specific mount flags */
	krwlock_t	hsfs_hash_lock;	/* protect hash table & hst_nohsnode */
	struct hsnode	*hsfs_hash[HS_HASHSIZE]; /* head of hash lists */
	uint32_t	hsfs_nohsnode;	/* no. of allocated hsnodes */
	kmutex_t	hsfs_free_lock;	/* protects free list */
	struct hsnode	*hsfs_free_f;	/* first entry of free list */
	struct hsnode	*hsfs_free_b;	/* last entry of free list */

	/*
	 * Counters exported through kstats.
	 */
	uint64_t	physical_read_bytes;
	uint64_t	cache_read_pages;
	uint64_t	readahead_bytes;
	uint64_t	coalesced_bytes;
	uint64_t	total_pages_requested;
	kstat_t		*hsfs_kstats;

	struct hsfs_queue *hqueue;	/* I/O Scheduling parameters */
};

/*
 * Error types: bit offsets into hsfs_err_flags.
 * Also serves as index into hsfs_error[], so must be
 * kept in sync with that data structure.
 */
#define	HSFS_ERR_TRAILING_JUNK		0
#define	HSFS_ERR_LOWER_CASE_NM		1
#define	HSFS_ERR_BAD_ROOT_DIR		2
#define	HSFS_ERR_UNSUP_TYPE		3
#define	HSFS_ERR_BAD_FILE_LEN		4
#define	HSFS_ERR_BAD_JOLIET_FILE_LEN	5
#define	HSFS_ERR_TRUNC_JOLIET_FILE_LEN	6
#define	HSFS_ERR_BAD_DIR_ENTRY		7
#define	HSFS_ERR_NEG_SUA_LEN		8
#define	HSFS_ERR_BAD_SUA_LEN		9

#define	HSFS_HAVE_LOWER_CASE(fsp) \
	((fsp)->hsfs_err_flags & (1 << HSFS_ERR_LOWER_CASE_NM))


/*
 * File system parameter macros
 */
#define	hs_blksize(HSFS, HSP, OFF)	/* file system block size */ \
	((HSP)->hs_vn.v_flag & VROOT ? \
	    ((OFF) >= \
		((HSFS)->hsfs_rdirsec & ~((HSFS)->hsfs_spcl - 1))*HS_SECSIZE ?\
		((HSFS)->hsfs_rdirsec & ((HSFS)->hsfs_spcl - 1))*HS_SECSIZE :\
		(HSFS)->hsfs_clsize): \
	    (HSFS)->hsfs_clsize)
#define	hs_blkoff(OFF)		/* offset within block */ \
	((OFF) & (HS_SECSIZE - 1))

/*
 * Conversion macros
 */
#define	VFS_TO_HSFS(VFSP)	((struct hsfs *)(VFSP)->vfs_data)
#define	HSFS_TO_VFS(FSP)	((FSP)->hsfs_vfs)

#define	VTOH(VP)		((struct hsnode *)(VP)->v_data)
#define	HTOV(HP)		(((HP)->hs_vnode))

/*
 * Convert between Logical Block Number and Sector Number.
 */
#define	LBN_TO_SEC(lbn, vfsp)	((lbn)>>((struct hsfs *)((vfsp)->vfs_data))->  \
				hsfs_vol.lbn_secshift)

#define	SEC_TO_LBN(sec, vfsp)	((sec)<<((struct hsfs *)((vfsp)->vfs_data))->  \
				hsfs_vol.lbn_secshift)

#define	LBN_TO_BYTE(lbn, vfsp)	((lbn)<<((struct hsfs *)((vfsp)->vfs_data))->  \
				hsfs_vol.lbn_shift)
#define	BYTE_TO_LBN(boff, vfsp)	((boff)>>((struct hsfs *)((vfsp)->vfs_data))-> \
				hsfs_vol.lbn_shift)

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_NODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * ISO 9660 RRIP extension filesystem specifications
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_RRIP_H
#define	_SYS_FS_HSFS_RRIP_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Mount options specific to HSFS.
 * This is not a good place for them; we should probably have a file
 * named hsfs_mount.h for such stuff.
 */
#define	HSFSMNT_NORRIP		0x1	/* -nrr option found		 */
#define	HSFSMNT_NOTRAILDOT	0x2	/* ignore trailing '.'		 */
#define	HSFSMNT_NOMAPLCASE	0x4	/* do not map filenames to lcase */
#define	HSFSMNT_NOTRAILSPACE	0x8	/* no trailing space in iso 9660 */
#define	HSFSMNT_NOVERSION	0x10	/* no version info in iso 9660 */
#define	HSFSMNT_NOJOLIET	0x20	/* ignore Joliet even if present */
#define	HSFSMNT_JOLIETLONG	0x40	/* do not truncate Joliet filenames */
#define	HSFSMNT_NOVERS2		0x80	/* ignore ISO-9660:1999		 */
#define	HSFSMNT_INODE		0x1000	/* May use ext_lbn as inode #, */
					/* FS is from a recent mkisofs */

/*
 * XXX: The following flag was used in the past to instruct the kernel to
 *	ignore Rock Ridge extensions on a CD. Unfortunately, this was
 *	implemented as part of the generic mount flags, a bad idea.
 *	This flag should not be used anymore. The HSFSMNT_NORRIP
 *	flag should be used in its place. The hsfs_mount code currently
 *	understands this flag, but this functionality should go
 *	away in the future.
 */
#define	MS_NO_RRIP		0x800000  /* if set, don't use Rock Ridge */


#define	MIN(a, b)   ((a) < (b) ? (a) : (b))

/*
 * Make sure we have this first
 */

#define	RRIP_VERSION		1
#define	RRIP_SUF_VERSION	1
#define	RRIP_EXT_VERSION	1

#define	RRIP_BIT	1	/* loc. in extension_name_table in susp.c */

#define	IS_RRIP_IMPLEMENTED(fsp) (IS_IMPL_BIT_SET(fsp, RRIP_BIT) ? 1 : 0)



/*
 * RRIP signature macros
 */
#define	RRIP_CL		"CL"
#define	RRIP_NM		"NM"
#define	RRIP_PL		"PL"
#define	RRIP_PN		"PN"
#define	RRIP_PX		"PX"
#define	RRIP_RE		"RE"
#define	RRIP_RR		"RR"
#define	RRIP_SL		"SL"
#define	RRIP_TF		"TF"

/*
 * RRIP ER extension fields
 */
#define	RRIP_ER_EXT_ID		"RRIP_1991A"

#define	RRIP_ER_EXT_DES		"THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES \
SUPPORT FOR POSIX FILE SYSTEM SEMANTICS."

#define	RRIP_ER_EXT_SRC		"PLEASE CONTACT DISC PUBLISHER FOR \
SPECIFICATION SOURCE.  SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR \
FOR CONTACT INFORMATION."

/*
 * "TF" time macros
 */
#define	RRIP_TF_FLAGS(x)	*(RRIP_tf_flags(x))
#define	RRIP_tf_flags(x)	(&((uchar_t *)(x))[4])

#define	RRIP_TIME_START_BP	5

#define	RRIP_TF_TIME_LENGTH(x)	(IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
					RRIP_TF_LONG_BIT) ? \
					ISO_DATE_LEN : ISO_SHORT_DATE_LEN)

/*
 * Time location bits
 */
#define	RRIP_TF_CREATION_BIT	0x01
#define	RRIP_TF_MODIFY_BIT	0x02
#define	RRIP_TF_ACCESS_BIT	0x04
#define	RRIP_TF_ATTRIBUTES_BIT	0x08
#define	RRIP_TF_BACKUP_BIT	0x10
#define	RRIP_TF_EXPIRATION_BIT	0x20
#define	RRIP_TF_EFFECTIVE_BIT	0x40
#define	RRIP_TF_LONG_BIT	0x80



#define	RRIP_tf_creation(x)	(&((uchar_t *)x)[RRIP_TIME_START_BP])
#define	RRIP_tf_modify(x)	(&((uchar_t *)x)[RRIP_TIME_START_BP + \
			(RRIP_TF_TIME_LENGTH(x) * \
				(IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
				RRIP_TF_CREATION_BIT)))])

#define	RRIP_tf_access(x)	(&((uchar_t *)x)[RRIP_TIME_START_BP + \
			(RRIP_TF_TIME_LENGTH(x) * \
			(IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
					RRIP_TF_CREATION_BIT) + \
			IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
					RRIP_TF_MODIFY_BIT)))])

#define	RRIP_tf_attributes(x)	(&((uchar_t *)x)[RRIP_TIME_START_BP + \
			(RRIP_TF_TIME_LENGTH(x) * \
				(IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
						RRIP_TF_CREATION_BIT) + \
				IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
						RRIP_TF_MODIFY_BIT) + \
				IS_TIME_BIT_SET(RRIP_TF_FLAGS(x), \
						RRIP_TF_ACCESS_BIT)))])



/*
 * Check if TF Bits are set.
 *
 * Note : IS_TIME_BIT_SET(x, y)  must be kept returning 1 and 0.
 * 	see RRIP_tf_*(x) Macros
 */
#define	IS_TIME_BIT_SET(x, y)	(((x) & (y))  ? 1 : 0)
#define	SET_TIME_BIT(x, y)	((x) |= (y))


/*
 * "PX" Posix attibutes
 */
#define	RRIP_mode(x)		(&((uchar_t *)x)[4])
#define	RRIP_MODE(x)		(mode_t)BOTH_INT(RRIP_mode(x))

#define	RRIP_nlink(x)		(&((uchar_t *)x)[12])
#define	RRIP_NLINK(x)		(short)BOTH_INT(RRIP_nlink(x))

#define	RRIP_uid(x)		(&((uchar_t *)x)[20])
#define	RRIP_UID(x)		(uid_t)BOTH_INT(RRIP_uid(x))

#define	RRIP_gid(x)		(&((uchar_t *)x)[28])
#define	RRIP_GID(x)		(gid_t)BOTH_INT(RRIP_gid(x))

#define	RRIP_ino(x)		(&((uchar_t *)x)[36])
#define	RRIP_INO(x)		(uint32_t)BOTH_INT(RRIP_ino(x))

#define	RRIP_PX_OLD_SIZE	36
#define	RRIP_PX_SIZE		44

/*
 * "PN" Posix major/minor numbers
 */

#define	RRIP_major(x)		(&((uchar_t *)x)[4])
#define	RRIP_MAJOR(x)		BOTH_INT(RRIP_major(x))

#define	RRIP_minor(x)		(&((uchar_t *)x)[12])
#define	RRIP_MINOR(x)		BOTH_INT(RRIP_minor(x))


/*
 *  "NM" alternate name and "SL" symbolic link macros...
 */

#define	SYM_LINK_LEN(x)		(strlen(x) + 1)
#define	RRIP_NAME_LEN_BASE	5
#define	RRIP_NAME_LEN(x)	(SUF_LEN(x) - RRIP_NAME_LEN_BASE)

#define	RRIP_NAME_FLAGS(x)	(((uchar_t *)x)[4])

/*
 * These are for the flag bits in the NM and SL and must remain <= 8 bits
 */
#define	RRIP_NAME_CONTINUE	0x01
#define	RRIP_NAME_CURRENT	0x02
#define	RRIP_NAME_PARENT	0x04
#define	RRIP_NAME_ROOT		0x08
#define	RRIP_NAME_VOLROOT	0x10
#define	RRIP_NAME_HOST		0x20


/*
 * These are unique to use in the > 8 bits of sig_args.name_flags
 * They are > 8 so that we can share bits from above.
 * This can grow to 32 bits.
 */
#define	RRIP_NAME_CHANGE	0x40
#define	RRIP_SYM_LINK_COMPLETE	0x80	/* set if sym link already read */
					/* from SUA (no longer than a short) */

/*
 * Bit handling....
 */
#define	SET_NAME_BIT(x, y)	((x) |= (y))
#define	UNSET_NAME_BIT(x, y)	((x) &= ~(y))
#define	IS_NAME_BIT_SET(x, y)	((x) & (y))
#define	NAME_HAS_CHANGED(flag)	\
			(IS_NAME_BIT_SET(flag, RRIP_NAME_CHANGE) ? 1 : 0)

#define	RRIP_name(x)		(&((uchar_t *)x)[5])
#define	RRIP_NAME(x)		RRIP_name(x)

/*
 * This is the maximum filename length that we support
 */
#define	RRIP_FILE_NAMELEN	255


/*
 * SL Symbolic link macros (in addition to common name flag macos
 */
/* these two macros are from the SL SUF pointer */
#define	RRIP_sl_comp(x)		(&((uchar_t *)x)[5])
#define	RRIP_SL_COMP(x)		RRIP_sl_comp(x)
#define	RRIP_SL_FLAGS(x)	(((uchar_t *)x)[4])


/* these macros are from the component pointer within the SL SUF */
#define	RRIP_comp(x)		(&((uchar_t *)x)[2])
#define	RRIP_COMP(x)		RRIP_comp(x)
#define	RRIP_COMP_FLAGS(x)	(((uchar_t *)x)[0])
#define	RRIP_COMP_LEN(x)	(RRIP_COMP_NAME_LEN(x) + 2)
#define	RRIP_COMP_NAME_LEN(x)	(((uchar_t *)x)[1])


/*
 * Directory hierarchy macros
 */

/*
 * Macros for checking relocation bits in flags member of dlist
 * structure defined in iso_impl.h
 */
#define	IS_RELOC_BIT_SET(x, y)	(((x) & (y))  ? 1 : 0)
#define	SET_RELOC_BIT(x, y)	((x) |= (y))

#define	CHILD_LINK		0x01
#define	PARENT_LINK		0x02
#define	RELOCATED_DIR		0x04

#define	RRIP_child_lbn(x)	(&((uchar_t *)x)[4])
#define	RRIP_CHILD_LBN(x)	(uint_t)BOTH_INT(RRIP_child_lbn(x))

#define	RRIP_parent_lbn(x)	(&((uchar_t *)x)[4])
#define	RRIP_PARENT_LBN(x)	(uint_t)BOTH_INT(RRIP_parent_lbn(x))


#ifdef _KERNEL

/*
 * Forward declarations
 */
extern uchar_t *rrip_name(sig_args_t *);
extern uchar_t *rrip_file_attr(sig_args_t *);
extern uchar_t *rrip_dev_nodes(sig_args_t *);
extern uchar_t *rrip_file_time(sig_args_t *);
extern uchar_t *rrip_sym_link(sig_args_t *);
extern uchar_t *rrip_parent_link(sig_args_t *);
extern uchar_t *rrip_child_link(sig_args_t *);
extern uchar_t *rrip_reloc_dir(sig_args_t *);
extern uchar_t *rrip_rock_ridge(sig_args_t *);
extern void hs_check_root_dirent(struct vnode *vp, struct hs_direntry *hdp);
extern int rrip_namecopy(char *from, char *to, char *tmp_name,
				uchar_t *dirp, uint_t last_offset,
				struct hsfs *fsp, struct hs_direntry *hdp);
#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_RRIP_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_SPEC_H
#define	_SYS_FS_HSFS_SPEC_H

/*
 * High Sierra filesystem specification
 */

#include <sys/types.h>
#include <sys/time.h>

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _KERNEL

/* routines required for date parsing */
extern void	hs_parse_dirdate(uchar_t *, struct timeval *);
extern void	hs_parse_longdate(uchar_t *, struct timeval *);

#endif	/* _KERNEL */


/* macros to parse binary integers */
#define	ZERO(x)		(uint_t)(((uchar_t *)(x))[0])
#define	ONE(x)		(uint_t)(((uchar_t *)(x))[1])
#define	TWO(x)		(uint_t)(((uchar_t *)(x))[2])
#define	THREE(x)	(uint_t)(((uchar_t *)(x))[3])

#define	MSB_INT(x) \
	((((((ZERO(x) << 8) | ONE(x)) << 8) | TWO(x)) << 8) | THREE(x))
#define	LSB_INT(x) \
	((((((THREE(x) << 8) | TWO(x)) << 8) | ONE(x)) << 8) | ZERO(x))
#define	MSB_SHORT(x)	((ZERO(x) << 8) | ONE(x))
#define	LSB_SHORT(x)	((ONE(x) << 8) | ZERO(x))

#if defined(__i386) || defined(__amd64)
#define	BOTH_SHORT(x)	(short)*((short *)x)
#define	BOTH_INT(x)	(int)*((int *)x)
#elif defined(__sparc)
/*
 * SPARC machines requires that integer must
 * be in a full word boundary.	CD-ROM data aligns
 * to even word boundary only.	Because of this mismatch,
 * we have to move integer data from CD-ROM to memory one
 * byte at a time.  LSB data starts first. We therefore
 * use this to do byte by byte copying.
 */
#define	BOTH_SHORT(x)	LSB_SHORT(x)
#define	BOTH_INT(x)	LSB_INT(x)
#endif

/*
 * The following describes actual on-disk structures.
 * To achieve portability, all structures are #defines
 * rather than a structure definition.	Macros are provided
 * to get either the data or address of individual fields.
 */

/* Overall High Sierra disk structure */
#define	HS_SECTOR_SIZE	2048		/* bytes per logical sector */
#define	HS_SECTOR_SHIFT	11		/* sector<->byte shift count */
#define	HS_SEC_PER_PAGE	(PAGESIZE/HS_SECTOR_SIZE)	/* sectors per page */
#define	HS_SYSAREA_SEC	0		/* 1st sector of system area */
#define	HS_VOLDESC_SEC	16		/* 1st sector of volume descriptors */
#define	HS_MAXFILEOFF 4294967295U	/* Max file offset (4Gb - 1). */
#define	MAXHSOFFSET (HS_SECTOR_SIZE - 1)
#define	MAXHSMASK   (~MAXHSOFFSET)

/* Standard File Structure Volume Descriptor */

enum hs_voldesc_type {
	VD_BOOT = 0, VD_SFS = 1, VD_CCFS = 2, VD_UNSPEC = 3, VD_EOV = 255
};
#define	HSV_ID_STRING	"CDROM"		/* HSV_std_id field */
#define	HSV_ID_STRLEN	5		/* HSV_std_id field length */
#define	HSV_ID_VER	1		/* HSV_std_ver field */
#define	HSV_FILE_STRUCT_ID_VER	1	/* HSV_file_struct_ver field */
#define	HSV_SYS_ID_STRLEN	32	/* HSV_sys_id field length */
#define	HSV_VOL_ID_STRLEN	32	/* HSV_vol_id field length */
#define	HSV_VOL_SET_ID_STRLEN	128	/* HSV_vol_set_id field length */
#define	HSV_PUB_ID_STRLEN	128	/* HSV_pub_id field length */
#define	HSV_PREP_ID_STRLEN	128	/* HSV_prep_id field length */
#define	HSV_APPL_ID_STRLEN	128	/* HSV_appl_id field length */
#define	HSV_COPYR_ID_STRLEN	32	/* HSV_copyr_id field length */
#define	HSV_ABSTR_ID_STRLEN	32	/* HSV_abstr_id field length */
#define	HSV_DATE_LEN		16	/* HSV date filed length */

/* macros to get the address of each field */
#define	HSV_desc_lbn(x)		(&((uchar_t *)x)[0])
#define	HSV_desc_type(x)	(&((uchar_t *)x)[8])
#define	HSV_std_id(x)		(&((uchar_t *)x)[9])
#define	HSV_std_ver(x)		(&((uchar_t *)x)[14])
#define	HSV_sys_id(x)		(&((uchar_t *)x)[16])
#define	HSV_vol_id(x)		(&((uchar_t *)x)[48])
#define	HSV_vol_size(x)		(&((uchar_t *)x)[88])
#define	HSV_set_size(x)		(&((uchar_t *)x)[128])
#define	HSV_set_seq(x)		(&((uchar_t *)x)[132])
#define	HSV_blk_size(x)		(&((uchar_t *)x)[136])
#define	HSV_ptbl_size(x)	(&((uchar_t *)x)[140])
#define	HSV_ptbl_man_ls(x)	(&((uchar_t *)x)[148])
#define	HSV_ptbl_opt_ls1(x)	(&((uchar_t *)x)[152])
#define	HSV_ptbl_opt_ls2(x)	(&((uchar_t *)x)[156])
#define	HSV_ptbl_opt_ls3(x)	(&((uchar_t *)x)[160])
#define	HSV_ptbl_man_ms(x)	(&((uchar_t *)x)[164])
#define	HSV_ptbl_opt_ms1(x)	(&((uchar_t *)x)[168])
#define	HSV_ptbl_opt_ms2(x)	(&((uchar_t *)x)[172])
#define	HSV_ptbl_opt_ms3(x)	(&((uchar_t *)x)[176])
#define	HSV_root_dir(x)		(&((uchar_t *)x)[180])
#define	HSV_vol_set_id(x)	(&((uchar_t *)x)[214])
#define	HSV_pub_id(x)		(&((uchar_t *)x)[342])
#define	HSV_prep_id(x)		(&((uchar_t *)x)[470])
#define	HSV_appl_id(x)		(&((uchar_t *)x)[598])
#define	HSV_copyr_id(x)		(&((uchar_t *)x)[726])
#define	HSV_abstr_id(x)		(&((uchar_t *)x)[758])
#define	HSV_cre_date(x)		(&((uchar_t *)x)[790])
#define	HSV_mod_date(x)		(&((uchar_t *)x)[806])
#define	HSV_exp_date(x)		(&((uchar_t *)x)[822])
#define	HSV_eff_date(x)		(&((uchar_t *)x)[838])
#define	HSV_file_struct_ver(x)	(&((uchar_t *)x)[854])

/* macros to get the values of each field (strings are returned as ptrs) */
#define	HSV_DESC_LBN(x)		BOTH_INT(HSV_desc_lbn(x))
#define	HSV_DESC_TYPE(x)	((enum hs_voldesc_type)*(HSV_desc_type(x)))
#define	HSV_STD_ID(x)		HSV_std_id(x)
#define	HSV_STD_VER(x)		*(HSV_std_ver(x))
#define	HSV_SYS_ID(x)		HSV_sys_id(x)
#define	HSV_VOL_ID(x)		HSV_vol_id(x)
#define	HSV_VOL_SIZE(x)		BOTH_INT(HSV_vol_size(x))
#define	HSV_SET_SIZE(x)		BOTH_SHORT(HSV_set_size(x))
#define	HSV_SET_SEQ(x)		BOTH_SHORT(HSV_set_seq(x))
#define	HSV_BLK_SIZE(x)		BOTH_SHORT(HSV_blk_size(x))
#define	HSV_PTBL_SIZE(x)	BOTH_INT(HSV_ptbl_size(x))
#define	HSV_PTBL_MAN_LS(x)	LSB_INT(HSV_ptbl_man_ls(x))
#define	HSV_PTBL_OPT_LS1(x)	LSB_INT(HSV_ptbl_opt_ls1(x))
#define	HSV_PTBL_OPT_LS2(x)	LSB_INT(HSV_ptbl_opt_ls2(x))
#define	HSV_PTBL_OPT_LS3(x)	LSB_INT(HSV_ptbl_opt_ls3(x))
#define	HSV_PTBL_MAN_MS(x)	MSB_INT(HSV_ptbl_man_ms(x))
#define	HSV_PTBL_OPT_MS1(x)	MSB_INT(HSV_ptbl_opt_ms1(x))
#define	HSV_PTBL_OPT_MS2(x)	MSB_INT(HSV_ptbl_opt_ms2(x))
#define	HSV_PTBL_OPT_MS3(x)	MSB_INT(HSV_ptbl_opt_ms3(x))
#define	HSV_ROOT_DIR(x)		HSV_root_dir(x)
#define	HSV_VOL_SET_ID(x)	HSV_vol_set_id(x)
#define	HSV_PUB_ID(x)		HSV_pub_id(x)
#define	HSV_PREP_ID(x)		HSV_prep_id(x)
#define	HSV_APPL_ID(x)		HSV_appl_id(x)
#define	HSV_COPYR_ID(x)		HSV_copyr_id(x)
#define	HSV_ABSTR_ID(x)		HSV_abstr_id(x)
#define	HSV_CRE_DATE(x)		HSV_cre_date(x)
#define	HSV_MOD_DATE(x)		HSV_mod_date(x)
#define	HSV_EXP_DATE(x)		HSV_exp_date(x)
#define	HSV_EFF_DATE(x)		HSV_eff_date(x)
#define	HSV_FILE_STRUCT_VER(x)	*(HSV_file_struct_ver(x))

/* Standard File Structure Volume Descriptor date fields */
#define	HSV_DATE_2DIG(x)	((((x)[0] - '0') * 10) + \
					((x)[1] - '0'))
#define	HSV_DATE_4DIG(x)	((((x)[0] - '0') * 1000) + \
					(((x)[1] - '0') * 100) + \
					(((x)[2] - '0') * 10) +	\
						((x)[3] - '0'))
#define	HSV_DATE_YEAR(x)	HSV_DATE_4DIG(&((uchar_t *)x)[0])
#define	HSV_DATE_MONTH(x)	HSV_DATE_2DIG(&((uchar_t *)x)[4])
#define	HSV_DATE_DAY(x)		HSV_DATE_2DIG(&((uchar_t *)x)[6])
#define	HSV_DATE_HOUR(x)	HSV_DATE_2DIG(&((uchar_t *)x)[8])
#define	HSV_DATE_MIN(x)		HSV_DATE_2DIG(&((uchar_t *)x)[10])
#define	HSV_DATE_SEC(x)		HSV_DATE_2DIG(&((uchar_t *)x)[12])
#define	HSV_DATE_HSEC(x)	HSV_DATE_2DIG(&((uchar_t *)x)[14])
#define	HSV_DATE_GMTOFF(x)	(((char *)x)[16])


/* Path table enry */
/* fix size of path table entry */
#define	HPE_FPESIZE		8
/* macros to get the address of each field */
#define	HPE_ext_lbn(x)		(&((uchar_t *)x)[0])
#define	HPE_xar_len(x)		(&((uchar_t *)x)[4])
#define	HPE_name_len(x)		(&((uchar_t *)x)[5])
#define	HPE_parent_no(x)	(&((uchar_t *)x)[6])
#define	HPE_name(x)		(&((uchar_t *)x)[8])

/* macros to get the values of each field */
#if defined(__sparc)
#define	HPE_EXT_LBN(x)		(MSB_INT(HPE_ext_lbn(x)))
#else
#define	HPE_EXT_LBN(x)		*(int *)(HPE_ext_lbn(x))
#endif
#define	HPE_XAR_LEN(x)		*(HPE_xar_len(x))
#define	HPE_NAME_LEN(x)		*(HPE_name_len(x))
#define	HPE_PARENT_NO(x)	*(short *)(HPE_parent_no(x))
#define	HPE_NAME(x)		HPE_name(x)

/* root record */
#define	HDE_ROOT_DIR_REC_SIZE	34	/* size of root directory record */
#define	HDE_FDESIZE		33	/* fixed size for hsfs directory area */
#define	HDE_FUSIZE		12	/* fixed size for unix area */
					/* max size of a name */
#define	HDE_MAX_NAME_LEN	(255 - HDE_FDESIZE - HDE_FUSIZE)

/* Directory Entry (Directory Record) */

#define	UNIX_TO_HDE_DATE(t, p)	parse_unixdate((t), (p))

/* macros to get the address of each field */
#define	HDE_dir_len(x)		(&((uchar_t *)x)[0])
#define	HDE_xar_len(x)		(&((uchar_t *)x)[1])
#define	HDE_ext_lbn(x)		(&((uchar_t *)x)[2])
#define	HDE_ext_size(x)		(&((uchar_t *)x)[10])
#define	HDE_cdate(x)		(&((uchar_t *)x)[18])
#define	HDE_flags(x)		(&((uchar_t *)x)[24])
#define	HDE_reserved(x)		(&((uchar_t *)x)[25])
#define	HDE_intrlv_size(x)	(&((uchar_t *)x)[26])
#define	HDE_intrlv_skip(x)	(&((uchar_t *)x)[27])
#define	HDE_vol_set(x)		(&((uchar_t *)x)[28])
#define	HDE_name_len(x)		(&((uchar_t *)x)[32])
#define	HDE_name(x)		(&((uchar_t *)x)[33])

/* **UNIX extension*** */
#define	HDE_mode(x)		(&((uchar_t *)x)[0])
#define	HDE_uid(x)		(&((uchar_t *)x)[4])
#define	HDE_gid(x)		(&((uchar_t *)x)[8])

/* macros to get the values of each field (strings are returned as ptrs) */
#define	HDE_DIR_LEN(x)		*(HDE_dir_len(x))
#define	HDE_XAR_LEN(x)		*(HDE_xar_len(x))
#define	HDE_EXT_LBN(x)		BOTH_INT(HDE_ext_lbn(x))
#define	HDE_EXT_SIZE(x)		BOTH_INT(HDE_ext_size(x))
#define	HDE_CDATE(x)		HDE_cdate(x)
#define	HDE_FLAGS(x)		*(HDE_flags(x))
#define	HDE_RESERVED(x)		*(HDE_reserved(x))
#define	HDE_INTRLV_SIZE(x)	*(HDE_intrlv_size(x))
#define	HDE_INTRLV_SKIP(x)	*(HDE_intrlv_skip(x))
#define	HDE_VOL_SET(x)		BOTH_SHORT(HDE_vol_set(x))
#define	HDE_NAME_LEN(x)		*(HDE_name_len(x))
#define	HDE_NAME(x)		HDE_name(x)

/* **UNIX EXTENSION**** */
#define	HDE_MODE(x)		*(HDE_mode(x))
#define	HDE_UID(x)		*(HDE_uid(x))
#define	HDE_GID(x)		*(HDE_gid(x))

/* mask bits for HDE_FLAGS */
#define	HDE_EXISTENCE		0x01	/* zero if file exists */
#define	HDE_DIRECTORY		0x02	/* zero if file is not a directory */
#define	HDE_ASSOCIATED		0x04	/* zero if file is not Associated */
#define	HDE_RECORD		0x08	/* zero if no record attributes */
#define	HDE_PROTECTION		0x10	/* zero if no protection attributes */
#define	HDE_UNUSED_FLAGS	0x60
#define	HDE_LAST_EXTENT		0x80	/* zero if last extent in file */
#define	HDE_PROHIBITED	(HDE_DIRECTORY | HDE_RECORD | \
				HDE_LAST_EXTENT | HDE_UNUSED_FLAGS)

/* Directory Record date fields */
#define	HDE_DATE_YEAR(x)	(((uchar_t *)x)[0] + 1900)
#define	HDE_DATE_MONTH(x)	(((uchar_t *)x)[1])
#define	HDE_DATE_DAY(x)		(((uchar_t *)x)[2])
#define	HDE_DATE_HOUR(x)	(((uchar_t *)x)[3])
#define	HDE_DATE_MIN(x)		(((uchar_t *)x)[4])
#define	HDE_DATE_SEC(x)		(((uchar_t *)x)[5])
#define	HDE_DATE_GMTOFF(x)	(((char *)x)[6])


/* tests for Interchange Levels 1 & 2 file types */
#define	HDE_REGULAR_FILE(x)	(((x) & HDE_PROHIBITED) == 0)
#define	HDE_REGULAR_DIR(x)	(((x) & HDE_PROHIBITED) == HDE_DIRECTORY)

#define	HS_DIR_NAMELEN		31	/* max length of a directory name */
#define	HS_FILE_NAMELEN		31	/* max length of a filename */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_SPEC_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * ISO 9660 RRIP extension filesystem specifications
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_HSFS_SUSP_H
#define	_SYS_FS_HSFS_SUSP_H

#ifdef	__cplusplus
extern "C" {
#endif

#define	DEBUGGING_ALL	0
#define	DEBUGGING	0
#define	DPRINTF		if (DEBUGGING) printf
#define	DPRINTF_ALL	if (DEBUGGING_ALL) printf

/*
 * 	return values from SUA parsing
 */
#define	SUA_NULL_POINTER	-1
#define	END_OF_SUA_PARSING	-2
#define	END_OF_SUA		-3
#define	GET_CONTINUATION	-4
#define	SUA_ENOMEM		-5
#define	SUA_EINVAL		-6
#define	RELOC_DIR		-7	/* actually for rrip */

/*
 * For dealing with implemented bits...
 *    These here expect the fsp and a bit as an agument
 */
#define	SET_IMPL_BIT(fsp, y)	((fsp->hsfs_ext_impl)  |= (0x01L) << (y))
#define	UNSET_IMPL_BIT(fsp, y)	((fsp->hsfs_ext_impl)  &= ~((0x01L) << (y)))
#define	IS_IMPL_BIT_SET(fsp, y)	((fsp->hsfs_ext_impl)  & ((0x01L) << (y)))

#define	HAVE_SUSP		0	/* have a SUSP */
#define	HAVE_PROHIBITED		1	/* prohibited file/dir type in fs */

/*
 * For dealing with implemented bits...
 *    These here expect just the fsp->hsfs_ext_impl
 */
#define	SET_SUSP_BIT(fsp)	(SET_IMPL_BIT((fsp), HAVE_SUSP))
#define	UNSET_SUSP_BIT(fsp)	(UNSET_IMPL_BIT((fsp), HAVE_SUSP))
#define	IS_SUSP_IMPLEMENTED(fsp) (IS_IMPL_BIT_SET(fsp, 0) ? 1 : 0)

#define	SUSP_VERSION	1

/*
 * SUSP signagure definitions
 */
#define	SUSP_SP		"SP"
#define	SUSP_CE		"CE"
#define	SUSP_PD		"PD"
#define	SUSP_ER		"ER"
#define	SUSP_ST		"ST"

/*
 * 	Generic System Use Field (SUF) Macros and declarations
 */

#define	SUF_SIG_LEN	2			/* length of signatures */
#define	SUF_MIN_LEN	4			/* minimum length of a */
						/* 	signature field */

#define	SUF_LEN(x)	*(SUF_len(x))		/* SUF length */
#define	SUF_len(x)	(&((uchar_t *)x)[2])	/* SUF length */

#define	SUF_VER(x)	*(SUF_ver(x))		/* SUF version */
#define	SUF_ver(x)	(&((uchar_t *)x)[3])	/* SUF version */

/*
 * Extension Reference Macros
 */

#define	ER_ID_LEN(x)	*(ER_id_len(x))	/* Extension ref id length */
#define	ER_id_len(x)	(&((uchar_t *)x)[4])	/* Extension ref id length */


#define	ER_DES_LEN(x)	*(ER_des_len(x))	/* Extension ref description */
						/* 	length */
#define	ER_des_len(x)	(&((uchar_t *)x)[5])	/* Extension ref description */
						/* 	length */

#define	ER_SRC_LEN(x)	*(ER_src_len(x))	/* Extension ref source */
						/* 	description length */

#define	ER_src_len(x)	(&((uchar_t *)x)[6])	/* Extension ref source */
						/* description length */


#define	ER_EXT_VER(x)	*(ER_ext_ver(x))	/* Extension ref description */
						/*  length */
#define	ER_ext_ver(x)	(&((uchar_t *)x)[7])	/* Extension ref description */
						/* length */

#define	ER_EXT_ID_LOC	8			/* location where the ER id */
						/* string begins */

#define	ER_ext_id(x)	(&((uchar_t *)x)[ER_EXT_ID_LOC])
						/* extension id string */

#define	ER_ext_des(x)	(&((uchar_t *)x)[ER_EXT_ID_LOC + ER_ID_LEN(x)])
						/* ext. description string */

#define	ER_ext_src(x)	(&((uchar_t *)x)[ER_EXT_ID_LOC + ER_ID_LEN(x) + \
					ER_DES_LEN(x)])
						/* ext. source string */


/*
 * Continuation Area Macros
 */
#define	CE_BLK_LOC(x)	BOTH_INT(CE_blk_loc(x))	/* cont. starting block */
#define	CE_blk_loc(x)	(&((uchar_t *)x)[4])	/* cont. starting block */

#define	CE_OFFSET(x)	BOTH_INT(CE_offset(x))	/* cont. offset */
#define	CE_offset(x)	(&((uchar_t *)x)[12])	/* cont. offset */

#define	CE_CONT_LEN(x)	BOTH_INT(CE_cont_len(x))	/* continuation len */
#define	CE_cont_len(x)	(&((uchar_t *)x)[20])	/* continuation len */


/*
 * Sharing Protocol (SP) Macros
 */
#define	SP_CHK_BYTE_1(x)	*(SP_chk_byte_1(x))	/* check bytes */
#define	SP_chk_byte_1(x)	(&((uchar_t *)x)[4])	/* check bytes */

#define	SP_CHK_BYTE_2(x)	*(SP_chk_byte_2(x))	/* check bytes */
#define	SP_chk_byte_2(x)	(&((uchar_t *)x)[5])	/* check bytes */

#define	SUSP_CHECK_BYTE_1	(uchar_t)0xBE		/* check for 0xBE */
#define	SUSP_CHECK_BYTE_2	(uchar_t)0xEF		/* check for 0xEF */

#define	CHECK_BYTES_OK(x)	((SP_CHK_BYTE_1(x) == SUSP_CHECK_BYTE_1) && \
				(SP_CHK_BYTE_2(x) == SUSP_CHECK_BYTE_2))

#define	SP_SUA_OFFSET(x)	*(SP_sua_offset(x))	/* SUA bytes to skip */
#define	SP_sua_offset(x)	(&((uchar_t *)x)[6])	/* SUA bytes to skip */



/*
 * Forward declarations
 */

#ifdef _KERNEL

extern uchar_t *share_protocol();
extern uchar_t *share_ext_ref();
extern uchar_t *share_continue();
extern uchar_t *share_padding();
extern uchar_t *share_stop();

#endif

/*
 * Extension signature structure, to corrolate the handler functions
 * with the signatures
 */
struct extension_signature_struct {
	char	*ext_signature;		/* extension signature */
	uchar_t	*(*sig_handler)();	/* extension handler function */
};

typedef	struct extension_signature_struct	ext_signature_t;


/*
 * Extension name structure, to corrolate the extensions with their own
 * 	signature tables.
 */
struct extension_name_struct {
	char  		*extension_name;	/* ER field identifier */
	ushort_t	ext_version;		/* version # of extensions */
	ext_signature_t	*signature_table;	/* pointer to signature */
						/*   table for appropriate */
						/*   extension */
};

typedef	struct extension_name_struct extension_name_t;

/*
 * Extern declaration for all supported extensions
 */
struct	cont_info_struct	{
	uint_t	cont_lbn;	/* location  of cont */
	uint_t	cont_offset;	/* offset into cont */
	uint_t	cont_len;	/* len of cont */
};

typedef struct cont_info_struct	cont_info_t;

/*
 * Structure for passing arguments to sig_handler()'s.  Since there are
 * so many sig_handler()'s, it would be slower to pass multiple
 * arguments to all of them. It would also ease maintainance
 */
struct sig_args_struct {
	uchar_t			*dirp;		/* pointer to ISO dir entry */
	uchar_t			*name_p;	/* dir entry name */
	int			*name_len_p;	/* dir entry name length */
	short			flags;		/* misc flags */
	ulong_t			name_flags;		/* misc flags */
	uchar_t			*SUF_ptr;	/* pointer to current SUF */
	struct hs_direntry	*hdp;		/* directory entry  */
	struct hsfs		*fsp;		/* file system  */
	cont_info_t		*cont_info_p;	/* continuation area */
};

typedef struct sig_args_struct	sig_args_t;


/*
 * Extern declaration for all supported extensions
 */

#ifdef _KERNEL

extern ext_signature_t		rrip_signature_table[];
extern ext_signature_t		susp_signature_table[];
extern extension_name_t		extension_name_table[];

extern ext_signature_t		*susp_sp;

extern int parse_sua(uchar_t *, int *name_len_p, int *, uchar_t *, uint_t,
	struct hs_direntry *,	struct hsfs *,	uchar_t	*, int search_num);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_HSFS_SUSP_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Loopback mount info - one per mount
 */

#ifndef _SYS_FS_LOFS_INFO_H
#define	_SYS_FS_LOFS_INFO_H

#ifdef _KERNEL
#include <sys/vfs_opreg.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif

struct lnode;

struct lobucket {
	kmutex_t	lh_lock;	/* lock protecting bucket contents */
	struct lnode	*lh_chain;	/* vnode chain for this bucket */
	uint_t		lh_count;	/* Number of vnodes in chain */
	/* Pad up to 64-byte boundary to avoid false sharing */
#ifdef _LP64
	char		_pad[44];
#else
	char		_pad[48];
#endif
};

struct lo_retired_ht {
	struct lo_retired_ht	*lrh_next;
	struct lobucket		*lrh_table;
	uint_t			lrh_size;
};

struct loinfo {
	struct vfs	*li_realvfs;	/* real vfs of mount */
	struct vfs	*li_mountvfs;	/* loopback vfs */
	struct vnode	*li_rootvp;	/* root vnode of this vfs */
	int		 li_mflag;	/* mount flags to inherit */
	int		 li_dflag;	/* mount flags to not inherit */
	uint_t		 li_refct;	/* # outstanding vnodes */
	volatile uint_t	 li_htsize;	/* # buckets in hashtable */
	struct lobucket *volatile li_hashtable; /* table of per-mount vnodes */
	struct lfsnode	*li_lfs;	/* list of other vfss */
	kmutex_t	 li_lfslock;	/* lock protecting li_lfs */
	kmutex_t	 li_htlock;	/* protect hashtable, htsize, retired */
	struct lo_retired_ht *li_retired; /* list of retired hashtables */
	int		 li_flag;	/* filesystem behavior flags */
};

/* inheritable mount flags - propagated from real vfs to loopback */
#define	INHERIT_VFS_FLAG	\
	(VFS_RDONLY|VFS_NOSETUID|VFS_NODEVICES|VFS_XATTR|VFS_NBMAND|VFS_NOEXEC)

/*
 * "nosub" is used to provide NFS server-like semantics for lo_lookup(): never
 * traverse mount points for sub-mounts.  The lookup will instead look under
 * the mount point.
 */
#define	MNTOPT_LOFS_NOSUB	"nosub"
#define	MNTOPT_LOFS_SUB		"sub"

/*
 * Flag values (for li_flag)
 */
#define	LO_NOSUB	0x02	/* don't traverse sub-mounts */

/*
 * lfsnodes are allocated as new real vfs's are encountered
 * when looking up things in a loopback name space
 * It contains a new vfs which is paired with the real vfs
 * so that vfs ops (fsstat) can get to the correct real vfs
 * given just a loopback vfs
 */
struct lfsnode {
	struct lfsnode	*lfs_next;	/* next in loinfo list */
	struct vfs	*lfs_realvfs;	/* real vfs */
	struct vnode    *lfs_realrootvp; /* real root vp */
	struct vfs	 lfs_vfs;	/* new loopback vfs */
};

#define	vtoli(VFSP)	((struct loinfo *)((VFSP)->vfs_data))

#ifdef _KERNEL
extern struct vfs *lo_realvfs(struct vfs *, struct vnode **);
extern void lofs_subrinit(void);
extern void lofs_subrfini(void);

extern void lsetup(struct loinfo *, uint_t);
extern void ldestroy(struct loinfo *);

extern const struct fs_operation_def lo_vnodeops_template[];

extern struct vnodeops *lo_vnodeops;
extern vfsops_t *lo_vfsops;
extern struct mod_ops mod_fsops;

#endif /* _KERNEL */


#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_LOFS_INFO_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Loop-back file information structure.
 */

#ifndef _SYS_FS_LOFS_NODE_H
#define	_SYS_FS_LOFS_NODE_H

#include <sys/fs/lofs_info.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * The lnode is the "inode" for loop-back files.  It contains
 * all the information necessary to handle loop-back file on the
 * client side.
 */
typedef struct lnode {
	struct lnode	*lo_next;	/* link for hash chain */
	struct vnode	*lo_vp;		/* pointer to real vnode */
	uint_t		lo_looping; 	/* looping flags (see below) */
	struct vnode	*lo_vnode;	/* place holder vnode for file */
} lnode_t;

/*
 * Flags used when looping has been detected.
 */
#define	LO_LOOPING	0x01	/* Looping detected */
#define	LO_AUTOLOOP	0x02	/* Autonode looping detected */

/*
 * Flag passed to makelonode().
 */
#define	LOF_FORCE	0x1	/* Force creation of new lnode */

/*
 * Convert between vnode and lnode
 */
#define	ltov(lp)	(((lp)->lo_vnode))
#define	vtol(vp)	((struct lnode *)((vp)->v_data))
#define	realvp(vp)	(vtol(vp)->lo_vp)

#ifdef _KERNEL
extern vnode_t *makelonode(vnode_t *, struct loinfo *, int);
extern void freelonode(lnode_t *);
#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_LOFS_NODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _SYS_MNTFS_MNTDATA_H
#define	_SYS_MNTFS_MNTDATA_H

#include <sys/vnode.h>
#include <sys/poll.h>
#include <sys/mnttab.h>
#include <sys/zone.h>

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct mntelem {
	/* Metadata. */
	struct mntelem 	*mnte_next;
	struct mntelem 	*mnte_prev;
	timespec_t	mnte_birth;
	timespec_t	mnte_death;
	timespec_t	mnte_vfs_ctime;
	int		mnte_refcnt;
	/* Payload. */
	int		mnte_hidden;
	char		*mnte_text;
	size_t		mnte_text_size;
	struct extmnttab mnte_tab;
} mntelem_t;

typedef struct mntsnap {
	timespec_t mnts_time;		/* Time of this snapshot. */
	timespec_t mnts_last_mtime;	/* mnttab modification time. */
	mntelem_t *mnts_first;		/* First element in this snapshot. */
	mntelem_t *mnts_next;		/* Next element to use. */
	int mnts_flags;			/* flags; see below. */
	size_t mnts_nmnts;		/* # of elements in this snapshot. */
	size_t mnts_text_size;		/* Text size for this snapshot. */
	size_t mnts_foffset;		/* File offset of last read(). */
	size_t mnts_ieoffset;		/* Offset of last read() in element. */
} mntsnap_t;

typedef struct mntnode {
	vnode_t *mnt_vnode;	/* vnode for this mntnode */
	vnode_t *mnt_mountvp;	/* vnode mounted on */
	krwlock_t mnt_contents;	/* protects mnt_flags, mnt_read & mnt_ioctl */
	uint_t mnt_flags;	/* flags; see below */
	mntsnap_t mnt_read;	/* data for read() */
	mntsnap_t mnt_ioctl;	/* data for ioctl() */
} mntnode_t;

/*
 * Conversion macros.
 */
#define	VTOM(vp)	((struct mntnode *)(vp)->v_data)
#define	MTOV(pnp)	((pnp)->mnt_vnode)
#define	MTOD(pnp)	((struct mntdata *)MTOV(pnp)->v_vfsp->vfs_data)

#define	MNTFS_ELEM_IS_DEAD(x)	((x)->mnte_death.tv_sec || \
				(x)->mnte_death.tv_nsec)
#define	MNTFS_ELEM_IS_ALIVE(x)	!MNTFS_ELEM_IS_DEAD(x)

#if defined(_KERNEL)

typedef struct mntdata {
	zone_ref_t mnt_zone_ref;	/* zone for mount point */
	uint_t mnt_nopen;		/* count of vnodes open */
	size_t mnt_size;		/* size of last normal snapshot */
	size_t mnt_hidden_size;		/* size of last hidden snapshot */
	timespec_t mnt_mtime;		/* mtime at last normal snapshot */
	timespec_t mnt_hidden_mtime;	/* mtime at last hidden snapshot */
	struct mntnode mnt_node;	/* embedded mntnode */
} mntdata_t;

/*
 * Value for a mntsnap_t's mnts_flags.
 */
#define	MNTS_SHOWHIDDEN	0x1	/* This snapshot contains hidden mounts. */
#define	MNTS_REWIND	0x2	/* This snapshot must be refreshed. */
/*
 * Values for a mntnode_t's mnt_flags.
 */
#define	MNT_SHOWHIDDEN	0x1	/* Include MS_NOMNTTAB mounts in snapshots. */

extern	struct vnodeops	*mntvnodeops;
extern	void mntfs_getmntopts(struct vfs *, char **, size_t *);

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_MNTFS_MNTDATA_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
 */

#ifndef	_SYS_FS_NAMENODE_H
#define	_SYS_FS_NAMENODE_H

#if defined(_KERNEL)
#include <sys/vnode.h>
#include <sys/vfs_opreg.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * This structure is used to pass a file descriptor from user
 * level to the kernel. It is first used by fattach() and then
 * be NAMEFS.
 */
struct namefd {
	int fd;
};

#if defined(_KERNEL)
/*
 * Each NAMEFS object is identified by a struct namenode/vnode pair.
 */
struct namenode {
	struct vnode    *nm_vnode;	/* represents mounted file desc. */
	int		nm_flag;	/* flags defined below */
	struct vattr    nm_vattr;	/* attributes of mounted file desc. */
	struct vnode	*nm_filevp;	/* file desc. prior to mounting */
	struct file	*nm_filep;	/* file pointer of nm_filevp */
	struct vnode	*nm_mountpt;	/* mount point prior to mounting */
	struct namenode *nm_nextp;	/* next link in the linked list */
	kmutex_t	nm_lock;	/* protects nm_vattr */
};

/*
 * Valid flags for namenodes.
 */
#define	NMNMNT		0x01	/* namenode not mounted */

/*
 * Macros to convert a vnode to a namenode, and vice versa.
 */
#define	VTONM(vp) ((struct namenode *)((vp)->v_data))
#define	NMTOV(nm) ((nm)->nm_vnode)

#define	NM_FILEVP_HASH_SIZE	64
#define	NM_FILEVP_HASH_MASK	(NM_FILEVP_HASH_SIZE - 1)
#define	NM_FILEVP_HASH_SHIFT	7
#define	NM_FILEVP_HASH(vp)	(&nm_filevp_hash[(((uintptr_t)vp) >> \
	NM_FILEVP_HASH_SHIFT) & NM_FILEVP_HASH_MASK])

extern struct namenode *nm_filevp_hash[NM_FILEVP_HASH_SIZE];
extern struct vfs namevfs;

extern int nameinit(int, char *);
extern int nm_unmountall(struct vnode *, struct cred *);
extern void nameinsert(struct namenode *);
extern void nameremove(struct namenode *);
extern struct namenode *namefind(struct vnode *, struct vnode *);
extern uint64_t namenodeno_alloc(void);
extern void namenodeno_free(uint64_t);
extern struct vnodeops *nm_vnodeops;
extern const struct fs_operation_def nm_vnodeops_template[];
extern kmutex_t ntable_lock;

typedef int nm_walk_mounts_f(const struct namenode *, cred_t *, void *);
extern int nm_walk_mounts(const vnode_t *, nm_walk_mounts_f *, cred_t *,
    void *);

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_NAMENODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_PC_DIR_H
#define	_SYS_FS_PC_DIR_H

#include <sys/dirent.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	PCFNAMESIZE	8
#define	PCFEXTSIZE	3
#define	PCMAXNAMLEN	255
#define	PCMAXNAM_UTF16	(256 * sizeof (uint16_t))	/* for UTF-16 */
#define	PCLFNCHUNKSIZE	13

struct pctime {
	ushort_t pct_time;		/* hh:mm:ss (little endian) */
	ushort_t pct_date;		/* yy:mm:dd (little endian) */
};

/*
 * Shifts and masks for time and date fields, in host byte order.
 */
#define	SECSHIFT	0
#define	SECMASK		0x1F
#define	MINSHIFT	5
#define	MINMASK		0x3F
#define	HOURSHIFT	11
#define	HOURMASK	0x1F

#define	DAYSHIFT	0
#define	DAYMASK		0x1F
#define	MONSHIFT	5
#define	MONMASK		0x0F
#define	YEARSHIFT	9
#define	YEARMASK	0x7F

struct pcdir {
	char pcd_filename[PCFNAMESIZE] __nonstring; /* file name */
	char pcd_ext[PCFEXTSIZE] __nonstring; /* file extension */
	uchar_t	pcd_attr;		/* file attributes */
	uchar_t	pcd_ntattr;		/* reserved for NT attributes */
	uchar_t	pcd_crtime_msec;	/* milliseconds after the minute */
	struct pctime pcd_crtime;	/* creation time/date */
	ushort_t pcd_ladate;		/* last-access date */
	union {
		uint16_t pcd_eattr;	/* OS/2 extended attribute */
		pc_cluster16_t pcd_scluster_hi;
	} un;
	struct pctime pcd_mtime;	/* last modified time/date */
	pc_cluster16_t pcd_scluster_lo;	/* starting cluster (little endian) */
	uint_t	pcd_size;		/* file size (little endian) */
};

#ifdef	__cplusplus
}
#endif

#include <sys/fs/pc_node.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Long filename support (introduced by Windows 95) is an interesting
 * exercise in compatibility. Basically, it is now no longer the case
 * that an entry in a directory (as described by the 'pcdir' structure above)
 * contains the entire name of a file. Now, a directory entry can consist of
 * a long filename component (a series of 'pcdir'-like structures) followed
 * by a short filename (the old form). Each long filename component is
 * identified by having it's Read-Only, Hidden, System, and Volume Label
 * attributes set.  Each can store 13 Unicode characters (16-bits, of
 * which we only look at the lower 8 for now), broken into (gak) three
 * sections of the entry (since that's the way the available bits fall out).
 * In addition, each long filename entry has a sequence number (starting
 * from 1). The first entry has bit 7 (0x40) set in the sequence number, and
 * has the maximum value in the sequence. This may seem a bit backwards, and
 * it gets worse: the first entry stores the last component of
 * the name. So the directory entry for a file named
 * "This is a very long filename indeed" might look like this:
 *
 * Offset  Sequence      Component         Attributes    Cluster    Size
 *    0      0x43       "me indeed"          RSHV           0         0
 *   32      0x02       "y long filena"      RSHV           0         0
 *   64      0x01       "This is a ver"      RSHV           0         0
 *   96      ----       "THISIS~1.TXT"       <whatever>  2122       110
 *
 * The last entry is for the short filename, which stores actual information
 * about the file (like type, permissions, cluster, and size). The short name
 * is also used by non-long-filename aware applications (like Windows 3.X and
 * DOS). This name is generated by Windows 95 (and now Solaris) from the
 * long name, and must (of course) be unique within the directory.
 * Solaris continues to this entry to actually identify the file and its
 * attributes (filenames only really matter when names are used, like at
 * lookup/readdir/remove/create/rename time - for general access to the file
 * they aren't used).
 *
 * Long filenames can also be broken by applications that don't
 * understand them (for example, a Solaris 2.5.1 user could rename
 * "THISIS~1.TXT" to "test.exe"). This can be detected because each long
 * filename component has a checksum which is based on the short filename.
 * After reading the long filename entry, if the checksum doesn't match the
 * short name that follows, we simply ignore it and use the short name.
 *
 * One subtle thing - though long file names are case-sensitive,
 * searches for them are not.
 *
 * Another _very_ subtle thing. The number of characters in the
 * last long filename chunk (the first entry, with the 0x40 bit set) is
 * either all the characters (if there is no null, '\0'), or all the
 * characters up to the null. _However_, if the remaining characters are
 * null, Norton Disk Doctor and Microsoft ScanDisk will claim
 * that the filename entry is damaged. The remaining bytes must actually
 * contain 0xff (discovered with Disk Doctor).
 *
 * Some information about long filename support can be found in the
 * book "Inside Windows 95" by Adrian King.
 */

/*
 * The number of bytes in each section of the name in a long filename
 * entry. This is _bytes_, not characters: each character is actually
 * 16 bits.
 */
#define	PCLF_FIRSTNAMESIZE	10
#define	PCLF_SECONDNAMESIZE	12
#define	PCLF_THIRDNAMESIZE	4

/*
 * A long filename entry. It must match the 'pcdir' structure in size,
 * and pcdl_attr must overlap pcd_attr.
 */
struct pcdir_lfn {
	uchar_t pcdl_ordinal;	/* lfn order. First is 01, next 02, */
				/* last has bit 7 (0x40) set */
	uchar_t pcdl_firstfilename[PCLF_FIRSTNAMESIZE];
	uchar_t pcdl_attr;
	uchar_t pcdl_type;	/* type - always contains 0 for an LFN entry */
	uchar_t pcdl_checksum;	/* checksum to validate the LFN entry - */
				/* based on the short name */
	uchar_t pcdl_secondfilename[PCLF_SECONDNAMESIZE];
	pc_cluster16_t pcd_scluster;	/* (not used, always 0) */
	uchar_t pcdl_thirdfilename[PCLF_THIRDNAMESIZE];
};

/*
 * FAT LFN entries are consecutively numbered downwards, and the last
 * entry of a LFN chain will have the 0x40 'termination' marker logically
 * or'ed in. The entry immediately preceeding the short name has number 1,
 * consecutively increasing. Since the filename length limit on FAT is
 * 255 unicode characters and every LFN entry contributes 13 characters,
 * the maximum sequence number is 255/13 + 1 == 20.
 */
#define	PCDL_IS_LAST_LFN(x) ((x->pcdl_ordinal) & 0x40)
#define	PCDL_LFN_BITS (PCA_RDONLY | PCA_HIDDEN | PCA_SYSTEM | PCA_LABEL)
#define	PCDL_LFN_MASK (PCDL_LFN_BITS | PCA_DIR | PCA_ARCH)
#define	PCDL_LFN_VALID_ORD(x)						\
	(((((struct pcdir_lfn *)(x))->pcdl_ordinal & ~0x40) > 0) &&	\
	((((struct pcdir_lfn *)(x))->pcdl_ordinal & ~0x40) <= 20))
#define	PCDL_IS_LFN(x)							\
	(enable_long_filenames &&					\
	(((x)->pcd_attr & PCDL_LFN_MASK) == PCDL_LFN_BITS) &&		\
	PCDL_LFN_VALID_ORD((x)))

/*
 * The first char of the file name has special meaning as follows:
 */
#define	PCD_UNUSED	((char)0x00)	/* entry has never been used */
#define	PCD_ERASED	((char)0xE5)	/* entry was erased */

/*
 * File attributes.
 */
#define	PCA_RDONLY	0x01	/* file is read only */
#define	PCA_HIDDEN	0x02	/* file is hidden */
#define	PCA_SYSTEM	0x04	/* system file */
#define	PCA_LABEL	0x08	/* entry contains the volume label */
#define	PCA_DIR		0x10	/* subdirectory */
#define	PCA_ARCH	0x20	/* file has been modified since last backup */

/*
 * Avoid hidden files unless the private variable is set.
 * Always avoid the label.
 */
#define	PCA_IS_HIDDEN(fsp, attr) \
	((((attr) & PCA_LABEL) == PCA_LABEL) || \
	((((fsp)->pcfs_flags & PCFS_HIDDEN) == 0) && \
	    ((attr) & (PCA_HIDDEN | PCA_SYSTEM))))

#define	PC_NAME_IS_DOT(namep) \
	(((namep)[0] == '.') && ((namep)[1] == '\0'))
#define	PC_NAME_IS_DOTDOT(namep) \
	(((namep)[0] == '.') && ((namep)[1] == '.') && ((namep)[2] == '\0'))
#define	PC_SHORTNAME_IS_DOT(namep) \
	(((namep)[0] == '.') && ((namep)[1] == ' '))
#define	PC_SHORTNAME_IS_DOTDOT(namep) \
	(((namep)[0] == '.') && ((namep)[1] == '.') && ((namep)[2] == ' '))
/*
 * slot structure is used by the directory search routine to return
 * the results of the search.  If the search is successful sl_blkno and
 * sl_offset reflect the disk address of the entry and sl_ep points to
 * the actual entry data in buffer sl_bp. sl_flags is set to whether the
 * entry is dot or dotdot. If the search is unsuccessful sl_blkno and
 * sl_offset points to an empty directory slot if there are any. Otherwise
 * it is set to -1.
 */
struct pcslot {
	enum {SL_NONE, SL_FOUND, SL_EXTEND} sl_status;	/* slot status */
	daddr_t		sl_blkno;	/* disk block number which has entry */
	int		sl_offset;	/* offset of entry within block */
	struct buf	*sl_bp;		/* buffer containing entry data */
	struct pcdir	*sl_ep;		/* pointer to entry data */
	int		sl_flags;	/* flags (see below) */
};
#define	SL_DOT		1	/* entry point to self */
#define	SL_DOTDOT	2	/* entry points to parent */

/*
 * A pcfs directory entry. Directory entries are actually variable
 * length, but this is the maximum size.
 *
 * This _must_ match a dirent64 structure in format.
 * d_name is 512 bytes long to accomodate 256 UTF-16 characters.
 */
struct pc_dirent {
	ino64_t		d_ino;		/* "inode number" of entry */
	off64_t		d_off;		/* offset of disk directory entry */
	unsigned short	d_reclen;	/* length of this record */
	char		d_name[PCMAXNAM_UTF16];
};

/*
 * Check FAT 8.3 filename characters for validity.
 * Lacking a kernel iconv, codepage support for short filenames
 * is not provided.
 * Short names must be uppercase ASCII (no support for MSDOS
 * codepages right now, sorry) and may not contain any of
 * *+=|\[];:",<>.?/ which are explicitly forbidden by the
 * FAT specifications.
 */
#define	pc_invalchar(c)						\
	(((c) >= 'a' && (c) <= 'z') ||				\
	(c) == '"' || (c) == '*' || (c) == '+' || (c) == ',' || \
	(c) == '.' || (c) == '/' || (c) == ':' || (c) == ';' || \
	(c) == '<' || (c) == '=' || (c) == '>' || (c) == '?' || \
	(c) == '[' || (c) == '|' || (c) == ']' || (c) == '\\')

#define	pc_validchar(c)	(((c) >= ' ' && !((c) & ~0177)) && !pc_invalchar(c))


#ifdef _KERNEL

/*
 * macros for converting ASCII to/from upper or lower case.
 * users may give and get names in lower case, but they are stored on the
 * disk in upper case to be PCDOS compatible.
 * These would better come from some shared source in <sys/...> but
 * there is no such place yet.
 */
#define	toupper(C)	(((C) >= 'a' && (C) <= 'z') ? (C) - 'a' + 'A' : (C))
#define	tolower(C)	(((C) >= 'A' && (C) <= 'Z') ? (C) - 'A' + 'a' : (C))

extern int pc_tvtopct(timestruc_t *, struct pctime *);	/* timeval to pctime */
extern void pc_pcttotv(struct pctime *, int64_t *);	/* pctime to timeval */
extern int pc_valid_lfn_char(char);		/* valid long filename ch */

extern int pc_read_long_fn(struct vnode *, struct uio *,
    struct pc_dirent *, struct pcdir **, offset_t *, struct buf **);
extern int pc_read_short_fn(struct vnode *, struct uio *,
    struct pc_dirent *, struct pcdir **, offset_t *, struct buf **);
extern int pc_match_long_fn(struct pcnode *, char *, struct pcdir **,
    struct pcslot *, offset_t *);
extern int pc_match_short_fn(struct pcnode *, char *,
    struct pcdir **, struct pcslot *, offset_t *);
extern uchar_t pc_checksum_long_fn(char *, char *);
extern void set_long_fn_chunk(struct pcdir_lfn *, char *, int);
extern int pc_valid_long_fn(char *, int);
extern int pc_extract_long_fn(struct pcnode *, char *,
    struct pcdir **, offset_t *offset, struct buf **);
extern int pc_fname_ext_to_name(char *, char *, char *, int);

extern pc_cluster32_t pc_getstartcluster(struct pcfs *, struct pcdir *);
extern void pc_setstartcluster(struct pcfs *, struct pcdir *, pc_cluster32_t);

/*
 * Private tunables
 */

/*
 * Use long filenames (Windows 95). Disabling this causes pcfs
 * to not recognize long filenames at all, which may cause it to
 * break associations between the short and long names. This is likely
 * to leave unused long filename entries  in directories (which may make
 * apparently empty directories unremovable), and would require a fsck_pcfs
 * to find and fix (or a Windows utility like Norton Disk Doctor or
 * Microsoft ScanDisk).
 */
extern int enable_long_filenames;	/* default: on */

#endif

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_PC_DIR_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_PC_FS_H
#define	_SYS_FS_PC_FS_H

#include <sys/thread.h>
#include <sys/ksynch.h>
#include <sys/sysmacros.h>
#include <sys/byteorder.h>

#ifdef	__cplusplus
extern "C" {
#endif

typedef	uint16_t	pc_cluster16_t;
typedef	uint32_t	pc_cluster32_t;

/*
 * PC (MSDOS) compatible virtual file system.
 *
 * A main goal of the implementation was to maintain statelessness
 * except while files are open. Thus mounting and unmounting merely
 * declared the file system name. The user may change disks at almost
 * any time without concern (just like the PC). It is assumed that when
 * files are open for writing the disk access light will be on, as a
 * warning not to change disks. The implementation must, however, detect
 * disk change and recover gracefully. It does this by comparing the
 * in core entry for a directory to the on disk entry whenever a directory
 * is searched. If a discrepancy is found active directories become root and
 * active files are marked invalid.
 *
 * There are only two type of nodes on the PC file system; files and
 * directories. These are represented by two separate vnode op vectors,
 * and they are kept in two separate tables. Files are known by the
 * disk block number and block (cluster) offset of the files directory
 * entry. Directories are known by the starting cluster number.
 *
 * The file system is locked for during each user operation. This is
 * done to simplify disk verification error conditions.
 *
 * Notes on FAT32 support
 * ----------------------
 * The basic difference between FAT32 and FAT16 is that cluster numbers are now
 * 32-bit instead of 16-bit. The FAT is thus an array of 32-bit cluster numbers,
 * and because of this the cluster size can be much smaller on a large disk
 * (4k, say, on a 1 Gig drive instead of 16k). Unfortunately, the FAT is not
 * the only place cluster numbers are stored - the starting cluster is stored
 * in the directory entry for a file, and of course it's only 16-bit. Luckily,
 * there's a 16-bit OS/2 Extended Attribute field that is now used to store the
 * upper 16-bits of the starting cluster number.
 *
 * Most of the FAT32 changes to pcfs are under 'if it's FAT32' to minimize the
 * effect on non-FAT32 filesystems (and still share the code), except for the
 * starting cluster changes. It seemed easier to make common functions to
 * handle that.
 *
 * Other changes:
 *
 *     1. FAT32 partitions are indicated by partition types 0xB and 0xC.
 *     2. The boot sector is now 2 sectors, to make room for FAT32 extensions.
 *     3. The root directory is no longer stored in a fixed location. Its'
 *        starting cluster is stored in the extended boot sector.
 *     4. "Summary information" is now stored and we need to (at least) maintain
 *        the number of free clusters or scandisk will be upset. Though the
 *        sector this info is in is pointed to by the extensions in the boot
 *        sector, the magic offset of this information is just that so
 *        far - magic. 0x1e0.
 *     5. FAT32 can use the alternate FAT. But we don't.
 *
 * FAT32 also exposed a latent bug: we bread() each copy of the FAT in one
 * big chunk.  This is not good on a large FAT32 drive, such as a 1 Gig
 * Jaz drive that has 4k clusters, since the FAT becomes 1 Meg in size and
 * bread blocks forever. So now we read the FAT in chunks.
 */


/*
 * The FAT bootsector uses little-endian multibyte values not aligned at
 * a 'native' wordsize. Instead of defining a strange data structure and
 * odd accessor methods for some members while using standard C accesses
 * for others, we don't bother and just define the structure offsets, and
 * a common set of misaligned-littleendian accessor macros.
 *
 * The "bootsec" and "fat32_bootsec" structures are only provided for
 * compatibility with old code including <sys/fs/pc_fs.h> but not used
 * by the PCFS kernel driver anymore.
 */
struct bootsec {
	uchar_t	instr[3];
	uchar_t	version[8];
	uchar_t	bps[2];			/* bytes per sector */
	uchar_t	spcl;			/* sectors per allocation unit */
	uchar_t	res_sec[2];		/* reserved sectors, starting at 0 */
	uchar_t	nfat;			/* number of FATs */
	uchar_t	rdirents[2];		/* number of root directory entries */
	uchar_t	numsect[2];		/* old total sectors in logical image */
	uchar_t	mediadesriptor;		/* media descriptor byte */
	ushort_t fatsec;		/* number of sectors per FAT */
	ushort_t spt;			/* sectors per track */
	ushort_t nhead;			/* number of heads */
	uint_t	hiddensec;		/* number of hidden sectors */
	uint_t	totalsec;		/* total sectors in logical image */
};

/*
 * FAT32 volumes have a bigger boot sector. They include the normal
 * boot sector.
 */
struct fat32_bootsec {
	struct bootsec	f_bs;
	uint32_t	f_fatlength;	/* size of FAT */
	uint16_t	f_flags;
	uint8_t		f_major;	/* major filesystem version #? */
	uint8_t		f_minor;	/* minor filesystem version #? */
	uint32_t	f_rootcluster;	/* first cluster in root directory */
	uint16_t	f_infosector;	/* where summary info is */
	uint16_t	f_backupboot;	/* backup boot sector */
	uint16_t	f_reserved2[6];
};


#define	OFF_JMPBOOT	0
#define	OFF_OEMNAME	3
#define	OFF_BYTESPERSEC	11
#define	OFF_SECPERCLUS	13
#define	OFF_RSVDSECCNT	14
#define	OFF_NUMFATS	16
#define	OFF_ROOTENTCNT	17
#define	OFF_TOTSEC16	19
#define	OFF_MEDIA	21
#define	OFF_FATSZ16	22
#define	OFF_SECPERTRK	24
#define	OFF_NUMHEADS	26
#define	OFF_HIDDSEC	28
#define	OFF_TOTSEC32	32
#define	OFF_BPBSIG	510

#define	OFF_DRVNUM16	36
#define	OFF_BOOTSIG16	38
#define	OFF_VOLID16	39
#define	OFF_VOLLAB16	43
#define	OFF_FILSYSTYP16	54

#define	OFF_FATSZ32	36
#define	OFF_EXTFLAGS32	40
#define	OFF_FSVER32	42
#define	OFF_ROOTCLUS32	44
#define	OFF_FSINFO32	48
#define	OFF_BKBOOTSEC32	50
#define	OFF_DRVNUM32	64
#define	OFF_BOOTSIG32	66
#define	OFF_VOLID32	67
#define	OFF_VOLLAB32	71
#define	OFF_FILSYSTYP32	82

#define	LE_16_NA(addr)					\
	(((uint16_t)*((uint8_t *)(addr))) +		\
	((uint16_t)*((uint8_t *)(addr) + 1) << 8))

#define	LE_32_NA(addr)					\
	(((uint32_t)*((uint8_t *)(addr))) +		\
	((uint32_t)*((uint8_t *)(addr) + 1) << 8) +	\
	((uint32_t)*((uint8_t *)(addr) + 2) << 16) +	\
	((uint32_t)*((uint8_t *)(addr) + 3) << 24))

/*
 * Generic FAT BPB fields
 */
#define	bpb_jmpBoot(bpb)		((unsigned char *)(bpb))
#define	bpb_OEMName(bpb)		((char *)(bpb) + OFF_OEMNAME)
#define	bpb_get_BytesPerSec(bpb)	LE_16_NA((bpb) + OFF_BYTESPERSEC)
#define	bpb_get_SecPerClus(bpb)		(((uint8_t *)(bpb))[OFF_SECPERCLUS])
#define	bpb_get_RsvdSecCnt(bpb)		LE_16_NA((bpb) + OFF_RSVDSECCNT)
#define	bpb_get_NumFATs(bpb)		(((uint8_t *)(bpb))[OFF_NUMFATS])
#define	bpb_get_RootEntCnt(bpb)		LE_16_NA((bpb) + OFF_ROOTENTCNT)
#define	bpb_get_TotSec16(bpb)		LE_16_NA((bpb) + OFF_TOTSEC16)
#define	bpb_get_Media(bpb)		(((uint8_t *)(bpb))[OFF_MEDIA])
#define	bpb_get_FatSz16(bpb)		LE_16_NA((bpb) + OFF_FATSZ16)
#define	bpb_get_SecPerTrk(bpb)		LE_16_NA((bpb) + OFF_SECPERTRK)
#define	bpb_get_NumHeads(bpb)		LE_16_NA((bpb) + OFF_NUMHEADS)
#define	bpb_get_HiddSec(bpb)		LE_32_NA((bpb) + OFF_HIDDSEC)
#define	bpb_get_TotSec32(bpb)		LE_32_NA((bpb) + OFF_TOTSEC32)
#define	bpb_get_BPBSig(bpb)		LE_16_NA((bpb) + OFF_BPBSIG)

/*
 * FAT12/16 extended BPB fields
 */
#define	bpb_get_DrvNum16(bpb)		(((uint8_t *)(bpb))[OFF_DRVNUM16])
#define	bpb_get_BootSig16(bpb)		(((uint8_t *)(bpb))[OFF_BOOTSIG16])
#define	bpb_VolLab16(bpb)		((char *)(bpb) + OFF_VOLLAB16)
#define	bpb_FilSysType16(bpb)		((char *)(bpb) + OFF_FILSYSTYP16)
#define	bpb_get_VolID16(bpb)		LE_32_NA((bpb) + OFF_VOLID16)

/*
 * FAT32 extended BPB fields
 */
#define	bpb_get_FatSz32(bpb)		LE_32_NA((bpb) + OFF_FATSZ32)
#define	bpb_get_ExtFlags32(bpb)		LE_16_NA((bpb) + OFF_EXTFLAGS32)
#define	bpb_get_FSVer32(bpb)		LE_16_NA((bpb) + OFF_FSVER32)
#define	bpb_get_RootClus32(bpb)		LE_32_NA((bpb) + OFF_ROOTCLUS32)
#define	bpb_get_FSInfo32(bpb)		LE_16_NA((bpb) + OFF_FSINFO32)
#define	bpb_get_BkBootSec32(bpb)	LE_16_NA((bpb) + OFF_BKBOOTSEC32)
#define	bpb_get_DrvNum32(bpb)		(((uint8_t *)(bpb))[OFF_DRVNUM32])
#define	bpb_get_BootSig32(bpb)		(((uint8_t *)(bpb))[OFF_BOOTSIG32])
#define	bpb_get_VolID32(bpb)		LE_32_NA((bpb) + OFF_VOLID32)
#define	bpb_VolLab32(bpb)		((char *)(bpb) + OFF_VOLLAB32)
#define	bpb_FilSysType32(bpb)		((char *)(bpb) + OFF_FILSYSTYP32)

/*
 * Validators
 */
#define	VALID_SECSIZE(s)	\
	(s == 512 || s == 1024 || s == 2048 || s == 4096)
#define	VALID_SPCL(s)		(ISP2((s)) && (unsigned int)(s) <= 128)
#define	VALID_CLSIZE(s)		(ISP2((s)) && (unsigned int)(s) <= (64 * 1024))
#define	VALID_NUMFATS(n)	((n) > 0 && (n) < 8)
#define	VALID_RSVDSEC(s)	((s) > 0)
#define	VALID_BPBSIG(sig)	((sig) == MBB_MAGIC)
#define	VALID_BOOTSIG(sig)	((sig) == 0x29)
#define	VALID_MEDIA(m)		((m) == 0xF0 || ((m) >= 0xF8 && (m) <= 0xFF))

/*
 * this might require a change for codepage support. In particular,
 * pc_validchar() cannot be a macro anymore if codepages get involved.
 */
#define	VALID_VOLLAB(l)		(			\
	pc_validchar((l)[0]) && pc_validchar((l)[1]) && \
	pc_validchar((l)[2]) &&	pc_validchar((l)[3]) && \
	pc_validchar((l)[4]) && pc_validchar((l)[5]) && \
	pc_validchar((l)[6]) && pc_validchar((l)[7]) && \
	pc_validchar((l)[8]) && pc_validchar((l)[9]) && \
	pc_validchar((l)[10]))

/*
 * We might actually use the 'validchar' checks as well; it only needs
 * to be printable. Should this ever caused failed media recognition,
 * we can change it. Many ISVs put different strings into the "oemname"
 * field.
 */
#define	VALID_OEMNAME(nm)	(			\
	bcmp((nm), "MSDOS", 5) == 0 || bcmp((nm), "MSWIN", 5) == 0)
#define	VALID_FSTYPSTR16(typ)	(bcmp((typ), "FAT", 3) == 0)
#define	VALID_FSTYPSTR32(typ)	(bcmp((typ), "FAT32", 5) == 0)
#define	VALID_JMPBOOT(b)	(			\
	((b)[0] == 0xeb && (b)[2] == 0x90) || (b)[0] == 0xe9)
#define	VALID_FSVER32(v)	((v) == PCFS_SUPPORTED_FSVER)
/*
 * Can we check this properly somehow ? There should be a better way.
 * The FAT spec doesn't mention reserved bits need to be zero ...
 */
#define	VALID_EXTFLAGS(flags)	(((flags) & 0x8f) == (flags))

/*
 * Validation results
 */
#define	BPB_SECSIZE_OK		(1 << 0)	/* ok: 512/1024/2048/4096 */
#define	BPB_OEMNAME_OK		(1 << 1)	/* "MSDOS" or "MSWIN" */
#define	BPB_JMPBOOT_OK		(1 << 2)	/* 16bit "jmp" / "call" */
#define	BPB_SECPERCLUS_OK	(1 << 3)	/* power of 2, [1 .. 128] */
#define	BPB_RSVDSECCNT_OK	(1 << 4)	/* cannot be zero */
#define	BPB_NUMFAT_OK		(1 << 5)	/* >= 1, <= 8 */
#define	BPB_ROOTENTCNT_OK	(1 << 6)	/* 0 on FAT32, != 0 else */
#define	BPB_TOTSEC_OK		(1 << 7)	/* smaller than volume */
#define	BPB_TOTSEC16_OK		(1 << 8)	/* 0 on FAT32, != 0 on FAT12 */
#define	BPB_TOTSEC32_OK		(1 << 9)	/* 0 on FAT12, != 0 on FAT32 */
#define	BPB_MEDIADESC_OK	(1 << 10)	/* 0xf0 or 0xf8..0xff */
#define	BPB_FATSZ_OK		(1 << 11)	/* [nclusters], no smaller */
#define	BPB_FATSZ16_OK		(1 << 12)	/* 0 on FAT32, != 0 else */
#define	BPB_FATSZ32_OK		(1 << 13)	/* non-zero on FAT32 */
#define	BPB_BPBSIG_OK		(1 << 14)	/* 0x55, 0xAA */
#define	BPB_BOOTSIG16_OK	(1 << 15)	/* 0x29 - if present */
#define	BPB_BOOTSIG32_OK	(1 << 16)	/* 0x29 - unless SYSLINUX2.x */
#define	BPB_FSTYPSTR16_OK	(1 << 17)	/* At least "FAT" */
#define	BPB_FSTYPSTR32_OK	(1 << 18)	/* "FAT32" */
#define	BPB_EXTFLAGS_OK		(1 << 19)	/* reserved bits should be 0 */
#define	BPB_FSVER_OK		(1 << 20)	/* must be 0 */
#define	BPB_ROOTCLUSTER_OK	(1 << 21)	/* must be != 0 and valid */
#define	BPB_FSISEC_OK		(1 << 22)	/* != 0, <= reserved */
#define	BPB_BKBOOTSEC_OK	(1 << 23)	/* != 0, <= reserved, != fsi */
#define	BPB_VOLLAB16_OK		(1 << 24)	/* passes pc_validchar() */
#define	BPB_VOLLAB32_OK		(1 << 25)	/* passes pc_validchar() */
#define	BPB_NCLUSTERS_OK	(1 << 26)	/* from FAT spec */
#define	BPB_CLSIZE_OK		(1 << 27)	/* cluster size */
#define	BPB_MEDIASZ_OK		(1 << 28)	/* filesystem fits on device */

#define	FAT12_VALIDMSK							\
	(BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK |		\
	BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK |		\
	BPB_TOTSEC_OK | BPB_TOTSEC16_OK |				\
	BPB_FATSZ_OK | BPB_FATSZ16_OK |	BPB_BPBSIG_OK)

#define	FAT16_VALIDMSK							\
	(BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK |		\
	BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK |		\
	BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | 		\
	BPB_FATSZ_OK | BPB_FATSZ16_OK | BPB_BPBSIG_OK)

/*
 * A note on FAT32: According to the FAT spec, FAT32 _must_ have a valid
 * extended BPB and therefore, as a proof of its existance, the FAT32
 * boot signature (offset 66) must be valid as well. Why don't we check
 * for BPB_BOOTSIG32_OK  then ?
 *
 * We don't test for this here first-pass, because there are media out
 * there that are valid FAT32 structurally but don't have a valid sig.
 * This happens if older versions of the SYSLINUX bootloader (below 3.x)
 * are installed on a media with a FAT32 on it. SYSLINUX 2.x and lower
 * overwrite the BPB past the end of the FAT12/16 extension with its
 * bootloader code - and the FAT16 extended BPB is 62 Bytes...
 * All structurally relevant fields of the FAT32 BPB are within the first
 * 52 Bytes, so the filesystem is accessible - but the signature check
 * would reject it.
 */
#define	FAT32_VALIDMSK							\
	(BPB_SECSIZE_OK | BPB_SECPERCLUS_OK | BPB_CLSIZE_OK |		\
	BPB_RSVDSECCNT_OK | BPB_NUMFAT_OK | BPB_ROOTENTCNT_OK |		\
	BPB_TOTSEC_OK | BPB_TOTSEC16_OK | BPB_TOTSEC32_OK | 		\
	BPB_FATSZ_OK | BPB_FATSZ16_OK |	BPB_FATSZ32_OK |		\
	BPB_EXTFLAGS_OK | BPB_FSVER_OK | BPB_ROOTCLUSTER_OK |		\
	BPB_BPBSIG_OK)

/*
 * FAT32 BPB allows 'versioning' via FSVer32. We follow the 'NULL' spec.
 */
#define	PCFS_SUPPORTED_FSVER	0


/*
 * Filesystem summary information (introduced originally for FAT32 volumes).
 * We need to maintain fs_free_clusters or Microsoft Scandisk will be upset.
 * We keep these values in-core even for FAT12/FAT16 but will never attempt
 * to write them out to disk then.
 */
typedef struct fat_fsinfo {
	uint32_t fs_free_clusters;	/* # free clusters. -1 if unknown */
	uint32_t fs_next_free;		/* search next free after this cn */
} fat_fsi_t;

/*
 * On-disk FSI. All values in little endian. Only FAT32 has this.
 */
typedef struct fat_od_fsi {
	uint32_t	fsi_leadsig;		/* 0x41615252 */
	char		fsi_reserved1[480];
	uint32_t	fsi_strucsig;		/* 0x61417272 */
	fat_fsi_t	fsi_incore;		/* free/nextfree */
	char		fsi_reserved2[12];
	uint32_t	fsi_trailsig;		/* 0xaa550000 */
} fat_od_fsi_t;

#define	FSI_LEADSIG	LE_32(0x41615252)
#define	FSI_STRUCSIG	LE_32(0x61417272)
#define	FSI_TRAILSIG	LE_32(0xaa550000)	/* same as MBB_MAGIC */

#define	FSISIG_OK(fsi)	(						\
	((fat_od_fsi_t *)(fsi))->fsi_leadsig == FSI_LEADSIG &&		\
	((fat_od_fsi_t *)(fsi))->fsi_strucsig == FSI_STRUCSIG &&	\
	((fat_od_fsi_t *)(fsi))->fsi_trailsig == FSI_TRAILSIG)

#define	FSINFO_UNKNOWN	((uint32_t)(-1))	/* free/next not valid */

typedef enum { FAT12, FAT16, FAT32, FAT_UNKNOWN, FAT_QUESTIONABLE } fattype_t;


struct pcfs {
	struct vfs *pcfs_vfs;		/* vfs for this fs */
	int pcfs_flags;			/* flags */
	int pcfs_ldrive;		/* logical DOS drive number */
	fattype_t pcfs_fattype;
	dev_t pcfs_xdev;		/* actual device that is mounted */
	struct vnode *pcfs_devvp;	/*   and a vnode for it */
	int pcfs_secsize;		/* sector size in bytes */
	int pcfs_spcl;			/* sectors per cluster */
	int pcfs_spt;			/* sectors per track */
	int pcfs_sdshift;		/* shift to convert sector into */
					/* DEV_BSIZE "sectors"; assume */
					/* pcfs_secsize is 2**n times of */
					/* DEV_BSIZE */
	int pcfs_fatsec;		/* number of sec per FAT */
	int pcfs_numfat;		/* number of FAT copies */
	int pcfs_rdirsec;		/* number of sec in root dir */
	daddr_t pcfs_dosstart;		/* start blkno of DOS partition */
	daddr_t pcfs_fsistart;		/* start blkno of FSI sector */
	daddr_t pcfs_fatstart;		/* start blkno of first FAT */
	daddr_t pcfs_rdirstart;		/* start blkno of root dir */
	daddr_t pcfs_datastart;		/* start blkno of data area */
	int pcfs_clsize;		/* cluster size in bytes */
	int pcfs_ncluster;		/* number of clusters in fs */
	int pcfs_nrefs;			/* number of active pcnodes */
	int pcfs_frefs;			/* number of active file pcnodes */
	int pcfs_nxfrecls;		/* next free cluster */
	uchar_t *pcfs_fatp;		/* ptr to FAT data */
	uchar_t *pcfs_fat_changemap;	/* map of changed fat data */
	int pcfs_fat_changemapsize;	/* size of FAT changemap */
	time_t pcfs_fattime;		/* time FAT becomes invalid */
	time_t pcfs_verifytime;		/* time to reverify disk */
	kmutex_t	pcfs_lock;		/* per filesystem lock */
	kthread_id_t pcfs_owner;		/* id of thread locking pcfs */
	int pcfs_count;			/* # of pcfs locks for pcfs_owner */
	struct fat_fsinfo pcfs_fsinfo;	/* in-core fsinfo */
	struct pcfs *pcfs_nxt;		/* linked list of all mounts */
	int pcfs_fatjustread;		/* Used to flag a freshly found FAT */
	struct vnode *pcfs_root;	/* vnode for the root dir of the fs */
	int pcfs_secondswest;		/* recording timezone for this fs */
	len_t pcfs_mediasize;
	int pcfs_rootblksize;
	int pcfs_mediadesc;		/* media descriptor */
	pc_cluster32_t pcfs_lastclmark;
	pc_cluster32_t pcfs_rootclnum;
	timestruc_t pcfs_mounttime;	/* timestamp for "/" */
};

/*
 * flags
 */
#define	PCFS_FATMOD		0x01	/* FAT has been modified */
#define	PCFS_LOCKED		0x02	/* fs is locked */
#define	PCFS_WANTED		0x04	/* locked fs is wanted */
#define	PCFS_NOCHK		0x800	/* don't resync fat on error */
#define	PCFS_BOOTPART		0x1000	/* boot partition type */
#define	PCFS_HIDDEN		0x2000	/* show hidden files */
#define	PCFS_PCMCIA_NO_CIS	0x4000	/* PCMCIA psuedo floppy */
#define	PCFS_FOLDCASE		0x8000	/* fold filenames to lowercase */
#define	PCFS_FSINFO_OK		0x10000	/* valid FAT32 fsinfo sector */
#define	PCFS_IRRECOV		0x20000	/* FS was messed with during write */
#define	PCFS_NOCLAMPTIME	0x40000	/* expose full FAT timestamp range */
#define	PCFS_NOATIME		0x80000	/* disable atime updates */

#define	IS_FAT12(PCFS)	((PCFS)->pcfs_fattype == FAT12)
#define	IS_FAT16(PCFS)	((PCFS)->pcfs_fattype == FAT16)
#define	IS_FAT32(PCFS)	((PCFS)->pcfs_fattype == FAT32)

/* for compatibility */
struct old_pcfs_args {
	int	secondswest;	/* seconds west of Greenwich */
	int	dsttime;    	/* type of dst correction */
};

struct pcfs_args {
	int	secondswest;	/* seconds west of Greenwich */
	int	dsttime;    	/* type of dst correction */
	int	flags;
};

/*
 * pcfs mount options.
 */
#define	MNTOPT_PCFS_HIDDEN	"hidden"
#define	MNTOPT_PCFS_NOHIDDEN	"nohidden"
#define	MNTOPT_PCFS_FOLDCASE	"foldcase"
#define	MNTOPT_PCFS_NOFOLDCASE	"nofoldcase"
#define	MNTOPT_PCFS_CLAMPTIME	"clamptime"
#define	MNTOPT_PCFS_NOCLAMPTIME	"noclamptime"
#define	MNTOPT_PCFS_TIMEZONE	"timezone"
#define	MNTOPT_PCFS_SECSIZE	"secsize"

/*
 * Disk timeout value in sec.
 * This is used to time out the in core FAT and to re-verify the disk.
 * This should be less than the time it takes to change floppys
 */
#define	PCFS_DISKTIMEOUT	2

#define	PCFS_MAXOFFSET_T	UINT32_MAX	/* PCFS max file size */

#define	VFSTOPCFS(VFSP)		((struct pcfs *)((VFSP)->vfs_data))
#define	PCFSTOVFS(FSP)		((FSP)->pcfs_vfs)

/*
 * special cluster numbers in FAT
 */
#define	PCF_FREECLUSTER		0x00	/* cluster is available */
#define	PCF_ERRORCLUSTER	0x01	/* error occurred allocating cluster */
#define	PCF_12BCLUSTER		0xFF0	/* 12-bit version of reserved cluster */
#define	PCF_RESCLUSTER		0xFFF0	/* 16-bit version of reserved cluster */
#define	PCF_RESCLUSTER32	0xFFFFFF0 /* 32-bit version */
#define	PCF_BADCLUSTER		0xFFF7	/* bad cluster, do not use */
#define	PCF_BADCLUSTER32	0xFFFFFF7 /* 32-bit version */
#define	PCF_LASTCLUSTER		0xFFF8	/* >= means last cluster in file */
#define	PCF_LASTCLUSTER32	0xFFFFFF8 /* 32-bit version */
#define	PCF_LASTCLUSTERMARK	0xFFFF	/* value used to mark last cluster */
#define	PCF_LASTCLUSTERMARK32	0xFFFFFFF /* 32-bit version */
#define	PCF_FIRSTCLUSTER	2	/* first valid cluster number */

/*
 * file system constants
 */
#define	PC_MAXFATSEC	256		/* maximum number of sectors in FAT */

/*
 * file system parameter macros
 */

#define	pc_clear_fatchanges(PCFS) \
	bzero((PCFS)->pcfs_fat_changemap, (PCFS)->pcfs_fat_changemapsize)

#define	pc_blksize(PCFS, PCP, OFF)	/* file system block size */	\
	(((PCTOV(PCP)->v_flag & VROOT) && !IS_FAT32(PCFS)) ? \
	    ((OFF) >= \
	    ((PCFS)->pcfs_rdirsec & \
	    ~((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize)? \
	    ((PCFS)->pcfs_rdirsec & \
	    ((PCFS)->pcfs_spcl - 1)) * ((PCFS)->pcfs_secsize): \
	    (PCFS)->pcfs_clsize): \
	    (PCFS)->pcfs_clsize)

#define	pc_blkoff(PCFS, OFF)		/* offset within block */ \
	((int)((OFF) & ((PCFS)->pcfs_clsize - 1)))

#define	pc_lblkno(PCFS, OFF)		/* logical block (cluster) no */ \
	((daddr_t)((OFF) / (PCFS)->pcfs_clsize))

#define	pc_dbtocl(PCFS, DB)		/* disk blks to clusters */ \
	((int)((DB) / (PCFS)->pcfs_spcl))

#define	pc_cltodb(PCFS, CL)		/* clusters to disk blks */ \
	((daddr_t)((CL) * (PCFS)->pcfs_spcl))

#define	pc_dbdaddr(PCFS, DB)	/* sector to DEV_BSIZE "sector" addr */ \
	((DB) << (PCFS)->pcfs_sdshift)

#define	pc_daddrdb(PCFS, DADDR)	/* DEV_BSIZE "sector" addr to sector addr */ \
	((DADDR) >> (PCFS)->pcfs_sdshift)

#define	pc_cldaddr(PCFS, CL)	/* DEV_BSIZE "sector" addr for cluster */ \
	pc_dbdaddr(PCFS, ((daddr_t)((PCFS)->pcfs_datastart +	\
	pc_cltodb(PCFS, (CL) - PCF_FIRSTCLUSTER))))

#define	pc_daddrcl(PCFS, DADDR)		/* cluster for disk address */	\
	((int)(PCF_FIRSTCLUSTER +					\
	pc_dbtocl(pc_daddrdb(PCFS, DADDR) - (PCFS)->pcfs_datastart)))

/*
 * Number of directory entries per sector / cluster
 */
#define	pc_direntpersec(PCFS)						\
	((int)((PCFS)->pcfs_secsize / sizeof (struct pcdir)))

#define	pc_direntpercl(PCFS)						\
	((int)((PCFS)->pcfs_clsize  / sizeof (struct pcdir)))

/*
 * out-of-range check for cluster numbers.
 */
#define	pc_validcl(PCFS, CL)		/* check that cluster no is legit */ \
	((int)(CL) >= PCF_FIRSTCLUSTER && \
	    (int)(CL) < (PCFS)->pcfs_ncluster + PCF_FIRSTCLUSTER)

/*
 * external routines.
 */
extern int pc_lockfs(struct pcfs *, int, int); /* lock fs and get fat */
extern void pc_unlockfs(struct pcfs *);	/* ulock the fs */
extern int pc_getfat(struct pcfs *);	/* get fat from disk */
extern void pc_invalfat(struct pcfs *);	/* invalidate incore fat */
extern int pc_syncfat(struct pcfs *);	/* sync fat to disk */
extern int pc_freeclusters(struct pcfs *);	/* num free clusters in fs */
extern pc_cluster32_t pc_alloccluster(struct pcfs *, int);
extern void pc_setcluster(struct pcfs *, pc_cluster32_t, pc_cluster32_t);
extern void pc_mark_fat_updated(struct pcfs *fsp, pc_cluster32_t cn);
extern int pc_fat_is_changed(struct pcfs *fsp, pc_cluster32_t bn);

/*
 * debugging
 */
extern int pcfsdebuglevel;
#define	PC_DPRINTF0(level, A) \
	if (pcfsdebuglevel >= level) \
	    cmn_err(CE_CONT, (A))
#define	PC_DPRINTF1(level, A, B) \
	if (pcfsdebuglevel >= level) \
	    cmn_err(CE_CONT, (A), (B))
#define	PC_DPRINTF2(level, A, B, C) \
	if (pcfsdebuglevel >= level) \
	    cmn_err(CE_CONT, (A), (B), (C))
#define	PC_DPRINTF3(level, A, B, C, D) \
	if (pcfsdebuglevel >= level) \
	    cmn_err(CE_CONT, (A), (B), (C), (D))
#define	PC_DPRINTF4(level, A, B, C, D, E) \
	if (pcfsdebuglevel >= level) \
	    cmn_err(CE_CONT, (A), (B), (C), (D), (E))

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_PC_FS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_PC_LABEL_H
#define	_SYS_FS_PC_LABEL_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/isa_defs.h>

/*
 * PC master boot block & partition table defines.
 */

#define	PCB_BPSEC	11	/* (short) bytes per sector */
#define	PCB_SPC		13	/* (byte) sectors per cluster */
#define	PCB_RESSEC	14	/* (short) reserved sectors */
#define	PCB_NFAT	16	/* (byte) number of fats */
#define	PCB_NROOTENT	17	/* (short) number of root dir entries */
#define	PCB_NSEC	19	/* (short) number of sectors on disk */
#define	PCB_MEDIA	21	/* (byte) media descriptor */
#define	PCB_SPF		22	/* (short) sectors per fat */
#define	PCB_SPT		24	/* (short) sectors per track */
#define	PCB_NHEAD	26	/* (short) number of heads */
#define	PCB_HIDSEC	28	/* (short) number of hidden sectors */

#define	PCFS_PART	0x1be	/* partition table offs in blk 0 of unit */
#define	PCFS_NUMPART	4	/* Number of partitions in blk 0 of unit */

/*
 *  Offsets into the boot sector where the string 'FAT' is expected.
 *  First value is where the string is on 12 and 16 bit FATs,
 *  the second value is where it is on 32 bit FATs.
 */
#define	PCFS_TYPESTRING_OFFSET16	0x36
#define	PCFS_TYPESTRING_OFFSET32	0x52

#define	PCFS_BPB	0xb	/* offset of the BPB in the boot block	*/
#define	PCFS_SIGN	0x1fe   /* offset of the DOS signature		*/
#define	DOS_SYSFAT12    1	/* DOS FAT 12 system indicator		*/
#define	DOS_SYSFAT16	4	/* DOS FAT 16 system indicator		*/
#define	DOS_SYSHUGE	6	/* DOS FAT 16 system indicator > 32MB	*/
#define	DOS_FAT32	0xB	/* FAT32 system indicator */
#define	DOS_FAT32_LBA	0xC	/* FAT32 system indicator (LBA) */
#define	DOS_FAT16P_LBA	0xE	/* FAT16 system indicator (Primary/LBA ) */
#define	DOS_FAT16_LBA	0xF	/* FAT16 system indicator (Extended/LBA) */
#define	DOS_F12MAXS	20740	/* Max sector for 12 Bit FAT (DOS>=3.2)	*/
#define	DOS_F12MAXC	4086	/* Max cluster for 12 Bit FAT (DOS>=3.2) */

#define	DOS_ID1		0xe9	/* JMP intrasegment			*/
#define	DOS_ID2a	0xeb    /* JMP short				*/
#define	DOS_ID2b	0x90
#define	DOS_SIGN	0xaa55	/* DOS signature in boot and partition	*/

#define	PC_FATBLOCK	1	/* starting block number of fat */
/*
 * Media descriptor byte.
 * Found in the boot block and in the first byte of the FAT.
 * Second and third byte in the FAT must be 0xFF.
 * Note that all technical sources indicate that this means of
 * identification is extremely unreliable.
 */
#define	MD_FIXED	0xF8	/* fixed disk				*/
#define	SS8SPT		0xFE	/* single sided 8 sectors per track	*/
#define	DS8SPT		0xFF	/* double sided 8 sectors per track	*/
#define	SS9SPT		0xFC	/* single sided 9 sectors per track	*/
#define	DS9SPT		0xFD	/* double sided 9 sectors per track	*/
#define	DS18SPT		0xF0	/* double sided 18 sectors per track	*/
#define	DS9_15SPT	0xF9	/* double sided 9/15 sectors per track	*/

#define	PC_SECSIZE	512	/* pc filesystem sector size */

/*
 * conversions to/from little endian format
 */
#if defined(_LITTLE_ENDIAN)
/* e.g. i386 machines */
#define	ltohs(S)	(*((ushort_t *)(&(S))))
#define	ltohi(I)	(*((uint_t *)(&(I))))
#define	htols(S)	(*((ushort_t *)(&(S))))
#define	htoli(I)	(*((uint_t *)(&(I))))

#else
/* e.g. SPARC machines */
#define	getbyte(A, N)	(((unsigned char *)(&(A)))[N])
#define	ltohs(S)	((getbyte(S, 1) << 8) | getbyte(S, 0))
#define	ltohi(I)	((getbyte(I, 3) << 24) | (getbyte(I, 2) << 16) | \
			    (getbyte(I, 1) << 8) | getbyte(I, 0))
#define	htols(S)	((getbyte(S, 1) << 8) | getbyte(S, 0))
#define	htoli(I)	((getbyte(I, 3) << 24) | (getbyte(I, 2) << 16) | \
			    (getbyte(I, 1) << 8) | getbyte(I, 0))
#endif

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_PC_LABEL_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_PC_NODE_H
#define	_SYS_FS_PC_NODE_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <vm/page.h>
#include <sys/buf.h>
#include <sys/vnode.h>

#ifdef _KERNEL
#include <sys/vfs_opreg.h>
#endif

/*
 * This overlays the fid structure (see vfs.h)
 *
 * 10 bytes max.
 */
struct pc_fid {
	ushort_t	pcfid_len;
	uint32_t	pcfid_block;	/* dblock containing directory entry */
	uint16_t	pcfid_offset;	/* offset within block of entry */
	uint16_t	pcfid_ctime;	/* creation time of entry (~= i_gen) */
};

struct pcnode {
	struct pcnode	*pc_forw;	/* active list ptrs, must be first */
	struct pcnode	*pc_back;
	int pc_flags;			/* see below */
	struct vnode	*pc_vn;		/* vnode for pcnode */
	uint_t pc_size;			/* size of file */
	pc_cluster32_t	pc_scluster;	/* starting cluster of file */
	daddr_t pc_eblkno;		/* disk blkno for entry */
	int pc_eoffset;			/* offset in disk block of entry */
	struct pcdir pc_entry;		/* directory entry of file */
	pc_cluster32_t	pc_lcluster;	/* last cluster visited */
	daddr_t		pc_lindex;	/* index of last cluster visited */
};

/*
 * flags
 */
#define	PC_MOD		0x01		/* file data has been modified */
#define	PC_CHG		0x02		/* node data has been changed */
#define	PC_INVAL	0x04		/* node is invalid */
#define	PC_EXTERNAL	0x08		/* vnode ref is held externally */
#define	PC_ACC		0x10		/* file data has been accessed */
#define	PC_RELEHOLD	0x80		/* node is being released */

#define	PCTOV(PCP)	((PCP)->pc_vn)
#define	VTOPC(VP)	((struct pcnode *)((VP)->v_data))

/*
 * Make a unique integer for a file
 */
#define	pc_makenodeid(BN, OFF, ATTR, SCLUSTER, ENTPS) \
	(ino_t)((ATTR) & PCA_DIR ? \
		(uint32_t)(-(SCLUSTER) - 1) : \
		((BN) * (ENTPS)) + ((OFF) / sizeof (struct pcdir)))

#define	NPCHASH 1

#if NPCHASH == 1
#define	PCFHASH(FSP, BN, O)	0
#define	PCDHASH(FSP, SC)	0
#else
#define	PCFHASH(FSP, BN, O)	(((unsigned)FSP + BN + O) % NPCHASH)
#define	PCDHASH(FSP, SC)	(((unsigned)FSP + SC) % NPCHASH)
#endif

struct pchead {
	struct pcnode *pch_forw;
	struct pcnode *pch_back;
};

/*
 * pcnode file and directory operations vectors
 */
extern struct vnodeops *pcfs_fvnodeops;
extern struct vnodeops *pcfs_dvnodeops;

#ifdef _KERNEL
extern const struct fs_operation_def pcfs_fvnodeops_template[];
extern const struct fs_operation_def pcfs_dvnodeops_template[];
#endif

extern struct pchead pcfhead[];
extern struct pchead pcdhead[];

/*
 * pcnode routines
 */
extern void pc_init(void);
extern struct pcnode *pc_getnode(struct pcfs *, daddr_t, int, struct pcdir *);
extern void pc_rele(struct pcnode *);
extern void pc_mark_mod(struct pcfs *, struct pcnode *);
extern void pc_mark_acc(struct pcfs *, struct pcnode *);
extern int pc_nodesync(struct pcnode *);
extern int pc_nodeupdate(struct pcnode *);
extern int pc_bmap(struct pcnode *, daddr_t, daddr_t *, uint_t *);

extern int pc_balloc(struct pcnode *, daddr_t, int, daddr_t *);
extern int pc_bfree(struct pcnode *, pc_cluster32_t);
extern int pc_verify(struct pcfs *);
extern void pc_diskchanged(struct pcfs *);
extern void pc_mark_irrecov(struct pcfs *);

extern int pc_dirlook(struct pcnode *, char *, struct pcnode **);
extern int pc_direnter(struct pcnode *, char *, struct vattr *,
	struct pcnode **);
extern int pc_dirremove(struct pcnode *, char *, struct vnode *, enum vtype,
		caller_context_t *);
extern int pc_rename(struct pcnode *, struct pcnode *, char *, char *,
		caller_context_t *);
extern int pc_blkatoff(struct pcnode *, offset_t, struct buf **,
	struct pcdir **);
extern int pc_truncate(struct pcnode *, uint_t);
extern int pc_fileclsize(struct pcfs *, pc_cluster32_t, pc_cluster32_t *);
extern int pcfs_putapage(struct vnode *, page_t *, u_offset_t *, size_t *, int,
	struct cred *);
extern void pc_badfs(struct pcfs *);

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_PC_NODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1997-1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _PXFS_KI_H
#define	_PXFS_KI_H

#include <sys/vfs.h>
#include <sys/vnode.h>
#include <sys/aio_req.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Kernel interface to pxfs routines: definition of stubs.
 */

/*
 * kaio interface to pxfs
 */

extern int clpxfs_aio_write(vnode_t *vp, struct aio_req *aio, cred_t *cred_p);
extern int clpxfs_aio_read(vnode_t *vp, struct aio_req *aio, cred_t *cred_p);

#ifdef __cplusplus
}
#endif

#endif /* _PXFS_KI_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2015, 2016 Joyent, Inc.  All rights reserved.
 * Copyright (c) 2014, 2017 by Delphix. All rights reserved.
 */

#ifndef _SYS_SDEV_IMPL_H
#define	_SYS_SDEV_IMPL_H

#ifdef __cplusplus
extern "C" {
#endif

#include <rpc/rpc.h>
#include <sys/dirent.h>
#include <sys/vfs.h>
#include <sys/vfs_opreg.h>
#include <sys/list.h>
#include <sys/nvpair.h>
#include <sys/sunddi.h>
#include <sys/fs/sdev_plugin.h>

/*
 * sdev_nodes are the file-system specific part of the
 * vnodes for the device filesystem.
 *
 * The device filesystem exports two node types:
 *
 * VDIR nodes		to represent directories
 * VCHR & VBLK nodes	to represent devices
 */

/*
 * /dev mount arguments
 */
struct sdev_mountargs {
	uint64_t sdev_attrdir;
};


/*
 * Nvpair names of profile information (list of device files available) of
 * non-global /dev mounts.  These strings must be unique among them.
 */
#define	SDEV_NVNAME_MOUNTPT	"prof_mountpt"
#define	SDEV_NVNAME_INCLUDE	"prof_include"
#define	SDEV_NVNAME_EXCLUDE	"prof_exclude"
#define	SDEV_NVNAME_SYMLINK	"prof_symlink"
#define	SDEV_NVNAME_MAP		"prof_map"

/*
 * supported devfsadm_cmd
 */
#define	DEVFSADMD_RUN_ALL	1

/*
 * devfsadm_error codes
 */
#define	DEVFSADM_RUN_INVALID		1
#define	DEVFSADM_RUN_EPERM		2
#define	DEVFSADM_RUN_NOTSUP		3

/*
 * devfsadm/devname door data structures
 */
typedef struct sdev_door_arg {
	uint8_t devfsadm_cmd;	/* what to do for devfsadm[d] */
} sdev_door_arg_t;

typedef struct sdev_door_res {
	int32_t devfsadm_error;
} sdev_door_res_t;

#ifdef _KERNEL

struct sdev_dprof {
	int has_glob;
	nvlist_t *dev_name;
	nvlist_t *dev_map;
	nvlist_t *dev_symlink;
	nvlist_t *dev_glob_incdir;
	nvlist_t *dev_glob_excdir;
};

/*
 * devname_handle_t
 */
struct devname_handle {
	struct sdev_node *dh_data;	/* the sdev_node */
	void    *dh_args;
};
typedef struct devname_handle devname_handle_t;

/*
 * Per-instance node data for the global zone instance
 * Only one mount of /dev in the global zone
 */
typedef struct sdev_global_data {
	struct devname_handle sdev_ghandle;
	ulong_t		sdev_dir_ggen;		/* name space generation # */
} sdev_global_data_t;

/*
 * Per-instance node data - profile data per non-global zone mount instance
 */
typedef struct sdev_local_data {
	ulong_t sdev_dir_lgen;		/* cached generation # of /dev dir */
	ulong_t sdev_devtree_lgen;	/* cached generation # of devtree */
	struct sdev_node *sdev_lorigin;	/* corresponding global sdev_node */
	struct sdev_dprof sdev_lprof;	/* profile for multi-inst */
} sdev_local_data_t;

/* sdev_flags */
typedef enum sdev_flags {
	SDEV_BUILD =		0x0001,	/* directory cache out-of-date */
	SDEV_GLOBAL =		0x0002,	/* global /dev nodes */
	SDEV_PERSIST =		0x0004,	/* backing store persisted node */
	SDEV_NO_NCACHE = 	0x0008,	/* do not include in neg. cache */
	SDEV_DYNAMIC =		0x0010,	/* special-purpose vnode ops */
					/* (ex: pts) */
	SDEV_VTOR =		0x0020,	/* validate sdev_nodes during search */
	SDEV_ATTR_INVALID =	0x0040,	/* invalid node attributes, */
					/* need update */
	SDEV_SUBDIR =		0x0080,	/* match all subdirs under here */
	SDEV_ZONED =		0x0100	/* zoned subdir */
} sdev_flags_t;

/*
 * /dev filesystem sdev_node defines
 */
typedef struct sdev_node {
	char		*sdev_name;	/* node name */
	size_t		sdev_namelen;	/* strlen(sdev_name) */
	char		*sdev_path;	/* absolute path */
	char		*sdev_symlink;	/* source for a symlink */
	struct vnode	*sdev_vnode;	/* vnode */

	krwlock_t	sdev_contents;	/* rw lock for this data structure */
	struct sdev_node *sdev_dotdot;	/* parent */

	avl_tree_t	sdev_entries;	/* VDIR: contents as avl tree */
	avl_node_t	sdev_avllink;	/* avl node linkage */

	struct vnode	*sdev_attrvp;	/* backing store vnode if persisted */
	struct vattr	*sdev_attr;	/* memory copy of the vattr */

	ino64_t		sdev_ino;	/* inode */
	uint_t		sdev_nlink;	/* link count */
	int		sdev_state;	/* state of this node */
	sdev_flags_t	sdev_flags;	/* flags bit */

	kmutex_t	sdev_lookup_lock; /* node creation synch lock */
	kcondvar_t	sdev_lookup_cv;	/* node creation sync cv */
	int		sdev_lookup_flags; /* node creation flags */

	/* per-instance data, either global or non-global zone */
	union {
		struct sdev_global_data	sdev_globaldata;
		struct sdev_local_data	sdev_localdata;
	} sdev_instance_data;
	list_node_t	sdev_plist;	/* link on plugin list */
	void		*sdev_private;
} sdev_node_t;

#define	sdev_ldata sdev_instance_data.sdev_localdata
#define	sdev_gdata sdev_instance_data.sdev_globaldata

#define	sdev_handle		sdev_gdata.sdev_ghandle
#define	sdev_gdir_gen		sdev_gdata.sdev_dir_ggen

#define	sdev_ldir_gen		sdev_ldata.sdev_dir_lgen
#define	sdev_devtree_gen	sdev_ldata.sdev_devtree_lgen
#define	sdev_origin		sdev_ldata.sdev_lorigin
#define	sdev_prof		sdev_ldata.sdev_lprof

/*
 * Directory contents traversal
 */
#define	SDEV_FIRST_ENTRY(ddv)		avl_first(&(ddv)->sdev_entries)
#define	SDEV_NEXT_ENTRY(ddv, dv)	AVL_NEXT(&(ddv)->sdev_entries, (dv))

/*
 * See the big theory statement in sdev_vnops.c for an explanation of these
 * states.
 */
typedef enum {
	SDEV_ZOMBIE = -1,
	SDEV_INIT = 0,
	SDEV_READY
} sdev_node_state_t;

/* sdev_lookup_flags */
#define	SDEV_LOOKUP	0x0001	/* node creation in progress */
#define	SDEV_READDIR	0x0002	/* VDIR readdir in progress */
#define	SDEV_LGWAITING	0x0004	/* waiting for devfsadm completion */

/* convenient macros */
#define	SDEV_IS_GLOBAL(dv)	\
	(dv->sdev_flags & SDEV_GLOBAL)
#define	SDEV_IS_PERSIST(dv)	\
	(dv->sdev_flags & SDEV_PERSIST)
#define	SDEV_IS_DYNAMIC(dv)	\
	(dv->sdev_flags & SDEV_DYNAMIC)
#define	SDEV_IS_NO_NCACHE(dv)	\
	(dv->sdev_flags & SDEV_NO_NCACHE)
#define	SDEV_IS_LOOKUP(dv)	\
	(dv->sdev_lookup_flags & SDEV_LOOKUP)
#define	SDEV_IS_READDIR(dv)	\
	(dv->sdev_lookup_flags & SDEV_READDIR)
#define	SDEV_IS_LGWAITING(dv)	\
	(dv->sdev_lookup_flags  & SDEV_LGWAITING)

#define	SDEVTOV(n)	((struct vnode *)(n)->sdev_vnode)
#define	VTOSDEV(vp)	((struct sdev_node *)(vp)->v_data)
#define	VN_HELD(v)	((v)->v_count != 0)
#define	SDEV_HELD(dv)	(VN_HELD(SDEVTOV(dv)))
#define	SDEV_HOLD(dv)	VN_HOLD(SDEVTOV(dv))
#define	SDEV_RELE(dv)	VN_RELE(SDEVTOV(dv))
#define	SDEV_SIMPLE_RELE(dv)	{	\
	struct vnode *vp = SDEVTOV(dv);	\
	mutex_enter(&vp->v_lock);	\
	VN_RELE_LOCKED(vp);		\
	mutex_exit(&vp->v_lock);	\
}

#define	SDEV_ACL_FLAVOR(vp)	(VFSTOSDEVFS(vp->v_vfsp)->sdev_acl_flavor)

/*
 * some defaults
 */
#define	SDEV_ROOTINO		((ino_t)2)
#define	SDEV_UID_DEFAULT	(0)
#define	SDEV_GID_DEFAULT	(3)
#define	SDEV_DIRMODE_DEFAULT	(S_IFDIR |0755)
#define	SDEV_DEVMODE_DEFAULT	(0600)
#define	SDEV_LNKMODE_DEFAULT	(S_IFLNK | 0777)

extern struct vattr sdev_vattr_dir;
extern struct vattr sdev_vattr_lnk;
extern struct vattr sdev_vattr_blk;
extern struct vattr sdev_vattr_chr;

/*
 * devname_lookup_func()
 */
extern int devname_lookup_func(struct sdev_node *, char *, struct vnode **,
    struct cred *, int (*)(struct sdev_node *, char *, void **, struct cred *,
    void *, char *), int);

/*
 * flags used by devname_lookup_func callbacks
 */
#define	SDEV_VATTR	0x4	/* callback returning node vattr */
#define	SDEV_VLINK	0x8	/* callback returning /dev link */

/*
 * devname_readdir_func()
 */
extern int devname_readdir_func(vnode_t *, uio_t *, cred_t *, int *, int);

/*
 * flags for devname_readdir_func
 */
#define	SDEV_BROWSE	0x1	/* fetch all entries from backing store */

/*
 * devname_setattr_func()
 */
extern int devname_setattr_func(struct vnode *, struct vattr *, int,
    struct cred *, int (*)(struct sdev_node *, struct vattr *, int), int);
/*
 * devname_inactive_func()
 */
extern void devname_inactive_func(struct vnode *, struct cred *,
    void (*)(struct vnode *));

/*
 * /dev file system instance defines
 */
/*
 * /dev version of vfs_data
 */
struct sdev_data {
	struct sdev_data	*sdev_prev;
	struct sdev_data	*sdev_next;
	struct sdev_node	*sdev_root;
	struct vfs		*sdev_vfsp;
	struct sdev_mountargs	*sdev_mountargs;
	ulong_t			sdev_acl_flavor;
};

#define	VFSTOSDEVFS(vfsp)	((struct sdev_data *)((vfsp)->vfs_data))

/*
 * sdev_fid overlays the fid structure (for VFS_VGET)
 */
struct sdev_fid {
	uint16_t	sdevfid_len;
	ino32_t		sdevfid_ino;
	int32_t		sdevfid_gen;
};

/*
 * devfsadm and devname communication defines
 */
typedef enum {
	DEVNAME_DEVFSADM_STOPPED = 0,	/* devfsadm has never run */
	DEVNAME_DEVFSADM_RUNNING,	/* devfsadm is running */
	DEVNAME_DEVFSADM_RUN		/* devfsadm ran once */
} devname_devfsadm_state_t;

extern volatile uint_t  devfsadm_state; /* atomic mask for devfsadm status */

#define	DEVNAME_DEVFSADM_SET_RUNNING(devfsadm_state)	\
	(devfsadm_state = DEVNAME_DEVFSADM_RUNNING)
#define	DEVNAME_DEVFSADM_SET_STOP(devfsadm_state)	\
	(devfsadm_state = DEVNAME_DEVFSADM_STOPPED)
#define	DEVNAME_DEVFSADM_SET_RUN(devfsadm_state)	\
	(devfsadm_state = DEVNAME_DEVFSADM_RUN)
#define	DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)	\
	(devfsadm_state == DEVNAME_DEVFSADM_RUNNING)
#define	DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)	\
	(devfsadm_state == DEVNAME_DEVFSADM_RUN)

#define	SDEV_BLOCK_OTHERS(dv, cmd)	{	\
	ASSERT(MUTEX_HELD(&dv->sdev_lookup_lock));	\
	dv->sdev_lookup_flags |= cmd;			\
}
extern void sdev_unblock_others(struct sdev_node *, uint_t);
#define	SDEV_UNBLOCK_OTHERS(dv, cmd)	{	\
	sdev_unblock_others(dv, cmd);		\
}

#define	SDEV_CLEAR_LOOKUP_FLAGS(dv, cmd)	{	\
	dv->sdev_lookup_flags &= ~cmd;	\
}

extern int sdev_wait4lookup(struct sdev_node *, int);
extern int devname_filename_register(char *);
extern int devname_nsmaps_register(char *, size_t);
extern void sdev_devfsadm_lockinit(void);
extern void sdev_devfsadm_lockdestroy(void);
extern void devname_add_devfsadm_node(char *);
extern void sdev_devfsadmd_thread(struct sdev_node *, struct sdev_node *,
    struct cred *);
extern int devname_profile_update(char *, size_t);
extern struct sdev_data *sdev_find_mntinfo(char *);
void sdev_mntinfo_rele(struct sdev_data *);
typedef void (*sdev_mnt_walk_f)(struct sdev_node *, void *);
void sdev_mnt_walk(sdev_mnt_walk_f, void *);
extern struct vnodeops *devpts_getvnodeops(void);
extern struct vnodeops *devvt_getvnodeops(void);
extern void sdev_plugin_nodeready(struct sdev_node *);
extern int sdev_plugin_init(void);
extern int sdev_plugin_fini(void);

/*
 * boot states - warning, the ordering here is significant
 *
 * the difference between "system available" and "boot complete"
 * is a debounce timeout to catch some daemon issuing a readdir
 * triggering a nuisance implict reconfig on each boot.
 */
#define	SDEV_BOOT_STATE_INITIAL		0
#define	SDEV_BOOT_STATE_RECONFIG	1	/* reconfig */
#define	SDEV_BOOT_STATE_SYSAVAIL	2	/* system available */
#define	SDEV_BOOT_STATE_COMPLETE	3	/* boot complete */

/*
 * Negative cache list and list element
 * The mutex protects the flags against multiple accesses and
 * must only be acquired when already holding the r/w lock.
 */
typedef struct sdev_nc_list {
	list_t		ncl_list;	/* the list itself */
	kmutex_t	ncl_mutex;	/* protects ncl_flags */
	krwlock_t	ncl_lock;	/* protects ncl_list */
	int		ncl_flags;
	int		ncl_nentries;
} sdev_nc_list_t;

typedef struct sdev_nc_node {
	char		*ncn_name;	/* name of the node */
	int		ncn_flags;	/* state information */
	int		ncn_expirecnt;	/* remove once expired */
	list_node_t	ncn_link;	/* link to next in list */
} sdev_nc_node_t;

/* ncl_flags */
#define	NCL_LIST_DIRTY		0x01	/* needs to be flushed */
#define	NCL_LIST_WRITING	0x02	/* write in progress */
#define	NCL_LIST_WENABLE	0x04	/* write-enabled post boot */

/* ncn_flags */
#define	NCN_ACTIVE	0x01	/* a lookup has occurred */
#define	NCN_SRC_STORE	0x02	/* src: persistent store */
#define	NCN_SRC_CURRENT	0x04	/* src: current boot */

/* sdev_lookup_failed flags */
#define	SLF_NO_NCACHE	0x01	/* node should not be added to ncache */
#define	SLF_REBUILT	0x02	/* reconfig performed during lookup attempt */

/*
 * The nvlist name and nvpair identifiers in the
 * /etc/devices/devname_cache nvlist format
 */
#define	DP_DEVNAME_ID			"devname"
#define	DP_DEVNAME_NCACHE_ID		"ncache"
#define	DP_DEVNAME_NC_EXPIRECNT_ID	"expire-counts"

/* devname-cache list element */
typedef struct nvp_devname {
	char			**nvp_paths;
	int			*nvp_expirecnts;
	int			nvp_npaths;
	list_node_t		nvp_link;
} nvp_devname_t;

/*
 * name service globals and prototypes
 */

/*
 * vnodeops and vfsops helpers
 */

typedef enum {
	SDEV_CACHE_ADD = 0,
	SDEV_CACHE_DELETE
} sdev_cache_ops_t;

extern struct sdev_node *sdev_cache_lookup(struct sdev_node *, char *);
extern void sdev_cache_update(struct sdev_node *, struct sdev_node **, char *,
    sdev_cache_ops_t);
extern void sdev_node_cache_init(void);
extern void sdev_node_cache_fini(void);
extern struct sdev_node *sdev_mkroot(struct vfs *, dev_t, struct vnode *,
    struct vnode *, struct cred *);
extern void sdev_filldir_dynamic(struct sdev_node *);
extern int sdev_mknode(struct sdev_node *, char *, struct sdev_node **,
    struct vattr *, struct vnode *, void *, struct cred *, sdev_node_state_t);
extern int sdev_getlink(struct vnode *linkvp, char **link);

extern int sdev_nodeinit(struct sdev_node *, char *, struct sdev_node **,
    vattr_t *);
extern int sdev_nodeready(struct sdev_node *, vattr_t *, vnode_t *, void *,
    cred_t *);
extern int sdev_shadow_node(struct sdev_node *, struct cred *);
extern void sdev_nodedestroy(struct sdev_node *, uint_t);
extern void sdev_update_timestamps(struct vnode *, cred_t *, uint_t);
extern void sdev_vattr_merge(struct sdev_node *, struct vattr *);
extern void sdev_devstate_change(void);
extern int sdev_lookup_filter(sdev_node_t *, char *);
extern void sdev_lookup_failed(sdev_node_t *, char *, int);
extern int sdev_unlocked_access(void *, int, struct cred *);

#define	SDEV_ENFORCE	0x1
extern void sdev_stale(struct sdev_node *);
extern int sdev_cleandir(struct sdev_node *, char *, uint_t);
extern int sdev_rnmnode(struct sdev_node *, struct sdev_node *,
    struct sdev_node *, struct sdev_node **, char *, struct cred *);
extern size_t add_dir_entry(dirent64_t *, char *, size_t, ino_t, offset_t);
extern struct vattr *sdev_getdefault_attr(enum vtype type);
extern int sdev_to_vp(struct sdev_node *, struct vnode **);
extern ino_t sdev_mkino(struct sdev_node *);
extern int devname_backstore_lookup(struct sdev_node *, char *,
    struct vnode **);
extern int sdev_is_devfs_node(char *);
extern int sdev_copyin_mountargs(struct mounta *, struct sdev_mountargs *);
extern int sdev_reserve_subdirs(struct sdev_node *);
extern int prof_lookup();
extern void prof_filldir(struct sdev_node *);
extern int prof_name_matched(char *, struct sdev_node *);
extern int devpts_validate(struct sdev_node *dv);
extern int devnet_validate(struct sdev_node *dv);
extern int devipnet_validate(struct sdev_node *dv);
extern int devvt_validate(struct sdev_node *dv);
extern int devzvol_validate(struct sdev_node *dv);
extern void *sdev_get_vtor(struct sdev_node *dv);

/*
 * devinfo helpers
 */
extern int sdev_modctl_readdir(const char *, char ***, int *, int *, int);
extern void sdev_modctl_readdir_free(char **, int, int);
extern int sdev_modctl_devexists(const char *);

/*
 * ncache handlers
 */

extern void sdev_ncache_init(void);
extern void sdev_ncache_setup(void);
extern void sdev_ncache_teardown(void);
extern void sdev_nc_addname(sdev_nc_list_t *, sdev_node_t *, char *, int);
extern void sdev_nc_node_exists(sdev_node_t *);
extern void sdev_nc_path_exists(sdev_nc_list_t *, char *);
extern void sdev_modctl_dump_files(void);

/*
 * plugin and legacy vtab stuff
 */
/* directory dependent vop table */
typedef struct sdev_vop_table {
	char *vt_name;				/* subdirectory name */
	const fs_operation_def_t *vt_service;	/* vnodeops table */
	struct vnodeops **vt_global_vops;	/* global container for vop */
	int (*vt_vtor)(struct sdev_node *);	/* validate sdev_node */
	int vt_flags;
} sdev_vop_table_t;

extern struct sdev_vop_table vtab[];
extern struct vnodeops *sdev_get_vop(struct sdev_node *);
extern void sdev_set_no_negcache(struct sdev_node *);
extern void *sdev_get_vtor(struct sdev_node *dv);

/*
 * globals
 */
extern kmutex_t sdev_lock;
extern int devtype;
extern kmem_cache_t *sdev_node_cache;
extern struct vnodeops		*sdev_vnodeops;
extern struct vnodeops		*devpts_vnodeops;
extern struct vnodeops		*devnet_vnodeops;
extern struct vnodeops		*devipnet_vnodeops;
extern struct vnodeops		*devvt_vnodeops;
extern struct sdev_data *sdev_origins; /* mount info for global /dev instance */
extern struct vnodeops		*devzvol_vnodeops;
extern int			sdev_vnodeops_tbl_size;

extern const fs_operation_def_t	sdev_vnodeops_tbl[];
extern const fs_operation_def_t	devpts_vnodeops_tbl[];
extern const fs_operation_def_t	devnet_vnodeops_tbl[];
extern const fs_operation_def_t devipnet_vnodeops_tbl[];
extern const fs_operation_def_t	devvt_vnodeops_tbl[];
extern const fs_operation_def_t	devsys_vnodeops_tbl[];
extern const fs_operation_def_t	devpseudo_vnodeops_tbl[];
extern const fs_operation_def_t	devzvol_vnodeops_tbl[];

extern sdev_nc_list_t	*sdev_ncache;
extern int		sdev_reconfig_boot;
extern int		sdev_boot_state;
extern int		sdev_reconfig_verbose;
extern int		sdev_reconfig_disable;
extern int		sdev_nc_disable;
extern int		sdev_nc_disable_reset;
extern int		sdev_nc_verbose;

extern taskq_t		*sdev_taskq;

/*
 * misc. defines
 */
#ifdef DEBUG
extern int sdev_debug;
#define	SDEV_DEBUG		0x01	/* error messages to console/log */
#define	SDEV_DEBUG_VOPS 	0x02	/* vnode ops errors */
#define	SDEV_DEBUG_DLF		0x04	/* trace devname_lookup_func */
#define	SDEV_DEBUG_DRF		0x08	/* trace devname_readdir_func */
#define	SDEV_DEBUG_NCACHE	0x10	/* negative cache tracing */
#define	SDEV_DEBUG_DEVFSADMD	0x20	/* comm. of devnamefs & devfsadm */
#define	SDEV_DEBUG_PTS		0x40	/* /dev/pts tracing */
#define	SDEV_DEBUG_RECONFIG	0x80	/* events triggering reconfig */
#define	SDEV_DEBUG_SDEV_NODE	0x100	/* trace sdev_node activities */
#define	SDEV_DEBUG_PROFILE	0x200	/* trace sdev_profile */
#define	SDEV_DEBUG_MODCTL	0x400	/* trace modctl activity */
#define	SDEV_DEBUG_FLK		0x800	/* trace failed lookups */
#define	SDEV_DEBUG_NET		0x1000	/* /dev/net tracing */
#define	SDEV_DEBUG_ZVOL		0x2000	/* /dev/zvol/tracing */

#define	sdcmn_err(args)  if (sdev_debug & SDEV_DEBUG) printf args
#define	sdcmn_err2(args) if (sdev_debug & SDEV_DEBUG_VOPS) printf args
#define	sdcmn_err3(args) if (sdev_debug & SDEV_DEBUG_DLF) printf args
#define	sdcmn_err4(args) if (sdev_debug & SDEV_DEBUG_DRF) printf args
#define	sdcmn_err5(args) if (sdev_debug & SDEV_DEBUG_NCACHE) printf args
#define	sdcmn_err6(args) if (sdev_debug & SDEV_DEBUG_DEVFSADMD) printf args
#define	sdcmn_err7(args) if (sdev_debug & SDEV_DEBUG_PTS) printf args
#define	sdcmn_err8(args) if (sdev_debug & SDEV_DEBUG_RECONFIG) printf args
#define	sdcmn_err9(args) if (sdev_debug & SDEV_DEBUG_SDEV_NODE) printf args
#define	sdcmn_err10(args) if (sdev_debug & SDEV_DEBUG_PROFILE) printf args
#define	sdcmn_err11(args) if (sdev_debug & SDEV_DEBUG_MODCTL) printf args
#define	sdcmn_err12(args) if (sdev_debug & SDEV_DEBUG_NET) printf args
#define	sdcmn_err13(args) if (sdev_debug & SDEV_DEBUG_ZVOL) printf args
#define	impossible(args) printf args
#else
#define	sdcmn_err(args)		((void)0)
#define	sdcmn_err2(args)	((void)0)
#define	sdcmn_err3(args)	((void)0)
#define	sdcmn_err4(args)	((void)0)
#define	sdcmn_err5(args)	((void)0)
#define	sdcmn_err6(args)	((void)0)
#define	sdcmn_err7(args)	((void)0)
#define	sdcmn_err8(args)	((void)0)
#define	sdcmn_err9(args)	((void)0)
#define	sdcmn_err10(args)	((void)0)
#define	sdcmn_err11(args)	((void)0)
#define	sdcmn_err12(args)	((void)0)
#define	sdcmn_err13(args)	((void)0)
#define	impossible(args)	((void)0)
#endif

#ifdef DEBUG
#define	SD_TRACE_FAILED_LOOKUP(ddv, nm, retried)			\
	if ((sdev_debug & SDEV_DEBUG_FLK) ||				\
	    ((retried) && (sdev_debug & SDEV_DEBUG_RECONFIG))) {	\
		printf("lookup of %s/%s by %s failed, line %d\n",	\
		    (ddv)->sdev_name, (nm), curproc->p_user.u_comm,	\
		    __LINE__);						\
	}
#else
#define	SD_TRACE_FAILED_LOOKUP(ddv, nm, retried)	((void)0)
#endif

#endif	/* _KERNEL */

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_SDEV_IMPL_H */
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright (c) 2018, Joyent, Inc.
 */

#ifndef _SYS_SDEV_PLUGIN_H
#define	_SYS_SDEV_PLUGIN_H

/*
 * Kernel sdev plugin interface
 */

#ifdef _KERNEL

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vnode.h>

#endif	/* _KERNEL */

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _KERNEL

typedef uintptr_t sdev_plugin_hdl_t;
typedef uintptr_t sdev_ctx_t;

/*
 * Valid return values for sdev_plugin_validate_t.
 */
typedef enum sdev_plugin_validate {
	SDEV_VTOR_INVALID = -1,
	SDEV_VTOR_SKIP = 0,
	SDEV_VTOR_VALID	= 1,
	SDEV_VTOR_STALE	= 2
} sdev_plugin_validate_t;

/*
 * Valid flags
 */
typedef enum sdev_plugin_flags {
	SDEV_PLUGIN_NO_NCACHE = 0x1,
	SDEV_PLUGIN_SUBDIR = 0x2
} sdev_plugin_flags_t;

#define	SDEV_PLUGIN_FLAGS_MASK	0x3

/*
 * Functions a module must implement
 */
typedef sdev_plugin_validate_t (*sp_valid_f)(sdev_ctx_t);
typedef int (*sp_filldir_f)(sdev_ctx_t);
typedef void (*sp_inactive_f)(sdev_ctx_t);

#define	SDEV_PLUGIN_VERSION	1

typedef struct sdev_plugin_ops {
	int spo_version;
	sdev_plugin_flags_t spo_flags;
	sp_valid_f spo_validate;
	sp_filldir_f spo_filldir;
	sp_inactive_f spo_inactive;
} sdev_plugin_ops_t;

extern sdev_plugin_hdl_t sdev_plugin_register(const char *, sdev_plugin_ops_t *,
    int *);
extern int sdev_plugin_unregister(sdev_plugin_hdl_t);

typedef enum sdev_ctx_flags {
	SDEV_CTX_GLOBAL = 0x2	/* node belongs to the GZ */
} sdev_ctx_flags_t;

/*
 * Context helper functions
 */
extern sdev_ctx_flags_t sdev_ctx_flags(sdev_ctx_t);
extern const char *sdev_ctx_name(sdev_ctx_t);
extern const char *sdev_ctx_path(sdev_ctx_t);
extern int sdev_ctx_minor(sdev_ctx_t, minor_t *);
extern enum vtype sdev_ctx_vtype(sdev_ctx_t);

/*
 * Callbacks to manipulate nodes
 */
extern int sdev_plugin_mkdir(sdev_ctx_t, char *);
extern int sdev_plugin_mknod(sdev_ctx_t, char *, mode_t, dev_t);

#endif	/* _KERNEL */

#ifdef __cplusplus
}
#endif

#endif /* _SYS_SDEV_PLUGIN_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SMBFS_IOCTL_H
#define	_SMBFS_IOCTL_H

/*
 * Project private IOCTL interface provided by SMBFS.
 */

#include <sys/ioccom.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct ioc_sdbuf {
	uint64_t addr;		/* buffer address (user space) */
	uint32_t alloc;		/* allocated length */
	uint32_t used;		/* content length */
	uint32_t selector;	/* i.e. DACL_SECURITY_INFORMATION */
} ioc_sdbuf_t;

/*
 * SMBFS ioctl codes
 *
 * We only need a couple of these, so (re)using some
 * FS-specific ioctl codes from sys/filio.h
 * Data for both is ioc_sdbuf_t
 */

#define	SMBFSIO_GETSD		_IO('f', 81)
#define	SMBFSIO_SETSD		_IO('f', 82)

#ifdef __cplusplus
}
#endif

#endif /* _SMBFS_IOCTL_H */
/*
 * Copyright (c) 2000-2001, Boris Popov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *	notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *	notice, this list of conditions and the following disclaimer in the
 *	documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *	must display the following acknowledgement:
 *	This product includes software developed by Boris Popov.
 * 4. Neither the name of the author nor the names of any co-contributors
 *	may be used to endorse or promote products derived from this software
 *	without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Id: smbfs.h,v 1.30.100.1 2005/05/27 02:35:28 lindak Exp $
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SMBFS_MOUNT_H
#define	_SMBFS_MOUNT_H

/*
 * This file defines the interface used by mount_smbfs.
 * Some of this came from the Darwin file:
 *   smb-217.2/kernel/fs/smbfs/smbfs.h
 */

#define	SMBFS_VERMAJ	1
#define	SMBFS_VERMIN	3300
#define	SMBFS_VERSION	(SMBFS_VERMAJ*100000 + SMBFS_VERMIN)
#define	SMBFS_VER_STR	"1.33"

#define	SMBFS_VFSNAME	"smbfs"

/* Additions not in mntent.h */
#define	MNTOPT_ACL	"acl"		/* enable smbfs ACLs */
#define	MNTOPT_NOACL	"noacl"		/* disable smbfs ACLs */

/* Values for smbfs_args.flags */
#define	SMBFS_MF_SOFT		0x0001
#define	SMBFS_MF_INTR		0x0002
#define	SMBFS_MF_NOAC		0x0004
#define	SMBFS_MF_ACREGMIN	0x0100	/* set min secs for file attr cache */
#define	SMBFS_MF_ACREGMAX	0x0200	/* set max secs for file attr cache */
#define	SMBFS_MF_ACDIRMIN	0x0400	/* set min secs for dir attr cache */
#define	SMBFS_MF_ACDIRMAX	0x0800	/* set max secs for dir attr cache */

/* Layout of the mount control block for an smb file system. */
struct smbfs_args {
	int		version;		/* smbfs mount version */
	int		devfd;			/* file descriptor */
	uint_t		flags;			/* SMBFS_MF_ flags */
	uid_t		uid;			/* octal user id */
	gid_t		gid;			/* octal group id */
	mode_t		file_mode;		/* octal srwx for files */
	mode_t		dir_mode;		/* octal srwx for dirs */
	int		acregmin;		/* attr cache file min secs */
	int		acregmax;		/* attr cache file max secs */
	int		acdirmin;		/* attr cache dir min secs */
	int		acdirmax;		/* attr cache dir max secs */
};

#ifdef _SYSCALL32

/* Layout of the mount control block for an smb file system. */
struct smbfs_args32 {
	int32_t		version;		/* smbfs mount version */
	int32_t		devfd;			/* file descriptor */
	uint32_t	flags;			/* SMBFS_MF_ flags */
	uid32_t		uid;			/* octal user id */
	gid32_t		gid;			/* octal group id */
	mode32_t	file_mode;		/* octal srwx for files */
	mode32_t	dir_mode;		/* octal srwx for dirs */
	int32_t		acregmin;		/* attr cache file min secs */
	int32_t		acregmax;		/* attr cache file max secs */
	int32_t		acdirmin;		/* attr cache dir min secs */
	int32_t		acdirmax;		/* attr cache dir max secs */
};

#endif /* _SYSCALL32 */
#endif	/* _SMBFS_MOUNT_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/


/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_SNODE_H
#define	_SYS_FS_SNODE_H

#include <sys/types.h>
#include <sys/t_lock.h>
#include <sys/cred.h>
#include <sys/vnode.h>

/*
 * The snode represents a special file in any filesystem.  There is
 * one snode for each active special file.  Filesystems that support
 * special files use specvp(vp, dev, type, cr) to convert a normal
 * vnode to a special vnode in the ops lookup() and create().
 *
 * To handle having multiple snodes that represent the same
 * underlying device vnode without cache aliasing problems,
 * the s_commonvp is used to point to the "common" vnode used for
 * caching data.  If an snode is created internally by the kernel,
 * then the s_realvp field is NULL and s_commonvp points to s_vnode.
 * The other snodes which are created as a result of a lookup of a
 * device in a file system have s_realvp pointing to the vp which
 * represents the device in the file system while the s_commonvp points
 * into the "common" vnode for the device in another snode.
 */

/*
 * Include SUNDDI type definitions so that the s_dip tag doesn't urk.
 */
#include <sys/dditypes.h>

#ifdef	__cplusplus
extern "C" {
#endif

struct snode {
	/* These fields are protected by stable_lock */
	struct	snode *s_next;		/* must be first */
	struct	vnode *s_vnode;		/* vnode associated with this snode */
	/*
	 * These fields are initialized once.
	 */
	struct	vnode *s_realvp;	/* vnode for the fs entry (if any) */
	struct	vnode *s_commonvp;	/* common device vnode */
	dev_t	s_dev;			/* device the snode represents */
	dev_info_t *s_dip;		/* dev_info (common snode only) */
	/*
	 * Doesn't always need to be updated atomically because it is a hint.
	 * No lock required.
	 */
	u_offset_t s_nextr;		/* next byte read offset (read-ahead) */

	/* These fields are protected by spec_syncbusy */
	struct	snode *s_list;		/* used for syncing */
	/* These fields are protected by s_lock */
	struct devplcy *s_plcy;		/* device node open policy (cs only) */
	u_offset_t s_size;		/* block device size in bytes */
	uint_t	s_flag;			/* flags, see below */
	dev_t	s_fsid;			/* file system identifier */
	time_t  s_atime;		/* time of last access */
	time_t  s_mtime;		/* time of last modification */
	time_t  s_ctime;		/* time of last attributes change */
	int	s_count;		/* count of opened references */
	long	s_mapcnt;		/* count of mappings of pages */
	/* The locks themselves */
	kmutex_t	s_lock;		/* protects snode fields */
	kcondvar_t	s_cv;		/* synchronize open/closes */
};

/* flags */
#define	SUPD		0x01		/* update device access time */
#define	SACC		0x02		/* update device modification time */
#define	SCHG		0x04		/* update device change time */
#define	SPRIV		0x08		/* file open for private access */
#define	SLOFFSET	0x10		/* device takes 64-bit uio offsets */
#define	SLOCKED		0x20		/* use to serialize open/closes */
#define	SWANT		0x40		/* some process waiting on lock */
#define	SANYOFFSET	0x80		/* device takes any uio offset */
#define	SCLONE		0x100		/* represents a cloned device */
#define	SNEEDCLOSE	0x200		/* needs driver close call */
#define	SDIPSET		0x400		/* the vnode has an association with */
					/* the driver, even though it may */
					/* not currently have an association */
					/* with a specific hardware instance */
					/* if s_dip is NULL */
#define	SSIZEVALID	0x800		/* s_size field is valid */
#define	SMUXED		0x1000		/* this snode is a stream that has */
					/* been multiplexed */
#define	SSELFCLONE	0x2000		/* represents a self cloning device */
#define	SNOFLUSH	0x4000		/* do not flush device on fsync */
#define	SCLOSING	0x8000		/* in last close(9E) */
#define	SFENCED		0x10000		/* snode fenced off for I/O retire */

#ifdef _KERNEL
/*
 * Convert between vnode and snode
 */
#define	VTOS(vp)	((struct snode *)((vp)->v_data))
#define	VTOCS(vp)	(VTOS(VTOS(vp)->s_commonvp))
#define	STOV(sp)	((sp)->s_vnode)

extern int spec_debug;

#define	SPEC_FENCE_DEBUG	0x0001	/* emit fence related debug messages */

#define	FENDBG(args)	if (spec_debug & SPEC_FENCE_DEBUG) cmn_err args


/*
 * Forward declarations
 */
struct vfssw;
struct cred;

extern struct vfs	spec_vfs;
extern struct vfsops	spec_vfsops;
extern struct kmem_cache *snode_cache;

/*
 * specfs functions
 */
offset_t	spec_maxoffset(struct vnode *);
struct vnodeops	*spec_getvnodeops(void);
struct vnode *specvp(struct vnode *, dev_t, vtype_t, struct cred *);
struct vnode *makespecvp(dev_t, vtype_t);
struct vnode *other_specvp(struct vnode *);
struct vnode *common_specvp(struct vnode *);
struct vnode *specfind(dev_t, vtype_t);
struct vnode *commonvp(dev_t, vtype_t);
struct vnode *makectty(vnode_t *);
void	sdelete(struct snode *);
void 	smark(struct snode *, int);
int	specinit(int, char *);
int	device_close(struct vnode *, int, struct cred *);
int	spec_putpage(struct vnode *, offset_t, size_t, int, struct cred *,
		caller_context_t *);
int	spec_segmap(dev_t, off_t, struct as *, caddr_t *, off_t,
		    uint_t, uint_t, uint_t, cred_t *);
struct vnode *specvp_devfs(struct vnode *, dev_t, vtype_t,
		    struct cred *, dev_info_t *);
void	spec_assoc_vp_with_devi(struct vnode *, dev_info_t *);
dev_info_t *spec_hold_devi_by_vp(struct vnode *);
int	spec_sync(struct vfs *, short, struct cred *);
void	spec_snode_walk(int (*callback)(struct snode *, void *), void *);
int	spec_devi_open_count(struct snode *, dev_info_t **);
int	spec_is_clone(struct vnode *);
int	spec_is_selfclone(struct vnode *);
int	spec_fence_snode(dev_info_t *dip, struct vnode *vp);
int	spec_unfence_snode(dev_info_t *dip);
void	spec_size_invalidate(dev_t, vtype_t);


/*
 * UNKNOWN_SIZE: If driver does not support the [Ss]ize or [Nn]blocks property
 * then the size is assumed to be "infinite".  Note that this "infinite" value
 * may need to be converted to a smaller "infinite" value to avoid EOVERFLOW at
 * field width conversion locations like the stat(2) and NFS code running
 * against a special file.  Special file code outside specfs may check the
 * type of the vnode (VCHR|VBLK) and use MAXOFFSET_T directly to detect
 * UNKNOWN_SIZE.
 */
#define	UNKNOWN_SIZE		MAXOFFSET_T

/*
 * SPEC_MAXOFFSET_T: Solaris does not fully support 64-bit offsets for D_64BIT
 * (SLOFFSET) block drivers on a 32-bit kernels: daddr_t is still a signed
 * 32-bit quantity - which limits the byte offset to 1TB. This issue goes
 * beyond a driver needing to convert from daddr_t to diskaddr_t if it sets
 * D_64BIT. Many of the DDI interfaces which take daddr_t arguments have no
 * 64-bit counterpart (bioclone, blkflush, bread, bread_common, breada, getblk,
 * getblk_common). SPEC_MAXOFFSET_T is used by 32-bit kernel code to enforce
 * this restriction.
 */
#ifdef	_ILP32
#ifdef	_LONGLONG_TYPE
#define	SPEC_MAXOFFSET_T	((1LL << ((NBBY * sizeof (daddr32_t)) +	\
				DEV_BSHIFT - 1)) - 1)
#else	/* !defined(_LONGLONG_TYPE) */
#define	SPEC_MAXOFFSET_T	MAXOFF_T
#endif	/* _LONGLONG_TYPE */
#endif	/* _ILP32 */

/*
 * Snode lookup stuff.
 * These routines maintain a table of snodes hashed by dev so
 * that the snode for an dev can be found if it already exists.
 * NOTE: STABLESIZE must be a power of 2 for STABLEHASH to work!
 */

#define	STABLESIZE	256
#define	STABLEHASH(dev)	((getmajor(dev) + getminor(dev)) & (STABLESIZE - 1))
extern struct snode *stable[];
extern kmutex_t	stable_lock;
extern kmutex_t	spec_syncbusy;

/*
 * Variables used by during asynchronous VOP_PUTPAGE operations.
 */
extern struct async_reqs *spec_async_reqs;	/* async request list */
extern kmutex_t spec_async_lock;		/* lock to protect async list */

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_SNODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/


#ifndef	_SYS_FS_SWAPNODE_H
#define	_SYS_FS_SWAPNODE_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * pointer to swapfs global data structures
 */
extern pgcnt_t swapfs_minfree;		/* amount of availrmem (in pages) */
					/* that is unavailable to swapfs */
extern pgcnt_t swapfs_desfree;

extern pgcnt_t swapfs_reserve;		/* amount of availrmem (in pages) */
					/* that is unavailable for swap */
					/* reservation to non-priv processes */

extern struct vnodeops *swap_vnodeops;
extern struct vnode *swapfs_getvp(ulong_t);

#ifdef SWAPFS_DEBUG
extern int swapfs_debug;
#define	SWAPFS_PRINT(X, S, Y1, Y2, Y3, Y4, Y5)	\
	if (swapfs_debug & (X)) 		\
		printf(S, Y1, Y2, Y3, Y4, Y5);
#define	SWAP_SUBR	0x01
#define	SWAP_VOPS	0x02
#define	SWAP_VFSOPS	0x04
#define	SWAP_PGC		0x08
#define	SWAP_PUTP	0x10
#else	/* SWAPFS_DEBUG */
#define	SWAPFS_PRINT(X, S, Y1, Y2, Y3, Y4, Y5)
#endif	/* SWAPFS_DEBUG */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_SWAPNODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2007 Sun Microsystems, Inc.
 * All rights reserved.  Use is subject to license terms.
 */
/*
 * Copyright 2015 Joyent, Inc.
 */

#ifndef	_SYS_FS_TMP_H
#define	_SYS_FS_TMP_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * tmpfs per-mount data structure.
 *
 * All fields are protected by tm_contents.
 * File renames on a particular file system are protected tm_renamelck.
 */
struct tmount {
	struct vfs	*tm_vfsp;	/* filesystem's vfs struct */
	struct tmpnode	*tm_rootnode;	/* root tmpnode */
	char 		*tm_mntpath;	/* name of tmpfs mount point */
	ulong_t		tm_anonmax;	/* file system max anon reservation */
	pgcnt_t		tm_anonmem;	/* pages of reserved anon memory */
	dev_t		tm_dev;		/* unique dev # of mounted `device' */
	uint_t		tm_gen;		/* pseudo generation number for files */
	kmutex_t	tm_contents;	/* lock for tmount structure */
	kmutex_t	tm_renamelck;	/* rename lock for this mount */
};

/*
 * File system independent to tmpfs conversion macros
 */
#define	VFSTOTM(vfsp)		((struct tmount *)(vfsp)->vfs_data)
#define	VTOTM(vp)		((struct tmount *)(vp)->v_vfsp->vfs_data)
#define	VTOTN(vp)		((struct tmpnode *)(vp)->v_data)
#define	TNTOV(tp)		((tp)->tn_vnode)
#define	tmpnode_hold(tp)	VN_HOLD(TNTOV(tp))
#define	tmpnode_rele(tp)	VN_RELE(TNTOV(tp))

/*
 * enums
 */
enum de_op	{ DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME }; /* direnter ops */
enum dr_op	{ DR_REMOVE, DR_RMDIR, DR_RENAME };	/* dirremove ops */

/*
 * tmpfs_minfree is the amount (in pages) of anonymous memory that tmpfs
 * leaves free for the rest of the system.  E.g. in a system with 32MB of
 * configured swap space, if 16MB were reserved (leaving 16MB free),
 * tmpfs could allocate up to 16MB - tmpfs_minfree.  The default value
 * for tmpfs_minfree is btopr(TMPMINFREE) but it can cautiously patched
 * to a different number of pages.
 * NB: If tmpfs allocates too much swap space, other processes will be
 * unable to execute.
 */
#define	TMPMINFREE	2 * 1024 * 1024	/* 2 Megabytes */

extern size_t	tmpfs_minfree;		/* Anonymous memory in pages */

/*
 * tmpfs can allocate only a certain percentage of kernel memory,
 * which is used for tmpnodes, directories, file names, etc.
 * This is statically set as TMPMAXFRACKMEM of physical memory.
 * The actual number of allocatable bytes can be patched in tmpfs_maxkmem.
 */
#define	TMPMAXFRACKMEM	25	/* 1/25 of physical memory */

extern size_t 	tmp_kmemspace;
extern size_t	tmpfs_maxkmem;	/* Allocatable kernel memory in bytes */

extern	void	tmpnode_init(struct tmount *, struct tmpnode *,
	struct vattr *, struct cred *);
extern	int	tmpnode_trunc(struct tmount *, struct tmpnode *, ulong_t);
extern	void	tmpnode_growmap(struct tmpnode *, ulong_t);
extern	int	tdirlookup(struct tmpnode *, char *, struct tmpnode **,
    struct cred *);
extern	int	tdirdelete(struct tmpnode *, struct tmpnode *, char *,
	enum dr_op, struct cred *);
extern	void	tdirinit(struct tmpnode *, struct tmpnode *);
extern	void	tdirtrunc(struct tmpnode *);
extern	void	*tmp_memalloc(size_t, int);
extern	void	tmp_memfree(void *, size_t);
extern	int	tmp_resv(struct tmount *, struct tmpnode *, size_t, int);
extern	int	tmp_taccess(void *, int, struct cred *);
extern	int	tmp_sticky_remove_access(struct tmpnode *, struct tmpnode *,
	struct cred *);
extern	int	tmp_convnum(char *, pgcnt_t *);
extern	int	tmp_convmode(char *, mode_t *);
extern	int	tdirenter(struct tmount *, struct tmpnode *, char *,
	enum de_op, struct tmpnode *, struct tmpnode *, struct vattr *,
	struct tmpnode **, struct cred *, caller_context_t *);

#define	TMP_MUSTHAVE	0x01

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_TMP_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_FS_TMPNODE_H
#define	_SYS_FS_TMPNODE_H

#include <sys/t_lock.h>
#include <vm/seg.h>
#include <vm/seg_vn.h>
#include <sys/vfs_opreg.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * tmpnode is the file system dependent node for tmpfs.
 *
 *	tn_rwlock protects access of the directory list at tn_dir
 *	as well as syncronizing read and writes to the tmpnode
 *
 *	tn_contents protects growing, shrinking, reading and writing
 *	the file along with tn_rwlock (see below).
 *
 *	tn_tlock protects updates to tn_mode and tn_nlink
 *
 *	tm_contents in the tmount filesystem data structure protects
 *	tn_forw and tn_back which are used to maintain a linked
 *	list of all tmpfs files associated with that file system
 *
 *	The anon array represents the secondary store for tmpfs.
 * 	To grow or shrink the file or fill in holes requires
 *	manipulation of the anon array. These operations are protected
 *	by a combination of tn_rwlock and tn_contents. Growing or shrinking
 * 	the array requires the write lock on tn_rwlock and tn_contents.
 *	Filling in a slot in the array requires the write lock on tn_contents.
 *	Reading the array requires the read lock on tn_contents.
 *
 *	The ordering of the locking is:
 *	tn_rwlock -> tn_contents -> page locks on pages in file
 *
 *	tn_tlock doesn't require any tmpnode locks
 */

struct tmpnode {
	struct tmpnode	*tn_back;		/* linked list of tmpnodes */
	struct tmpnode	*tn_forw;		/* linked list of tmpnodes */
	union {
		struct {
			struct tdirent	*un_dirlist; /* dirent list */
			uint_t	un_dirents;	/* number of dirents */
		} un_dirstruct;
		char 		*un_symlink;	/* pointer to symlink */
		struct {
			struct anon_hdr	*un_anon; /* anon backing for file */
			pgcnt_t	un_size;	/* size repres. by array */
		} un_anonstruct;
	} un_tmpnode;
	struct vnode 	*tn_vnode;		/* vnode for this tmpnode */
	int 		tn_gen;			/* pseudo gen number for tfid */
	struct vattr	tn_attr;		/* attributes */
	krwlock_t	tn_contents;		/* vm side -serialize mods */
	krwlock_t	tn_rwlock;		/* rw,trunc size - serialize */
						/* mods and directory updates */
	kmutex_t	tn_tlock;		/* time, flag, and nlink lock */
	struct tmpnode *tn_xattrdp;		/* ext. attribute directory */
	uint_t		tn_flags;		/* tmpnode specific flags */
};

#define	tn_dir		un_tmpnode.un_dirstruct.un_dirlist
#define	tn_dirents	un_tmpnode.un_dirstruct.un_dirents
#define	tn_symlink	un_tmpnode.un_symlink
#define	tn_anon		un_tmpnode.un_anonstruct.un_anon
#define	tn_asize	un_tmpnode.un_anonstruct.un_size

/*
 * tmnode flag values.
 */
#define	ISXATTR		0x1

/*
 * Attributes
 */
#define	tn_mask		tn_attr.va_mask
#define	tn_type		tn_attr.va_type
#define	tn_mode		tn_attr.va_mode
#define	tn_uid		tn_attr.va_uid
#define	tn_gid		tn_attr.va_gid
#define	tn_fsid		tn_attr.va_fsid
#define	tn_nodeid	tn_attr.va_nodeid
#define	tn_nlink	tn_attr.va_nlink
#define	tn_size		tn_attr.va_size
#define	tn_atime	tn_attr.va_atime
#define	tn_mtime	tn_attr.va_mtime
#define	tn_ctime	tn_attr.va_ctime
#define	tn_rdev		tn_attr.va_rdev
#define	tn_blksize	tn_attr.va_blksize
#define	tn_nblocks	tn_attr.va_nblocks
#define	tn_seq		tn_attr.va_seq

/*
 * tmpfs directories are made up of a linked list of tdirent structures
 * hanging off directory tmpnodes.  File names are not fixed length,
 * but are null terminated.
 */
struct tdirent {
	struct tmpnode	*td_tmpnode;		/* tnode for this file */
	struct tdirent	*td_next;		/* next directory entry */
	struct tdirent	*td_prev;		/* prev directory entry */
	uint_t		td_offset;		/* "offset" of dir entry */
	uint_t		td_hash;		/* a hash of td_name */
	struct tdirent	*td_link;		/* linked via the hash table */
	struct tmpnode	*td_parent;		/* parent, dir we are in */
	char		*td_name;		/* must be null terminated */
						/* max length is MAXNAMELEN */
};

/*
 * tfid overlays the fid structure (for VFS_VGET)
 */
struct tfid {
	uint16_t tfid_len;
	ino32_t	tfid_ino;
	int32_t	tfid_gen;
};

#define	ESAME	(-1)		/* trying to rename linked files (special) */

extern struct vnodeops *tmp_vnodeops;
extern const struct fs_operation_def tmp_vnodeops_template[];

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_TMPNODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	All Rights Reserved */

#ifndef	_SYS_FS_UDF_INODE_H
#define	_SYS_FS_UDF_INODE_H

#include <sys/note.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	SUN_IMPL_ID	"*SUN SOLARIS UDF"
#define	SUN_IMPL_ID_LEN	16
#define	SUN_OS_CLASS	4
#define	SUN_OS_ID	2

/*
 * Size of each cluster
 * and bits to be shifted
 */
#define	CLSTR_SIZE	8
#define	CLSTR_MASK	7


/*
 * enums
 */
enum de_op { DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME };	/* direnter ops */
enum dr_op { DR_REMOVE, DR_RMDIR, DR_RENAME };		/* dirremove ops */

/*
 * The following macros optimize certain frequently calculated
 * quantities by using shifts and masks in place of divisions
 * modulos and multiplications.
 */

#define	blkoff(udfvfsp, loc)	/* calculates (loc % udfcfs->udf_lbsize) */ \
		((loc) & (udfvfsp)->udf_lbmask)

#define	lblkno(udf_vfsp, loc)	\
	((int32_t)((loc) / (udf_vfsp)->udf_lbsize))

#define	fsbtodb(udf, blk)	\
	((blk) << udf->udf_l2d_shift)


struct udf_fid {
	uint16_t	udfid_len;	/* Length of data */
	uint16_t	udfid_prn;	/* the partition number of icb */
	uint32_t	udfid_icb_lbn;	/* file entry block no */
	uint32_t	udfid_uinq_lo;	/* uniq id to validate the vnode */
};




#define	MAXNAMLEN	255




struct ud_part {
	uint16_t	udp_flags;	/* See below */
	uint16_t	udp_number;	/* partition Number */
	uint32_t	udp_seqno;	/* to find the prevailaing desc */
	uint32_t	udp_access;	/* access type */
	uint32_t	udp_start;	/* Starting block no of partition */
	uint32_t	udp_length;	/* Lenght of the partition */
	uint32_t	udp_unall_loc;	/* unall space tbl or bitmap loc */
	uint32_t	udp_unall_len;	/* unall space tbl or bitmap length */
	uint32_t	udp_freed_loc;	/* freed space tbl or bitmap loc */
	uint32_t	udp_freed_len;	/* freed space tbl or bitmap length */
					/* From part desc */

	uint32_t	udp_nfree;	/* No of free blocks in the partition */
	uint32_t	udp_nblocks;	/* Total no of blks in the partition */
					/* From lvid */
	uint32_t	udp_last_alloc;	/* Last allocated space in bitmap */

	int32_t		udp_cache_count;	/* Cache is used for metadata */
	daddr_t		udp_cache[CLSTR_SIZE];
};

/*
 * udp_flags
 */
#define	UDP_BITMAPS	0x00
#define	UDP_SPACETBLS	0x01

/*
 * udp_access
 */
#define	UDP_MT_RO	0x0001		/* ROM */
#define	UDP_MT_WO	0x0002		/* WORM */
#define	UDP_MT_RW	0x0003		/* RW */
#define	UDP_MT_OW	0x0004		/* OW */



#define	MAX_SPM		4

struct ud_map {
	uint32_t	udm_flags;	/* Flags */
	uint16_t	udm_vsn;	/* Volume Sequence Number */
	uint16_t	udm_pn;		/* Partition Number */
	uint32_t	udm_vat_icb;	/* VAT ICB location */
	uint32_t	udm_nent;	/* Number of vat entries */
	uint32_t	*udm_count;	/* Number of entrues in each table */
	struct buf	**udm_bp;	/* VAT translation tables */
	uint32_t	**udm_addr;


	int32_t		udm_plen;
	int32_t		udm_nspm;
	uint32_t	udm_spsz;
	uint32_t	udm_loc[MAX_SPM];
	struct buf	*udm_sbp[MAX_SPM];
	caddr_t		udm_spaddr[MAX_SPM];
};

/*
 * udm_flags
 */
#define	UDM_MAP_NORM	0x00
#define	UDM_MAP_VPM	0x01
#define	UDM_MAP_SPM	0x02

struct udf_vfs {
	struct vfs	*udf_vfs;	/* Back link */
	struct udf_vfs	*udf_next;	/* Chain of udf file-system's */
	struct udf_vfs	*udf_wnext;	/* work list link */

	struct buf	*udf_vds;	/* most of the superblock */
	struct buf	*udf_iseq;	/* Integrity of the fs */
	struct vnode	*udf_root;	/* Root vnode */
	struct vnode	*udf_devvp;	/* Block device vnode */

	char		*udf_fsmnt;	/* Path name of directory mouted on */
	uint32_t	udf_flags;	/* Flags */
	uint32_t	udf_mtype;	/* Media type */

	int32_t		udf_rdclustsz;	/* read cluster size */
	int32_t		udf_wrclustsz;	/* write cluster size */

	uint64_t	udf_maxfsize;	/* Max file size allowed in this fs */
	int32_t		udf_maxfbits;	/* No of bit's for max file size */

	char		udf_volid[32];	/* volume identifier */
					/* from pvd */
	uint16_t	udf_tsno;	/* Taken from pvd and */
					/* used in making tags */

	int32_t		udf_lbsize;	/* Block size */
					/* from lvd */
	int32_t		udf_lbmask;	/* udf_lbsize - 1 */
	int32_t		udf_l2b_shift;	/* lbsize to bytes */
	int32_t		udf_l2d_shift;	/* right shift's to */
					/* make lbsize to DEV_BSIZE */

	int32_t		udf_npart;	/* No. of partition's in the volume */
					/* restricted to 1 till udf 1.50 */
	struct ud_part	*udf_parts;	/* pointer to array of partitions */
					/* from part desc's */

	int32_t		udf_nmaps;
	struct ud_map	*udf_maps;

	int32_t		udf_fragmented;	/* File System fragmented */
	int32_t		udf_mark_bad;	/* force fsck at next mount */

	/*
	 * sum of udp_nfree and udp_nblocks
	 * from the array udf_parts[0] to udf_parts[udf_nparts - 1]
	 */
	uint32_t	udf_freeblks;	/* Total udf_lbsize Free Blocks */
	uint32_t	udf_totalblks;	/* Total number of Blocks */
				/* udf_parts[0].udp_nfree == udf_freespace */
				/* till udf 1.50 (DVD-R?) */
	uint64_t	udf_maxuniq;	/* Maximum unique ID on the fs */
	uint32_t	udf_nfiles;	/* No of files */
	uint32_t	udf_ndirs;	/* No of directories */
	uint32_t	udf_miread;	/* minimum read revision */
	uint32_t	udf_miwrite;	/* minimum write revision */
	uint32_t	udf_mawrite;	/* maximum read revision */
					/* from lvid */

	time_t		udf_time;	/* Last time super block is written */
	uint32_t	udf_mod;	/* file system was modified */
	uint32_t	udf_clean;	/* state of the file system */
	kmutex_t	udf_lock;	/* protects contents */

	kmutex_t	udf_rename_lck;	/* lock for udf_rename */

	/*
	 * Have them cached here for fast access
	 */
	struct pri_vol_desc	*udf_pvd;
	struct log_vol_desc	*udf_lvd;
	struct log_vol_int_desc *udf_lvid;

	uint32_t		udf_mvds_loc;
	uint32_t		udf_mvds_len;

	uint32_t		udf_rvds_loc;
	uint32_t		udf_rvds_len;

	uint32_t		udf_iseq_loc;
	uint32_t		udf_iseq_len;

	uint16_t		udf_fsd_prn;
	uint32_t		udf_fsd_loc;
	uint32_t		udf_fsd_len;

	uint16_t		udf_ricb_prn;
	uint32_t		udf_ricb_loc;
	uint32_t		udf_ricb_len;
	daddr_t			udf_root_blkno;
};


#ifndef	__lint
_NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock,
		udf_vfs::udf_fragmented))
_NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock,
		udf_vfs::udf_freeblks udf_vfs::udf_totalblks))
_NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock,
		udf_vfs::udf_maxuniq udf_vfs::udf_nfiles
		udf_vfs::udf_ndirs))
_NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock,
		udf_vfs::udf_time
		udf_vfs::udf_mod udf_vfs::udf_clean))

_NOTE(READ_ONLY_DATA(udf_vfs::udf_nmaps udf_vfs::udf_maps))

_NOTE(READ_ONLY_DATA(udf_vfs::udf_mtype
		udf_vfs::udf_rdclustsz
		udf_vfs::udf_wrclustsz
		udf_vfs::udf_maxfsize
		udf_vfs::udf_maxfbits
		udf_vfs::udf_lbsize
		udf_vfs::udf_l2b_shift
		udf_vfs::udf_lbmask
		udf_vfs::udf_l2d_shift))

_NOTE(READ_ONLY_DATA(udf_vfs::udf_pvd
		udf_vfs::udf_lvd
		udf_vfs::udf_lvid))

_NOTE(READ_ONLY_DATA(udf_vfs::udf_mvds_loc
		udf_vfs::udf_mvds_len
		udf_vfs::udf_iseq_loc
		udf_vfs::udf_iseq_len
		udf_vfs::udf_fsd_prn
		udf_vfs::udf_fsd_loc
		udf_vfs::udf_fsd_len
		udf_vfs::udf_ricb_prn
		udf_vfs::udf_ricb_loc
		udf_vfs::udf_ricb_len
		udf_vfs::udf_root_blkno))

_NOTE(READ_ONLY_DATA(ud_part::udp_flags
		ud_part::udp_number
		ud_part::udp_seqno
		ud_part::udp_access
		ud_part::udp_start
		ud_part::udp_length
		ud_part::udp_unall_loc
		ud_part::udp_unall_len
		ud_part::udp_freed_loc
		ud_part::udp_freed_len
		ud_part::udp_nblocks))

_NOTE(MUTEX_PROTECTS_DATA(udf_vfs::udf_lock,
		ud_part::udp_nfree
		ud_part::udp_last_alloc
		ud_part::udp_cache_count
		ud_part::udp_cache))
#endif

/*
 * udf_mtype
 */
#define	UDF_MT_RO	UDP_MT_RO		/* ROM */
#define	UDF_MT_WO	UDP_MT_OW		/* WORM */
#define	UDF_MT_RW	UDP_MT_RW		/* RW */
#define	UDF_MT_OW	UDP_MT_OW		/* OW */

/*
 * udf_flags
 */
#define	UDF_FL_RDONLY	0x0001		/* file system is read only */
#define	UDF_FL_RW	0x0002		/* file system is read write */

/*
 * udf_clean
 */
#define	UDF_DIRTY	0x00
#define	UDF_CLEAN	0x01


#define	RD_CLUSTSZ(ip)		((ip)->i_udf->udf_rdclustsz)
#define	WR_CLUSTSZ(ip)		((ip)->i_udf->udf_wrclustsz)

/*
 * Size can be a 64-bit value and therefore we sign extend fs_bmask
 * to a 64-bit value too so that the higher 32 bits are masked
 * properly. Note that the type of fs_bmask has to be signed. Otherwise
 * compiler will set the higher 32 bits as zero and we don't want
 * this to happen.
 */

#ifdef	UNDEF
#define	blkroundup(fs, size)	/* calculates roundup(size, fs->fs_bsize) */ \
	(((size) + (fs)->udf_lbsize - 1) & (offset_t)(fs)->udf_lbmask)
#endif

#define	blkroundup(fs, size)	/* calculates roundup(size, fs->fs_bsize) */ \
	(((size) + (fs)->udf_lbmask) & (offset_t)(~(fs)->udf_lbmask))

#define	blksize(fs)	(fs->udf_lbsize)


/*
 * Convert between inode pointers and vnode pointers
 */
#define	VTOI(VP)	((struct ud_inode *)(VP)->v_data)
#define	ITOV(IP)	((IP)->i_vnode)
#define	i_vfs		i_vnode->v_vfsp

struct icb_ext {
	uint16_t	ib_flags;

	/* Direct Entry will go here */
	uint16_t	ib_prn;		/* partition reference number */
	uint32_t	ib_block;	/* block offset into partition */
	uint64_t	ib_offset;	/* offset into the file bytes */
	int32_t		ib_count;	/* No of bytes in current ext */
	uint32_t	ib_marker1;	/* 0xAAAAAAAA */
	uint32_t	ib_marker2;	/* 0xBBBBBBBB */
};


/* ib_flags */
#define	IB_UN_REC	0x1		/* The entry is not allocated */
#define	IB_UN_RE_AL	0x2		/* The entry is not recorded */
					/* and not unallocated */
#define	IB_CON		0x3		/* Continuation entry */

#define	IB_MASK		0x3

#define	IB_ALLOCATED(flags)	\
	(((flags) & IB_MASK) != IB_UN_RE_AL)

#define	EXT_PER_MALLOC	8


struct ud_inode {
	struct ud_inode	*i_forw;
	struct ud_inode	*i_back;
	struct ud_inode	*i_freef;
	struct ud_inode	*i_freeb;

	struct vnode	*i_vnode;	/* vnode associated with this inode */
	struct vnode	*i_devvp;	/* vnode for block I/O */
	struct udf_vfs	*i_udf;		/* incore fs associated with inode */
	krwlock_t	i_rwlock;	/* serializes write/setattr requests */
	krwlock_t	i_contents;	/* protects (most of) inode contents */
	dev_t		i_dev;		/* device where inode resides */
	u_offset_t	i_diroff;	/* last loc for fast name lookup */

	daddr_t		i_icb_lbano;	/* Loc of file icb on disk */
	uint16_t	i_icb_prn;	/* partition reference number */
	kcondvar_t	i_wrcv;		/* sleep/wakeup for write throttle */
	uint32_t	i_flag;
	uint32_t	i_icb_block;

	int16_t		i_astrat;	/* ICB strategy */
	int16_t		i_desc_type;	/* Allocation desc type */
	int32_t		i_ext_count;	/* Number of extents allocated */
	int32_t		i_ext_used;	/* Number of extents used */
	struct icb_ext	*i_ext;		/* array of extents */

	kmutex_t	i_con_lock;
	struct icb_ext	*i_con;
	int32_t		i_con_count;
	int32_t		i_con_used;
	int32_t		i_con_read;

	uint32_t	i_cur_max_ext;
	vtype_t		i_type;		/* File type */
	uint16_t	i_char;		/* File characteristics */
	uint16_t	i_perm;		/* File permissions */

	uid_t		i_uid;		/* File owner's uid */
	gid_t		i_gid;		/* File owner's gid */
	uint32_t	i_nlink;	/* number of links to file */
	uint32_t	i_maxent;	/* Max entries that are recorded */
	u_offset_t	i_size;		/* File size in bytes */
	uint64_t	i_lbr;		/* Logical blocks recorded */
	uint64_t	i_uniqid;	/* from the file entry */

	timespec32_t	i_atime;
	timespec32_t	i_mtime;
	timespec32_t	i_ctime;

	size_t		i_delaylen;	/* delayed writes, units=bytes */
	offset_t	i_delayoff;	/* where we started delaying */
	offset_t	i_nextrio;	/* where to start the next clust */
	uint64_t	i_writes;	/* remaining bytes in write q */
	kmutex_t	i_tlock;	/* protects time fields, i_flag */
	major_t		i_major;
	minor_t		i_minor;

	uint32_t	i_marker1;	/* 0xAAAAAAAA */
	uint32_t	i_seq;		/* sequence number attribute */
	offset_t	i_nextr;	/* next byte read offset (read-ahead) */
	long		i_mapcnt;	/* number of mappings of pages */
	int		*i_map;		/* block list for the file */
	dev_t		i_rdev;		/* INCORE rdev from */
	uint32_t	i_marker2;	/* 0xBBBBBBBB */
	uint32_t	i_data_off;	/* Data offset into embedded file */
	uint32_t	i_max_emb;
	uint32_t	i_marker3;
};


#ifndef	__lint
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_astrat))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_desc_type))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_ext_count))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_ext_used))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_ext))

_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_type))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_char))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_perm))

_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_uid))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_gid))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_nlink))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_size))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_lbr))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_uniqid))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_major))
_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents, ud_inode::i_minor))

_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_atime))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_mtime))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_ctime))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_delayoff))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_delaylen))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_nextrio))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_writes))
_NOTE(MUTEX_PROTECTS_DATA(ud_inode::i_tlock, ud_inode::i_flag))

_NOTE(RWLOCK_PROTECTS_DATA(ud_inode::i_contents,
		icb_ext::ib_flags icb_ext::ib_prn
		icb_ext::ib_block
		icb_ext::ib_count icb_ext::ib_offset))
#endif


/* i_flag */
#define	IUPD		0x0001		/* file has been modified */
#define	IACC		0x0002		/* inode access time to be updated */
#define	IMOD		0x0004		/* inode has been modified */
#define	ICHG		0x0008		/* inode has been changed */
#define	INOACC		0x0010		/* no access time update in getpage */
#define	IMODTIME	0x0020		/* mod time already set */
#define	IREF		0x0040		/* inode is being referenced */
#define	ISYNC		0x0080		/* do all allocation synchronously */
#define	IMODACC		0x0200		/* only access time changed; */
#define	IATTCHG		0x0400		/* only size/blocks have changed */
#define	IBDWRITE	0x0800		/* the inode has been scheduled for */
					/* write operation asynchrously */

/*
 * i_char
 * Do not change used by MANDLOCK macro in vnode.h
 */
#define	ISUID		VSUID		/* set user id on execution */
#define	ISGID		VSGID		/* set group id on execution */
#define	ISVTX		VSVTX		/* save swapped text even after use */
/*
 * Setuid	--S---------
 * Setgid	-G----------
 * SaveTXT	T-----------
 */

/* i_perm */
#define	IEXEC		0x0400		/* read, write, execute permissions */
#define	IWRITE		0x0800
#define	IREAD		0x1000
#define	IATTR		0x2000
#define	IDELE		0x4000

#define	UP_MASK		0x1CE7
#define	VA2UD_PERM(perm)	\
	(((perm) & 0x7) | (((perm) & 0x38) << 2) | (((perm) & 0x1C0) << 4))
#define	UD2VA_PERM(perm)	\
	(((perm) & 0x7) | (((perm) & 0xE0) >> 2) | (((perm) & 0x1C00) >> 4))

/*
 * Permissions
 * Other	-----------DARWX
 * Group	------DARWX-----
 * Owner	-DARWX----------
 */
#define	UD_DPERM2UPERM(dperm)	((((dperm) >> 4) & 0x1C0) |	\
					(((dperm) >> 2) & 0x38) |	\
					((dperm) & 0x7))
#define	UD_UPERM2DPERM(uperm)	((((uperm) & 0x1C0) << 4) |	\
					(((uperm) & 0x38) << 2) |	\
					((uperm) & 0x7))


/* specify how the inode info is written in ud_syncip() */
#define	I_SYNC	1	/* wait for the inode written to disk */
#define	I_DSYNC	2	/* wait for the inode written to disk */
			/* only if IATTCHG is set */
#define	I_ASYNC	0	/* don't wait for the inode written */


#define	UD_HASH_SZ	512

#if ((UD_HASH_SZ & (UD_HASH_SZ - 1)) == 0)
#define	UD_INOHASH(dev, bno)	(hash2ints((int)dev, (int)bno) & UD_HASH_SZ - 1)
#else
#define	UD_INOHASH(dev, bno)	(hash2ints((int)dev, (int)bno) % UD_HASH_SZ)
#endif

union ihead {
	union	ihead		*ih_head[2];
	struct	ud_inode	*ih_chain[2];
};


#define	IMARK(ip) ud_imark(ip)
#define	ITIMES_NOLOCK(ip) ud_itimes_nolock(ip)

#define	ITIMES(ip) { \
	mutex_enter(&(ip)->i_tlock); \
	ITIMES_NOLOCK(ip); \
	mutex_exit(&(ip)->i_tlock); \
}

#define	ESAME	(-1)		/* trying to rename linked files (special) */

#define	UDF_HOLE	(daddr32_t)-1	/* value used when no block allocated */


extern int32_t ud_trace;
#define	ud_printf(xyz)	\
		if (ud_trace) {	\
			cmn_err(CE_NOTE, xyz);	\
		}

#ifndef	__lint
_NOTE(SCHEME_PROTECTS_DATA("Unshared data",
		buf
		dirent64
		fid
		flock64
		statvfs64
		timespec32
		udf_fid
		uio
		vattr
		vfs
		vnode))

_NOTE(SCHEME_PROTECTS_DATA("Unshared data",
		file_entry
		file_id
		icb_tag
		indirect_entry
		log_vol_int_desc
		long_ad
		lvid_iu
		regid
		short_ad
		tag
		tstamp))

_NOTE(LOCK_ORDER(ud_inode::i_rwlock
		ud_inode::i_contents
		ud_inode::i_tlock))
#endif

/*
 * udf_vfsops.c
 */
void		ud_update_superblock(struct vfs *);


/*
 * udf_vnops.c
 */
int32_t		ud_rdwri(enum uio_rw, int32_t, struct ud_inode *, caddr_t,
			int32_t, offset_t, enum uio_seg, int32_t *,
			struct cred *cr);
int32_t		ud_putapage(struct vnode *, page_t *, u_offset_t *,
			size_t *, int32_t, struct cred *);


/*
 * udf_inode.c
 */
int32_t	ud_iget(struct vfs *, uint16_t, uint32_t, struct ud_inode **,
    struct buf *, struct cred *);
void	ud_iinactive(struct ud_inode *, struct cred *);
void	ud_iupdat(struct ud_inode *, int32_t);
int32_t	ud_itrunc(struct ud_inode *, u_offset_t, int32_t, struct cred *);
int32_t	ud_iaccess(struct ud_inode *, int32_t, struct cred *, int dolock);
int32_t	ud_iflush(struct vfs *);
void	ud_imark(struct ud_inode *);
void	ud_itimes_nolock(struct ud_inode *);
void	ud_delcache(struct ud_inode *);
void	ud_idrop(struct ud_inode *);
void	ud_init_inodes(void);


/*
 * udf_alloc.c
 */
int32_t		ud_alloc_space(struct vfs *, uint16_t, uint32_t,
			uint32_t, uint32_t *, uint32_t *, int32_t, int32_t);
void		ud_free_space(struct vfs *, uint16_t, uint32_t, uint32_t);
int32_t		ud_ialloc(struct ud_inode *, struct ud_inode **,
			struct vattr *, struct cred *);
void		ud_ifree(struct ud_inode *, vtype_t);
int32_t		ud_freesp(struct vnode *, struct flock64 *, int32_t,
			struct cred *);
int32_t		ud_alloc_from_cache(struct udf_vfs *, struct ud_part *,
			uint32_t *);
int32_t		ud_release_cache(struct udf_vfs *);


/*
 * udf_subr.c
 */
void		ud_vfs_add(struct udf_vfs *);
void		ud_vfs_remove(struct udf_vfs *);
daddr_t		ud_xlate_to_daddr(struct udf_vfs *, uint16_t,
			uint32_t, int32_t, uint32_t *);
int32_t		ud_ip_off2bno(struct ud_inode *, uint32_t, uint32_t *);
void		ud_dtime2utime(struct timespec32 *, struct tstamp const *);
void		ud_utime2dtime(struct timespec32 const *, struct tstamp *);
int32_t		ud_syncip(struct ud_inode *, int32_t, int32_t);
void		ud_update(int32_t);
int32_t		ud_fbwrite(struct fbuf *, struct ud_inode *);
void		ud_sbwrite(struct udf_vfs *);
int32_t		ud_sync_indir(struct ud_inode *);
void		ud_update_regid(struct regid *);
int32_t		ud_read_icb_till_off(struct ud_inode *, u_offset_t);
void		ud_make_tag(struct udf_vfs *, struct tag *,
			uint16_t, uint32_t, uint16_t);
int32_t		ud_make_dev_spec_ear(struct dev_spec_ear *, major_t, minor_t);
int32_t		ud_make_ftimes_ear(struct ftimes_ear *,
			int32_t, struct timespec32 *);
int32_t		ud_get_next_fid(struct ud_inode *, struct fbuf **, uint32_t,
			struct file_id **, uint8_t **, uint8_t *);
int32_t		ud_verify_tag_and_desc(struct tag *, uint16_t, uint32_t,
		int32_t, int32_t);
uint16_t	ud_crc(uint8_t *, int32_t);
int32_t		ud_compressunicode(int32_t, int32_t, uint16_t *, uint8_t *);
uint32_t	ud_check_te_unrec(struct udf_vfs *, caddr_t, uint32_t);
int32_t		ud_compress(int32_t, int32_t *, uint8_t *, uint8_t *);
int32_t		ud_uncompress(int32_t, int32_t *, uint8_t *, uint8_t *);
struct buf	*ud_bread(dev_t, daddr_t, long);
int		ud_sticky_remove_access(struct ud_inode *, struct ud_inode *,
			struct cred *);


/*
 * udf_dir.c
 */
int32_t		ud_dirlook(struct ud_inode *,
			char *, struct ud_inode **, struct cred *, int32_t);
int32_t		ud_direnter(struct ud_inode *, char *, enum de_op,
			struct ud_inode *, struct ud_inode *, struct vattr *,
			struct ud_inode **, struct cred *, caller_context_t *);
int32_t		ud_dirremove(struct ud_inode *,
			char *, struct ud_inode *, struct vnode *,
			enum dr_op, struct cred *, caller_context_t *);


/*
 * udf_bmap.c
 */
int32_t		ud_bmap_has_holes(struct ud_inode *);
int32_t		ud_bmap_write(struct ud_inode *, u_offset_t,
			int, int32_t, struct cred *);
int32_t		ud_bmap_read(struct ud_inode *, u_offset_t,
			daddr_t *, int32_t *);
void		ud_insert_new_ext(struct ud_inode *,
			int32_t, struct icb_ext *);
int32_t		ud_alloc_and_make_ext(struct ud_inode *, int32_t);
int32_t		ud_create_new_icb(struct ud_inode *);
void		ud_append_new_ext(struct ud_inode *, uint16_t,
			u_offset_t, uint32_t, uint16_t, uint32_t);


#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UDF_INODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_UDF_VOLUME_H
#define	_SYS_FS_UDF_VOLUME_H

#include <sys/isa_defs.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	UDF_102	0x66
#define	UDF_150	0x96
#define	UDF_200	0xC8

/* fid_idlen include compression id */
#define	FID_LEN(fid)	(((sizeof (struct file_id) +	\
		SWAP_16((fid)->fid_iulen) + (fid)->fid_idlen - 2) + 3) & ~3)

/*
 * #define	ID_LEN(fid)	\
 *		(((SWAP_16((fid)->fid_iulen) + (fid)->fid_idlen - 2) + 3) & ~3)
 */

#define	F_LEN		(sizeof (struct file_id) - 2)

#define	UDF_DOMAIN_NAME		"*OSTA UDF Compliant\0\0\0\0"
#define	UDF_LV_INFO		"*UDF LV Info\0\0\0\0\0\0\0\0\0\0\0\0"
#define	UDF_FREEEASPACE		"*UDF FreeEASpace\0\0\0\0\0\0\0\0"
#define	UDF_FREEAEASPACE	"*UDF FreeAppEASpace\0\0\0\0"
#define	UDF_CGMS_INFO		"*UDF DVD CGMS Info\0\0\0\0"
#define	UDF_OS2_EA		"*UDF OS/2 EA\0\0\0\0\0\0\0\0\0\0\0"
#define	UDF_OS2_EA_LEN		"*UDF OS/2 EALength\0\0\0\0\0\0"
#define	UDF_MAC_VOLINFO		"*UDF Mac VolumeInfo\0\0\0\0"
#define	UDF_MAC_UNIQID		"*UDF Mac UniqueIDTable\0"
#define	UDF_MAC_RESFRK		"*UDF Mac ResourceFork\0\0"
#define	UDF_VIRT_PART		"*UDF Virtual Partition\0"
#define	UDF_SPAR_PART		"*UDF Sparable Partition"
#define	UDF_VAT			"*UDF Virtual Alloc Tbl\0"
#define	UDF_SPAR_TBL		"*UDF Sparing Table\0\0\0\0\0"


#if defined(_BIG_ENDIAN)
#define	SWAP_16(a)	(((ushort_t)((a) & 0xff) << 8) | \
					((ushort_t)((a) & 0xff00) >> 8))
#define	SWAP_32(a)	((((a) & 0xff) << 24) |	\
				(((a) & 0xff00) << 8) |	\
				(((a) & 0xff0000) >> 8) |	\
				(((a) & 0xff000000) >> 24))
#define	SWAP_64(a)	((((a) & 0xffULL) << 56)	| \
				(((a) & 0xff00ULL) << 40) | \
				(((a) & 0xff0000ULL) << 24) | \
				(((a) & 0xff000000ULL) << 8) | \
				(((a) & 0xff00000000ULL) >> 8) | \
				(((a) & 0xff0000000000ULL) >> 24) | \
				(((a) & 0xff000000000000ULL) >> 40) | \
				(((a) & 0xff00000000000000ULL) >> 56))

#define	GET_32(a)	((uint32_t)(*((uint8_t *)a)) | \
				(((uint32_t)(*(((uint8_t *)a) + 1))) << 8) | \
				(((uint32_t)(*(((uint8_t *)a) + 2))) << 16) | \
				(((uint32_t)(*(((uint8_t *)a) + 3))) << 24))
#else
#define	SWAP_16(a)	(a)
#define	SWAP_32(a)	(a)
#define	SWAP_64(a)	(a)

#define	GET_32(a)	(*((uint32_t *)a))
#endif	/* _BIG_ENDIAN */


#define	BCD2HEX_16(a)	(((a) & 0xf) + \
			(((ushort_t)((a) & 0xf0) >> 4) * 10) + \
			(((ushort_t)((a) & 0xf00) >> 8) * 100) + \
			(((ushort_t)((a) & 0xf000) >> 12) * 1000))

#define	HEX2BCD_16(a)	((((ushort_t)a) % 10) | \
			(((ushort_t)((ushort_t)(a) / 10) % 10) << 4) | \
			(((ushort_t)((ushort_t)(a) / 100) % 10) << 8) | \
			(((ushort_t)((ushort_t)(a) / 1000) % 10) << 12))

#define	ANCHOR_VOL_DESC_LOC	(256)
#define	ANCHOR_VOL_DESC_LEN	0x200



/* Basic data structures */


typedef char dstring_t;


/*
 * recorded at the start of the descriptor
 * used to distinguish between different
 * descriptors
 */
struct tag {
	uint16_t	tag_id;		/* 00 Tag Identifier */
	uint16_t	tag_desc_ver;	/* 02 Descriptor Version */
	uint8_t		tag_cksum;	/* 04 Tag Checksum */
	uint8_t		tag_res;	/* 05 Reserved */
	uint16_t	tag_sno;	/* 06 Tag Serial Number */
	uint16_t	tag_crc;	/* 08 Descriptor CRC */
	uint16_t	tag_crc_len;	/* 0A Descriptor CRC length */
	uint32_t	tag_loc;	/* 0C Tag Location */
};
typedef struct tag tag_t;

/*
 * descriptor tag id values
 */

#define	UD_PRI_VOL_DESC		0x0001
#define	UD_ANCH_VOL_DESC	0x0002
#define	UD_VOL_DESC_PTR		0x0003
#define	UD_IMPL_USE_DESC	0x0004
#define	UD_PART_DESC		0x0005
#define	UD_LOG_VOL_DESC		0x0006
#define	UD_UNALL_SPA_DESC	0x0007
#define	UD_TERM_DESC		0x0008
#define	UD_LOG_VOL_INT		0x0009

#define	UD_FILE_SET_DESC	0x0100
#define	UD_FILE_ID_DESC		0x0101
#define	UD_ALLOC_EXT_DESC	0x0102
#define	UD_INDIRECT_ENT		0x0103
#define	UD_TERMINAL_ENT		0x0104
#define	UD_FILE_ENTRY		0x0105
#define	UD_EXT_ATTR_HDR		0x0106
#define	UD_UNALL_SPA_ENT	0x0107
#define	UD_SPA_BMAP_DESC	0x0108
#define	UD_PART_INT_DESC	0x0109
#define	UD_EXT_FILE_ENT		0x010A




/*
 * Character set's allowed in descriptor fields
 * shall be specified
 */
struct charspec {
	uint8_t		cs_type;	/* 00 Character Set Type */
	char		cs_info[63];	/* 01 Character Set Information */
};
typedef struct charspec charspec_t;

#define	CS_TYPE0	0x00
#define	CS_TYPE1	0x01
#define	CS_TYPE2	0x02
#define	CS_TYPE3	0x03
#define	CS_TYPE4	0x04
#define	CS_TYPE5	0x05
#define	CS_TYPE6	0x06
#define	CS_TYPE7	0x07
#define	CS_TYPE8	0x08



/*
 * Entity Identification
 */
struct regid {
	uint8_t		reg_flags;	/* 00 Flags */
	char		reg_id[23];	/* 01 Identifier */
	char		reg_ids[8];	/* 18 Identifier Suffix */
};
typedef struct regid regid_t;

#define	EI_FLAG_DIRTY		0x00
#define	EI_FLAG_PROT		0x01

struct lb_addr {
	/* uint32_t	lba_number;	00 Logical Block Number */
	/* uint8_t	lba_prn[2];	04 Partition Reference Number */
	char		lba_aaa[6];
};
typedef	struct lb_addr lb_addr_t;
#define	lba_number(x)(((x)->lba_aaa[0]) | \
			((x)->lba_aaa[1] << 8) | \
			((x)->lba_aaa[2] << 16) | \
			((x)->lba_aaa[3] << 24))

#define	lba_prn(x)	((x)->lba_aaa[4] | ((x)->lba_aaa[5] << 8))


/*
 * Extend Descriptor
 */
struct extent_ad {
	uint32_t	ext_len;	/* 00 Extent Length */
	uint32_t	ext_loc;	/* 04 Extent Location */
};
typedef struct extent_ad extent_ad_t;

/*
 * Short Allocation Descriptor
 */
struct short_ad {
	uint32_t	sad_ext_len;	/* 00 Extent Length */
	uint32_t	sad_ext_loc;	/* 04 extent Position */
};
typedef struct short_ad short_ad_t;

/*
 * Long Allocation Descriptor
 */
struct long_ad {
	uint32_t	lad_ext_len;	/* 00 Extent Length */
	uint32_t	lad_ext_loc;	/* 04 Extent Location */
	uint16_t	lad_ext_prn;	/* 08 Extent part ref no */
	/* lb_addr_t	lad_ext_loc;	 04 Extent Location */
	char		lad_iu[6];	/* 0A Implementation Use */
};
typedef struct long_ad long_ad_t;




/*
 * Format to record date and time
 * If zero date & time is not specified
 */
struct tstamp {
	uint16_t	ts_tzone;	/* 00 Type and Time Zone */
	uint16_t	ts_year;	/* 02 Year */
	uint8_t		ts_month;	/* 04 Month */
	uint8_t		ts_day;		/* 05 Day */
	uint8_t		ts_hour;	/* 06 Hour */
	uint8_t		ts_min;		/* 07 Minute */
	uint8_t		ts_sec;		/* 08 Second */
	uint8_t		ts_csec;	/* 09 Centi-seconds */
	uint8_t		ts_husec;	/* 0A Hundreds of Micro sec's */
	uint8_t		ts_usec;	/* 0B Micro-seconds */
};
typedef struct tstamp tstamp_t;


/*
 * ts_tzone
 */
#define	TMODE		0xF000
#define	TSIGN		0x0800
#define	TOFFSET		0x07FF
#define	TINVALID	(TSIGN|TOFFSET)


/*
 * Format of the ICB tag which specifies
 * most of the infomation of the file
 */
struct icb_tag {
	uint32_t	itag_prnde;	/* 00 Prior Recorded No of Dir Entry */
	uint16_t	itag_strategy;	/* 04 Strategy Type */
	uint16_t	itag_param;	/* 06 Strategy parameter */
	uint16_t	itag_max_ent;	/* 08 Maximum No of Entries */
	uint8_t		itag_rsvd;	/* 0A Reserved */
	uint8_t		itag_ftype;	/* 0B File Type */
	/* lb_addr_t	itag_lb_addr;	0C parent ICB Location */
	uint32_t	itag_lb_loc;	/* 0C */
	uint16_t	itag_lb_prn;	/* 10 */
	uint16_t	itag_flags;	/* 12 Flags */
};
typedef struct icb_tag icb_tag_t;

/*
 * Different strategy types for the file
 * For DVD_ROM we use onlt type4
 */
#define	STRAT_TYPE1		0x0001
#define	STRAT_TYPE2		0x0002
#define	STRAT_TYPE3		0x0003
#define	STRAT_TYPE4		0x0004
#define	STRAT_TYPE4096		0x1000

/*
 * File types
 */
#define	FTYPE_UNALL_SPACE	0x01
#define	FTYPE_PART_INTEG	0x02
#define	FTYPE_INDIRECT		0x03
#define	FTYPE_DIRECTORY		0x04
#define	FTYPE_FILE		0x05
#define	FTYPE_BLOCK_DEV		0x06
#define	FTYPE_CHAR_DEV		0x07
#define	FTYPE_EAR		0x08
#define	FTYPE_FIFO		0x09
#define	FTYPE_C_ISSOCK		0x0A
#define	FTYPE_T_ENTRY		0x0B
#define	FTYPE_SYMLINK		0x0C

/*
 * Flags
 */
#define	ICB_FLAG_SHORT_AD	0x0000
#define	ICB_FLAG_LONG_AD	0x0001
#define	ICB_FLAG_EXT_AD		0x0002
#define	ICB_FLAG_ONE_AD		0x0003
#define	ICB_FLAG_SORTED		0x0008
#define	ICB_FLAG_NON_RELOC	0x0010
#define	ICB_FLAG_ARCHIVE	0x0020
#define	ICB_FLAG_SETUID		0x0040
#define	ICB_FLAG_SETGID		0x0080
#define	ICB_FLAG_STICKY		0x0100
#define	ICB_FLAG_CONTIG		0x0200
#define	ICB_FLAG_SYSTEM		0x0400
#define	ICB_FLAG_TRNSFRMED	0x0800
#define	ICB_FLAG_MVERS		0x1000




/* Volume recognition descriptors */




/*
 * Primary volume descriptor identifis the
 * volume and certain attributes of the volume
 */
struct pri_vol_desc {
	tag_t		pvd_tag;	/* 00 Descriptor Tag */
	uint32_t	pvd_vdsn;	/* 10 Volume Descriptor Seq Num */
	uint32_t	pvd_pvdn;	/* 14 Primary Vol Desc Num */
	dstring_t	pvd_vol_id[32];	/* 18 Volume Identifier */
	uint16_t	pvd_vsn;	/* 38 Volume Sequence Num */
	uint16_t	pvd_mvsn;	/* 3A Max Volume Sequence Num */
	uint16_t	pvd_il;		/* 3C Interchange Level */
	uint16_t	pvd_mil;	/* 3E Max Interchange Level */
	uint32_t	pvd_csl;	/* 40 Character Set List */
	uint32_t	pvd_mcsl;	/* 44 Max Character Set List */
	dstring_t	pvd_vsi[128];	/* 48 Volume Set Identifier */
	charspec_t	pvd_desc_cs;	/* C8 Descriptor Character Set */
	charspec_t	pvd_exp_cs;	/* 108 Explanatory Char Set */
	extent_ad_t	pvd_vol_abs;	/* 148 Volume Abstract */
	extent_ad_t	pvd_vcn;	/* 150 Volume Copyright Notice */
	regid_t		pvd_appl_id;	/* 158 Application Identifier */
	tstamp_t	pvd_time;	/* 178 Recording Data & Time */
	regid_t		pvd_ii;		/* 184 Implementation Identifier */
	char		pvd_iu[64];	/* 1A4 Implementation Use */
	uint32_t	pvd_pvdsl;	/* 1E4 Pred Vol Desc Seq Loc */
	uint16_t	pvd_flags;	/* 1E8 Flags */
	uint8_t		pvd_res[22];	/* 1EA Reserved */
};




/*
 * Anchor Volume Descriptor Pointer specifies
 * the extent of Main & Reserve volume descriptor
 */
struct anch_vol_desc_ptr {
	tag_t		avd_tag;	/* 00 Descriptor Tag */
	extent_ad_t	avd_main_vdse;	/* 10 Main Vol Desc Seq Extent */
	extent_ad_t	avd_res_vdse;	/* 18 Reserve Vol Desc Seq Ext */
	char		avd_res[480];	/* 20 Reserved */
};
typedef struct anch_vol_desc_ptr anch_vol_desc_ptr_t;




/*
 * Volume Descriptor Pointer
 */
struct vol_desc_ptr {
	tag_t		vdp_tag;	/* 00 Descriptor Tag */
	uint32_t	vdp_vdsn;	/* 10 Volume Descriptor Seq Num */
	extent_ad_t	vdp_nvdse;	/* 14 Next Vol Desc Seq Extent */
	uint8_t		vdp_res[484];	/* 1A Reserved */
};
typedef struct vol_desc_ptr vol_desc_ptr_t;




/*
 * Implementation Use Volume Descriptor
 * This is taken from udf1.02/1.50 documents
 * the fields after iuvd_ii are defined only
 * for the udf domain
 */
struct iuvd_desc {
	tag_t		iuvd_tag;	/* 00 Descriptor Tag */
	uint32_t	iuvd_vdsn;	/* 10 Volume Desc Seq Num */
	regid_t		iuvd_ii;	/* 14 Domain Identifier */
	charspec_t	iuvd_cset;	/* 34 LVI Charset */
	dstring_t	iuvd_lvi[128];	/* 74 Logical Vol Identifier */
	dstring_t	iuvd_ifo1[36];	/* F4 LV Info1 */
	dstring_t	iuvd_ifo2[36];	/* 118 LV Info2 */
	dstring_t	iuvd_ifo3[36];	/* 13C LV Info3 */
	regid_t		iuvd_iid;	/* 160 Implementation ID */
	uint8_t		iuvd_iu[128];	/* 180 Implementation Use */
};
typedef struct iuvd_desc iuvd_desc_t;





/*
 * Partition Descriptor
 * specifies the size and location of the partition
 */
struct part_desc {
	tag_t		pd_tag;		/* 00 Descriptor Tag */
	uint32_t	pd_vdsn;	/* 10 Volume Desc Seq Num */
	uint16_t	pd_pflags;	/* 14 Partition Flags */
	uint16_t	pd_pnum;	/* 16 partition Number */
	regid_t		pd_pcontents;	/* 18 Partition Contents */
	uint8_t		pd_pc_use[128];	/* 38 Partition Contents Use */
	uint32_t	pd_acc_type;	/* B8 Access Type */
	uint32_t	pd_part_start;	/* BC Part Start Location */
	uint32_t	pd_part_length;	/* C0 partition Length */
	regid_t		pd_ii;		/* C4 Implementation Identifier */
	uint8_t		pd_iu[128];	/* E4 Implementation Use */
	uint8_t		pd_res[156];	/* 164 Reserved */
};
typedef struct part_desc part_desc_t;


/*
 * pd_acc_type
 */
#define	PART_ACC_RO	0x01
#define	PART_ACC_WO	0x02
#define	PART_ACC_RW	0x03
#define	PART_ACC_OW	0x04


/*
 * Partition Header Descriptor
 * Overloads pd_pc_use
 */
struct phdr_desc {
	struct short_ad	phdr_ust;		/* Unallocated Space Table */
	struct short_ad	phdr_usb;		/* Unallocated Space Bitmap */
	struct short_ad	phdr_it;		/* Partition Integrity Table */
	struct short_ad	phdr_fst;		/* Freed Space Table */
	struct short_ad	phdr_fsb;		/* Freed Space Bitmap */
};
typedef struct phdr_desc phdr_desc_t;






/*
 * Logical Volume Descriptor
 */
struct log_vol_desc {
	tag_t		lvd_tag;	/* 00 Descriptor Tag */
	uint32_t	lvd_vdsn;	/* 10 Volume Desc Seq Num */
	charspec_t	lvd_desc_cs;	/* 14 Descriptor Char Set */
	dstring_t	lvd_lvid[128];	/* 54 Logical Vol Identifier */
	uint32_t	lvd_log_bsize;	/* D4 Logical Block Size */
	regid_t		lvd_dom_id;	/* D8 Domain Identifier */
	long_ad_t	lvd_lvcu;	/* F8 Logical Vol Contents Use */
	uint32_t	lvd_mtbl_len;	/* 108 Map Table Length */
	uint32_t	lvd_num_pmaps;	/* 10C Number of Partition Maps */
	regid_t		lvd_ii;		/* 110 Implementation Identifier */
	uint8_t		lvd_iu[128];	/* 130 Implementation Use */
	extent_ad_t	lvd_int_seq_ext; /* 1B0 Integrity Sequence Extent */
	uint8_t		lvd_pmaps[72];	/* 1B8 Partition Maps */
};
typedef struct log_vol_desc log_vol_desc_t;





/*
 * Unallocated Space Descriptor
 * Contains information about the space
 * that does not belong to any of the
 * partition
 */
struct unall_spc_desc {
	tag_t		ua_tag;		/* 00 Descriptor Tag */
	uint32_t	ua_vdsn;	/* 10 Volume Desc Seq Num */
	uint32_t	ua_nad;		/* 14 Number of Allocation Desc */
	uint8_t		ua_al_dsc[488];	/* 18 Allocation Desc */
};
typedef struct unall_spc_desc unall_spc_desc_t;




/*
 * Terminating Descriptor
 * this will be the last in a Volume Descriptor Sequence
 */
struct term_desc {
	tag_t		td_tag;		/* 00 Descriptor Tag */
	uint8_t		td_res[496];	/* 10 Reserved */
};
typedef struct term_desc term_desc_t;


/*
 * Logical Volume Header Descriptor
 * This will be overlaid on lvid_lvcu
 * and will contain the maximum value of
 * unique id on the media
 */
struct log_vol_hdr_desc {
	uint64_t	lvhd_uniqid;	/* 00 Unique Id */
	uint8_t		lvhd_pad[24];	/* 08 reserved */
};
typedef struct log_vol_hdr_desc log_vol_hdr_desc_t;

/*
 * Logical Volume Integrity Sequence
 * This will contain the integrity of the
 * file system
 */
struct log_vol_int_desc {
	tag_t		lvid_tag;	/* 00 Descriptor Tag */
	tstamp_t	lvid_tstamp;	/* 10 Recording Date and Time */
	uint32_t	lvid_int_type;	/* 1C Integrity Type */
	extent_ad_t	lvid_nie;	/* 20 Next Integrity Extent */
	/* uint8_t	lvid_lvcu[32]; */
	log_vol_hdr_desc_t lvid_lvcu;	/* 28 Logical Volume Contents Use */
	uint32_t	lvid_npart;	/* 48 Number of Partitions */
	uint32_t	lvid_liu;	/* 4C Length of Implementation Use */
	uint32_t	lvid_fst[2];	/* 50 Free Space Table */
					/* Size Table */
					/* Implementation Use */
};
typedef struct log_vol_int_desc log_vol_int_desc_t;

#define	lvid_uniqid	lvid_lvcu.lvhd_uniqid


#define	LOG_VOL_OPEN_INT	0x00
#define	LOG_VOL_CLOSE_INT	0x01


/*
 * Logical Volume integrity Implementation Use
 * This is defined in udf spec
 */
struct lvid_iu {
	regid_t		lvidiu_regid;	/* 00 Implementation ID */
	uint32_t	lvidiu_nfiles;	/* 20 Number of Files */
	uint32_t	lvidiu_ndirs;	/* 24 Number of Directories */
	uint16_t	lvidiu_mread;	/* 28 Minimum UDF read revision */
	uint16_t	lvidiu_mwrite;	/* 2A Minimum UDF write revision */
	uint16_t	lvidiu_maxwr;	/* 2C Maximum UDF write revision */
};







/*
 * File Set Descriptor
 * This will point to the root directory.
 */
struct file_set_desc {
	tag_t		fsd_tag;	/* 00 Descriptor Tag */
	tstamp_t	fsd_time;	/* 10 Recording Date and Time */
	uint16_t	fsd_ilevel;	/* 1C Interchange Level */
	uint16_t	fsd_mi_level;	/* 1E Max Interchange Level */
	uint32_t	fsd_cs_list;	/* 20 Character Set List */
	uint32_t	fsd_mcs_list;	/* 24 Max Character Set List */
	uint32_t	fsd_fs_no;	/* 28 File Set Number */
	uint32_t	fsd_fsd_no;	/* 2C File Set Desc Number */
	charspec_t	fsd_lvidcs;	/* 30 Log Vol Id Char Set */
	char		fsd_lvid[128];	/* 70 Log Vol Identifier */
	charspec_t	fsd_fscs;	/* F0 File Set Character Set */
	char		fsd_fsi[32];	/* 130 File Set Identifier */
	char		fsd_cfi[32];	/* 150 Copyright File Identifier */
	char		fsd_afi[32];	/* 170 Abstract File identifier */
	long_ad_t	fsd_root_icb;	/* 190 Root Directory ICB */
	regid_t		fsd_did;	/* 1A0 Domain Identifier */
	long_ad_t	fsd_next;	/* 1C0 Next Extent */
	uint8_t		fsd_res[48];	/* 1D0 Reserved */
};
typedef struct file_set_desc file_set_desc_t;







/*
 * File Identifier Descriptor
 * Directory entries
 */
struct file_id {
	tag_t		fid_tag;	/* 00 Descriptor Tag */
	uint16_t	fid_ver;	/* 10 File Version Number */
	uint8_t		fid_flags;	/* 12 File characteristics */
	uint8_t		fid_idlen;	/* 13 Length File Identifier */
	long_ad_t	fid_icb;	/* 14 ICB */
	uint16_t	fid_iulen;	/* 24 Length of Implmentation use */
	uint8_t		fid_spec[2];	/* iulen for iu name and padding */
};
typedef struct file_id file_id_t;

#define	FID_EXIST	0x01
#define	FID_DIR		0x02
#define	FID_DELETED	0x04
#define	FID_PARENT	0x08







/*
 * Allocation Extent Descriptor
 */
struct alloc_ext_desc {
	tag_t		aed_tag;	/* 00 Descriptor Tag */
	uint32_t	aed_rev_ael;	/* 10 Previous Alloc Extent Location */
	uint32_t	aed_len_aed;	/* 14 Length of Allocation Desc */
};
typedef struct alloc_ext_desc alloc_ext_desc_t;





/*
 * Indirect Entry
 * used to specify the address of another ICB
 */
struct indirect_entry {
	tag_t		ie_tag;		/* 00 Descriptor Tag */
	icb_tag_t	ie_icb_tag;	/* 10 ICB tag */
	long_ad_t	ie_indirecticb;	/* 24 Indirect ICB */
};
typedef struct indirect_entry indirect_entry_t;




/*
 * Terminal Entry
 */
struct term_entry {
	tag_t		te_tag;		/* 00 Descriptor Tag */
	icb_tag_t	te_icb_tag;	/* 10 ICB tag */
};
typedef struct term_entry term_entry_t;




/*
 * File entry describes the
 * file attributes and location it is recorded on the media
 */
struct file_entry {
	tag_t		fe_tag;		/* 00 Descriptor Tag */
	icb_tag_t	fe_icb_tag;	/* 10 ICB tag */
	uint32_t	fe_uid;		/* 24 Uid */
	uint32_t	fe_gid;		/* 28 Gid */
	uint32_t	fe_perms;	/* 2C Permissions */
	uint16_t	fe_lcount;	/* 30 File Link Count */
	uint8_t		fe_rec_for;	/* 32 Record Format */
	uint8_t		fe_rec_dis;	/* 33 Record Display Attributes */
	uint32_t	fe_rec_len;	/* 34 Record Length */
	uint64_t	fe_info_len;	/* 38 Information Length */
	uint64_t	fe_lbr;		/* 40 Logical Blocks recorded */
	tstamp_t	fe_acc_time;	/* 48 Access Data and Time */
	tstamp_t	fe_mod_time;	/* 54 Modification Data and Time */
	tstamp_t	fe_attr_time;	/* 60 Attribute Data and Time */
	uint32_t	fe_ckpoint;	/* 6C Checkpoint */
	long_ad_t	fe_ea_icb;	/* 70 Extended Attr ICB */
	regid_t		fe_impl_id;	/* 80 Implementation Identifier */
	uint64_t	fe_uniq_id;	/* A0 Unique Id */
	uint32_t	fe_len_ear;	/* A8 Length of Extended Attr */
	uint32_t	fe_len_adesc;	/* AC Length of Alloc Desc */
	char		fe_spec[336];	/* B0 used for EA and AD's */
};
typedef struct file_entry file_entry_t;





/*
 * Extended Attribute Header
 */
struct ext_attr_hdr {
	tag_t		eah_tag;	/* 00 Descriptor Tag */
	uint32_t	eah_ial;	/* 10 Implementation Attr Location */
	uint32_t	eah_aal;	/* 14 Application Attr Location */
};
typedef struct ext_attr_hdr ext_attr_hdr_t;







/*
 * Unallocated Space Entry
 */
struct unall_space_ent {
	tag_t		use_tag;	/* 00 Descriptor Tag */
	icb_tag_t	use_icb_tag;	/* 10 ICB tag */
	uint32_t	use_len_ad;	/* 24 Lenght of Allocation desc */
	uint8_t		use_ad[484];	/* 28 Allocation Descriptors */
};
typedef struct unall_space_ent unall_space_ent_t;





/*
 * Space Bitmap Descriptor
 */
struct space_bmap_desc {
	tag_t		sbd_tag;	/* 00 Descriptor Tag */
	uint32_t	sbd_nbits;	/* 10 Number of Bits */
	uint32_t	sbd_nbytes;	/* 14 Number of Bytes */
	uint8_t		sbd_bmap[500];	/* 18 Bitmap */
};
typedef struct space_bmap_desc space_bmap_desc_t;





/*
 * Partition Integrity entry
 */
struct part_int_desc {
	tag_t		pid_tag;	/* 00 Descriptor Tag */
	icb_tag_t	pid_idb_tag;	/* 10 ICB tag */
	tstamp_t	pid_rtime;	/* 24 Recording Data and Time */
	uint8_t		pid_integ;	/* 30 Integrity type */
	uint8_t		pid_res[175];	/* 31 Reserved */
	regid_t		pid_ii;		/* E0 Implementation Identifier */
	uint8_t		pid_iu[256];	/* 100 Implementation Use */
};
typedef struct part_int_desc part_int_desc_t;


#define	PART_OPEN_INT		0x00
#define	PART_CLOSE_INT		0x01
#define	PART_STABLE_INT		0x02




struct attr_hdr {
	uint32_t	ahdr_atype;	/* Attribute Type */
	uint8_t		ahdr_astype;	/* Attribute Subtype */
	uint8_t		ahdr_res[3];	/* Reserved */
	uint32_t	ahdr_length;	/* Attribute Length */
	uint8_t		ahdr_data[4];	/* Attribute Data */
};

/*
 * We will support and use the
 * following Extended Attributes
 * we will ignore others while reading
 * and will preserve then when updating
 * the EAR's
 * In all the EA's we allocate the last member
 * as 4 bytes. This is a sort of hack
 * since the structure has to be
 * properly alined to 4 bytes.
 */

struct dev_spec_ear {
	uint32_t	ds_atype;	/* 00 Attribute Type */
	uint8_t		ds_astype;	/* 04 Attribute Subtype */
	uint8_t		ds_res[3];	/* 05 Reserved */
	uint32_t	ds_attr_len;	/* 08 Attrbute Length */
	uint32_t	ds_iu_len;	/* 0C Impl Use Length */
	uint32_t	ds_major_id;	/* 10 Major Device ID */
	uint32_t	ds_minor_id;	/* 14 Minor Device ID */
	uint8_t		ds_iu[4];	/* 18 Implementation Use */
};


struct ftimes_ear {
	uint32_t	ft_atype;	/* 00 Attribute Type */
	uint8_t		ft_astype;	/* 04 Attribute Subtype */
	uint8_t		ft_res[3];	/* 05 Reserved */
	uint32_t	ft_attr_len;	/* 08 Attrbute Length */
	uint32_t	ft_data_len;	/* 0C Data Length */
	uint32_t	ft_exist;	/* 10 File Time Existence */
	uint8_t		ft_ft[4];	/* 14 File Times */
};

/* ft_exit */
#define	FT_EXIST	0x0
#define	FT_DELETE	0x2
#define	FT_FEDT		0x3
#define	FT_BACKUP	0x5

struct iu_ea {
	uint32_t	iuea_atype;	/* 00 Attribute Type */
	uint8_t		iuea_astype;	/* 04 Attribute Subtype */
	uint8_t		iuea_res[3];	/* 05 Reserved */
	uint32_t	iuea_attr_len;	/* 08 Attrbute Length */
	uint32_t	iuea_iu_len;	/* 0C Implementation Use Length */
	regid_t		iuea_ii;		/* 10 Implementation ID */
	uint8_t		iuea_iu[4];	/* 30 Impl Use */
};


/*
 * CGMS & FREE_SPACE will be
 * over laid on iu_iu field
 */

struct copy_mgt_info {
	uint16_t	cgms_cksum;	/* Header Checksum */
	uint8_t		cgms_info;	/* CGMS Information */
	uint8_t		cgms_dstype;	/* Data Structure Type */
	uint32_t	cgms_psi;	/* Protection System Info */
};

#define	COPY_PROTECTED	0x80

struct FREE_SPACE {
	uint16_t	fs_cksum;	/* Header Checksum */
	uint8_t		fs_freesp[2];	/* Free EA space */
};




struct nsr_desc {
	uint8_t		nsr_str_type;
	uint8_t		nsr_id[5];
	uint8_t		nsr_ver;
	uint8_t		nsr_res;
	uint8_t		nsr_data[2040];
};



/*
 * Partition Map
 */
struct pmap_hdr {
	uint8_t		maph_type;	/* Partition Map Type */
	uint8_t		maph_length;	/* Partition Map Length */
};

#define	MAP_TYPE1	1
#define	MAP_TYPE2	2

#define	MAP_TYPE1_LEN	6
#define	MAP_TYPE2_LEN	64

struct pmap_typ1 {
	uint8_t		map1_type;	/* Map type == 1 */
	uint8_t		map1_length;	/* Map length == 6 */
	uint16_t	map1_vsn;	/* Volume Sequence Number */
	uint16_t	map1_pn;	/* Partition Number */
};


/*
 * Only two types of type2 maps
 * are supported they are
 * *UDF Virtual Partition
 * *UDF Sparable Partition
 * For vpm fields till map2_pn
 * are valid and the entire structure is
 * valid for spm
 */
struct pmap_typ2 {
	uint8_t		map2_type;	/* 00 Map type == 2 */
	uint8_t		map2_length;	/* 01 Map length == 64 */
	uint16_t	map2_pad1;	/* 02 Reserved */
	regid_t		map2_pti;	/* 04 Entiry ID */
	uint16_t	map2_vsn;	/* 24 Volume Sequence Number */
	uint16_t	map2_pn;	/* 26 Partition Number */
	uint16_t	map2_pl;	/* 28 Packet Length == 32 */
	uint8_t		map2_nst;	/* 2A Number of sparing tables */
	uint8_t		map2_pad2;	/* 2B Reserved */
	uint32_t	map2_sest;	/* 2C Size of each sparing table */
	uint32_t	map2_st[4];	/* 30 sparing Tables */
};


struct stbl_entry {
	uint32_t	sent_ol;	/* Original Location */
	uint32_t	sent_ml;	/* Mapped Location */
};

typedef struct stbl_entry stbl_entry_t;

struct stbl {
	tag_t		stbl_tag;	/* 00 Tag */
	regid_t		stbl_si;	/* 10 Sparing Identifier */
	uint16_t	stbl_len;	/* 30 Reallocation Table Len */
	uint16_t	stbl_res1;	/* 32 Reserved */
	uint32_t	stbl_seqno;	/* 34 Sequence Number */
	stbl_entry_t	stbl_entry;	/* 38 Sparing Table Entries */
};

struct path_comp {
	uint8_t		pc_type;	/* Component Type */
	uint8_t		pc_len;		/* Length of Component ID */
	uint16_t	pc_ver;		/* Component File Version Number */
	uint8_t		pc_id[4];	/* Component ID */
};

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UDF_VOLUME_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	_SYS_FS_UFS_ACL_H
#define	_SYS_FS_UFS_ACL_H

#include <sys/types.h>
#include <sys/cred.h>
#include <sys/vfs.h>
#include <sys/acl.h>
#include <sys/fs/ufs_fs.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * On-disk UFS ACL structure
 */

typedef struct ufs_acl {
	union {
		uint32_t 	acl_next;	/* Pad for old structure */
		ushort_t	acl_tag;	/* Entry type */
	} acl_un;
	o_mode_t	acl_perm;		/* Permission bits */
	uid_t		acl_who;		/* User or group ID */
} ufs_acl_t;

#define	acl_tag acl_un.acl_tag
#define	acl_next acl_un.acl_next

/*
 * In-core UFS ACL structure
 */

typedef struct ufs_ic_acl {
	struct ufs_ic_acl	*acl_ic_next;	/* Next ACL for this inode */
	o_mode_t		acl_ic_perm;	/* Permission bits */
	uid_t			acl_ic_who;	/* User or group ID */
} ufs_ic_acl_t;

/*
 * In-core ACL mask
 */
typedef struct ufs_aclmask {
	short		acl_ismask;	/* Is mask defined? */
	o_mode_t	acl_maskbits;	/* Permission mask */
} ufs_aclmask_t;

/*
 * full acl
 */
typedef struct ic_acl {
	ufs_ic_acl_t	*owner;		/* owner object */
	ufs_ic_acl_t	*group;		/* group object */
	ufs_ic_acl_t	*other;		/* other object */
	ufs_ic_acl_t	*users;		/* list of users */
	ufs_ic_acl_t	*groups;	/* list of groups */
	ufs_aclmask_t	mask;		/* mask */
} ic_acl_t;

/*
 * In-core shadow inode
 */
typedef	struct si {
	struct si *s_next;		/* signature hash next */
	struct si *s_forw;		/* inode hash next */
	struct si *s_fore;		/* unref'd list next */

	int	s_flags;		/* see below */
	ino_t	s_shadow;		/* shadow inode number */
	dev_t	s_dev;			/* device (major,minor) */
	int	s_signature;		/* signature for all ACLs */
	int 	s_use;			/* on disk use count */
	int	s_ref;			/* in core reference count */
	krwlock_t s_lock;		/* lock for this structure */

	ic_acl_t  s_a;			/* acls */
	ic_acl_t  s_d;			/* def acls */
} si_t;

#define	aowner	s_a.owner
#define	agroup	s_a.group
#define	aother	s_a.other
#define	ausers	s_a.users
#define	agroups	s_a.groups
#define	aclass	s_a.mask

#define	downer	s_d.owner
#define	dgroup	s_d.group
#define	dother	s_d.other
#define	dusers	s_d.users
#define	dgroups	s_d.groups
#define	dclass	s_d.mask

#define	s_prev	s_forw

/*
 * s_flags
 */
#define	SI_CACHED 0x0001		/* Is in si_cache */

/*
 * Header to identify data on disk
 */
typedef struct ufs_fsd {
	int	fsd_type;		/* type of data */
	int	fsd_size;		/* size in bytes of ufs_fsd and data */
	char	fsd_data[1];		/* data */
} ufs_fsd_t;

/*
 * Data types  (fsd_type)
 */
#define	FSD_FREE	(0)		/* Free entry */
#define	FSD_ACL		(1)		/* Access Control Lists */
#define	FSD_DFACL	(2)		/* reserved for future use */
#define	FSD_RESERVED3	(3)		/* reserved for future use */
#define	FSD_RESERVED4	(4)		/* reserved for future use */
#define	FSD_RESERVED5	(5)		/* reserved for future use */
#define	FSD_RESERVED6	(6)		/* reserved for future use */
#define	FSD_RESERVED7	(7)		/* reserved for future use */

/*
 * FSD manipulation macros
 * The FSD macros are aligned on integer boundary even if the preceeding
 * record had a byte aligned length. So the record length is always
 * integer length. All increments of the data pointers must use the
 * FSD_RECSZ macro.
 */
#define	FSD_TPSZ(fsdp)		(sizeof (fsdp->fsd_type))
#define	FSD_TPMSK(fsdp)		(FSD_TPSZ(fsdp) - 1)
#define	FSD_RECSZ(fsdp, size)	((size + FSD_TPMSK(fsdp)) & ~FSD_TPMSK(fsdp))
/*
 * flags for acl_validate
 */
#define	ACL_CHECK	0x01
#define	DEF_ACL_CHECK	0x02

#define	MODE_CHECK(O, M, PERM, C, I) \
    secpolicy_vnode_access2(C, ITOV(I), O, (PERM), M)

/*
 * Check that the file type is one that accepts ACLs
 */
#define	CHECK_ACL_ALLOWED(MODE) (((MODE) == IFDIR) || ((MODE) == IFREG) || \
				((MODE) == IFIFO) || ((MODE) == IFCHR) || \
				((MODE) == IFBLK) || ((MODE) == IFATTRDIR))

/*
 * Get ACL group permissions if the mask is not present, and the ACL
 * group permission intersected with the mask if the mask is present
 */
#define	MASK2MODE(ACL)							\
	((ACL)->aclass.acl_ismask ?					\
		((((ACL)->aclass.acl_maskbits &				\
			(ACL)->agroup->acl_ic_perm) & 07) << 3) :	\
		(((ACL)->agroup->acl_ic_perm & 07) << 3))

#define	MODE2ACL(P, MODE, CRED)					\
	ASSERT((P));						\
	(P)->acl_ic_next = NULL;				\
	(P)->acl_ic_perm &= ((MODE) & 7);			\
	(P)->acl_ic_who = (CRED);

#define	ACL_MOVE(P, T, B)					\
{								\
	ufs_ic_acl_t *acl;					\
	for (acl = (P); acl; acl = acl->acl_ic_next) {		\
		(B)->acl_tag = (T);				\
		(B)->acl_perm = acl->acl_ic_perm;		\
		(B)->acl_who = acl->acl_ic_who;			\
		(B)++;						\
	}							\
}

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_ACL_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1997,2001 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _SYS_FS_UFS_BIO_H
#define	_SYS_FS_UFS_BIO_H

#include <sys/t_lock.h>
#include <sys/kstat.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Statistics on ufs buffer cache
 * Not protected by locks
 */
struct ufsbiostats {
	kstat_named_t ub_breads;	/* ufs_bread */
	kstat_named_t ub_bwrites;	/* ufs_bwrite and ufs_bwrite2 */
	kstat_named_t ub_fbiwrites;	/* ufs_fbiwrite */
	kstat_named_t ub_getpages;	/* ufs_getpage_miss */
	kstat_named_t ub_getras;	/* ufs_getpage_ra */
	kstat_named_t ub_putsyncs;	/* ufs_putapage (B_SYNC) */
	kstat_named_t ub_putasyncs;	/* ufs_putapage (B_ASYNC) */
	kstat_named_t ub_pageios;	/* ufs_pageios (swap) */
};

extern struct ufsbiostats ub;

#if defined(_KERNEL)

/*
 * let's define macros for the ufs_bio calls (as they were originally
 * defined name-wise).  using these macros to access the appropriate
 * *_common routines to minimize subroutine calls.
 */
extern struct buf *bread_common(void *arg, dev_t dev,
					daddr_t blkno, long bsize);
extern void bwrite_common(void *arg, struct buf *bp, int force_wait,
					int do_relse, int clear_flags);
extern struct buf *getblk_common(void * arg, dev_t dev,
					daddr_t blkno, long bsize, int flag);

#define	UFS_BREAD(ufsvfsp, dev, blkno, bsize)	\
	bread_common(ufsvfsp, dev, blkno, bsize)
#define	UFS_BWRITE(ufsvfsp, bp)	\
	bwrite_common(ufsvfsp, bp, /* force_wait */ 0, /* do_relse */ 1, \
	/* clear_flags */ (B_READ | B_DONE | B_ERROR | B_DELWRI))
#define	UFS_BRWRITE(ufsvfsp, bp)	\
	(bp)->b_flags |= B_RETRYWRI; \
	bwrite_common(ufsvfsp, bp, /* force_wait */ 0, /* do_relse */ 1, \
	/* clear_flags */ (B_READ | B_DONE | B_ERROR | B_DELWRI))
#define	UFS_BWRITE2(ufsvfsp, bp) \
	bwrite_common(ufsvfsp, bp, /* force_wait */ 1, /* do_relse */ 0, \
	/* clear_flags */ (B_READ | B_DONE | B_ERROR | B_DELWRI))
#define	UFS_GETBLK(ufsvfsp, dev, blkno, bsize)	\
	getblk_common(ufsvfsp, dev, blkno, bsize, /* errflg */ 0)

#endif	/* defined(_KERNEL) */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_BIO_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
 *
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_FS_UFS_FILIO_H
#define	_SYS_FS_UFS_FILIO_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * _FIOIO
 *
 * struct for _FIOIO ioctl():
 *	Input:
 *		fio_ino	- inode number
 *		fio_gen	- generation number
 *	Output:
 *		fio_fd	- readonly file descriptor
 *
 */

struct fioio {
	ino_t	fio_ino;	/* input : inode number */
	int	fio_gen;	/* input : generation number */
	int	fio_fd;		/* output: readonly file descriptor */
};

#if defined(_SYSCALL32)

struct fioio32 {
	ino32_t	fio_ino;	/* input : inode number */
	int32_t	fio_gen;	/* input : generation number */
	int32_t	fio_fd;		/* output: readonly file descriptor */
};

#endif	/* _SYSCALL32 */

/*
 * _FIOTUNE
 */
struct fiotune {
	int	maxcontig;	/* cluster and directio size */
	int	rotdelay;	/* skip blocks between contig allocations */
	int	maxbpg;		/* currently defaults to 2048 */
	int	minfree;	/* %age to reserve for root */
	int	optim;		/* space or time */
};

/*
 * UFS Logging
 */
typedef struct fiolog {
	uint_t	nbytes_requested;
	uint_t	nbytes_actual;
	int	error;
} fiolog_t;

#define	FIOLOG_ENONE	0
#define	FIOLOG_ETRANS	1
#define	FIOLOG_EROFS	2
#define	FIOLOG_EULOCK	3
#define	FIOLOG_EWLOCK	4
#define	FIOLOG_ECLEAN	5
#define	FIOLOG_ENOULOCK	6

#if defined(_KERNEL)

extern	int	ufs_fiosatime(struct vnode *, struct timeval *, int,
		struct cred *);
extern	int	ufs_fiosdio(struct vnode *, uint_t *, int flag, struct cred *);
extern	int	ufs_fiogdio(struct vnode *, uint_t *, int flag, struct cred *);
extern	int	ufs_fioio(struct vnode *, struct fioio *, int, struct cred *);
extern	int	ufs_fioisbusy(struct vnode *, int *, struct cred *);
extern	int	ufs_fiodirectio(struct vnode *, int, struct cred *);
extern	int	ufs_fiotune(struct vnode *, struct fiotune *, struct cred *);
extern	int	ufs_fiologenable(vnode_t *, fiolog_t *, cred_t *, int);
extern	int	ufs_fiologdisable(vnode_t *, fiolog_t *, cred_t *, int);
extern	int	ufs_fioislog(vnode_t *, uint32_t *, cred_t *, int);
extern	int	ufs_fio_holey(vnode_t *, int, offset_t *);
extern	int	ufs_mark_compressed(struct vnode *vp);

#endif	/* defined(_KERNEL) */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_FILIO_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/

/*
 * University Copyright- Copyright (c) 1982, 1986, 1988
 * The Regents of the University of California
 * All Rights Reserved
 *
 * University Acknowledgment- Portions of this document are derived from
 * software developed by the University of California, Berkeley, and its
 * contributors.
 */

#ifndef	_SYS_FS_UFS_FS_H
#define	_SYS_FS_UFS_FS_H

#include <sys/isa_defs.h>
#include <sys/types32.h>
#include <sys/t_lock.h>		/* for kmutex_t */

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * The following values are minor release values for UFS.
 * The fs_version field in the superblock will equal one of them.
 */

#define		MTB_UFS_VERSION_MIN	1
#define		MTB_UFS_VERSION_1	1
#define		UFS_VERSION_MIN	0
#define		UFS_EFISTYLE4NONEFI_VERSION_2	2

/*
 * Each disk drive contains some number of file systems.
 * A file system consists of a number of cylinder groups.
 * Each cylinder group has inodes and data.
 *
 * A file system is described by its super-block, which in turn
 * describes the cylinder groups.  The super-block is critical
 * data and is replicated in the first 10 cylinder groups and the
 * the last 10 cylinder groups to protect against
 * catastrophic loss.  This is done at mkfs time and the critical
 * super-block data does not change, so the copies need not be
 * referenced further unless disaster strikes.
 *
 * For file system fs, the offsets of the various blocks of interest
 * are given in the super block as:
 *	[fs->fs_sblkno]		Super-block
 *	[fs->fs_cblkno]		Cylinder group block
 *	[fs->fs_iblkno]		Inode blocks
 *	[fs->fs_dblkno]		Data blocks
 * The beginning of cylinder group cg in fs, is given by
 * the ``cgbase(fs, cg)'' macro.
 *
 * The first boot and super blocks are given in absolute disk addresses.
 * The byte-offset forms are preferred, as they don't imply a sector size.
 */
#define	BBSIZE		8192
#define	SBSIZE		8192
#define	BBOFF		((off_t)(0))
#define	SBOFF		((off_t)(BBOFF + BBSIZE))
#define	BBLOCK		((daddr32_t)(0))
#define	SBLOCK		((daddr32_t)(BBLOCK + BBSIZE / DEV_BSIZE))

/*
 * Addresses stored in inodes are capable of addressing fragments
 * of `blocks'. File system blocks of at most size MAXBSIZE can
 * be optionally broken into 2, 4, or 8 pieces, each of which is
 * addressible; these pieces may be DEV_BSIZE, or some multiple of
 * a DEV_BSIZE unit.
 *
 * Large files consist of exclusively large data blocks.  To avoid
 * undue wasted disk space, the last data block of a small file may be
 * allocated as only as many fragments of a large block as are
 * necessary.  The file system format retains only a single pointer
 * to such a fragment, which is a piece of a single large block that
 * has been divided.  The size of such a fragment is determinable from
 * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.
 *
 * The file system records space availability at the fragment level;
 * to determine block availability, aligned fragments are examined.
 *
 * The root inode is the root of the file system.
 * Inode 0 can't be used for normal purposes and
 * historically bad blocks were linked to inode 1,
 * thus the root inode is 2. (inode 1 is no longer used for
 * this purpose, however numerous dump tapes make this
 * assumption, so we are stuck with it)
 * The lost+found directory is given the next available
 * inode when it is created by ``mkfs''.
 */
#define	UFSROOTINO	((ino_t)2)	/* i number of all roots */
#define	LOSTFOUNDINO    (UFSROOTINO + 1)
#ifndef _LONGLONG_TYPE
#define	UFS_MAXOFFSET_T	MAXOFF_T
#define	UFS_FILESIZE_BITS	32
#else
#define	UFS_MAXOFFSET_T	((1LL << NBBY * sizeof (daddr32_t) + DEV_BSHIFT - 1) \
							- 1)
#define	UFS_FILESIZE_BITS	41
#endif /* _LONGLONG_TYPE */

/*
 * MINBSIZE is the smallest allowable block size.
 * In order to insure that it is possible to create files of size
 * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.
 * MINBSIZE must be big enough to hold a cylinder group block,
 * thus changes to (struct cg) must keep its size within MINBSIZE.
 * Note that super blocks are always of size SBSIZE,
 * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE.
 */
#define	MINBSIZE	4096

/*
 * The path name on which the file system is mounted is maintained
 * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in
 * the super block for this name.
 * The limit on the amount of summary information per file system
 * is defined by MAXCSBUFS. It is currently parameterized for a
 * maximum of two million cylinders.
 */
#define	MAXMNTLEN 512
#define	MAXCSBUFS 32

#define	LABEL_TYPE_VTOC		1
#define	LABEL_TYPE_EFI		2
#define	LABEL_TYPE_OTHER	3

/*
 * The following constant is taken from the ANSI T13 ATA Specification
 * and defines the maximum size (in sectors) that an ATA disk can be
 * and still has to provide CHS translation. For a disk above this
 * size all sectors are to be accessed via their LBA address. This
 * makes a good cut off value to move from disk provided geometry
 * to the predefined defaults used in efi label disks.
 */
#define	CHSLIMIT	(63 * 256 * 1024)

/*
 * Per cylinder group information; summarized in blocks allocated
 * from first cylinder group data blocks.  These blocks have to be
 * read in from fs_csaddr (size fs_cssize) in addition to the
 * super block.
 *
 * N.B. sizeof (struct csum) must be a power of two in order for
 * the ``fs_cs'' macro to work (see below).
 */
struct csum {
	int32_t	cs_ndir;	/* number of directories */
	int32_t	cs_nbfree;	/* number of free blocks */
	int32_t	cs_nifree;	/* number of free inodes */
	int32_t	cs_nffree;	/* number of free frags */
};

/*
 * In the 5.0 release, the file system state flag in the superblock (fs_clean)
 * is now used. The value of fs_clean can be:
 *	FSACTIVE	file system may have fsck inconsistencies
 *	FSCLEAN		file system has successfully unmounted (implies
 *			everything is ok)
 *	FSSTABLE	No fsck inconsistencies, no guarantee on user data
 *	FSBAD		file system is mounted from a partition that is
 *			neither FSCLEAN or FSSTABLE
 *	FSSUSPEND	Clean flag processing is temporarily disabled
 *	FSLOG		Logging file system
 * Under this scheme, fsck can safely skip file systems that
 * are FSCLEAN or FSSTABLE.  To provide additional safeguard,
 * fs_clean information could be trusted only if
 * fs_state == FSOKAY - fs_time, where FSOKAY is a constant
 *
 * Note: mount(2) will now return ENOSPC if fs_clean is neither FSCLEAN nor
 * FSSTABLE, or fs_state is not valid.  The exceptions are the root or
 * the read-only partitions
 */

/*
 * Super block for a file system.
 *
 * Most of the data in the super block is read-only data and needs
 * no explicit locking to protect it. Exceptions are:
 *	fs_time
 *	fs_optim
 *	fs_cstotal
 *	fs_fmod
 *	fs_cgrotor
 *	fs_flags   (largefiles flag - set when a file grows large)
 * These fields require the use of fs->fs_lock.
 */
#define	FS_MAGIC	0x011954
#define	MTB_UFS_MAGIC	0xdecade
#define	FSOKAY		(0x7c269d38)
/*  #define	FSOKAY		(0x7c269d38 + 3) */
/*
 * fs_clean values
 */
#define	FSACTIVE	((char)0)
#define	FSCLEAN		((char)0x1)
#define	FSSTABLE	((char)0x2)
#define	FSBAD		((char)0xff)	/* mounted !FSCLEAN and !FSSTABLE */
#define	FSSUSPEND	((char)0xfe)	/* temporarily suspended */
#define	FSLOG		((char)0xfd)	/* logging fs */
#define	FSFIX		((char)0xfc)	/* being repaired while mounted */

/*
 * fs_flags values
 */
#define	FSLARGEFILES	((char)0x1)	/* largefiles exist on filesystem */

struct  fs {
	uint32_t fs_link;		/* linked list of file systems */
	uint32_t fs_rolled;		/* logging only: fs fully rolled */
	daddr32_t fs_sblkno;		/* addr of super-block in filesys */
	daddr32_t fs_cblkno;		/* offset of cyl-block in filesys */
	daddr32_t fs_iblkno;		/* offset of inode-blocks in filesys */
	daddr32_t fs_dblkno;		/* offset of first data after cg */
	int32_t	fs_cgoffset;		/* cylinder group offset in cylinder */
	int32_t	fs_cgmask;		/* used to calc mod fs_ntrak */
	time32_t fs_time;		/* last time written */
	int32_t	fs_size;		/* number of blocks in fs */
	int32_t	fs_dsize;		/* number of data blocks in fs */
	int32_t	fs_ncg;			/* number of cylinder groups */
	int32_t	fs_bsize;		/* size of basic blocks in fs */
	int32_t	fs_fsize;		/* size of frag blocks in fs */
	int32_t	fs_frag;		/* number of frags in a block in fs */
/* these are configuration parameters */
	int32_t	fs_minfree;		/* minimum percentage of free blocks */
	int32_t	fs_rotdelay;		/* num of ms for optimal next block */
	int32_t	fs_rps;			/* disk revolutions per second */
/* these fields can be computed from the others */
	int32_t	fs_bmask;		/* ``blkoff'' calc of blk offsets */
	int32_t	fs_fmask;		/* ``fragoff'' calc of frag offsets */
	int32_t	fs_bshift;		/* ``lblkno'' calc of logical blkno */
	int32_t	fs_fshift;		/* ``numfrags'' calc number of frags */
/* these are configuration parameters */
	int32_t	fs_maxcontig;		/* max number of contiguous blks */
	int32_t	fs_maxbpg;		/* max number of blks per cyl group */
/* these fields can be computed from the others */
	int32_t	fs_fragshift;		/* block to frag shift */
	int32_t	fs_fsbtodb;		/* fsbtodb and dbtofsb shift constant */
	int32_t	fs_sbsize;		/* actual size of super block */
	int32_t	fs_csmask;		/* csum block offset */
	int32_t	fs_csshift;		/* csum block number */
	int32_t	fs_nindir;		/* value of NINDIR */
	int32_t	fs_inopb;		/* value of INOPB */
	int32_t	fs_nspf;		/* value of NSPF */
/* yet another configuration parameter */
	int32_t	fs_optim;		/* optimization preference, see below */
/* these fields are derived from the hardware */
	/* USL SVR4 compatibility */
#ifdef _LITTLE_ENDIAN
	/*
	 * USL SVR4 compatibility
	 *
	 * There was a significant divergence here between Solaris and
	 * SVR4 for x86.  By swapping these two members in the superblock,
	 * we get read-only compatibility of SVR4 filesystems.  Otherwise
	 * there would be no compatibility.  This change was introduced
	 * during bootstrapping of Solaris on x86.  By making this ifdef'ed
	 * on byte order, we provide ongoing compatibility across all
	 * platforms with the same byte order, the highest compatibility
	 * that can be achieved.
	 */
	int32_t	fs_state;		/* file system state time stamp */
#else
	int32_t	fs_npsect;		/* # sectors/track including spares */
#endif
	int32_t fs_si;			/* summary info state - lufs only */
	int32_t	fs_trackskew;		/* sector 0 skew, per track */
/* a unique id for this filesystem (currently unused and unmaintained) */
/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
/* Neither of those fields is used in the Tahoe code right now but */
/* there could be problems if they are.				*/
	int32_t	fs_id[2];		/* file system id */
/* sizes determined by number of cylinder groups and their sizes */
	daddr32_t fs_csaddr;		/* blk addr of cyl grp summary area */
	int32_t	fs_cssize;		/* size of cyl grp summary area */
	int32_t	fs_cgsize;		/* cylinder group size */
/* these fields are derived from the hardware */
	int32_t	fs_ntrak;		/* tracks per cylinder */
	int32_t	fs_nsect;		/* sectors per track */
	int32_t	fs_spc;			/* sectors per cylinder */
/* this comes from the disk driver partitioning */
	int32_t	fs_ncyl;		/* cylinders in file system */
/* these fields can be computed from the others */
	int32_t	fs_cpg;			/* cylinders per group */
	int32_t	fs_ipg;			/* inodes per group */
	int32_t	fs_fpg;			/* blocks per group * fs_frag */
/* this data must be re-computed after crashes */
	struct	csum fs_cstotal;	/* cylinder summary information */
/* these fields are cleared at mount time */
	char	fs_fmod;		/* super block modified flag */
	char	fs_clean;		/* file system state flag */
	char	fs_ronly;		/* mounted read-only flag */
	char	fs_flags;		/* largefiles flag, etc. */
	char	fs_fsmnt[MAXMNTLEN];	/* name mounted on */
/* these fields retain the current block allocation info */
	int32_t	fs_cgrotor;		/* last cg searched */
	/*
	 * The following used to be fs_csp[MAXCSBUFS]. It was not
	 * used anywhere except in old utilities.  We removed this
	 * in 5.6 and expect fs_u.fs_csp to be used instead.
	 * We no longer limit fs_cssize based on MAXCSBUFS.
	 */
	union { 			/* fs_cs (csum) info */
		uint32_t fs_csp_pad[MAXCSBUFS];
		struct csum *fs_csp;
	} fs_u;
	int32_t	fs_cpc;			/* cyl per cycle in postbl */
	short	fs_opostbl[16][8];	/* old rotation block list head */
	int32_t	fs_sparecon[51];	/* reserved for future constants */
	int32_t fs_version;		/* minor version of ufs */
	int32_t	fs_logbno;		/* block # of embedded log */
	int32_t fs_reclaim;		/* reclaim open, deleted files */
	int32_t	fs_sparecon2;		/* reserved for future constant */
#ifdef _LITTLE_ENDIAN
	/* USL SVR4 compatibility */
	int32_t	fs_npsect;		/* # sectors/track including spares */
#else
	int32_t	fs_state;		/* file system state time stamp */
#endif
	quad_t	fs_qbmask;		/* ~fs_bmask - for use with quad size */
	quad_t	fs_qfmask;		/* ~fs_fmask - for use with quad size */
	int32_t	fs_postblformat;	/* format of positional layout tables */
	int32_t	fs_nrpos;		/* number of rotaional positions */
	int32_t	fs_postbloff;		/* (short) rotation block list head */
	int32_t	fs_rotbloff;		/* (uchar_t) blocks for each rotation */
	int32_t	fs_magic;		/* magic number */
	uchar_t	fs_space[1];		/* list of blocks for each rotation */
/* actually longer */
};

/*
 * values for fs_reclaim
 */
#define	FS_RECLAIM	(0x00000001)	/* run the reclaim-files thread */
#define	FS_RECLAIMING	(0x00000002)	/* running the reclaim-files thread */
#define	FS_CHECKCLEAN	(0x00000004)	/* checking for a clean file system */
#define	FS_CHECKRECLAIM	(0x00000008)	/* checking for a reclaimable file */

/*
 * values for fs_rolled
 */
#define	FS_PRE_FLAG	0	/* old system, prior to fs_rolled flag */
#define	FS_ALL_ROLLED	1
#define	FS_NEED_ROLL	2

/*
 * values for fs_si, logging only
 * si is the summary of the summary - a copy of the cylinder group summary
 * info held in an array for perf. On a mount if this is out of date
 * (FS_SI_BAD) it can be re-constructed by re-reading the cgs.
 */
#define	FS_SI_OK	0	/* on-disk summary info ok */
#define	FS_SI_BAD	1	/* out of date on-disk si */

/*
 * Preference for optimization.
 */
#define	FS_OPTTIME	0	/* minimize allocation time */
#define	FS_OPTSPACE	1	/* minimize disk fragmentation */

/*
 * Rotational layout table format types
 */
#define	FS_42POSTBLFMT		-1	/* 4.2BSD rotational table format */
#define	FS_DYNAMICPOSTBLFMT	1	/* dynamic rotational table format */

/*
 * Macros for access to superblock array structures
 */
#ifdef _KERNEL
#define	fs_postbl(ufsvfsp, cylno) \
	(((ufsvfsp)->vfs_fs->fs_postblformat != FS_DYNAMICPOSTBLFMT) \
	? ((ufsvfsp)->vfs_fs->fs_opostbl[cylno]) \
	: ((short *)((char *)(ufsvfsp)->vfs_fs + \
	(ufsvfsp)->vfs_fs->fs_postbloff) \
	+ (cylno) * (ufsvfsp)->vfs_nrpos))
#else
#define	fs_postbl(fs, cylno) \
	(((fs)->fs_postblformat != FS_DYNAMICPOSTBLFMT) \
	? ((fs)->fs_opostbl[cylno]) \
	: ((short *)((char *)(fs) + \
	(fs)->fs_postbloff) \
	+ (cylno) * (fs)->fs_nrpos))
#endif

#define	fs_rotbl(fs) \
	(((fs)->fs_postblformat != FS_DYNAMICPOSTBLFMT) \
	? ((fs)->fs_space) \
	: ((uchar_t *)((char *)(fs) + (fs)->fs_rotbloff)))

/*
 * Convert cylinder group to base address of its global summary info.
 *
 * N.B. This macro assumes that sizeof (struct csum) is a power of two.
 * We just index off the first entry into one big array
 */

#define	fs_cs(fs, indx) fs_u.fs_csp[(indx)]

/*
 * Cylinder group block for a file system.
 *
 * Writable fields in the cylinder group are protected by the associated
 * super block lock fs->fs_lock.
 */
#define	CG_MAGIC	0x090255
struct	cg {
	uint32_t cg_link;		/* NOT USED linked list of cyl groups */
	int32_t	cg_magic;		/* magic number */
	time32_t cg_time;		/* time last written */
	int32_t	cg_cgx;			/* we are the cgx'th cylinder group */
	short	cg_ncyl;		/* number of cyl's this cg */
	short	cg_niblk;		/* number of inode blocks this cg */
	int32_t	cg_ndblk;		/* number of data blocks this cg */
	struct	csum cg_cs;		/* cylinder summary information */
	int32_t	cg_rotor;		/* position of last used block */
	int32_t	cg_frotor;		/* position of last used frag */
	int32_t	cg_irotor;		/* position of last used inode */
	int32_t	cg_frsum[MAXFRAG];	/* counts of available frags */
	int32_t	cg_btotoff;		/* (int32_t)block totals per cylinder */
	int32_t	cg_boff;		/* (short) free block positions */
	int32_t	cg_iusedoff;		/* (char) used inode map */
	int32_t	cg_freeoff;		/* (uchar_t) free block map */
	int32_t	cg_nextfreeoff;		/* (uchar_t) next available space */
	int32_t	cg_sparecon[16];	/* reserved for future use */
	uchar_t	cg_space[1];		/* space for cylinder group maps */
/* actually longer */
};

/*
 * Macros for access to cylinder group array structures
 */

#define	cg_blktot(cgp) \
	(((cgp)->cg_magic != CG_MAGIC) \
	? (((struct ocg *)(cgp))->cg_btot) \
	: ((int32_t *)((char *)(cgp) + (cgp)->cg_btotoff)))

#ifdef _KERNEL
#define	cg_blks(ufsvfsp, cgp, cylno) \
	(((cgp)->cg_magic != CG_MAGIC) \
	? (((struct ocg *)(cgp))->cg_b[cylno]) \
	: ((short *)((char *)(cgp) + (cgp)->cg_boff) + \
	(cylno) * (ufsvfsp)->vfs_nrpos))
#else
#define	cg_blks(fs, cgp, cylno) \
	(((cgp)->cg_magic != CG_MAGIC) \
	? (((struct ocg *)(cgp))->cg_b[cylno]) \
	: ((short *)((char *)(cgp) + (cgp)->cg_boff) + \
	(cylno) * (fs)->fs_nrpos))
#endif

#define	cg_inosused(cgp) \
	(((cgp)->cg_magic != CG_MAGIC) \
	? (((struct ocg *)(cgp))->cg_iused) \
	: ((char *)((char *)(cgp) + (cgp)->cg_iusedoff)))

#define	cg_blksfree(cgp) \
	(((cgp)->cg_magic != CG_MAGIC) \
	? (((struct ocg *)(cgp))->cg_free) \
	: ((uchar_t *)((char *)(cgp) + (cgp)->cg_freeoff)))

#define	cg_chkmagic(cgp) \
	((cgp)->cg_magic == CG_MAGIC || \
	((struct ocg *)(cgp))->cg_magic == CG_MAGIC)

/*
 * The following structure is defined
 * for compatibility with old file systems.
 */
struct	ocg {
	uint32_t cg_link;		/* NOT USED linked list of cyl groups */
	uint32_t cg_rlink;		/* NOT USED incore cyl groups */
	time32_t cg_time;		/* time last written */
	int32_t	cg_cgx;			/* we are the cgx'th cylinder group */
	short	cg_ncyl;		/* number of cyl's this cg */
	short	cg_niblk;		/* number of inode blocks this cg */
	int32_t	cg_ndblk;		/* number of data blocks this cg */
	struct	csum cg_cs;		/* cylinder summary information */
	int32_t	cg_rotor;		/* position of last used block */
	int32_t	cg_frotor;		/* position of last used frag */
	int32_t	cg_irotor;		/* position of last used inode */
	int32_t	cg_frsum[8];		/* counts of available frags */
	int32_t	cg_btot[32];		/* block totals per cylinder */
	short	cg_b[32][8];		/* positions of free blocks */
	char	cg_iused[256];		/* used inode map */
	int32_t	cg_magic;		/* magic number */
	uchar_t	cg_free[1];		/* free block map */
/* actually longer */
};

/*
 * Turn frag offsets into disk block addresses.
 * This maps frags to device size blocks.
 * (In the names of these macros, "fsb" refers to "frags", not
 * file system blocks.)
 */
#ifdef KERNEL
#define	fsbtodb(fs, b)	(((daddr_t)(b)) << (fs)->fs_fsbtodb)
#else /* KERNEL */
#define	fsbtodb(fs, b)	(((diskaddr_t)(b)) << (fs)->fs_fsbtodb)
#endif /* KERNEL */

#define	dbtofsb(fs, b)	((b) >> (fs)->fs_fsbtodb)

/*
 * Get the offset of the log, in either sectors, frags, or file system
 * blocks.  The interpretation of the fs_logbno field depends on whether
 * this is UFS or MTB UFS.  (UFS stores the value as sectors.  MTBUFS
 * stores the value as frags.)
 */

#ifdef KERNEL
#define	logbtodb(fs, b)	((fs)->fs_magic == FS_MAGIC ? \
		(daddr_t)(b) : ((daddr_t)(b) << (fs)->fs_fsbtodb))
#else /* KERNEL */
#define	logbtodb(fs, b)	((fs)->fs_magic == FS_MAGIC ? \
		(diskaddr_t)(b) : ((diskaddr_t)(b) << (fs)->fs_fsbtodb))
#endif /* KERNEL */
#define	logbtofrag(fs, b)	((fs)->fs_magic == FS_MAGIC ? \
		(b) >> (fs)->fs_fsbtodb : (b))
#define	logbtofsblk(fs, b) ((fs)->fs_magic == FS_MAGIC ? \
		(b) >> ((fs)->fs_fsbtodb + (fs)->fs_fragshift) : \
		(b) >> (fs)->fs_fragshift)

/*
 * Cylinder group macros to locate things in cylinder groups.
 * They calc file system addresses of cylinder group data structures.
 */
#define	cgbase(fs, c)	((daddr32_t)((fs)->fs_fpg * (c)))

#define	cgstart(fs, c) \
	(cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))

#define	cgsblock(fs, c)	(cgstart(fs, c) + (fs)->fs_sblkno)	/* super blk */

#define	cgtod(fs, c)	(cgstart(fs, c) + (fs)->fs_cblkno)	/* cg block */

#define	cgimin(fs, c)	(cgstart(fs, c) + (fs)->fs_iblkno)	/* inode blk */

#define	cgdmin(fs, c)	(cgstart(fs, c) + (fs)->fs_dblkno)	/* 1st data */

/*
 * Macros for handling inode numbers:
 *	inode number to file system block offset.
 *	inode number to cylinder group number.
 *	inode number to file system block address.
 */
#define	itoo(fs, x)	((x) % (uint32_t)INOPB(fs))

#define	itog(fs, x)	((x) / (uint32_t)(fs)->fs_ipg)

#define	itod(fs, x) \
	((daddr32_t)(cgimin(fs, itog(fs, x)) + \
	(blkstofrags((fs), (((x)%(ulong_t)(fs)->fs_ipg)/(ulong_t)INOPB(fs))))))

/*
 * Give cylinder group number for a file system block.
 * Give cylinder group block number for a file system block.
 */
#define	dtog(fs, d)	((d) / (fs)->fs_fpg)
#define	dtogd(fs, d)	((d) % (fs)->fs_fpg)

/*
 * Extract the bits for a block from a map.
 * Compute the cylinder and rotational position of a cyl block addr.
 */
#define	blkmap(fs, map, loc) \
	(((map)[(loc) / NBBY] >> ((loc) % NBBY)) & \
	(0xff >> (NBBY - (fs)->fs_frag)))

#define	cbtocylno(fs, bno) \
	((bno) * NSPF(fs) / (fs)->fs_spc)

#ifdef _KERNEL
#define	cbtorpos(ufsvfsp, bno) \
	((((bno) * NSPF((ufsvfsp)->vfs_fs) % (ufsvfsp)->vfs_fs->fs_spc) % \
	(ufsvfsp)->vfs_fs->fs_nsect) * \
	(ufsvfsp)->vfs_nrpos) / (ufsvfsp)->vfs_fs->fs_nsect
#else
#define	cbtorpos(fs, bno) \
	((((bno) * NSPF(fs) % (fs)->fs_spc) % \
	(fs)->fs_nsect) * \
	(fs)->fs_nrpos) / (fs)->fs_nsect
#endif

/*
 * The following macros optimize certain frequently calculated
 * quantities by using shifts and masks in place of divisions
 * modulos and multiplications.
 */

/*
 * This macro works for 40 bit offset support in ufs because
 * this calculates offset in the block and therefore no loss of
 * information while casting to int.
 */

#define	blkoff(fs, loc)		/* calculates (loc % fs->fs_bsize) */ \
	((int)((loc) & ~(fs)->fs_bmask))

/*
 * This macro works for 40 bit offset support similar to blkoff
 */

#define	fragoff(fs, loc)	/* calculates (loc % fs->fs_fsize) */ \
	((int)((loc) & ~(fs)->fs_fmask))

/*
 * The cast to int32_t does not result in any loss of information because
 * the number of logical blocks in the file system is limited to
 * what fits in an int32_t anyway.
 */

#define	lblkno(fs, loc)		/* calculates (loc / fs->fs_bsize) */ \
	((int32_t)((loc) >> (fs)->fs_bshift))

/*
 * The same argument as above applies here.
 */

#define	numfrags(fs, loc)	/* calculates (loc / fs->fs_fsize) */ \
	((int32_t)((loc) >> (fs)->fs_fshift))

/*
 * Size can be a 64-bit value and therefore we sign extend fs_bmask
 * to a 64-bit value too so that the higher 32 bits are masked
 * properly. Note that the type of fs_bmask has to be signed. Otherwise
 * compiler will set the higher 32 bits as zero and we don't want
 * this to happen.
 */

#define	blkroundup(fs, size)	/* calculates roundup(size, fs->fs_bsize) */ \
	(((size) + (fs)->fs_bsize - 1) & (offset_t)(fs)->fs_bmask)

/*
 * Same argument as above.
 */

#define	fragroundup(fs, size)	/* calculates roundup(size, fs->fs_fsize) */ \
	(((size) + (fs)->fs_fsize - 1) & (offset_t)(fs)->fs_fmask)

/*
 * frags cannot exceed 32-bit value since we only support 40bit sizes.
 */

#define	fragstoblks(fs, frags)	/* calculates (frags / fs->fs_frag) */ \
	((frags) >> (fs)->fs_fragshift)

#define	blkstofrags(fs, blks)	/* calculates (blks * fs->fs_frag) */ \
	((blks) << (fs)->fs_fragshift)

#define	fragnum(fs, fsb)	/* calculates (fsb % fs->fs_frag) */ \
	((fsb) & ((fs)->fs_frag - 1))

#define	blknum(fs, fsb)		/* calculates rounddown(fsb, fs->fs_frag) */ \
	((fsb) &~ ((fs)->fs_frag - 1))

/*
 * Determine the number of available frags given a
 * percentage to hold in reserve
 */
#define	freespace(fs, ufsvfsp) \
	((blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \
	(fs)->fs_cstotal.cs_nffree) - (ufsvfsp)->vfs_minfrags)

/*
 * Determining the size of a file block in the file system.
 */

#define	blksize(fs, ip, lbn) \
	(((lbn) >= NDADDR || \
	(ip)->i_size >= (offset_t)((lbn) + 1) << (fs)->fs_bshift) \
	    ? (fs)->fs_bsize \
	    : (fragroundup(fs, blkoff(fs, (ip)->i_size))))

#define	dblksize(fs, dip, lbn) \
	(((lbn) >= NDADDR || \
	(dip)->di_size >= (offset_t)((lbn) + 1) << (fs)->fs_bshift) \
	    ? (fs)->fs_bsize \
	    : (fragroundup(fs, blkoff(fs, (dip)->di_size))))

/*
 * Number of disk sectors per block; assumes DEV_BSIZE byte sector size.
 */
#define	NSPB(fs)	((fs)->fs_nspf << (fs)->fs_fragshift)
#define	NSPF(fs)	((fs)->fs_nspf)

/*
 * INOPB is the number of inodes in a secondary storage block.
 */
#define	INOPB(fs)	((fs)->fs_inopb)
#define	INOPF(fs)	((fs)->fs_inopb >> (fs)->fs_fragshift)

/*
 * NINDIR is the number of indirects in a file system block.
 */
#define	NINDIR(fs)	((fs)->fs_nindir)

/*
 * bit map related macros
 */
#define	bitloc(a, i)	((a)[(i)/NBBY])
#define	setbit(a, i)	((a)[(i)/NBBY] |= 1<<((i)%NBBY))
#define	clrbit(a, i)	((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
#define	isset(a, i)	((a)[(i)/NBBY] & (1<<((i)%NBBY)))
#define	isclr(a, i)	(((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)

#define	getfs(vfsp) \
	((struct fs *)((struct ufsvfs *)vfsp->vfs_data)->vfs_bufp->b_un.b_addr)

#define	RETRY_LOCK_DELAY 1

/*
 * Macros to test and acquire i_rwlock:
 * some vnops hold the target directory's i_rwlock after calling
 * ufs_lockfs_begin but in many other operations (like ufs_readdir)
 * VOP_RWLOCK is explicitly called by the filesystem independent code before
 * calling the file system operation. In these cases the order is reversed
 * (i.e i_rwlock is taken first and then ufs_lockfs_begin is called). This
 * is fine as long as ufs_lockfs_begin acts as a VOP counter but with
 * ufs_quiesce setting the SLOCK bit this becomes a synchronizing
 * object which might lead to a deadlock. So we use rw_tryenter instead of
 * rw_enter. If we fail to get this lock and find that SLOCK bit is set, we
 * call ufs_lockfs_end and restart the operation.
 */

#define	ufs_tryirwlock(lock, mode, label) \
{\
	indeadlock = 0;\
label:\
	if (!rw_tryenter(lock, mode))\
	{\
		if (ulp && ULOCKFS_IS_SLOCK(ulp)) {\
			indeadlock = 1;\
		} else {\
			delay(RETRY_LOCK_DELAY);\
			goto  label;\
		}\
	}\
}

/*
 * The macro ufs_tryirwlock_trans is used in functions which call
 * TRANS_BEGIN_CSYNC and ufs_lockfs_begin, hence the need to call
 * TRANS_END_CSYNC and ufs_lockfs_end.
 */

#define	ufs_tryirwlock_trans(lock, mode, transmode, label) \
{\
	indeadlock = 0;\
label:\
	if (!rw_tryenter(lock, mode))\
	{\
		if (ulp && ULOCKFS_IS_SLOCK(ulp)) {\
			TRANS_END_CSYNC(ufsvfsp, error, issync,\
				transmode, trans_size);\
			ufs_lockfs_end(ulp);\
			indeadlock = 1;\
		} else {\
			delay(RETRY_LOCK_DELAY);\
			goto  label;\
		}\
	}\
}

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_FS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/

/*
 * University Copyright- Copyright (c) 1982, 1986, 1988
 * The Regents of the University of California
 * All Rights Reserved
 *
 * University Acknowledgment- Portions of this document are derived from
 * software developed by the University of California, Berkeley, and its
 * contributors.
 */

#ifndef	_SYS_FS_UFS_FSDIR_H
#define	_SYS_FS_UFS_FSDIR_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * A directory consists of some number of blocks of DIRBLKSIZ
 * bytes, where DIRBLKSIZ is chosen such that it can be transferred
 * to disk in a single atomic operation (e.g. 512 bytes on most machines).
 *
 * Each DIRBLKSIZ byte block contains some number of directory entry
 * structures, which are of variable length.  Each directory entry has
 * a struct direct at the front of it, containing its inode number,
 * the length of the entry, and the length of the name contained in
 * the entry.  These are followed by the name padded to a 4 byte boundary
 * with null bytes.  All names are guaranteed null terminated.
 * The maximum length of a name in a directory is MAXNAMLEN.
 *
 * The macro DIRSIZ(dp) gives the amount of space required to represent
 * a directory entry.  Free space in a directory is represented by
 * entries which have dp->d_reclen > DIRSIZ(dp).  All DIRBLKSIZ bytes
 * in a directory block are claimed by the directory entries.  This
 * usually results in the last entry in a directory having a large
 * dp->d_reclen.  When entries are deleted from a directory, the
 * space is returned to the previous entry in the same directory
 * block by increasing its dp->d_reclen.  If the first entry of
 * a directory block is free, then its dp->d_ino is set to 0.
 * Entries other than the first in a directory do not normally have
 * dp->d_ino set to 0.
 */
#define	DIRBLKSIZ	DEV_BSIZE
#define	MAXNAMLEN	255

struct	direct {
	uint32_t	d_ino;		/* inode number of entry */
	ushort_t	d_reclen;	/* length of this record */
	ushort_t	d_namlen;	/* length of string in d_name */
	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
};

/*
 * The DIRSIZ macro gives the minimum record length which will hold
 * the directory entry.  This requires the amount of space in struct direct
 * without the d_name field, plus enough space for the name with a terminating
 * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
 */
#undef DIRSIZ
#define	DIRSIZ(dp) \
	((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1+3) &~ 3))

#ifdef _KERNEL
/*
 * Template for manipulating directories.
 * Should use struct direct's, but the name field
 * is MAXNAMLEN - 1, and this just won't do.
 */
struct dirtemplate {
	uint32_t	dot_ino;
	short		dot_reclen;
	short		dot_namlen;
	char		dot_name[4];		/* must be multiple of 4 */
	uint32_t	dotdot_ino;
	short		dotdot_reclen;
	short		dotdot_namlen;
	char		dotdot_name[4];		/* ditto */
};

/*
 * Reduced structure for manipulating directories.
 * Note, we are using __packed here to ensure the size of structure
 * without changing the alignment.
 */
struct tmp_dir {
	uint32_t	d_ino;		/* inode number of entry */
	ushort_t	d_reclen;	/* length of this record */
	ushort_t	d_namlen;	/* length of string in d_name */
	char		d_name[4];	/* name must be no longer than this */
} __packed;

#endif

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_FSDIR_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1983, 2010, Oracle and/or its affiliates. All rights reserved.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/

/*
 * University Copyright- Copyright (c) 1982, 1986, 1988
 * The Regents of the University of California
 * All Rights Reserved
 *
 * University Acknowledgment- Portions of this document are derived from
 * software developed by the University of California, Berkeley, and its
 * contributors.
 */

#ifndef	_SYS_FS_UFS_INODE_H
#define	_SYS_FS_UFS_INODE_H

#include <sys/isa_defs.h>
#include <sys/fbuf.h>
#include <sys/fdbuffer.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/t_lock.h>
#include <sys/thread.h>
#include <sys/cred.h>
#include <sys/time.h>
#include <sys/types32.h>
#include <sys/fs/ufs_fs.h>
#include <sys/fs/ufs_lockfs.h>
#include <sys/fs/ufs_trans.h>
#include <sys/kstat.h>
#include <sys/fs/ufs_acl.h>
#include <sys/fs/ufs_panic.h>
#include <sys/dnlc.h>

#ifdef _KERNEL
#include <sys/vfs_opreg.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * The I node is the focus of all local file activity in UNIX.
 * There is a unique inode allocated for each active file,
 * each current directory, each mounted-on file, each mapping,
 * and the root.  An inode is `named' by its dev/inumber pair.
 * Data in icommon is read in from permanent inode on volume.
 *
 * Each inode has 5 locks associated with it:
 *	i_rwlock:	Serializes ufs_write and ufs_setattr request
 *			and allows ufs_read requests to proceed in parallel.
 *			Serializes reads/updates to directories.
 *	vfs_dqrwlock:	Manages quota sub-system quiescence.  See below.
 *	i_contents:	Protects almost all of the fields in the inode
 *			except for those listed below. When held
 *			in writer mode also protects those fields
 *			listed under i_tlock.
 *	i_tlock:	When i_tlock is held with the i_contents reader
 *			lock the i_atime, i_mtime, i_ctime,
 *			i_delayoff, i_delaylen, i_nextrio, i_writes, i_flag
 *			i_seq, i_writer & i_mapcnt fields are protected.
 *			For more i_flag locking info see below.
 *	ih_lock:	Protects inode hash chain buckets
 *	ifree_lock:	Protects inode freelist
 *
 * Lock ordering:
 *	i_rwlock > i_contents > i_tlock
 *	i_rwlock > vfs_dqrwlock > i_contents(writer) > i_tlock
 *	i_contents > i_tlock
 *	vfs_dqrwlock > i_contents(writer) > i_tlock
 *	ih_lock > i_contents > i_tlock
 *
 * Making major changes to quota sub-system state, while the file
 * system is mounted required the addition of another lock.  The
 * primary lock in the quota sub-system is vfs_dqrwlock in the ufsvfs
 * structure.  This lock is used to manage quota sub-system quiescence
 * for a particular file system. Major changes to quota sub-system
 * state (disabling quotas, enabling quotas, and setting new quota
 * limits) all require the file system to be quiescent and grabbing
 * vfs_dqrwlock as writer accomplishes this.  On the other hand,
 * grabbing vfs_dqrwlock as reader makes the quota sub-system
 * non-quiescent and lets the quota sub-system know that now is not a
 * good time to change major quota sub-system state.  Typically
 * vfs_dqrwlock is grabbed for reading before i_contents is grabbed for
 * writing.  However, there are cases where vfs_dqrwlock is grabbed for
 * reading without a corresponding i_contents write grab because there
 * is no relevant inode.  There are also cases where i_contents is
 * grabbed for writing when a vfs_dqrwlock read grab is not needed
 * because the inode changes do not affect quotas.
 *
 * Unfortunately, performance considerations have required that we be more
 * intelligent about using i_tlock when updating i_flag.  Ideally, we would
 * have simply separated out several of the bits in i_flag into their own
 * ints to avoid problems.  But, instead, we have implemented the following
 * rules:
 *
 *	o You can update any i_flag field while holding the writer-contents,
 *	  or by holding the reader-contents AND holding i_tlock.
 *	  You can only call ITIMES_NOLOCK while holding the writer-contents,
 *	  or by holding the reader-contents AND holding i_tlock.
 *
 *	o For a directory, holding the reader-rw_lock is sufficient for setting
 *	  IACC.
 *
 *	o Races with IREF are avoided by holding the reader contents lock
 *	  and by holding i_tlock in ufs_rmidle, ufs_putapage, and ufs_getpage.
 *	  And by holding the writer-contents in ufs_iinactive.
 *
 *	o The callers are no longer required to handle the calls to ITIMES
 *	  and ITIMES_NOLOCK.  The functions that set the i_flag bits are
 *	  responsible for managing those calls.  The exceptions are the
 *	  bmap routines.
 *
 * SVR4 Extended Fundamental Type (EFT) support:
 *	The inode structure has been enhanced to support
 *	32-bit user-id, 32-bit group-id, and 32-bit device number.
 *	Standard SVR4 ufs also supports 32-bit mode field.  For the reason
 *	of backward compatibility with the previous ufs disk format,
 *	32-bit mode field is not supported.
 *
 *	The current inode structure is 100% backward compatible with
 *	the previous inode structure if no user-id or group-id exceeds
 *	USHRT_MAX, and no major or minor number of a device number
 *	stored in an inode exceeds 255.
 *
 * Rules for managing i_seq:
 *	o i_seq is locked under the same rules as i_flag
 *	o The i_ctime or i_mtime MUST never change without increasing
 *	  the value of i_seq.
 *	o You may increase the value of i_seq without the timestamps
 *	  changing, this may decrease the callers performance but will
 *	  be functionally correct.
 *	o The common case is when IUPD or ICHG is set, increase i_seq
 *	  and immediately call ITIMES* or ufs_iupdat to create a new timestamp.
 *	o A less common case is the setting of IUPD or ICHG and while still
 *	  holding the correct lock defer the timestamp and i_seq update
 *	  until later, but it must still be done before the lock is released.
 *	  bmap_write is an example of this, where the caller does the update.
 *	o If multiple changes are being made with the timestamps being
 *	  updated only at the end, a single increase of i_seq is allowed.
 *	o If changes are made with IUPD or ICHG being set, but
 *	  the controlling lock is being dropped before the timestamp is
 *	  updated, there is a risk that another thread will also change
 *	  the file, update i_flag, and push just one timestamp update.
 *	  There is also the risk that another thread calls ITIMES or
 *	  ufs_iupdat without setting IUPD|ICHG and thus not changing i_seq,
 *	  this will cause ufs_imark to change the timestamps without changing
 *	  i_seq. If the controlling lock is dropped, ISEQ must be set to
 *	  force i_seq to be increased on next ufs_imark, but i_seq MUST still
 *	  be increased by the original setting thread before its deferred
 *	  call to ITIMES to insure it is increased the correct number of times.
 */

#define	UID_LONG  (o_uid_t)65535
				/* flag value to indicate uid is 32-bit long */
#define	GID_LONG  (o_uid_t)65535
				/* flag value to indicate gid is 32-bit long */

#define	NDADDR	12		/* direct addresses in inode */
#define	NIADDR	3		/* indirect addresses in inode */
#define	FSL_SIZE (NDADDR + NIADDR - 1) * sizeof (daddr32_t)
				/* max fast symbolic name length is 56 */

#define	i_fs	i_ufsvfs->vfs_bufp->b_un.b_fs
#define	i_vfs	i_vnode->v_vfsp

struct icommon {
	o_mode_t ic_smode;	/*  0: mode and type of file */
	short	ic_nlink;	/*  2: number of links to file */
	o_uid_t	ic_suid;	/*  4: owner's user id */
	o_gid_t	ic_sgid;	/*  6: owner's group id */
	u_offset_t ic_lsize;	/*  8: number of bytes in file */
#ifdef _KERNEL
	struct timeval32 ic_atime;	/* 16: time last accessed */
	struct timeval32 ic_mtime;	/* 24: time last modified */
	struct timeval32 ic_ctime;	/* 32: last time inode changed */
#else
	time32_t ic_atime;	/* 16: time last accessed */
	int32_t	ic_atspare;
	time32_t ic_mtime;	/* 24: time last modified */
	int32_t	ic_mtspare;
	time32_t ic_ctime;	/* 32: last time inode changed */
	int32_t	ic_ctspare;
#endif
	daddr32_t	ic_db[NDADDR];	/* 40: disk block addresses */
	daddr32_t	ic_ib[NIADDR];	/* 88: indirect blocks */
	int32_t	ic_flags;	/* 100: cflags */
	int32_t	ic_blocks;	/* 104: 512 byte blocks actually held */
	int32_t	ic_gen;		/* 108: generation number */
	int32_t	ic_shadow;	/* 112: shadow inode */
	uid_t	ic_uid;		/* 116: long EFT version of uid */
	gid_t	ic_gid;		/* 120: long EFT version of gid */
	uint32_t ic_oeftflag;	/* 124: extended attr directory ino, 0 = none */
};

/*
 * Large directories can be cached. Directory caching can take the following
 * states:
 */
typedef enum {
	CD_DISABLED_NOMEM = -2,
	CD_DISABLED_TOOBIG,
	CD_DISABLED,
	CD_ENABLED
} cachedir_t;

/*
 * Large Files: Note we use the inline functions load_double, store_double
 * to load and store the long long values of i_size. Therefore the
 * address of i_size must be eight byte aligned. Kmem_alloc of incore
 * inode structure makes sure that the structure is 8-byte aligned.
 * XX64 - reorder this structure?
 */
typedef struct inode {
	struct	inode *i_chain[2];	/* must be first */
	struct inode *i_freef;	/* free list forward - must be before i_ic */
	struct inode *i_freeb;	/* free list back - must be before i_ic */
	struct	icommon	i_ic;	/* Must be here */
	struct	vnode *i_vnode;	/* vnode associated with this inode */
	struct	vnode *i_devvp;	/* vnode for block I/O */
	dev_t	i_dev;		/* device where inode resides */
	ino_t	i_number;	/* i number, 1-to-1 with device address */
	off_t	i_diroff;	/* offset in dir, where we found last entry */
				/* just a hint - no locking needed */
	struct ufsvfs *i_ufsvfs; /* incore fs associated with inode */
	struct	dquot *i_dquot;	/* quota structure controlling this file */
	krwlock_t i_rwlock;	/* serializes write/setattr requests */
	krwlock_t i_contents;	/* protects (most of) inode contents */
	kmutex_t i_tlock;	/* protects time fields, i_flag */
	offset_t i_nextr;	/*					*/
				/* next byte read offset (read-ahead)	*/
				/*   No lock required			*/
				/*					*/
	uint_t	i_flag;		/* inode flags */
	uint_t	i_seq;		/* modification sequence number */
	cachedir_t i_cachedir;	/* Cache this directory on next lookup */
				/* - no locking needed  */
	long	i_mapcnt;	/* mappings to file pages */
	int	*i_map;		/* block list for the corresponding file */
	dev_t	i_rdev;		/* INCORE rdev from i_oldrdev by ufs_iget */
	size_t	i_delaylen;	/* delayed writes, units=bytes */
	offset_t i_delayoff;	/* where we started delaying */
	offset_t i_nextrio;	/* where to start the next clust */
	long	i_writes;	/* number of outstanding bytes in write q */
	kcondvar_t i_wrcv;	/* sleep/wakeup for write throttle */
	offset_t i_doff;	/* dinode byte offset in file system */
	si_t *i_ufs_acl;	/* pointer to acl entry */
	dcanchor_t i_danchor;	/* directory cache anchor */
	kthread_t *i_writer;	/* thread which is in window in wrip() */
} inode_t;

struct dinode {
	union {
		struct	icommon di_icom;
		char	di_size[128];
	} di_un;
};

#define	i_mode		i_ic.ic_smode
#define	i_nlink		i_ic.ic_nlink
#define	i_uid		i_ic.ic_uid
#define	i_gid		i_ic.ic_gid
#define	i_smode		i_ic.ic_smode
#define	i_suid		i_ic.ic_suid
#define	i_sgid		i_ic.ic_sgid

#define	i_size		i_ic.ic_lsize
#define	i_db		i_ic.ic_db
#define	i_ib		i_ic.ic_ib

#define	i_atime		i_ic.ic_atime
#define	i_mtime		i_ic.ic_mtime
#define	i_ctime		i_ic.ic_ctime

#define	i_shadow	i_ic.ic_shadow
#define	i_oeftflag	i_ic.ic_oeftflag
#define	i_blocks	i_ic.ic_blocks
#define	i_cflags	i_ic.ic_flags
#ifdef _LITTLE_ENDIAN
/*
 * Originally done on x86, but carried on to all other little
 * architectures, which provides for file system compatibility.
 */
#define	i_ordev		i_ic.ic_db[1]	/* USL SVR4 compatibility */
#else
#define	i_ordev		i_ic.ic_db[0]	/* was i_oldrdev */
#endif
#define	i_gen		i_ic.ic_gen
#define	i_forw		i_chain[0]
#define	i_back		i_chain[1]

/* EFT transition aids - obsolete */
#define	oEFT_MAGIC	0x90909090
#define	di_oeftflag	di_ic.ic_oeftflag

#define	di_ic		di_un.di_icom
#define	di_mode		di_ic.ic_smode
#define	di_nlink	di_ic.ic_nlink
#define	di_uid		di_ic.ic_uid
#define	di_gid		di_ic.ic_gid
#define	di_smode	di_ic.ic_smode
#define	di_suid		di_ic.ic_suid
#define	di_sgid		di_ic.ic_sgid

#define	di_size		di_ic.ic_lsize
#define	di_db		di_ic.ic_db
#define	di_ib		di_ic.ic_ib

#define	di_atime	di_ic.ic_atime
#define	di_mtime	di_ic.ic_mtime
#define	di_ctime	di_ic.ic_ctime
#define	di_cflags	di_ic.ic_flags

#ifdef _LITTLE_ENDIAN
#define	di_ordev	di_ic.ic_db[1]
#else
#define	di_ordev	di_ic.ic_db[0]
#endif
#define	di_shadow	di_ic.ic_shadow
#define	di_blocks	di_ic.ic_blocks
#define	di_gen		di_ic.ic_gen

/* flags */
#define	IUPD		0x0001		/* file has been modified */
#define	IACC		0x0002		/* inode access time to be updated */
#define	IMOD		0x0004		/* inode has been modified */
#define	ICHG		0x0008		/* inode has been changed */
#define	INOACC		0x0010		/* no access time update in getpage */
#define	IMODTIME	0x0020		/* mod time already set */
#define	IREF		0x0040		/* inode is being referenced */
#define	ISYNC		0x0080		/* do all allocation synchronously */
#define	IFASTSYMLNK	0x0100		/* fast symbolic link */
#define	IMODACC		0x0200		/* only access time changed; */
					/*   filesystem won't become active */
#define	IATTCHG		0x0400		/* only size/blocks have changed */
#define	IBDWRITE	0x0800		/* the inode has been scheduled for */
					/* write operation asynchronously */
#define	ISTALE		0x1000		/* inode couldn't be read from disk */
#define	IDEL		0x2000		/* inode is being deleted */
#define	IDIRECTIO	0x4000		/* attempt directio */
#define	ISEQ		0x8000		/* deferred i_seq increase */
#define	IJUNKIQ		0x10000		/* on junk idle queue */
#define	IQUIET		0x20000		/* No file system full messages */

/* cflags */
#define	IXATTR		0x0001		/* extended attribute */
#define	IFALLOCATE	0x0002		/* fallocate'd file */
#define	ICOMPRESS	0x0004		/* compressed for dcfs - see */
					/*   `ufs_ioctl()`_FIO_COMPRESSED */

/* modes */
#define	IFMT		0170000		/* type of file */
#define	IFIFO		0010000		/* named pipe (fifo) */
#define	IFCHR		0020000		/* character special */
#define	IFDIR		0040000		/* directory */
#define	IFBLK		0060000		/* block special */
#define	IFREG		0100000		/* regular */
#define	IFLNK		0120000		/* symbolic link */
#define	IFSHAD		0130000		/* shadow indode */
#define	IFSOCK		0140000		/* socket */
#define	IFATTRDIR	0160000		/* Attribute directory */

#define	ISUID		04000		/* set user id on execution */
#define	ISGID		02000		/* set group id on execution */
#define	ISVTX		01000		/* save swapped text even after use */
#define	IREAD		0400		/* read, write, execute permissions */
#define	IWRITE		0200
#define	IEXEC		0100

/* specify how the inode info is written in ufs_syncip() */
#define	I_SYNC		1		/* wait for the inode written to disk */
#define	I_DSYNC		2		/* wait for the inode written to disk */
					/* only if IATTCHG is set */
#define	I_ASYNC		0		/* don't wait for the inode written */

/* flags passed to ufs_itrunc(), indirtrunc(), and free() */
#define	I_FREE	0x00000001		/* inode is being freed */
#define	I_DIR	0x00000002		/* inode is a directory */
#define	I_IBLK	0x00000004		/* indirect block */
#define	I_CHEAP	0x00000008		/* cheap free */
#define	I_SHAD	0x00000010		/* inode is a shadow inode */
#define	I_QUOTA	0x00000020		/* quota file */
#define	I_NOCANCEL	0x40		/* Don't cancel these fragments */
#define	I_ACCT	0x00000080		/* Update ufsvfs' unreclaimed_blocks */

/*
 * If ufs_dircheckforname() fails to find an entry with the given name,
 * this "slot" structure holds state for ufs_direnter_*() as to where
 * there is space to put an entry with that name.
 * If ufs_dircheckforname() finds an entry with the given name, this structure
 * holds state for ufs_dirrename() and ufs_dirremove() as to where the
 * entry is. "status" indicates what ufs_dircheckforname() found:
 *      NONE            name not found, large enough free slot not found,
 *      FOUND           name not found, large enough free slot found
 *      EXIST           name found
 * If ufs_dircheckforname() fails due to an error, this structure is not
 * filled in.
 *
 * After ufs_dircheckforname() succeeds the values are:
 *      status  offset          size            fbp, ep
 *      ------  ------          ----            -------
 *      NONE    end of dir      needed          not valid
 *      FOUND   start of entry  of ent          both valid if fbp != NULL
 *      EXIST   start of entry  of prev ent     valid
 *
 * "endoff" is set to 0 if the an entry with the given name is found, or if no
 * free slot could be found or made; this means that the directory should not
 * be truncated.  If the entry was found, the search terminates so
 * ufs_dircheckforname() didn't find out where the last valid entry in the
 * directory was, so it doesn't know where to cut the directory off; if no free
 * slot could be found or made, the directory has to be extended to make room
 * for the new entry, so there's nothing to cut off.
 * Otherwise, "endoff" is set to the larger of the offset of the last
 * non-empty entry in the directory, or the offset at which the new entry will
 * be placed, whichever is larger.  This is used by ufs_diraddentry(); if a new
 * entry is to be added to the directory, any complete directory blocks at the
 * end of the directory that contain no non-empty entries are lopped off the
 * end, thus shrinking the directory dynamically.
 */
typedef enum {NONE, FOUND, EXIST} slotstat_t;
struct ufs_slot {
	struct	direct *ep;	/* pointer to slot */
	struct	fbuf *fbp;	/* dir buf where slot is */
	off_t	offset;		/* offset of area with free space */
	off_t	endoff;		/* last useful location found in search */
	slotstat_t status;	/* status of slot */
	int	size;		/* size of area at slotoffset */
	int	cached;		/* cached directory */
};

/*
 * Statistics on inodes
 * Not protected by locks
 */
struct instats {
	kstat_named_t in_size;		/* current cache size */
	kstat_named_t in_maxsize;	/* maximum cache size */
	kstat_named_t in_hits;		/* cache hits */
	kstat_named_t in_misses;	/* cache misses */
	kstat_named_t in_malloc;	/* kmem_alloce'd */
	kstat_named_t in_mfree;		/* kmem_free'd */
	kstat_named_t in_maxreached;	/* Largest size reached by cache */
	kstat_named_t in_frfront;	/* # put at front of freelist */
	kstat_named_t in_frback;	/* # put at back of freelist */
	kstat_named_t in_qfree;		/* q's to delete thread */
	kstat_named_t in_scan;		/* # inodes scanned */
	kstat_named_t in_tidles;	/* # inodes idled by idle thread */
	kstat_named_t in_lidles;	/* # inodes idled by ufs_lookup */
	kstat_named_t in_vidles;	/* # inodes idled by ufs_vget */
	kstat_named_t in_kcalloc;	/* # inodes kmem_cache_alloced */
	kstat_named_t in_kcfree;	/* # inodes kmem_cache_freed */
	kstat_named_t in_poc;		/* # push-on-close's */
};

#ifdef _KERNEL

/*
 * Extended attributes
 */

#define	XATTR_DIR_NAME	"/@/"
extern int	ufs_ninode;		/* high-water mark for inode cache */

extern struct vnodeops *ufs_vnodeops;	/* vnode operations for ufs */
extern const struct fs_operation_def ufs_vnodeops_template[];

/*
 * Convert between inode pointers and vnode pointers
 */
#define	VTOI(VP)	((struct inode *)(VP)->v_data)
#define	ITOV(IP)	((struct vnode *)(IP)->i_vnode)

/*
 * convert to fs
 */
#define	ITOF(IP)	((struct fs *)(IP)->i_fs)

/*
 * Convert between vnode types and inode formats
 */
extern enum vtype	iftovt_tab[];

#ifdef notneeded

/* Look at sys/mode.h and os/vnode.c */

extern int		vttoif_tab[];

#endif

/*
 * Mark an inode with the current (unique) timestamp.
 * (Note that UFS's concept of time only keeps 32 bits of seconds
 * in the on-disk format).
 */
extern struct timeval32 iuniqtime;
extern kmutex_t ufs_iuniqtime_lock;

#define	ITIMES_NOLOCK(ip) ufs_itimes_nolock(ip)

#define	ITIMES(ip) { \
	mutex_enter(&(ip)->i_tlock); \
	ITIMES_NOLOCK(ip); \
	mutex_exit(&(ip)->i_tlock); \
}

/*
 * The following interfaces are used to do atomic loads and stores
 * of an inode's i_size, which is a long long data type.
 *
 * For LP64, we just to a load or a store - atomicity and alignment
 * are 8-byte guaranteed.  For x86 there are no such instructions,
 * so we grab i_contents as reader to get the size; we already hold
 * it as writer when we're setting the size.
 */

#ifdef _LP64

#define	UFS_GET_ISIZE(resultp, ip)	*(resultp) = (ip)->i_size
#define	UFS_SET_ISIZE(value, ip)	(ip)->i_size = (value)

#else	/* _LP64 */

#define	UFS_GET_ISIZE(resultp, ip)				\
	{							\
		rw_enter(&(ip)->i_contents, RW_READER);		\
		*(resultp) = (ip)->i_size;			\
		rw_exit(&(ip)->i_contents);			\
	}
#define	UFS_SET_ISIZE(value, ip)				\
	{							\
		ASSERT(RW_WRITE_HELD(&(ip)->i_contents));	\
		(ip)->i_size = (value);				\
	}

#endif	/* _LP64 */

/*
 * Allocate the specified block in the inode
 * and make sure any in-core pages are initialized.
 */
#define	BMAPALLOC(ip, off, size, cr) \
	bmap_write((ip), (u_offset_t)(off), (size), BI_NORMAL, NULL, cr)

#define	ESAME	(-1)		/* trying to rename linked files (special) */

#define	UFS_HOLE	(daddr32_t)-1	/* value used when no block allocated */

/*
 * enums
 */

/* direnter ops */
enum de_op { DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME, DE_SYMLINK, DE_ATTRDIR};

/* dirremove ops */
enum dr_op { DR_REMOVE, DR_RMDIR, DR_RENAME };

/*
 * block initialization type for bmap_write
 *
 * BI_NORMAL - allocate and zero fill pages in memory
 * BI_ALLOC_ONLY - only allocate the block, do not zero out pages in mem
 * BI_FALLOCATE - allocate only, do not zero out pages, and store as negative
 *                block number in inode block list
 */
enum bi_type { BI_NORMAL, BI_ALLOC_ONLY, BI_FALLOCATE };

/*
 * This overlays the fid structure (see vfs.h)
 *
 * LP64 note: we use int32_t instead of ino_t since UFS does not use
 * inode numbers larger than 32-bits and ufid's are passed to NFS
 * which expects them to not grow in size beyond 10 bytes (12 including
 * the length).
 */
struct ufid {
	ushort_t ufid_len;
	ushort_t ufid_flags;
	int32_t	ufid_ino;
	int32_t	ufid_gen;
};

/*
 * each ufs thread (see ufs_thread.c) is managed by this struct
 */
struct ufs_q {
	union uq_head {
		void		*_uq_generic;	/* first entry on q */
		struct inode	*_uq_i;
		ufs_failure_t	*_uq_uf;
	} _uq_head;
	int		uq_ne;		/* # of entries/failures found */
	int		uq_lowat;	/* thread runs when ne == lowat */
	int		uq_hiwat;	/* synchronous idle if ne >= hiwat */
	ushort_t	uq_flags;	/* flags (see below) */
	kcondvar_t	uq_cv;		/* for sleep/wakeup */
	kthread_id_t	uq_threadp;	/* thread managing this q */
	kmutex_t	uq_mutex;	/* protects this struct */
};

#define	uq_head		_uq_head._uq_generic
#define	uq_ihead	_uq_head._uq_i
#define	uq_ufhead	_uq_head._uq_uf

/*
 * uq_flags
 */
#define	UQ_EXIT		(0x0001)	/* q server exits at its convenience */
#define	UQ_WAIT		(0x0002)	/* thread is waiting on q server */
#define	UQ_SUSPEND	(0x0004)	/* request for suspension */
#define	UQ_SUSPENDED	(0x0008)	/* thread has suspended itself */

/*
 * When logging is enabled, statvfs must account for blocks and files that
 * may be on the delete queue.  Protected by ufsvfsp->vfs_delete.uq_mutex
 */
struct ufs_delq_info {
	u_offset_t	delq_unreclaimed_blocks;
	ulong_t		delq_unreclaimed_files;
};


/*
 * global idle queues
 * The queues are sized dynamically in proportion to ufs_ninode
 * which, unless overridden, scales with the amount of memory.
 * The idle queue is halved whenever it hits the low water mark
 * (1/4 of ufs_ninode), but can burst to sizes much larger. The number
 * of hash queues is currently maintained to give on average IQHASHQLEN
 * entries when the idle queue is at the low water mark.
 * Note, we do not need to search along the hash queues, but use them
 * in order to batch together geographically local inodes to allow
 * their updates (via the log or buffer cache) to require less disk seeks.
 * This gives an incredible performance boost for logging and a boost for
 * non logging file systems.
 */
typedef struct {
	inode_t *i_chain[2];	/* must match inode_t, but unused */
	inode_t *i_freef;	/* must match inode_t, idle list forward */
	inode_t *i_freeb;	/* must match inode_t, idle list back  */
} iqhead_t;

extern struct ufs_q ufs_idle_q;		/* used by global ufs idle thread */
extern iqhead_t *ufs_junk_iq;		/* junk idle queues */
extern iqhead_t *ufs_useful_iq;		/* useful idle queues */
extern int ufs_njunk_iq;		/* number of entries in junk iq */
extern int ufs_nuseful_iq;		/* number of entries in useful iq */
extern int ufs_niqhash;			/* number of iq hash qs - power of 2 */
extern int ufs_iqhashmask;		/* iq hash mask = ufs_niqhash - 1 */

#define	IQHASHQLEN 32			/* see comments above */
#define	INOCGSHIFT 7			/* 128 inodes per cylinder group */
#define	IQHASH(ip) (((ip)->i_number >> INOCGSHIFT) & ufs_iqhashmask)
#define	IQNEXT(i) ((i) + 1) & ufs_iqhashmask /* next idle queue */

extern struct ufs_q	ufs_hlock;	/* used by global ufs hlock thread */

/*
 * vfs_lfflags flags
 */
#define	UFS_LARGEFILES	((ushort_t)0x1)	/* set if mount allows largefiles */

/*
 * vfs_dfritime flags
 */
#define	UFS_DFRATIME	0x1		/* deferred access time */

/*
 * UFS VFS private data.
 *
 * UFS file system instances may be linked on several lists.
 *
 * -	The vfs_next field chains together every extant ufs instance; this
 *	list is rooted at ufs_instances and should be used in preference to
 *	the overall vfs list (which is properly the province of the generic
 *	file system code, not of file system implementations).  This same list
 *	link is used during forcible unmounts to chain together instances that
 *	can't yet be completely dismantled,
 *
 * -	The vfs_wnext field is used within ufs_update to form a work list of
 *	UFS instances to be synced out.
 */
typedef struct ufsvfs {
	struct vfs	*vfs_vfs;	/* back link			*/
	struct ufsvfs	*vfs_next;	/* instance list link		*/
	struct ufsvfs	*vfs_wnext;	/* work list link		*/
	struct vnode	*vfs_root;	/* root vnode			*/
	struct buf	*vfs_bufp;	/* buffer containing superblock */
	struct vnode	*vfs_devvp;	/* block device vnode		*/
	ushort_t	vfs_lfflags;	/* Large files (set by mount)   */
	ushort_t	vfs_qflags;	/* QUOTA: filesystem flags	*/
	struct inode	*vfs_qinod;	/* QUOTA: pointer to quota file */
	uint_t		vfs_btimelimit;	/* QUOTA: block time limit	*/
	uint_t		vfs_ftimelimit;	/* QUOTA: file time limit	*/
	krwlock_t	vfs_dqrwlock;	/* QUOTA: protects quota fields */
	/*
	 * some fs local threads
	 */
	struct ufs_q	vfs_delete;	/* delayed inode delete */
	struct ufs_q	vfs_reclaim;	/* reclaim open, deleted files */

	/*
	 * This is copied from the super block at mount time.
	 */
	int		vfs_nrpos;	/* # rotational positions */
	/*
	 * This lock protects cg's and super block pointed at by
	 * vfs_bufp->b_fs.  Locks contents of fs and cg's and contents
	 * of vfs_dio.
	 */
	kmutex_t	vfs_lock;
	struct ulockfs	vfs_ulockfs;	/* ufs lockfs support */
	uint_t		vfs_dio;	/* delayed io (_FIODIO) */
	uint_t		vfs_nointr;	/* disallow lockfs interrupts */
	uint_t		vfs_nosetsec;	/* disallow ufs_setsecattr */
	uint_t		vfs_syncdir;	/* synchronous local directory ops */
	uint_t		vfs_dontblock;	/* don't block on forced umount */

	/*
	 * trans (logging ufs) stuff
	 */
	uint_t		vfs_domatamap;	/* set if matamap enabled */
	ulong_t		vfs_maxacl;	/* transaction stuff - max acl size */
	ulong_t		vfs_dirsize;	/* logspace for directory creation */
	ulong_t		vfs_avgbfree;	/* average free blks in cg (blkpref) */
	/*
	 * Some useful constants
	 */
	int	vfs_nindirshift;	/* calc. from fs_nindir */
	int	vfs_nindiroffset;	/* calc. from fs_ninidr */
	int	vfs_ioclustsz;		/* bytes in read/write cluster */
	int	vfs_iotransz;		/* max device i/o transfer size  */

	vfs_ufsfx_t	vfs_fsfx;	/* lock/fix-on-panic support */
	/*
	 * More useful constants
	 */
	int	vfs_minfrags;		/* calc. from fs_minfree */
	/*
	 * Force DirectIO on all files
	 */
	uint_t	vfs_forcedirectio;
	/*
	 * Deferred inode time related fields
	 */
	clock_t		vfs_iotstamp;	/* last I/O timestamp */
	uint_t		vfs_dfritime;	/* deferred inode time flags */
	/*
	 * Some more useful info
	 */
	dev_t		vfs_dev;	/* device mounted from */
	struct ml_unit	*vfs_log;	/* pointer to embedded log struct */
	uint_t		vfs_noatime;    /* disable inode atime updates */
	/*
	 * snapshot stuff
	 */
	void		*vfs_snapshot;	/* snapshot handle */
	/*
	 *  Controls logging "file system full" messages to messages file
	 */
	clock_t		vfs_lastwhinetime;

	int		vfs_nolog_si;	/* not logging summary info */
	int		vfs_validfs;	/* indicates mounted fs */

	/*
	 * Additional information about vfs_delete above
	 */
	struct ufs_delq_info vfs_delete_info; /* what's on the delete queue */
} ufsvfs_t;

#define	vfs_fs	vfs_bufp->b_un.b_fs

/*
 * values for vfs_validfs
 */
#define	UT_UNMOUNTED	0
#define	UT_MOUNTED	1
#define	UT_HLOCKING	2

/* inohsz is guaranteed to be a power of 2 */
#define	INOHASH(ino)	(((int)ino) & (inohsz - 1))

#define	ISFALLOCBLK(ip, bn)	\
	(((bn) < 0) && ((bn) % ip->i_fs->fs_frag == 0) && \
	((ip)->i_cflags & IFALLOCATE && (bn) != UFS_HOLE))

union ihead {
	union	ihead	*ih_head[2];
	struct	inode	*ih_chain[2];
};

extern	union	ihead	*ihead;
extern  kmutex_t	*ih_lock;
extern  int	*ih_ne;
extern	int	inohsz;

extern	clock_t	ufs_iowait;

#endif /* _KERNEL */

/*
 * ufs function prototypes
 */
#if defined(_KERNEL) && !defined(_BOOT)

extern	void	ufs_iinit(void);
extern	int	ufs_iget(struct vfs *, ino_t, struct inode **, cred_t *);
extern	int	ufs_iget_alloced(struct vfs *, ino_t, struct inode **,
    cred_t *);
extern	void	ufs_reset_vnode(vnode_t *);
extern	void	ufs_iinactive(struct inode *);
extern	void	ufs_iupdat(struct inode *, int);
extern	int	ufs_rmidle(struct inode *);
extern	int	ufs_itrunc(struct inode *, u_offset_t, int, cred_t *);
extern	int	ufs_iaccess(struct inode *, int, cred_t *, int);
extern  int	rdip(struct inode *, struct uio *, int, struct cred *);
extern  int	wrip(struct inode *, struct uio *, int, struct cred *);

extern void	ufs_imark(struct inode *);
extern void	ufs_itimes_nolock(struct inode *);

extern	int	ufs_diraccess(struct inode *, int, struct cred *);
extern	int	ufs_dirlook(struct inode *, char *, struct inode **,
    cred_t *, int, int);
extern	int	ufs_direnter_cm(struct inode *, char *, enum de_op,
    struct vattr *, struct inode **, cred_t *, int);
extern	int	ufs_direnter_lr(struct inode *, char *, enum de_op,
    struct inode *, struct inode *, cred_t *);
extern	int	ufs_dircheckpath(ino_t, struct inode *, struct inode *,
    struct cred *);
extern	int	ufs_dirmakeinode(struct inode *, struct inode **,
    struct vattr *, enum de_op, cred_t *);
extern	int	ufs_dirremove(struct inode *, char *, struct inode *,
    vnode_t *, enum dr_op, cred_t *);
extern  int	ufs_dircheckforname(struct inode *, char *, int,
    struct ufs_slot *, struct inode **, struct cred *, int);
extern	int	ufs_xattrdirempty(struct inode *, ino_t, cred_t *);
extern	int	blkatoff(struct inode *, off_t, char **, struct fbuf **);

extern	void	sbupdate(struct vfs *);

extern	int	ufs_ialloc(struct inode *, ino_t, mode_t, struct inode **,
    cred_t *);
extern	void	ufs_ifree(struct inode *, ino_t, mode_t);
extern	void	free(struct inode *, daddr_t, off_t, int);
extern	int	alloc(struct inode *, daddr_t, int, daddr_t *, cred_t *);
extern	int	realloccg(struct inode *, daddr_t, daddr_t, int, int,
    daddr_t *, cred_t *);
extern	int	ufs_allocsp(struct vnode *, struct flock64 *, cred_t *);
extern	int	ufs_freesp(struct vnode *, struct flock64 *, int, cred_t *);
extern	ino_t	dirpref(inode_t *);
extern	daddr_t	blkpref(struct inode *, daddr_t, int, daddr32_t *);
extern	daddr_t	contigpref(ufsvfs_t *, size_t, size_t);

extern	int	ufs_rdwri(enum uio_rw, int, struct inode *, caddr_t, ssize_t,
	offset_t, enum uio_seg, int *, cred_t *);

extern	int	bmap_read(struct inode *, u_offset_t, daddr_t *, int *);
extern	int	bmap_write(struct inode *, u_offset_t, int, enum bi_type,
    daddr_t *, struct cred *);
extern	int	bmap_has_holes(struct inode *);
extern	int	bmap_find(struct inode *, boolean_t, u_offset_t *);
extern	int	bmap_set_bn(struct vnode *, u_offset_t, daddr32_t);

extern	void	ufs_vfs_add(struct ufsvfs *);
extern	void	ufs_vfs_remove(struct ufsvfs *);

extern	void	ufs_sbwrite(struct ufsvfs *);
extern	void	ufs_update(int);
extern	int	ufs_getsummaryinfo(dev_t, struct ufsvfs *, struct fs *);
extern	int	ufs_putsummaryinfo(dev_t, struct ufsvfs *, struct fs *);
extern	int	ufs_syncip(struct inode *, int, int, top_t);
extern	int	ufs_sync_indir(struct inode *);
extern	int	ufs_indirblk_sync(struct inode *, offset_t);
extern	int	ufs_badblock(struct inode *, daddr_t);
extern	int	ufs_indir_badblock(struct inode *, daddr32_t *);
extern	void	ufs_notclean(struct ufsvfs *);
extern	void	ufs_checkclean(struct vfs *);
extern	int	isblock(struct fs *, uchar_t *, daddr_t);
extern	void	setblock(struct fs *, uchar_t *, daddr_t);
extern	void	clrblock(struct fs *, uchar_t *, daddr_t);
extern	int	isclrblock(struct fs *, uchar_t *, daddr_t);
extern	void	fragacct(struct fs *, int, int32_t *, int);
extern	int	skpc(char, uint_t, char *);
extern	int	ufs_fbwrite(struct fbuf *, struct inode *);
extern	int	ufs_fbiwrite(struct fbuf *, struct inode *, daddr_t, long);
extern	int	ufs_putapage(struct vnode *, struct page *, u_offset_t *,
				size_t *, int, struct cred *);
extern inode_t	*ufs_alloc_inode(ufsvfs_t *, ino_t);
extern void	ufs_free_inode(inode_t *);

/*
 * special stuff
 */
extern	void	ufs_setreclaim(struct inode *);
extern	int	ufs_scan_inodes(int, int (*)(struct inode *, void *), void *,
				struct ufsvfs *);
extern	int	ufs_sync_inode(struct inode *, void *);
extern	int	ufs_sticky_remove_access(struct inode *, struct inode *,
    struct cred *);
/*
 * quota
 */
extern	int	chkiq(struct ufsvfs *, int, struct inode *, uid_t, int,
			struct cred *, char **errp, size_t *lenp);

/*
 * ufs thread stuff
 */
extern	void	ufs_thread_delete(struct vfs *);
extern	void	ufs_delete_drain(struct vfs *, int, int);
extern	void	ufs_delete(struct ufsvfs *, struct inode *, int);
extern	void	ufs_inode_cache_reclaim(void *);
extern	void	ufs_idle_drain(struct vfs *);
extern	void	ufs_idle_some(int);
extern	void	ufs_thread_idle(void);
extern	void	ufs_thread_reclaim(struct vfs *);
extern	void	ufs_thread_init(struct ufs_q *, int);
extern	void	ufs_thread_start(struct ufs_q *, void (*)(), struct vfs *);
extern	void	ufs_thread_exit(struct ufs_q *);
extern	void	ufs_thread_suspend(struct ufs_q *);
extern	void	ufs_thread_continue(struct ufs_q *);
extern	void	ufs_thread_hlock(void *);
extern	void	ufs_delete_init(struct ufsvfs *, int);
extern	void	ufs_delete_adjust_stats(struct ufsvfs *, struct statvfs64 *);
extern	void	ufs_delete_drain_wait(struct ufsvfs *, int);

/*
 * ufs lockfs stuff
 */
struct seg;
extern int ufs_reconcile_fs(struct vfs *, struct ufsvfs *, int);
extern int ufs_quiesce(struct ulockfs *);
extern int ufs_flush(struct vfs *);
extern int ufs_fiolfs(struct vnode *, struct lockfs *, int);
extern int ufs__fiolfs(struct vnode *, struct lockfs *, int, int);
extern int ufs_fiolfss(struct vnode *, struct lockfs *);
extern int ufs_fioffs(struct vfs *, struct cred *);
extern int ufs_check_lockfs(struct ufsvfs *, struct ulockfs *, ulong_t);
extern int ufs_lockfs_begin(struct ufsvfs *, struct ulockfs **, ulong_t);
extern int ufs_lockfs_trybegin(struct ufsvfs *, struct ulockfs **, ulong_t);
extern int ufs_lockfs_begin_getpage(struct ufsvfs *, struct ulockfs **,
		struct seg *, int, uint_t *);
extern void ufs_lockfs_end(struct ulockfs *);
/*
 * ufs acl stuff
 */
extern int ufs_si_inherit(struct inode *, struct inode *, o_mode_t, cred_t *);
extern void si_cache_init(void);
extern int ufs_si_load(struct inode *, cred_t *);
extern void ufs_si_del(struct inode *);
extern int ufs_acl_access(struct inode *, int, cred_t *);
extern void ufs_si_cache_flush(dev_t);
extern int ufs_si_free(si_t *, struct vfs *, cred_t *);
extern int ufs_acl_setattr(struct inode *, struct vattr *, cred_t *);
extern int ufs_acl_get(struct inode *, vsecattr_t *, int, cred_t *);
extern int ufs_acl_set(struct inode *, vsecattr_t *, int, cred_t *);
/*
 * ufs directio stuff
 */
extern void ufs_directio_init();
extern int ufs_directio_write(struct inode *, uio_t *, int, int, cred_t *,
    int *);
extern int ufs_directio_read(struct inode *, uio_t *, cred_t *, int *);
#define	DIRECTIO_FAILURE	(0)
#define	DIRECTIO_SUCCESS	(1)

/*
 * ufs extensions for PXFS
 */

int ufs_rdwr_data(vnode_t *vp, u_offset_t offset, size_t len, fdbuffer_t *fdb,
    int flags, cred_t *cr);
int ufs_alloc_data(vnode_t *vp, u_offset_t offset, size_t *len, fdbuffer_t *fdb,
    int flags, cred_t *cr);

/*
 * prototypes to support the forced unmount
 */

void ufs_freeze(struct ulockfs *, struct lockfs *);
int ufs_thaw(struct vfs *, struct ufsvfs *, struct ulockfs *);

/*
 * extended attributes
 */

int ufs_xattrmkdir(inode_t *, inode_t **, int, struct cred *);
int ufs_xattr_getattrdir(vnode_t *, inode_t **, int, struct cred *);
void ufs_unhook_shadow(inode_t *, inode_t *);

#endif	/* defined(_KERNEL) && !defined(_BOOT) */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_INODE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_FS_UFS_LOCKFS_H
#define	_SYS_FS_UFS_LOCKFS_H

#include <sys/lockfs.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Sun ufs file system locking (lockfs)
 *
 * ufs file system supports the following lock types:
 * 	unlock		- releasing existing locks, or do a file system flush
 *	name lock	- no delete, no rename
 *	write lock	- no update to file system, including delete
 *	delete lock	- no delete, rename is allowed
 *	hard lock	- no update, no access, cannot be unlocked
 *			- for supporting forcible umount
 *	error lock	- no update, no access, may only be unlocked
 *			- once fs becomes clean, may be upgraded to
 *			- a hard lock
 *	error lock (read-only) -- not yet implemented --
 *			- no write changes allowed to fs, may be upgraded
 *			- to error or hard lock
 *			- degrades to panic on subsequent failures
 *
 * ufs_vnodeops(es) that conflict with the above file system lock types
 *	will get either suspended, or get a EAGAIN error,
 *	or get an EIO error if the file system is hard locked,
 *	or will block if the file system is error locked.
 *
 * There are exceptions.
 *	The following ufs_vnops do not obey the locking protocol:
 *	ufs_close, ufs_putpage, ufs_inactive, ufs_addmap, ufs_delmap,
 *	ufs_rwlock, ufs_rwunlock, ufs_poll.
 *
 * ul_vnops_cnt will get increment by 1 when a ufs vnodeops is entered;
 * it will be decremented by 1 when a ufs_vnodeops is exited.
 * A file system is in a quiescent state if ufs_vnops_cnt is zero.
 * Since ufs_pageio() has to change ul_vnops_cnt without using ul_lock
 * all users of ul_vnops_cnt increment and decrement it via atomic_add_long().
 */

#include <sys/fs/ufs_trans.h>
#include <sys/thread.h>

/*
 * ul_flag
 */
#define	ULOCKFS_BUSY	0x00000001	/* ul_fs_lock is being set */
#define	ULOCKFS_NOIACC	0x00000004	/* don't keep access times */
#define	ULOCKFS_NOIDEL	0x00000008	/* don't free deleted files */
#define	ULOCKFS_FALLOC	0x00000010	/* fallocate threads exist */

#define	ULOCKFS_IS_BUSY(LF)	((LF)->ul_flag & ULOCKFS_BUSY)
#define	ULOCKFS_IS_NOIACC(LF)	((LF)->ul_flag & ULOCKFS_NOIACC)
#define	ULOCKFS_IS_NOIDEL(LF)	((LF)->ul_flag & ULOCKFS_NOIDEL)
#define	ULOCKFS_IS_FALLOC(LF)	((LF)->ul_flag & ULOCKFS_FALLOC)

#define	ULOCKFS_CLR_BUSY(LF)	((LF)->ul_flag &= ~ULOCKFS_BUSY)
#define	ULOCKFS_SET_BUSY(LF)	((LF)->ul_flag |= ULOCKFS_BUSY)

#define	ULOCKFS_CLR_FALLOC(LF)	((LF)->ul_flag &= ~ULOCKFS_FALLOC)
#define	ULOCKFS_SET_FALLOC(LF)	((LF)->ul_flag |= ULOCKFS_FALLOC)

/*
 * ul_fs_mod
 */
#define	ULOCKFS_SET_MOD(LF)	((LF)->ul_fs_mod = 1)
#define	ULOCKFS_CLR_MOD(LF)	((LF)->ul_fs_mod = 0)
#define	ULOCKFS_IS_MOD(LF)	((LF)->ul_fs_mod)

/*
 * ul_fs_lock
 *
 * softlock will temporarily block most ufs_vnodeops.
 * it is used so that a waiting lockfs command will not be starved
 *
 * fwlock will block other fallocate threads wanting to obtain a write lock
 * on the file system.
 */
#define	ULOCKFS_ULOCK	((1 << LOCKFS_ULOCK))	/* unlock */
#define	ULOCKFS_WLOCK	((1 << LOCKFS_WLOCK))	/* write  lock */
#define	ULOCKFS_NLOCK	((1 << LOCKFS_NLOCK))	/* name   lock */
#define	ULOCKFS_DLOCK	((1 << LOCKFS_DLOCK))	/* delete lock */
#define	ULOCKFS_HLOCK	((1 << LOCKFS_HLOCK))	/* hard   lock */
#define	ULOCKFS_ELOCK	((1 << LOCKFS_ELOCK))	/* error  lock */
#define	ULOCKFS_ROELOCK	((1 << LOCKFS_ROELOCK)) /* error lock (read-only) */
/* Maximum number of LOCKFS lockfs defined in sys/lockfs.h are 6 */
#define	ULOCKFS_FWLOCK	(1 << (LOCKFS_MAXLOCK + 1)) /* fallocate write lock */
#define	ULOCKFS_SLOCK	0x80000000		/* soft   lock */

#define	ULOCKFS_IS_WLOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_WLOCK)
#define	ULOCKFS_IS_HLOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_HLOCK)
#define	ULOCKFS_IS_ELOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_ELOCK)
#define	ULOCKFS_IS_ROELOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_ROELOCK)
#define	ULOCKFS_IS_ULOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_ULOCK)
#define	ULOCKFS_IS_NLOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_NLOCK)
#define	ULOCKFS_IS_DLOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_DLOCK)
#define	ULOCKFS_IS_SLOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_SLOCK)
#define	ULOCKFS_IS_FWLOCK(LF)	((LF)->ul_fs_lock & ULOCKFS_FWLOCK)
#define	ULOCKFS_IS_JUSTULOCK(LF) \
	(((LF)->ul_fs_lock & (ULOCKFS_SLOCK | ULOCKFS_ULOCK)) == ULOCKFS_ULOCK)

#define	ULOCKFS_SET_SLOCK(LF)	((LF)->ul_fs_lock |= ULOCKFS_SLOCK)
#define	ULOCKFS_CLR_SLOCK(LF)	((LF)->ul_fs_lock &= ~ULOCKFS_SLOCK)

#define	ULOCKFS_SET_FWLOCK(LF)	((LF)->ul_fs_lock |= ULOCKFS_FWLOCK)
#define	ULOCKFS_CLR_FWLOCK(LF)	((LF)->ul_fs_lock &= ~ULOCKFS_FWLOCK)

#define	ULOCKFS_READ_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_WRITE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
			ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
/* used by both ufs_getattr and ufs_getsecattr */
#define	ULOCKFS_GETATTR_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
/* used by both ufs_setattr and ufs_setsecattr */
#define	ULOCKFS_SETATTR_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_ACCESS_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_LOOKUP_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_CREATE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_REMOVE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
			ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK | \
					ULOCKFS_NLOCK | ULOCKFS_DLOCK)
#define	ULOCKFS_LINK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_RENAME_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
					ULOCKFS_SLOCK | ULOCKFS_WLOCK | \
					ULOCKFS_ROELOCK | ULOCKFS_NLOCK)
#define	ULOCKFS_MKDIR_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_RMDIR_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
			ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK | \
					ULOCKFS_NLOCK | ULOCKFS_DLOCK)
#define	ULOCKFS_READDIR_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_SYMLINK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_READLINK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_FSYNC_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_FID_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_RWLOCK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_RWUNLOCK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_SEEK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_FRLOCK_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_SPACE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_FALLOCATE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | \
				ULOCKFS_WLOCK | ULOCKFS_FWLOCK)
#define	ULOCKFS_QUOTA_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
/* GETPAGE breaks up into two masks */
#define	ULOCKFS_GETREAD_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_GETWRITE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_MAP_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_FIODUTIMES_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_FIODIO_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)
#define	ULOCKFS_FIODIOS_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_PATHCONF_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)

#define	ULOCKFS_VGET_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | ULOCKFS_SLOCK)
#define	ULOCKFS_DELETE_MASK	(ULOCKFS_HLOCK | ULOCKFS_ELOCK | \
				ULOCKFS_ROELOCK | ULOCKFS_SLOCK | ULOCKFS_WLOCK)

struct ulockfs {
	ulong_t		ul_flag;	/* flags */
	ulong_t		ul_fs_lock;	/* current file system lock state */
	ulong_t		ul_fs_mod;	/* for test; fs was modified */
	ulong_t		ul_vnops_cnt;	/* # of active ufs vnops outstanding */
	kmutex_t	ul_lock;	/* mutex to protect ulockfs structure */
	kcondvar_t 	ul_cv;
	kthread_id_t	ul_sbowner;	/* thread than can write superblock */
	struct lockfs	ul_lockfs;	/* ioctl lock struct */
	ulong_t		ul_falloc_cnt;	/* # of on-going fallocate ops */
};

extern ulong_t ufs_quiesce_pend;

#define	VTOUL(VP) \
	((struct ulockfs *) \
	&((struct ufsvfs *)((VP)->v_vfsp->vfs_data))->vfs_ulockfs)
#define	ITOUL(IP)	((struct ulockfs *)&((IP)->i_ufsvfs->vfs_ulockfs))

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_LOCKFS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_FS_UFS_LOG_H
#define	_SYS_FS_UFS_LOG_H

#include <sys/buf.h>
#include <sys/fs/ufs_trans.h>
#include <sys/fs/ufs_filio.h>
#include <sys/fs/ufs_inode.h>

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct lufs_save {
	buf_t		*sv_bp;
	size_t		sv_nb_left;
	int		sv_error;
} lufs_save_t;

typedef struct lufs_buf {
	buf_t		lb_buf;
	void		*lb_ptr;
} lufs_buf_t;

/*
 * Log space is stored as extents
 */
#define	LUFS_EXTENTS	(UINT32_C(0))
#define	LS_SECTORS	2

typedef struct extent {
	uint32_t	lbno;	/* Logical block # within the space */
	uint32_t	pbno;	/* Physical block number of extent. */
				/* in disk blocks for non-MTB ufs */
				/* in frags for MTB ufs */
	uint32_t	nbno;	/* # blocks in this extent */
} extent_t;

typedef struct ic_extent {
	uint32_t	ic_lbno;	/* Logical block # within the space */
	uint32_t	ic_nbno;	/* # blocks in this extent */
	daddr_t		ic_pbno;	/* Physical block number of extent. */
					/* (always in disk blocks) 	*/
} ic_extent_t;

typedef struct extent_block {
	uint32_t	type;		/* Set to LUFS_EXTENTS to identify */
					/*   structure on disk. */
	int32_t		chksum;		/* Checksum over entire block. */
	uint32_t	nextents;	/* Size of extents array. */
	uint32_t	nbytes;		/* # bytes mapped by extent_block. */
	uint32_t	nextbno;	/* blkno of next extent_block. */
	extent_t	extents[1];
} extent_block_t;

typedef struct ic_extent_block {
	uint32_t	ic_nextents;	/* Size of extents array. */
	uint32_t	ic_nbytes;	/* # bytes mapped by extent_block. */
	uint32_t	ic_nextbno;	/* blkno of next extent_block. */
	ic_extent_t	ic_extents[1];
} ic_extent_block_t;

/*
 * Don't size the incore buffers too small or too large
 */
#define	LDL_MINTRANSFER		(UINT32_C(32768))	/* 32 k */
#define	LDL_MAXTRANSFER		(UINT32_C(1048576))	/* 1 M */

/*
 * LDL_DIVISOR (ldl_divisor) is the number to calculate the log size
 * from the file system size according to the calculation in lufs_enable()
 */
#define	LDL_DIVISOR		1024 /* 1024 gives 1MB per 1GB */

/*
 * This gives the maximum size of log for which the 1MB per 1GB rule
 * applies. The size of the log will only be greater than this based
 * on the cylinder group space requirements.
 */
#define	LDL_SOFTLOGCAP		(256 * 1024 * 1024)

/*
 * But set reasonable min/max units
 */
#define	LDL_MINLOGSIZE		(1024 * 1024)
#define	LDL_MAXLOGSIZE		(512 * 1024 * 1024)

/*
 * Log space requirement per cylinder group. This needs to accommodate a
 * cg delta (inc. header) and have a factor to cover other deltas involved
 * in a single transaction which could touch all cyl groups in a file system.
 */
#define	LDL_CGSIZEREQ(fs) \
	((fs)->fs_cgsize + ((fs)->fs_cgsize >> 1))

#define	LDL_MINBUFSIZE		(32 * 1024)
#define	LDL_USABLE_BSIZE	(DEV_BSIZE - sizeof (sect_trailer_t))
#define	NB_LEFT_IN_SECTOR(off) 	(LDL_USABLE_BSIZE - ((off) - dbtob(btodb(off))))

typedef struct cirbuf {
	buf_t		*cb_bp;		/* buf's with space in circular buf */
	buf_t		*cb_dirty;	/* filling this buffer for log write */
	buf_t		*cb_free;	/* free bufs list */
	caddr_t		cb_va;		/* address of circular buffer */
	size_t		cb_nb;		/* size of circular buffer */
	krwlock_t	cb_rwlock;	/* r/w lock to protect list mgmt. */
} cirbuf_t;

#define	LUFS_VERSION		(UINT32_C(1))	/* Version 1 */
#define	LUFS_VERSION_LATEST	LUFS_VERSION

/*
 * The old Disksuite unit structure has been split into two parts -- the
 * incore part which is created at run time and the ondisk structure.  To
 * minimize code changes, the incore structure retains the old name,
 * ml_unit_t and the ondisk structure is called ml_odunit_t.  The ondisk
 * structure is stored at the beginning of the log.
 *
 * This structure must fit into a sector (512b)
 *
 */
typedef struct ml_odunit {
	uint32_t	od_version;	/* version number */
	uint32_t	od_badlog;	/* is the log okay? */
	uint32_t	od_unused1;

	/*
	 * Important constants
	 */
	uint32_t	od_maxtransfer;	/* max transfer in bytes */
	uint32_t	od_devbsize;	/* device bsize */
	int32_t		od_bol_lof;	/* byte offset to begin of log */
	int32_t		od_eol_lof;	/* byte offset to end of log */

	/*
	 * The disk space is split into state and circular log
	 */
	uint32_t	od_requestsize;	/* size requested by user */
	uint32_t	od_statesize;	/* size of state area in bytes */
	uint32_t	od_logsize;	/* size of log area in bytes */
	int32_t		od_statebno;	/* first block of state area */
	int32_t		od_unused2;

	/*
	 * Head and tail of log
	 */
	int32_t		od_head_lof;	/* byte offset of head */
	uint32_t	od_head_ident;	/* head sector id # */
	int32_t		od_tail_lof;	/* byte offset of tail */
	uint32_t	od_tail_ident;	/* tail sector id # */
	uint32_t	od_chksum;	/* checksum to verify ondisk contents */

	/*
	 * Used for error recovery
	 */
	uint32_t	od_head_tid;	/* used for logscan; set at sethead */

	/*
	 * Debug bits
	 */
	int32_t		od_debug;

	/*
	 * Misc
	 */
	struct timeval	od_timestamp;	/* time of last state change */
} ml_odunit_t;

typedef struct ml_unit {
	struct ml_unit	*un_next;	/* next incore log */
	int		un_flags;	/* Incore state */
	buf_t		*un_bp;		/* contains memory for un_ondisk */
	struct ufsvfs	*un_ufsvfs;	/* backpointer to ufsvfs */
	dev_t		un_dev;		/* for convenience */
	ic_extent_block_t *un_ebp;	/* block of extents */
	size_t		un_nbeb;	/* # bytes used by *un_ebp */
	struct mt_map	*un_deltamap;	/* deltamap */
	struct mt_map	*un_logmap;	/* logmap includes moby trans stuff */
	struct mt_map	*un_matamap;	/* optional - matamap */

	/*
	 * Used for managing transactions
	 */
	uint32_t	un_maxresv;	/* maximum reservable space */
	uint32_t	un_resv;	/* reserved byte count for this trans */
	uint32_t	un_resv_wantin;	/* reserved byte count for next trans */

	/*
	 * Used during logscan
	 */
	uint32_t	un_tid;

	/*
	 * Read/Write Buffers
	 */
	cirbuf_t	un_rdbuf;	/* read buffer space */
	cirbuf_t	un_wrbuf;	/* write buffer space */

	/*
	 * Ondisk state
	 */
	ml_odunit_t	un_ondisk;	/* ondisk log information */

	/*
	 * locks
	 */
	kmutex_t	un_log_mutex;	/* allows one log write at a time */
	kmutex_t	un_state_mutex;	/* only 1 state update at a time */
} ml_unit_t;

/*
 * Macros to allow access to the ondisk elements via the ml_unit_t incore
 * structure.
 */

#define	un_version	un_ondisk.od_version
#define	un_badlog	un_ondisk.od_badlog
#define	un_maxtransfer	un_ondisk.od_maxtransfer
#define	un_devbsize	un_ondisk.od_devbsize
#define	un_bol_lof	un_ondisk.od_bol_lof
#define	un_eol_lof	un_ondisk.od_eol_lof
#define	un_statesize	un_ondisk.od_statesize
#define	un_logsize	un_ondisk.od_logsize
#define	un_statebno	un_ondisk.od_statebno
#define	un_requestsize	un_ondisk.od_requestsize
#define	un_head_lof	un_ondisk.od_head_lof
#define	un_head_ident	un_ondisk.od_head_ident
#define	un_tail_lof	un_ondisk.od_tail_lof
#define	un_tail_ident	un_ondisk.od_tail_ident
#define	un_chksum	un_ondisk.od_chksum
#define	un_head_tid	un_ondisk.od_head_tid
#define	un_debug	un_ondisk.od_debug
#define	un_timestamp	un_ondisk.od_timestamp

/*
 *	un_flags
 */
#define	LDL_SCAN	0x0001	/* log scan in progress */
#define	LDL_ERROR	0x0002	/* in error state */
#define	LDL_NOROLL	0x0004  /* Log Not Yet Rollable */

typedef struct sect_trailer {
	uint32_t	st_tid;		/* transaction id */
	uint32_t	st_ident;	/* unique sector id */
} sect_trailer_t;

/*
 * map block
 */
#define	MAPBLOCKSIZE	(8192)
#define	MAPBLOCKSHIFT	(13)
#define	MAPBLOCKOFF	(MAPBLOCKSIZE-1)
#define	MAPBLOCKMASK	(~MAPBLOCKOFF)
#define	DEV_BMASK	(DEV_BSIZE - 1)

/*
 * cached roll buffer
 */
typedef struct crb {
	int64_t		c_mof;		/* master file offset of buffer */
	caddr_t		c_buf;		/* pointer to cached roll buffer */
	uint32_t	c_nb;		/* size of buffer */
	ushort_t	c_refcnt;	/* reference count on crb */
	uchar_t		c_invalid;	/* crb should not be used */
} crb_t;

#define	CRB_END ((crb_t *)1) /* must be non zero */

/*
 * delta header
 */
struct delta {
	int64_t		d_mof;	/* byte offset on device to start writing */
				/*   delta */
	int32_t		d_nb;	/* # bytes in the delta */
	delta_t 	d_typ;	/* Type of delta.  Defined in ufs_trans.h */
};
/*
 * common map entry
 */
typedef struct mapentry	mapentry_t;
struct mapentry {
	/*
	 * doubly linked list of all mapentries in map -- MUST BE FIRST
	 */
	mapentry_t	*me_next;
	mapentry_t	*me_prev;

	mapentry_t	*me_hash;
	mapentry_t	*me_agenext;
	mapentry_t	*me_cancel;
	crb_t		*me_crb;
	int		(*me_func)();
	ulong_t		me_arg;
	ulong_t		me_age;
	struct delta	me_delta;
	uint32_t	me_tid;
	off_t		me_lof;
	ushort_t	me_flags;
};

#define	me_mof	me_delta.d_mof
#define	me_nb	me_delta.d_nb
#define	me_dt	me_delta.d_typ

/*
 * me_flags
 */
#define	ME_SCAN		(0x0001)	/* entry from log scan */
#define	ME_HASH		(0x0002)	/* on hash   list */
#define	ME_CANCEL	(0x0004)	/* on cancel list */
#define	ME_AGE		(0x0008)	/* on age    list */
#define	ME_LIST		(0x0010)	/* on list   list */
#define	ME_ROLL		(0x0020)	/* on pseudo-roll list */
#define	ME_USER		(0x0040)	/* User Block DT_CANCEL entry */

/*
 * MAP TYPES
 */
enum maptypes	{
	deltamaptype, logmaptype, matamaptype
};

/*
 * MAP
 */
#define	DELTAMAP_NHASH	(512)
#define	LOGMAP_NHASH	(2048)
#define	MAP_INDEX(mof, mtm) \
	(((mof) >> MAPBLOCKSHIFT) & (mtm->mtm_nhash-1))
#define	MAP_HASH(mof, mtm) \
	((mtm)->mtm_hash + MAP_INDEX((mof), (mtm)))

typedef struct mt_map {
	/*
	 * anchor doubly linked list this map's entries -- MUST BE FIRST
	 */
	mapentry_t	*mtm_next;
	mapentry_t	*mtm_prev;

	enum maptypes	mtm_type;	/* map type */
	int		mtm_flags;	/* generic flags */
	int		mtm_ref;	/* PTE like ref bit */
	ulong_t		mtm_debug;	/* set at create time */
	ulong_t		mtm_age;	/* mono-inc; tags mapentries */
	mapentry_t	*mtm_cancel;	/* to be canceled at commit */
	ulong_t		mtm_nhash;	/* # of hash anchors */
	mapentry_t	**mtm_hash;	/* array of singly linked lists */
	struct topstats	*mtm_tops;	/* trans ops - enabled by an ioctl */
	long		mtm_nme;	/* # of mapentries */
	long		mtm_nmet;	/* # of mapentries this transaction */
	long		mtm_cfrags;	/* Canceled frags */
	long		mtm_cfragmax;	/* Maximum canceled frags */
	/*
	 * used after logscan to set the log's tail
	 */
	off_t		mtm_tail_lof;
	size_t		mtm_tail_nb;

	/*
	 * debug field for Scan test
	 */
	off_t		mtm_trimlof;	/* log was trimmed to this lof */
	off_t		mtm_trimtail;	/* tail lof before trimming */
	off_t		mtm_trimalof;	/* lof of last allocation delta */
	off_t		mtm_trimclof;	/* lof of last commit delta */
	off_t		mtm_trimrlof;	/* lof of last rolled delta */
	ml_unit_t	*mtm_ul;	/* log unit for this map */

	/*
	 * moby trans stuff
	 */
	uint32_t		mtm_tid;
	uint32_t		mtm_committid;
	ushort_t		mtm_closed;
	ushort_t		mtm_seq;
	long			mtm_wantin;
	long			mtm_active;
	long			mtm_activesync;
	ulong_t			mtm_dirty;
	kmutex_t		mtm_lock;
	kcondvar_t		mtm_cv_commit;
	kcondvar_t		mtm_cv_next;
	kcondvar_t		mtm_cv_eot;

	/*
	 * mutex that protects all the fields in mt_map except
	 * mtm_mapnext and mtm_refcnt
	 */
	kmutex_t	mtm_mutex;

	/*
	 * logmap only condition variables
	 */
	kcondvar_t	mtm_to_roll_cv; /* roll log or kill roll thread */
	kcondvar_t	mtm_from_roll_cv; /* log rolled or thread exiting */

	/*
	 * rw lock for the agenext mapentry field
	 */
	krwlock_t	mtm_rwlock;
	/*
	 * DEBUG: runtestscan
	 */
	kmutex_t	mtm_scan_mutex;

	/*
	 * logmap only taskq sync count variable, protected by mtm_lock.
	 * keeps track of the number of pending top_issue_sync
	 * dispatches.
	 */
	int		mtm_taskq_sync_count;

	/*
	 * logmap only condition variable, to synchronize with lufs_unsnarf.
	 */
	kcondvar_t	mtm_cv;
} mt_map_t;

/*
 * mtm_flags
 */
#define	MTM_ROLL_EXIT		0x00000001 /* force roll thread to exit */
#define	MTM_ROLL_RUNNING	0x00000002 /* roll thread is running */
#define	MTM_FORCE_ROLL		0x00000004 /* force at least one roll cycle */
#define	MTM_ROLLING		0x00000008 /* currently rolling the log */
#define	MTM_CANCELED		0x00000010 /* cancel entries were removed */

/*
 * Generic range checking macros
 */
#define	OVERLAP(sof, snb, dof, dnb) \
	(((sof) >= (dof) && (sof) < ((dof) + (dnb))) || \
	((dof) >= (sof) && (dof) < ((sof) + (snb))))
#define	WITHIN(sof, snb, dof, dnb) \
	(((sof) >= (dof)) && (((sof) + (snb)) <= ((dof) + (dnb))))
#define	DATAoverlapME(mof, hnb, me) \
	(OVERLAP((mof), (hnb), (me)->me_mof, (me)->me_nb))
#define	MEwithinDATA(me, mof, hnb) \
	(WITHIN((me)->me_mof, (me)->me_nb, (mof), (hnb)))
#define	DATAwithinME(mof, hnb, me) \
	(WITHIN((mof), (hnb), (me)->me_mof, (me)->me_nb))
#define	DATAwithinCRB(mof, nb, crb) \
	(WITHIN((mof), (nb), (crb)->c_mof, (crb)->c_nb))

/*
 * TRANSACTION OPS STATS
 */
typedef struct topstats {
	uint64_t	mtm_top_num[TOP_MAX];
	uint64_t	mtm_top_size_etot[TOP_MAX];
	uint64_t	mtm_top_size_rtot[TOP_MAX];
	uint64_t	mtm_top_size_max[TOP_MAX];
	uint64_t	mtm_top_size_min[TOP_MAX];
	uint64_t	mtm_delta_num[DT_MAX];
} topstats_t;

/*
 * fio_lufs_stats_t is used by _FIO_GET_TOP_STATS ioctl for getting topstats
 */
typedef struct fio_lufs_stats {
	uint32_t	ls_debug;	/* out: un_debug value */
	uint32_t	_ls_pad;	/* make size 64-bit aligned on x86 */
	topstats_t	ls_topstats;	/* out: transaction stats */
} fio_lufs_stats_t;

/*
 * roll buf structure; one per roll buffer
 */
typedef uint16_t rbsecmap_t;
typedef struct rollbuf {
	buf_t rb_bh;		/* roll buffer header */
	struct rollbuf *rb_next; /* link for mof ordered roll bufs */
	crb_t *rb_crb;		/* cached roll buffer to roll */
	mapentry_t *rb_age;	/* age list */
	rbsecmap_t rb_secmap;	/* sector map */
} rollbuf_t;

/*
 * un_debug
 *	MT_TRANSACT		- keep per thread accounting of tranactions
 *	MT_MATAMAP		- double check deltas and ops against matamap
 *	MT_WRITE_CHECK		- check master+deltas against metadata write
 *	MT_LOG_WRITE_CHECK	- read after write for log writes
 *	MT_CHECK_MAP		- check map after every insert/delete
 *	MT_TRACE		- trace transactions (used with MT_TRANSACT)
 *	MT_SIZE			- fail on size errors (used with MT_TRANSACT)
 *	MT_NOASYNC		- force every op to be sync
 *	MT_FORCEROLL		- forcibly roll the log after every commit
 *	MT_SCAN			- running runtestscan; special case as needed
 */
#define	MT_NONE			(0x00000000)
#define	MT_TRANSACT		(0x00000001)
#define	MT_MATAMAP		(0x00000002)
#define	MT_WRITE_CHECK		(0x00000004)
#define	MT_LOG_WRITE_CHECK	(0x00000008)
#define	MT_CHECK_MAP		(0x00000010)
#define	MT_TRACE		(0x00000020)
#define	MT_SIZE			(0x00000040)
#define	MT_NOASYNC		(0x00000080)
#define	MT_FORCEROLL		(0x00000100)
#define	MT_SCAN			(0x00000200)

struct logstats {
	kstat_named_t ls_lreads;	/* master reads */
	kstat_named_t ls_lwrites;	/* master writes */
	kstat_named_t ls_lreadsinmem;	/* log reads in memory */
	kstat_named_t ls_ldlreads;	/* log reads */
	kstat_named_t ls_ldlwrites;	/* log writes */
	kstat_named_t ls_mreads;	/* log master reads */
	kstat_named_t ls_rreads;	/* log roll reads */
	kstat_named_t ls_rwrites;	/* log roll writes */
};

#ifdef _KERNEL

typedef struct threadtrans {
	ulong_t		deltas_size;	/* size of deltas this transaction */
	uint32_t	last_async_tid;	/* last async transaction id */
	uchar_t		any_deltas;	/* any deltas done this transaction */
#ifdef DEBUG
	uint_t		topid;		/* transaction type */
	ulong_t		esize;		/* estimated trans size */
	ulong_t		rsize;		/* real trans size */
	dev_t		dev;		/* device */
#endif /* DEBUG */
} threadtrans_t;

/*
 * Log layer protos -- lufs_log.c
 */
extern void		ldl_strategy(ml_unit_t *, buf_t *);
extern void		ldl_round_commit(ml_unit_t *);
extern void		ldl_push_commit(ml_unit_t *);
extern int		ldl_need_commit(ml_unit_t *);
extern int		ldl_has_space(ml_unit_t *, mapentry_t *);
extern void		ldl_write(ml_unit_t *, caddr_t, offset_t, mapentry_t *);
extern void		ldl_waito(ml_unit_t *);
extern int		ldl_read(ml_unit_t *, caddr_t, offset_t, off_t,
					mapentry_t *);
extern void		ldl_sethead(ml_unit_t *, off_t, uint32_t);
extern void		ldl_settail(ml_unit_t *, off_t, size_t);
extern ulong_t		ldl_logscan_nbcommit(off_t);
extern int		ldl_logscan_read(ml_unit_t *, off_t *, size_t, caddr_t);
extern void		ldl_logscan_begin(ml_unit_t *);
extern void		ldl_logscan_end(ml_unit_t *);
extern int		ldl_need_roll(ml_unit_t *);
extern void		ldl_seterror(ml_unit_t *, char *);
extern size_t		ldl_bufsize(ml_unit_t *);
extern void		ldl_savestate(ml_unit_t *);
extern void		free_cirbuf(cirbuf_t *);
extern void		alloc_rdbuf(cirbuf_t *, size_t, size_t);
extern void		alloc_wrbuf(cirbuf_t *, size_t);

/*
 * trans driver layer -- lufs.c
 */
extern int		trans_not_wait(struct buf *cb);
extern int		trans_not_done(struct buf *cb);
extern int		trans_wait(struct buf *cb);
extern int		trans_done(struct buf *cb);
extern void		lufs_strategy(ml_unit_t *, buf_t *);
extern void		lufs_read_strategy(ml_unit_t *, buf_t *);
extern void		lufs_write_strategy(ml_unit_t *, buf_t *);
extern void		lufs_init(void);
extern uint32_t		lufs_hd_genid(const ml_unit_t *);
extern int		lufs_enable(struct vnode *, struct fiolog *, cred_t *);
extern int		lufs_disable(vnode_t *, struct fiolog *);

/*
 * transaction op layer -- lufs_top.c
 */
extern void	_init_top(void);
extern int	top_read_roll(rollbuf_t *, ml_unit_t *);


/*
 * map layer -- lufs_map.c
 */
extern void		map_free_entries(mt_map_t *);
extern int		matamap_overlap(mt_map_t *, offset_t, off_t);
extern int		matamap_within(mt_map_t *, offset_t, off_t);
extern int		deltamap_need_commit(mt_map_t *);
extern void		deltamap_add(mt_map_t *, offset_t, off_t, delta_t,
				int (*)(), ulong_t, threadtrans_t *tp);
extern mapentry_t	*deltamap_remove(mt_map_t *, offset_t, off_t);
extern void		deltamap_del(mt_map_t *, offset_t, off_t);
extern void		deltamap_push(ml_unit_t *);
extern void		logmap_cancel_remove(mt_map_t *);
extern int		logmap_need_commit(mt_map_t *);
extern int		logmap_need_roll_async(mt_map_t *);
extern int		logmap_need_roll_sync(mt_map_t *);
extern void		logmap_start_roll(ml_unit_t *);
extern void		logmap_kill_roll(ml_unit_t *);
extern void		logmap_forceroll(mt_map_t *);
extern void		logmap_forceroll_nowait(mt_map_t *);
extern int		logmap_overlap(mt_map_t *, offset_t, off_t);
extern void		logmap_remove_roll(mt_map_t *, offset_t, off_t);
extern int		logmap_next_roll(mt_map_t *, offset_t *);
extern int		logmap_list_get(mt_map_t *, offset_t, off_t,
				mapentry_t **);
extern int		logmap_list_get_roll(mt_map_t *, offset_t, rollbuf_t *);
extern void		logmap_list_put(mt_map_t *, mapentry_t *);
extern void		logmap_list_put_roll(mt_map_t *, mapentry_t *);
extern int		logmap_setup_read(mapentry_t *, rollbuf_t *);
extern void		logmap_make_space(struct mt_map *, ml_unit_t *,
				mapentry_t *);
extern void		logmap_add(ml_unit_t *, char *, offset_t, mapentry_t *);
extern void		logmap_add_buf(ml_unit_t *, char *, offset_t,
				mapentry_t *, caddr_t, uint32_t);
extern void		logmap_commit(ml_unit_t *, uint32_t);
extern void		logmap_sethead(mt_map_t *, ml_unit_t *);
extern void		logmap_settail(mt_map_t *, ml_unit_t *);
extern void		logmap_roll_dev(ml_unit_t *ul);
extern void		logmap_cancel(ml_unit_t *, offset_t, off_t, int);
extern void		logmap_free_cancel(mt_map_t *, mapentry_t **);
extern int		logmap_iscancel(mt_map_t *, offset_t, off_t);
extern void		logmap_logscan(ml_unit_t *);
extern mt_map_t		*map_put(mt_map_t *);
extern mt_map_t		*map_get(ml_unit_t *, enum maptypes, int);
extern void		_init_map(void);

/*
 * scan and roll threads -- lufs_thread.c
 */
extern void	trans_roll(ml_unit_t *);

/*
 * DEBUG
 */
#ifdef	DEBUG
extern int	map_put_debug(mt_map_t *);
extern int	map_get_debug(ml_unit_t *, mt_map_t *);
extern int	top_write_debug(ml_unit_t *, mapentry_t *, offset_t, off_t);
extern int	matamap_overlap(mt_map_t *, offset_t, off_t);
extern int	ldl_sethead_debug(ml_unit_t *);
extern int	map_check_linkage(mt_map_t *);
extern int	logmap_logscan_debug(mt_map_t *, mapentry_t *);
extern int	map_check_ldl_write(ml_unit_t *, caddr_t, offset_t,
								mapentry_t *);
extern int	logmap_logscan_commit_debug(off_t, mt_map_t *);
extern int	logmap_logscan_add_debug(struct delta *, mt_map_t *);
extern int	top_delta_debug(ml_unit_t *, offset_t, off_t, delta_t);
extern int	top_begin_debug(ml_unit_t *, top_t, ulong_t);
extern int	top_end_debug(ml_unit_t *, mt_map_t *, top_t, ulong_t);
extern int	top_roll_debug(ml_unit_t *);
extern int	top_init_debug(void);
extern int	lufs_initialize_debug(ml_odunit_t *);
#endif	/* DEBUG */

extern uint64_t delta_stats[DT_MAX];
extern uint64_t roll_stats[DT_MAX];
extern struct logstats logstats;
extern int ufs_crb_enable;

extern uint_t topkey;
extern uint32_t ufs_ncg_log;

extern uint_t lufs_debug;

#endif	/* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_LOG_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1991, 1996-1999 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _SYS_FS_UFS_MOUNT_H
#define	_SYS_FS_UFS_MOUNT_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/isa_defs.h>

struct ufs_args {
	int	flags;
};

/*
 * UFS mount option flags
 */
#define	UFSMNT_NOINTR	0x00000001	/* disallow interrupts on lockfs */
#define	UFSMNT_SYNCDIR	0x00000002	/* synchronous local directory ops */
#define	UFSMNT_NOSETSEC	0x00000004	/* disallow use of ufs_setsecattr */
#define	UFSMNT_LARGEFILES 0x00000008	/* allow large files */
#define	UFSMNT_NOATIME  0x00001000	/* disable updates of i_atime */
/* deferred inode time */
#define	UFSMNT_NODFRATIME	0x00002000	/* no deferred access time */
/* action to take when internal inconsistency is detected */
#define	UFSMNT_ONERROR_PANIC	0x00000020	/* forced system shutdown */
#define	UFSMNT_ONERROR_LOCK	0x00000040	/* error lock the fs */
#define	UFSMNT_ONERROR_UMOUNT	0x00000080	/* forced umount of the fs */
#define	UFSMNT_ONERROR_FLGMASK	0x000000E0
/* default action is to repair fs */
#define	UFSMNT_ONERROR_DEFAULT		UFSMNT_ONERROR_PANIC
#define	UFSMNT_DISABLEDIRECTIO	0x00000100	/* disable directio ioctls */
/* Force DirectIO */
#define	UFSMNT_FORCEDIRECTIO	0x00000200	/* directio for all files */
#define	UFSMNT_NOFORCEDIRECTIO	0x00000400	/* no directio for all files */
/* logging */
#define	UFSMNT_LOGGING		0x00000800	/* enable logging */

#define	UFSMNT_ONERROR_PANIC_STR	"panic"
#define	UFSMNT_ONERROR_LOCK_STR		"lock"
#define	UFSMNT_ONERROR_UMOUNT_STR	"umount"

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_MOUNT_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_UFS_PANIC_H
#define	_SYS_FS_UFS_PANIC_H

#include <sys/types.h>
#include <sys/vfs.h>
#include <sys/fs/ufs_inode.h>
#include <sys/fs/ufs_fs.h>

#ifdef	__cplusplus
extern "C" {
#endif

#if defined(_KERNEL)

/*
 * failures have an associated state
 *  making them bit values simplifies state transition validity checking
 */

typedef enum ufs_failure_states {
	/* initial states, set mostly by thread encountering failure */
	UF_UNDEF	= 0x0000,	/* freshly-allocated memory */
	UF_INIT		= 0x0001,	/* being created */
	UF_QUEUE	= 0x0002,	/* queued for fix thread */

	/* transitional states, set mostly by fix failure thread */
	UF_TRYLCK	= 0x0010,	/* attempting to be locked */
	UF_LOCKED	= 0x0020,	/* error lock set */
	UF_UMOUNT	= 0x0040,	/* attempting to be unmounted */
	UF_FIXING	= 0x0080,	/* fsck started; attempting unlock */

	/* terminal states, once in this state, fix failure thread is done */
	UF_FIXED	= 0x0100,	/* no problemo, man */
	UF_NOTFIX	= 0x0200,	/* can't fix; shouldn't panic */
	UF_REPLICA	= 0x0400,	/* replica panic; fix original only */
	UF_PANIC	= 0x0800,	/* gave up/exceeded limits/can't fix */
					/* not strictly a terminal state, */
					/* because we will do some actions */
					/* if we find a failure in this state */
					/* but those actions will be terminal */

	/* handy, but used only as terminators and placeholders */
	UF_ILLEGAL	= 0xffff,	/* invalid state */
	UF_ALLSTATES	= 0x0ff3	/* all possible state */
} ufs_failure_states_t;

/*
 * each manifestation of a fault (ie. "panic") is
 * associated with a distinct ufs_failure event
 */

typedef struct ufs_failure
{
	struct ufs_failure	*uf_chain[2];	/* protected by ufs_elock mux */
	struct ufs_failure	*uf_orig;	/* if duplicate event, */
						/* here's the original */
	struct ufs_failure	*uf_master;	/* if sharing a logged device */
						/* here's the master failure */
	struct buf		*uf_bp;		/* ptr to buf containing sb */
	kmutex_t		*uf_vfs_lockp;	/* ptr to vfs_lock */
	struct vfs_ufsfx	*uf_vfs_ufsfxp;	/* ptr to fix-on-panic per fs */
	struct vfs		*uf_vfsp;	/* ptr to vfs */
	struct ufsvfs		*uf_ufsvfsp;	/* to match if unmounted */
	dev_t			 uf_dev;	/* device id */
	ufs_failure_states_t	 uf_s;		/* current failure state */
	int			 uf_flags;	/* internal flags */
	time_t			 uf_begin_tm;	/* when did panic begin? */
	time_t			 uf_end_tm;	/* ... end? */
	time_t			 uf_entered_tm;	/* ... was state entered? */
	struct lockfs		 uf_lf;		/* needed to set lockfs lock */
	int			 uf_lf_err;	/* errno if lockfs fails  */
	long			 uf_retry;	/* seconds */
	unsigned		 uf_counter;	/* of state-specific actions */
	kmutex_t		 uf_mutex;	/* protects struct body */
	char		uf_fsname[MAXMNTLEN];	/* for post-unmount errors */
						/* after ufsvfsp is free'd */
	char uf_panic_str[LOCKFS_MAXCOMMENTLEN]; /* original panic message */
						/* XXX could be smaller */
} ufs_failure_t;

#define	uf_next	uf_chain[0]
#define	uf_prev	uf_chain[1]
#define	uf_fs	uf_bp->b_un.b_fs

/*
 * per-filesystem panic event state
 */
typedef struct vfs_ufsfx {
	long		 fx_flags;		/* see ufs_panic.h for the */
	ufs_failure_t	*fx_current;		/* currently being fixed */
} vfs_ufsfx_t;

/*
 * External entry points
 *
 *  ufs_fault(vnode_t *, char *fmt, ...)
 *	replaces calls to cmn_err(CE_PANIC, char *fmt, ...)
 *  	The vnode is any vnode in the filesystem.
 *	ufs_fault returns an errno to bubble up.
 *  ufsfx_init()
 *	is called at modload time to set global values etc.
 *  ufsfx_mount()
 *	is called at mount time to do per-fs initialization
 *	returns 0 (ok) or errno
 *  ufsfx_unmount()
 *	is called at unmount time to prevent spinning on work
 *	to fix an unmounted fs
 *  ufsfx_lockfs()
 *  ufsfx_unlockfs()
 *      are called at upon (un)locking of a fs for coordination
 *  ufsfx_get_failure_qlen()
 *	is called by the hlock thread to coordinate with the fix
 *	failure thread
 */

/*PRINTFLIKE2*/
int	ufs_fault(vnode_t *, char *fmt, ...) __KPRINTFLIKE(2);
void	ufsfx_init(void);
int	ufsfx_mount(struct ufsvfs *, int);
void	ufsfx_unmount(struct ufsvfs *);
void	ufsfx_lockfs(struct ufsvfs *);
void	ufsfx_unlockfs(struct ufsvfs *);
int	ufsfx_get_failure_qlen(void);

extern struct ufs_q ufs_fix;

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_PANIC_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
 *
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * Please do not edit this file.
 * It was generated using rpcgen.
 */

#ifndef _SYS_FS_UFS_PROT_H
#define	_SYS_FS_UFS_PROT_H

#include <rpc/rpc.h>

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/fs/ufs_fs.h>
#include <sys/types.h>
#include <sys/errno.h>

enum ufsdrc_t {
	UFSDRC_OK = 0,
	UFSDRC_NOENT = ENOENT,
	UFSDRC_PERM = EPERM,
	UFSDRC_INVAL = EINVAL,
	UFSDRC_NOEXEC = ENOEXEC,
	UFSDRC_NODEV = ENODEV,
	UFSDRC_NXIO = ENXIO,
	UFSDRC_BUSY = EBUSY,
	UFSDRC_OPNOTSUP = EOPNOTSUPP,
	UFSDRC_EXECERR = 254,
	UFSDRC_ERR = 255
};
typedef enum ufsdrc_t ufsdrc_t;

struct fs_identity_t {
	dev32_t fs_dev;
	char *fs_name;
};
typedef struct fs_identity_t fs_identity_t;

struct ufsd_repairfs_args_t {
	fs_identity_t ua_fsid;
	uint_t ua_attempts;
};
typedef struct ufsd_repairfs_args_t ufsd_repairfs_args_t;

struct ufsd_repairfs_list_t {
	int ual_listlen;
	ufsd_repairfs_args_t *ual_list;
};
typedef struct ufsd_repairfs_list_t ufsd_repairfs_list_t;

enum ufsd_event_t {
	UFSDEV_NONE = 0,
	UFSDEV_REBOOT = 0 + 1,
	UFSDEV_FSCK = 0 + 2,
	UFSDEV_LOG_OP = 0 + 3
};
typedef enum ufsd_event_t ufsd_event_t;

enum ufsd_boot_type_t {
	UFSDB_NONE = 0,
	UFSDB_CLEAN = 0 + 1,
	UFSDB_POSTPANIC = 0 + 2
};
typedef enum ufsd_boot_type_t ufsd_boot_type_t;

enum ufsd_log_op_t {
	UFSDLO_NONE = 0,
	UFSDLO_COMMIT = 0 + 1,
	UFSDLO_GET = 0 + 2,
	UFSDLO_PUT = 0 + 3,
	UFSDLO_RESET = 0 + 4
};
typedef enum ufsd_log_op_t ufsd_log_op_t;

enum ufsd_fsck_state_t {
	UFSDFS_NONE = 0,
	UFSDFS_DISPATCH = 0 + 1,
	UFSDFS_ERREXIT = 0 + 2,
	UFSDFS_SUCCESS = 0 + 3
};
typedef enum ufsd_fsck_state_t ufsd_fsck_state_t;
#define	UFSD_VARMSGMAX 1024
#define	UFSD_SPAREMSGBYTES 4

struct ufsd_log_data_t {
	int umld_eob;
	int umld_seq;
	struct {
		uint_t umld_buf_len;
		char *umld_buf_val;
	} umld_buf;
};
typedef struct ufsd_log_data_t ufsd_log_data_t;

struct ufsd_log_msg_t {
	ufsd_log_op_t um_lop;
	union {
		ufsd_log_data_t um_logdata;
	} ufsd_log_msg_t_u;
};
typedef struct ufsd_log_msg_t ufsd_log_msg_t;

struct ufsd_msg_vardata_t {
	ufsd_event_t umv_ev;
	union {
		ufsd_boot_type_t umv_b;
		ufsd_fsck_state_t umv_fs;
		ufsd_log_msg_t umv_lm;
	} ufsd_msg_vardata_t_u;
};
typedef struct ufsd_msg_vardata_t ufsd_msg_vardata_t;

struct ufsd_msg_t {
	time32_t um_time;
	uint_t um_from;
	struct {
		uint_t um_spare_len;
		char *um_spare_val;
	} um_spare;
	ufsd_msg_vardata_t um_var;
};
typedef struct ufsd_msg_t ufsd_msg_t;
#define	UFSD_SERVNAME	"ufsd"
#define	xdr_dev_t	xdr_u_int
#define	xdr_time_t	xdr_int
/*
 * Set UFSD_THISVERS to the newest version of the protocol
 * This allows the preprocessor to force an error if the
 * protocol changes, since the kernel xdr routines may need to be
 * recoded.  Note that we can't explicitly set the version to a
 * symbol as rpcgen will then create erroneous routine names.
 */
#define	UFSD_V1			1
#define	UFSD_ORIGVERS		UFSD_V1
#define	UFSD_THISVERS		1

#define	UFSD_PROG ((unsigned long)(100233))
#define	UFSD_VERS ((unsigned long)(1))

#define	UFSD_NULL ((unsigned long)(0))
extern  ufsdrc_t *ufsd_null_1(void *, CLIENT *);
extern  ufsdrc_t *ufsd_null_1_svc(void *, struct svc_req *);
#define	UFSD_REPAIRFS ((unsigned long)(1))
extern  ufsdrc_t *ufsd_repairfs_1(ufsd_repairfs_args_t *, CLIENT *);
extern  ufsdrc_t *
		ufsd_repairfs_1_svc(ufsd_repairfs_args_t *, struct svc_req *);
#define	UFSD_REPAIRFSLIST ((unsigned long)(2))
extern  ufsdrc_t *ufsd_repairfslist_1(ufsd_repairfs_list_t *, CLIENT *);
extern  ufsdrc_t *
	ufsd_repairfslist_1_svc(ufsd_repairfs_list_t *, struct svc_req *);
#define	UFSD_SEND ((unsigned long)(3))
extern  ufsdrc_t *ufsd_send_1(ufsd_msg_t *, CLIENT *);
extern  ufsdrc_t *ufsd_send_1_svc(ufsd_msg_t *, struct svc_req *);
#define	UFSD_RECV ((unsigned long)(4))
extern  ufsdrc_t *ufsd_recv_1(ufsd_msg_t *, CLIENT *);
extern  ufsdrc_t *ufsd_recv_1_svc(ufsd_msg_t *, struct svc_req *);
#define	UFSD_EXIT ((unsigned long)(5))
extern  ufsdrc_t *ufsd_exit_1(void *, CLIENT *);
extern  ufsdrc_t *ufsd_exit_1_svc(void *, struct svc_req *);
extern int ufsd_prog_1_freeresult(SVCXPRT *, xdrproc_t, caddr_t);

/* the xdr functions */

extern  bool_t xdr_ufsdrc_t(XDR *, ufsdrc_t *);
extern  bool_t xdr_fs_identity_t(XDR *, fs_identity_t *);
extern  bool_t xdr_ufsd_repairfs_args_t(XDR *, ufsd_repairfs_args_t *);
extern  bool_t xdr_ufsd_repairfs_list_t(XDR *, ufsd_repairfs_list_t *);
extern  bool_t xdr_ufsd_event_t(XDR *, ufsd_event_t *);
extern  bool_t xdr_ufsd_boot_type_t(XDR *, ufsd_boot_type_t *);
extern  bool_t xdr_ufsd_log_op_t(XDR *, ufsd_log_op_t *);
extern  bool_t xdr_ufsd_fsck_state_t(XDR *, ufsd_fsck_state_t *);
extern  bool_t xdr_ufsd_log_data_t(XDR *, ufsd_log_data_t *);
extern  bool_t xdr_ufsd_log_msg_t(XDR *, ufsd_log_msg_t *);
extern  bool_t xdr_ufsd_msg_vardata_t(XDR *, ufsd_msg_vardata_t *);
extern  bool_t xdr_ufsd_msg_t(XDR *, ufsd_msg_t *);

#ifdef __cplusplus
}
#endif

#endif /* !_SYS_FS_UFS_PROT_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved	*/

/*
 * University Copyright- Copyright (c) 1982, 1986, 1988
 * The Regents of the University of California
 * All Rights Reserved
 *
 * University Acknowledgment- Portions of this document are derived from
 * software developed by the University of California, Berkeley, and its
 * contributors.
 */

#ifndef	_SYS_FS_UFS_QUOTA_H
#define	_SYS_FS_UFS_QUOTA_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Lock order for the quota sub-system:
 *
 *  vfs_dqrwlock > ip.i_contents > dq_cachelock > dquot.dq_lock > dq_freelock
 *  vfs_dqrwlock > ip.i_contents > dq_cachelock >                 dq_freelock
 *  vfs_dqrwlock > ip.i_contents >                dquot.dq_lock > dq_freelock
 *  vfs_dqrwlock > ip.i_contents >                                dq_freelock
 *  vfs_dqrwlock > ip.i_contents > dq_cachelock > dquot.dq_lock > qip.i_contents
 */

/*
 * The following constants define the default amount of time given a user
 * before the soft limits are treated as hard limits (usually resulting
 * in an allocation failure). These may be  modified by the quotactl
 * system call with the Q_SETQLIM or Q_SETQUOTA commands.
 */

#define	DQ_FTIMELIMIT	(7 * 24*60*60)		/* 1 week */
#define	DQ_BTIMELIMIT	(7 * 24*60*60)		/* 1 week */

/*
 * The dqblk structure defines the format of the disk quota file
 * (as it appears on disk) - the file is an array of these structures
 * indexed by user number.  The setquota sys call establishes the inode
 * for each quota file (a pointer is retained in the mount structure).
 */

struct dqblk {
	uint32_t  dqb_bhardlimit; /* absolute limit on disk blks alloc */
	uint32_t  dqb_bsoftlimit; /* preferred limit on disk blks */
	uint32_t  dqb_curblocks;  /* current block count */
	uint32_t  dqb_fhardlimit; /* maximum # allocated files + 1 */
	uint32_t  dqb_fsoftlimit; /* preferred file limit */
	uint32_t  dqb_curfiles;   /* current # allocated files */
	uint32_t  dqb_btimelimit; /* time limit for excessive disk use */
	uint32_t  dqb_ftimelimit; /* time limit for excessive files */
};

#define	dqoff(UID)	(((offset_t)(UID) * sizeof (struct dqblk)))

/*
 * The dquot structure records disk usage for a user on a filesystem.
 * There is one allocated for each quota that exists on any filesystem
 * for the current user. A cache is kept of recently used entries.
 * Active inodes have a pointer to the dquot associated with them.
 */
struct  dquot {
	struct dquot *dq_forw, *dq_back; /* hash list, MUST be first entry */
	struct dquot *dq_freef, *dq_freeb; /* free list */
	short	dq_flags;
#define	DQ_ERROR	0x01		/* An error occurred reading dq */
#define	DQ_MOD		0x04		/* this quota modified since read */
#define	DQ_BLKS		0x10		/* has been warned about blk limit */
#define	DQ_FILES	0x20		/* has been warned about file limit */
#define	DQ_TRANS	0x40		/* logging ufs operation started */
	ulong_t	dq_cnt;			/* count of active references */
	uid_t	dq_uid;			/* user this applies to */
	struct ufsvfs *dq_ufsvfsp;	/* filesystem this relates to */
	offset_t dq_mof;		/* master disk offset of quota record */
	struct dqblk dq_dqb;		/* actual usage & quotas */
#ifdef _KERNEL
	kmutex_t	dq_lock;	/* per dq structure lock */
#endif /* _KERNEL */
};

#define	dq_bhardlimit	dq_dqb.dqb_bhardlimit
#define	dq_bsoftlimit	dq_dqb.dqb_bsoftlimit
#define	dq_curblocks	dq_dqb.dqb_curblocks
#define	dq_fhardlimit	dq_dqb.dqb_fhardlimit
#define	dq_fsoftlimit	dq_dqb.dqb_fsoftlimit
#define	dq_curfiles	dq_dqb.dqb_curfiles
#define	dq_btimelimit	dq_dqb.dqb_btimelimit
#define	dq_ftimelimit	dq_dqb.dqb_ftimelimit

/*
 * flags for vfs_qflags in ufsvfs struct
 */
#define	MQ_ENABLED	0x01		/* quotas are enabled */

#if defined(_KERNEL)

/*
 * dquot chach hash chain headers
 */
#define	NDQHASH		64			/* smallish power of two */
#define	DQHASH(uid, mp) \
	(((uintptr_t)(mp) + (unsigned)(uid)) & (NDQHASH-1))

struct	dqhead {
	struct	dquot	*dqh_forw;	/* MUST be first */
	struct	dquot	*dqh_back;	/* MUST be second */
};

extern struct dqhead dqhead[NDQHASH];

extern struct dquot *dquot, *dquotNDQUOT;
extern int ndquot;
extern krwlock_t dq_rwlock;		/* quota sub-system init lock */
extern int quotas_initialized;		/* quota sub-system init flag */

extern void qtinit();
extern void qtinit2();
extern struct dquot *getinoquota(struct inode *);
extern int chkdq(struct inode *ip, long, int, struct cred *, char **errp,
		size_t *lenp);
extern int chkiq(struct ufsvfs *, int, struct inode *, uid_t, int,
		struct cred *, char **errp, size_t *lenp);
extern void dqrele(struct dquot *);
extern int closedq(struct ufsvfs *, struct cred *);
extern int qsync(struct ufsvfs *);

extern int getdiskquota(uid_t, struct ufsvfs *, int, struct dquot **);
extern void dqput(struct dquot *);
extern void dqupdate(struct dquot *);
extern void dqinval(struct dquot *);
extern void invalidatedq(struct ufsvfs *);

extern int quotactl(struct vnode *, intptr_t, int flag, struct cred *);

#endif	/* _KERNEL */

/*
 * Definitions for the 'quotactl' system call.
 */
#define	Q_QUOTAON	1	/* turn quotas on */
#define	Q_QUOTAOFF	2	/* turn quotas off */
#define	Q_SETQUOTA	3	/* set disk limits & usage */
#define	Q_GETQUOTA	4	/* get disk limits & usage */
#define	Q_SETQLIM	5	/* set disk limits only */
#define	Q_SYNC		6	/* update disk copy of quota usages */
#define	Q_ALLSYNC	7	/* update disk copy of quota usages for all */

#ifdef _SYSCALL32
/* ILP32 compatible structure for LP64 kernel. */
struct quotctl32 {
	int		op;
	uid_t		uid;
	uint32_t	addr;
};
#endif /* SYSCALL32 */

struct quotctl {
	int	op;
	uid_t	uid;
	caddr_t	addr;
};

#define	Q_QUOTACTL	0x00030189	/* ioctl command for quotactl */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_QUOTA_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_FS_UFS_SNAP_H
#define	_SYS_FS_UFS_SNAP_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/fssnap_if.h>
#include <sys/vnode.h>
#include <sys/cred.h>

/* debug levels */
#define	UFSSNAPDB_CREATE	0x01
#define	UFSSNAPDB_DELETE	0x02

/* Constants */
#define	UFS_MAX_SNAPBACKFILESIZE	(1LL << 39)  /* 512 GB */

extern int ufs_snap_create(struct vnode *, struct fiosnapcreate_multi *,
    cred_t *);
extern int ufs_snap_delete(struct vnode *, struct fiosnapdelete *, cred_t *);

#ifdef	__cplusplus
}
#endif

#endif /* _SYS_FS_UFS_SNAP_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
 *
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_FS_UFS_TRANS_H
#define	_SYS_FS_UFS_TRANS_H

#ifdef	__cplusplus
extern "C" {
#endif

#include	<sys/types.h>
#include	<sys/cred.h>
#include	<sys/fs/ufs_fs.h>

/*
 * Types of deltas
 */
typedef enum delta_type {
	DT_NONE,	/*  0 no assigned type */
	DT_SB,		/*  1 superblock */
	DT_CG,		/*  2 cylinder group */
	DT_SI,		/*  3 summary info */
	DT_AB,		/*  4 allocation block */
	DT_ABZERO,	/*  5 a zero'ed allocation block */
	DT_DIR,		/*  6 directory */
	DT_INODE,	/*  7 inode */
	DT_FBI,		/*  8 fbiwrite */
	DT_QR,		/*  9 quota record */
	DT_COMMIT,	/* 10 commit record */
	DT_CANCEL,	/* 11 cancel record */
	DT_BOT,		/* 12 begin transaction */
	DT_EOT,		/* 13 end   transaction */
	DT_UD,		/* 14 userdata */
	DT_SUD,		/* 15 userdata found during log scan */
	DT_SHAD,	/* 16 data for a shadow inode */
	DT_MAX		/* 17 maximum delta type */
} delta_t;

/*
 * transaction operation types
 */
typedef enum top_type {
	TOP_READ_SYNC,		/* 0 */
	TOP_WRITE,		/* 1 */
	TOP_WRITE_SYNC,		/* 2 */
	TOP_SETATTR,		/* 3 */
	TOP_CREATE,		/* 4 */
	TOP_REMOVE,		/* 5 */
	TOP_LINK,		/* 6 */
	TOP_RENAME,		/* 7 */
	TOP_MKDIR,		/* 8 */
	TOP_RMDIR,		/* 9 */
	TOP_SYMLINK,		/* 10 */
	TOP_FSYNC,		/* 11 */
	TOP_GETPAGE,		/* 12 */
	TOP_PUTPAGE,		/* 13 */
	TOP_SBUPDATE_FLUSH,	/* 14 */
	TOP_SBUPDATE_UPDATE,	/* 15 */
	TOP_SBUPDATE_UNMOUNT,	/* 16 */
	TOP_SYNCIP_CLOSEDQ,	/* 17 */
	TOP_SYNCIP_FLUSHI,	/* 18 */
	TOP_SYNCIP_HLOCK,	/* 19 */
	TOP_SYNCIP_SYNC,	/* 20 */
	TOP_SYNCIP_FREE,	/* 21 */
	TOP_SBWRITE_RECLAIM,	/* 22 */
	TOP_SBWRITE_STABLE,	/* 23 */
	TOP_IFREE,		/* 24 */
	TOP_IUPDAT,		/* 25 */
	TOP_MOUNT,		/* 26 */
	TOP_COMMIT_ASYNC,	/* 27 */
	TOP_COMMIT_FLUSH,	/* 28 */
	TOP_COMMIT_UPDATE,	/* 29 */
	TOP_COMMIT_UNMOUNT,	/* 30 */
	TOP_SETSECATTR,		/* 31 */
	TOP_QUOTA,		/* 32 */
	TOP_ITRUNC,		/* 33 */
	TOP_ALLOCSP,		/* 34 */
	TOP_MAX			/* 35 TOP_MAX MUST be the last entry */
} top_t;

struct inode;
struct ufsvfs;

/*
 * vfs_log == NULL means not logging
 */
#define	TRANS_ISTRANS(ufsvfsp)	(ufsvfsp->vfs_log)

/*
 * begin a synchronous transaction
 */
#define	TRANS_BEGIN_SYNC(ufsvfsp, vid, vsize, error)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) { \
		error = 0; \
		top_begin_sync(ufsvfsp, vid, vsize, &error); \
	} \
}

/*
 * begin a asynchronous transaction
 */
#define	TRANS_BEGIN_ASYNC(ufsvfsp, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		(void) top_begin_async(ufsvfsp, vid, vsize, 0); \
}

/*
 * try to begin a asynchronous transaction
 */
#define	TRANS_TRY_BEGIN_ASYNC(ufsvfsp, vid, vsize, err)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		err = top_begin_async(ufsvfsp, vid, vsize, 1); \
	else\
		err = 0; \
}

/*
 * Begin a synchronous or asynchronous transaction.
 * The lint case is needed because vsize can be a constant.
 */
#ifndef __lint

#define	TRANS_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) {\
		if (ufsvfsp->vfs_syncdir) {\
			int error = 0; \
			ASSERT(vsize); \
			top_begin_sync(ufsvfsp, vid, vsize, &error); \
			ASSERT(error == 0); \
			issync = 1; \
		} else {\
			(void) top_begin_async(ufsvfsp, vid, vsize, 0); \
			issync = 0; \
		}\
	}\
}

#else /* __lint */

#define	TRANS_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) {\
		if (ufsvfsp->vfs_syncdir) {\
			int error = 0; \
			top_begin_sync(ufsvfsp, vid, vsize, &error); \
			issync = 1; \
		} else {\
			(void) top_begin_async(ufsvfsp, vid, vsize, 0); \
			issync = 0; \
		}\
	}\
}
#endif /* __lint */

/*
 * try to begin a synchronous or asynchronous transaction
 */

#define	TRANS_TRY_BEGIN_CSYNC(ufsvfsp, issync, vid, vsize, error)\
{\
	if (TRANS_ISTRANS(ufsvfsp)) {\
		if (ufsvfsp->vfs_syncdir) {\
			ASSERT(vsize); \
			top_begin_sync(ufsvfsp, vid, vsize, &error); \
			ASSERT(error == 0); \
			issync = 1; \
		} else {\
			error = top_begin_async(ufsvfsp, vid, vsize, 1); \
			issync = 0; \
		}\
	}\
}\


/*
 * end a asynchronous transaction
 */
#define	TRANS_END_ASYNC(ufsvfsp, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		top_end_async(ufsvfsp, vid, vsize); \
}

/*
 * end a synchronous transaction
 */
#define	TRANS_END_SYNC(ufsvfsp, error, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		top_end_sync(ufsvfsp, &error, vid, vsize); \
}

/*
 * end a synchronous or asynchronous transaction
 */
#define	TRANS_END_CSYNC(ufsvfsp, error, issync, vid, vsize)\
{\
	if (TRANS_ISTRANS(ufsvfsp))\
		if (issync)\
			top_end_sync(ufsvfsp, &error, vid, vsize); \
		else\
			top_end_async(ufsvfsp, vid, vsize); \
}
/*
 * record a delta
 */
#define	TRANS_DELTA(ufsvfsp, mof, nb, dtyp, func, arg) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_delta(ufsvfsp, (offset_t)(mof), nb, dtyp, func, arg)

/*
 * cancel a delta
 */
#define	TRANS_CANCEL(ufsvfsp, mof, nb, flags) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_cancel(ufsvfsp, (offset_t)(mof), nb, flags)
/*
 * log a delta
 */
#define	TRANS_LOG(ufsvfsp, va, mof, nb, buf, bufsz) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_log(ufsvfsp, va, (offset_t)(mof), nb, buf, bufsz)
/*
 * check if a range is being canceled (converting from metadata into userdata)
 */
#define	TRANS_ISCANCEL(ufsvfsp, mof, nb) \
	((TRANS_ISTRANS(ufsvfsp)) ? \
		top_iscancel(ufsvfsp, (offset_t)(mof), nb) : 0)
/*
 * put the log into error state
 */
#define	TRANS_SETERROR(ufsvfsp) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		top_seterror(ufsvfsp)
/*
 * check if device has had an error
 */
#define	TRANS_ISERROR(ufsvfsp) \
	((TRANS_ISTRANS(ufsvfsp)) ? \
		ufsvfsp->vfs_log->un_flags & LDL_ERROR : 0)

/*
 * The following macros provide a more readable interface to TRANS_DELTA
 */
#define	TRANS_BUF(ufsvfsp, vof, nb, bp, type) \
	TRANS_DELTA(ufsvfsp, \
		ldbtob(bp->b_blkno) + (offset_t)(vof), nb, type, \
		ufs_trans_push_buf, bp->b_blkno)

#define	TRANS_BUF_ITEM_128(ufsvfsp, item, base, bp, type) \
	TRANS_BUF(ufsvfsp, \
	(((uintptr_t)&(item)) & ~(128 - 1)) - (uintptr_t)(base), 128, bp, type)

#define	TRANS_INODE(ufsvfsp, ip) \
	TRANS_DELTA(ufsvfsp, ip->i_doff, sizeof (struct dinode), \
			DT_INODE, ufs_trans_push_inode, ip->i_number)

/*
 * If ever parts of an inode except the timestamps are logged using
 * this macro (or any other technique), bootloader logging support must
 * be made aware of these changes.
 */
#define	TRANS_INODE_DELTA(ufsvfsp, vof, nb, ip) \
	TRANS_DELTA(ufsvfsp, (ip->i_doff + (offset_t)(vof)), \
		nb, DT_INODE, ufs_trans_push_inode, ip->i_number)

#define	TRANS_INODE_TIMES(ufsvfsp, ip) \
	TRANS_INODE_DELTA(ufsvfsp, (caddr_t)&ip->i_atime - (caddr_t)&ip->i_ic, \
		sizeof (struct timeval32) * 3, ip)

/*
 * Check if we need to log cylinder group summary info.
 */
#define	TRANS_SI(ufsvfsp, fs, cg) \
	if (TRANS_ISTRANS(ufsvfsp)) \
		if (ufsvfsp->vfs_nolog_si) \
			fs->fs_si = FS_SI_BAD; \
		else \
			TRANS_DELTA(ufsvfsp, \
				ldbtob(fsbtodb(fs, fs->fs_csaddr)) + \
				((caddr_t)&fs->fs_cs(fs, cg) - \
				(caddr_t)fs->fs_u.fs_csp), \
				sizeof (struct csum), DT_SI, \
				ufs_trans_push_si, cg)

#define	TRANS_DIR(ip, offset) \
	(TRANS_ISTRANS(ip->i_ufsvfs) ? ufs_trans_dir(ip, offset) : 0)

#define	TRANS_QUOTA(dqp)	\
	if (TRANS_ISTRANS(dqp->dq_ufsvfsp))	\
		ufs_trans_quota(dqp);

#define	TRANS_DQRELE(ufsvfsp, dqp) \
	if (TRANS_ISTRANS(ufsvfsp) && \
	    ((curthread->t_flag & T_DONTBLOCK) == 0)) { \
		ufs_trans_dqrele(dqp); \
	} else { \
		rw_enter(&ufsvfsp->vfs_dqrwlock, RW_READER); \
		dqrele(dqp); \
		rw_exit(&ufsvfsp->vfs_dqrwlock); \
	}

#define	TRANS_ITRUNC(ip, length, flags, cr)	\
	ufs_trans_itrunc(ip, length, flags, cr);

#define	TRANS_WRITE_RESV(ip, uiop, ulp, resvp, residp)	\
	if ((TRANS_ISTRANS(ip->i_ufsvfs) != NULL) && (ulp != NULL)) \
		ufs_trans_write_resv(ip, uiop, resvp, residp);

#define	TRANS_WRITE(ip, uiop, ioflag, err, ulp, cr, resv, resid)	\
	if ((TRANS_ISTRANS(ip->i_ufsvfs) != NULL) && (ulp != NULL)) \
		err = ufs_trans_write(ip, uiop, ioflag, cr, resv, resid); \
	else \
		err = wrip(ip, uiop, ioflag, cr);

/*
 * These functions "wrap" functions that are not VOP or VFS
 * entry points but must still use the TRANS_BEGIN/TRANS_END
 * protocol
 */
#define	TRANS_SBUPDATE(ufsvfsp, vfsp, topid) \
	ufs_trans_sbupdate(ufsvfsp, vfsp, topid)
#define	TRANS_SYNCIP(ip, bflags, iflag, topid) \
	ufs_syncip(ip, bflags, iflag, topid)
#define	TRANS_SBWRITE(ufsvfsp, topid)	ufs_trans_sbwrite(ufsvfsp, topid)
#define	TRANS_IUPDAT(ip, waitfor)	ufs_trans_iupdat(ip, waitfor)

#ifdef	DEBUG
/*
 * Test/Debug ops
 *	The following ops maintain the metadata map.
 *	The metadata map is a debug/test feature.
 *	These ops are *not* used in the production product.
 */

/*
 * Set a flag if meta data checking.
 */
#define	TRANS_DOMATAMAP(ufsvfsp) \
	ufsvfsp->vfs_domatamap = \
		(TRANS_ISTRANS(ufsvfsp) && \
		(ufsvfsp->vfs_log->un_debug & MT_MATAMAP))

#define	TRANS_MATA_IGET(ufsvfsp, ip) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_iget(ip)

#define	TRANS_MATA_FREE(ufsvfsp, mof, nb) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_free(ufsvfsp, (offset_t)(mof), nb)

#define	TRANS_MATA_ALLOC(ufsvfsp, ip, bno, size, zero) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_alloc(ufsvfsp, ip, bno, size, zero)

#define	TRANS_MATA_MOUNT(ufsvfsp) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_mount(ufsvfsp)

#define	TRANS_MATA_UMOUNT(ufsvfsp) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_umount(ufsvfsp)

#define	TRANS_MATA_SI(ufsvfsp, fs) \
	if (ufsvfsp->vfs_domatamap) \
		ufs_trans_mata_si(ufsvfsp, fs)

#define	TRANS_MATAADD(ufsvfsp, mof, nb) \
	top_mataadd(ufsvfsp, (offset_t)(mof), nb)

#else /* !DEBUG */

#define	TRANS_DOMATAMAP(ufsvfsp)
#define	TRANS_MATA_IGET(ufsvfsp, ip)
#define	TRANS_MATA_FREE(ufsvfsp, mof, nb)
#define	TRANS_MATA_ALLOC(ufsvfsp, ip, bno, size, zero)
#define	TRANS_MATA_MOUNT(ufsvfsp)
#define	TRANS_MATA_UMOUNT(ufsvfsp)
#define	TRANS_MATA_SI(ufsvfsp, fs)
#define	TRANS_MATAADD(ufsvfsp, mof, nb)

#endif  /* !DEBUG */

#include	<sys/fs/ufs_quota.h>
#include	<sys/fs/ufs_lockfs.h>
/*
 * identifies the type of operation passed into TRANS_BEGIN/END
 */
#define	TOP_SYNC		(0x00000001)
#define	TOP_ASYNC		(0x00000002)
#define	TOP_SYNC_FORCED		(0x00000004)	/* forced sync transaction */
/*
 *  estimated values
 */
#define	HEADERSIZE		(128)
#define	ALLOCSIZE		(160)
#define	INODESIZE		(sizeof (struct dinode) + HEADERSIZE)
#define	SIZESB			((sizeof (struct fs)) + HEADERSIZE)
#define	SIZEDIR			(DIRBLKSIZ + HEADERSIZE)
/*
 * calculated values
 */
#define	SIZECG(IP)		((IP)->i_fs->fs_cgsize + HEADERSIZE)
#define	FRAGSIZE(IP)		((IP)->i_fs->fs_fsize + HEADERSIZE)
#define	ACLSIZE(IP)		(((IP)->i_ufsvfs->vfs_maxacl + HEADERSIZE) + \
					INODESIZE)
#define	MAXACLSIZE		((MAX_ACL_ENTRIES << 1) * sizeof (aclent_t))
#define	DIRSIZE(IP)		(INODESIZE + (4 * ALLOCSIZE) + \
				    (IP)->i_fs->fs_fsize + HEADERSIZE)
#define	QUOTASIZE		sizeof (struct dquot) + HEADERSIZE
/*
 * size calculations
 */
#define	TOP_CREATE_SIZE(IP)	\
	(ACLSIZE(IP) + SIZECG(IP) + DIRSIZE(IP) + INODESIZE)
#define	TOP_REMOVE_SIZE(IP)	\
	DIRSIZE(IP)  + SIZECG(IP) + INODESIZE + SIZESB
#define	TOP_LINK_SIZE(IP)	\
	DIRSIZE(IP) + INODESIZE
#define	TOP_RENAME_SIZE(IP)	\
	DIRSIZE(IP) + DIRSIZE(IP) + SIZECG(IP)
#define	TOP_MKDIR_SIZE(IP)	\
	DIRSIZE(IP) + INODESIZE + DIRSIZE(IP) + INODESIZE + FRAGSIZE(IP) + \
	    SIZECG(IP) + ACLSIZE(IP)
#define	TOP_SYMLINK_SIZE(IP)	\
	DIRSIZE((IP)) + INODESIZE + INODESIZE + SIZECG(IP)
#define	TOP_GETPAGE_SIZE(IP)	\
	ALLOCSIZE + ALLOCSIZE + ALLOCSIZE + INODESIZE + SIZECG(IP)
#define	TOP_SYNCIP_SIZE		INODESIZE
#define	TOP_READ_SIZE		INODESIZE
#define	TOP_RMDIR_SIZE		(SIZESB + (INODESIZE * 2) + SIZEDIR)
#define	TOP_SETQUOTA_SIZE(FS)	((FS)->fs_bsize << 2)
#define	TOP_QUOTA_SIZE		(QUOTASIZE)
#define	TOP_SETSECATTR_SIZE(IP)	(MAXACLSIZE)
#define	TOP_IUPDAT_SIZE(IP)	INODESIZE + SIZECG(IP)
#define	TOP_SBUPDATE_SIZE	(SIZESB)
#define	TOP_SBWRITE_SIZE	(SIZESB)
#define	TOP_PUTPAGE_SIZE(IP)	(INODESIZE + SIZECG(IP))
#define	TOP_SETATTR_SIZE(IP)	(SIZECG(IP) + INODESIZE + QUOTASIZE + \
		ACLSIZE(IP))
#define	TOP_IFREE_SIZE(IP)	(SIZECG(IP) + INODESIZE + QUOTASIZE)
#define	TOP_MOUNT_SIZE		(SIZESB)
#define	TOP_COMMIT_SIZE		(0)

/*
 * The minimum log size is 1M.  So we will allow 1 fs operation to
 * reserve at most 512K of log space.
 */
#define	TOP_MAX_RESV	(512 * 1024)


/*
 * ufs trans function prototypes
 */
#if defined(_KERNEL)

extern int		ufs_trans_hlock();
extern void		ufs_trans_onerror();
extern int		ufs_trans_push_inode(struct ufsvfs *, delta_t, ino_t);
extern int		ufs_trans_push_buf(struct ufsvfs *, delta_t, daddr_t);
extern int		ufs_trans_push_si(struct ufsvfs *, delta_t, int);
extern void		ufs_trans_sbupdate(struct ufsvfs *, struct vfs *,
				top_t);
extern void		ufs_trans_sbwrite(struct ufsvfs *, top_t);
extern void		ufs_trans_iupdat(struct inode *, int);
extern void		ufs_trans_mata_mount(struct ufsvfs *);
extern void		ufs_trans_mata_umount(struct ufsvfs *);
extern void		ufs_trans_mata_si(struct ufsvfs *, struct fs *);
extern void		ufs_trans_mata_iget(struct inode *);
extern void		ufs_trans_mata_free(struct ufsvfs *, offset_t, off_t);
extern void		ufs_trans_mata_alloc(struct ufsvfs *, struct inode *,
				daddr_t, ulong_t, int);
extern int		ufs_trans_dir(struct inode *, off_t);
extern void		ufs_trans_quota(struct dquot *);
extern void		ufs_trans_dqrele(struct dquot *);
extern int		ufs_trans_itrunc(struct inode *, u_offset_t, int,
			    cred_t *);
extern int		ufs_trans_write(struct inode *, struct uio *, int,
			    cred_t *, int, long);
extern void		ufs_trans_write_resv(struct inode *, struct uio *,
				int *, int *);
extern int		ufs_trans_check(dev_t);
extern void		ufs_trans_redev(dev_t odev, dev_t ndev);
extern void		ufs_trans_trunc_resv(struct inode *, u_offset_t, int *,
				u_offset_t *);

/*
 * transaction prototypes
 */
void	lufs_unsnarf(struct ufsvfs *ufsvfsp);
int	lufs_snarf(struct ufsvfs *ufsvfsp, struct fs *fs, int ronly);
void	top_delta(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb, delta_t dtyp,
	    int (*func)(), ulong_t arg);
void	top_cancel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb, int flags);
int	top_iscancel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb);
void	top_seterror(struct ufsvfs *ufsvfsp);
int	top_iserror(struct ufsvfs *ufsvfsp);
void	top_begin_sync(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size,
	    int *error);
int	top_begin_async(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size,
	    int tryasync);
void	top_end_sync(struct ufsvfs *ufsvfsp, int *ep, top_t topid,
	    ulong_t size);
void	top_end_async(struct ufsvfs *ufsvfsp, top_t topid, ulong_t size);
void	top_log(struct ufsvfs *ufsvfsp, char *va, offset_t vamof, off_t nb,
	    caddr_t buf, uint32_t bufsz);
void	top_mataadd(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb);
void	top_matadel(struct ufsvfs *ufsvfsp, offset_t mof, off_t nb);
void	top_mataclr(struct ufsvfs *ufsvfsp);


#endif	/* defined(_KERNEL) */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_UFS_TRANS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
 * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
 * Copyright (c) 2014 Integros [integros.com]
 * Copyright 2020 Joyent, Inc.
 * Copyright (c) 2017 Datto Inc.
 * Copyright (c) 2017, Intel Corporation.
 */

/* Portions Copyright 2010 Robert Milkowski */

#ifndef	_SYS_FS_ZFS_H
#define	_SYS_FS_ZFS_H

#include <sys/time.h>
/*
 * In OpenZFS we include sys/zio_priority.h to get the enum value of
 * ZIO_PRIORITY_NUM_QUEUEABLE, which is used for the various array sizes in
 * the structure definitions below. However, in illumos zio_priority.h is not
 * readily available to the userland code where we have a very large number of
 * files including sys/zfs.h. Thus, we define ZIO_PRIORITY_N_QUEUEABLE here and
 * this should be kept in sync if ZIO_PRIORITY_NUM_QUEUEABLE changes.
 */
#define	ZIO_PRIORITY_N_QUEUEABLE	8

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Types and constants shared between userland and the kernel.
 */

/*
 * Each dataset can be one of the following types.  These constants can be
 * combined into masks that can be passed to various functions.
 */
typedef enum {
	ZFS_TYPE_FILESYSTEM	= (1 << 0),
	ZFS_TYPE_SNAPSHOT	= (1 << 1),
	ZFS_TYPE_VOLUME		= (1 << 2),
	ZFS_TYPE_POOL		= (1 << 3),
	ZFS_TYPE_BOOKMARK	= (1 << 4)
} zfs_type_t;

/*
 * NB: lzc_dataset_type should be updated whenever a new objset type is added,
 * if it represents a real type of a dataset that can be created from userland.
 */
typedef enum dmu_objset_type {
	DMU_OST_NONE,
	DMU_OST_META,
	DMU_OST_ZFS,
	DMU_OST_ZVOL,
	DMU_OST_OTHER,			/* For testing only! */
	DMU_OST_ANY,			/* Be careful! */
	DMU_OST_NUMTYPES
} dmu_objset_type_t;

#define	ZFS_TYPE_DATASET	\
	(ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME | ZFS_TYPE_SNAPSHOT)

/*
 * All of these include the terminating NUL byte.
 */
#define	ZAP_MAXNAMELEN 256
#define	ZAP_MAXVALUELEN (1024 * 8)
#define	ZAP_OLDMAXVALUELEN 1024
#define	ZFS_MAX_DATASET_NAME_LEN 256

/*
 * Dataset properties are identified by these constants and must be added to
 * the end of this list to ensure that external consumers are not affected
 * by the change. If you make any changes to this list, be sure to update
 * the property table in usr/src/common/zfs/zfs_prop.c.
 */
typedef enum {
	ZPROP_CONT = -2,
	ZPROP_INVAL = -1,
	ZFS_PROP_TYPE = 0,
	ZFS_PROP_CREATION,
	ZFS_PROP_USED,
	ZFS_PROP_AVAILABLE,
	ZFS_PROP_REFERENCED,
	ZFS_PROP_COMPRESSRATIO,
	ZFS_PROP_MOUNTED,
	ZFS_PROP_ORIGIN,
	ZFS_PROP_QUOTA,
	ZFS_PROP_RESERVATION,
	ZFS_PROP_VOLSIZE,
	ZFS_PROP_VOLBLOCKSIZE,
	ZFS_PROP_RECORDSIZE,
	ZFS_PROP_MOUNTPOINT,
	ZFS_PROP_SHARENFS,
	ZFS_PROP_CHECKSUM,
	ZFS_PROP_COMPRESSION,
	ZFS_PROP_ATIME,
	ZFS_PROP_DEVICES,
	ZFS_PROP_EXEC,
	ZFS_PROP_SETUID,
	ZFS_PROP_READONLY,
	ZFS_PROP_ZONED,
	ZFS_PROP_SNAPDIR,
	ZFS_PROP_ACLMODE,
	ZFS_PROP_ACLINHERIT,
	ZFS_PROP_ACLIMPLICIT,	/* ACL Implicit Owner Rights (RackTop) */
	ZFS_PROP_CREATETXG,
	ZFS_PROP_NAME,			/* not exposed to the user */
	ZFS_PROP_CANMOUNT,
	ZFS_PROP_ISCSIOPTIONS,		/* not exposed to the user */
	ZFS_PROP_XATTR,
	ZFS_PROP_NUMCLONES,		/* not exposed to the user */
	ZFS_PROP_COPIES,
	ZFS_PROP_VERSION,
	ZFS_PROP_UTF8ONLY,
	ZFS_PROP_NORMALIZE,
	ZFS_PROP_CASE,
	ZFS_PROP_VSCAN,
	ZFS_PROP_NBMAND,
	ZFS_PROP_SHARESMB,
	ZFS_PROP_REFQUOTA,
	ZFS_PROP_REFRESERVATION,
	ZFS_PROP_GUID,
	ZFS_PROP_PRIMARYCACHE,
	ZFS_PROP_SECONDARYCACHE,
	ZFS_PROP_USEDSNAP,
	ZFS_PROP_USEDDS,
	ZFS_PROP_USEDCHILD,
	ZFS_PROP_USEDREFRESERV,
	ZFS_PROP_USERACCOUNTING,	/* not exposed to the user */
	ZFS_PROP_STMF_SHAREINFO,	/* not exposed to the user */
	ZFS_PROP_DEFER_DESTROY,
	ZFS_PROP_USERREFS,
	ZFS_PROP_LOGBIAS,
	ZFS_PROP_UNIQUE,		/* not exposed to the user */
	ZFS_PROP_OBJSETID,		/* not exposed to the user */
	ZFS_PROP_DEDUP,
	ZFS_PROP_MLSLABEL,
	ZFS_PROP_SYNC,
	ZFS_PROP_DNODESIZE,
	ZFS_PROP_REFRATIO,
	ZFS_PROP_WRITTEN,
	ZFS_PROP_CLONES,
	ZFS_PROP_LOGICALUSED,
	ZFS_PROP_LOGICALREFERENCED,
	ZFS_PROP_INCONSISTENT,		/* not exposed to the user */
	ZFS_PROP_FILESYSTEM_LIMIT,
	ZFS_PROP_SNAPSHOT_LIMIT,
	ZFS_PROP_FILESYSTEM_COUNT,
	ZFS_PROP_SNAPSHOT_COUNT,
	ZFS_PROP_REDUNDANT_METADATA,
	ZFS_PROP_PREV_SNAP,
	ZFS_PROP_RECEIVE_RESUME_TOKEN,
	ZFS_PROP_REMAPTXG,		/* not exposed to the user */
	ZFS_PROP_SPECIAL_SMALL_BLOCKS,
	ZFS_PROP_ENCRYPTION,
	ZFS_PROP_KEYLOCATION,
	ZFS_PROP_KEYFORMAT,
	ZFS_PROP_PBKDF2_SALT,
	ZFS_PROP_PBKDF2_ITERS,
	ZFS_PROP_ENCRYPTION_ROOT,
	ZFS_PROP_KEY_GUID,
	ZFS_PROP_KEYSTATUS,
	ZFS_PROP_IVSET_GUID,		/* not exposed to the user */
	ZFS_NUM_PROPS
} zfs_prop_t;

typedef enum {
	ZFS_PROP_USERUSED,
	ZFS_PROP_USERQUOTA,
	ZFS_PROP_GROUPUSED,
	ZFS_PROP_GROUPQUOTA,
	ZFS_PROP_USEROBJUSED,
	ZFS_PROP_USEROBJQUOTA,
	ZFS_PROP_GROUPOBJUSED,
	ZFS_PROP_GROUPOBJQUOTA,
	ZFS_PROP_PROJECTUSED,
	ZFS_PROP_PROJECTQUOTA,
	ZFS_PROP_PROJECTOBJUSED,
	ZFS_PROP_PROJECTOBJQUOTA,
	ZFS_NUM_USERQUOTA_PROPS
} zfs_userquota_prop_t;

extern const char *zfs_userquota_prop_prefixes[ZFS_NUM_USERQUOTA_PROPS];

/*
 * Pool properties are identified by these constants and must be added to the
 * end of this list to ensure that external consumers are not affected
 * by the change. If you make any changes to this list, be sure to update
 * the property table in usr/src/common/zfs/zpool_prop.c.
 */
typedef enum {
	ZPOOL_PROP_INVAL = -1,
	ZPOOL_PROP_NAME,
	ZPOOL_PROP_SIZE,
	ZPOOL_PROP_CAPACITY,
	ZPOOL_PROP_ALTROOT,
	ZPOOL_PROP_HEALTH,
	ZPOOL_PROP_GUID,
	ZPOOL_PROP_VERSION,
	ZPOOL_PROP_BOOTFS,
	ZPOOL_PROP_DELEGATION,
	ZPOOL_PROP_AUTOREPLACE,
	ZPOOL_PROP_CACHEFILE,
	ZPOOL_PROP_FAILUREMODE,
	ZPOOL_PROP_LISTSNAPS,
	ZPOOL_PROP_AUTOEXPAND,
	ZPOOL_PROP_DEDUPDITTO,
	ZPOOL_PROP_DEDUPRATIO,
	ZPOOL_PROP_FREE,
	ZPOOL_PROP_ALLOCATED,
	ZPOOL_PROP_READONLY,
	ZPOOL_PROP_COMMENT,
	ZPOOL_PROP_EXPANDSZ,
	ZPOOL_PROP_FREEING,
	ZPOOL_PROP_FRAGMENTATION,
	ZPOOL_PROP_LEAKED,
	ZPOOL_PROP_MAXBLOCKSIZE,
	ZPOOL_PROP_BOOTSIZE,
	ZPOOL_PROP_CHECKPOINT,
	ZPOOL_PROP_TNAME,
	ZPOOL_PROP_MAXDNODESIZE,
	ZPOOL_PROP_MULTIHOST,
	ZPOOL_PROP_ASHIFT,
	ZPOOL_PROP_AUTOTRIM,
	ZPOOL_NUM_PROPS
} zpool_prop_t;

/* Small enough to not hog a whole line of printout in zpool(8). */
#define	ZPROP_MAX_COMMENT	32

#define	ZPROP_VALUE		"value"
#define	ZPROP_SOURCE		"source"

typedef enum {
	ZPROP_SRC_NONE = 0x1,
	ZPROP_SRC_DEFAULT = 0x2,
	ZPROP_SRC_TEMPORARY = 0x4,
	ZPROP_SRC_LOCAL = 0x8,
	ZPROP_SRC_INHERITED = 0x10,
	ZPROP_SRC_RECEIVED = 0x20
} zprop_source_t;

#define	ZPROP_SRC_ALL	0x3f

#define	ZPROP_SOURCE_VAL_RECVD	"$recvd"
#define	ZPROP_N_MORE_ERRORS	"N_MORE_ERRORS"
/*
 * Dataset flag implemented as a special entry in the props zap object
 * indicating that the dataset has received properties on or after
 * SPA_VERSION_RECVD_PROPS. The first such receive blows away local properties
 * just as it did in earlier versions, and thereafter, local properties are
 * preserved.
 */
#define	ZPROP_HAS_RECVD		"$hasrecvd"

typedef enum {
	ZPROP_ERR_NOCLEAR = 0x1, /* failure to clear existing props */
	ZPROP_ERR_NORESTORE = 0x2 /* failure to restore props on error */
} zprop_errflags_t;

typedef int (*zprop_func)(int, void *);

/*
 * Properties to be set on the root file system of a new pool
 * are stuffed into their own nvlist, which is then included in
 * the properties nvlist with the pool properties.
 */
#define	ZPOOL_ROOTFS_PROPS	"root-props-nvl"

/*
 * Length of 'written@' and 'written#'
 */
#define	ZFS_WRITTEN_PROP_PREFIX_LEN	8

/*
 * Dataset property functions shared between libzfs and kernel.
 */
const char *zfs_prop_default_string(zfs_prop_t);
uint64_t zfs_prop_default_numeric(zfs_prop_t);
boolean_t zfs_prop_readonly(zfs_prop_t);
boolean_t zfs_prop_visible(zfs_prop_t prop);
boolean_t zfs_prop_inheritable(zfs_prop_t);
boolean_t zfs_prop_setonce(zfs_prop_t);
boolean_t zfs_prop_encryption_key_param(zfs_prop_t);
boolean_t zfs_prop_valid_keylocation(const char *, boolean_t);
const char *zfs_prop_to_name(zfs_prop_t);
zfs_prop_t zfs_name_to_prop(const char *);
boolean_t zfs_prop_user(const char *);
boolean_t zfs_prop_userquota(const char *);
boolean_t zfs_prop_written(const char *);
int zfs_prop_index_to_string(zfs_prop_t, uint64_t, const char **);
int zfs_prop_string_to_index(zfs_prop_t, const char *, uint64_t *);
uint64_t zfs_prop_random_value(zfs_prop_t, uint64_t seed);
boolean_t zfs_prop_valid_for_type(int, zfs_type_t, boolean_t);

/*
 * Pool property functions shared between libzfs and kernel.
 */
zpool_prop_t zpool_name_to_prop(const char *);
const char *zpool_prop_to_name(zpool_prop_t);
const char *zpool_prop_default_string(zpool_prop_t);
uint64_t zpool_prop_default_numeric(zpool_prop_t);
boolean_t zpool_prop_readonly(zpool_prop_t);
boolean_t zpool_prop_feature(const char *);
boolean_t zpool_prop_unsupported(const char *name);
int zpool_prop_index_to_string(zpool_prop_t, uint64_t, const char **);
int zpool_prop_string_to_index(zpool_prop_t, const char *, uint64_t *);
uint64_t zpool_prop_random_value(zpool_prop_t, uint64_t seed);

/*
 * Definitions for the Delegation.
 */
typedef enum {
	ZFS_DELEG_WHO_UNKNOWN = 0,
	ZFS_DELEG_USER = 'u',
	ZFS_DELEG_USER_SETS = 'U',
	ZFS_DELEG_GROUP = 'g',
	ZFS_DELEG_GROUP_SETS = 'G',
	ZFS_DELEG_EVERYONE = 'e',
	ZFS_DELEG_EVERYONE_SETS = 'E',
	ZFS_DELEG_CREATE = 'c',
	ZFS_DELEG_CREATE_SETS = 'C',
	ZFS_DELEG_NAMED_SET = 's',
	ZFS_DELEG_NAMED_SET_SETS = 'S'
} zfs_deleg_who_type_t;

typedef enum {
	ZFS_DELEG_NONE = 0,
	ZFS_DELEG_PERM_LOCAL = 1,
	ZFS_DELEG_PERM_DESCENDENT = 2,
	ZFS_DELEG_PERM_LOCALDESCENDENT = 3,
	ZFS_DELEG_PERM_CREATE = 4
} zfs_deleg_inherit_t;

#define	ZFS_DELEG_PERM_UID	"uid"
#define	ZFS_DELEG_PERM_GID	"gid"
#define	ZFS_DELEG_PERM_GROUPS	"groups"

#define	ZFS_MLSLABEL_DEFAULT	"none"

#define	ZFS_SMB_ACL_SRC		"src"
#define	ZFS_SMB_ACL_TARGET	"target"

typedef enum {
	ZFS_CANMOUNT_OFF = 0,
	ZFS_CANMOUNT_ON = 1,
	ZFS_CANMOUNT_NOAUTO = 2
} zfs_canmount_type_t;

typedef enum {
	ZFS_LOGBIAS_LATENCY = 0,
	ZFS_LOGBIAS_THROUGHPUT = 1
} zfs_logbias_op_t;

typedef enum zfs_share_op {
	ZFS_SHARE_NFS = 0,
	ZFS_UNSHARE_NFS = 1,
	ZFS_SHARE_SMB = 2,
	ZFS_UNSHARE_SMB = 3
} zfs_share_op_t;

typedef enum zfs_smb_acl_op {
	ZFS_SMB_ACL_ADD,
	ZFS_SMB_ACL_REMOVE,
	ZFS_SMB_ACL_RENAME,
	ZFS_SMB_ACL_PURGE
} zfs_smb_acl_op_t;

typedef enum zfs_cache_type {
	ZFS_CACHE_NONE = 0,
	ZFS_CACHE_METADATA = 1,
	ZFS_CACHE_ALL = 2
} zfs_cache_type_t;

typedef enum {
	ZFS_SYNC_STANDARD = 0,
	ZFS_SYNC_ALWAYS = 1,
	ZFS_SYNC_DISABLED = 2
} zfs_sync_type_t;

typedef enum {
	ZFS_DNSIZE_LEGACY = 0,
	ZFS_DNSIZE_AUTO = 1,
	ZFS_DNSIZE_1K = 1024,
	ZFS_DNSIZE_2K = 2048,
	ZFS_DNSIZE_4K = 4096,
	ZFS_DNSIZE_8K = 8192,
	ZFS_DNSIZE_16K = 16384
} zfs_dnsize_type_t;

typedef enum {
	ZFS_REDUNDANT_METADATA_ALL,
	ZFS_REDUNDANT_METADATA_MOST
} zfs_redundant_metadata_type_t;

typedef enum zfs_keystatus {
	ZFS_KEYSTATUS_NONE = 0,
	ZFS_KEYSTATUS_UNAVAILABLE,
	ZFS_KEYSTATUS_AVAILABLE
} zfs_keystatus_t;

typedef enum zfs_keyformat {
	ZFS_KEYFORMAT_NONE = 0,
	ZFS_KEYFORMAT_RAW,
	ZFS_KEYFORMAT_HEX,
	ZFS_KEYFORMAT_PASSPHRASE,
	ZFS_KEYFORMAT_FORMATS
} zfs_keyformat_t;

typedef enum zfs_key_location {
	ZFS_KEYLOCATION_NONE = 0,
	ZFS_KEYLOCATION_PROMPT,
	ZFS_KEYLOCATION_URI,
	ZFS_KEYLOCATION_LOCATIONS
} zfs_keylocation_t;

#define	DEFAULT_PBKDF2_ITERATIONS 350000
#define	MIN_PBKDF2_ITERATIONS 100000

/*
 * On-disk version number.
 */
#define	SPA_VERSION_1			1ULL
#define	SPA_VERSION_2			2ULL
#define	SPA_VERSION_3			3ULL
#define	SPA_VERSION_4			4ULL
#define	SPA_VERSION_5			5ULL
#define	SPA_VERSION_6			6ULL
#define	SPA_VERSION_7			7ULL
#define	SPA_VERSION_8			8ULL
#define	SPA_VERSION_9			9ULL
#define	SPA_VERSION_10			10ULL
#define	SPA_VERSION_11			11ULL
#define	SPA_VERSION_12			12ULL
#define	SPA_VERSION_13			13ULL
#define	SPA_VERSION_14			14ULL
#define	SPA_VERSION_15			15ULL
#define	SPA_VERSION_16			16ULL
#define	SPA_VERSION_17			17ULL
#define	SPA_VERSION_18			18ULL
#define	SPA_VERSION_19			19ULL
#define	SPA_VERSION_20			20ULL
#define	SPA_VERSION_21			21ULL
#define	SPA_VERSION_22			22ULL
#define	SPA_VERSION_23			23ULL
#define	SPA_VERSION_24			24ULL
#define	SPA_VERSION_25			25ULL
#define	SPA_VERSION_26			26ULL
#define	SPA_VERSION_27			27ULL
#define	SPA_VERSION_28			28ULL
#define	SPA_VERSION_5000		5000ULL

/*
 * When bumping up SPA_VERSION, make sure GRUB ZFS understands the on-disk
 * format change. Go to usr/src/grub/grub-0.97/stage2/{zfs-include/, fsys_zfs*},
 * and do the appropriate changes.  Also bump the version number in
 * usr/src/grub/capability.
 */
#define	SPA_VERSION			SPA_VERSION_5000
#define	SPA_VERSION_STRING		"5000"

/*
 * Symbolic names for the changes that caused a SPA_VERSION switch.
 * Used in the code when checking for presence or absence of a feature.
 * Feel free to define multiple symbolic names for each version if there
 * were multiple changes to on-disk structures during that version.
 *
 * NOTE: When checking the current SPA_VERSION in your code, be sure
 *       to use spa_version() since it reports the version of the
 *       last synced uberblock.  Checking the in-flight version can
 *       be dangerous in some cases.
 */
#define	SPA_VERSION_INITIAL		SPA_VERSION_1
#define	SPA_VERSION_DITTO_BLOCKS	SPA_VERSION_2
#define	SPA_VERSION_SPARES		SPA_VERSION_3
#define	SPA_VERSION_RAIDZ2		SPA_VERSION_3
#define	SPA_VERSION_BPOBJ_ACCOUNT	SPA_VERSION_3
#define	SPA_VERSION_RAIDZ_DEFLATE	SPA_VERSION_3
#define	SPA_VERSION_DNODE_BYTES		SPA_VERSION_3
#define	SPA_VERSION_ZPOOL_HISTORY	SPA_VERSION_4
#define	SPA_VERSION_GZIP_COMPRESSION	SPA_VERSION_5
#define	SPA_VERSION_BOOTFS		SPA_VERSION_6
#define	SPA_VERSION_SLOGS		SPA_VERSION_7
#define	SPA_VERSION_DELEGATED_PERMS	SPA_VERSION_8
#define	SPA_VERSION_FUID		SPA_VERSION_9
#define	SPA_VERSION_REFRESERVATION	SPA_VERSION_9
#define	SPA_VERSION_REFQUOTA		SPA_VERSION_9
#define	SPA_VERSION_UNIQUE_ACCURATE	SPA_VERSION_9
#define	SPA_VERSION_L2CACHE		SPA_VERSION_10
#define	SPA_VERSION_NEXT_CLONES		SPA_VERSION_11
#define	SPA_VERSION_ORIGIN		SPA_VERSION_11
#define	SPA_VERSION_DSL_SCRUB		SPA_VERSION_11
#define	SPA_VERSION_SNAP_PROPS		SPA_VERSION_12
#define	SPA_VERSION_USED_BREAKDOWN	SPA_VERSION_13
#define	SPA_VERSION_PASSTHROUGH_X	SPA_VERSION_14
#define	SPA_VERSION_USERSPACE		SPA_VERSION_15
#define	SPA_VERSION_STMF_PROP		SPA_VERSION_16
#define	SPA_VERSION_RAIDZ3		SPA_VERSION_17
#define	SPA_VERSION_USERREFS		SPA_VERSION_18
#define	SPA_VERSION_HOLES		SPA_VERSION_19
#define	SPA_VERSION_ZLE_COMPRESSION	SPA_VERSION_20
#define	SPA_VERSION_DEDUP		SPA_VERSION_21
#define	SPA_VERSION_RECVD_PROPS		SPA_VERSION_22
#define	SPA_VERSION_SLIM_ZIL		SPA_VERSION_23
#define	SPA_VERSION_SA			SPA_VERSION_24
#define	SPA_VERSION_SCAN		SPA_VERSION_25
#define	SPA_VERSION_DIR_CLONES		SPA_VERSION_26
#define	SPA_VERSION_DEADLISTS		SPA_VERSION_26
#define	SPA_VERSION_FAST_SNAP		SPA_VERSION_27
#define	SPA_VERSION_MULTI_REPLACE	SPA_VERSION_28
#define	SPA_VERSION_BEFORE_FEATURES	SPA_VERSION_28
#define	SPA_VERSION_FEATURES		SPA_VERSION_5000

#define	SPA_VERSION_IS_SUPPORTED(v) \
	(((v) >= SPA_VERSION_INITIAL && (v) <= SPA_VERSION_BEFORE_FEATURES) || \
	((v) >= SPA_VERSION_FEATURES && (v) <= SPA_VERSION))

/*
 * ZPL version - rev'd whenever an incompatible on-disk format change
 * occurs.  This is independent of SPA/DMU/ZAP versioning.  You must
 * also update the version_table[] and help message in zfs_prop.c.
 *
 * When changing, be sure to teach GRUB how to read the new format!
 * See usr/src/grub/grub-0.97/stage2/{zfs-include/,fsys_zfs*}
 */
#define	ZPL_VERSION_1			1ULL
#define	ZPL_VERSION_2			2ULL
#define	ZPL_VERSION_3			3ULL
#define	ZPL_VERSION_4			4ULL
#define	ZPL_VERSION_5			5ULL
#define	ZPL_VERSION			ZPL_VERSION_5
#define	ZPL_VERSION_STRING		"5"

#define	ZPL_VERSION_INITIAL		ZPL_VERSION_1
#define	ZPL_VERSION_DIRENT_TYPE		ZPL_VERSION_2
#define	ZPL_VERSION_FUID		ZPL_VERSION_3
#define	ZPL_VERSION_NORMALIZATION	ZPL_VERSION_3
#define	ZPL_VERSION_SYSATTR		ZPL_VERSION_3
#define	ZPL_VERSION_USERSPACE		ZPL_VERSION_4
#define	ZPL_VERSION_SA			ZPL_VERSION_5

/* Persistent L2ARC version */
#define	L2ARC_PERSISTENT_VERSION_1	1ULL
#define	L2ARC_PERSISTENT_VERSION	L2ARC_PERSISTENT_VERSION_1
#define	L2ARC_PERSISTENT_VERSION_STRING	"1"

/* Rewind policy information */
#define	ZPOOL_NO_REWIND		1  /* No policy - default behavior */
#define	ZPOOL_NEVER_REWIND	2  /* Do not search for best txg or rewind */
#define	ZPOOL_TRY_REWIND	4  /* Search for best txg, but do not rewind */
#define	ZPOOL_DO_REWIND		8  /* Rewind to best txg w/in deferred frees */
#define	ZPOOL_EXTREME_REWIND	16 /* Allow extreme measures to find best txg */
#define	ZPOOL_REWIND_MASK	28 /* All the possible rewind bits */
#define	ZPOOL_REWIND_POLICIES	31 /* All the possible policy bits */

typedef struct zpool_load_policy {
	uint32_t	zlp_rewind;	/* rewind policy requested */
	uint64_t	zlp_maxmeta;	/* max acceptable meta-data errors */
	uint64_t	zlp_maxdata;	/* max acceptable data errors */
	uint64_t	zlp_txg;	/* specific txg to load */
} zpool_load_policy_t;

/*
 * The following are configuration names used in the nvlist describing a pool's
 * configuration.  New on-disk names should be prefixed with "<reverse-DNS>:"
 * (e.g. "org.open-zfs:") to avoid conflicting names being developed
 * independently.
 */
#define	ZPOOL_CONFIG_VERSION		"version"
#define	ZPOOL_CONFIG_POOL_NAME		"name"
#define	ZPOOL_CONFIG_POOL_STATE		"state"
#define	ZPOOL_CONFIG_POOL_TXG		"txg"
#define	ZPOOL_CONFIG_POOL_GUID		"pool_guid"
#define	ZPOOL_CONFIG_CREATE_TXG		"create_txg"
#define	ZPOOL_CONFIG_TOP_GUID		"top_guid"
#define	ZPOOL_CONFIG_VDEV_TREE		"vdev_tree"
#define	ZPOOL_CONFIG_TYPE		"type"
#define	ZPOOL_CONFIG_CHILDREN		"children"
#define	ZPOOL_CONFIG_ID			"id"
#define	ZPOOL_CONFIG_GUID		"guid"
#define	ZPOOL_CONFIG_INDIRECT_OBJECT	"com.delphix:indirect_object"
#define	ZPOOL_CONFIG_INDIRECT_BIRTHS	"com.delphix:indirect_births"
#define	ZPOOL_CONFIG_PREV_INDIRECT_VDEV	"com.delphix:prev_indirect_vdev"
#define	ZPOOL_CONFIG_PATH		"path"
#define	ZPOOL_CONFIG_DEVID		"devid"
#define	ZPOOL_CONFIG_METASLAB_ARRAY	"metaslab_array"
#define	ZPOOL_CONFIG_METASLAB_SHIFT	"metaslab_shift"
#define	ZPOOL_CONFIG_ASHIFT		"ashift"
#define	ZPOOL_CONFIG_ASIZE		"asize"
#define	ZPOOL_CONFIG_DTL		"DTL"
#define	ZPOOL_CONFIG_SCAN_STATS		"scan_stats"	/* not stored on disk */
#define	ZPOOL_CONFIG_REMOVAL_STATS	"removal_stats"	/* not stored on disk */
#define	ZPOOL_CONFIG_CHECKPOINT_STATS	"checkpoint_stats" /* not on disk */
#define	ZPOOL_CONFIG_VDEV_STATS		"vdev_stats"	/* not stored on disk */
#define	ZPOOL_CONFIG_INDIRECT_SIZE	"indirect_size"	/* not stored on disk */

/* container nvlist of extended stats */
#define	ZPOOL_CONFIG_VDEV_STATS_EX	"vdev_stats_ex"

/* Active queue read/write stats */
#define	ZPOOL_CONFIG_VDEV_SYNC_R_ACTIVE_QUEUE	"vdev_sync_r_active_queue"
#define	ZPOOL_CONFIG_VDEV_SYNC_W_ACTIVE_QUEUE	"vdev_sync_w_active_queue"
#define	ZPOOL_CONFIG_VDEV_ASYNC_R_ACTIVE_QUEUE	"vdev_async_r_active_queue"
#define	ZPOOL_CONFIG_VDEV_ASYNC_W_ACTIVE_QUEUE	"vdev_async_w_active_queue"
#define	ZPOOL_CONFIG_VDEV_SCRUB_ACTIVE_QUEUE	"vdev_async_scrub_active_queue"
#define	ZPOOL_CONFIG_VDEV_TRIM_ACTIVE_QUEUE	"vdev_async_trim_active_queue"

/* Queue sizes */
#define	ZPOOL_CONFIG_VDEV_SYNC_R_PEND_QUEUE	"vdev_sync_r_pend_queue"
#define	ZPOOL_CONFIG_VDEV_SYNC_W_PEND_QUEUE	"vdev_sync_w_pend_queue"
#define	ZPOOL_CONFIG_VDEV_ASYNC_R_PEND_QUEUE	"vdev_async_r_pend_queue"
#define	ZPOOL_CONFIG_VDEV_ASYNC_W_PEND_QUEUE	"vdev_async_w_pend_queue"
#define	ZPOOL_CONFIG_VDEV_SCRUB_PEND_QUEUE	"vdev_async_scrub_pend_queue"
#define	ZPOOL_CONFIG_VDEV_TRIM_PEND_QUEUE	"vdev_async_trim_pend_queue"

/* Latency read/write histogram stats */
#define	ZPOOL_CONFIG_VDEV_TOT_R_LAT_HISTO	"vdev_tot_r_lat_histo"
#define	ZPOOL_CONFIG_VDEV_TOT_W_LAT_HISTO	"vdev_tot_w_lat_histo"
#define	ZPOOL_CONFIG_VDEV_DISK_R_LAT_HISTO	"vdev_disk_r_lat_histo"
#define	ZPOOL_CONFIG_VDEV_DISK_W_LAT_HISTO	"vdev_disk_w_lat_histo"
#define	ZPOOL_CONFIG_VDEV_SYNC_R_LAT_HISTO	"vdev_sync_r_lat_histo"
#define	ZPOOL_CONFIG_VDEV_SYNC_W_LAT_HISTO	"vdev_sync_w_lat_histo"
#define	ZPOOL_CONFIG_VDEV_ASYNC_R_LAT_HISTO	"vdev_async_r_lat_histo"
#define	ZPOOL_CONFIG_VDEV_ASYNC_W_LAT_HISTO	"vdev_async_w_lat_histo"
#define	ZPOOL_CONFIG_VDEV_SCRUB_LAT_HISTO	"vdev_scrub_histo"
#define	ZPOOL_CONFIG_VDEV_TRIM_LAT_HISTO	"vdev_trim_histo"

/* Request size histograms */
#define	ZPOOL_CONFIG_VDEV_SYNC_IND_R_HISTO	"vdev_sync_ind_r_histo"
#define	ZPOOL_CONFIG_VDEV_SYNC_IND_W_HISTO	"vdev_sync_ind_w_histo"
#define	ZPOOL_CONFIG_VDEV_ASYNC_IND_R_HISTO	"vdev_async_ind_r_histo"
#define	ZPOOL_CONFIG_VDEV_ASYNC_IND_W_HISTO	"vdev_async_ind_w_histo"
#define	ZPOOL_CONFIG_VDEV_IND_SCRUB_HISTO	"vdev_ind_scrub_histo"
#define	ZPOOL_CONFIG_VDEV_IND_TRIM_HISTO	"vdev_ind_trim_histo"
#define	ZPOOL_CONFIG_VDEV_SYNC_AGG_R_HISTO	"vdev_sync_agg_r_histo"
#define	ZPOOL_CONFIG_VDEV_SYNC_AGG_W_HISTO	"vdev_sync_agg_w_histo"
#define	ZPOOL_CONFIG_VDEV_ASYNC_AGG_R_HISTO	"vdev_async_agg_r_histo"
#define	ZPOOL_CONFIG_VDEV_ASYNC_AGG_W_HISTO	"vdev_async_agg_w_histo"
#define	ZPOOL_CONFIG_VDEV_AGG_SCRUB_HISTO	"vdev_agg_scrub_histo"
#define	ZPOOL_CONFIG_VDEV_AGG_TRIM_HISTO	"vdev_agg_trim_histo"

/* Number of slow IOs */
#define	ZPOOL_CONFIG_VDEV_SLOW_IOS		"vdev_slow_ios"

#define	ZPOOL_CONFIG_WHOLE_DISK		"whole_disk"
#define	ZPOOL_CONFIG_ERRCOUNT		"error_count"
#define	ZPOOL_CONFIG_NOT_PRESENT	"not_present"
#define	ZPOOL_CONFIG_SPARES		"spares"
#define	ZPOOL_CONFIG_IS_SPARE		"is_spare"
#define	ZPOOL_CONFIG_NPARITY		"nparity"
#define	ZPOOL_CONFIG_HOSTID		"hostid"
#define	ZPOOL_CONFIG_HOSTNAME		"hostname"
#define	ZPOOL_CONFIG_LOADED_TIME	"initial_load_time"
#define	ZPOOL_CONFIG_UNSPARE		"unspare"
#define	ZPOOL_CONFIG_PHYS_PATH		"phys_path"
#define	ZPOOL_CONFIG_IS_LOG		"is_log"
#define	ZPOOL_CONFIG_L2CACHE		"l2cache"
#define	ZPOOL_CONFIG_HOLE_ARRAY		"hole_array"
#define	ZPOOL_CONFIG_VDEV_CHILDREN	"vdev_children"
#define	ZPOOL_CONFIG_IS_HOLE		"is_hole"
#define	ZPOOL_CONFIG_DDT_HISTOGRAM	"ddt_histogram"
#define	ZPOOL_CONFIG_DDT_OBJ_STATS	"ddt_object_stats"
#define	ZPOOL_CONFIG_DDT_STATS		"ddt_stats"
#define	ZPOOL_CONFIG_SPLIT		"splitcfg"
#define	ZPOOL_CONFIG_ORIG_GUID		"orig_guid"
#define	ZPOOL_CONFIG_SPLIT_GUID		"split_guid"
#define	ZPOOL_CONFIG_SPLIT_LIST		"guid_list"
#define	ZPOOL_CONFIG_REMOVING		"removing"
#define	ZPOOL_CONFIG_RESILVER_TXG	"resilver_txg"
#define	ZPOOL_CONFIG_COMMENT		"comment"
#define	ZPOOL_CONFIG_SUSPENDED		"suspended"	/* not stored on disk */
#define	ZPOOL_CONFIG_SUSPENDED_REASON	"suspended_reason"	/* not stored */
#define	ZPOOL_CONFIG_TIMESTAMP		"timestamp"	/* not stored on disk */
#define	ZPOOL_CONFIG_BOOTFS		"bootfs"	/* not stored on disk */
#define	ZPOOL_CONFIG_MISSING_DEVICES	"missing_vdevs"	/* not stored on disk */
#define	ZPOOL_CONFIG_LOAD_INFO		"load_info"	/* not stored on disk */
#define	ZPOOL_CONFIG_REWIND_INFO	"rewind_info"	/* not stored on disk */
#define	ZPOOL_CONFIG_UNSUP_FEAT		"unsup_feat"	/* not stored on disk */
#define	ZPOOL_CONFIG_ENABLED_FEAT	"enabled_feat"	/* not stored on disk */
#define	ZPOOL_CONFIG_CAN_RDONLY		"can_rdonly"	/* not stored on disk */
#define	ZPOOL_CONFIG_FEATURES_FOR_READ	"features_for_read"
#define	ZPOOL_CONFIG_FEATURE_STATS	"feature_stats"	/* not stored on disk */
#define	ZPOOL_CONFIG_ERRATA		"errata"	/* not stored on disk */
#define	ZPOOL_CONFIG_VDEV_TOP_ZAP	"com.delphix:vdev_zap_top"
#define	ZPOOL_CONFIG_VDEV_LEAF_ZAP	"com.delphix:vdev_zap_leaf"
#define	ZPOOL_CONFIG_HAS_PER_VDEV_ZAPS	"com.delphix:has_per_vdev_zaps"
#define	ZPOOL_CONFIG_RESILVER_DEFER	"com.datto:resilver_defer"
#define	ZPOOL_CONFIG_CACHEFILE		"cachefile"	/* not stored on disk */
#define	ZPOOL_CONFIG_MMP_STATE		"mmp_state"	/* not stored on disk */
#define	ZPOOL_CONFIG_MMP_TXG		"mmp_txg"	/* not stored on disk */
#define	ZPOOL_CONFIG_MMP_SEQ		"mmp_seq"	/* not stored on disk */
#define	ZPOOL_CONFIG_MMP_HOSTNAME	"mmp_hostname"	/* not stored on disk */
#define	ZPOOL_CONFIG_MMP_HOSTID		"mmp_hostid"	/* not stored on disk */
#define	ZPOOL_CONFIG_ALLOCATION_BIAS	"alloc_bias"	/* not stored on disk */

/*
 * The persistent vdev state is stored as separate values rather than a single
 * 'vdev_state' entry.  This is because a device can be in multiple states, such
 * as offline and degraded.
 */
#define	ZPOOL_CONFIG_OFFLINE		"offline"
#define	ZPOOL_CONFIG_FAULTED		"faulted"
#define	ZPOOL_CONFIG_DEGRADED		"degraded"
#define	ZPOOL_CONFIG_REMOVED		"removed"
#define	ZPOOL_CONFIG_FRU		"fru"
#define	ZPOOL_CONFIG_AUX_STATE		"aux_state"

/* Pool load policy parameters */
#define	ZPOOL_LOAD_POLICY		"load-policy"
#define	ZPOOL_LOAD_REWIND_POLICY	"load-rewind-policy"
#define	ZPOOL_LOAD_REQUEST_TXG		"load-request-txg"
#define	ZPOOL_LOAD_META_THRESH		"load-meta-thresh"
#define	ZPOOL_LOAD_DATA_THRESH		"load-data-thresh"

/* Rewind data discovered */
#define	ZPOOL_CONFIG_LOAD_TIME		"rewind_txg_ts"
#define	ZPOOL_CONFIG_LOAD_DATA_ERRORS	"verify_data_errors"
#define	ZPOOL_CONFIG_REWIND_TIME	"seconds_of_rewind"

#define	VDEV_TYPE_ROOT			"root"
#define	VDEV_TYPE_MIRROR		"mirror"
#define	VDEV_TYPE_REPLACING		"replacing"
#define	VDEV_TYPE_RAIDZ			"raidz"
#define	VDEV_TYPE_DISK			"disk"
#define	VDEV_TYPE_FILE			"file"
#define	VDEV_TYPE_MISSING		"missing"
#define	VDEV_TYPE_HOLE			"hole"
#define	VDEV_TYPE_SPARE			"spare"
#define	VDEV_TYPE_LOG			"log"
#define	VDEV_TYPE_L2CACHE		"l2cache"
#define	VDEV_TYPE_INDIRECT		"indirect"

/* VDEV_TOP_ZAP_* are used in top-level vdev ZAP objects. */
#define	VDEV_TOP_ZAP_INDIRECT_OBSOLETE_SM \
	"com.delphix:indirect_obsolete_sm"
#define	VDEV_TOP_ZAP_OBSOLETE_COUNTS_ARE_PRECISE \
	"com.delphix:obsolete_counts_are_precise"
#define	VDEV_TOP_ZAP_POOL_CHECKPOINT_SM \
	"com.delphix:pool_checkpoint_sm"
#define	VDEV_TOP_ZAP_MS_UNFLUSHED_PHYS_TXGS \
	"com.delphix:ms_unflushed_phys_txgs"

#define	VDEV_TOP_ZAP_ALLOCATION_BIAS \
	"org.zfsonlinux:allocation_bias"

/* vdev metaslab allocation bias */
#define	VDEV_ALLOC_BIAS_LOG		"log"
#define	VDEV_ALLOC_BIAS_SPECIAL		"special"
#define	VDEV_ALLOC_BIAS_DEDUP		"dedup"

/* vdev initialize state */
#define	VDEV_LEAF_ZAP_INITIALIZE_LAST_OFFSET	\
	"com.delphix:next_offset_to_initialize"
#define	VDEV_LEAF_ZAP_INITIALIZE_STATE	\
	"com.delphix:vdev_initialize_state"
#define	VDEV_LEAF_ZAP_INITIALIZE_ACTION_TIME	\
	"com.delphix:vdev_initialize_action_time"

/* vdev TRIM state */
#define	VDEV_LEAF_ZAP_TRIM_LAST_OFFSET	\
	"org.zfsonlinux:next_offset_to_trim"
#define	VDEV_LEAF_ZAP_TRIM_STATE	\
	"org.zfsonlinux:vdev_trim_state"
#define	VDEV_LEAF_ZAP_TRIM_ACTION_TIME	\
	"org.zfsonlinux:vdev_trim_action_time"
#define	VDEV_LEAF_ZAP_TRIM_RATE		\
	"org.zfsonlinux:vdev_trim_rate"
#define	VDEV_LEAF_ZAP_TRIM_PARTIAL	\
	"org.zfsonlinux:vdev_trim_partial"
#define	VDEV_LEAF_ZAP_TRIM_SECURE	\
	"org.zfsonlinux:vdev_trim_secure"

/*
 * This is needed in userland to report the minimum necessary device size.
 *
 * Note that the zfs test suite uses 64MB vdevs.
 */
#define	SPA_MINDEVSIZE		(64ULL << 20)

/*
 * Set if the fragmentation has not yet been calculated. This can happen
 * because the space maps have not been upgraded or the histogram feature
 * is not enabled.
 */
#define	ZFS_FRAG_INVALID	UINT64_MAX

/*
 * The location of the pool configuration repository, shared between kernel and
 * userland.
 */
#define	ZPOOL_CACHE		"/etc/zfs/zpool.cache"

/*
 * vdev states are ordered from least to most healthy.
 * A vdev that's CANT_OPEN or below is considered unusable.
 */
typedef enum vdev_state {
	VDEV_STATE_UNKNOWN = 0,	/* Uninitialized vdev			*/
	VDEV_STATE_CLOSED,	/* Not currently open			*/
	VDEV_STATE_OFFLINE,	/* Not allowed to open			*/
	VDEV_STATE_REMOVED,	/* Explicitly removed from system	*/
	VDEV_STATE_CANT_OPEN,	/* Tried to open, but failed		*/
	VDEV_STATE_FAULTED,	/* External request to fault device	*/
	VDEV_STATE_DEGRADED,	/* Replicated vdev with unhealthy kids	*/
	VDEV_STATE_HEALTHY	/* Presumed good			*/
} vdev_state_t;

#define	VDEV_STATE_ONLINE	VDEV_STATE_HEALTHY

/*
 * vdev aux states.  When a vdev is in the CANT_OPEN state, the aux field
 * of the vdev stats structure uses these constants to distinguish why.
 */
typedef enum vdev_aux {
	VDEV_AUX_NONE,		/* no error				*/
	VDEV_AUX_OPEN_FAILED,	/* ldi_open_*() or vn_open() failed	*/
	VDEV_AUX_CORRUPT_DATA,	/* bad label or disk contents		*/
	VDEV_AUX_NO_REPLICAS,	/* insufficient number of replicas	*/
	VDEV_AUX_BAD_GUID_SUM,	/* vdev guid sum doesn't match		*/
	VDEV_AUX_TOO_SMALL,	/* vdev size is too small		*/
	VDEV_AUX_BAD_LABEL,	/* the label is OK but invalid		*/
	VDEV_AUX_VERSION_NEWER,	/* on-disk version is too new		*/
	VDEV_AUX_VERSION_OLDER,	/* on-disk version is too old		*/
	VDEV_AUX_UNSUP_FEAT,	/* unsupported features			*/
	VDEV_AUX_SPARED,	/* hot spare used in another pool	*/
	VDEV_AUX_ERR_EXCEEDED,	/* too many errors			*/
	VDEV_AUX_IO_FAILURE,	/* experienced I/O failure		*/
	VDEV_AUX_BAD_LOG,	/* cannot read log chain(s)		*/
	VDEV_AUX_EXTERNAL,	/* external diagnosis			*/
	VDEV_AUX_SPLIT_POOL,	/* vdev was split off into another pool	*/
	VDEV_AUX_ACTIVE,	/* vdev active on a different host	*/
	VDEV_AUX_CHILDREN_OFFLINE, /* all children are offline		*/
	VDEV_AUX_BAD_ASHIFT	/* vdev ashift is invalid		*/
} vdev_aux_t;

/*
 * pool state.  The following states are written to disk as part of the normal
 * SPA lifecycle: ACTIVE, EXPORTED, DESTROYED, SPARE, L2CACHE.  The remaining
 * states are software abstractions used at various levels to communicate
 * pool state.
 */
typedef enum pool_state {
	POOL_STATE_ACTIVE = 0,		/* In active use		*/
	POOL_STATE_EXPORTED,		/* Explicitly exported		*/
	POOL_STATE_DESTROYED,		/* Explicitly destroyed		*/
	POOL_STATE_SPARE,		/* Reserved for hot spare use	*/
	POOL_STATE_L2CACHE,		/* Level 2 ARC device		*/
	POOL_STATE_UNINITIALIZED,	/* Internal spa_t state		*/
	POOL_STATE_UNAVAIL,		/* Internal libzfs state	*/
	POOL_STATE_POTENTIALLY_ACTIVE	/* Internal libzfs state	*/
} pool_state_t;

/*
 * mmp state. The following states provide additional detail describing
 * why a pool couldn't be safely imported.
 */
typedef enum mmp_state {
	MMP_STATE_ACTIVE = 0,		/* In active use		*/
	MMP_STATE_INACTIVE,		/* Inactive and safe to import	*/
	MMP_STATE_NO_HOSTID		/* System hostid is not set	*/
} mmp_state_t;

/*
 * Scan Functions.
 */
typedef enum pool_scan_func {
	POOL_SCAN_NONE,
	POOL_SCAN_SCRUB,
	POOL_SCAN_RESILVER,
	POOL_SCAN_FUNCS
} pool_scan_func_t;

/*
 * Used to control scrub pause and resume.
 */
typedef enum pool_scrub_cmd {
	POOL_SCRUB_NORMAL = 0,
	POOL_SCRUB_PAUSE,
	POOL_SCRUB_FLAGS_END
} pool_scrub_cmd_t;

/*
 * Initialize functions.
 */
typedef enum pool_initialize_func {
	POOL_INITIALIZE_START,
	POOL_INITIALIZE_CANCEL,
	POOL_INITIALIZE_SUSPEND,
	POOL_INITIALIZE_FUNCS
} pool_initialize_func_t;

/*
 * TRIM functions.
 */
typedef enum pool_trim_func {
	POOL_TRIM_START,
	POOL_TRIM_CANCEL,
	POOL_TRIM_SUSPEND,
	POOL_TRIM_FUNCS
} pool_trim_func_t;

/*
 * ZIO types.  Needed to interpret vdev statistics below.
 */
typedef enum zio_type {
	ZIO_TYPE_NULL = 0,
	ZIO_TYPE_READ,
	ZIO_TYPE_WRITE,
	ZIO_TYPE_FREE,
	ZIO_TYPE_CLAIM,
	ZIO_TYPE_IOCTL,
	ZIO_TYPE_TRIM,
	ZIO_TYPES
} zio_type_t;

/*
 * Pool statistics.  Note: all fields should be 64-bit because this
 * is passed between kernel and userland as an nvlist uint64 array.
 */
typedef struct pool_scan_stat {
	/* values stored on disk */
	uint64_t	pss_func;	/* pool_scan_func_t */
	uint64_t	pss_state;	/* dsl_scan_state_t */
	uint64_t	pss_start_time;	/* scan start time */
	uint64_t	pss_end_time;	/* scan end time */
	uint64_t	pss_to_examine;	/* total bytes to scan */
	uint64_t	pss_examined;	/* total bytes located by scanner */
	uint64_t	pss_to_process; /* total bytes to process */
	uint64_t	pss_processed;	/* total processed bytes */
	uint64_t	pss_errors;	/* scan errors	*/

	/* values not stored on disk */
	uint64_t	pss_pass_exam;	/* examined bytes per scan pass */
	uint64_t	pss_pass_issued; /* issued bytes per scan pass */
	uint64_t	pss_pass_start;	/* start time of a scan pass */
	uint64_t	pss_pass_scrub_pause; /* pause time of a scurb pass */
	/* cumulative time scrub spent paused, needed for rate calculation */
	uint64_t	pss_pass_scrub_spent_paused;

	/* Sorted scrubbing new fields */
	/* Stored on disk */
	uint64_t	pss_issued;	/* total bytes checked by scanner */
} pool_scan_stat_t;

/*
 * Errata described by http://zfsonlinux.org/msg/ZFS-8000-ER.  The ordering
 * of this enum must be maintained to ensure the errata identifiers map to
 * the correct documentation.  New errata may only be appended to the list
 * and must contain corresponding documentation at the above link.
 */
typedef enum zpool_errata {
	ZPOOL_ERRATA_NONE,
	ZPOOL_ERRATA_ZOL_2094_SCRUB,
	ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY,
	ZPOOL_ERRATA_ZOL_6845_ENCRYPTION,
	ZPOOL_ERRATA_ZOL_8308_ENCRYPTION,
} zpool_errata_t;

typedef struct pool_removal_stat {
	uint64_t prs_state; /* dsl_scan_state_t */
	uint64_t prs_removing_vdev;
	uint64_t prs_start_time;
	uint64_t prs_end_time;
	uint64_t prs_to_copy; /* bytes that need to be copied */
	uint64_t prs_copied; /* bytes copied so far */
	/*
	 * bytes of memory used for indirect mappings.
	 * This includes all removed vdevs.
	 */
	uint64_t prs_mapping_memory;
} pool_removal_stat_t;

typedef enum dsl_scan_state {
	DSS_NONE,
	DSS_SCANNING,
	DSS_FINISHED,
	DSS_CANCELED,
	DSS_NUM_STATES
} dsl_scan_state_t;

typedef enum {
	CS_NONE,
	CS_CHECKPOINT_EXISTS,
	CS_CHECKPOINT_DISCARDING,
	CS_NUM_STATES
} checkpoint_state_t;

typedef struct pool_checkpoint_stat {
	uint64_t pcs_state;		/* checkpoint_state_t */
	uint64_t pcs_start_time;	/* time checkpoint/discard started */
	uint64_t pcs_space;		/* checkpointed space */
} pool_checkpoint_stat_t;

typedef enum {
	VDEV_INITIALIZE_NONE,
	VDEV_INITIALIZE_ACTIVE,
	VDEV_INITIALIZE_CANCELED,
	VDEV_INITIALIZE_SUSPENDED,
	VDEV_INITIALIZE_COMPLETE
} vdev_initializing_state_t;

typedef enum {
	VDEV_TRIM_NONE,
	VDEV_TRIM_ACTIVE,
	VDEV_TRIM_CANCELED,
	VDEV_TRIM_SUSPENDED,
	VDEV_TRIM_COMPLETE,
} vdev_trim_state_t;

/*
 * Vdev statistics.  Note: all fields should be 64-bit because this
 * is passed between kernel and user land as an nvlist uint64 array.
 *
 * The vs_ops[] and vs_bytes[] arrays must always be an array size of 6 in
 * order to keep subsequent members at their known fixed offsets.  When
 * adding a new field it must be added to the end the structure.
 */
#define	VS_ZIO_TYPES	6

typedef struct vdev_stat {
	hrtime_t	vs_timestamp;		/* time since vdev load	*/
	uint64_t	vs_state;		/* vdev state		*/
	uint64_t	vs_aux;			/* see vdev_aux_t	*/
	uint64_t	vs_alloc;		/* space allocated	*/
	uint64_t	vs_space;		/* total capacity	*/
	uint64_t	vs_dspace;		/* deflated capacity	*/
	uint64_t	vs_rsize;		/* replaceable dev size */
	uint64_t	vs_esize;		/* expandable dev size */
	uint64_t	vs_ops[VS_ZIO_TYPES];	/* operation count	*/
	uint64_t	vs_bytes[VS_ZIO_TYPES];	/* bytes read/written	*/
	uint64_t	vs_read_errors;		/* read errors		*/
	uint64_t	vs_write_errors;	/* write errors		*/
	uint64_t	vs_checksum_errors;	/* checksum errors	*/
	uint64_t	vs_initialize_errors;	/* initializing errors	*/
	uint64_t	vs_self_healed;		/* self-healed bytes	*/
	uint64_t	vs_scan_removing;	/* removing?	*/
	uint64_t	vs_scan_processed;	/* scan processed bytes	*/
	uint64_t	vs_fragmentation;	/* device fragmentation */
	uint64_t	vs_initialize_bytes_done; /* bytes initialized */
	uint64_t	vs_initialize_bytes_est; /* total bytes to initialize */
	uint64_t	vs_initialize_state;	/* vdev_initialzing_state_t */
	uint64_t	vs_initialize_action_time; /* time_t */
	uint64_t	vs_checkpoint_space;    /* checkpoint-consumed space */
	uint64_t	vs_resilver_deferred;	/* resilver deferred	*/
	uint64_t	vs_slow_ios;		/* slow IOs */
	uint64_t	vs_trim_errors;		/* trimming errors	*/
	uint64_t	vs_trim_notsup;		/* supported by device */
	uint64_t	vs_trim_bytes_done;	/* bytes trimmed */
	uint64_t	vs_trim_bytes_est;	/* total bytes to trim */
	uint64_t	vs_trim_state;		/* vdev_trim_state_t */
	uint64_t	vs_trim_action_time;	/* time_t */
} vdev_stat_t;

/*
 * Extended stats
 *
 * These are stats which aren't included in the original iostat output.  For
 * convenience, they are grouped together in vdev_stat_ex, although each stat
 * is individually exported as a nvlist.
 */
typedef struct vdev_stat_ex {
	/* Number of ZIOs issued to disk and waiting to finish */
	uint64_t vsx_active_queue[ZIO_PRIORITY_N_QUEUEABLE];

	/* Number of ZIOs pending to be issued to disk */
	uint64_t vsx_pend_queue[ZIO_PRIORITY_N_QUEUEABLE];

	/*
	 * Below are the histograms for various latencies. Buckets are in
	 * units of nanoseconds.
	 */

	/*
	 * 2^37 nanoseconds = 134s. Timeouts will probably start kicking in
	 * before this.
	 */
#define	VDEV_L_HISTO_BUCKETS	37	/* Latency histo buckets */
#define	VDEV_RQ_HISTO_BUCKETS	25	/* Request size histo buckets */

	/* Amount of time in ZIO queue (ns) */
	uint64_t vsx_queue_histo[ZIO_PRIORITY_N_QUEUEABLE]
	    [VDEV_L_HISTO_BUCKETS];

	/* Total ZIO latency (ns).  Includes queuing and disk access time */
	uint64_t vsx_total_histo[ZIO_TYPES][VDEV_L_HISTO_BUCKETS];

	/* Amount of time to read/write the disk (ns) */
	uint64_t vsx_disk_histo[ZIO_TYPES][VDEV_L_HISTO_BUCKETS];

	/* "lookup the bucket for a value" macro */
#define	HISTO(val, buckets)	(val != 0 ? MIN(highbit64(val) - 1, \
	    buckets - 1) : 0)
#define	L_HISTO(a)	HISTO(a, VDEV_L_HISTO_BUCKETS)
#define	RQ_HISTO(a)	HISTO(a, VDEV_RQ_HISTO_BUCKETS)

	/* Physical IO histogram */
	uint64_t vsx_ind_histo[ZIO_PRIORITY_N_QUEUEABLE]
	    [VDEV_RQ_HISTO_BUCKETS];

	/* Delegated (aggregated) physical IO histogram */
	uint64_t vsx_agg_histo[ZIO_PRIORITY_N_QUEUEABLE]
	    [VDEV_RQ_HISTO_BUCKETS];

} vdev_stat_ex_t;

/*
 * DDT statistics.  Note: all fields should be 64-bit because this
 * is passed between kernel and userland as an nvlist uint64 array.
 */
typedef struct ddt_object {
	uint64_t	ddo_count;	/* number of elments in ddt	*/
	uint64_t	ddo_dspace;	/* size of ddt on disk		*/
	uint64_t	ddo_mspace;	/* size of ddt in-core		*/
} ddt_object_t;

typedef struct ddt_stat {
	uint64_t	dds_blocks;	/* blocks			*/
	uint64_t	dds_lsize;	/* logical size			*/
	uint64_t	dds_psize;	/* physical size		*/
	uint64_t	dds_dsize;	/* deflated allocated size	*/
	uint64_t	dds_ref_blocks;	/* referenced blocks		*/
	uint64_t	dds_ref_lsize;	/* referenced lsize * refcnt	*/
	uint64_t	dds_ref_psize;	/* referenced psize * refcnt	*/
	uint64_t	dds_ref_dsize;	/* referenced dsize * refcnt	*/
} ddt_stat_t;

typedef struct ddt_histogram {
	ddt_stat_t	ddh_stat[64];	/* power-of-two histogram buckets */
} ddt_histogram_t;

#define	ZVOL_DRIVER	"zvol"
#define	ZFS_DRIVER	"zfs"
#define	ZFS_DEV		"/dev/zfs"
#define	ZFS_DISK_ROOT	"/dev/dsk"
#define	ZFS_DISK_ROOTD	ZFS_DISK_ROOT "/"
#define	ZFS_RDISK_ROOT	"/dev/rdsk"
#define	ZFS_RDISK_ROOTD	ZFS_RDISK_ROOT "/"

/* general zvol path */
#define	ZVOL_DIR		"/dev/zvol"
/* expansion */
#define	ZVOL_PSEUDO_DEV		"/devices/pseudo/zfs@0:"
/* for dump and swap */
#define	ZVOL_FULL_DEV_DIR	ZVOL_DIR "/dsk/"
#define	ZVOL_FULL_RDEV_DIR	ZVOL_DIR "/rdsk/"

#define	ZVOL_PROP_NAME		"name"
#define	ZVOL_DEFAULT_BLOCKSIZE	8192

/*
 * /dev/zfs ioctl numbers.
 */
typedef enum zfs_ioc {
	/*
	 * Core features - 81/128 numbers reserved.
	 */
#ifdef __FreeBSD__
	ZFS_IOC_FIRST = 0,
#else
	ZFS_IOC_FIRST =	('Z' << 8),
#endif
	ZFS_IOC = ZFS_IOC_FIRST,
	ZFS_IOC_POOL_CREATE = ZFS_IOC_FIRST,	/* 0x5a00 */
	ZFS_IOC_POOL_DESTROY,			/* 0x5a01 */
	ZFS_IOC_POOL_IMPORT,			/* 0x5a02 */
	ZFS_IOC_POOL_EXPORT,			/* 0x5a03 */
	ZFS_IOC_POOL_CONFIGS,			/* 0x5a04 */
	ZFS_IOC_POOL_STATS,			/* 0x5a05 */
	ZFS_IOC_POOL_TRYIMPORT,			/* 0x5a06 */
	ZFS_IOC_POOL_SCAN,			/* 0x5a07 */
	ZFS_IOC_POOL_FREEZE,			/* 0x5a08 */
	ZFS_IOC_POOL_UPGRADE,			/* 0x5a09 */
	ZFS_IOC_POOL_GET_HISTORY,		/* 0x5a0a */
	ZFS_IOC_VDEV_ADD,			/* 0x5a0b */
	ZFS_IOC_VDEV_REMOVE,			/* 0x5a0c */
	ZFS_IOC_VDEV_SET_STATE,			/* 0x5a0d */
	ZFS_IOC_VDEV_ATTACH,			/* 0x5a0e */
	ZFS_IOC_VDEV_DETACH,			/* 0x5a0f */
	ZFS_IOC_VDEV_SETPATH,			/* 0x5a10 */
	ZFS_IOC_VDEV_SETFRU,			/* 0x5a11 */
	ZFS_IOC_OBJSET_STATS,			/* 0x5a12 */
	ZFS_IOC_OBJSET_ZPLPROPS,		/* 0x5a13 */
	ZFS_IOC_DATASET_LIST_NEXT,		/* 0x5a14 */
	ZFS_IOC_SNAPSHOT_LIST_NEXT,		/* 0x5a15 */
	ZFS_IOC_SET_PROP,			/* 0x5a16 */
	ZFS_IOC_CREATE,				/* 0x5a17 */
	ZFS_IOC_DESTROY,			/* 0x5a18 */
	ZFS_IOC_ROLLBACK,			/* 0x5a19 */
	ZFS_IOC_RENAME,				/* 0x5a1a */
	ZFS_IOC_RECV,				/* 0x5a1b */
	ZFS_IOC_SEND,				/* 0x5a1c */
	ZFS_IOC_INJECT_FAULT,			/* 0x5a1d */
	ZFS_IOC_CLEAR_FAULT,			/* 0x5a1e */
	ZFS_IOC_INJECT_LIST_NEXT,		/* 0x5a1f */
	ZFS_IOC_ERROR_LOG,			/* 0x5a20 */
	ZFS_IOC_CLEAR,				/* 0x5a21 */
	ZFS_IOC_PROMOTE,			/* 0x5a22 */
	ZFS_IOC_SNAPSHOT,			/* 0x5a23 */
	ZFS_IOC_DSOBJ_TO_DSNAME,		/* 0x5a24 */
	ZFS_IOC_OBJ_TO_PATH,			/* 0x5a25 */
	ZFS_IOC_POOL_SET_PROPS,			/* 0x5a26 */
	ZFS_IOC_POOL_GET_PROPS,			/* 0x5a27 */
	ZFS_IOC_SET_FSACL,			/* 0x5a28 */
	ZFS_IOC_GET_FSACL,			/* 0x5a29 */
	ZFS_IOC_SHARE,				/* 0x5a2a */
	ZFS_IOC_INHERIT_PROP,			/* 0x5a2b */
	ZFS_IOC_SMB_ACL,			/* 0x5a2c */
	ZFS_IOC_USERSPACE_ONE,			/* 0x5a2d */
	ZFS_IOC_USERSPACE_MANY,			/* 0x5a2e */
	ZFS_IOC_USERSPACE_UPGRADE,		/* 0x5a2f */
	ZFS_IOC_HOLD,				/* 0x5a30 */
	ZFS_IOC_RELEASE,			/* 0x5a31 */
	ZFS_IOC_GET_HOLDS,			/* 0x5a32 */
	ZFS_IOC_OBJSET_RECVD_PROPS,		/* 0x5a33 */
	ZFS_IOC_VDEV_SPLIT,			/* 0x5a34 */
	ZFS_IOC_NEXT_OBJ,			/* 0x5a35 */
	ZFS_IOC_DIFF,				/* 0x5a36 */
	ZFS_IOC_TMP_SNAPSHOT,			/* 0x5a37 */
	ZFS_IOC_OBJ_TO_STATS,			/* 0x5a38 */
	ZFS_IOC_SPACE_WRITTEN,			/* 0x5a39 */
	ZFS_IOC_SPACE_SNAPS,			/* 0x5a3a */
	ZFS_IOC_DESTROY_SNAPS,			/* 0x5a3b */
	ZFS_IOC_POOL_REGUID,			/* 0x5a3c */
	ZFS_IOC_POOL_REOPEN,			/* 0x5a3d */
	ZFS_IOC_SEND_PROGRESS,			/* 0x5a3e */
	ZFS_IOC_LOG_HISTORY,			/* 0x5a3f */
	ZFS_IOC_SEND_NEW,			/* 0x5a40 */
	ZFS_IOC_SEND_SPACE,			/* 0x5a41 */
	ZFS_IOC_CLONE,				/* 0x5a42 */
	ZFS_IOC_BOOKMARK,			/* 0x5a43 */
	ZFS_IOC_GET_BOOKMARKS,			/* 0x5a44 */
	ZFS_IOC_DESTROY_BOOKMARKS,		/* 0x5a45 */
	ZFS_IOC_POOL_SYNC,			/* 0x5a46 */
	ZFS_IOC_CHANNEL_PROGRAM,		/* 0x5a47 */
	ZFS_IOC_LOAD_KEY,			/* 0x5a48 */
	ZFS_IOC_UNLOAD_KEY,			/* 0x5a49 */
	ZFS_IOC_CHANGE_KEY,			/* 0x5a4a */
	ZFS_IOC_REMAP,				/* 0x5a4b */
	ZFS_IOC_POOL_CHECKPOINT,		/* 0x5a4c */
	ZFS_IOC_POOL_DISCARD_CHECKPOINT,	/* 0x5a4d */
	ZFS_IOC_POOL_INITIALIZE,		/* 0x5a4e */
	ZFS_IOC_POOL_TRIM,			/* 0x5a4f */
	ZFS_IOC_REDACT,				/* 0x5a50 */
	ZFS_IOC_GET_BOOKMARK_PROPS,		/* 0x5a51 */
	ZFS_IOC_WAIT,				/* 0x5a52 */

	/*
	 * Per-platform (Optional) - 8/128 numbers reserved.
	 */
	ZFS_IOC_PLATFORM = ZFS_IOC_FIRST + 0x80,
	ZFS_IOC_EVENTS_NEXT,			/* 0x81 (Linux) */
	ZFS_IOC_EVENTS_CLEAR,			/* 0x82 (Linux) */
	ZFS_IOC_EVENTS_SEEK,			/* 0x83 (Linux) */
	ZFS_IOC_NEXTBOOT,			/* 0x84 (FreeBSD) */
	ZFS_IOC_JAIL,				/* 0x85 (FreeBSD) */
	ZFS_IOC_UNJAIL,				/* 0x86 (FreeBSD) */
	ZFS_IOC_SET_BOOTENV,			/* 0x87 */
	ZFS_IOC_GET_BOOTENV,			/* 0x88 */
	ZFS_IOC_LAST
} zfs_ioc_t;

/*
 * ZFS-specific error codes used for returning descriptive errors
 * to the userland through zfs ioctls.
 *
 * The enum implicitly includes all the error codes from errno.h.
 * New code should use and extend this enum for errors that are
 * not described precisely by generic errno codes.
 */
typedef enum {
	ZFS_ERR_CHECKPOINT_EXISTS = 1024,
	ZFS_ERR_DISCARDING_CHECKPOINT,
	ZFS_ERR_NO_CHECKPOINT,
	ZFS_ERR_DEVRM_IN_PROGRESS,
	ZFS_ERR_VDEV_TOO_BIG,
	ZFS_ERR_FROM_IVSET_GUID_MISSING,
	ZFS_ERR_FROM_IVSET_GUID_MISMATCH,
	ZFS_ERR_SPILL_BLOCK_FLAG_MISSING,
	ZFS_ERR_UNKNOWN_SEND_STREAM_FEATURE,
	ZFS_ERR_IOC_CMD_UNAVAIL,
	ZFS_ERR_IOC_ARG_UNAVAIL,
	ZFS_ERR_IOC_ARG_REQUIRED,
	ZFS_ERR_IOC_ARG_BADTYPE,
} zfs_errno_t;

/*
 * Internal SPA load state.  Used by FMA diagnosis engine.
 */
typedef enum {
	SPA_LOAD_NONE,		/* no load in progress	*/
	SPA_LOAD_OPEN,		/* normal open		*/
	SPA_LOAD_IMPORT,	/* import in progress	*/
	SPA_LOAD_TRYIMPORT,	/* tryimport in progress */
	SPA_LOAD_RECOVER,	/* recovery requested	*/
	SPA_LOAD_ERROR,		/* load failed		*/
	SPA_LOAD_CREATE		/* creation in progress */
} spa_load_state_t;

/* supported encryption algorithms */
enum zio_encrypt {
	ZIO_CRYPT_INHERIT = 0,
	ZIO_CRYPT_ON,
	ZIO_CRYPT_OFF,
	ZIO_CRYPT_AES_128_CCM,
	ZIO_CRYPT_AES_192_CCM,
	ZIO_CRYPT_AES_256_CCM,
	ZIO_CRYPT_AES_128_GCM,
	ZIO_CRYPT_AES_192_GCM,
	ZIO_CRYPT_AES_256_GCM,
	ZIO_CRYPT_FUNCTIONS
};

typedef enum {
	ZPOOL_WAIT_CKPT_DISCARD,
	ZPOOL_WAIT_FREE,
	ZPOOL_WAIT_INITIALIZE,
	ZPOOL_WAIT_REPLACE,
	ZPOOL_WAIT_REMOVE,
	ZPOOL_WAIT_RESILVER,
	ZPOOL_WAIT_SCRUB,
	ZPOOL_WAIT_NUM_ACTIVITIES
} zpool_wait_activity_t;

/*
 * Bookmark name values.
 */
#define	ZPOOL_ERR_LIST		"error list"
#define	ZPOOL_ERR_DATASET	"dataset"
#define	ZPOOL_ERR_OBJECT	"object"

#define	HIS_MAX_RECORD_LEN	(MAXPATHLEN + MAXPATHLEN + 1)

/*
 * The following are names used in the nvlist describing
 * the pool's history log.
 */
#define	ZPOOL_HIST_RECORD	"history record"
#define	ZPOOL_HIST_TIME		"history time"
#define	ZPOOL_HIST_CMD		"history command"
#define	ZPOOL_HIST_WHO		"history who"
#define	ZPOOL_HIST_ZONE		"history zone"
#define	ZPOOL_HIST_HOST		"history hostname"
#define	ZPOOL_HIST_TXG		"history txg"
#define	ZPOOL_HIST_INT_EVENT	"history internal event"
#define	ZPOOL_HIST_INT_STR	"history internal str"
#define	ZPOOL_HIST_INT_NAME	"internal_name"
#define	ZPOOL_HIST_IOCTL	"ioctl"
#define	ZPOOL_HIST_INPUT_NVL	"in_nvl"
#define	ZPOOL_HIST_OUTPUT_NVL	"out_nvl"
#define	ZPOOL_HIST_DSNAME	"dsname"
#define	ZPOOL_HIST_DSID		"dsid"
#define	ZPOOL_HIST_ERRNO	"errno"

/*
 * The following are names used when invoking ZFS_IOC_POOL_INITIALIZE.
 */
#define	ZPOOL_INITIALIZE_COMMAND	"initialize_command"
#define	ZPOOL_INITIALIZE_VDEVS		"initialize_vdevs"

/*
 * Special nvlist name that will not have its args recorded in the pool's
 * history log.
 */
#define	ZPOOL_HIDDEN_ARGS	"hidden_args"

/*
 * The following are names used when invoking ZFS_IOC_POOL_TRIM.
 */
#define	ZPOOL_TRIM_COMMAND		"trim_command"
#define	ZPOOL_TRIM_VDEVS		"trim_vdevs"
#define	ZPOOL_TRIM_RATE			"trim_rate"
#define	ZPOOL_TRIM_SECURE		"trim_secure"

/*
 * The following are names used when invoking ZFS_IOC_POOL_WAIT.
 */
#define	ZPOOL_WAIT_ACTIVITY		"wait_activity"
#define	ZPOOL_WAIT_TAG			"wait_tag"
#define	ZPOOL_WAIT_WAITED		"wait_waited"

/*
 * Flags for ZFS_IOC_VDEV_SET_STATE
 */
#define	ZFS_ONLINE_CHECKREMOVE	0x1
#define	ZFS_ONLINE_UNSPARE	0x2
#define	ZFS_ONLINE_FORCEFAULT	0x4
#define	ZFS_ONLINE_EXPAND	0x8
#define	ZFS_OFFLINE_TEMPORARY	0x1

/*
 * Flags for ZFS_IOC_POOL_IMPORT
 */
#define	ZFS_IMPORT_NORMAL	0x0
#define	ZFS_IMPORT_VERBATIM	0x1
#define	ZFS_IMPORT_ANY_HOST	0x2
#define	ZFS_IMPORT_MISSING_LOG	0x4
#define	ZFS_IMPORT_ONLY		0x8
#define	ZFS_IMPORT_CHECKPOINT	0x10
#define	ZFS_IMPORT_TEMP_NAME	0x20
#define	ZFS_IMPORT_SKIP_MMP	0x40
#define	ZFS_IMPORT_LOAD_KEYS	0x80

/*
 * Channel program argument/return nvlist keys and defaults.
 */
#define	ZCP_ARG_PROGRAM		"program"
#define	ZCP_ARG_ARGLIST		"arg"
#define	ZCP_ARG_SYNC		"sync"
#define	ZCP_ARG_INSTRLIMIT	"instrlimit"
#define	ZCP_ARG_MEMLIMIT	"memlimit"

#define	ZCP_ARG_CLIARGV		"argv"

#define	ZCP_RET_ERROR		"error"
#define	ZCP_RET_RETURN		"return"

#define	ZCP_DEFAULT_INSTRLIMIT	(10 * 1000 * 1000)
#define	ZCP_MAX_INSTRLIMIT	(10 * ZCP_DEFAULT_INSTRLIMIT)
#define	ZCP_DEFAULT_MEMLIMIT	(10 * 1024 * 1024)
#define	ZCP_MAX_MEMLIMIT	(10 * ZCP_DEFAULT_MEMLIMIT)

/*
 * Sysevent payload members.  ZFS will generate the following sysevents with the
 * given payloads:
 *
 *	ESC_ZFS_RESILVER_START
 *	ESC_ZFS_RESILVER_END
 *	ESC_ZFS_POOL_DESTROY
 *	ESC_ZFS_POOL_REGUID
 *
 *		ZFS_EV_POOL_NAME	DATA_TYPE_STRING
 *		ZFS_EV_POOL_GUID	DATA_TYPE_UINT64
 *
 *	ESC_ZFS_VDEV_REMOVE
 *	ESC_ZFS_VDEV_CLEAR
 *	ESC_ZFS_VDEV_CHECK
 *
 *		ZFS_EV_POOL_NAME	DATA_TYPE_STRING
 *		ZFS_EV_POOL_GUID	DATA_TYPE_UINT64
 *		ZFS_EV_VDEV_PATH	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_VDEV_GUID	DATA_TYPE_UINT64
 *
 *	ESC_ZFS_HISTORY_EVENT
 *
 *		ZFS_EV_POOL_NAME	DATA_TYPE_STRING
 *		ZFS_EV_POOL_GUID	DATA_TYPE_UINT64
 *		ZFS_EV_HIST_TIME	DATA_TYPE_UINT64	(optional)
 *		ZFS_EV_HIST_CMD		DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_WHO		DATA_TYPE_UINT64	(optional)
 *		ZFS_EV_HIST_ZONE	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_HOST	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_TXG		DATA_TYPE_UINT64	(optional)
 *		ZFS_EV_HIST_INT_EVENT	DATA_TYPE_UINT64	(optional)
 *		ZFS_EV_HIST_INT_STR	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_INT_NAME	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_IOCTL	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_DSNAME	DATA_TYPE_STRING	(optional)
 *		ZFS_EV_HIST_DSID	DATA_TYPE_UINT64	(optional)
 *
 * The ZFS_EV_HIST_* members will correspond to the ZPOOL_HIST_* members in the
 * history log nvlist.  The keynames will be free of any spaces or other
 * characters that could be potentially unexpected to consumers of the
 * sysevents.
 */
#define	ZFS_EV_POOL_NAME	"pool_name"
#define	ZFS_EV_POOL_GUID	"pool_guid"
#define	ZFS_EV_VDEV_PATH	"vdev_path"
#define	ZFS_EV_VDEV_GUID	"vdev_guid"
#define	ZFS_EV_HIST_TIME	"history_time"
#define	ZFS_EV_HIST_CMD		"history_command"
#define	ZFS_EV_HIST_WHO		"history_who"
#define	ZFS_EV_HIST_ZONE	"history_zone"
#define	ZFS_EV_HIST_HOST	"history_hostname"
#define	ZFS_EV_HIST_TXG		"history_txg"
#define	ZFS_EV_HIST_INT_EVENT	"history_internal_event"
#define	ZFS_EV_HIST_INT_STR	"history_internal_str"
#define	ZFS_EV_HIST_INT_NAME	"history_internal_name"
#define	ZFS_EV_HIST_IOCTL	"history_ioctl"
#define	ZFS_EV_HIST_DSNAME	"history_dsname"
#define	ZFS_EV_HIST_DSID	"history_dsid"

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_ZFS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _ZUT_H
#define	_ZUT_H

/*
 * IOCTLs for the zfs unit test driver
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>

#define	ZUT_DRIVER	"zut"
#define	ZUT_DEV		"/dev/zut"

#define	ZUT_VERSION_STRING		"1"

/*
 * /dev/zut ioctl numbers.
 */
#define	ZUT_IOC		('U' << 8)

/* Request flags */
#define	ZUT_IGNORECASE		0x01
#define	ZUT_ACCFILTER		0x02
#define	ZUT_XATTR		0x04
#define	ZUT_EXTRDDIR		0x08
#define	ZUT_GETSTAT		0x10

typedef struct zut_lookup {
	int	zl_reqflags;
	int	zl_deflags;		/* output */
	int	zl_retcode;		/* output */
	char	zl_dir[MAXPATHLEN];
	char	zl_file[MAXNAMELEN];
	char	zl_xfile[MAXNAMELEN];
	char	zl_real[MAXPATHLEN];	/* output */
	uint64_t zl_xvattrs;		/* output */
	struct stat64 zl_statbuf;	/* output */
} zut_lookup_t;

typedef struct zut_readdir {
	uint64_t zr_buf;		/* pointer to output buffer */
	uint64_t zr_loffset;		/* output */
	char	zr_dir[MAXPATHLEN];
	char	zr_file[MAXNAMELEN];
	int	zr_reqflags;
	int	zr_retcode;		/* output */
	int	zr_eof;			/* output */
	uint_t	zr_bytes;		/* output */
	uint_t	zr_buflen;
} zut_readdir_t;

typedef enum zut_ioc {
	ZUT_IOC_MIN_CMD = ZUT_IOC - 1,
	ZUT_IOC_LOOKUP = ZUT_IOC,
	ZUT_IOC_READDIR,
	ZUT_IOC_MAX_CMD
} zut_ioc_t;

#ifdef __cplusplus
}
#endif

#endif /* _ZUT_H */