This file is indexed.

/usr/include/ocfs2/ocfs2.h is in ocfs2-tools-dev 1.8.5-3ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   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
/* -*- mode: c; c-basic-offset: 8; -*-
 * vim: noexpandtab sw=8 ts=8 sts=0:
 *
 * ocfs2.h
 *
 * Filesystem object routines for the OCFS2 userspace library.
 *
 * Copyright (C) 2004 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License, version 2,  as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 *
 * Authors: Joel Becker
 */

#ifndef _FILESYS_H
#define _FILESYS_H

#ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 600
#endif
#ifndef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif

#include <stdio.h>
#include <stdint.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>

#include <limits.h>

#include <linux/types.h>

#include <et/com_err.h>

#include <ocfs2-kernel/kernel-list.h>
#include <ocfs2-kernel/sparse_endian_types.h>
#include <ocfs2-kernel/ocfs2_fs.h>
#include <ocfs2-kernel/quota_tree.h>
#include <o2dlm/o2dlm.h>
#include <o2cb/o2cb.h>
#include <ocfs2/ocfs2_err.h>
#include <ocfs2/jbd2.h>
#include <ocfs2-kernel/ocfs2_lockid.h>
#include <ocfs2-kernel/ocfs2_ioctl.h>

#define OCFS2_LIB_FEATURE_INCOMPAT_SUPP		(OCFS2_FEATURE_INCOMPAT_SUPP | \
						 OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV | \
						 OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG | \
						 OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT   | \
						 OCFS2_FEATURE_INCOMPAT_INLINE_DATA   | \
						 OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG)

#define OCFS2_LIB_FEATURE_RO_COMPAT_SUPP	OCFS2_FEATURE_RO_COMPAT_SUPP

#define OCFS2_LIB_FEATURE_COMPAT_SUPP		OCFS2_FEATURE_COMPAT_SUPP

#define OCFS2_LIB_ABORTED_TUNEFS_SUPP		OCFS2_TUNEFS_INPROG_REMOVE_SLOT


/* define OCFS2_SB for ocfs2-tools */
#define OCFS2_SB(sb)	(sb)

/* Flags for the ocfs2_filesys structure */
#define OCFS2_FLAG_RO			0x00
#define OCFS2_FLAG_RW			0x01
#define OCFS2_FLAG_CHANGED		0x02
#define OCFS2_FLAG_DIRTY		0x04
#define OCFS2_FLAG_SWAP_BYTES		0x08
#define OCFS2_FLAG_BUFFERED		0x10
#define OCFS2_FLAG_NO_REV_CHECK		0x20	/* Do not check the OCFS
						   vol_header structure
						   for revision info */
#define OCFS2_FLAG_HEARTBEAT_DEV_OK	0x40
#define OCFS2_FLAG_STRICT_COMPAT_CHECK	0x80
#define OCFS2_FLAG_IMAGE_FILE	      0x0100
#define OCFS2_FLAG_NO_ECC_CHECKS      0x0200	/* Do not validate metaecc
						 * information on block
						 * reads. */
#define OCFS2_FLAG_HARD_RO            0x0400


/* Return flags for the directory iterator functions */
#define OCFS2_DIRENT_CHANGED	0x01
#define OCFS2_DIRENT_ABORT	0x02
#define OCFS2_DIRENT_ERROR	0x04

/* Directory iterator flags */
#define OCFS2_DIRENT_FLAG_INCLUDE_EMPTY		0x01
#define OCFS2_DIRENT_FLAG_INCLUDE_REMOVED	0x02
#define OCFS2_DIRENT_FLAG_EXCLUDE_DOTS		0x04
#define OCFS2_DIRENT_FLAG_INCLUDE_TRAILER	0x08

/* Return flags for the chain iterator functions */
#define OCFS2_CHAIN_CHANGED	0x01
#define OCFS2_CHAIN_ABORT	0x02
#define OCFS2_CHAIN_ERROR	0x04

/* Directory constants */
#define OCFS2_DIRENT_DOT_FILE		1
#define OCFS2_DIRENT_DOT_DOT_FILE	2
#define OCFS2_DIRENT_OTHER_FILE		3
#define OCFS2_DIRENT_DELETED_FILE	4

/* Directory scan flags */
#define OCFS2_DIR_SCAN_FLAG_EXCLUDE_DOTS	0x01

/* Check if mounted flags */
#define OCFS2_MF_MOUNTED		1
#define OCFS2_MF_ISROOT			2
#define OCFS2_MF_READONLY		4
#define OCFS2_MF_SWAP			8
#define OCFS2_MF_BUSY			16
#define OCFS2_MF_MOUNTED_CLUSTER	32

/* check_heartbeats progress states */
#define OCFS2_CHB_START		1
#define OCFS2_CHB_WAITING	2
#define OCFS2_CHB_COMPLETE	3

/* Flags for global quotafile info */
#define OCFS2_QF_INFO_DIRTY 1
#define OCFS2_QF_INFO_LOADED 2

typedef void (*ocfs2_chb_notify)(int state, char *progress, void *data);

typedef struct _ocfs2_filesys ocfs2_filesys;
typedef struct _ocfs2_cached_inode ocfs2_cached_inode;
typedef struct _ocfs2_cached_dquot ocfs2_cached_dquot;
typedef struct _io_channel io_channel;
typedef struct _ocfs2_inode_scan ocfs2_inode_scan;
typedef struct _ocfs2_dir_scan ocfs2_dir_scan;
typedef struct _ocfs2_bitmap ocfs2_bitmap;
typedef struct _ocfs2_devices ocfs2_devices;

enum ocfs2_block_type {
	OCFS2_BLOCK_UNKNOWN,
	OCFS2_BLOCK_INODE,
	OCFS2_BLOCK_SUPERBLOCK,
	OCFS2_BLOCK_EXTENT_BLOCK,
	OCFS2_BLOCK_GROUP_DESCRIPTOR,
	OCFS2_BLOCK_DIR_BLOCK,
	OCFS2_BLOCK_XATTR,
	OCFS2_BLOCK_REFCOUNT,
	OCFS2_BLOCK_DXROOT,
	OCFS2_BLOCK_DXLEAF,
};

#define MAXQUOTAS 2
#define USRQUOTA 0
#define GRPQUOTA 1

#define OCFS2_DEF_BLOCK_GRACE 604800 /* 1 week */
#define OCFS2_DEF_INODE_GRACE 604800 /* 1 week */
#define OCFS2_DEF_QUOTA_SYNC 10000   /* 10 seconds */

struct _ocfs2_quota_info {
	ocfs2_cached_inode *qi_inode;
	int flags;
	struct ocfs2_global_disk_dqinfo qi_info;
};

typedef struct _ocfs2_quota_info ocfs2_quota_info;

struct _ocfs2_filesys {
	char *fs_devname;
	uint32_t fs_flags;
	io_channel *fs_io;
	struct ocfs2_dinode *fs_super;
	struct ocfs2_dinode *fs_orig_super;
	unsigned int fs_blocksize;
	unsigned int fs_clustersize;
	uint32_t fs_clusters;
	uint64_t fs_blocks;
	uint32_t fs_umask;
	uint64_t fs_root_blkno;
	uint64_t fs_sysdir_blkno;
	uint64_t fs_first_cg_blkno;
	char uuid_str[OCFS2_VOL_UUID_LEN * 2 + 1];

	/* Allocators */
	ocfs2_cached_inode *fs_cluster_alloc;
	ocfs2_cached_inode **fs_inode_allocs;
	ocfs2_cached_inode *fs_system_inode_alloc;
	ocfs2_cached_inode **fs_eb_allocs;
	ocfs2_cached_inode *fs_system_eb_alloc;

	struct o2dlm_ctxt *fs_dlm_ctxt;
	struct ocfs2_image_state *ost;

	ocfs2_quota_info qinfo[MAXQUOTAS];

	/* Reserved for the use of the calling application. */
	void *fs_private;
};

struct _ocfs2_cached_inode {
	struct _ocfs2_filesys *ci_fs;
	uint64_t ci_blkno;
	struct ocfs2_dinode *ci_inode;
	ocfs2_bitmap *ci_chains;
};

typedef unsigned int qid_t;

struct _ocfs2_cached_dquot {
	loff_t d_off;	/* Offset of structure in the file */
	struct _ocfs2_cached_dquot *d_next;	/* Next entry in hashchain */
	struct _ocfs2_cached_dquot **d_pprev;	/* Previous pointer in hashchain */
	struct ocfs2_global_disk_dqblk d_ddquot;	/* Quota entry */
};

struct ocfs2_slot_data {
	int		sd_valid;
	unsigned int	sd_node_num;
};

struct ocfs2_slot_map_data {
	int			md_num_slots;
	struct ocfs2_slot_data	*md_slots;
};

struct _ocfs2_devices {
	struct list_head list;
	char dev_name[PATH_MAX];
	uint8_t label[64];
	uint8_t uuid[16];
	int mount_flags;
	int fs_type;			/* 0=unknown, 1=ocfs, 2=ocfs2 */
	int hb_dev;
	char stack[OCFS2_STACK_LABEL_LEN + 1]; /* Local, O2CB, CMAN, PCMK */
	char cluster[OCFS2_CLUSTER_NAME_LEN + 1];
	unsigned char stackflags;
	uint32_t maj_num;		/* major number of the device */
	uint32_t min_num;		/* minor number of the device */
	errcode_t errcode;		/* error encountered reading device */
	void *private;
	struct ocfs2_slot_map_data *map; /* Mounted nodes, must be freed */
};

typedef struct _ocfs2_fs_options ocfs2_fs_options;

struct _ocfs2_fs_options {
	uint32_t opt_compat;
	uint32_t opt_incompat;
	uint32_t opt_ro_compat;
};

enum ocfs2_mkfs_types {
	OCFS2_MKFSTYPE_DEFAULT,
	OCFS2_MKFSTYPE_DATAFILES,
	OCFS2_MKFSTYPE_MAIL,
	OCFS2_MKFSTYPE_VMSTORE,
};

struct _ocfs2_quota_hash {
	int alloc_entries;
	int used_entries;
	ocfs2_cached_dquot **hash;
};

struct ocfs2_dx_hinfo {
	uint32_t major_hash;
	uint32_t minor_hash;
};

struct ocfs2_dir_lookup_result {
	struct ocfs2_dx_hinfo       dl_hinfo;         /* name hash results */
	char *                      dl_leaf;          /* unindexed block buffer */
	uint64_t                    dl_leaf_blkno;    /* blk number of dl_leaf */
	struct ocfs2_dir_entry *    dl_entry;         /* dirent pointed into dl_leaf */
	struct ocfs2_dx_leaf *      dl_dx_leaf;       /* indexed block buffer */
	uint64_t                    dl_dx_leaf_blkno; /* blk number of dl_dx_leaf */
	struct ocfs2_dx_entry *     dl_dx_entry;      /* indexed entry pointed to dl_dx_leaf */
	int                         dl_dx_entry_idx;  /* index of dl_dx_entry in entries list */
};

typedef struct _ocfs2_quota_hash ocfs2_quota_hash;

errcode_t ocfs2_malloc(unsigned long size, void *ptr);
errcode_t ocfs2_malloc0(unsigned long size, void *ptr);
errcode_t ocfs2_free(void *ptr);
errcode_t ocfs2_realloc(unsigned long size, void *ptr);
errcode_t ocfs2_realloc0(unsigned long size, void *ptr,
			 unsigned long old_size);
errcode_t ocfs2_malloc_blocks(io_channel *channel, int num_blocks,
			      void *ptr);
errcode_t ocfs2_malloc_block(io_channel *channel, void *ptr);

int io_is_device_readonly(io_channel *channel);
errcode_t io_open(const char *name, int flags, io_channel **channel);
errcode_t io_close(io_channel *channel);
int io_get_error(io_channel *channel);
errcode_t io_set_blksize(io_channel *channel, int blksize);
int io_get_blksize(io_channel *channel);
int io_get_fd(io_channel *channel);

struct ocfs2_io_stats {
	uint64_t is_bytes_read;
	uint64_t is_bytes_written;
	uint32_t is_cache_hits;
	uint32_t is_cache_misses;
	uint32_t is_cache_inserts;
	uint32_t is_cache_removes;
};

void io_get_stats(io_channel *channel, struct ocfs2_io_stats *stats);

/*
 * Raw I/O functions.  They will use the I/O cache if available.  The
 * _nocache version will not add a block to the cache, but if the block is
 * already in the cache it will be moved to the end of the LRU and kept
 * in a good state.
 *
 * Use ocfs2_read_blocks() if your application might handle o2image file.
 *
 * If a channel is set to 'nocache' via io_set_nocache(), it will use
 * the _nocache() functions even if called via the regular functions.
 * This allows control of naive code that we don't want to have to carry
 * nocache parameters around.  Smarter code can ignore this function and
 * use the _nocache() functions directly.
 */
errcode_t io_read_block(io_channel *channel, int64_t blkno, int count,
			char *data);
errcode_t io_read_block_nocache(io_channel *channel, int64_t blkno, int count,
			char *data);
errcode_t io_write_block(io_channel *channel, int64_t blkno, int count,
			 const char *data);
errcode_t io_write_block_nocache(io_channel *channel, int64_t blkno, int count,
			 const char *data);
errcode_t io_init_cache(io_channel *channel, size_t nr_blocks);
void io_set_nocache(io_channel *channel, bool nocache);
errcode_t io_init_cache_size(io_channel *channel, size_t bytes);
size_t io_get_cache_size(io_channel *channel);
errcode_t io_share_cache(io_channel *from, io_channel *to);
errcode_t io_mlock_cache(io_channel *channel);
void io_destroy_cache(io_channel *channel);


struct io_vec_unit {
	uint64_t	ivu_blkno;
	char		*ivu_buf;
	uint32_t	ivu_buflen;
};

errcode_t io_vec_read_blocks(io_channel *channel, struct io_vec_unit *ivus,
			     int count);

errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb);
/* Writes the main superblock at OCFS2_SUPER_BLOCK_BLKNO */
errcode_t ocfs2_write_primary_super(ocfs2_filesys *fs);
/* Writes the primary and backups if enabled */
errcode_t ocfs2_write_super(ocfs2_filesys *fs);

/*
 * ocfs2_read_blocks() is a wraper around io_read_block. If device is an
 * image file it translates disk offset to image offset.
 * ocfs2_read_blocks_nocache() calls io_read_block_nocache().
 */
errcode_t ocfs2_read_blocks(ocfs2_filesys *fs, int64_t blkno, int count,
			    char *data);
errcode_t ocfs2_read_blocks_nocache(ocfs2_filesys *fs, int64_t blkno, int count,
				    char *data);
int ocfs2_is_hard_readonly(ocfs2_filesys *fs);
int ocfs2_mount_local(ocfs2_filesys *fs);
errcode_t ocfs2_open(const char *name, int flags,
		     unsigned int superblock, unsigned int blksize,
		     ocfs2_filesys **ret_fs);
errcode_t ocfs2_flush(ocfs2_filesys *fs);
errcode_t ocfs2_close(ocfs2_filesys *fs);
void ocfs2_freefs(ocfs2_filesys *fs);

void ocfs2_swap_inode_from_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di);
void ocfs2_swap_inode_to_cpu(ocfs2_filesys *fs, struct ocfs2_dinode *di);
errcode_t ocfs2_read_inode(ocfs2_filesys *fs, uint64_t blkno,
			   char *inode_buf);
errcode_t ocfs2_write_inode(ocfs2_filesys *fs, uint64_t blkno,
			    char *inode_buf);
errcode_t ocfs2_write_inode_without_meta_ecc(ocfs2_filesys *fs, uint64_t blkno,
			    char *inode_buf);
errcode_t ocfs2_check_directory(ocfs2_filesys *fs, uint64_t dir);
int ocfs2_check_dir_entry(ocfs2_filesys *fs, struct ocfs2_dir_entry *de,
				char *dir_buf, unsigned int offset);
errcode_t ocfs2_read_cached_inode(ocfs2_filesys *fs, uint64_t blkno,
				  ocfs2_cached_inode **ret_ci);
errcode_t ocfs2_write_cached_inode(ocfs2_filesys *fs,
				   ocfs2_cached_inode *cinode);
errcode_t ocfs2_free_cached_inode(ocfs2_filesys *fs,
				  ocfs2_cached_inode *cinode);
errcode_t ocfs2_refresh_cached_inode(ocfs2_filesys *fs,
				     ocfs2_cached_inode *cinode);

/*
 * obj is the object containing the extent list.  eg, if you are swapping
 * an inode's extent list, you're passing 'di' for the obj and
 * '&di->id2.i_list' for the el.  obj is needed to make sure the
 * byte swapping code doesn't walk off the end of the buffer in the
 * presence of corruption.
 */
void ocfs2_swap_extent_list_from_cpu(ocfs2_filesys *fs, void *obj,
				     struct ocfs2_extent_list *el);
void ocfs2_swap_extent_list_to_cpu(ocfs2_filesys *fs, void *obj,
				   struct ocfs2_extent_list *el);
errcode_t ocfs2_extent_map_get_blocks(ocfs2_cached_inode *cinode,
				      uint64_t v_blkno, int count,
				      uint64_t *p_blkno,
				      uint64_t *ret_count,
				      uint16_t *extent_flags);
errcode_t ocfs2_get_clusters(ocfs2_cached_inode *cinode,
			     uint32_t v_cluster,
			     uint32_t *p_cluster,
			     uint32_t *num_clusters,
			     uint16_t *extent_flags);
errcode_t ocfs2_xattr_get_clusters(ocfs2_filesys *fs,
				   struct ocfs2_extent_list *el,
				   uint64_t el_blkno,
				   char *el_blk,
				   uint32_t v_cluster,
				   uint32_t *p_cluster,
				   uint32_t *num_clusters,
				   uint16_t *extent_flags);
int ocfs2_find_leaf(ocfs2_filesys *fs, struct ocfs2_dinode *di,
		    uint32_t cpos, char **leaf_buf);
int ocfs2_search_extent_list(struct ocfs2_extent_list *el, uint32_t v_cluster);
void ocfs2_swap_journal_superblock(journal_superblock_t *jsb);
errcode_t ocfs2_init_journal_superblock(ocfs2_filesys *fs, char *buf,
					int buflen, uint32_t jrnl_size);
errcode_t ocfs2_read_journal_superblock(ocfs2_filesys *fs, uint64_t blkno,
					char *jsb_buf);
errcode_t ocfs2_write_journal_superblock(ocfs2_filesys *fs, uint64_t blkno,
					 char *jsb_buf);
errcode_t ocfs2_make_journal(ocfs2_filesys *fs, uint64_t blkno,
			     uint32_t clusters, ocfs2_fs_options *features);
errcode_t ocfs2_journal_clear_features(journal_superblock_t *jsb,
				       ocfs2_fs_options *features);
errcode_t ocfs2_journal_set_features(journal_superblock_t *jsb,
				     ocfs2_fs_options *features);
extern size_t ocfs2_journal_tag_bytes(journal_superblock_t *jsb);
extern uint64_t ocfs2_journal_tag_block(journal_block_tag_t *tag,
					size_t tag_bytes);

void ocfs2_swap_extent_block_to_cpu(ocfs2_filesys *fs,
				    struct ocfs2_extent_block *eb);
void ocfs2_swap_extent_block_from_cpu(ocfs2_filesys *fs,
				      struct ocfs2_extent_block *eb);
errcode_t ocfs2_read_extent_block(ocfs2_filesys *fs, uint64_t blkno,
       				  char *eb_buf);
errcode_t ocfs2_read_extent_block_nocheck(ocfs2_filesys *fs, uint64_t blkno,
					  char *eb_buf);
errcode_t ocfs2_write_extent_block(ocfs2_filesys *fs, uint64_t blkno,
       				   char *eb_buf);
void ocfs2_swap_refcount_list_to_cpu(ocfs2_filesys *fs, void *obj,
				     struct ocfs2_refcount_list *rl);
void ocfs2_swap_refcount_list_from_cpu(ocfs2_filesys *fs, void *obj,
				       struct ocfs2_refcount_list *rl);
void ocfs2_swap_refcount_block_to_cpu(ocfs2_filesys *fs,
				      struct ocfs2_refcount_block *rb);
void ocfs2_swap_refcount_block_from_cpu(ocfs2_filesys *fs,
					struct ocfs2_refcount_block *rb);
errcode_t ocfs2_read_refcount_block(ocfs2_filesys *fs, uint64_t blkno,
				    char *eb_buf);
errcode_t ocfs2_read_refcount_block_nocheck(ocfs2_filesys *fs, uint64_t blkno,
					    char *eb_buf);
errcode_t ocfs2_write_refcount_block(ocfs2_filesys *fs, uint64_t blkno,
				     char *rb_buf);
errcode_t ocfs2_delete_refcount_block(ocfs2_filesys *fs, uint64_t blkno);
errcode_t ocfs2_new_refcount_block(ocfs2_filesys *fs, uint64_t *blkno,
				   uint64_t root_blkno, uint32_t rf_generation);
errcode_t ocfs2_increase_refcount(ocfs2_filesys *fs, uint64_t ino,
				  uint64_t cpos, uint32_t len);
errcode_t ocfs2_decrease_refcount(ocfs2_filesys *fs,
				  uint64_t ino, uint32_t cpos,
				  uint32_t len, int delete);
errcode_t ocfs2_refcount_cow(ocfs2_cached_inode *cinode,
			     uint32_t cpos, uint32_t write_len,
			     uint32_t max_cpos);
errcode_t ocfs2_refcount_cow_xattr(ocfs2_cached_inode *ci,
				   char *xe_buf,
				   uint64_t xe_blkno,
				   char *value_buf,
				   uint64_t value_blkno,
				   struct ocfs2_xattr_value_root *xv,
				   uint32_t cpos, uint32_t write_len);
errcode_t ocfs2_change_refcount_flag(ocfs2_filesys *fs, uint64_t i_blkno,
				     uint32_t v_cpos, uint32_t clusters,
				     uint64_t p_cpos,
				     int new_flags, int clear_flags);
errcode_t ocfs2_refcount_tree_get_rec(ocfs2_filesys *fs,
				      struct ocfs2_refcount_block *rb,
				      uint32_t phys_cpos,
				      uint64_t *p_blkno,
				      uint32_t *e_cpos,
				      uint32_t *num_clusters);
errcode_t ocfs2_refcount_punch_hole(ocfs2_filesys *fs, uint64_t rf_blkno,
				    uint64_t p_start, uint32_t len);
errcode_t ocfs2_change_refcount(ocfs2_filesys *fs, uint64_t rf_blkno,
				uint64_t p_start, uint32_t len,
				uint32_t refcount);
int ocfs2_get_refcount_rec(ocfs2_filesys *fs,
			   char *ref_root_buf,
			   uint64_t cpos, unsigned int len,
			   struct ocfs2_refcount_rec *ret_rec,
			   int *index,
			   char *ret_buf);
errcode_t ocfs2_create_refcount_tree(ocfs2_filesys *fs, uint64_t *refcount_loc);
errcode_t ocfs2_attach_refcount_tree(ocfs2_filesys *fs,
				     uint64_t ino, uint64_t refcount_loc);
errcode_t ocfs2_detach_refcount_tree(ocfs2_filesys *fs,
				     uint64_t ino, uint64_t refcount_loc);
errcode_t ocfs2_swap_dir_entries_from_cpu(void *buf, uint64_t bytes);
errcode_t ocfs2_swap_dir_entries_to_cpu(void *buf, uint64_t bytes);
void ocfs2_swap_dir_trailer(struct ocfs2_dir_block_trailer *trailer);
errcode_t ocfs2_read_dir_block(ocfs2_filesys *fs, struct ocfs2_dinode *di,
			       uint64_t block, void *buf);
errcode_t ocfs2_write_dir_block(ocfs2_filesys *fs, struct ocfs2_dinode *di,
				uint64_t block, void *buf);
unsigned int ocfs2_dir_trailer_blk_off(ocfs2_filesys *fs);
struct ocfs2_dir_block_trailer *ocfs2_dir_trailer_from_block(ocfs2_filesys *fs,
							     void *data);
int ocfs2_supports_dir_trailer(ocfs2_filesys *fs);
int ocfs2_dir_has_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di);
int ocfs2_skip_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
			   struct ocfs2_dir_entry *de, unsigned long offset);
void ocfs2_init_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
			    uint64_t blkno, void *buf);
void ocfs2_swap_dx_root_to_cpu(ocfs2_filesys *fs,
			       struct ocfs2_dx_root_block *dx_root);
void ocfs2_swap_dx_leaf_to_cpu(struct ocfs2_dx_leaf *dx_leaf);
void ocfs2_swap_dx_root_from_cpu(ocfs2_filesys *fs,
		struct ocfs2_dx_root_block *dx_root);
errcode_t ocfs2_read_dx_root(ocfs2_filesys *fs, uint64_t block,
			     void *buf);
void ocfs2_swap_dx_leaf_from_cpu(struct ocfs2_dx_leaf *dx_leaf);
errcode_t ocfs2_read_dx_leaf(ocfs2_filesys *fs, uint64_t block,
			     void *buf);
int ocfs2_dir_indexed(struct ocfs2_dinode *di);
errcode_t ocfs2_dx_dir_truncate(ocfs2_filesys *fs, uint64_t dir);
errcode_t ocfs2_dir_iterate2(ocfs2_filesys *fs,
			     uint64_t dir,
			     int flags,
			     char *block_buf,
			     int (*func)(uint64_t	dir,
					 int		entry,
					 struct ocfs2_dir_entry *dirent,
					 uint64_t blocknr,
					 int	offset,
					 int	blocksize,
					 char	*buf,
					 void	*priv_data),
			     void *priv_data);
extern errcode_t ocfs2_dir_iterate(ocfs2_filesys *fs, 
				   uint64_t dir,
				   int flags,
				   char *block_buf,
				   int (*func)(struct ocfs2_dir_entry *dirent,
					       uint64_t blocknr,
					       int	offset,
					       int	blocksize,
					       char	*buf,
					       void	*priv_data),
				   void *priv_data);

extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
			struct ocfs2_dinode *dir,
			int flags,
			int (*func)(ocfs2_filesys *fs,
				    struct ocfs2_dx_entry_list *entry_list,
				    struct ocfs2_dx_root_block *dx_root,
				    struct ocfs2_dx_leaf *dx_leaf,
				    void *priv_data),
			void *priv_data);

extern errcode_t ocfs2_dx_frees_iterate(ocfs2_filesys *fs,
			struct ocfs2_dinode *dir,
			struct ocfs2_dx_root_block *dx_root,
			int flags,
			int (*func)(ocfs2_filesys *fs,
				    uint64_t blkno,
				    struct ocfs2_dir_block_trailer *trailer,
				    char *dirblock,
				    void *priv_data),
			void *priv_data);

errcode_t ocfs2_lookup(ocfs2_filesys *fs, uint64_t dir,
		       const char *name, int namelen, char *buf,
		       uint64_t *inode);

errcode_t ocfs2_lookup_system_inode(ocfs2_filesys *fs, int type,
				    int slot_num, uint64_t *blkno);

errcode_t ocfs2_link(ocfs2_filesys *fs, uint64_t dir, const char *name,
		     uint64_t ino, int flags);

errcode_t ocfs2_unlink(ocfs2_filesys *fs, uint64_t dir,
		       const char *name, uint64_t ino, int flags);

errcode_t ocfs2_open_inode_scan(ocfs2_filesys *fs,
				ocfs2_inode_scan **ret_scan);
void ocfs2_close_inode_scan(ocfs2_inode_scan *scan);
errcode_t ocfs2_get_next_inode(ocfs2_inode_scan *scan,
			       uint64_t *blkno, char *inode);
uint64_t ocfs2_get_max_inode_count(ocfs2_inode_scan *scan);

errcode_t ocfs2_open_dir_scan(ocfs2_filesys *fs, uint64_t dir, int flags,
			      ocfs2_dir_scan **ret_scan);
void ocfs2_close_dir_scan(ocfs2_dir_scan *scan);
errcode_t ocfs2_get_next_dir_entry(ocfs2_dir_scan *scan,
				   struct ocfs2_dir_entry *dirent);

errcode_t ocfs2_cluster_bitmap_new(ocfs2_filesys *fs,
				   const char *description,
				   ocfs2_bitmap **ret_bitmap);
errcode_t ocfs2_block_bitmap_new(ocfs2_filesys *fs,
				 const char *description,
				 ocfs2_bitmap **ret_bitmap);
void ocfs2_bitmap_free(ocfs2_bitmap **bitmap);
errcode_t ocfs2_bitmap_set(ocfs2_bitmap *bitmap, uint64_t bitno,
			   int *oldval);
errcode_t ocfs2_bitmap_clear(ocfs2_bitmap *bitmap, uint64_t bitno,
			     int *oldval);
errcode_t ocfs2_bitmap_test(ocfs2_bitmap *bitmap, uint64_t bitno,
			    int *val);
errcode_t ocfs2_bitmap_find_next_set(ocfs2_bitmap *bitmap,
				     uint64_t start, uint64_t *found);
errcode_t ocfs2_bitmap_find_next_clear(ocfs2_bitmap *bitmap,
				       uint64_t start, uint64_t *found);
errcode_t ocfs2_bitmap_read(ocfs2_bitmap *bitmap);
errcode_t ocfs2_bitmap_write(ocfs2_bitmap *bitmap);
uint64_t ocfs2_bitmap_get_set_bits(ocfs2_bitmap *bitmap);
errcode_t ocfs2_bitmap_alloc_range(ocfs2_bitmap *bitmap, uint64_t min,
				   uint64_t len, uint64_t *first_bit,
				   uint64_t *bits_found);
errcode_t ocfs2_bitmap_clear_range(ocfs2_bitmap *bitmap, uint64_t len, 
				   uint64_t first_bit);

errcode_t ocfs2_get_device_size(const char *file, int blocksize,
				uint64_t *retblocks);

errcode_t ocfs2_get_device_sectsize(const char *file, int *sectsize);

errcode_t ocfs2_check_if_mounted(const char *file, int *mount_flags);
errcode_t ocfs2_check_mount_point(const char *device, int *mount_flags,
		                  char *mtpt, int mtlen);

errcode_t ocfs2_read_whole_file(ocfs2_filesys *fs, uint64_t blkno,
				char **buf, int *len);

void ocfs2_swap_disk_heartbeat_block(struct o2hb_disk_heartbeat_block *hb);
errcode_t ocfs2_check_heartbeat(char *device, int *mount_flags,
				struct list_head *nodes_list);

errcode_t ocfs2_check_heartbeats(struct list_head *dev_list, int ignore_local);

errcode_t ocfs2_get_ocfs1_label(char *device, uint8_t *label, uint16_t label_len,
				uint8_t *uuid, uint16_t uuid_len);

void ocfs2_swap_group_desc_from_cpu(ocfs2_filesys *fs,
				    struct ocfs2_group_desc *gd);
void ocfs2_swap_group_desc_to_cpu(ocfs2_filesys *fs,
				  struct ocfs2_group_desc *gd);
errcode_t ocfs2_read_group_desc(ocfs2_filesys *fs, uint64_t blkno,
				char *gd_buf);

errcode_t ocfs2_write_group_desc(ocfs2_filesys *fs, uint64_t blkno,
				 char *gd_buf);
uint64_t ocfs2_get_block_from_group(ocfs2_filesys *fs,
				    struct ocfs2_group_desc *grp,
				    int bpc, int bit_offset);

errcode_t ocfs2_cache_chain_allocator_blocks(ocfs2_filesys *fs,
					     struct ocfs2_dinode *di);
errcode_t ocfs2_chain_iterate(ocfs2_filesys *fs,
			      uint64_t blkno,
			      int (*func)(ocfs2_filesys *fs,
					  uint64_t gd_blkno,
					  int chain_num,
					  void *priv_data),
			      void *priv_data);

errcode_t ocfs2_load_chain_allocator(ocfs2_filesys *fs,
				     ocfs2_cached_inode *cinode);
errcode_t ocfs2_write_chain_allocator(ocfs2_filesys *fs,
				      ocfs2_cached_inode *cinode);
errcode_t ocfs2_chain_alloc(ocfs2_filesys *fs,
			    ocfs2_cached_inode *cinode,
			    uint64_t *gd_blkno,
			    uint16_t *suballoc_bit,
			    uint64_t *bitno);
errcode_t ocfs2_chain_free(ocfs2_filesys *fs,
			   ocfs2_cached_inode *cinode,
			   uint64_t bitno);
errcode_t ocfs2_chain_alloc_range(ocfs2_filesys *fs,
				  ocfs2_cached_inode *cinode,
				  uint64_t min,
				  uint64_t requested,
				  uint64_t *start_bit,
				  uint64_t *bits_found);
errcode_t ocfs2_chain_free_range(ocfs2_filesys *fs,
				 ocfs2_cached_inode *cinode,
				 uint64_t len,
				 uint64_t start_bit);
errcode_t ocfs2_chain_test(ocfs2_filesys *fs,
			   ocfs2_cached_inode *cinode,
			   uint64_t bitno,
			   int *oldval);
errcode_t ocfs2_chain_force_val(ocfs2_filesys *fs,
				ocfs2_cached_inode *cinode,
				uint64_t blkno, 
				int newval,
				int *oldval);
errcode_t ocfs2_chain_add_group(ocfs2_filesys *fs,
				ocfs2_cached_inode *cinode);

errcode_t ocfs2_init_dir(ocfs2_filesys *fs,
			 uint64_t dir,
			 uint64_t parent_dir);

errcode_t ocfs2_expand_dir(ocfs2_filesys *fs,
			   uint64_t dir);

errcode_t ocfs2_test_inode_allocated(ocfs2_filesys *fs, uint64_t blkno,
				     int *is_allocated);
void ocfs2_init_group_desc(ocfs2_filesys *fs,
			   struct ocfs2_group_desc *gd,
			   uint64_t blkno, uint32_t generation,
			   uint64_t parent_inode, uint16_t bits,
			   uint16_t chain, int suballoc);

errcode_t ocfs2_new_dir_block(ocfs2_filesys *fs, uint64_t dir_ino,
			      uint64_t parent_ino, char **block);

errcode_t ocfs2_inode_insert_extent(ocfs2_filesys *fs, uint64_t ino,
				    uint32_t cpos, uint64_t c_blkno,
				    uint32_t clusters, uint16_t flag);
errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
					   uint32_t cpos, uint64_t c_blkno,
					   uint32_t clusters, uint16_t flag);

void ocfs2_dinode_new_extent_list(ocfs2_filesys *fs, struct ocfs2_dinode *di);
void ocfs2_set_inode_data_inline(ocfs2_filesys *fs, struct ocfs2_dinode *di);
errcode_t ocfs2_convert_inline_data_to_extents(ocfs2_cached_inode *ci);
errcode_t ocfs2_new_inode(ocfs2_filesys *fs, uint64_t *ino, int mode);
errcode_t ocfs2_new_system_inode(ocfs2_filesys *fs, uint64_t *ino, int mode, int flags);
errcode_t ocfs2_delete_inode(ocfs2_filesys *fs, uint64_t ino);
errcode_t ocfs2_new_extent_block(ocfs2_filesys *fs, uint64_t *blkno);
errcode_t ocfs2_new_dx_root(ocfs2_filesys *fs, struct ocfs2_dinode *di, uint64_t *dr_blkno);
errcode_t ocfs2_delete_extent_block(ocfs2_filesys *fs, uint64_t blkno);
errcode_t ocfs2_delete_dx_root(ocfs2_filesys *fs, uint64_t dr_blkno);

/*
 * Allocate the blocks and insert them to the file.
 * only i_clusters of dinode will be updated accordingly, i_size not changed.
 */
errcode_t ocfs2_extend_allocation(ocfs2_filesys *fs, uint64_t ino,
				  uint32_t new_clusters);
/* Ditto for cached inode */
errcode_t ocfs2_cached_inode_extend_allocation(ocfs2_cached_inode *ci,
					       uint32_t new_clusters);
/* Extend the file to the new size. No clusters will be allocated. */
errcode_t ocfs2_extend_file(ocfs2_filesys *fs, uint64_t ino, uint64_t new_size);

int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
			      uint32_t cpos, uint32_t len, uint64_t p_blkno);
/* Reserve spaces at "offset" with a "len" in the files. */
errcode_t ocfs2_allocate_unwritten_extents(ocfs2_filesys *fs, uint64_t ino,
					   uint64_t offset, uint64_t len);

errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size);
errcode_t ocfs2_truncate_inline(ocfs2_filesys *fs, uint64_t ino,
				uint64_t new_i_size);
errcode_t ocfs2_truncate_full(ocfs2_filesys *fs, uint64_t ino,
			      uint64_t new_i_size,
			      errcode_t (*free_clusters)(ocfs2_filesys *fs,
							 uint32_t len,
							 uint64_t start,
							 void *free_data),
			      void *free_data);
errcode_t ocfs2_zero_tail_and_truncate(ocfs2_filesys *fs,
				       ocfs2_cached_inode *ci,
				       uint64_t new_size,
				       uint32_t *new_clusters);
errcode_t ocfs2_grow_chain_allocator(ocfs2_filesys *fs,
				     int type,
				     int slot_num,
				     uint32_t num_clusters);
errcode_t ocfs2_new_clusters(ocfs2_filesys *fs,
			     uint32_t min,
			     uint32_t requested,
			     uint64_t *start_blkno,
			     uint32_t *clusters_found);
errcode_t ocfs2_test_cluster_allocated(ocfs2_filesys *fs, uint32_t cpos,
				       int *is_allocated);
errcode_t ocfs2_new_specific_cluster(ocfs2_filesys *fs, uint32_t cpos);
errcode_t ocfs2_free_clusters(ocfs2_filesys *fs,
			      uint32_t len,
			      uint64_t start_blkno);
errcode_t ocfs2_test_clusters(ocfs2_filesys *fs,
			      uint32_t len,
			      uint64_t start_blkno,
			      int test,
			      int *matches);

errcode_t ocfs2_lookup(ocfs2_filesys *fs, uint64_t dir, const char *name,
		       int namelen, char *buf, uint64_t *inode);

errcode_t ocfs2_namei(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
		      const char *name, uint64_t *inode);

errcode_t ocfs2_namei_follow(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
			     const char *name, uint64_t *inode);

errcode_t ocfs2_follow_link(ocfs2_filesys *fs, uint64_t root, uint64_t cwd,
			    uint64_t inode, uint64_t *res_inode);

errcode_t ocfs2_file_read(ocfs2_cached_inode *ci, void *buf, uint32_t count,
			  uint64_t offset, uint32_t *got);

errcode_t ocfs2_file_write(ocfs2_cached_inode *ci, void *buf, uint32_t count,
			   uint64_t offset, uint32_t *wrote);

errcode_t ocfs2_fill_cluster_desc(ocfs2_filesys *fs,
				  struct o2cb_cluster_desc *desc);
errcode_t ocfs2_set_cluster_desc(ocfs2_filesys *fs,
				 struct o2cb_cluster_desc *desc);
errcode_t ocfs2_fill_heartbeat_desc(ocfs2_filesys *fs,
				    struct o2cb_region_desc *desc);

errcode_t ocfs2_lock_down_cluster(ocfs2_filesys *fs);

errcode_t ocfs2_release_cluster(ocfs2_filesys *fs);

errcode_t ocfs2_initialize_dlm(ocfs2_filesys *fs, const char *service);

errcode_t ocfs2_shutdown_dlm(ocfs2_filesys *fs, const char *service);

errcode_t ocfs2_super_lock(ocfs2_filesys *fs);

errcode_t ocfs2_super_unlock(ocfs2_filesys *fs);

errcode_t ocfs2_meta_lock(ocfs2_filesys *fs, ocfs2_cached_inode *inode,
			  enum o2dlm_lock_level level, int flags);

errcode_t ocfs2_meta_unlock(ocfs2_filesys *fs, ocfs2_cached_inode *ci);

/* Quota operations */
static inline int ocfs2_global_dqstr_in_blk(int blocksize)
{
	return (blocksize - OCFS2_QBLK_RESERVED_SPACE -
		sizeof(struct qt_disk_dqdbheader)) /
		sizeof(struct ocfs2_global_disk_dqblk);
}
void ocfs2_swap_quota_header(struct ocfs2_disk_dqheader *header);
void ocfs2_swap_quota_local_info(struct ocfs2_local_disk_dqinfo *info);
void ocfs2_swap_quota_chunk_header(struct ocfs2_local_disk_chunk *chunk);
void ocfs2_swap_quota_global_info(struct ocfs2_global_disk_dqinfo *info);
void ocfs2_swap_quota_global_dqblk(struct ocfs2_global_disk_dqblk *dqblk);
void ocfs2_swap_quota_leaf_block_header(struct qt_disk_dqdbheader *bheader);
errcode_t ocfs2_init_local_quota_file(ocfs2_filesys *fs, int type,
				      uint64_t blkno);
errcode_t ocfs2_init_local_quota_files(ocfs2_filesys *fs, int type);
int ocfs2_qtree_depth(int blocksize);
int ocfs2_qtree_entry_unused(struct ocfs2_global_disk_dqblk *ddquot);
errcode_t ocfs2_init_global_quota_file(ocfs2_filesys *fs, int type);
errcode_t ocfs2_init_fs_quota_info(ocfs2_filesys *fs, int type);
errcode_t ocfs2_read_global_quota_info(ocfs2_filesys *fs, int type);
errcode_t ocfs2_load_fs_quota_info(ocfs2_filesys *fs);
errcode_t ocfs2_write_global_quota_info(ocfs2_filesys *fs, int type);
errcode_t ocfs2_write_dquot(ocfs2_filesys *fs, int type,
			    ocfs2_cached_dquot *dquot);
errcode_t ocfs2_delete_dquot(ocfs2_filesys *fs, int type,
			     ocfs2_cached_dquot *dquot);
errcode_t ocfs2_read_dquot(ocfs2_filesys *fs, int type, qid_t id,
			   ocfs2_cached_dquot **ret_dquot);
errcode_t ocfs2_new_quota_hash(ocfs2_quota_hash **hashp);
errcode_t ocfs2_free_quota_hash(ocfs2_quota_hash *hash);
errcode_t ocfs2_insert_quota_hash(ocfs2_quota_hash *hash,
				  ocfs2_cached_dquot *dquot);
errcode_t ocfs2_remove_quota_hash(ocfs2_quota_hash *hash,
				  ocfs2_cached_dquot *dquot);
errcode_t ocfs2_find_quota_hash(ocfs2_quota_hash *hash, qid_t id,
				ocfs2_cached_dquot **dquotp);
errcode_t ocfs2_find_create_quota_hash(ocfs2_quota_hash *hash, qid_t id,
				       ocfs2_cached_dquot **dquotp);
errcode_t ocfs2_find_read_quota_hash(ocfs2_filesys *fs, ocfs2_quota_hash *hash,
				     int type, qid_t id,
				     ocfs2_cached_dquot **dquotp);
errcode_t ocfs2_compute_quota_usage(ocfs2_filesys *fs,
				    ocfs2_quota_hash *usr_hash,
				    ocfs2_quota_hash *grp_hash);
errcode_t ocfs2_init_quota_change(ocfs2_filesys *fs,
				  ocfs2_quota_hash **usrhash,
				  ocfs2_quota_hash **grphash);
errcode_t ocfs2_finish_quota_change(ocfs2_filesys *fs,
				    ocfs2_quota_hash *usrhash,
				    ocfs2_quota_hash *grphash);
errcode_t ocfs2_apply_quota_change(ocfs2_filesys *fs,
				   ocfs2_quota_hash *usrhash,
				   ocfs2_quota_hash *grphash,
				   uid_t uid, gid_t gid,
				   int64_t space_change,
				   int64_t inode_change);
errcode_t ocfs2_iterate_quota_hash(ocfs2_quota_hash *hash,
				   errcode_t (*f)(ocfs2_cached_dquot *, void *),
				   void *data);
errcode_t ocfs2_write_release_dquots(ocfs2_filesys *fs, int type,
				     ocfs2_quota_hash *hash);

/* Low level */
void ocfs2_swap_slot_map(struct ocfs2_slot_map *sm, int num_slots);
void ocfs2_swap_slot_map_extended(struct ocfs2_slot_map_extended *se,
				  int num_slots);
errcode_t ocfs2_read_slot_map(ocfs2_filesys *fs,
			      int num_slots,
			      struct ocfs2_slot_map **map_ret);
errcode_t ocfs2_read_slot_map_extended(ocfs2_filesys *fs,
				       int num_slots,
				       struct ocfs2_slot_map_extended **map_ret);
errcode_t ocfs2_write_slot_map(ocfs2_filesys *fs,
			       int num_slots,
			       struct ocfs2_slot_map *sm);
errcode_t ocfs2_write_slot_map_extended(ocfs2_filesys *fs,
					int num_slots,
					struct ocfs2_slot_map_extended *se);

/* High level functions for metadata ecc */
void ocfs2_compute_meta_ecc(ocfs2_filesys *fs, void *data,
			    struct ocfs2_block_check *bc);
errcode_t ocfs2_validate_meta_ecc(ocfs2_filesys *fs, void *data,
				  struct ocfs2_block_check *bc);
/* Low level checksum compute functions.  Use the high-level ones. */
extern void ocfs2_block_check_compute(void *data, size_t blocksize,
				      struct ocfs2_block_check *bc);
extern errcode_t ocfs2_block_check_validate(void *data, size_t blocksize,
					    struct ocfs2_block_check *bc);

/* High level */
errcode_t ocfs2_format_slot_map(ocfs2_filesys *fs);
errcode_t ocfs2_load_slot_map(ocfs2_filesys *fs,
			      struct ocfs2_slot_map_data **data_ret);
errcode_t ocfs2_store_slot_map(ocfs2_filesys *fs,
			       struct ocfs2_slot_map_data *md);

enum ocfs2_lock_type ocfs2_get_lock_type(char c);

char *ocfs2_get_lock_type_string(enum ocfs2_lock_type type);

errcode_t ocfs2_encode_lockres(enum ocfs2_lock_type type, uint64_t blkno,
			       uint32_t generation, uint64_t parent,
			       char *lockres);

errcode_t ocfs2_decode_lockres(char *lockres, enum ocfs2_lock_type *type,
			       uint64_t *blkno, uint32_t *generation,
			       uint64_t *parent);

errcode_t ocfs2_printable_lockres(char *lockres, char *name, int len);

/* write the superblock at the specific block. */
errcode_t ocfs2_write_backup_super(ocfs2_filesys *fs, uint64_t blkno);

/* Get the blkno according to the file system info.
 * The unused ones, depending on the volume size, are zeroed.
 * Return the length of the block array.
 */
int ocfs2_get_backup_super_offsets(ocfs2_filesys *fs,
				   uint64_t *blocks, size_t len);

/* This function will get the superblock pointed to by fs and copy it to
 * the blocks. But first it will ensure all the appropriate clusters are free.
 * If not, it will error out with ENOSPC. If free, it will set bits for all
 * the clusters, zero the clusters and write the backup sb.
 * In case of updating, it will override the backup blocks with the newest
 * superblock information.
 */
errcode_t ocfs2_set_backup_super_list(ocfs2_filesys *fs,
				      uint64_t *blocks, size_t len);
/* Conversely, this clears all the allocator bits associated with the
 * specified backup superblocks */
errcode_t ocfs2_clear_backup_super_list(ocfs2_filesys *fs,
					uint64_t *blocks, size_t len);

/* Refresh the backup superblock information */
errcode_t ocfs2_refresh_backup_supers(ocfs2_filesys *fs);
/* Refresh a specific list of backup superblocks */
errcode_t ocfs2_refresh_backup_super_list(ocfs2_filesys *fs,
					  uint64_t *blocks, size_t len);

errcode_t ocfs2_read_backup_super(ocfs2_filesys *fs, int backup, char *sbbuf);

/* get the virtual offset of the last allocated cluster. */
errcode_t ocfs2_get_last_cluster_offset(ocfs2_filesys *fs,
					struct ocfs2_dinode *di,
					uint32_t *v_cluster);

/* Filesystem features */
enum ocfs2_feature_levels {
	OCFS2_FEATURE_LEVEL_DEFAULT = 0,
	OCFS2_FEATURE_LEVEL_MAX_COMPAT,
	OCFS2_FEATURE_LEVEL_MAX_FEATURES,
};

errcode_t ocfs2_snprint_feature_flags(char *str, size_t size,
				      ocfs2_fs_options *flags);
errcode_t ocfs2_snprint_tunefs_flags(char *str, size_t size, uint16_t flags);
errcode_t ocfs2_snprint_extent_flags(char *str, size_t size, uint8_t flags);
errcode_t ocfs2_snprint_refcount_flags(char *str, size_t size, uint8_t flags);
errcode_t ocfs2_snprint_cluster_o2cb_flags(char *str, size_t size,
					   uint8_t flags);
errcode_t ocfs2_parse_feature(const char *opts,
			      ocfs2_fs_options *feature_flags,
			      ocfs2_fs_options *reverse_flags);

errcode_t ocfs2_parse_feature_level(const char *typestr,
				    enum ocfs2_feature_levels *level);

errcode_t ocfs2_merge_feature_flags_with_level(ocfs2_fs_options *dest,
					       enum ocfs2_mkfs_types fstype,
					       int level,
					       ocfs2_fs_options *feature_set,
					       ocfs2_fs_options *reverse_set);

/*
 * Get a callback with each feature in feature_set in order.  This will
 * calculate the dependencies of each feature in feature_set, then call func
 * once per feature, with only that feature passed to func.
 */
void ocfs2_feature_foreach(ocfs2_fs_options *feature_set,
			   int (*func)(ocfs2_fs_options *feature,
				       void *user_data),
			   void *user_data);
/* The reverse function.  It will call the features in reverse order. */
void ocfs2_feature_reverse_foreach(ocfs2_fs_options *reverse_set,
				   int (*func)(ocfs2_fs_options *feature,
					       void *user_data),
				   void *user_data);


/* These are deprecated names - don't use them */
int ocfs2_get_backup_super_offset(ocfs2_filesys *fs,
				  uint64_t *blocks, size_t len);
errcode_t ocfs2_refresh_backup_super(ocfs2_filesys *fs,
				     uint64_t *blocks, size_t len);
errcode_t ocfs2_set_backup_super(ocfs2_filesys *fs,
				 uint64_t *blocks, size_t len);



/* 
 * ${foo}_to_${bar} is a floor function.  blocks_to_clusters will
 * returns the cluster that contains a block, not the number of clusters
 * that hold a given number of blocks.
 *
 * ${foo}_in_${bar} is a ceiling function.  clusters_in_blocks will give
 * the number of clusters needed to hold a given number of blocks.
 *
 * These functions return UINTxx_MAX when they overflow, but UINTxx_MAX
 * cannot be used to check overflow.  UINTxx_MAX is a valid value in much
 * of ocfs2.  The caller is responsible for preventing overflow before
 * using these functions.
 */

static inline uint64_t ocfs2_clusters_to_blocks(ocfs2_filesys *fs,
						uint32_t clusters)
{
	int c_to_b_bits =
		OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
		OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;

	return (uint64_t)clusters << c_to_b_bits;
}

static inline uint32_t ocfs2_blocks_to_clusters(ocfs2_filesys *fs,
						uint64_t blocks)
{
	int b_to_c_bits =
		OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
		OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
	uint64_t ret = blocks >> b_to_c_bits;

	if (ret > UINT32_MAX)
		ret = UINT32_MAX;

	return (uint32_t)ret;
}

static inline uint64_t ocfs2_clusters_to_bytes(ocfs2_filesys *fs,
					       uint32_t clusters)
{
	uint64_t ret = clusters;

	ret = ret << OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
	if (ret < clusters)
		ret = UINT64_MAX;

	return ret;
}

static inline uint32_t ocfs2_bytes_to_clusters(ocfs2_filesys *fs,
					       uint64_t bytes)
{
	uint64_t ret =
		bytes >> OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;

	if (ret > UINT32_MAX)
		ret = UINT32_MAX;

	return (uint32_t)ret;
}

static inline uint64_t ocfs2_block_to_cluster_start(ocfs2_filesys *fs,
						    uint64_t blocks)
{
	int c_to_b_bits =
		OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
		OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
	uint32_t clusters;

	clusters = ocfs2_blocks_to_clusters(fs, blocks);
	return (uint64_t)clusters << c_to_b_bits;
}

static inline uint64_t ocfs2_blocks_to_bytes(ocfs2_filesys *fs,
					     uint64_t blocks)
{
	uint64_t ret =
		blocks << OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;

	if (ret < blocks)
		ret = UINT64_MAX;

	return ret;
}

static inline uint64_t ocfs2_bytes_to_blocks(ocfs2_filesys *fs,
					     uint64_t bytes)
{
	return bytes >> OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
}

static inline uint32_t ocfs2_clusters_in_blocks(ocfs2_filesys *fs, 
						uint64_t blocks)
{
	int c_to_b_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
		          OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
	uint64_t ret = blocks + ((1 << c_to_b_bits) - 1); 

	if (ret < blocks) /* deal with wrapping */
		ret = UINT64_MAX;

	ret = ret >> c_to_b_bits;
	if (ret > UINT32_MAX)
		ret = UINT32_MAX;

	return (uint32_t)ret;
}

static inline uint32_t ocfs2_clusters_in_bytes(ocfs2_filesys *fs,
					       uint64_t bytes)
{
	uint64_t ret = bytes + fs->fs_clustersize - 1;

	if (ret < bytes) /* deal with wrapping */
		ret = UINT64_MAX;

	ret = ret >> OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
	if (ret > UINT32_MAX)
		ret = UINT32_MAX;

	return (uint32_t)ret;
}

static inline uint64_t ocfs2_blocks_in_bytes(ocfs2_filesys *fs,
					     uint64_t bytes)
{
	uint64_t ret = bytes + fs->fs_blocksize - 1;

	if (ret < bytes) /* deal with wrapping */
		return UINT64_MAX;

	return ret >> OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
}

static inline uint64_t ocfs2_align_bytes_to_clusters(ocfs2_filesys *fs,
						     uint64_t bytes)
{
	uint32_t clusters;

	clusters = ocfs2_clusters_in_bytes(fs, bytes);
	return (uint64_t)clusters <<
			OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
}

static inline uint64_t ocfs2_align_bytes_to_blocks(ocfs2_filesys *fs,
						   uint64_t bytes)
{
	uint64_t blocks;

	blocks = ocfs2_blocks_in_bytes(fs, bytes);
	return blocks << OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
}

/* given a cluster offset, calculate which block group it belongs to
 * and return that block offset. */
static inline uint64_t ocfs2_which_cluster_group(ocfs2_filesys *fs,
						 uint16_t cpg,
						 uint32_t cluster)
{
	struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super);
	uint32_t group_no;

	group_no = cluster / cpg;
	if (!group_no)
		return sb->s_first_cluster_group;
	return ocfs2_clusters_to_blocks(fs, group_no * cpg);
}

static inline int ocfs2_block_out_of_range(ocfs2_filesys *fs, uint64_t block)
{
	return (block < OCFS2_SUPER_BLOCK_BLKNO) || (block > fs->fs_blocks);
}

struct ocfs2_cluster_group_sizes {
	uint16_t	cgs_cpg;
	uint16_t	cgs_tail_group_bits;
	uint32_t	cgs_cluster_groups;
};
static inline void ocfs2_calc_cluster_groups(uint64_t clusters, 
					     uint64_t blocksize,
				     struct ocfs2_cluster_group_sizes *cgs)
{
	uint16_t max_bits = 8 * ocfs2_group_bitmap_size(blocksize, 0, 0);

	cgs->cgs_cpg = max_bits;
	if (max_bits > clusters)
		cgs->cgs_cpg = clusters;

	cgs->cgs_cluster_groups = (clusters + cgs->cgs_cpg - 1) / 
				  cgs->cgs_cpg;

	cgs->cgs_tail_group_bits = clusters % cgs->cgs_cpg;
	if (cgs->cgs_tail_group_bits == 0)
		cgs->cgs_tail_group_bits = cgs->cgs_cpg;
}

/*
 * This is only valid for leaf nodes, which are the only ones that can
 * have empty extents anyway.
 */
static inline int ocfs2_is_empty_extent(struct ocfs2_extent_rec *rec)
{
	return !rec->e_leaf_clusters;
}

/*
 * Helper function to look at the # of clusters in an extent record.
 */
static inline uint32_t ocfs2_rec_clusters(uint16_t tree_depth,
					  struct ocfs2_extent_rec *rec)
{
	/*
	 * Cluster count in extent records is slightly different
	 * between interior nodes and leaf nodes. This is to support
	 * unwritten extents which need a flags field in leaf node
	 * records, thus shrinking the available space for a clusters
	 * field.
	 */
	if (tree_depth)
		return rec->e_int_clusters;
	else
		return rec->e_leaf_clusters;
}

static inline void ocfs2_set_rec_clusters(uint16_t tree_depth,
					  struct ocfs2_extent_rec *rec,
					  uint32_t clusters)
{
	if (tree_depth)
		rec->e_int_clusters = clusters;
	else
		rec->e_leaf_clusters = clusters;
}

static inline int ocfs2_sparse_alloc(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
		return 1;
	return 0;
}

static inline int ocfs2_clusterinfo_valid(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat &
	    (OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK |
	     OCFS2_FEATURE_INCOMPAT_CLUSTERINFO))
		return 1;
	return 0;
}

static inline int ocfs2_userspace_stack(struct ocfs2_super_block *osb)
{
	if (ocfs2_clusterinfo_valid(osb) &&
	    memcmp(osb->s_cluster_info.ci_stack, OCFS2_CLASSIC_CLUSTER_STACK,
		   OCFS2_STACK_LABEL_LEN))
		return 1;
	return 0;
}

static inline int ocfs2_o2cb_stack(struct ocfs2_super_block *osb)
{
	if (ocfs2_clusterinfo_valid(osb) &&
	    !memcmp(osb->s_cluster_info.ci_stack, OCFS2_CLASSIC_CLUSTER_STACK,
		    OCFS2_STACK_LABEL_LEN))
		return 1;
	return 0;
}

static inline int ocfs2_cluster_o2cb_global_heartbeat(struct ocfs2_super_block *osb)
{
	if (!ocfs2_o2cb_stack(osb))
		return 0;

	return osb->s_cluster_info.ci_stackflags &
		OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT;
}

static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super_block *osb)
{
	/*
	 * Support for sparse files is a pre-requisite
	 */
	if (!ocfs2_sparse_alloc(osb))
		return 0;

	if (osb->s_feature_ro_compat & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
		return 1;
	return 0;
}

static inline int ocfs2_supports_append_dio(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_APPEND_DIO)
		return 1;
	return 0;
}

static inline int ocfs2_uses_extended_slot_map(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP)
		return 1;
	return 0;
}

static inline int ocfs2_support_inline_data(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INLINE_DATA)
		return 1;
	return 0;
}

static inline int ocfs2_meta_ecc(struct ocfs2_super_block *osb)
{
	if (OCFS2_HAS_INCOMPAT_FEATURE(osb,
				       OCFS2_FEATURE_INCOMPAT_META_ECC))
		return 1;
	return 0;
}

static inline int ocfs2_support_xattr(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_XATTR)
		return 1;
	return 0;
}

static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super_block *osb)
{
	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS)
		return 1;
	return 0;
}

/*
 * When we're swapping some of our disk structures, a garbage count
 * can send us past the edge of a block buffer.  This function guards
 * against that.  It returns true if the element would walk off then end
 * of the block buffer.
 */
static inline int ocfs2_swap_barrier(ocfs2_filesys *fs, void *block_buffer,
				     void *element, size_t element_size)
{
	char *limit, *end;

	limit = block_buffer;
	limit += fs->fs_blocksize;

	end = element;
	end += element_size;

	return end > limit;
}


static inline int ocfs2_refcount_tree(struct ocfs2_super_block *osb)
{
	if (OCFS2_HAS_INCOMPAT_FEATURE(osb,
				       OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE))
		return 1;
	return 0;
}

static inline int ocfs2_supports_discontig_bg(struct ocfs2_super_block *osb)
{
	if (OCFS2_HAS_INCOMPAT_FEATURE(osb,
					OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG))
		return 1;
	return 0;
}

/*
 * shamelessly lifted from the kernel
 *
 * min()/max() macros that also do
 * strict type-checking.. See the
 * "unnecessary" pointer comparison.
 */
#define ocfs2_min(x,y) ({ \
	const typeof(x) _x = (x);       \
	const typeof(y) _y = (y);       \
	(void) (&_x == &_y);            \
	_x < _y ? _x : _y; })
                                                                                
#define ocfs2_max(x,y) ({ \
	const typeof(x) _x = (x);       \
	const typeof(y) _y = (y);       \
	(void) (&_x == &_y);            \
	_x > _y ? _x : _y; })

/* lifted from the kernel. include/linux/kernel.h */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

/*
 * DEPRECATED: Extent/block iterate functions.
 *
 * Do not use these for reading/writing regular files - they don't properly
 * handle holes or inline data.
 */

/* Return flags for the extent iterator functions */
#define OCFS2_EXTENT_CHANGED	0x01
#define OCFS2_EXTENT_ABORT	0x02
#define OCFS2_EXTENT_ERROR	0x04

/*
 * Extent iterate flags
 *
 * OCFS2_EXTENT_FLAG_APPEND indicates that the iterator function should
 * be called on extents past the leaf next_free_rec.  This is used by
 * ocfs2_expand_dir() to add a new extent to a directory (via
 * OCFS2_BLOCK_FLAG_APPEND and the block iteration functions).
 *
 * OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE indicates that the iterator
 * function for tree_depth > 0 records (ocfs2_extent_blocks, iow)
 * should be called after all of the extents contained in the
 * extent_block are processed.  This is useful if you are going to be
 * deallocating extents.
 *
 * OCFS2_EXTENT_FLAG_DATA_ONLY indicates that the iterator function
 * should be called for data extents (depth == 0) only.
 */
#define OCFS2_EXTENT_FLAG_APPEND		0x01
#define OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE	0x02
#define OCFS2_EXTENT_FLAG_DATA_ONLY		0x04


/* Return flags for the block iterator functions */
#define OCFS2_BLOCK_CHANGED	0x01
#define OCFS2_BLOCK_ABORT	0x02
#define OCFS2_BLOCK_ERROR	0x04


#define OCFS2_IS_VALID_DX_ROOT(ptr)					\
		(!strcmp((char *)(ptr)->dr_signature, OCFS2_DX_ROOT_SIGNATURE))

/*
 * Block iterate flags
 *
 * In OCFS2, block iteration runs through the blocks contained in an
 * inode's data extents.  As such, "DATA_ONLY" and "DEPTH_TRAVERSE"
 * can't really apply.
 *
 * OCFS2_BLOCK_FLAG_APPEND is as OCFS2_EXTENT_FLAG_APPEND, except on a
 * blocksize basis.  This may mean that the underlying extent already
 * contains the space for a new block, and i_size is updated
 * accordingly.
 */
#define OCFS2_BLOCK_FLAG_APPEND		0x01

errcode_t ocfs2_extent_iterate(ocfs2_filesys *fs,
			       uint64_t blkno,
			       int flags,
			       char *block_buf,
			       int (*func)(ocfs2_filesys *fs,
					   struct ocfs2_extent_rec *rec,
					   int tree_depth,
					   uint32_t ccount,
					   uint64_t ref_blkno,
					   int ref_recno,
					   void *priv_data),
			       void *priv_data);
errcode_t ocfs2_extent_iterate_inode(ocfs2_filesys *fs,
				     struct ocfs2_dinode *inode,
				     int flags,
				     char *block_buf,
				     int (*func)(ocfs2_filesys *fs,
					         struct ocfs2_extent_rec *rec,
					         int tree_depth,
					         uint32_t ccount,
					         uint64_t ref_blkno,
					         int ref_recno,
					         void *priv_data),
					         void *priv_data);
errcode_t ocfs2_extent_iterate_dx_root(ocfs2_filesys *fs,
				       struct ocfs2_dx_root_block *dx_root,
				       int flags,
				       char *block_buf,
				       int (*func)(ocfs2_filesys *fs,
						   struct ocfs2_extent_rec *rec,
						   int tree_depth,
						   uint32_t ccount,
						   uint64_t ref_blkno,
						   int ref_recno,
						   void *priv_data),
				       void *priv_data);

errcode_t ocfs2_block_iterate(ocfs2_filesys *fs,
			      uint64_t blkno,
			      int flags,
			      int (*func)(ocfs2_filesys *fs,
					  uint64_t blkno,
					  uint64_t bcount,
					  uint16_t ext_flags,
					  void *priv_data),
			      void *priv_data);
errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
				    struct ocfs2_dinode *inode,
				    int flags,
				    int (*func)(ocfs2_filesys *fs,
						uint64_t blkno,
						uint64_t bcount,
						uint16_t ext_flags,
						void *priv_data),
				    void *priv_data);

#define OCFS2_XATTR_ABORT	0x01
#define OCFS2_XATTR_ERROR	0x02
errcode_t ocfs2_xattr_iterate(ocfs2_cached_inode *ci,
			      int (*func)(ocfs2_cached_inode *ci,
					  char *xe_buf,
					  uint64_t xe_blkno,
					  struct ocfs2_xattr_entry *xe,
					  char *value_buf,
					  uint64_t value_blkno,
					  void *value,
					  int in_bucket,
					  void *priv_data),
			      void *priv_data);

uint32_t ocfs2_xattr_uuid_hash(unsigned char *uuid);
uint32_t ocfs2_xattr_name_hash(uint32_t uuid_hash, const char *name,
			       int name_len);
int ocfs2_tree_find_leaf(ocfs2_filesys *fs, struct ocfs2_extent_list *el,
			 uint64_t el_blkno, char *el_blk,
			 uint32_t cpos, char **leaf_buf);
uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs);
uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs);
/* See ocfs2_swap_extent_list() for a discussion of obj */
void ocfs2_swap_xattrs_to_cpu(ocfs2_filesys *fs, void *obj,
			      struct ocfs2_xattr_header *xh);
void ocfs2_swap_xattrs_from_cpu(ocfs2_filesys *fs, void *obj,
				struct ocfs2_xattr_header *xh);
void ocfs2_swap_xattr_block_to_cpu(ocfs2_filesys *fs,
				   struct ocfs2_xattr_block *xb);
void ocfs2_swap_xattr_block_from_cpu(ocfs2_filesys *fs,
				     struct ocfs2_xattr_block *xb);
errcode_t ocfs2_read_xattr_block(ocfs2_filesys *fs,
				 uint64_t blkno,
				 char *xb_buf);
errcode_t ocfs2_write_xattr_block(ocfs2_filesys *fs,
				  uint64_t blkno,
				  char *xb_buf);
errcode_t ocfs2_xattr_get_rec(ocfs2_filesys *fs,
			      struct ocfs2_xattr_block *xb,
			      uint32_t name_hash,
			      uint64_t *p_blkno,
			      uint32_t *e_cpos,
			      uint32_t *num_clusters);
uint16_t ocfs2_xattr_value_real_size(uint16_t name_len, uint16_t value_len);
uint16_t ocfs2_xattr_min_offset(struct ocfs2_xattr_header *xh, uint16_t size);
uint16_t ocfs2_xattr_name_value_len(struct ocfs2_xattr_header *xh);
errcode_t ocfs2_read_xattr_bucket(ocfs2_filesys *fs,
				  uint64_t blkno,
				  char *bucket_buf);
errcode_t ocfs2_write_xattr_bucket(ocfs2_filesys *fs,
				   uint64_t blkno,
				   char *bucket_buf);
errcode_t ocfs2_xattr_value_truncate(ocfs2_filesys *fs, uint64_t ino,
				     struct ocfs2_xattr_value_root *xv);
errcode_t ocfs2_xattr_tree_truncate(ocfs2_filesys *fs,
				    struct ocfs2_xattr_tree_root *xt);
errcode_t ocfs2_extent_iterate_xattr(ocfs2_filesys *fs,
				     struct ocfs2_extent_list *el,
				     uint64_t last_eb_blk,
				     int flags,
				     int (*func)(ocfs2_filesys *fs,
						struct ocfs2_extent_rec *rec,
						int tree_depth,
						uint32_t ccount,
						uint64_t ref_blkno,
						int ref_recno,
						void *priv_data),
				     void *priv_data,
				     int *changed);
errcode_t ocfs2_delete_xattr_block(ocfs2_filesys *fs, uint64_t blkno);
errcode_t ocfs2_dir_indexed_tree_truncate(ocfs2_filesys *fs,
					struct ocfs2_dx_root_block *dx_root);
errcode_t ocfs2_write_dx_root(ocfs2_filesys *fs, uint64_t block, char *buf);
errcode_t ocfs2_write_dx_leaf(ocfs2_filesys *fs, uint64_t block, void *buf);
errcode_t ocfs2_dx_dir_build(ocfs2_filesys *fs, uint64_t dir);
errcode_t ocfs2_dx_dir_insert_entry(ocfs2_filesys *fs, uint64_t dir, const char *name,
					uint64_t ino, uint64_t blkno);
int ocfs2_search_dirblock(ocfs2_filesys *fs, char *dir_buf,
			const char *name, int namelen, unsigned int bytes,
			struct ocfs2_dir_entry **res_dir);
void ocfs2_dx_dir_name_hash(ocfs2_filesys *fs, const char *name,
			int len, struct ocfs2_dx_hinfo *hinfo);
errcode_t ocfs2_dx_dir_lookup(ocfs2_filesys *fs, struct ocfs2_dx_root_block *dx_root,
			struct ocfs2_extent_list *el, struct ocfs2_dx_hinfo *hinfo,
			uint32_t *ret_cpos, uint64_t *ret_phys_blkno);
errcode_t ocfs2_dx_dir_search(ocfs2_filesys *fs, const char *name,
			int namelen, struct ocfs2_dx_root_block *dx_root,
			struct ocfs2_dir_lookup_result *res);
void release_lookup_res(struct ocfs2_dir_lookup_result *res);
int ocfs2_find_max_rec_len(ocfs2_filesys *fs, char *buf);
void ocfs2_dx_list_remove_entry(struct ocfs2_dx_entry_list *entry_list, int index);
int ocfs2_is_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di, unsigned long de_off);
/* routines for block check */
uint32_t ocfs2_hamming_encode(uint32_t parity, void *data,
				unsigned int d, unsigned int nr);
uint32_t ocfs2_hamming_encode_block(void *data, unsigned int d);
void ocfs2_hamming_fix(void *data, unsigned int d,
			unsigned int nr, unsigned int fix);
void ocfs2_hamming_fix_block(void *data, unsigned int d, unsigned int fix);
uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len);

enum ocfs2_block_type ocfs2_detect_block(char *buf);
void ocfs2_swap_block_from_cpu(ocfs2_filesys *fs, void *block);
void ocfs2_swap_block_to_cpu(ocfs2_filesys *fs, void *block);

#endif  /* _FILESYS_H */