diff options
Diffstat (limited to 'fs/xfs/libxfs')
27 files changed, 5541 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h new file mode 100644 index 000000000000..6e247a99f5db --- /dev/null +++ b/fs/xfs/libxfs/xfs_ag.h | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_AG_H__ | ||
19 | #define __XFS_AG_H__ | ||
20 | |||
21 | /* | ||
22 | * Allocation group header | ||
23 | * This is divided into three structures, placed in sequential 512-byte | ||
24 | * buffers after a copy of the superblock (also in a 512-byte buffer). | ||
25 | */ | ||
26 | |||
27 | struct xfs_buf; | ||
28 | struct xfs_mount; | ||
29 | struct xfs_trans; | ||
30 | |||
31 | #define XFS_AGF_MAGIC 0x58414746 /* 'XAGF' */ | ||
32 | #define XFS_AGI_MAGIC 0x58414749 /* 'XAGI' */ | ||
33 | #define XFS_AGFL_MAGIC 0x5841464c /* 'XAFL' */ | ||
34 | #define XFS_AGF_VERSION 1 | ||
35 | #define XFS_AGI_VERSION 1 | ||
36 | |||
37 | #define XFS_AGF_GOOD_VERSION(v) ((v) == XFS_AGF_VERSION) | ||
38 | #define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION) | ||
39 | |||
40 | /* | ||
41 | * Btree number 0 is bno, 1 is cnt. This value gives the size of the | ||
42 | * arrays below. | ||
43 | */ | ||
44 | #define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1) | ||
45 | |||
46 | /* | ||
47 | * The second word of agf_levels in the first a.g. overlaps the EFS | ||
48 | * superblock's magic number. Since the magic numbers valid for EFS | ||
49 | * are > 64k, our value cannot be confused for an EFS superblock's. | ||
50 | */ | ||
51 | |||
52 | typedef struct xfs_agf { | ||
53 | /* | ||
54 | * Common allocation group header information | ||
55 | */ | ||
56 | __be32 agf_magicnum; /* magic number == XFS_AGF_MAGIC */ | ||
57 | __be32 agf_versionnum; /* header version == XFS_AGF_VERSION */ | ||
58 | __be32 agf_seqno; /* sequence # starting from 0 */ | ||
59 | __be32 agf_length; /* size in blocks of a.g. */ | ||
60 | /* | ||
61 | * Freespace information | ||
62 | */ | ||
63 | __be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */ | ||
64 | __be32 agf_spare0; /* spare field */ | ||
65 | __be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */ | ||
66 | __be32 agf_spare1; /* spare field */ | ||
67 | |||
68 | __be32 agf_flfirst; /* first freelist block's index */ | ||
69 | __be32 agf_fllast; /* last freelist block's index */ | ||
70 | __be32 agf_flcount; /* count of blocks in freelist */ | ||
71 | __be32 agf_freeblks; /* total free blocks */ | ||
72 | |||
73 | __be32 agf_longest; /* longest free space */ | ||
74 | __be32 agf_btreeblks; /* # of blocks held in AGF btrees */ | ||
75 | uuid_t agf_uuid; /* uuid of filesystem */ | ||
76 | |||
77 | /* | ||
78 | * reserve some contiguous space for future logged fields before we add | ||
79 | * the unlogged fields. This makes the range logging via flags and | ||
80 | * structure offsets much simpler. | ||
81 | */ | ||
82 | __be64 agf_spare64[16]; | ||
83 | |||
84 | /* unlogged fields, written during buffer writeback. */ | ||
85 | __be64 agf_lsn; /* last write sequence */ | ||
86 | __be32 agf_crc; /* crc of agf sector */ | ||
87 | __be32 agf_spare2; | ||
88 | |||
89 | /* structure must be padded to 64 bit alignment */ | ||
90 | } xfs_agf_t; | ||
91 | |||
92 | #define XFS_AGF_CRC_OFF offsetof(struct xfs_agf, agf_crc) | ||
93 | |||
94 | #define XFS_AGF_MAGICNUM 0x00000001 | ||
95 | #define XFS_AGF_VERSIONNUM 0x00000002 | ||
96 | #define XFS_AGF_SEQNO 0x00000004 | ||
97 | #define XFS_AGF_LENGTH 0x00000008 | ||
98 | #define XFS_AGF_ROOTS 0x00000010 | ||
99 | #define XFS_AGF_LEVELS 0x00000020 | ||
100 | #define XFS_AGF_FLFIRST 0x00000040 | ||
101 | #define XFS_AGF_FLLAST 0x00000080 | ||
102 | #define XFS_AGF_FLCOUNT 0x00000100 | ||
103 | #define XFS_AGF_FREEBLKS 0x00000200 | ||
104 | #define XFS_AGF_LONGEST 0x00000400 | ||
105 | #define XFS_AGF_BTREEBLKS 0x00000800 | ||
106 | #define XFS_AGF_UUID 0x00001000 | ||
107 | #define XFS_AGF_NUM_BITS 13 | ||
108 | #define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1) | ||
109 | |||
110 | #define XFS_AGF_FLAGS \ | ||
111 | { XFS_AGF_MAGICNUM, "MAGICNUM" }, \ | ||
112 | { XFS_AGF_VERSIONNUM, "VERSIONNUM" }, \ | ||
113 | { XFS_AGF_SEQNO, "SEQNO" }, \ | ||
114 | { XFS_AGF_LENGTH, "LENGTH" }, \ | ||
115 | { XFS_AGF_ROOTS, "ROOTS" }, \ | ||
116 | { XFS_AGF_LEVELS, "LEVELS" }, \ | ||
117 | { XFS_AGF_FLFIRST, "FLFIRST" }, \ | ||
118 | { XFS_AGF_FLLAST, "FLLAST" }, \ | ||
119 | { XFS_AGF_FLCOUNT, "FLCOUNT" }, \ | ||
120 | { XFS_AGF_FREEBLKS, "FREEBLKS" }, \ | ||
121 | { XFS_AGF_LONGEST, "LONGEST" }, \ | ||
122 | { XFS_AGF_BTREEBLKS, "BTREEBLKS" }, \ | ||
123 | { XFS_AGF_UUID, "UUID" } | ||
124 | |||
125 | /* disk block (xfs_daddr_t) in the AG */ | ||
126 | #define XFS_AGF_DADDR(mp) ((xfs_daddr_t)(1 << (mp)->m_sectbb_log)) | ||
127 | #define XFS_AGF_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp)) | ||
128 | #define XFS_BUF_TO_AGF(bp) ((xfs_agf_t *)((bp)->b_addr)) | ||
129 | |||
130 | extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, | ||
131 | xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); | ||
132 | |||
133 | /* | ||
134 | * Size of the unlinked inode hash table in the agi. | ||
135 | */ | ||
136 | #define XFS_AGI_UNLINKED_BUCKETS 64 | ||
137 | |||
138 | typedef struct xfs_agi { | ||
139 | /* | ||
140 | * Common allocation group header information | ||
141 | */ | ||
142 | __be32 agi_magicnum; /* magic number == XFS_AGI_MAGIC */ | ||
143 | __be32 agi_versionnum; /* header version == XFS_AGI_VERSION */ | ||
144 | __be32 agi_seqno; /* sequence # starting from 0 */ | ||
145 | __be32 agi_length; /* size in blocks of a.g. */ | ||
146 | /* | ||
147 | * Inode information | ||
148 | * Inodes are mapped by interpreting the inode number, so no | ||
149 | * mapping data is needed here. | ||
150 | */ | ||
151 | __be32 agi_count; /* count of allocated inodes */ | ||
152 | __be32 agi_root; /* root of inode btree */ | ||
153 | __be32 agi_level; /* levels in inode btree */ | ||
154 | __be32 agi_freecount; /* number of free inodes */ | ||
155 | |||
156 | __be32 agi_newino; /* new inode just allocated */ | ||
157 | __be32 agi_dirino; /* last directory inode chunk */ | ||
158 | /* | ||
159 | * Hash table of inodes which have been unlinked but are | ||
160 | * still being referenced. | ||
161 | */ | ||
162 | __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS]; | ||
163 | /* | ||
164 | * This marks the end of logging region 1 and start of logging region 2. | ||
165 | */ | ||
166 | uuid_t agi_uuid; /* uuid of filesystem */ | ||
167 | __be32 agi_crc; /* crc of agi sector */ | ||
168 | __be32 agi_pad32; | ||
169 | __be64 agi_lsn; /* last write sequence */ | ||
170 | |||
171 | __be32 agi_free_root; /* root of the free inode btree */ | ||
172 | __be32 agi_free_level;/* levels in free inode btree */ | ||
173 | |||
174 | /* structure must be padded to 64 bit alignment */ | ||
175 | } xfs_agi_t; | ||
176 | |||
177 | #define XFS_AGI_CRC_OFF offsetof(struct xfs_agi, agi_crc) | ||
178 | |||
179 | #define XFS_AGI_MAGICNUM (1 << 0) | ||
180 | #define XFS_AGI_VERSIONNUM (1 << 1) | ||
181 | #define XFS_AGI_SEQNO (1 << 2) | ||
182 | #define XFS_AGI_LENGTH (1 << 3) | ||
183 | #define XFS_AGI_COUNT (1 << 4) | ||
184 | #define XFS_AGI_ROOT (1 << 5) | ||
185 | #define XFS_AGI_LEVEL (1 << 6) | ||
186 | #define XFS_AGI_FREECOUNT (1 << 7) | ||
187 | #define XFS_AGI_NEWINO (1 << 8) | ||
188 | #define XFS_AGI_DIRINO (1 << 9) | ||
189 | #define XFS_AGI_UNLINKED (1 << 10) | ||
190 | #define XFS_AGI_NUM_BITS_R1 11 /* end of the 1st agi logging region */ | ||
191 | #define XFS_AGI_ALL_BITS_R1 ((1 << XFS_AGI_NUM_BITS_R1) - 1) | ||
192 | #define XFS_AGI_FREE_ROOT (1 << 11) | ||
193 | #define XFS_AGI_FREE_LEVEL (1 << 12) | ||
194 | #define XFS_AGI_NUM_BITS_R2 13 | ||
195 | |||
196 | /* disk block (xfs_daddr_t) in the AG */ | ||
197 | #define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log)) | ||
198 | #define XFS_AGI_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp)) | ||
199 | #define XFS_BUF_TO_AGI(bp) ((xfs_agi_t *)((bp)->b_addr)) | ||
200 | |||
201 | extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, | ||
202 | xfs_agnumber_t agno, struct xfs_buf **bpp); | ||
203 | |||
204 | /* | ||
205 | * The third a.g. block contains the a.g. freelist, an array | ||
206 | * of block pointers to blocks owned by the allocation btree code. | ||
207 | */ | ||
208 | #define XFS_AGFL_DADDR(mp) ((xfs_daddr_t)(3 << (mp)->m_sectbb_log)) | ||
209 | #define XFS_AGFL_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp)) | ||
210 | #define XFS_BUF_TO_AGFL(bp) ((xfs_agfl_t *)((bp)->b_addr)) | ||
211 | |||
212 | #define XFS_BUF_TO_AGFL_BNO(mp, bp) \ | ||
213 | (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ | ||
214 | &(XFS_BUF_TO_AGFL(bp)->agfl_bno[0]) : \ | ||
215 | (__be32 *)(bp)->b_addr) | ||
216 | |||
217 | /* | ||
218 | * Size of the AGFL. For CRC-enabled filesystes we steal a couple of | ||
219 | * slots in the beginning of the block for a proper header with the | ||
220 | * location information and CRC. | ||
221 | */ | ||
222 | #define XFS_AGFL_SIZE(mp) \ | ||
223 | (((mp)->m_sb.sb_sectsize - \ | ||
224 | (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ | ||
225 | sizeof(struct xfs_agfl) : 0)) / \ | ||
226 | sizeof(xfs_agblock_t)) | ||
227 | |||
228 | typedef struct xfs_agfl { | ||
229 | __be32 agfl_magicnum; | ||
230 | __be32 agfl_seqno; | ||
231 | uuid_t agfl_uuid; | ||
232 | __be64 agfl_lsn; | ||
233 | __be32 agfl_crc; | ||
234 | __be32 agfl_bno[]; /* actually XFS_AGFL_SIZE(mp) */ | ||
235 | } xfs_agfl_t; | ||
236 | |||
237 | #define XFS_AGFL_CRC_OFF offsetof(struct xfs_agfl, agfl_crc) | ||
238 | |||
239 | /* | ||
240 | * tags for inode radix tree | ||
241 | */ | ||
242 | #define XFS_ICI_NO_TAG (-1) /* special flag for an untagged lookup | ||
243 | in xfs_inode_ag_iterator */ | ||
244 | #define XFS_ICI_RECLAIM_TAG 0 /* inode is to be reclaimed */ | ||
245 | #define XFS_ICI_EOFBLOCKS_TAG 1 /* inode has blocks beyond EOF */ | ||
246 | |||
247 | #define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels) | ||
248 | #define XFS_MIN_FREELIST_RAW(bl,cl,mp) \ | ||
249 | (MIN(bl + 1, XFS_AG_MAXLEVELS(mp)) + MIN(cl + 1, XFS_AG_MAXLEVELS(mp))) | ||
250 | #define XFS_MIN_FREELIST(a,mp) \ | ||
251 | (XFS_MIN_FREELIST_RAW( \ | ||
252 | be32_to_cpu((a)->agf_levels[XFS_BTNUM_BNOi]), \ | ||
253 | be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp)) | ||
254 | #define XFS_MIN_FREELIST_PAG(pag,mp) \ | ||
255 | (XFS_MIN_FREELIST_RAW( \ | ||
256 | (unsigned int)(pag)->pagf_levels[XFS_BTNUM_BNOi], \ | ||
257 | (unsigned int)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp)) | ||
258 | |||
259 | #define XFS_AGB_TO_FSB(mp,agno,agbno) \ | ||
260 | (((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno)) | ||
261 | #define XFS_FSB_TO_AGNO(mp,fsbno) \ | ||
262 | ((xfs_agnumber_t)((fsbno) >> (mp)->m_sb.sb_agblklog)) | ||
263 | #define XFS_FSB_TO_AGBNO(mp,fsbno) \ | ||
264 | ((xfs_agblock_t)((fsbno) & xfs_mask32lo((mp)->m_sb.sb_agblklog))) | ||
265 | #define XFS_AGB_TO_DADDR(mp,agno,agbno) \ | ||
266 | ((xfs_daddr_t)XFS_FSB_TO_BB(mp, \ | ||
267 | (xfs_fsblock_t)(agno) * (mp)->m_sb.sb_agblocks + (agbno))) | ||
268 | #define XFS_AG_DADDR(mp,agno,d) (XFS_AGB_TO_DADDR(mp, agno, 0) + (d)) | ||
269 | |||
270 | /* | ||
271 | * For checking for bad ranges of xfs_daddr_t's, covering multiple | ||
272 | * allocation groups or a single xfs_daddr_t that's a superblock copy. | ||
273 | */ | ||
274 | #define XFS_AG_CHECK_DADDR(mp,d,len) \ | ||
275 | ((len) == 1 ? \ | ||
276 | ASSERT((d) == XFS_SB_DADDR || \ | ||
277 | xfs_daddr_to_agbno(mp, d) != XFS_SB_DADDR) : \ | ||
278 | ASSERT(xfs_daddr_to_agno(mp, d) == \ | ||
279 | xfs_daddr_to_agno(mp, (d) + (len) - 1))) | ||
280 | |||
281 | #endif /* __XFS_AG_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h new file mode 100644 index 000000000000..feacb061bab7 --- /dev/null +++ b/fs/xfs/libxfs/xfs_alloc.h | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_ALLOC_H__ | ||
19 | #define __XFS_ALLOC_H__ | ||
20 | |||
21 | struct xfs_buf; | ||
22 | struct xfs_btree_cur; | ||
23 | struct xfs_mount; | ||
24 | struct xfs_perag; | ||
25 | struct xfs_trans; | ||
26 | |||
27 | extern struct workqueue_struct *xfs_alloc_wq; | ||
28 | |||
29 | /* | ||
30 | * Freespace allocation types. Argument to xfs_alloc_[v]extent. | ||
31 | */ | ||
32 | #define XFS_ALLOCTYPE_ANY_AG 0x01 /* allocate anywhere, use rotor */ | ||
33 | #define XFS_ALLOCTYPE_FIRST_AG 0x02 /* ... start at ag 0 */ | ||
34 | #define XFS_ALLOCTYPE_START_AG 0x04 /* anywhere, start in this a.g. */ | ||
35 | #define XFS_ALLOCTYPE_THIS_AG 0x08 /* anywhere in this a.g. */ | ||
36 | #define XFS_ALLOCTYPE_START_BNO 0x10 /* near this block else anywhere */ | ||
37 | #define XFS_ALLOCTYPE_NEAR_BNO 0x20 /* in this a.g. and near this block */ | ||
38 | #define XFS_ALLOCTYPE_THIS_BNO 0x40 /* at exactly this block */ | ||
39 | |||
40 | /* this should become an enum again when the tracing code is fixed */ | ||
41 | typedef unsigned int xfs_alloctype_t; | ||
42 | |||
43 | #define XFS_ALLOC_TYPES \ | ||
44 | { XFS_ALLOCTYPE_ANY_AG, "ANY_AG" }, \ | ||
45 | { XFS_ALLOCTYPE_FIRST_AG, "FIRST_AG" }, \ | ||
46 | { XFS_ALLOCTYPE_START_AG, "START_AG" }, \ | ||
47 | { XFS_ALLOCTYPE_THIS_AG, "THIS_AG" }, \ | ||
48 | { XFS_ALLOCTYPE_START_BNO, "START_BNO" }, \ | ||
49 | { XFS_ALLOCTYPE_NEAR_BNO, "NEAR_BNO" }, \ | ||
50 | { XFS_ALLOCTYPE_THIS_BNO, "THIS_BNO" } | ||
51 | |||
52 | /* | ||
53 | * Flags for xfs_alloc_fix_freelist. | ||
54 | */ | ||
55 | #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ | ||
56 | #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ | ||
57 | |||
58 | /* | ||
59 | * In order to avoid ENOSPC-related deadlock caused by | ||
60 | * out-of-order locking of AGF buffer (PV 947395), we place | ||
61 | * constraints on the relationship among actual allocations for | ||
62 | * data blocks, freelist blocks, and potential file data bmap | ||
63 | * btree blocks. However, these restrictions may result in no | ||
64 | * actual space allocated for a delayed extent, for example, a data | ||
65 | * block in a certain AG is allocated but there is no additional | ||
66 | * block for the additional bmap btree block due to a split of the | ||
67 | * bmap btree of the file. The result of this may lead to an | ||
68 | * infinite loop in xfssyncd when the file gets flushed to disk and | ||
69 | * all delayed extents need to be actually allocated. To get around | ||
70 | * this, we explicitly set aside a few blocks which will not be | ||
71 | * reserved in delayed allocation. Considering the minimum number of | ||
72 | * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap | ||
73 | * btree requires 1 fsb, so we set the number of set-aside blocks | ||
74 | * to 4 + 4*agcount. | ||
75 | */ | ||
76 | #define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) | ||
77 | |||
78 | /* | ||
79 | * When deciding how much space to allocate out of an AG, we limit the | ||
80 | * allocation maximum size to the size the AG. However, we cannot use all the | ||
81 | * blocks in the AG - some are permanently used by metadata. These | ||
82 | * blocks are generally: | ||
83 | * - the AG superblock, AGF, AGI and AGFL | ||
84 | * - the AGF (bno and cnt) and AGI btree root blocks | ||
85 | * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits | ||
86 | * | ||
87 | * The AG headers are sector sized, so the amount of space they take up is | ||
88 | * dependent on filesystem geometry. The others are all single blocks. | ||
89 | */ | ||
90 | #define XFS_ALLOC_AG_MAX_USABLE(mp) \ | ||
91 | ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7) | ||
92 | |||
93 | |||
94 | /* | ||
95 | * Argument structure for xfs_alloc routines. | ||
96 | * This is turned into a structure to avoid having 20 arguments passed | ||
97 | * down several levels of the stack. | ||
98 | */ | ||
99 | typedef struct xfs_alloc_arg { | ||
100 | struct xfs_trans *tp; /* transaction pointer */ | ||
101 | struct xfs_mount *mp; /* file system mount point */ | ||
102 | struct xfs_buf *agbp; /* buffer for a.g. freelist header */ | ||
103 | struct xfs_perag *pag; /* per-ag struct for this agno */ | ||
104 | xfs_fsblock_t fsbno; /* file system block number */ | ||
105 | xfs_agnumber_t agno; /* allocation group number */ | ||
106 | xfs_agblock_t agbno; /* allocation group-relative block # */ | ||
107 | xfs_extlen_t minlen; /* minimum size of extent */ | ||
108 | xfs_extlen_t maxlen; /* maximum size of extent */ | ||
109 | xfs_extlen_t mod; /* mod value for extent size */ | ||
110 | xfs_extlen_t prod; /* prod value for extent size */ | ||
111 | xfs_extlen_t minleft; /* min blocks must be left after us */ | ||
112 | xfs_extlen_t total; /* total blocks needed in xaction */ | ||
113 | xfs_extlen_t alignment; /* align answer to multiple of this */ | ||
114 | xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */ | ||
115 | xfs_extlen_t len; /* output: actual size of extent */ | ||
116 | xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */ | ||
117 | xfs_alloctype_t otype; /* original allocation type */ | ||
118 | char wasdel; /* set if allocation was prev delayed */ | ||
119 | char wasfromfl; /* set if allocation is from freelist */ | ||
120 | char isfl; /* set if is freelist blocks - !acctg */ | ||
121 | char userdata; /* set if this is user data */ | ||
122 | xfs_fsblock_t firstblock; /* io first block allocated */ | ||
123 | } xfs_alloc_arg_t; | ||
124 | |||
125 | /* | ||
126 | * Defines for userdata | ||
127 | */ | ||
128 | #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ | ||
129 | #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ | ||
130 | |||
131 | /* | ||
132 | * Find the length of the longest extent in an AG. | ||
133 | */ | ||
134 | xfs_extlen_t | ||
135 | xfs_alloc_longest_free_extent(struct xfs_mount *mp, | ||
136 | struct xfs_perag *pag); | ||
137 | |||
138 | /* | ||
139 | * Compute and fill in value of m_ag_maxlevels. | ||
140 | */ | ||
141 | void | ||
142 | xfs_alloc_compute_maxlevels( | ||
143 | struct xfs_mount *mp); /* file system mount structure */ | ||
144 | |||
145 | /* | ||
146 | * Get a block from the freelist. | ||
147 | * Returns with the buffer for the block gotten. | ||
148 | */ | ||
149 | int /* error */ | ||
150 | xfs_alloc_get_freelist( | ||
151 | struct xfs_trans *tp, /* transaction pointer */ | ||
152 | struct xfs_buf *agbp, /* buffer containing the agf structure */ | ||
153 | xfs_agblock_t *bnop, /* block address retrieved from freelist */ | ||
154 | int btreeblk); /* destination is a AGF btree */ | ||
155 | |||
156 | /* | ||
157 | * Log the given fields from the agf structure. | ||
158 | */ | ||
159 | void | ||
160 | xfs_alloc_log_agf( | ||
161 | struct xfs_trans *tp, /* transaction pointer */ | ||
162 | struct xfs_buf *bp, /* buffer for a.g. freelist header */ | ||
163 | int fields);/* mask of fields to be logged (XFS_AGF_...) */ | ||
164 | |||
165 | /* | ||
166 | * Interface for inode allocation to force the pag data to be initialized. | ||
167 | */ | ||
168 | int /* error */ | ||
169 | xfs_alloc_pagf_init( | ||
170 | struct xfs_mount *mp, /* file system mount structure */ | ||
171 | struct xfs_trans *tp, /* transaction pointer */ | ||
172 | xfs_agnumber_t agno, /* allocation group number */ | ||
173 | int flags); /* XFS_ALLOC_FLAGS_... */ | ||
174 | |||
175 | /* | ||
176 | * Put the block on the freelist for the allocation group. | ||
177 | */ | ||
178 | int /* error */ | ||
179 | xfs_alloc_put_freelist( | ||
180 | struct xfs_trans *tp, /* transaction pointer */ | ||
181 | struct xfs_buf *agbp, /* buffer for a.g. freelist header */ | ||
182 | struct xfs_buf *agflbp,/* buffer for a.g. free block array */ | ||
183 | xfs_agblock_t bno, /* block being freed */ | ||
184 | int btreeblk); /* owner was a AGF btree */ | ||
185 | |||
186 | /* | ||
187 | * Read in the allocation group header (free/alloc section). | ||
188 | */ | ||
189 | int /* error */ | ||
190 | xfs_alloc_read_agf( | ||
191 | struct xfs_mount *mp, /* mount point structure */ | ||
192 | struct xfs_trans *tp, /* transaction pointer */ | ||
193 | xfs_agnumber_t agno, /* allocation group number */ | ||
194 | int flags, /* XFS_ALLOC_FLAG_... */ | ||
195 | struct xfs_buf **bpp); /* buffer for the ag freelist header */ | ||
196 | |||
197 | /* | ||
198 | * Allocate an extent (variable-size). | ||
199 | */ | ||
200 | int /* error */ | ||
201 | xfs_alloc_vextent( | ||
202 | xfs_alloc_arg_t *args); /* allocation argument structure */ | ||
203 | |||
204 | /* | ||
205 | * Free an extent. | ||
206 | */ | ||
207 | int /* error */ | ||
208 | xfs_free_extent( | ||
209 | struct xfs_trans *tp, /* transaction pointer */ | ||
210 | xfs_fsblock_t bno, /* starting block number of extent */ | ||
211 | xfs_extlen_t len); /* length of extent */ | ||
212 | |||
213 | int /* error */ | ||
214 | xfs_alloc_lookup_le( | ||
215 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
216 | xfs_agblock_t bno, /* starting block of extent */ | ||
217 | xfs_extlen_t len, /* length of extent */ | ||
218 | int *stat); /* success/failure */ | ||
219 | |||
220 | int /* error */ | ||
221 | xfs_alloc_lookup_ge( | ||
222 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
223 | xfs_agblock_t bno, /* starting block of extent */ | ||
224 | xfs_extlen_t len, /* length of extent */ | ||
225 | int *stat); /* success/failure */ | ||
226 | |||
227 | int /* error */ | ||
228 | xfs_alloc_get_rec( | ||
229 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
230 | xfs_agblock_t *bno, /* output: starting block of extent */ | ||
231 | xfs_extlen_t *len, /* output: length of extent */ | ||
232 | int *stat); /* output: success/failure */ | ||
233 | |||
234 | #endif /* __XFS_ALLOC_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.h b/fs/xfs/libxfs/xfs_alloc_btree.h new file mode 100644 index 000000000000..45e189e7e81c --- /dev/null +++ b/fs/xfs/libxfs/xfs_alloc_btree.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_ALLOC_BTREE_H__ | ||
19 | #define __XFS_ALLOC_BTREE_H__ | ||
20 | |||
21 | /* | ||
22 | * Freespace on-disk structures | ||
23 | */ | ||
24 | |||
25 | struct xfs_buf; | ||
26 | struct xfs_btree_cur; | ||
27 | struct xfs_mount; | ||
28 | |||
29 | /* | ||
30 | * Btree block header size depends on a superblock flag. | ||
31 | */ | ||
32 | #define XFS_ALLOC_BLOCK_LEN(mp) \ | ||
33 | (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ | ||
34 | XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN) | ||
35 | |||
36 | /* | ||
37 | * Record, key, and pointer address macros for btree blocks. | ||
38 | * | ||
39 | * (note that some of these may appear unused, but they are used in userspace) | ||
40 | */ | ||
41 | #define XFS_ALLOC_REC_ADDR(mp, block, index) \ | ||
42 | ((xfs_alloc_rec_t *) \ | ||
43 | ((char *)(block) + \ | ||
44 | XFS_ALLOC_BLOCK_LEN(mp) + \ | ||
45 | (((index) - 1) * sizeof(xfs_alloc_rec_t)))) | ||
46 | |||
47 | #define XFS_ALLOC_KEY_ADDR(mp, block, index) \ | ||
48 | ((xfs_alloc_key_t *) \ | ||
49 | ((char *)(block) + \ | ||
50 | XFS_ALLOC_BLOCK_LEN(mp) + \ | ||
51 | ((index) - 1) * sizeof(xfs_alloc_key_t))) | ||
52 | |||
53 | #define XFS_ALLOC_PTR_ADDR(mp, block, index, maxrecs) \ | ||
54 | ((xfs_alloc_ptr_t *) \ | ||
55 | ((char *)(block) + \ | ||
56 | XFS_ALLOC_BLOCK_LEN(mp) + \ | ||
57 | (maxrecs) * sizeof(xfs_alloc_key_t) + \ | ||
58 | ((index) - 1) * sizeof(xfs_alloc_ptr_t))) | ||
59 | |||
60 | extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, | ||
61 | struct xfs_trans *, struct xfs_buf *, | ||
62 | xfs_agnumber_t, xfs_btnum_t); | ||
63 | extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); | ||
64 | |||
65 | #endif /* __XFS_ALLOC_BTREE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h new file mode 100644 index 000000000000..e2929da7c3ba --- /dev/null +++ b/fs/xfs/libxfs/xfs_attr_leaf.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc. | ||
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write the Free Software Foundation, | ||
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | #ifndef __XFS_ATTR_LEAF_H__ | ||
20 | #define __XFS_ATTR_LEAF_H__ | ||
21 | |||
22 | struct attrlist; | ||
23 | struct attrlist_cursor_kern; | ||
24 | struct xfs_attr_list_context; | ||
25 | struct xfs_da_args; | ||
26 | struct xfs_da_state; | ||
27 | struct xfs_da_state_blk; | ||
28 | struct xfs_inode; | ||
29 | struct xfs_trans; | ||
30 | |||
31 | /* | ||
32 | * Used to keep a list of "remote value" extents when unlinking an inode. | ||
33 | */ | ||
34 | typedef struct xfs_attr_inactive_list { | ||
35 | xfs_dablk_t valueblk; /* block number of value bytes */ | ||
36 | int valuelen; /* number of bytes in value */ | ||
37 | } xfs_attr_inactive_list_t; | ||
38 | |||
39 | |||
40 | /*======================================================================== | ||
41 | * Function prototypes for the kernel. | ||
42 | *========================================================================*/ | ||
43 | |||
44 | /* | ||
45 | * Internal routines when attribute fork size < XFS_LITINO(mp). | ||
46 | */ | ||
47 | void xfs_attr_shortform_create(struct xfs_da_args *args); | ||
48 | void xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff); | ||
49 | int xfs_attr_shortform_lookup(struct xfs_da_args *args); | ||
50 | int xfs_attr_shortform_getvalue(struct xfs_da_args *args); | ||
51 | int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); | ||
52 | int xfs_attr_shortform_remove(struct xfs_da_args *args); | ||
53 | int xfs_attr_shortform_list(struct xfs_attr_list_context *context); | ||
54 | int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); | ||
55 | int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); | ||
56 | |||
57 | |||
58 | /* | ||
59 | * Internal routines when attribute fork size == XFS_LBSIZE(mp). | ||
60 | */ | ||
61 | int xfs_attr3_leaf_to_node(struct xfs_da_args *args); | ||
62 | int xfs_attr3_leaf_to_shortform(struct xfs_buf *bp, | ||
63 | struct xfs_da_args *args, int forkoff); | ||
64 | int xfs_attr3_leaf_clearflag(struct xfs_da_args *args); | ||
65 | int xfs_attr3_leaf_setflag(struct xfs_da_args *args); | ||
66 | int xfs_attr3_leaf_flipflags(struct xfs_da_args *args); | ||
67 | |||
68 | /* | ||
69 | * Routines used for growing the Btree. | ||
70 | */ | ||
71 | int xfs_attr3_leaf_split(struct xfs_da_state *state, | ||
72 | struct xfs_da_state_blk *oldblk, | ||
73 | struct xfs_da_state_blk *newblk); | ||
74 | int xfs_attr3_leaf_lookup_int(struct xfs_buf *leaf, | ||
75 | struct xfs_da_args *args); | ||
76 | int xfs_attr3_leaf_getvalue(struct xfs_buf *bp, struct xfs_da_args *args); | ||
77 | int xfs_attr3_leaf_add(struct xfs_buf *leaf_buffer, | ||
78 | struct xfs_da_args *args); | ||
79 | int xfs_attr3_leaf_remove(struct xfs_buf *leaf_buffer, | ||
80 | struct xfs_da_args *args); | ||
81 | int xfs_attr3_leaf_list_int(struct xfs_buf *bp, | ||
82 | struct xfs_attr_list_context *context); | ||
83 | |||
84 | /* | ||
85 | * Routines used for shrinking the Btree. | ||
86 | */ | ||
87 | int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval); | ||
88 | void xfs_attr3_leaf_unbalance(struct xfs_da_state *state, | ||
89 | struct xfs_da_state_blk *drop_blk, | ||
90 | struct xfs_da_state_blk *save_blk); | ||
91 | int xfs_attr3_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp); | ||
92 | |||
93 | /* | ||
94 | * Utility routines. | ||
95 | */ | ||
96 | xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_buf *bp, int *count); | ||
97 | int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp, | ||
98 | struct xfs_buf *leaf2_bp); | ||
99 | int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local); | ||
100 | int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp, | ||
101 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | ||
102 | struct xfs_buf **bpp); | ||
103 | void xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to, | ||
104 | struct xfs_attr_leafblock *from); | ||
105 | void xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to, | ||
106 | struct xfs_attr3_icleaf_hdr *from); | ||
107 | |||
108 | #endif /* __XFS_ATTR_LEAF_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h new file mode 100644 index 000000000000..5a9acfa156d7 --- /dev/null +++ b/fs/xfs/libxfs/xfs_attr_remote.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Red Hat, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_ATTR_REMOTE_H__ | ||
19 | #define __XFS_ATTR_REMOTE_H__ | ||
20 | |||
21 | int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); | ||
22 | |||
23 | int xfs_attr_rmtval_get(struct xfs_da_args *args); | ||
24 | int xfs_attr_rmtval_set(struct xfs_da_args *args); | ||
25 | int xfs_attr_rmtval_remove(struct xfs_da_args *args); | ||
26 | |||
27 | #endif /* __XFS_ATTR_REMOTE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_attr_sf.h b/fs/xfs/libxfs/xfs_attr_sf.h new file mode 100644 index 000000000000..919756e3ba53 --- /dev/null +++ b/fs/xfs/libxfs/xfs_attr_sf.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_ATTR_SF_H__ | ||
19 | #define __XFS_ATTR_SF_H__ | ||
20 | |||
21 | /* | ||
22 | * Attribute storage when stored inside the inode. | ||
23 | * | ||
24 | * Small attribute lists are packed as tightly as possible so as | ||
25 | * to fit into the literal area of the inode. | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | * Entries are packed toward the top as tight as possible. | ||
30 | */ | ||
31 | typedef struct xfs_attr_shortform { | ||
32 | struct xfs_attr_sf_hdr { /* constant-structure header block */ | ||
33 | __be16 totsize; /* total bytes in shortform list */ | ||
34 | __u8 count; /* count of active entries */ | ||
35 | } hdr; | ||
36 | struct xfs_attr_sf_entry { | ||
37 | __uint8_t namelen; /* actual length of name (no NULL) */ | ||
38 | __uint8_t valuelen; /* actual length of value (no NULL) */ | ||
39 | __uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */ | ||
40 | __uint8_t nameval[1]; /* name & value bytes concatenated */ | ||
41 | } list[1]; /* variable sized array */ | ||
42 | } xfs_attr_shortform_t; | ||
43 | typedef struct xfs_attr_sf_hdr xfs_attr_sf_hdr_t; | ||
44 | typedef struct xfs_attr_sf_entry xfs_attr_sf_entry_t; | ||
45 | |||
46 | /* | ||
47 | * We generate this then sort it, attr_list() must return things in hash-order. | ||
48 | */ | ||
49 | typedef struct xfs_attr_sf_sort { | ||
50 | __uint8_t entno; /* entry number in original list */ | ||
51 | __uint8_t namelen; /* length of name value (no null) */ | ||
52 | __uint8_t valuelen; /* length of value */ | ||
53 | __uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */ | ||
54 | xfs_dahash_t hash; /* this entry's hash value */ | ||
55 | unsigned char *name; /* name value, pointer into buffer */ | ||
56 | } xfs_attr_sf_sort_t; | ||
57 | |||
58 | #define XFS_ATTR_SF_ENTSIZE_BYNAME(nlen,vlen) /* space name/value uses */ \ | ||
59 | (((int)sizeof(xfs_attr_sf_entry_t)-1 + (nlen)+(vlen))) | ||
60 | #define XFS_ATTR_SF_ENTSIZE_MAX /* max space for name&value */ \ | ||
61 | ((1 << (NBBY*(int)sizeof(__uint8_t))) - 1) | ||
62 | #define XFS_ATTR_SF_ENTSIZE(sfep) /* space an entry uses */ \ | ||
63 | ((int)sizeof(xfs_attr_sf_entry_t)-1 + (sfep)->namelen+(sfep)->valuelen) | ||
64 | #define XFS_ATTR_SF_NEXTENTRY(sfep) /* next entry in struct */ \ | ||
65 | ((xfs_attr_sf_entry_t *)((char *)(sfep) + XFS_ATTR_SF_ENTSIZE(sfep))) | ||
66 | #define XFS_ATTR_SF_TOTSIZE(dp) /* total space in use */ \ | ||
67 | (be16_to_cpu(((xfs_attr_shortform_t *) \ | ||
68 | ((dp)->i_afp->if_u1.if_data))->hdr.totsize)) | ||
69 | |||
70 | #endif /* __XFS_ATTR_SF_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_bit.h b/fs/xfs/libxfs/xfs_bit.h new file mode 100644 index 000000000000..e1649c0d3e02 --- /dev/null +++ b/fs/xfs/libxfs/xfs_bit.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_BIT_H__ | ||
19 | #define __XFS_BIT_H__ | ||
20 | |||
21 | /* | ||
22 | * XFS bit manipulation routines. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * masks with n high/low bits set, 64-bit values | ||
27 | */ | ||
28 | static inline __uint64_t xfs_mask64hi(int n) | ||
29 | { | ||
30 | return (__uint64_t)-1 << (64 - (n)); | ||
31 | } | ||
32 | static inline __uint32_t xfs_mask32lo(int n) | ||
33 | { | ||
34 | return ((__uint32_t)1 << (n)) - 1; | ||
35 | } | ||
36 | static inline __uint64_t xfs_mask64lo(int n) | ||
37 | { | ||
38 | return ((__uint64_t)1 << (n)) - 1; | ||
39 | } | ||
40 | |||
41 | /* Get high bit set out of 32-bit argument, -1 if none set */ | ||
42 | static inline int xfs_highbit32(__uint32_t v) | ||
43 | { | ||
44 | return fls(v) - 1; | ||
45 | } | ||
46 | |||
47 | /* Get high bit set out of 64-bit argument, -1 if none set */ | ||
48 | static inline int xfs_highbit64(__uint64_t v) | ||
49 | { | ||
50 | return fls64(v) - 1; | ||
51 | } | ||
52 | |||
53 | /* Get low bit set out of 32-bit argument, -1 if none set */ | ||
54 | static inline int xfs_lowbit32(__uint32_t v) | ||
55 | { | ||
56 | return ffs(v) - 1; | ||
57 | } | ||
58 | |||
59 | /* Get low bit set out of 64-bit argument, -1 if none set */ | ||
60 | static inline int xfs_lowbit64(__uint64_t v) | ||
61 | { | ||
62 | __uint32_t w = (__uint32_t)v; | ||
63 | int n = 0; | ||
64 | |||
65 | if (w) { /* lower bits */ | ||
66 | n = ffs(w); | ||
67 | } else { /* upper bits */ | ||
68 | w = (__uint32_t)(v >> 32); | ||
69 | if (w) { | ||
70 | n = ffs(w); | ||
71 | if (n) | ||
72 | n += 32; | ||
73 | } | ||
74 | } | ||
75 | return n - 1; | ||
76 | } | ||
77 | |||
78 | /* Return whether bitmap is empty (1 == empty) */ | ||
79 | extern int xfs_bitmap_empty(uint *map, uint size); | ||
80 | |||
81 | /* Count continuous one bits in map starting with start_bit */ | ||
82 | extern int xfs_contig_bits(uint *map, uint size, uint start_bit); | ||
83 | |||
84 | /* Find next set bit in map */ | ||
85 | extern int xfs_next_bit(uint *map, uint size, uint start_bit); | ||
86 | |||
87 | #endif /* __XFS_BIT_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h new file mode 100644 index 000000000000..38ba36e9b2f0 --- /dev/null +++ b/fs/xfs/libxfs/xfs_bmap.h | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_BMAP_H__ | ||
19 | #define __XFS_BMAP_H__ | ||
20 | |||
21 | struct getbmap; | ||
22 | struct xfs_bmbt_irec; | ||
23 | struct xfs_ifork; | ||
24 | struct xfs_inode; | ||
25 | struct xfs_mount; | ||
26 | struct xfs_trans; | ||
27 | |||
28 | extern kmem_zone_t *xfs_bmap_free_item_zone; | ||
29 | |||
30 | /* | ||
31 | * List of extents to be free "later". | ||
32 | * The list is kept sorted on xbf_startblock. | ||
33 | */ | ||
34 | typedef struct xfs_bmap_free_item | ||
35 | { | ||
36 | xfs_fsblock_t xbfi_startblock;/* starting fs block number */ | ||
37 | xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */ | ||
38 | struct xfs_bmap_free_item *xbfi_next; /* link to next entry */ | ||
39 | } xfs_bmap_free_item_t; | ||
40 | |||
41 | /* | ||
42 | * Header for free extent list. | ||
43 | * | ||
44 | * xbf_low is used by the allocator to activate the lowspace algorithm - | ||
45 | * when free space is running low the extent allocator may choose to | ||
46 | * allocate an extent from an AG without leaving sufficient space for | ||
47 | * a btree split when inserting the new extent. In this case the allocator | ||
48 | * will enable the lowspace algorithm which is supposed to allow further | ||
49 | * allocations (such as btree splits and newroots) to allocate from | ||
50 | * sequential AGs. In order to avoid locking AGs out of order the lowspace | ||
51 | * algorithm will start searching for free space from AG 0. If the correct | ||
52 | * transaction reservations have been made then this algorithm will eventually | ||
53 | * find all the space it needs. | ||
54 | */ | ||
55 | typedef struct xfs_bmap_free | ||
56 | { | ||
57 | xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */ | ||
58 | int xbf_count; /* count of items on list */ | ||
59 | int xbf_low; /* alloc in low mode */ | ||
60 | } xfs_bmap_free_t; | ||
61 | |||
62 | #define XFS_BMAP_MAX_NMAP 4 | ||
63 | |||
64 | /* | ||
65 | * Flags for xfs_bmapi_* | ||
66 | */ | ||
67 | #define XFS_BMAPI_ENTIRE 0x001 /* return entire extent, not trimmed */ | ||
68 | #define XFS_BMAPI_METADATA 0x002 /* mapping metadata not user data */ | ||
69 | #define XFS_BMAPI_ATTRFORK 0x004 /* use attribute fork not data */ | ||
70 | #define XFS_BMAPI_PREALLOC 0x008 /* preallocation op: unwritten space */ | ||
71 | #define XFS_BMAPI_IGSTATE 0x010 /* Ignore state - */ | ||
72 | /* combine contig. space */ | ||
73 | #define XFS_BMAPI_CONTIG 0x020 /* must allocate only one extent */ | ||
74 | /* | ||
75 | * unwritten extent conversion - this needs write cache flushing and no additional | ||
76 | * allocation alignments. When specified with XFS_BMAPI_PREALLOC it converts | ||
77 | * from written to unwritten, otherwise convert from unwritten to written. | ||
78 | */ | ||
79 | #define XFS_BMAPI_CONVERT 0x040 | ||
80 | #define XFS_BMAPI_STACK_SWITCH 0x080 | ||
81 | |||
82 | #define XFS_BMAPI_FLAGS \ | ||
83 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ | ||
84 | { XFS_BMAPI_METADATA, "METADATA" }, \ | ||
85 | { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ | ||
86 | { XFS_BMAPI_PREALLOC, "PREALLOC" }, \ | ||
87 | { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ | ||
88 | { XFS_BMAPI_CONTIG, "CONTIG" }, \ | ||
89 | { XFS_BMAPI_CONVERT, "CONVERT" }, \ | ||
90 | { XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" } | ||
91 | |||
92 | |||
93 | static inline int xfs_bmapi_aflag(int w) | ||
94 | { | ||
95 | return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : 0); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Special values for xfs_bmbt_irec_t br_startblock field. | ||
100 | */ | ||
101 | #define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL) | ||
102 | #define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL) | ||
103 | |||
104 | static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) | ||
105 | { | ||
106 | ((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \ | ||
107 | (flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * Flags for xfs_bmap_add_extent*. | ||
112 | */ | ||
113 | #define BMAP_LEFT_CONTIG (1 << 0) | ||
114 | #define BMAP_RIGHT_CONTIG (1 << 1) | ||
115 | #define BMAP_LEFT_FILLING (1 << 2) | ||
116 | #define BMAP_RIGHT_FILLING (1 << 3) | ||
117 | #define BMAP_LEFT_DELAY (1 << 4) | ||
118 | #define BMAP_RIGHT_DELAY (1 << 5) | ||
119 | #define BMAP_LEFT_VALID (1 << 6) | ||
120 | #define BMAP_RIGHT_VALID (1 << 7) | ||
121 | #define BMAP_ATTRFORK (1 << 8) | ||
122 | |||
123 | #define XFS_BMAP_EXT_FLAGS \ | ||
124 | { BMAP_LEFT_CONTIG, "LC" }, \ | ||
125 | { BMAP_RIGHT_CONTIG, "RC" }, \ | ||
126 | { BMAP_LEFT_FILLING, "LF" }, \ | ||
127 | { BMAP_RIGHT_FILLING, "RF" }, \ | ||
128 | { BMAP_ATTRFORK, "ATTR" } | ||
129 | |||
130 | |||
131 | /* | ||
132 | * This macro is used to determine how many extents will be shifted | ||
133 | * in one write transaction. We could require two splits, | ||
134 | * an extent move on the first and an extent merge on the second, | ||
135 | * So it is proper that one extent is shifted inside write transaction | ||
136 | * at a time. | ||
137 | */ | ||
138 | #define XFS_BMAP_MAX_SHIFT_EXTENTS 1 | ||
139 | |||
140 | #ifdef DEBUG | ||
141 | void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, | ||
142 | int whichfork, unsigned long caller_ip); | ||
143 | #define XFS_BMAP_TRACE_EXLIST(ip,c,w) \ | ||
144 | xfs_bmap_trace_exlist(ip,c,w, _THIS_IP_) | ||
145 | #else | ||
146 | #define XFS_BMAP_TRACE_EXLIST(ip,c,w) | ||
147 | #endif | ||
148 | |||
149 | int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); | ||
150 | void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); | ||
151 | void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len, | ||
152 | struct xfs_bmap_free *flist, struct xfs_mount *mp); | ||
153 | void xfs_bmap_cancel(struct xfs_bmap_free *flist); | ||
154 | void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); | ||
155 | int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, | ||
156 | xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); | ||
157 | int xfs_bmap_last_before(struct xfs_trans *tp, struct xfs_inode *ip, | ||
158 | xfs_fileoff_t *last_block, int whichfork); | ||
159 | int xfs_bmap_last_offset(struct xfs_inode *ip, xfs_fileoff_t *unused, | ||
160 | int whichfork); | ||
161 | int xfs_bmap_one_block(struct xfs_inode *ip, int whichfork); | ||
162 | int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, | ||
163 | int whichfork); | ||
164 | int xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno, | ||
165 | xfs_filblks_t len, struct xfs_bmbt_irec *mval, | ||
166 | int *nmap, int flags); | ||
167 | int xfs_bmapi_delay(struct xfs_inode *ip, xfs_fileoff_t bno, | ||
168 | xfs_filblks_t len, struct xfs_bmbt_irec *mval, | ||
169 | int *nmap, int flags); | ||
170 | int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, | ||
171 | xfs_fileoff_t bno, xfs_filblks_t len, int flags, | ||
172 | xfs_fsblock_t *firstblock, xfs_extlen_t total, | ||
173 | struct xfs_bmbt_irec *mval, int *nmap, | ||
174 | struct xfs_bmap_free *flist); | ||
175 | int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, | ||
176 | xfs_fileoff_t bno, xfs_filblks_t len, int flags, | ||
177 | xfs_extnum_t nexts, xfs_fsblock_t *firstblock, | ||
178 | struct xfs_bmap_free *flist, int *done); | ||
179 | int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, | ||
180 | xfs_extnum_t num); | ||
181 | uint xfs_default_attroffset(struct xfs_inode *ip); | ||
182 | int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, | ||
183 | int *done, xfs_fileoff_t start_fsb, | ||
184 | xfs_fileoff_t offset_shift_fsb, xfs_extnum_t *current_ext, | ||
185 | xfs_fsblock_t *firstblock, struct xfs_bmap_free *flist, | ||
186 | int num_exts); | ||
187 | |||
188 | #endif /* __XFS_BMAP_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h new file mode 100644 index 000000000000..819a8a4dee95 --- /dev/null +++ b/fs/xfs/libxfs/xfs_bmap_btree.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002-2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_BMAP_BTREE_H__ | ||
19 | #define __XFS_BMAP_BTREE_H__ | ||
20 | |||
21 | struct xfs_btree_cur; | ||
22 | struct xfs_btree_block; | ||
23 | struct xfs_mount; | ||
24 | struct xfs_inode; | ||
25 | struct xfs_trans; | ||
26 | |||
27 | /* | ||
28 | * Extent state and extent format macros. | ||
29 | */ | ||
30 | #define XFS_EXTFMT_INODE(x) \ | ||
31 | (xfs_sb_version_hasextflgbit(&((x)->i_mount->m_sb)) ? \ | ||
32 | XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE) | ||
33 | #define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN) | ||
34 | |||
35 | /* | ||
36 | * Btree block header size depends on a superblock flag. | ||
37 | */ | ||
38 | #define XFS_BMBT_BLOCK_LEN(mp) \ | ||
39 | (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ | ||
40 | XFS_BTREE_LBLOCK_CRC_LEN : XFS_BTREE_LBLOCK_LEN) | ||
41 | |||
42 | #define XFS_BMBT_REC_ADDR(mp, block, index) \ | ||
43 | ((xfs_bmbt_rec_t *) \ | ||
44 | ((char *)(block) + \ | ||
45 | XFS_BMBT_BLOCK_LEN(mp) + \ | ||
46 | ((index) - 1) * sizeof(xfs_bmbt_rec_t))) | ||
47 | |||
48 | #define XFS_BMBT_KEY_ADDR(mp, block, index) \ | ||
49 | ((xfs_bmbt_key_t *) \ | ||
50 | ((char *)(block) + \ | ||
51 | XFS_BMBT_BLOCK_LEN(mp) + \ | ||
52 | ((index) - 1) * sizeof(xfs_bmbt_key_t))) | ||
53 | |||
54 | #define XFS_BMBT_PTR_ADDR(mp, block, index, maxrecs) \ | ||
55 | ((xfs_bmbt_ptr_t *) \ | ||
56 | ((char *)(block) + \ | ||
57 | XFS_BMBT_BLOCK_LEN(mp) + \ | ||
58 | (maxrecs) * sizeof(xfs_bmbt_key_t) + \ | ||
59 | ((index) - 1) * sizeof(xfs_bmbt_ptr_t))) | ||
60 | |||
61 | #define XFS_BMDR_REC_ADDR(block, index) \ | ||
62 | ((xfs_bmdr_rec_t *) \ | ||
63 | ((char *)(block) + \ | ||
64 | sizeof(struct xfs_bmdr_block) + \ | ||
65 | ((index) - 1) * sizeof(xfs_bmdr_rec_t))) | ||
66 | |||
67 | #define XFS_BMDR_KEY_ADDR(block, index) \ | ||
68 | ((xfs_bmdr_key_t *) \ | ||
69 | ((char *)(block) + \ | ||
70 | sizeof(struct xfs_bmdr_block) + \ | ||
71 | ((index) - 1) * sizeof(xfs_bmdr_key_t))) | ||
72 | |||
73 | #define XFS_BMDR_PTR_ADDR(block, index, maxrecs) \ | ||
74 | ((xfs_bmdr_ptr_t *) \ | ||
75 | ((char *)(block) + \ | ||
76 | sizeof(struct xfs_bmdr_block) + \ | ||
77 | (maxrecs) * sizeof(xfs_bmdr_key_t) + \ | ||
78 | ((index) - 1) * sizeof(xfs_bmdr_ptr_t))) | ||
79 | |||
80 | /* | ||
81 | * These are to be used when we know the size of the block and | ||
82 | * we don't have a cursor. | ||
83 | */ | ||
84 | #define XFS_BMAP_BROOT_PTR_ADDR(mp, bb, i, sz) \ | ||
85 | XFS_BMBT_PTR_ADDR(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0)) | ||
86 | |||
87 | #define XFS_BMAP_BROOT_SPACE_CALC(mp, nrecs) \ | ||
88 | (int)(XFS_BMBT_BLOCK_LEN(mp) + \ | ||
89 | ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) | ||
90 | |||
91 | #define XFS_BMAP_BROOT_SPACE(mp, bb) \ | ||
92 | (XFS_BMAP_BROOT_SPACE_CALC(mp, be16_to_cpu((bb)->bb_numrecs))) | ||
93 | #define XFS_BMDR_SPACE_CALC(nrecs) \ | ||
94 | (int)(sizeof(xfs_bmdr_block_t) + \ | ||
95 | ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) | ||
96 | #define XFS_BMAP_BMDR_SPACE(bb) \ | ||
97 | (XFS_BMDR_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) | ||
98 | |||
99 | /* | ||
100 | * Maximum number of bmap btree levels. | ||
101 | */ | ||
102 | #define XFS_BM_MAXLEVELS(mp,w) ((mp)->m_bm_maxlevels[(w)]) | ||
103 | |||
104 | /* | ||
105 | * Prototypes for xfs_bmap.c to call. | ||
106 | */ | ||
107 | extern void xfs_bmdr_to_bmbt(struct xfs_inode *, xfs_bmdr_block_t *, int, | ||
108 | struct xfs_btree_block *, int); | ||
109 | extern void xfs_bmbt_get_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s); | ||
110 | extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_host_t *r); | ||
111 | extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_host_t *r); | ||
112 | extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_host_t *r); | ||
113 | extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_host_t *r); | ||
114 | |||
115 | extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); | ||
116 | extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); | ||
117 | |||
118 | extern void xfs_bmbt_set_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s); | ||
119 | extern void xfs_bmbt_set_allf(xfs_bmbt_rec_host_t *r, xfs_fileoff_t o, | ||
120 | xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v); | ||
121 | extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_host_t *r, xfs_filblks_t v); | ||
122 | extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_host_t *r, xfs_fsblock_t v); | ||
123 | extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_host_t *r, xfs_fileoff_t v); | ||
124 | extern void xfs_bmbt_set_state(xfs_bmbt_rec_host_t *r, xfs_exntst_t v); | ||
125 | |||
126 | extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o, | ||
127 | xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v); | ||
128 | |||
129 | extern void xfs_bmbt_to_bmdr(struct xfs_mount *, struct xfs_btree_block *, int, | ||
130 | xfs_bmdr_block_t *, int); | ||
131 | |||
132 | extern int xfs_bmbt_get_maxrecs(struct xfs_btree_cur *, int level); | ||
133 | extern int xfs_bmdr_maxrecs(int blocklen, int leaf); | ||
134 | extern int xfs_bmbt_maxrecs(struct xfs_mount *, int blocklen, int leaf); | ||
135 | |||
136 | extern int xfs_bmbt_change_owner(struct xfs_trans *tp, struct xfs_inode *ip, | ||
137 | int whichfork, xfs_ino_t new_owner, | ||
138 | struct list_head *buffer_list); | ||
139 | |||
140 | extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, | ||
141 | struct xfs_trans *, struct xfs_inode *, int); | ||
142 | |||
143 | #endif /* __XFS_BMAP_BTREE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h new file mode 100644 index 000000000000..a04b69422f67 --- /dev/null +++ b/fs/xfs/libxfs/xfs_btree.h | |||
@@ -0,0 +1,468 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_BTREE_H__ | ||
19 | #define __XFS_BTREE_H__ | ||
20 | |||
21 | struct xfs_buf; | ||
22 | struct xfs_bmap_free; | ||
23 | struct xfs_inode; | ||
24 | struct xfs_mount; | ||
25 | struct xfs_trans; | ||
26 | |||
27 | extern kmem_zone_t *xfs_btree_cur_zone; | ||
28 | |||
29 | /* | ||
30 | * Generic key, ptr and record wrapper structures. | ||
31 | * | ||
32 | * These are disk format structures, and are converted where necessary | ||
33 | * by the btree specific code that needs to interpret them. | ||
34 | */ | ||
35 | union xfs_btree_ptr { | ||
36 | __be32 s; /* short form ptr */ | ||
37 | __be64 l; /* long form ptr */ | ||
38 | }; | ||
39 | |||
40 | union xfs_btree_key { | ||
41 | xfs_bmbt_key_t bmbt; | ||
42 | xfs_bmdr_key_t bmbr; /* bmbt root block */ | ||
43 | xfs_alloc_key_t alloc; | ||
44 | xfs_inobt_key_t inobt; | ||
45 | }; | ||
46 | |||
47 | union xfs_btree_rec { | ||
48 | xfs_bmbt_rec_t bmbt; | ||
49 | xfs_bmdr_rec_t bmbr; /* bmbt root block */ | ||
50 | xfs_alloc_rec_t alloc; | ||
51 | xfs_inobt_rec_t inobt; | ||
52 | }; | ||
53 | |||
54 | /* | ||
55 | * This nonsense is to make -wlint happy. | ||
56 | */ | ||
57 | #define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi) | ||
58 | #define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi) | ||
59 | #define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi) | ||
60 | |||
61 | #define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi) | ||
62 | #define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi) | ||
63 | #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) | ||
64 | #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) | ||
65 | #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) | ||
66 | |||
67 | /* | ||
68 | * For logging record fields. | ||
69 | */ | ||
70 | #define XFS_BB_MAGIC (1 << 0) | ||
71 | #define XFS_BB_LEVEL (1 << 1) | ||
72 | #define XFS_BB_NUMRECS (1 << 2) | ||
73 | #define XFS_BB_LEFTSIB (1 << 3) | ||
74 | #define XFS_BB_RIGHTSIB (1 << 4) | ||
75 | #define XFS_BB_BLKNO (1 << 5) | ||
76 | #define XFS_BB_LSN (1 << 6) | ||
77 | #define XFS_BB_UUID (1 << 7) | ||
78 | #define XFS_BB_OWNER (1 << 8) | ||
79 | #define XFS_BB_NUM_BITS 5 | ||
80 | #define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1) | ||
81 | #define XFS_BB_NUM_BITS_CRC 9 | ||
82 | #define XFS_BB_ALL_BITS_CRC ((1 << XFS_BB_NUM_BITS_CRC) - 1) | ||
83 | |||
84 | /* | ||
85 | * Generic stats interface | ||
86 | */ | ||
87 | #define __XFS_BTREE_STATS_INC(type, stat) \ | ||
88 | XFS_STATS_INC(xs_ ## type ## _2_ ## stat) | ||
89 | #define XFS_BTREE_STATS_INC(cur, stat) \ | ||
90 | do { \ | ||
91 | switch (cur->bc_btnum) { \ | ||
92 | case XFS_BTNUM_BNO: __XFS_BTREE_STATS_INC(abtb, stat); break; \ | ||
93 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(abtc, stat); break; \ | ||
94 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(bmbt, stat); break; \ | ||
95 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(ibt, stat); break; \ | ||
96 | case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(fibt, stat); break; \ | ||
97 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ | ||
98 | } \ | ||
99 | } while (0) | ||
100 | |||
101 | #define __XFS_BTREE_STATS_ADD(type, stat, val) \ | ||
102 | XFS_STATS_ADD(xs_ ## type ## _2_ ## stat, val) | ||
103 | #define XFS_BTREE_STATS_ADD(cur, stat, val) \ | ||
104 | do { \ | ||
105 | switch (cur->bc_btnum) { \ | ||
106 | case XFS_BTNUM_BNO: __XFS_BTREE_STATS_ADD(abtb, stat, val); break; \ | ||
107 | case XFS_BTNUM_CNT: __XFS_BTREE_STATS_ADD(abtc, stat, val); break; \ | ||
108 | case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_ADD(bmbt, stat, val); break; \ | ||
109 | case XFS_BTNUM_INO: __XFS_BTREE_STATS_ADD(ibt, stat, val); break; \ | ||
110 | case XFS_BTNUM_FINO: __XFS_BTREE_STATS_ADD(fibt, stat, val); break; \ | ||
111 | case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ | ||
112 | } \ | ||
113 | } while (0) | ||
114 | |||
115 | #define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */ | ||
116 | |||
117 | struct xfs_btree_ops { | ||
118 | /* size of the key and record structures */ | ||
119 | size_t key_len; | ||
120 | size_t rec_len; | ||
121 | |||
122 | /* cursor operations */ | ||
123 | struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); | ||
124 | void (*update_cursor)(struct xfs_btree_cur *src, | ||
125 | struct xfs_btree_cur *dst); | ||
126 | |||
127 | /* update btree root pointer */ | ||
128 | void (*set_root)(struct xfs_btree_cur *cur, | ||
129 | union xfs_btree_ptr *nptr, int level_change); | ||
130 | |||
131 | /* block allocation / freeing */ | ||
132 | int (*alloc_block)(struct xfs_btree_cur *cur, | ||
133 | union xfs_btree_ptr *start_bno, | ||
134 | union xfs_btree_ptr *new_bno, | ||
135 | int *stat); | ||
136 | int (*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp); | ||
137 | |||
138 | /* update last record information */ | ||
139 | void (*update_lastrec)(struct xfs_btree_cur *cur, | ||
140 | struct xfs_btree_block *block, | ||
141 | union xfs_btree_rec *rec, | ||
142 | int ptr, int reason); | ||
143 | |||
144 | /* records in block/level */ | ||
145 | int (*get_minrecs)(struct xfs_btree_cur *cur, int level); | ||
146 | int (*get_maxrecs)(struct xfs_btree_cur *cur, int level); | ||
147 | |||
148 | /* records on disk. Matter for the root in inode case. */ | ||
149 | int (*get_dmaxrecs)(struct xfs_btree_cur *cur, int level); | ||
150 | |||
151 | /* init values of btree structures */ | ||
152 | void (*init_key_from_rec)(union xfs_btree_key *key, | ||
153 | union xfs_btree_rec *rec); | ||
154 | void (*init_rec_from_key)(union xfs_btree_key *key, | ||
155 | union xfs_btree_rec *rec); | ||
156 | void (*init_rec_from_cur)(struct xfs_btree_cur *cur, | ||
157 | union xfs_btree_rec *rec); | ||
158 | void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, | ||
159 | union xfs_btree_ptr *ptr); | ||
160 | |||
161 | /* difference between key value and cursor value */ | ||
162 | __int64_t (*key_diff)(struct xfs_btree_cur *cur, | ||
163 | union xfs_btree_key *key); | ||
164 | |||
165 | const struct xfs_buf_ops *buf_ops; | ||
166 | |||
167 | #if defined(DEBUG) || defined(XFS_WARN) | ||
168 | /* check that k1 is lower than k2 */ | ||
169 | int (*keys_inorder)(struct xfs_btree_cur *cur, | ||
170 | union xfs_btree_key *k1, | ||
171 | union xfs_btree_key *k2); | ||
172 | |||
173 | /* check that r1 is lower than r2 */ | ||
174 | int (*recs_inorder)(struct xfs_btree_cur *cur, | ||
175 | union xfs_btree_rec *r1, | ||
176 | union xfs_btree_rec *r2); | ||
177 | #endif | ||
178 | }; | ||
179 | |||
180 | /* | ||
181 | * Reasons for the update_lastrec method to be called. | ||
182 | */ | ||
183 | #define LASTREC_UPDATE 0 | ||
184 | #define LASTREC_INSREC 1 | ||
185 | #define LASTREC_DELREC 2 | ||
186 | |||
187 | |||
188 | /* | ||
189 | * Btree cursor structure. | ||
190 | * This collects all information needed by the btree code in one place. | ||
191 | */ | ||
192 | typedef struct xfs_btree_cur | ||
193 | { | ||
194 | struct xfs_trans *bc_tp; /* transaction we're in, if any */ | ||
195 | struct xfs_mount *bc_mp; /* file system mount struct */ | ||
196 | const struct xfs_btree_ops *bc_ops; | ||
197 | uint bc_flags; /* btree features - below */ | ||
198 | union { | ||
199 | xfs_alloc_rec_incore_t a; | ||
200 | xfs_bmbt_irec_t b; | ||
201 | xfs_inobt_rec_incore_t i; | ||
202 | } bc_rec; /* current insert/search record value */ | ||
203 | struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ | ||
204 | int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ | ||
205 | __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ | ||
206 | #define XFS_BTCUR_LEFTRA 1 /* left sibling has been read-ahead */ | ||
207 | #define XFS_BTCUR_RIGHTRA 2 /* right sibling has been read-ahead */ | ||
208 | __uint8_t bc_nlevels; /* number of levels in the tree */ | ||
209 | __uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */ | ||
210 | xfs_btnum_t bc_btnum; /* identifies which btree type */ | ||
211 | union { | ||
212 | struct { /* needed for BNO, CNT, INO */ | ||
213 | struct xfs_buf *agbp; /* agf/agi buffer pointer */ | ||
214 | xfs_agnumber_t agno; /* ag number */ | ||
215 | } a; | ||
216 | struct { /* needed for BMAP */ | ||
217 | struct xfs_inode *ip; /* pointer to our inode */ | ||
218 | struct xfs_bmap_free *flist; /* list to free after */ | ||
219 | xfs_fsblock_t firstblock; /* 1st blk allocated */ | ||
220 | int allocated; /* count of alloced */ | ||
221 | short forksize; /* fork's inode space */ | ||
222 | char whichfork; /* data or attr fork */ | ||
223 | char flags; /* flags */ | ||
224 | #define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */ | ||
225 | } b; | ||
226 | } bc_private; /* per-btree type data */ | ||
227 | } xfs_btree_cur_t; | ||
228 | |||
229 | /* cursor flags */ | ||
230 | #define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */ | ||
231 | #define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */ | ||
232 | #define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */ | ||
233 | #define XFS_BTREE_CRC_BLOCKS (1<<3) /* uses extended btree blocks */ | ||
234 | |||
235 | |||
236 | #define XFS_BTREE_NOERROR 0 | ||
237 | #define XFS_BTREE_ERROR 1 | ||
238 | |||
239 | /* | ||
240 | * Convert from buffer to btree block header. | ||
241 | */ | ||
242 | #define XFS_BUF_TO_BLOCK(bp) ((struct xfs_btree_block *)((bp)->b_addr)) | ||
243 | |||
244 | |||
245 | /* | ||
246 | * Check that block header is ok. | ||
247 | */ | ||
248 | int | ||
249 | xfs_btree_check_block( | ||
250 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
251 | struct xfs_btree_block *block, /* generic btree block pointer */ | ||
252 | int level, /* level of the btree block */ | ||
253 | struct xfs_buf *bp); /* buffer containing block, if any */ | ||
254 | |||
255 | /* | ||
256 | * Check that (long) pointer is ok. | ||
257 | */ | ||
258 | int /* error (0 or EFSCORRUPTED) */ | ||
259 | xfs_btree_check_lptr( | ||
260 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
261 | xfs_dfsbno_t ptr, /* btree block disk address */ | ||
262 | int level); /* btree block level */ | ||
263 | |||
264 | /* | ||
265 | * Delete the btree cursor. | ||
266 | */ | ||
267 | void | ||
268 | xfs_btree_del_cursor( | ||
269 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
270 | int error); /* del because of error */ | ||
271 | |||
272 | /* | ||
273 | * Duplicate the btree cursor. | ||
274 | * Allocate a new one, copy the record, re-get the buffers. | ||
275 | */ | ||
276 | int /* error */ | ||
277 | xfs_btree_dup_cursor( | ||
278 | xfs_btree_cur_t *cur, /* input cursor */ | ||
279 | xfs_btree_cur_t **ncur);/* output cursor */ | ||
280 | |||
281 | /* | ||
282 | * Get a buffer for the block, return it with no data read. | ||
283 | * Long-form addressing. | ||
284 | */ | ||
285 | struct xfs_buf * /* buffer for fsbno */ | ||
286 | xfs_btree_get_bufl( | ||
287 | struct xfs_mount *mp, /* file system mount point */ | ||
288 | struct xfs_trans *tp, /* transaction pointer */ | ||
289 | xfs_fsblock_t fsbno, /* file system block number */ | ||
290 | uint lock); /* lock flags for get_buf */ | ||
291 | |||
292 | /* | ||
293 | * Get a buffer for the block, return it with no data read. | ||
294 | * Short-form addressing. | ||
295 | */ | ||
296 | struct xfs_buf * /* buffer for agno/agbno */ | ||
297 | xfs_btree_get_bufs( | ||
298 | struct xfs_mount *mp, /* file system mount point */ | ||
299 | struct xfs_trans *tp, /* transaction pointer */ | ||
300 | xfs_agnumber_t agno, /* allocation group number */ | ||
301 | xfs_agblock_t agbno, /* allocation group block number */ | ||
302 | uint lock); /* lock flags for get_buf */ | ||
303 | |||
304 | /* | ||
305 | * Check for the cursor referring to the last block at the given level. | ||
306 | */ | ||
307 | int /* 1=is last block, 0=not last block */ | ||
308 | xfs_btree_islastblock( | ||
309 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
310 | int level); /* level to check */ | ||
311 | |||
312 | /* | ||
313 | * Compute first and last byte offsets for the fields given. | ||
314 | * Interprets the offsets table, which contains struct field offsets. | ||
315 | */ | ||
316 | void | ||
317 | xfs_btree_offsets( | ||
318 | __int64_t fields, /* bitmask of fields */ | ||
319 | const short *offsets,/* table of field offsets */ | ||
320 | int nbits, /* number of bits to inspect */ | ||
321 | int *first, /* output: first byte offset */ | ||
322 | int *last); /* output: last byte offset */ | ||
323 | |||
324 | /* | ||
325 | * Get a buffer for the block, return it read in. | ||
326 | * Long-form addressing. | ||
327 | */ | ||
328 | int /* error */ | ||
329 | xfs_btree_read_bufl( | ||
330 | struct xfs_mount *mp, /* file system mount point */ | ||
331 | struct xfs_trans *tp, /* transaction pointer */ | ||
332 | xfs_fsblock_t fsbno, /* file system block number */ | ||
333 | uint lock, /* lock flags for read_buf */ | ||
334 | struct xfs_buf **bpp, /* buffer for fsbno */ | ||
335 | int refval, /* ref count value for buffer */ | ||
336 | const struct xfs_buf_ops *ops); | ||
337 | |||
338 | /* | ||
339 | * Read-ahead the block, don't wait for it, don't return a buffer. | ||
340 | * Long-form addressing. | ||
341 | */ | ||
342 | void /* error */ | ||
343 | xfs_btree_reada_bufl( | ||
344 | struct xfs_mount *mp, /* file system mount point */ | ||
345 | xfs_fsblock_t fsbno, /* file system block number */ | ||
346 | xfs_extlen_t count, /* count of filesystem blocks */ | ||
347 | const struct xfs_buf_ops *ops); | ||
348 | |||
349 | /* | ||
350 | * Read-ahead the block, don't wait for it, don't return a buffer. | ||
351 | * Short-form addressing. | ||
352 | */ | ||
353 | void /* error */ | ||
354 | xfs_btree_reada_bufs( | ||
355 | struct xfs_mount *mp, /* file system mount point */ | ||
356 | xfs_agnumber_t agno, /* allocation group number */ | ||
357 | xfs_agblock_t agbno, /* allocation group block number */ | ||
358 | xfs_extlen_t count, /* count of filesystem blocks */ | ||
359 | const struct xfs_buf_ops *ops); | ||
360 | |||
361 | /* | ||
362 | * Initialise a new btree block header | ||
363 | */ | ||
364 | void | ||
365 | xfs_btree_init_block( | ||
366 | struct xfs_mount *mp, | ||
367 | struct xfs_buf *bp, | ||
368 | __u32 magic, | ||
369 | __u16 level, | ||
370 | __u16 numrecs, | ||
371 | __u64 owner, | ||
372 | unsigned int flags); | ||
373 | |||
374 | void | ||
375 | xfs_btree_init_block_int( | ||
376 | struct xfs_mount *mp, | ||
377 | struct xfs_btree_block *buf, | ||
378 | xfs_daddr_t blkno, | ||
379 | __u32 magic, | ||
380 | __u16 level, | ||
381 | __u16 numrecs, | ||
382 | __u64 owner, | ||
383 | unsigned int flags); | ||
384 | |||
385 | /* | ||
386 | * Common btree core entry points. | ||
387 | */ | ||
388 | int xfs_btree_increment(struct xfs_btree_cur *, int, int *); | ||
389 | int xfs_btree_decrement(struct xfs_btree_cur *, int, int *); | ||
390 | int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); | ||
391 | int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); | ||
392 | int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *); | ||
393 | int xfs_btree_insert(struct xfs_btree_cur *, int *); | ||
394 | int xfs_btree_delete(struct xfs_btree_cur *, int *); | ||
395 | int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *); | ||
396 | int xfs_btree_change_owner(struct xfs_btree_cur *cur, __uint64_t new_owner, | ||
397 | struct list_head *buffer_list); | ||
398 | |||
399 | /* | ||
400 | * btree block CRC helpers | ||
401 | */ | ||
402 | void xfs_btree_lblock_calc_crc(struct xfs_buf *); | ||
403 | bool xfs_btree_lblock_verify_crc(struct xfs_buf *); | ||
404 | void xfs_btree_sblock_calc_crc(struct xfs_buf *); | ||
405 | bool xfs_btree_sblock_verify_crc(struct xfs_buf *); | ||
406 | |||
407 | /* | ||
408 | * Internal btree helpers also used by xfs_bmap.c. | ||
409 | */ | ||
410 | void xfs_btree_log_block(struct xfs_btree_cur *, struct xfs_buf *, int); | ||
411 | void xfs_btree_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int, int); | ||
412 | |||
413 | /* | ||
414 | * Helpers. | ||
415 | */ | ||
416 | static inline int xfs_btree_get_numrecs(struct xfs_btree_block *block) | ||
417 | { | ||
418 | return be16_to_cpu(block->bb_numrecs); | ||
419 | } | ||
420 | |||
421 | static inline void xfs_btree_set_numrecs(struct xfs_btree_block *block, | ||
422 | __uint16_t numrecs) | ||
423 | { | ||
424 | block->bb_numrecs = cpu_to_be16(numrecs); | ||
425 | } | ||
426 | |||
427 | static inline int xfs_btree_get_level(struct xfs_btree_block *block) | ||
428 | { | ||
429 | return be16_to_cpu(block->bb_level); | ||
430 | } | ||
431 | |||
432 | |||
433 | /* | ||
434 | * Min and max functions for extlen, agblock, fileoff, and filblks types. | ||
435 | */ | ||
436 | #define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b)) | ||
437 | #define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b)) | ||
438 | #define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b)) | ||
439 | #define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b)) | ||
440 | #define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b)) | ||
441 | #define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b)) | ||
442 | #define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b)) | ||
443 | #define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b)) | ||
444 | |||
445 | #define XFS_FSB_SANITY_CHECK(mp,fsb) \ | ||
446 | (XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \ | ||
447 | XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks) | ||
448 | |||
449 | /* | ||
450 | * Trace hooks. Currently not implemented as they need to be ported | ||
451 | * over to the generic tracing functionality, which is some effort. | ||
452 | * | ||
453 | * i,j = integer (32 bit) | ||
454 | * b = btree block buffer (xfs_buf_t) | ||
455 | * p = btree ptr | ||
456 | * r = btree record | ||
457 | * k = btree key | ||
458 | */ | ||
459 | #define XFS_BTREE_TRACE_ARGBI(c, b, i) | ||
460 | #define XFS_BTREE_TRACE_ARGBII(c, b, i, j) | ||
461 | #define XFS_BTREE_TRACE_ARGI(c, i) | ||
462 | #define XFS_BTREE_TRACE_ARGIPK(c, i, p, s) | ||
463 | #define XFS_BTREE_TRACE_ARGIPR(c, i, p, r) | ||
464 | #define XFS_BTREE_TRACE_ARGIK(c, i, k) | ||
465 | #define XFS_BTREE_TRACE_ARGR(c, r) | ||
466 | #define XFS_BTREE_TRACE_CURSOR(c, t) | ||
467 | |||
468 | #endif /* __XFS_BTREE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_cksum.h b/fs/xfs/libxfs/xfs_cksum.h new file mode 100644 index 000000000000..fad1676ad8cd --- /dev/null +++ b/fs/xfs/libxfs/xfs_cksum.h | |||
@@ -0,0 +1,63 @@ | |||
1 | #ifndef _XFS_CKSUM_H | ||
2 | #define _XFS_CKSUM_H 1 | ||
3 | |||
4 | #define XFS_CRC_SEED (~(__uint32_t)0) | ||
5 | |||
6 | /* | ||
7 | * Calculate the intermediate checksum for a buffer that has the CRC field | ||
8 | * inside it. The offset of the 32bit crc fields is passed as the | ||
9 | * cksum_offset parameter. | ||
10 | */ | ||
11 | static inline __uint32_t | ||
12 | xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset) | ||
13 | { | ||
14 | __uint32_t zero = 0; | ||
15 | __uint32_t crc; | ||
16 | |||
17 | /* Calculate CRC up to the checksum. */ | ||
18 | crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset); | ||
19 | |||
20 | /* Skip checksum field */ | ||
21 | crc = crc32c(crc, &zero, sizeof(__u32)); | ||
22 | |||
23 | /* Calculate the rest of the CRC. */ | ||
24 | return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)], | ||
25 | length - (cksum_offset + sizeof(__be32))); | ||
26 | } | ||
27 | |||
28 | /* | ||
29 | * Convert the intermediate checksum to the final ondisk format. | ||
30 | * | ||
31 | * The CRC32c calculation uses LE format even on BE machines, but returns the | ||
32 | * result in host endian format. Hence we need to byte swap it back to LE format | ||
33 | * so that it is consistent on disk. | ||
34 | */ | ||
35 | static inline __le32 | ||
36 | xfs_end_cksum(__uint32_t crc) | ||
37 | { | ||
38 | return ~cpu_to_le32(crc); | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | * Helper to generate the checksum for a buffer. | ||
43 | */ | ||
44 | static inline void | ||
45 | xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset) | ||
46 | { | ||
47 | __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset); | ||
48 | |||
49 | *(__le32 *)(buffer + cksum_offset) = xfs_end_cksum(crc); | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Helper to verify the checksum for a buffer. | ||
54 | */ | ||
55 | static inline int | ||
56 | xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset) | ||
57 | { | ||
58 | __uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset); | ||
59 | |||
60 | return *(__le32 *)(buffer + cksum_offset) == xfs_end_cksum(crc); | ||
61 | } | ||
62 | |||
63 | #endif /* _XFS_CKSUM_H */ | ||
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h new file mode 100644 index 000000000000..6e153e399a77 --- /dev/null +++ b/fs/xfs/libxfs/xfs_da_btree.h | |||
@@ -0,0 +1,221 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. | ||
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write the Free Software Foundation, | ||
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | #ifndef __XFS_DA_BTREE_H__ | ||
20 | #define __XFS_DA_BTREE_H__ | ||
21 | |||
22 | struct xfs_bmap_free; | ||
23 | struct xfs_inode; | ||
24 | struct xfs_trans; | ||
25 | struct zone; | ||
26 | struct xfs_dir_ops; | ||
27 | |||
28 | /* | ||
29 | * Directory/attribute geometry information. There will be one of these for each | ||
30 | * data fork type, and it will be passed around via the xfs_da_args. Global | ||
31 | * structures will be attached to the xfs_mount. | ||
32 | */ | ||
33 | struct xfs_da_geometry { | ||
34 | int blksize; /* da block size in bytes */ | ||
35 | int fsbcount; /* da block size in filesystem blocks */ | ||
36 | uint8_t fsblog; /* log2 of _filesystem_ block size */ | ||
37 | uint8_t blklog; /* log2 of da block size */ | ||
38 | uint node_ents; /* # of entries in a danode */ | ||
39 | int magicpct; /* 37% of block size in bytes */ | ||
40 | xfs_dablk_t datablk; /* blockno of dir data v2 */ | ||
41 | xfs_dablk_t leafblk; /* blockno of leaf data v2 */ | ||
42 | xfs_dablk_t freeblk; /* blockno of free data v2 */ | ||
43 | }; | ||
44 | |||
45 | /*======================================================================== | ||
46 | * Btree searching and modification structure definitions. | ||
47 | *========================================================================*/ | ||
48 | |||
49 | /* | ||
50 | * Search comparison results | ||
51 | */ | ||
52 | enum xfs_dacmp { | ||
53 | XFS_CMP_DIFFERENT, /* names are completely different */ | ||
54 | XFS_CMP_EXACT, /* names are exactly the same */ | ||
55 | XFS_CMP_CASE /* names are same but differ in case */ | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * Structure to ease passing around component names. | ||
60 | */ | ||
61 | typedef struct xfs_da_args { | ||
62 | struct xfs_da_geometry *geo; /* da block geometry */ | ||
63 | const __uint8_t *name; /* string (maybe not NULL terminated) */ | ||
64 | int namelen; /* length of string (maybe no NULL) */ | ||
65 | __uint8_t filetype; /* filetype of inode for directories */ | ||
66 | __uint8_t *value; /* set of bytes (maybe contain NULLs) */ | ||
67 | int valuelen; /* length of value */ | ||
68 | int flags; /* argument flags (eg: ATTR_NOCREATE) */ | ||
69 | xfs_dahash_t hashval; /* hash value of name */ | ||
70 | xfs_ino_t inumber; /* input/output inode number */ | ||
71 | struct xfs_inode *dp; /* directory inode to manipulate */ | ||
72 | xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ | ||
73 | struct xfs_bmap_free *flist; /* ptr to freelist for bmap_finish */ | ||
74 | struct xfs_trans *trans; /* current trans (changes over time) */ | ||
75 | xfs_extlen_t total; /* total blocks needed, for 1st bmap */ | ||
76 | int whichfork; /* data or attribute fork */ | ||
77 | xfs_dablk_t blkno; /* blkno of attr leaf of interest */ | ||
78 | int index; /* index of attr of interest in blk */ | ||
79 | xfs_dablk_t rmtblkno; /* remote attr value starting blkno */ | ||
80 | int rmtblkcnt; /* remote attr value block count */ | ||
81 | int rmtvaluelen; /* remote attr value length in bytes */ | ||
82 | xfs_dablk_t blkno2; /* blkno of 2nd attr leaf of interest */ | ||
83 | int index2; /* index of 2nd attr in blk */ | ||
84 | xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */ | ||
85 | int rmtblkcnt2; /* remote attr value block count */ | ||
86 | int rmtvaluelen2; /* remote attr value length in bytes */ | ||
87 | int op_flags; /* operation flags */ | ||
88 | enum xfs_dacmp cmpresult; /* name compare result for lookups */ | ||
89 | } xfs_da_args_t; | ||
90 | |||
91 | /* | ||
92 | * Operation flags: | ||
93 | */ | ||
94 | #define XFS_DA_OP_JUSTCHECK 0x0001 /* check for ok with no space */ | ||
95 | #define XFS_DA_OP_RENAME 0x0002 /* this is an atomic rename op */ | ||
96 | #define XFS_DA_OP_ADDNAME 0x0004 /* this is an add operation */ | ||
97 | #define XFS_DA_OP_OKNOENT 0x0008 /* lookup/add op, ENOENT ok, else die */ | ||
98 | #define XFS_DA_OP_CILOOKUP 0x0010 /* lookup to return CI name if found */ | ||
99 | |||
100 | #define XFS_DA_OP_FLAGS \ | ||
101 | { XFS_DA_OP_JUSTCHECK, "JUSTCHECK" }, \ | ||
102 | { XFS_DA_OP_RENAME, "RENAME" }, \ | ||
103 | { XFS_DA_OP_ADDNAME, "ADDNAME" }, \ | ||
104 | { XFS_DA_OP_OKNOENT, "OKNOENT" }, \ | ||
105 | { XFS_DA_OP_CILOOKUP, "CILOOKUP" } | ||
106 | |||
107 | /* | ||
108 | * Storage for holding state during Btree searches and split/join ops. | ||
109 | * | ||
110 | * Only need space for 5 intermediate nodes. With a minimum of 62-way | ||
111 | * fanout to the Btree, we can support over 900 million directory blocks, | ||
112 | * which is slightly more than enough. | ||
113 | */ | ||
114 | typedef struct xfs_da_state_blk { | ||
115 | struct xfs_buf *bp; /* buffer containing block */ | ||
116 | xfs_dablk_t blkno; /* filesystem blkno of buffer */ | ||
117 | xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */ | ||
118 | int index; /* relevant index into block */ | ||
119 | xfs_dahash_t hashval; /* last hash value in block */ | ||
120 | int magic; /* blk's magic number, ie: blk type */ | ||
121 | } xfs_da_state_blk_t; | ||
122 | |||
123 | typedef struct xfs_da_state_path { | ||
124 | int active; /* number of active levels */ | ||
125 | xfs_da_state_blk_t blk[XFS_DA_NODE_MAXDEPTH]; | ||
126 | } xfs_da_state_path_t; | ||
127 | |||
128 | typedef struct xfs_da_state { | ||
129 | xfs_da_args_t *args; /* filename arguments */ | ||
130 | struct xfs_mount *mp; /* filesystem mount point */ | ||
131 | xfs_da_state_path_t path; /* search/split paths */ | ||
132 | xfs_da_state_path_t altpath; /* alternate path for join */ | ||
133 | unsigned char inleaf; /* insert into 1->lf, 0->splf */ | ||
134 | unsigned char extravalid; /* T/F: extrablk is in use */ | ||
135 | unsigned char extraafter; /* T/F: extrablk is after new */ | ||
136 | xfs_da_state_blk_t extrablk; /* for double-splits on leaves */ | ||
137 | /* for dirv2 extrablk is data */ | ||
138 | } xfs_da_state_t; | ||
139 | |||
140 | /* | ||
141 | * Utility macros to aid in logging changed structure fields. | ||
142 | */ | ||
143 | #define XFS_DA_LOGOFF(BASE, ADDR) ((char *)(ADDR) - (char *)(BASE)) | ||
144 | #define XFS_DA_LOGRANGE(BASE, ADDR, SIZE) \ | ||
145 | (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ | ||
146 | (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) | ||
147 | |||
148 | /* | ||
149 | * Name ops for directory and/or attr name operations | ||
150 | */ | ||
151 | struct xfs_nameops { | ||
152 | xfs_dahash_t (*hashname)(struct xfs_name *); | ||
153 | enum xfs_dacmp (*compname)(struct xfs_da_args *, | ||
154 | const unsigned char *, int); | ||
155 | }; | ||
156 | |||
157 | |||
158 | /*======================================================================== | ||
159 | * Function prototypes. | ||
160 | *========================================================================*/ | ||
161 | |||
162 | /* | ||
163 | * Routines used for growing the Btree. | ||
164 | */ | ||
165 | int xfs_da3_node_create(struct xfs_da_args *args, xfs_dablk_t blkno, | ||
166 | int level, struct xfs_buf **bpp, int whichfork); | ||
167 | int xfs_da3_split(xfs_da_state_t *state); | ||
168 | |||
169 | /* | ||
170 | * Routines used for shrinking the Btree. | ||
171 | */ | ||
172 | int xfs_da3_join(xfs_da_state_t *state); | ||
173 | void xfs_da3_fixhashpath(struct xfs_da_state *state, | ||
174 | struct xfs_da_state_path *path_to_to_fix); | ||
175 | |||
176 | /* | ||
177 | * Routines used for finding things in the Btree. | ||
178 | */ | ||
179 | int xfs_da3_node_lookup_int(xfs_da_state_t *state, int *result); | ||
180 | int xfs_da3_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, | ||
181 | int forward, int release, int *result); | ||
182 | /* | ||
183 | * Utility routines. | ||
184 | */ | ||
185 | int xfs_da3_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, | ||
186 | xfs_da_state_blk_t *new_blk); | ||
187 | int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp, | ||
188 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | ||
189 | struct xfs_buf **bpp, int which_fork); | ||
190 | |||
191 | /* | ||
192 | * Utility routines. | ||
193 | */ | ||
194 | int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno); | ||
195 | int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno, | ||
196 | int count); | ||
197 | int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, | ||
198 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | ||
199 | struct xfs_buf **bp, int whichfork); | ||
200 | int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp, | ||
201 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | ||
202 | struct xfs_buf **bpp, int whichfork, | ||
203 | const struct xfs_buf_ops *ops); | ||
204 | xfs_daddr_t xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno, | ||
205 | xfs_daddr_t mapped_bno, int whichfork, | ||
206 | const struct xfs_buf_ops *ops); | ||
207 | int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | ||
208 | struct xfs_buf *dead_buf); | ||
209 | |||
210 | uint xfs_da_hashname(const __uint8_t *name_string, int name_length); | ||
211 | enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, | ||
212 | const unsigned char *name, int len); | ||
213 | |||
214 | |||
215 | xfs_da_state_t *xfs_da_state_alloc(void); | ||
216 | void xfs_da_state_free(xfs_da_state_t *state); | ||
217 | |||
218 | extern struct kmem_zone *xfs_da_state_zone; | ||
219 | extern const struct xfs_nameops xfs_default_nameops; | ||
220 | |||
221 | #endif /* __XFS_DA_BTREE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h new file mode 100644 index 000000000000..0a49b0286372 --- /dev/null +++ b/fs/xfs/libxfs/xfs_da_format.h | |||
@@ -0,0 +1,861 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | ||
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write the Free Software Foundation, | ||
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | #ifndef __XFS_DA_FORMAT_H__ | ||
20 | #define __XFS_DA_FORMAT_H__ | ||
21 | |||
22 | /* | ||
23 | * This structure is common to both leaf nodes and non-leaf nodes in the Btree. | ||
24 | * | ||
25 | * It is used to manage a doubly linked list of all blocks at the same | ||
26 | * level in the Btree, and to identify which type of block this is. | ||
27 | */ | ||
28 | #define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ | ||
29 | #define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ | ||
30 | #define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ | ||
31 | #define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ | ||
32 | |||
33 | typedef struct xfs_da_blkinfo { | ||
34 | __be32 forw; /* previous block in list */ | ||
35 | __be32 back; /* following block in list */ | ||
36 | __be16 magic; /* validity check on block */ | ||
37 | __be16 pad; /* unused */ | ||
38 | } xfs_da_blkinfo_t; | ||
39 | |||
40 | /* | ||
41 | * CRC enabled directory structure types | ||
42 | * | ||
43 | * The headers change size for the additional verification information, but | ||
44 | * otherwise the tree layouts and contents are unchanged. Hence the da btree | ||
45 | * code can use the struct xfs_da_blkinfo for manipulating the tree links and | ||
46 | * magic numbers without modification for both v2 and v3 nodes. | ||
47 | */ | ||
48 | #define XFS_DA3_NODE_MAGIC 0x3ebe /* magic number: non-leaf blocks */ | ||
49 | #define XFS_ATTR3_LEAF_MAGIC 0x3bee /* magic number: attribute leaf blks */ | ||
50 | #define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ | ||
51 | #define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ | ||
52 | |||
53 | struct xfs_da3_blkinfo { | ||
54 | /* | ||
55 | * the node link manipulation code relies on the fact that the first | ||
56 | * element of this structure is the struct xfs_da_blkinfo so it can | ||
57 | * ignore the differences in the rest of the structures. | ||
58 | */ | ||
59 | struct xfs_da_blkinfo hdr; | ||
60 | __be32 crc; /* CRC of block */ | ||
61 | __be64 blkno; /* first block of the buffer */ | ||
62 | __be64 lsn; /* sequence number of last write */ | ||
63 | uuid_t uuid; /* filesystem we belong to */ | ||
64 | __be64 owner; /* inode that owns the block */ | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * This is the structure of the root and intermediate nodes in the Btree. | ||
69 | * The leaf nodes are defined above. | ||
70 | * | ||
71 | * Entries are not packed. | ||
72 | * | ||
73 | * Since we have duplicate keys, use a binary search but always follow | ||
74 | * all match in the block, not just the first match found. | ||
75 | */ | ||
76 | #define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */ | ||
77 | |||
78 | typedef struct xfs_da_node_hdr { | ||
79 | struct xfs_da_blkinfo info; /* block type, links, etc. */ | ||
80 | __be16 __count; /* count of active entries */ | ||
81 | __be16 __level; /* level above leaves (leaf == 0) */ | ||
82 | } xfs_da_node_hdr_t; | ||
83 | |||
84 | struct xfs_da3_node_hdr { | ||
85 | struct xfs_da3_blkinfo info; /* block type, links, etc. */ | ||
86 | __be16 __count; /* count of active entries */ | ||
87 | __be16 __level; /* level above leaves (leaf == 0) */ | ||
88 | __be32 __pad32; | ||
89 | }; | ||
90 | |||
91 | #define XFS_DA3_NODE_CRC_OFF (offsetof(struct xfs_da3_node_hdr, info.crc)) | ||
92 | |||
93 | typedef struct xfs_da_node_entry { | ||
94 | __be32 hashval; /* hash value for this descendant */ | ||
95 | __be32 before; /* Btree block before this key */ | ||
96 | } xfs_da_node_entry_t; | ||
97 | |||
98 | typedef struct xfs_da_intnode { | ||
99 | struct xfs_da_node_hdr hdr; | ||
100 | struct xfs_da_node_entry __btree[]; | ||
101 | } xfs_da_intnode_t; | ||
102 | |||
103 | struct xfs_da3_intnode { | ||
104 | struct xfs_da3_node_hdr hdr; | ||
105 | struct xfs_da_node_entry __btree[]; | ||
106 | }; | ||
107 | |||
108 | /* | ||
109 | * In-core version of the node header to abstract the differences in the v2 and | ||
110 | * v3 disk format of the headers. Callers need to convert to/from disk format as | ||
111 | * appropriate. | ||
112 | */ | ||
113 | struct xfs_da3_icnode_hdr { | ||
114 | __uint32_t forw; | ||
115 | __uint32_t back; | ||
116 | __uint16_t magic; | ||
117 | __uint16_t count; | ||
118 | __uint16_t level; | ||
119 | }; | ||
120 | |||
121 | /* | ||
122 | * Directory version 2. | ||
123 | * | ||
124 | * There are 4 possible formats: | ||
125 | * - shortform - embedded into the inode | ||
126 | * - single block - data with embedded leaf at the end | ||
127 | * - multiple data blocks, single leaf+freeindex block | ||
128 | * - data blocks, node and leaf blocks (btree), freeindex blocks | ||
129 | * | ||
130 | * Note: many node blocks structures and constants are shared with the attr | ||
131 | * code and defined in xfs_da_btree.h. | ||
132 | */ | ||
133 | |||
134 | #define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: single block dirs */ | ||
135 | #define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: multiblock dirs */ | ||
136 | #define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */ | ||
137 | |||
138 | /* | ||
139 | * Directory Version 3 With CRCs. | ||
140 | * | ||
141 | * The tree formats are the same as for version 2 directories. The difference | ||
142 | * is in the block header and dirent formats. In many cases the v3 structures | ||
143 | * use v2 definitions as they are no different and this makes code sharing much | ||
144 | * easier. | ||
145 | * | ||
146 | * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the | ||
147 | * format is v2 then they switch to the existing v2 code, or the format is v3 | ||
148 | * they implement the v3 functionality. This means the existing dir2 is a mix of | ||
149 | * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called | ||
150 | * where there is a difference in the formats, otherwise the code is unchanged. | ||
151 | * | ||
152 | * Where it is possible, the code decides what to do based on the magic numbers | ||
153 | * in the blocks rather than feature bits in the superblock. This means the code | ||
154 | * is as independent of the external XFS code as possible as doesn't require | ||
155 | * passing struct xfs_mount pointers into places where it isn't really | ||
156 | * necessary. | ||
157 | * | ||
158 | * Version 3 includes: | ||
159 | * | ||
160 | * - a larger block header for CRC and identification purposes and so the | ||
161 | * offsets of all the structures inside the blocks are different. | ||
162 | * | ||
163 | * - new magic numbers to be able to detect the v2/v3 types on the fly. | ||
164 | */ | ||
165 | |||
166 | #define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */ | ||
167 | #define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */ | ||
168 | #define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */ | ||
169 | |||
170 | /* | ||
171 | * Dirents in version 3 directories have a file type field. Additions to this | ||
172 | * list are an on-disk format change, requiring feature bits. Valid values | ||
173 | * are as follows: | ||
174 | */ | ||
175 | #define XFS_DIR3_FT_UNKNOWN 0 | ||
176 | #define XFS_DIR3_FT_REG_FILE 1 | ||
177 | #define XFS_DIR3_FT_DIR 2 | ||
178 | #define XFS_DIR3_FT_CHRDEV 3 | ||
179 | #define XFS_DIR3_FT_BLKDEV 4 | ||
180 | #define XFS_DIR3_FT_FIFO 5 | ||
181 | #define XFS_DIR3_FT_SOCK 6 | ||
182 | #define XFS_DIR3_FT_SYMLINK 7 | ||
183 | #define XFS_DIR3_FT_WHT 8 | ||
184 | |||
185 | #define XFS_DIR3_FT_MAX 9 | ||
186 | |||
187 | /* | ||
188 | * Byte offset in data block and shortform entry. | ||
189 | */ | ||
190 | typedef __uint16_t xfs_dir2_data_off_t; | ||
191 | #define NULLDATAOFF 0xffffU | ||
192 | typedef uint xfs_dir2_data_aoff_t; /* argument form */ | ||
193 | |||
194 | /* | ||
195 | * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. | ||
196 | * Only need 16 bits, this is the byte offset into the single block form. | ||
197 | */ | ||
198 | typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; | ||
199 | |||
200 | /* | ||
201 | * Offset in data space of a data entry. | ||
202 | */ | ||
203 | typedef __uint32_t xfs_dir2_dataptr_t; | ||
204 | #define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff) | ||
205 | #define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0) | ||
206 | |||
207 | /* | ||
208 | * Byte offset in a directory. | ||
209 | */ | ||
210 | typedef xfs_off_t xfs_dir2_off_t; | ||
211 | |||
212 | /* | ||
213 | * Directory block number (logical dirblk in file) | ||
214 | */ | ||
215 | typedef __uint32_t xfs_dir2_db_t; | ||
216 | |||
217 | /* | ||
218 | * Inode number stored as 8 8-bit values. | ||
219 | */ | ||
220 | typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; | ||
221 | |||
222 | /* | ||
223 | * Inode number stored as 4 8-bit values. | ||
224 | * Works a lot of the time, when all the inode numbers in a directory | ||
225 | * fit in 32 bits. | ||
226 | */ | ||
227 | typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; | ||
228 | |||
229 | typedef union { | ||
230 | xfs_dir2_ino8_t i8; | ||
231 | xfs_dir2_ino4_t i4; | ||
232 | } xfs_dir2_inou_t; | ||
233 | #define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL) | ||
234 | |||
235 | /* | ||
236 | * Directory layout when stored internal to an inode. | ||
237 | * | ||
238 | * Small directories are packed as tightly as possible so as to fit into the | ||
239 | * literal area of the inode. These "shortform" directories consist of a | ||
240 | * single xfs_dir2_sf_hdr header followed by zero or more xfs_dir2_sf_entry | ||
241 | * structures. Due the different inode number storage size and the variable | ||
242 | * length name field in the xfs_dir2_sf_entry all these structure are | ||
243 | * variable length, and the accessors in this file should be used to iterate | ||
244 | * over them. | ||
245 | */ | ||
246 | typedef struct xfs_dir2_sf_hdr { | ||
247 | __uint8_t count; /* count of entries */ | ||
248 | __uint8_t i8count; /* count of 8-byte inode #s */ | ||
249 | xfs_dir2_inou_t parent; /* parent dir inode number */ | ||
250 | } __arch_pack xfs_dir2_sf_hdr_t; | ||
251 | |||
252 | typedef struct xfs_dir2_sf_entry { | ||
253 | __u8 namelen; /* actual name length */ | ||
254 | xfs_dir2_sf_off_t offset; /* saved offset */ | ||
255 | __u8 name[]; /* name, variable size */ | ||
256 | /* | ||
257 | * A single byte containing the file type field follows the inode | ||
258 | * number for version 3 directory entries. | ||
259 | * | ||
260 | * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a | ||
261 | * variable offset after the name. | ||
262 | */ | ||
263 | } __arch_pack xfs_dir2_sf_entry_t; | ||
264 | |||
265 | static inline int xfs_dir2_sf_hdr_size(int i8count) | ||
266 | { | ||
267 | return sizeof(struct xfs_dir2_sf_hdr) - | ||
268 | (i8count == 0) * | ||
269 | (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t)); | ||
270 | } | ||
271 | |||
272 | static inline xfs_dir2_data_aoff_t | ||
273 | xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) | ||
274 | { | ||
275 | return get_unaligned_be16(&sfep->offset.i); | ||
276 | } | ||
277 | |||
278 | static inline void | ||
279 | xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) | ||
280 | { | ||
281 | put_unaligned_be16(off, &sfep->offset.i); | ||
282 | } | ||
283 | |||
284 | static inline struct xfs_dir2_sf_entry * | ||
285 | xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) | ||
286 | { | ||
287 | return (struct xfs_dir2_sf_entry *) | ||
288 | ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Data block structures. | ||
293 | * | ||
294 | * A pure data block looks like the following drawing on disk: | ||
295 | * | ||
296 | * +-------------------------------------------------+ | ||
297 | * | xfs_dir2_data_hdr_t | | ||
298 | * +-------------------------------------------------+ | ||
299 | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | ||
300 | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | ||
301 | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | ||
302 | * | ... | | ||
303 | * +-------------------------------------------------+ | ||
304 | * | unused space | | ||
305 | * +-------------------------------------------------+ | ||
306 | * | ||
307 | * As all the entries are variable size structures the accessors below should | ||
308 | * be used to iterate over them. | ||
309 | * | ||
310 | * In addition to the pure data blocks for the data and node formats, | ||
311 | * most structures are also used for the combined data/freespace "block" | ||
312 | * format below. | ||
313 | */ | ||
314 | |||
315 | #define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */ | ||
316 | #define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG) | ||
317 | #define XFS_DIR2_DATA_FREE_TAG 0xffff | ||
318 | #define XFS_DIR2_DATA_FD_COUNT 3 | ||
319 | |||
320 | /* | ||
321 | * Directory address space divided into sections, | ||
322 | * spaces separated by 32GB. | ||
323 | */ | ||
324 | #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) | ||
325 | #define XFS_DIR2_DATA_SPACE 0 | ||
326 | #define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE) | ||
327 | |||
328 | /* | ||
329 | * Describe a free area in the data block. | ||
330 | * | ||
331 | * The freespace will be formatted as a xfs_dir2_data_unused_t. | ||
332 | */ | ||
333 | typedef struct xfs_dir2_data_free { | ||
334 | __be16 offset; /* start of freespace */ | ||
335 | __be16 length; /* length of freespace */ | ||
336 | } xfs_dir2_data_free_t; | ||
337 | |||
338 | /* | ||
339 | * Header for the data blocks. | ||
340 | * | ||
341 | * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. | ||
342 | */ | ||
343 | typedef struct xfs_dir2_data_hdr { | ||
344 | __be32 magic; /* XFS_DIR2_DATA_MAGIC or */ | ||
345 | /* XFS_DIR2_BLOCK_MAGIC */ | ||
346 | xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; | ||
347 | } xfs_dir2_data_hdr_t; | ||
348 | |||
349 | /* | ||
350 | * define a structure for all the verification fields we are adding to the | ||
351 | * directory block structures. This will be used in several structures. | ||
352 | * The magic number must be the first entry to align with all the dir2 | ||
353 | * structures so we determine how to decode them just by the magic number. | ||
354 | */ | ||
355 | struct xfs_dir3_blk_hdr { | ||
356 | __be32 magic; /* magic number */ | ||
357 | __be32 crc; /* CRC of block */ | ||
358 | __be64 blkno; /* first block of the buffer */ | ||
359 | __be64 lsn; /* sequence number of last write */ | ||
360 | uuid_t uuid; /* filesystem we belong to */ | ||
361 | __be64 owner; /* inode that owns the block */ | ||
362 | }; | ||
363 | |||
364 | struct xfs_dir3_data_hdr { | ||
365 | struct xfs_dir3_blk_hdr hdr; | ||
366 | xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT]; | ||
367 | __be32 pad; /* 64 bit alignment */ | ||
368 | }; | ||
369 | |||
370 | #define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc) | ||
371 | |||
372 | /* | ||
373 | * Active entry in a data block. | ||
374 | * | ||
375 | * Aligned to 8 bytes. After the variable length name field there is a | ||
376 | * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p. | ||
377 | * | ||
378 | * For dir3 structures, there is file type field between the name and the tag. | ||
379 | * This can only be manipulated by helper functions. It is packed hard against | ||
380 | * the end of the name so any padding for rounding is between the file type and | ||
381 | * the tag. | ||
382 | */ | ||
383 | typedef struct xfs_dir2_data_entry { | ||
384 | __be64 inumber; /* inode number */ | ||
385 | __u8 namelen; /* name length */ | ||
386 | __u8 name[]; /* name bytes, no null */ | ||
387 | /* __u8 filetype; */ /* type of inode we point to */ | ||
388 | /* __be16 tag; */ /* starting offset of us */ | ||
389 | } xfs_dir2_data_entry_t; | ||
390 | |||
391 | /* | ||
392 | * Unused entry in a data block. | ||
393 | * | ||
394 | * Aligned to 8 bytes. Tag appears as the last 2 bytes and must be accessed | ||
395 | * using xfs_dir2_data_unused_tag_p. | ||
396 | */ | ||
397 | typedef struct xfs_dir2_data_unused { | ||
398 | __be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */ | ||
399 | __be16 length; /* total free length */ | ||
400 | /* variable offset */ | ||
401 | __be16 tag; /* starting offset of us */ | ||
402 | } xfs_dir2_data_unused_t; | ||
403 | |||
404 | /* | ||
405 | * Pointer to a freespace's tag word. | ||
406 | */ | ||
407 | static inline __be16 * | ||
408 | xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup) | ||
409 | { | ||
410 | return (__be16 *)((char *)dup + | ||
411 | be16_to_cpu(dup->length) - sizeof(__be16)); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Leaf block structures. | ||
416 | * | ||
417 | * A pure leaf block looks like the following drawing on disk: | ||
418 | * | ||
419 | * +---------------------------+ | ||
420 | * | xfs_dir2_leaf_hdr_t | | ||
421 | * +---------------------------+ | ||
422 | * | xfs_dir2_leaf_entry_t | | ||
423 | * | xfs_dir2_leaf_entry_t | | ||
424 | * | xfs_dir2_leaf_entry_t | | ||
425 | * | xfs_dir2_leaf_entry_t | | ||
426 | * | ... | | ||
427 | * +---------------------------+ | ||
428 | * | xfs_dir2_data_off_t | | ||
429 | * | xfs_dir2_data_off_t | | ||
430 | * | xfs_dir2_data_off_t | | ||
431 | * | ... | | ||
432 | * +---------------------------+ | ||
433 | * | xfs_dir2_leaf_tail_t | | ||
434 | * +---------------------------+ | ||
435 | * | ||
436 | * The xfs_dir2_data_off_t members (bests) and tail are at the end of the block | ||
437 | * for single-leaf (magic = XFS_DIR2_LEAF1_MAGIC) blocks only, but not present | ||
438 | * for directories with separate leaf nodes and free space blocks | ||
439 | * (magic = XFS_DIR2_LEAFN_MAGIC). | ||
440 | * | ||
441 | * As all the entries are variable size structures the accessors below should | ||
442 | * be used to iterate over them. | ||
443 | */ | ||
444 | |||
445 | /* | ||
446 | * Offset of the leaf/node space. First block in this space | ||
447 | * is the btree root. | ||
448 | */ | ||
449 | #define XFS_DIR2_LEAF_SPACE 1 | ||
450 | #define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) | ||
451 | |||
452 | /* | ||
453 | * Leaf block header. | ||
454 | */ | ||
455 | typedef struct xfs_dir2_leaf_hdr { | ||
456 | xfs_da_blkinfo_t info; /* header for da routines */ | ||
457 | __be16 count; /* count of entries */ | ||
458 | __be16 stale; /* count of stale entries */ | ||
459 | } xfs_dir2_leaf_hdr_t; | ||
460 | |||
461 | struct xfs_dir3_leaf_hdr { | ||
462 | struct xfs_da3_blkinfo info; /* header for da routines */ | ||
463 | __be16 count; /* count of entries */ | ||
464 | __be16 stale; /* count of stale entries */ | ||
465 | __be32 pad; /* 64 bit alignment */ | ||
466 | }; | ||
467 | |||
468 | struct xfs_dir3_icleaf_hdr { | ||
469 | __uint32_t forw; | ||
470 | __uint32_t back; | ||
471 | __uint16_t magic; | ||
472 | __uint16_t count; | ||
473 | __uint16_t stale; | ||
474 | }; | ||
475 | |||
476 | /* | ||
477 | * Leaf block entry. | ||
478 | */ | ||
479 | typedef struct xfs_dir2_leaf_entry { | ||
480 | __be32 hashval; /* hash value of name */ | ||
481 | __be32 address; /* address of data entry */ | ||
482 | } xfs_dir2_leaf_entry_t; | ||
483 | |||
484 | /* | ||
485 | * Leaf block tail. | ||
486 | */ | ||
487 | typedef struct xfs_dir2_leaf_tail { | ||
488 | __be32 bestcount; | ||
489 | } xfs_dir2_leaf_tail_t; | ||
490 | |||
491 | /* | ||
492 | * Leaf block. | ||
493 | */ | ||
494 | typedef struct xfs_dir2_leaf { | ||
495 | xfs_dir2_leaf_hdr_t hdr; /* leaf header */ | ||
496 | xfs_dir2_leaf_entry_t __ents[]; /* entries */ | ||
497 | } xfs_dir2_leaf_t; | ||
498 | |||
499 | struct xfs_dir3_leaf { | ||
500 | struct xfs_dir3_leaf_hdr hdr; /* leaf header */ | ||
501 | struct xfs_dir2_leaf_entry __ents[]; /* entries */ | ||
502 | }; | ||
503 | |||
504 | #define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) | ||
505 | |||
506 | /* | ||
507 | * Get address of the bests array in the single-leaf block. | ||
508 | */ | ||
509 | static inline __be16 * | ||
510 | xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) | ||
511 | { | ||
512 | return (__be16 *)ltp - be32_to_cpu(ltp->bestcount); | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * Free space block defintions for the node format. | ||
517 | */ | ||
518 | |||
519 | /* | ||
520 | * Offset of the freespace index. | ||
521 | */ | ||
522 | #define XFS_DIR2_FREE_SPACE 2 | ||
523 | #define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) | ||
524 | |||
525 | typedef struct xfs_dir2_free_hdr { | ||
526 | __be32 magic; /* XFS_DIR2_FREE_MAGIC */ | ||
527 | __be32 firstdb; /* db of first entry */ | ||
528 | __be32 nvalid; /* count of valid entries */ | ||
529 | __be32 nused; /* count of used entries */ | ||
530 | } xfs_dir2_free_hdr_t; | ||
531 | |||
532 | typedef struct xfs_dir2_free { | ||
533 | xfs_dir2_free_hdr_t hdr; /* block header */ | ||
534 | __be16 bests[]; /* best free counts */ | ||
535 | /* unused entries are -1 */ | ||
536 | } xfs_dir2_free_t; | ||
537 | |||
538 | struct xfs_dir3_free_hdr { | ||
539 | struct xfs_dir3_blk_hdr hdr; | ||
540 | __be32 firstdb; /* db of first entry */ | ||
541 | __be32 nvalid; /* count of valid entries */ | ||
542 | __be32 nused; /* count of used entries */ | ||
543 | __be32 pad; /* 64 bit alignment */ | ||
544 | }; | ||
545 | |||
546 | struct xfs_dir3_free { | ||
547 | struct xfs_dir3_free_hdr hdr; | ||
548 | __be16 bests[]; /* best free counts */ | ||
549 | /* unused entries are -1 */ | ||
550 | }; | ||
551 | |||
552 | #define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc) | ||
553 | |||
554 | /* | ||
555 | * In core version of the free block header, abstracted away from on-disk format | ||
556 | * differences. Use this in the code, and convert to/from the disk version using | ||
557 | * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk. | ||
558 | */ | ||
559 | struct xfs_dir3_icfree_hdr { | ||
560 | __uint32_t magic; | ||
561 | __uint32_t firstdb; | ||
562 | __uint32_t nvalid; | ||
563 | __uint32_t nused; | ||
564 | |||
565 | }; | ||
566 | |||
567 | /* | ||
568 | * Single block format. | ||
569 | * | ||
570 | * The single block format looks like the following drawing on disk: | ||
571 | * | ||
572 | * +-------------------------------------------------+ | ||
573 | * | xfs_dir2_data_hdr_t | | ||
574 | * +-------------------------------------------------+ | ||
575 | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | ||
576 | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t | | ||
577 | * | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t : | ||
578 | * | ... | | ||
579 | * +-------------------------------------------------+ | ||
580 | * | unused space | | ||
581 | * +-------------------------------------------------+ | ||
582 | * | ... | | ||
583 | * | xfs_dir2_leaf_entry_t | | ||
584 | * | xfs_dir2_leaf_entry_t | | ||
585 | * +-------------------------------------------------+ | ||
586 | * | xfs_dir2_block_tail_t | | ||
587 | * +-------------------------------------------------+ | ||
588 | * | ||
589 | * As all the entries are variable size structures the accessors below should | ||
590 | * be used to iterate over them. | ||
591 | */ | ||
592 | |||
593 | typedef struct xfs_dir2_block_tail { | ||
594 | __be32 count; /* count of leaf entries */ | ||
595 | __be32 stale; /* count of stale lf entries */ | ||
596 | } xfs_dir2_block_tail_t; | ||
597 | |||
598 | /* | ||
599 | * Pointer to the leaf entries embedded in a data block (1-block format) | ||
600 | */ | ||
601 | static inline struct xfs_dir2_leaf_entry * | ||
602 | xfs_dir2_block_leaf_p(struct xfs_dir2_block_tail *btp) | ||
603 | { | ||
604 | return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count); | ||
605 | } | ||
606 | |||
607 | |||
608 | /* | ||
609 | * Attribute storage layout | ||
610 | * | ||
611 | * Attribute lists are structured around Btrees where all the data | ||
612 | * elements are in the leaf nodes. Attribute names are hashed into an int, | ||
613 | * then that int is used as the index into the Btree. Since the hashval | ||
614 | * of an attribute name may not be unique, we may have duplicate keys. The | ||
615 | * internal links in the Btree are logical block offsets into the file. | ||
616 | * | ||
617 | * Struct leaf_entry's are packed from the top. Name/values grow from the | ||
618 | * bottom but are not packed. The freemap contains run-length-encoded entries | ||
619 | * for the free bytes after the leaf_entry's, but only the N largest such, | ||
620 | * smaller runs are dropped. When the freemap doesn't show enough space | ||
621 | * for an allocation, we compact the name/value area and try again. If we | ||
622 | * still don't have enough space, then we have to split the block. The | ||
623 | * name/value structs (both local and remote versions) must be 32bit aligned. | ||
624 | * | ||
625 | * Since we have duplicate hash keys, for each key that matches, compare | ||
626 | * the actual name string. The root and intermediate node search always | ||
627 | * takes the first-in-the-block key match found, so we should only have | ||
628 | * to work "forw"ard. If none matches, continue with the "forw"ard leaf | ||
629 | * nodes until the hash key changes or the attribute name is found. | ||
630 | * | ||
631 | * We store the fact that an attribute is a ROOT/USER/SECURE attribute in | ||
632 | * the leaf_entry. The namespaces are independent only because we also look | ||
633 | * at the namespace bit when we are looking for a matching attribute name. | ||
634 | * | ||
635 | * We also store an "incomplete" bit in the leaf_entry. It shows that an | ||
636 | * attribute is in the middle of being created and should not be shown to | ||
637 | * the user if we crash during the time that the bit is set. We clear the | ||
638 | * bit when we have finished setting up the attribute. We do this because | ||
639 | * we cannot create some large attributes inside a single transaction, and we | ||
640 | * need some indication that we weren't finished if we crash in the middle. | ||
641 | */ | ||
642 | #define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */ | ||
643 | |||
644 | typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */ | ||
645 | __be16 base; /* base of free region */ | ||
646 | __be16 size; /* length of free region */ | ||
647 | } xfs_attr_leaf_map_t; | ||
648 | |||
649 | typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */ | ||
650 | xfs_da_blkinfo_t info; /* block type, links, etc. */ | ||
651 | __be16 count; /* count of active leaf_entry's */ | ||
652 | __be16 usedbytes; /* num bytes of names/values stored */ | ||
653 | __be16 firstused; /* first used byte in name area */ | ||
654 | __u8 holes; /* != 0 if blk needs compaction */ | ||
655 | __u8 pad1; | ||
656 | xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE]; | ||
657 | /* N largest free regions */ | ||
658 | } xfs_attr_leaf_hdr_t; | ||
659 | |||
660 | typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */ | ||
661 | __be32 hashval; /* hash value of name */ | ||
662 | __be16 nameidx; /* index into buffer of name/value */ | ||
663 | __u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */ | ||
664 | __u8 pad2; /* unused pad byte */ | ||
665 | } xfs_attr_leaf_entry_t; | ||
666 | |||
667 | typedef struct xfs_attr_leaf_name_local { | ||
668 | __be16 valuelen; /* number of bytes in value */ | ||
669 | __u8 namelen; /* length of name bytes */ | ||
670 | __u8 nameval[1]; /* name/value bytes */ | ||
671 | } xfs_attr_leaf_name_local_t; | ||
672 | |||
673 | typedef struct xfs_attr_leaf_name_remote { | ||
674 | __be32 valueblk; /* block number of value bytes */ | ||
675 | __be32 valuelen; /* number of bytes in value */ | ||
676 | __u8 namelen; /* length of name bytes */ | ||
677 | __u8 name[1]; /* name bytes */ | ||
678 | } xfs_attr_leaf_name_remote_t; | ||
679 | |||
680 | typedef struct xfs_attr_leafblock { | ||
681 | xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ | ||
682 | xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ | ||
683 | xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */ | ||
684 | xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */ | ||
685 | } xfs_attr_leafblock_t; | ||
686 | |||
687 | /* | ||
688 | * CRC enabled leaf structures. Called "version 3" structures to match the | ||
689 | * version number of the directory and dablk structures for this feature, and | ||
690 | * attr2 is already taken by the variable inode attribute fork size feature. | ||
691 | */ | ||
692 | struct xfs_attr3_leaf_hdr { | ||
693 | struct xfs_da3_blkinfo info; | ||
694 | __be16 count; | ||
695 | __be16 usedbytes; | ||
696 | __be16 firstused; | ||
697 | __u8 holes; | ||
698 | __u8 pad1; | ||
699 | struct xfs_attr_leaf_map freemap[XFS_ATTR_LEAF_MAPSIZE]; | ||
700 | __be32 pad2; /* 64 bit alignment */ | ||
701 | }; | ||
702 | |||
703 | #define XFS_ATTR3_LEAF_CRC_OFF (offsetof(struct xfs_attr3_leaf_hdr, info.crc)) | ||
704 | |||
705 | struct xfs_attr3_leafblock { | ||
706 | struct xfs_attr3_leaf_hdr hdr; | ||
707 | struct xfs_attr_leaf_entry entries[1]; | ||
708 | |||
709 | /* | ||
710 | * The rest of the block contains the following structures after the | ||
711 | * leaf entries, growing from the bottom up. The variables are never | ||
712 | * referenced, the locations accessed purely from helper functions. | ||
713 | * | ||
714 | * struct xfs_attr_leaf_name_local | ||
715 | * struct xfs_attr_leaf_name_remote | ||
716 | */ | ||
717 | }; | ||
718 | |||
719 | /* | ||
720 | * incore, neutral version of the attribute leaf header | ||
721 | */ | ||
722 | struct xfs_attr3_icleaf_hdr { | ||
723 | __uint32_t forw; | ||
724 | __uint32_t back; | ||
725 | __uint16_t magic; | ||
726 | __uint16_t count; | ||
727 | __uint16_t usedbytes; | ||
728 | __uint16_t firstused; | ||
729 | __u8 holes; | ||
730 | struct { | ||
731 | __uint16_t base; | ||
732 | __uint16_t size; | ||
733 | } freemap[XFS_ATTR_LEAF_MAPSIZE]; | ||
734 | }; | ||
735 | |||
736 | /* | ||
737 | * Flags used in the leaf_entry[i].flags field. | ||
738 | * NOTE: the INCOMPLETE bit must not collide with the flags bits specified | ||
739 | * on the system call, they are "or"ed together for various operations. | ||
740 | */ | ||
741 | #define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */ | ||
742 | #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ | ||
743 | #define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ | ||
744 | #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ | ||
745 | #define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT) | ||
746 | #define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT) | ||
747 | #define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT) | ||
748 | #define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT) | ||
749 | |||
750 | /* | ||
751 | * Conversion macros for converting namespace bits from argument flags | ||
752 | * to ondisk flags. | ||
753 | */ | ||
754 | #define XFS_ATTR_NSP_ARGS_MASK (ATTR_ROOT | ATTR_SECURE) | ||
755 | #define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | XFS_ATTR_SECURE) | ||
756 | #define XFS_ATTR_NSP_ONDISK(flags) ((flags) & XFS_ATTR_NSP_ONDISK_MASK) | ||
757 | #define XFS_ATTR_NSP_ARGS(flags) ((flags) & XFS_ATTR_NSP_ARGS_MASK) | ||
758 | #define XFS_ATTR_NSP_ARGS_TO_ONDISK(x) (((x) & ATTR_ROOT ? XFS_ATTR_ROOT : 0) |\ | ||
759 | ((x) & ATTR_SECURE ? XFS_ATTR_SECURE : 0)) | ||
760 | #define XFS_ATTR_NSP_ONDISK_TO_ARGS(x) (((x) & XFS_ATTR_ROOT ? ATTR_ROOT : 0) |\ | ||
761 | ((x) & XFS_ATTR_SECURE ? ATTR_SECURE : 0)) | ||
762 | |||
763 | /* | ||
764 | * Alignment for namelist and valuelist entries (since they are mixed | ||
765 | * there can be only one alignment value) | ||
766 | */ | ||
767 | #define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t)) | ||
768 | |||
769 | static inline int | ||
770 | xfs_attr3_leaf_hdr_size(struct xfs_attr_leafblock *leafp) | ||
771 | { | ||
772 | if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) | ||
773 | return sizeof(struct xfs_attr3_leaf_hdr); | ||
774 | return sizeof(struct xfs_attr_leaf_hdr); | ||
775 | } | ||
776 | |||
777 | static inline struct xfs_attr_leaf_entry * | ||
778 | xfs_attr3_leaf_entryp(xfs_attr_leafblock_t *leafp) | ||
779 | { | ||
780 | if (leafp->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) | ||
781 | return &((struct xfs_attr3_leafblock *)leafp)->entries[0]; | ||
782 | return &leafp->entries[0]; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Cast typed pointers for "local" and "remote" name/value structs. | ||
787 | */ | ||
788 | static inline char * | ||
789 | xfs_attr3_leaf_name(xfs_attr_leafblock_t *leafp, int idx) | ||
790 | { | ||
791 | struct xfs_attr_leaf_entry *entries = xfs_attr3_leaf_entryp(leafp); | ||
792 | |||
793 | return &((char *)leafp)[be16_to_cpu(entries[idx].nameidx)]; | ||
794 | } | ||
795 | |||
796 | static inline xfs_attr_leaf_name_remote_t * | ||
797 | xfs_attr3_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx) | ||
798 | { | ||
799 | return (xfs_attr_leaf_name_remote_t *)xfs_attr3_leaf_name(leafp, idx); | ||
800 | } | ||
801 | |||
802 | static inline xfs_attr_leaf_name_local_t * | ||
803 | xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx) | ||
804 | { | ||
805 | return (xfs_attr_leaf_name_local_t *)xfs_attr3_leaf_name(leafp, idx); | ||
806 | } | ||
807 | |||
808 | /* | ||
809 | * Calculate total bytes used (including trailing pad for alignment) for | ||
810 | * a "local" name/value structure, a "remote" name/value structure, and | ||
811 | * a pointer which might be either. | ||
812 | */ | ||
813 | static inline int xfs_attr_leaf_entsize_remote(int nlen) | ||
814 | { | ||
815 | return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \ | ||
816 | XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); | ||
817 | } | ||
818 | |||
819 | static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen) | ||
820 | { | ||
821 | return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) + | ||
822 | XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1); | ||
823 | } | ||
824 | |||
825 | static inline int xfs_attr_leaf_entsize_local_max(int bsize) | ||
826 | { | ||
827 | return (((bsize) >> 1) + ((bsize) >> 2)); | ||
828 | } | ||
829 | |||
830 | |||
831 | |||
832 | /* | ||
833 | * Remote attribute block format definition | ||
834 | * | ||
835 | * There is one of these headers per filesystem block in a remote attribute. | ||
836 | * This is done to ensure there is a 1:1 mapping between the attribute value | ||
837 | * length and the number of blocks needed to store the attribute. This makes the | ||
838 | * verification of a buffer a little more complex, but greatly simplifies the | ||
839 | * allocation, reading and writing of these attributes as we don't have to guess | ||
840 | * the number of blocks needed to store the attribute data. | ||
841 | */ | ||
842 | #define XFS_ATTR3_RMT_MAGIC 0x5841524d /* XARM */ | ||
843 | |||
844 | struct xfs_attr3_rmt_hdr { | ||
845 | __be32 rm_magic; | ||
846 | __be32 rm_offset; | ||
847 | __be32 rm_bytes; | ||
848 | __be32 rm_crc; | ||
849 | uuid_t rm_uuid; | ||
850 | __be64 rm_owner; | ||
851 | __be64 rm_blkno; | ||
852 | __be64 rm_lsn; | ||
853 | }; | ||
854 | |||
855 | #define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc) | ||
856 | |||
857 | #define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \ | ||
858 | ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ | ||
859 | sizeof(struct xfs_attr3_rmt_hdr) : 0)) | ||
860 | |||
861 | #endif /* __XFS_DA_FORMAT_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_dinode.h b/fs/xfs/libxfs/xfs_dinode.h new file mode 100644 index 000000000000..623bbe8fd921 --- /dev/null +++ b/fs/xfs/libxfs/xfs_dinode.h | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DINODE_H__ | ||
19 | #define __XFS_DINODE_H__ | ||
20 | |||
21 | #define XFS_DINODE_MAGIC 0x494e /* 'IN' */ | ||
22 | #define XFS_DINODE_GOOD_VERSION(v) ((v) >= 1 && (v) <= 3) | ||
23 | |||
24 | typedef struct xfs_timestamp { | ||
25 | __be32 t_sec; /* timestamp seconds */ | ||
26 | __be32 t_nsec; /* timestamp nanoseconds */ | ||
27 | } xfs_timestamp_t; | ||
28 | |||
29 | /* | ||
30 | * On-disk inode structure. | ||
31 | * | ||
32 | * This is just the header or "dinode core", the inode is expanded to fill a | ||
33 | * variable size the leftover area split into a data and an attribute fork. | ||
34 | * The format of the data and attribute fork depends on the format of the | ||
35 | * inode as indicated by di_format and di_aformat. To access the data and | ||
36 | * attribute use the XFS_DFORK_DPTR, XFS_DFORK_APTR, and XFS_DFORK_PTR macros | ||
37 | * below. | ||
38 | * | ||
39 | * There is a very similar struct icdinode in xfs_inode which matches the | ||
40 | * layout of the first 96 bytes of this structure, but is kept in native | ||
41 | * format instead of big endian. | ||
42 | * | ||
43 | * Note: di_flushiter is only used by v1/2 inodes - it's effectively a zeroed | ||
44 | * padding field for v3 inodes. | ||
45 | */ | ||
46 | typedef struct xfs_dinode { | ||
47 | __be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */ | ||
48 | __be16 di_mode; /* mode and type of file */ | ||
49 | __u8 di_version; /* inode version */ | ||
50 | __u8 di_format; /* format of di_c data */ | ||
51 | __be16 di_onlink; /* old number of links to file */ | ||
52 | __be32 di_uid; /* owner's user id */ | ||
53 | __be32 di_gid; /* owner's group id */ | ||
54 | __be32 di_nlink; /* number of links to file */ | ||
55 | __be16 di_projid_lo; /* lower part of owner's project id */ | ||
56 | __be16 di_projid_hi; /* higher part owner's project id */ | ||
57 | __u8 di_pad[6]; /* unused, zeroed space */ | ||
58 | __be16 di_flushiter; /* incremented on flush */ | ||
59 | xfs_timestamp_t di_atime; /* time last accessed */ | ||
60 | xfs_timestamp_t di_mtime; /* time last modified */ | ||
61 | xfs_timestamp_t di_ctime; /* time created/inode modified */ | ||
62 | __be64 di_size; /* number of bytes in file */ | ||
63 | __be64 di_nblocks; /* # of direct & btree blocks used */ | ||
64 | __be32 di_extsize; /* basic/minimum extent size for file */ | ||
65 | __be32 di_nextents; /* number of extents in data fork */ | ||
66 | __be16 di_anextents; /* number of extents in attribute fork*/ | ||
67 | __u8 di_forkoff; /* attr fork offs, <<3 for 64b align */ | ||
68 | __s8 di_aformat; /* format of attr fork's data */ | ||
69 | __be32 di_dmevmask; /* DMIG event mask */ | ||
70 | __be16 di_dmstate; /* DMIG state info */ | ||
71 | __be16 di_flags; /* random flags, XFS_DIFLAG_... */ | ||
72 | __be32 di_gen; /* generation number */ | ||
73 | |||
74 | /* di_next_unlinked is the only non-core field in the old dinode */ | ||
75 | __be32 di_next_unlinked;/* agi unlinked list ptr */ | ||
76 | |||
77 | /* start of the extended dinode, writable fields */ | ||
78 | __le32 di_crc; /* CRC of the inode */ | ||
79 | __be64 di_changecount; /* number of attribute changes */ | ||
80 | __be64 di_lsn; /* flush sequence */ | ||
81 | __be64 di_flags2; /* more random flags */ | ||
82 | __u8 di_pad2[16]; /* more padding for future expansion */ | ||
83 | |||
84 | /* fields only written to during inode creation */ | ||
85 | xfs_timestamp_t di_crtime; /* time created */ | ||
86 | __be64 di_ino; /* inode number */ | ||
87 | uuid_t di_uuid; /* UUID of the filesystem */ | ||
88 | |||
89 | /* structure must be padded to 64 bit alignment */ | ||
90 | } xfs_dinode_t; | ||
91 | |||
92 | #define XFS_DINODE_CRC_OFF offsetof(struct xfs_dinode, di_crc) | ||
93 | |||
94 | #define DI_MAX_FLUSH 0xffff | ||
95 | |||
96 | /* | ||
97 | * Size of the core inode on disk. Version 1 and 2 inodes have | ||
98 | * the same size, but version 3 has grown a few additional fields. | ||
99 | */ | ||
100 | static inline uint xfs_dinode_size(int version) | ||
101 | { | ||
102 | if (version == 3) | ||
103 | return sizeof(struct xfs_dinode); | ||
104 | return offsetof(struct xfs_dinode, di_crc); | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * The 32 bit link count in the inode theoretically maxes out at UINT_MAX. | ||
109 | * Since the pathconf interface is signed, we use 2^31 - 1 instead. | ||
110 | * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX. | ||
111 | */ | ||
112 | #define XFS_MAXLINK ((1U << 31) - 1U) | ||
113 | #define XFS_MAXLINK_1 65535U | ||
114 | |||
115 | /* | ||
116 | * Values for di_format | ||
117 | */ | ||
118 | typedef enum xfs_dinode_fmt { | ||
119 | XFS_DINODE_FMT_DEV, /* xfs_dev_t */ | ||
120 | XFS_DINODE_FMT_LOCAL, /* bulk data */ | ||
121 | XFS_DINODE_FMT_EXTENTS, /* struct xfs_bmbt_rec */ | ||
122 | XFS_DINODE_FMT_BTREE, /* struct xfs_bmdr_block */ | ||
123 | XFS_DINODE_FMT_UUID /* uuid_t */ | ||
124 | } xfs_dinode_fmt_t; | ||
125 | |||
126 | /* | ||
127 | * Inode minimum and maximum sizes. | ||
128 | */ | ||
129 | #define XFS_DINODE_MIN_LOG 8 | ||
130 | #define XFS_DINODE_MAX_LOG 11 | ||
131 | #define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG) | ||
132 | #define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG) | ||
133 | |||
134 | /* | ||
135 | * Inode size for given fs. | ||
136 | */ | ||
137 | #define XFS_LITINO(mp, version) \ | ||
138 | ((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version))) | ||
139 | |||
140 | /* | ||
141 | * Inode data & attribute fork sizes, per inode. | ||
142 | */ | ||
143 | #define XFS_DFORK_Q(dip) ((dip)->di_forkoff != 0) | ||
144 | #define XFS_DFORK_BOFF(dip) ((int)((dip)->di_forkoff << 3)) | ||
145 | |||
146 | #define XFS_DFORK_DSIZE(dip,mp) \ | ||
147 | (XFS_DFORK_Q(dip) ? \ | ||
148 | XFS_DFORK_BOFF(dip) : \ | ||
149 | XFS_LITINO(mp, (dip)->di_version)) | ||
150 | #define XFS_DFORK_ASIZE(dip,mp) \ | ||
151 | (XFS_DFORK_Q(dip) ? \ | ||
152 | XFS_LITINO(mp, (dip)->di_version) - XFS_DFORK_BOFF(dip) : \ | ||
153 | 0) | ||
154 | #define XFS_DFORK_SIZE(dip,mp,w) \ | ||
155 | ((w) == XFS_DATA_FORK ? \ | ||
156 | XFS_DFORK_DSIZE(dip, mp) : \ | ||
157 | XFS_DFORK_ASIZE(dip, mp)) | ||
158 | |||
159 | /* | ||
160 | * Return pointers to the data or attribute forks. | ||
161 | */ | ||
162 | #define XFS_DFORK_DPTR(dip) \ | ||
163 | ((char *)dip + xfs_dinode_size(dip->di_version)) | ||
164 | #define XFS_DFORK_APTR(dip) \ | ||
165 | (XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip)) | ||
166 | #define XFS_DFORK_PTR(dip,w) \ | ||
167 | ((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip)) | ||
168 | |||
169 | #define XFS_DFORK_FORMAT(dip,w) \ | ||
170 | ((w) == XFS_DATA_FORK ? \ | ||
171 | (dip)->di_format : \ | ||
172 | (dip)->di_aformat) | ||
173 | #define XFS_DFORK_NEXTENTS(dip,w) \ | ||
174 | ((w) == XFS_DATA_FORK ? \ | ||
175 | be32_to_cpu((dip)->di_nextents) : \ | ||
176 | be16_to_cpu((dip)->di_anextents)) | ||
177 | |||
178 | #define XFS_BUF_TO_DINODE(bp) ((xfs_dinode_t *)((bp)->b_addr)) | ||
179 | |||
180 | /* | ||
181 | * For block and character special files the 32bit dev_t is stored at the | ||
182 | * beginning of the data fork. | ||
183 | */ | ||
184 | static inline xfs_dev_t xfs_dinode_get_rdev(struct xfs_dinode *dip) | ||
185 | { | ||
186 | return be32_to_cpu(*(__be32 *)XFS_DFORK_DPTR(dip)); | ||
187 | } | ||
188 | |||
189 | static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) | ||
190 | { | ||
191 | *(__be32 *)XFS_DFORK_DPTR(dip) = cpu_to_be32(rdev); | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Values for di_flags | ||
196 | * There should be a one-to-one correspondence between these flags and the | ||
197 | * XFS_XFLAG_s. | ||
198 | */ | ||
199 | #define XFS_DIFLAG_REALTIME_BIT 0 /* file's blocks come from rt area */ | ||
200 | #define XFS_DIFLAG_PREALLOC_BIT 1 /* file space has been preallocated */ | ||
201 | #define XFS_DIFLAG_NEWRTBM_BIT 2 /* for rtbitmap inode, new format */ | ||
202 | #define XFS_DIFLAG_IMMUTABLE_BIT 3 /* inode is immutable */ | ||
203 | #define XFS_DIFLAG_APPEND_BIT 4 /* inode is append-only */ | ||
204 | #define XFS_DIFLAG_SYNC_BIT 5 /* inode is written synchronously */ | ||
205 | #define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */ | ||
206 | #define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */ | ||
207 | #define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */ | ||
208 | #define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */ | ||
209 | #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ | ||
210 | #define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ | ||
211 | #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ | ||
212 | #define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */ | ||
213 | #define XFS_DIFLAG_FILESTREAM_BIT 14 /* use filestream allocator */ | ||
214 | #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) | ||
215 | #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) | ||
216 | #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) | ||
217 | #define XFS_DIFLAG_IMMUTABLE (1 << XFS_DIFLAG_IMMUTABLE_BIT) | ||
218 | #define XFS_DIFLAG_APPEND (1 << XFS_DIFLAG_APPEND_BIT) | ||
219 | #define XFS_DIFLAG_SYNC (1 << XFS_DIFLAG_SYNC_BIT) | ||
220 | #define XFS_DIFLAG_NOATIME (1 << XFS_DIFLAG_NOATIME_BIT) | ||
221 | #define XFS_DIFLAG_NODUMP (1 << XFS_DIFLAG_NODUMP_BIT) | ||
222 | #define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT) | ||
223 | #define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT) | ||
224 | #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) | ||
225 | #define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) | ||
226 | #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) | ||
227 | #define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT) | ||
228 | #define XFS_DIFLAG_FILESTREAM (1 << XFS_DIFLAG_FILESTREAM_BIT) | ||
229 | |||
230 | #ifdef CONFIG_XFS_RT | ||
231 | #define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) | ||
232 | #else | ||
233 | #define XFS_IS_REALTIME_INODE(ip) (0) | ||
234 | #endif | ||
235 | |||
236 | #define XFS_DIFLAG_ANY \ | ||
237 | (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ | ||
238 | XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ | ||
239 | XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ | ||
240 | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ | ||
241 | XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM) | ||
242 | |||
243 | #endif /* __XFS_DINODE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h new file mode 100644 index 000000000000..c8e86b0b5e99 --- /dev/null +++ b/fs/xfs/libxfs/xfs_dir2.h | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DIR2_H__ | ||
19 | #define __XFS_DIR2_H__ | ||
20 | |||
21 | struct xfs_bmap_free; | ||
22 | struct xfs_da_args; | ||
23 | struct xfs_inode; | ||
24 | struct xfs_mount; | ||
25 | struct xfs_trans; | ||
26 | struct xfs_dir2_sf_hdr; | ||
27 | struct xfs_dir2_sf_entry; | ||
28 | struct xfs_dir2_data_hdr; | ||
29 | struct xfs_dir2_data_entry; | ||
30 | struct xfs_dir2_data_unused; | ||
31 | |||
32 | extern struct xfs_name xfs_name_dotdot; | ||
33 | |||
34 | /* | ||
35 | * directory operations vector for encode/decode routines | ||
36 | */ | ||
37 | struct xfs_dir_ops { | ||
38 | int (*sf_entsize)(struct xfs_dir2_sf_hdr *hdr, int len); | ||
39 | struct xfs_dir2_sf_entry * | ||
40 | (*sf_nextentry)(struct xfs_dir2_sf_hdr *hdr, | ||
41 | struct xfs_dir2_sf_entry *sfep); | ||
42 | __uint8_t (*sf_get_ftype)(struct xfs_dir2_sf_entry *sfep); | ||
43 | void (*sf_put_ftype)(struct xfs_dir2_sf_entry *sfep, | ||
44 | __uint8_t ftype); | ||
45 | xfs_ino_t (*sf_get_ino)(struct xfs_dir2_sf_hdr *hdr, | ||
46 | struct xfs_dir2_sf_entry *sfep); | ||
47 | void (*sf_put_ino)(struct xfs_dir2_sf_hdr *hdr, | ||
48 | struct xfs_dir2_sf_entry *sfep, | ||
49 | xfs_ino_t ino); | ||
50 | xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr); | ||
51 | void (*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr, | ||
52 | xfs_ino_t ino); | ||
53 | |||
54 | int (*data_entsize)(int len); | ||
55 | __uint8_t (*data_get_ftype)(struct xfs_dir2_data_entry *dep); | ||
56 | void (*data_put_ftype)(struct xfs_dir2_data_entry *dep, | ||
57 | __uint8_t ftype); | ||
58 | __be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep); | ||
59 | struct xfs_dir2_data_free * | ||
60 | (*data_bestfree_p)(struct xfs_dir2_data_hdr *hdr); | ||
61 | |||
62 | xfs_dir2_data_aoff_t data_dot_offset; | ||
63 | xfs_dir2_data_aoff_t data_dotdot_offset; | ||
64 | xfs_dir2_data_aoff_t data_first_offset; | ||
65 | size_t data_entry_offset; | ||
66 | |||
67 | struct xfs_dir2_data_entry * | ||
68 | (*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr); | ||
69 | struct xfs_dir2_data_entry * | ||
70 | (*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr); | ||
71 | struct xfs_dir2_data_entry * | ||
72 | (*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr); | ||
73 | struct xfs_dir2_data_entry * | ||
74 | (*data_entry_p)(struct xfs_dir2_data_hdr *hdr); | ||
75 | struct xfs_dir2_data_unused * | ||
76 | (*data_unused_p)(struct xfs_dir2_data_hdr *hdr); | ||
77 | |||
78 | int leaf_hdr_size; | ||
79 | void (*leaf_hdr_to_disk)(struct xfs_dir2_leaf *to, | ||
80 | struct xfs_dir3_icleaf_hdr *from); | ||
81 | void (*leaf_hdr_from_disk)(struct xfs_dir3_icleaf_hdr *to, | ||
82 | struct xfs_dir2_leaf *from); | ||
83 | int (*leaf_max_ents)(struct xfs_da_geometry *geo); | ||
84 | struct xfs_dir2_leaf_entry * | ||
85 | (*leaf_ents_p)(struct xfs_dir2_leaf *lp); | ||
86 | |||
87 | int node_hdr_size; | ||
88 | void (*node_hdr_to_disk)(struct xfs_da_intnode *to, | ||
89 | struct xfs_da3_icnode_hdr *from); | ||
90 | void (*node_hdr_from_disk)(struct xfs_da3_icnode_hdr *to, | ||
91 | struct xfs_da_intnode *from); | ||
92 | struct xfs_da_node_entry * | ||
93 | (*node_tree_p)(struct xfs_da_intnode *dap); | ||
94 | |||
95 | int free_hdr_size; | ||
96 | void (*free_hdr_to_disk)(struct xfs_dir2_free *to, | ||
97 | struct xfs_dir3_icfree_hdr *from); | ||
98 | void (*free_hdr_from_disk)(struct xfs_dir3_icfree_hdr *to, | ||
99 | struct xfs_dir2_free *from); | ||
100 | int (*free_max_bests)(struct xfs_da_geometry *geo); | ||
101 | __be16 * (*free_bests_p)(struct xfs_dir2_free *free); | ||
102 | xfs_dir2_db_t (*db_to_fdb)(struct xfs_da_geometry *geo, | ||
103 | xfs_dir2_db_t db); | ||
104 | int (*db_to_fdindex)(struct xfs_da_geometry *geo, | ||
105 | xfs_dir2_db_t db); | ||
106 | }; | ||
107 | |||
108 | extern const struct xfs_dir_ops * | ||
109 | xfs_dir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); | ||
110 | extern const struct xfs_dir_ops * | ||
111 | xfs_nondir_get_ops(struct xfs_mount *mp, struct xfs_inode *dp); | ||
112 | |||
113 | /* | ||
114 | * Generic directory interface routines | ||
115 | */ | ||
116 | extern void xfs_dir_startup(void); | ||
117 | extern int xfs_da_mount(struct xfs_mount *mp); | ||
118 | extern void xfs_da_unmount(struct xfs_mount *mp); | ||
119 | |||
120 | extern int xfs_dir_isempty(struct xfs_inode *dp); | ||
121 | extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, | ||
122 | struct xfs_inode *pdp); | ||
123 | extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, | ||
124 | struct xfs_name *name, xfs_ino_t inum, | ||
125 | xfs_fsblock_t *first, | ||
126 | struct xfs_bmap_free *flist, xfs_extlen_t tot); | ||
127 | extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, | ||
128 | struct xfs_name *name, xfs_ino_t *inum, | ||
129 | struct xfs_name *ci_name); | ||
130 | extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, | ||
131 | struct xfs_name *name, xfs_ino_t ino, | ||
132 | xfs_fsblock_t *first, | ||
133 | struct xfs_bmap_free *flist, xfs_extlen_t tot); | ||
134 | extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, | ||
135 | struct xfs_name *name, xfs_ino_t inum, | ||
136 | xfs_fsblock_t *first, | ||
137 | struct xfs_bmap_free *flist, xfs_extlen_t tot); | ||
138 | extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, | ||
139 | struct xfs_name *name, uint resblks); | ||
140 | |||
141 | /* | ||
142 | * Direct call from the bmap code, bypassing the generic directory layer. | ||
143 | */ | ||
144 | extern int xfs_dir2_sf_to_block(struct xfs_da_args *args); | ||
145 | |||
146 | /* | ||
147 | * Interface routines used by userspace utilities | ||
148 | */ | ||
149 | extern int xfs_dir2_isblock(struct xfs_da_args *args, int *r); | ||
150 | extern int xfs_dir2_isleaf(struct xfs_da_args *args, int *r); | ||
151 | extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, | ||
152 | struct xfs_buf *bp); | ||
153 | |||
154 | extern void xfs_dir2_data_freescan(struct xfs_inode *dp, | ||
155 | struct xfs_dir2_data_hdr *hdr, int *loghead); | ||
156 | extern void xfs_dir2_data_log_entry(struct xfs_da_args *args, | ||
157 | struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); | ||
158 | extern void xfs_dir2_data_log_header(struct xfs_da_args *args, | ||
159 | struct xfs_buf *bp); | ||
160 | extern void xfs_dir2_data_log_unused(struct xfs_da_args *args, | ||
161 | struct xfs_buf *bp, struct xfs_dir2_data_unused *dup); | ||
162 | extern void xfs_dir2_data_make_free(struct xfs_da_args *args, | ||
163 | struct xfs_buf *bp, xfs_dir2_data_aoff_t offset, | ||
164 | xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); | ||
165 | extern void xfs_dir2_data_use_free(struct xfs_da_args *args, | ||
166 | struct xfs_buf *bp, struct xfs_dir2_data_unused *dup, | ||
167 | xfs_dir2_data_aoff_t offset, xfs_dir2_data_aoff_t len, | ||
168 | int *needlogp, int *needscanp); | ||
169 | |||
170 | extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( | ||
171 | struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, | ||
172 | struct xfs_dir2_data_unused *dup); | ||
173 | |||
174 | extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; | ||
175 | extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; | ||
176 | extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops; | ||
177 | extern const struct xfs_buf_ops xfs_dir3_free_buf_ops; | ||
178 | extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; | ||
179 | |||
180 | #endif /* __XFS_DIR2_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h new file mode 100644 index 000000000000..34d85aca3058 --- /dev/null +++ b/fs/xfs/libxfs/xfs_format.h | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_FORMAT_H__ | ||
19 | #define __XFS_FORMAT_H__ | ||
20 | |||
21 | /* | ||
22 | * XFS On Disk Format Definitions | ||
23 | * | ||
24 | * This header file defines all the on-disk format definitions for | ||
25 | * general XFS objects. Directory and attribute related objects are defined in | ||
26 | * xfs_da_format.h, which log and log item formats are defined in | ||
27 | * xfs_log_format.h. Everything else goes here. | ||
28 | */ | ||
29 | |||
30 | struct xfs_mount; | ||
31 | struct xfs_trans; | ||
32 | struct xfs_inode; | ||
33 | struct xfs_buf; | ||
34 | struct xfs_ifork; | ||
35 | |||
36 | /* | ||
37 | * RealTime Device format definitions | ||
38 | */ | ||
39 | |||
40 | /* Min and max rt extent sizes, specified in bytes */ | ||
41 | #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ | ||
42 | #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ | ||
43 | #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ | ||
44 | |||
45 | #define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize) | ||
46 | #define XFS_BLOCKMASK(mp) ((mp)->m_blockmask) | ||
47 | #define XFS_BLOCKWSIZE(mp) ((mp)->m_blockwsize) | ||
48 | #define XFS_BLOCKWMASK(mp) ((mp)->m_blockwmask) | ||
49 | |||
50 | /* | ||
51 | * RT Summary and bit manipulation macros. | ||
52 | */ | ||
53 | #define XFS_SUMOFFS(mp,ls,bb) ((int)((ls) * (mp)->m_sb.sb_rbmblocks + (bb))) | ||
54 | #define XFS_SUMOFFSTOBLOCK(mp,s) \ | ||
55 | (((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog) | ||
56 | #define XFS_SUMPTR(mp,bp,so) \ | ||
57 | ((xfs_suminfo_t *)((bp)->b_addr + \ | ||
58 | (((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp)))) | ||
59 | |||
60 | #define XFS_BITTOBLOCK(mp,bi) ((bi) >> (mp)->m_blkbit_log) | ||
61 | #define XFS_BLOCKTOBIT(mp,bb) ((bb) << (mp)->m_blkbit_log) | ||
62 | #define XFS_BITTOWORD(mp,bi) \ | ||
63 | ((int)(((bi) >> XFS_NBWORDLOG) & XFS_BLOCKWMASK(mp))) | ||
64 | |||
65 | #define XFS_RTMIN(a,b) ((a) < (b) ? (a) : (b)) | ||
66 | #define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b)) | ||
67 | |||
68 | #define XFS_RTLOBIT(w) xfs_lowbit32(w) | ||
69 | #define XFS_RTHIBIT(w) xfs_highbit32(w) | ||
70 | |||
71 | #if XFS_BIG_BLKNOS | ||
72 | #define XFS_RTBLOCKLOG(b) xfs_highbit64(b) | ||
73 | #else | ||
74 | #define XFS_RTBLOCKLOG(b) xfs_highbit32(b) | ||
75 | #endif | ||
76 | |||
77 | /* | ||
78 | * Dquot and dquot block format definitions | ||
79 | */ | ||
80 | #define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */ | ||
81 | #define XFS_DQUOT_VERSION (u_int8_t)0x01 /* latest version number */ | ||
82 | |||
83 | /* | ||
84 | * This is the main portion of the on-disk representation of quota | ||
85 | * information for a user. This is the q_core of the xfs_dquot_t that | ||
86 | * is kept in kernel memory. We pad this with some more expansion room | ||
87 | * to construct the on disk structure. | ||
88 | */ | ||
89 | typedef struct xfs_disk_dquot { | ||
90 | __be16 d_magic; /* dquot magic = XFS_DQUOT_MAGIC */ | ||
91 | __u8 d_version; /* dquot version */ | ||
92 | __u8 d_flags; /* XFS_DQ_USER/PROJ/GROUP */ | ||
93 | __be32 d_id; /* user,project,group id */ | ||
94 | __be64 d_blk_hardlimit;/* absolute limit on disk blks */ | ||
95 | __be64 d_blk_softlimit;/* preferred limit on disk blks */ | ||
96 | __be64 d_ino_hardlimit;/* maximum # allocated inodes */ | ||
97 | __be64 d_ino_softlimit;/* preferred inode limit */ | ||
98 | __be64 d_bcount; /* disk blocks owned by the user */ | ||
99 | __be64 d_icount; /* inodes owned by the user */ | ||
100 | __be32 d_itimer; /* zero if within inode limits if not, | ||
101 | this is when we refuse service */ | ||
102 | __be32 d_btimer; /* similar to above; for disk blocks */ | ||
103 | __be16 d_iwarns; /* warnings issued wrt num inodes */ | ||
104 | __be16 d_bwarns; /* warnings issued wrt disk blocks */ | ||
105 | __be32 d_pad0; /* 64 bit align */ | ||
106 | __be64 d_rtb_hardlimit;/* absolute limit on realtime blks */ | ||
107 | __be64 d_rtb_softlimit;/* preferred limit on RT disk blks */ | ||
108 | __be64 d_rtbcount; /* realtime blocks owned */ | ||
109 | __be32 d_rtbtimer; /* similar to above; for RT disk blocks */ | ||
110 | __be16 d_rtbwarns; /* warnings issued wrt RT disk blocks */ | ||
111 | __be16 d_pad; | ||
112 | } xfs_disk_dquot_t; | ||
113 | |||
114 | /* | ||
115 | * This is what goes on disk. This is separated from the xfs_disk_dquot because | ||
116 | * carrying the unnecessary padding would be a waste of memory. | ||
117 | */ | ||
118 | typedef struct xfs_dqblk { | ||
119 | xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */ | ||
120 | char dd_fill[4]; /* filling for posterity */ | ||
121 | |||
122 | /* | ||
123 | * These two are only present on filesystems with the CRC bits set. | ||
124 | */ | ||
125 | __be32 dd_crc; /* checksum */ | ||
126 | __be64 dd_lsn; /* last modification in log */ | ||
127 | uuid_t dd_uuid; /* location information */ | ||
128 | } xfs_dqblk_t; | ||
129 | |||
130 | #define XFS_DQUOT_CRC_OFF offsetof(struct xfs_dqblk, dd_crc) | ||
131 | |||
132 | /* | ||
133 | * Remote symlink format and access functions. | ||
134 | */ | ||
135 | #define XFS_SYMLINK_MAGIC 0x58534c4d /* XSLM */ | ||
136 | |||
137 | struct xfs_dsymlink_hdr { | ||
138 | __be32 sl_magic; | ||
139 | __be32 sl_offset; | ||
140 | __be32 sl_bytes; | ||
141 | __be32 sl_crc; | ||
142 | uuid_t sl_uuid; | ||
143 | __be64 sl_owner; | ||
144 | __be64 sl_blkno; | ||
145 | __be64 sl_lsn; | ||
146 | }; | ||
147 | |||
148 | #define XFS_SYMLINK_CRC_OFF offsetof(struct xfs_dsymlink_hdr, sl_crc) | ||
149 | |||
150 | /* | ||
151 | * The maximum pathlen is 1024 bytes. Since the minimum file system | ||
152 | * blocksize is 512 bytes, we can get a max of 3 extents back from | ||
153 | * bmapi when crc headers are taken into account. | ||
154 | */ | ||
155 | #define XFS_SYMLINK_MAPS 3 | ||
156 | |||
157 | #define XFS_SYMLINK_BUF_SPACE(mp, bufsize) \ | ||
158 | ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ | ||
159 | sizeof(struct xfs_dsymlink_hdr) : 0)) | ||
160 | |||
161 | |||
162 | /* | ||
163 | * Allocation Btree format definitions | ||
164 | * | ||
165 | * There are two on-disk btrees, one sorted by blockno and one sorted | ||
166 | * by blockcount and blockno. All blocks look the same to make the code | ||
167 | * simpler; if we have time later, we'll make the optimizations. | ||
168 | */ | ||
169 | #define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */ | ||
170 | #define XFS_ABTB_CRC_MAGIC 0x41423342 /* 'AB3B' */ | ||
171 | #define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */ | ||
172 | #define XFS_ABTC_CRC_MAGIC 0x41423343 /* 'AB3C' */ | ||
173 | |||
174 | /* | ||
175 | * Data record/key structure | ||
176 | */ | ||
177 | typedef struct xfs_alloc_rec { | ||
178 | __be32 ar_startblock; /* starting block number */ | ||
179 | __be32 ar_blockcount; /* count of free blocks */ | ||
180 | } xfs_alloc_rec_t, xfs_alloc_key_t; | ||
181 | |||
182 | typedef struct xfs_alloc_rec_incore { | ||
183 | xfs_agblock_t ar_startblock; /* starting block number */ | ||
184 | xfs_extlen_t ar_blockcount; /* count of free blocks */ | ||
185 | } xfs_alloc_rec_incore_t; | ||
186 | |||
187 | /* btree pointer type */ | ||
188 | typedef __be32 xfs_alloc_ptr_t; | ||
189 | |||
190 | /* | ||
191 | * Block numbers in the AG: | ||
192 | * SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3. | ||
193 | */ | ||
194 | #define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1)) | ||
195 | #define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1)) | ||
196 | |||
197 | |||
198 | /* | ||
199 | * Inode Allocation Btree format definitions | ||
200 | * | ||
201 | * There is a btree for the inode map per allocation group. | ||
202 | */ | ||
203 | #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ | ||
204 | #define XFS_IBT_CRC_MAGIC 0x49414233 /* 'IAB3' */ | ||
205 | #define XFS_FIBT_MAGIC 0x46494254 /* 'FIBT' */ | ||
206 | #define XFS_FIBT_CRC_MAGIC 0x46494233 /* 'FIB3' */ | ||
207 | |||
208 | typedef __uint64_t xfs_inofree_t; | ||
209 | #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) | ||
210 | #define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) | ||
211 | #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) | ||
212 | #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) | ||
213 | |||
214 | static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) | ||
215 | { | ||
216 | return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Data record structure | ||
221 | */ | ||
222 | typedef struct xfs_inobt_rec { | ||
223 | __be32 ir_startino; /* starting inode number */ | ||
224 | __be32 ir_freecount; /* count of free inodes (set bits) */ | ||
225 | __be64 ir_free; /* free inode mask */ | ||
226 | } xfs_inobt_rec_t; | ||
227 | |||
228 | typedef struct xfs_inobt_rec_incore { | ||
229 | xfs_agino_t ir_startino; /* starting inode number */ | ||
230 | __int32_t ir_freecount; /* count of free inodes (set bits) */ | ||
231 | xfs_inofree_t ir_free; /* free inode mask */ | ||
232 | } xfs_inobt_rec_incore_t; | ||
233 | |||
234 | |||
235 | /* | ||
236 | * Key structure | ||
237 | */ | ||
238 | typedef struct xfs_inobt_key { | ||
239 | __be32 ir_startino; /* starting inode number */ | ||
240 | } xfs_inobt_key_t; | ||
241 | |||
242 | /* btree pointer type */ | ||
243 | typedef __be32 xfs_inobt_ptr_t; | ||
244 | |||
245 | /* | ||
246 | * block numbers in the AG. | ||
247 | */ | ||
248 | #define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) | ||
249 | #define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) | ||
250 | |||
251 | /* | ||
252 | * The first data block of an AG depends on whether the filesystem was formatted | ||
253 | * with the finobt feature. If so, account for the finobt reserved root btree | ||
254 | * block. | ||
255 | */ | ||
256 | #define XFS_PREALLOC_BLOCKS(mp) \ | ||
257 | (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ | ||
258 | XFS_FIBT_BLOCK(mp) + 1 : \ | ||
259 | XFS_IBT_BLOCK(mp) + 1) | ||
260 | |||
261 | |||
262 | |||
263 | /* | ||
264 | * BMAP Btree format definitions | ||
265 | * | ||
266 | * This includes both the root block definition that sits inside an inode fork | ||
267 | * and the record/pointer formats for the leaf/node in the blocks. | ||
268 | */ | ||
269 | #define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */ | ||
270 | #define XFS_BMAP_CRC_MAGIC 0x424d4133 /* 'BMA3' */ | ||
271 | |||
272 | /* | ||
273 | * Bmap root header, on-disk form only. | ||
274 | */ | ||
275 | typedef struct xfs_bmdr_block { | ||
276 | __be16 bb_level; /* 0 is a leaf */ | ||
277 | __be16 bb_numrecs; /* current # of data records */ | ||
278 | } xfs_bmdr_block_t; | ||
279 | |||
280 | /* | ||
281 | * Bmap btree record and extent descriptor. | ||
282 | * l0:63 is an extent flag (value 1 indicates non-normal). | ||
283 | * l0:9-62 are startoff. | ||
284 | * l0:0-8 and l1:21-63 are startblock. | ||
285 | * l1:0-20 are blockcount. | ||
286 | */ | ||
287 | #define BMBT_EXNTFLAG_BITLEN 1 | ||
288 | #define BMBT_STARTOFF_BITLEN 54 | ||
289 | #define BMBT_STARTBLOCK_BITLEN 52 | ||
290 | #define BMBT_BLOCKCOUNT_BITLEN 21 | ||
291 | |||
292 | typedef struct xfs_bmbt_rec { | ||
293 | __be64 l0, l1; | ||
294 | } xfs_bmbt_rec_t; | ||
295 | |||
296 | typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ | ||
297 | typedef xfs_bmbt_rec_t xfs_bmdr_rec_t; | ||
298 | |||
299 | typedef struct xfs_bmbt_rec_host { | ||
300 | __uint64_t l0, l1; | ||
301 | } xfs_bmbt_rec_host_t; | ||
302 | |||
303 | /* | ||
304 | * Values and macros for delayed-allocation startblock fields. | ||
305 | */ | ||
306 | #define STARTBLOCKVALBITS 17 | ||
307 | #define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20) | ||
308 | #define DSTARTBLOCKMASKBITS (15 + 20) | ||
309 | #define STARTBLOCKMASK \ | ||
310 | (((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) | ||
311 | #define DSTARTBLOCKMASK \ | ||
312 | (((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS) | ||
313 | |||
314 | static inline int isnullstartblock(xfs_fsblock_t x) | ||
315 | { | ||
316 | return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK; | ||
317 | } | ||
318 | |||
319 | static inline int isnulldstartblock(xfs_dfsbno_t x) | ||
320 | { | ||
321 | return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK; | ||
322 | } | ||
323 | |||
324 | static inline xfs_fsblock_t nullstartblock(int k) | ||
325 | { | ||
326 | ASSERT(k < (1 << STARTBLOCKVALBITS)); | ||
327 | return STARTBLOCKMASK | (k); | ||
328 | } | ||
329 | |||
330 | static inline xfs_filblks_t startblockval(xfs_fsblock_t x) | ||
331 | { | ||
332 | return (xfs_filblks_t)((x) & ~STARTBLOCKMASK); | ||
333 | } | ||
334 | |||
335 | /* | ||
336 | * Possible extent formats. | ||
337 | */ | ||
338 | typedef enum { | ||
339 | XFS_EXTFMT_NOSTATE = 0, | ||
340 | XFS_EXTFMT_HASSTATE | ||
341 | } xfs_exntfmt_t; | ||
342 | |||
343 | /* | ||
344 | * Possible extent states. | ||
345 | */ | ||
346 | typedef enum { | ||
347 | XFS_EXT_NORM, XFS_EXT_UNWRITTEN, | ||
348 | XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID | ||
349 | } xfs_exntst_t; | ||
350 | |||
351 | /* | ||
352 | * Incore version of above. | ||
353 | */ | ||
354 | typedef struct xfs_bmbt_irec | ||
355 | { | ||
356 | xfs_fileoff_t br_startoff; /* starting file offset */ | ||
357 | xfs_fsblock_t br_startblock; /* starting block number */ | ||
358 | xfs_filblks_t br_blockcount; /* number of blocks */ | ||
359 | xfs_exntst_t br_state; /* extent state */ | ||
360 | } xfs_bmbt_irec_t; | ||
361 | |||
362 | /* | ||
363 | * Key structure for non-leaf levels of the tree. | ||
364 | */ | ||
365 | typedef struct xfs_bmbt_key { | ||
366 | __be64 br_startoff; /* starting file offset */ | ||
367 | } xfs_bmbt_key_t, xfs_bmdr_key_t; | ||
368 | |||
369 | /* btree pointer type */ | ||
370 | typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; | ||
371 | |||
372 | |||
373 | /* | ||
374 | * Generic Btree block format definitions | ||
375 | * | ||
376 | * This is a combination of the actual format used on disk for short and long | ||
377 | * format btrees. The first three fields are shared by both format, but the | ||
378 | * pointers are different and should be used with care. | ||
379 | * | ||
380 | * To get the size of the actual short or long form headers please use the size | ||
381 | * macros below. Never use sizeof(xfs_btree_block). | ||
382 | * | ||
383 | * The blkno, crc, lsn, owner and uuid fields are only available in filesystems | ||
384 | * with the crc feature bit, and all accesses to them must be conditional on | ||
385 | * that flag. | ||
386 | */ | ||
387 | struct xfs_btree_block { | ||
388 | __be32 bb_magic; /* magic number for block type */ | ||
389 | __be16 bb_level; /* 0 is a leaf */ | ||
390 | __be16 bb_numrecs; /* current # of data records */ | ||
391 | union { | ||
392 | struct { | ||
393 | __be32 bb_leftsib; | ||
394 | __be32 bb_rightsib; | ||
395 | |||
396 | __be64 bb_blkno; | ||
397 | __be64 bb_lsn; | ||
398 | uuid_t bb_uuid; | ||
399 | __be32 bb_owner; | ||
400 | __le32 bb_crc; | ||
401 | } s; /* short form pointers */ | ||
402 | struct { | ||
403 | __be64 bb_leftsib; | ||
404 | __be64 bb_rightsib; | ||
405 | |||
406 | __be64 bb_blkno; | ||
407 | __be64 bb_lsn; | ||
408 | uuid_t bb_uuid; | ||
409 | __be64 bb_owner; | ||
410 | __le32 bb_crc; | ||
411 | __be32 bb_pad; /* padding for alignment */ | ||
412 | } l; /* long form pointers */ | ||
413 | } bb_u; /* rest */ | ||
414 | }; | ||
415 | |||
416 | #define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */ | ||
417 | #define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */ | ||
418 | |||
419 | /* sizes of CRC enabled btree blocks */ | ||
420 | #define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40) | ||
421 | #define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48) | ||
422 | |||
423 | #define XFS_BTREE_SBLOCK_CRC_OFF \ | ||
424 | offsetof(struct xfs_btree_block, bb_u.s.bb_crc) | ||
425 | #define XFS_BTREE_LBLOCK_CRC_OFF \ | ||
426 | offsetof(struct xfs_btree_block, bb_u.l.bb_crc) | ||
427 | |||
428 | #endif /* __XFS_FORMAT_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h new file mode 100644 index 000000000000..95ad1c002d60 --- /dev/null +++ b/fs/xfs/libxfs/xfs_ialloc.h | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_IALLOC_H__ | ||
19 | #define __XFS_IALLOC_H__ | ||
20 | |||
21 | struct xfs_buf; | ||
22 | struct xfs_dinode; | ||
23 | struct xfs_imap; | ||
24 | struct xfs_mount; | ||
25 | struct xfs_trans; | ||
26 | struct xfs_btree_cur; | ||
27 | |||
28 | /* Move inodes in clusters of this size */ | ||
29 | #define XFS_INODE_BIG_CLUSTER_SIZE 8192 | ||
30 | |||
31 | /* Calculate and return the number of filesystem blocks per inode cluster */ | ||
32 | static inline int | ||
33 | xfs_icluster_size_fsb( | ||
34 | struct xfs_mount *mp) | ||
35 | { | ||
36 | if (mp->m_sb.sb_blocksize >= mp->m_inode_cluster_size) | ||
37 | return 1; | ||
38 | return mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog; | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | * Make an inode pointer out of the buffer/offset. | ||
43 | */ | ||
44 | static inline struct xfs_dinode * | ||
45 | xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) | ||
46 | { | ||
47 | return (struct xfs_dinode *) | ||
48 | (xfs_buf_offset(b, o << (mp)->m_sb.sb_inodelog)); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Allocate an inode on disk. | ||
53 | * Mode is used to tell whether the new inode will need space, and whether | ||
54 | * it is a directory. | ||
55 | * | ||
56 | * To work within the constraint of one allocation per transaction, | ||
57 | * xfs_dialloc() is designed to be called twice if it has to do an | ||
58 | * allocation to make more free inodes. If an inode is | ||
59 | * available without an allocation, agbp would be set to the current | ||
60 | * agbp and alloc_done set to false. | ||
61 | * If an allocation needed to be done, agbp would be set to the | ||
62 | * inode header of the allocation group and alloc_done set to true. | ||
63 | * The caller should then commit the current transaction and allocate a new | ||
64 | * transaction. xfs_dialloc() should then be called again with | ||
65 | * the agbp value returned from the previous call. | ||
66 | * | ||
67 | * Once we successfully pick an inode its number is returned and the | ||
68 | * on-disk data structures are updated. The inode itself is not read | ||
69 | * in, since doing so would break ordering constraints with xfs_reclaim. | ||
70 | * | ||
71 | * *agbp should be set to NULL on the first call, *alloc_done set to FALSE. | ||
72 | */ | ||
73 | int /* error */ | ||
74 | xfs_dialloc( | ||
75 | struct xfs_trans *tp, /* transaction pointer */ | ||
76 | xfs_ino_t parent, /* parent inode (directory) */ | ||
77 | umode_t mode, /* mode bits for new inode */ | ||
78 | int okalloc, /* ok to allocate more space */ | ||
79 | struct xfs_buf **agbp, /* buf for a.g. inode header */ | ||
80 | xfs_ino_t *inop); /* inode number allocated */ | ||
81 | |||
82 | /* | ||
83 | * Free disk inode. Carefully avoids touching the incore inode, all | ||
84 | * manipulations incore are the caller's responsibility. | ||
85 | * The on-disk inode is not changed by this operation, only the | ||
86 | * btree (free inode mask) is changed. | ||
87 | */ | ||
88 | int /* error */ | ||
89 | xfs_difree( | ||
90 | struct xfs_trans *tp, /* transaction pointer */ | ||
91 | xfs_ino_t inode, /* inode to be freed */ | ||
92 | struct xfs_bmap_free *flist, /* extents to free */ | ||
93 | int *deleted, /* set if inode cluster was deleted */ | ||
94 | xfs_ino_t *first_ino); /* first inode in deleted cluster */ | ||
95 | |||
96 | /* | ||
97 | * Return the location of the inode in imap, for mapping it into a buffer. | ||
98 | */ | ||
99 | int | ||
100 | xfs_imap( | ||
101 | struct xfs_mount *mp, /* file system mount structure */ | ||
102 | struct xfs_trans *tp, /* transaction pointer */ | ||
103 | xfs_ino_t ino, /* inode to locate */ | ||
104 | struct xfs_imap *imap, /* location map structure */ | ||
105 | uint flags); /* flags for inode btree lookup */ | ||
106 | |||
107 | /* | ||
108 | * Compute and fill in value of m_in_maxlevels. | ||
109 | */ | ||
110 | void | ||
111 | xfs_ialloc_compute_maxlevels( | ||
112 | struct xfs_mount *mp); /* file system mount structure */ | ||
113 | |||
114 | /* | ||
115 | * Log specified fields for the ag hdr (inode section) | ||
116 | */ | ||
117 | void | ||
118 | xfs_ialloc_log_agi( | ||
119 | struct xfs_trans *tp, /* transaction pointer */ | ||
120 | struct xfs_buf *bp, /* allocation group header buffer */ | ||
121 | int fields); /* bitmask of fields to log */ | ||
122 | |||
123 | /* | ||
124 | * Read in the allocation group header (inode allocation section) | ||
125 | */ | ||
126 | int /* error */ | ||
127 | xfs_ialloc_read_agi( | ||
128 | struct xfs_mount *mp, /* file system mount structure */ | ||
129 | struct xfs_trans *tp, /* transaction pointer */ | ||
130 | xfs_agnumber_t agno, /* allocation group number */ | ||
131 | struct xfs_buf **bpp); /* allocation group hdr buf */ | ||
132 | |||
133 | /* | ||
134 | * Read in the allocation group header to initialise the per-ag data | ||
135 | * in the mount structure | ||
136 | */ | ||
137 | int | ||
138 | xfs_ialloc_pagi_init( | ||
139 | struct xfs_mount *mp, /* file system mount structure */ | ||
140 | struct xfs_trans *tp, /* transaction pointer */ | ||
141 | xfs_agnumber_t agno); /* allocation group number */ | ||
142 | |||
143 | /* | ||
144 | * Lookup a record by ino in the btree given by cur. | ||
145 | */ | ||
146 | int xfs_inobt_lookup(struct xfs_btree_cur *cur, xfs_agino_t ino, | ||
147 | xfs_lookup_t dir, int *stat); | ||
148 | |||
149 | /* | ||
150 | * Get the data from the pointed-to record. | ||
151 | */ | ||
152 | int xfs_inobt_get_rec(struct xfs_btree_cur *cur, | ||
153 | xfs_inobt_rec_incore_t *rec, int *stat); | ||
154 | |||
155 | /* | ||
156 | * Inode chunk initialisation routine | ||
157 | */ | ||
158 | int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp, | ||
159 | struct list_head *buffer_list, | ||
160 | xfs_agnumber_t agno, xfs_agblock_t agbno, | ||
161 | xfs_agblock_t length, unsigned int gen); | ||
162 | |||
163 | #endif /* __XFS_IALLOC_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h new file mode 100644 index 000000000000..d7ebea72c2d0 --- /dev/null +++ b/fs/xfs/libxfs/xfs_ialloc_btree.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_IALLOC_BTREE_H__ | ||
19 | #define __XFS_IALLOC_BTREE_H__ | ||
20 | |||
21 | /* | ||
22 | * Inode map on-disk structures | ||
23 | */ | ||
24 | |||
25 | struct xfs_buf; | ||
26 | struct xfs_btree_cur; | ||
27 | struct xfs_mount; | ||
28 | |||
29 | /* | ||
30 | * Btree block header size depends on a superblock flag. | ||
31 | */ | ||
32 | #define XFS_INOBT_BLOCK_LEN(mp) \ | ||
33 | (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \ | ||
34 | XFS_BTREE_SBLOCK_CRC_LEN : XFS_BTREE_SBLOCK_LEN) | ||
35 | |||
36 | /* | ||
37 | * Record, key, and pointer address macros for btree blocks. | ||
38 | * | ||
39 | * (note that some of these may appear unused, but they are used in userspace) | ||
40 | */ | ||
41 | #define XFS_INOBT_REC_ADDR(mp, block, index) \ | ||
42 | ((xfs_inobt_rec_t *) \ | ||
43 | ((char *)(block) + \ | ||
44 | XFS_INOBT_BLOCK_LEN(mp) + \ | ||
45 | (((index) - 1) * sizeof(xfs_inobt_rec_t)))) | ||
46 | |||
47 | #define XFS_INOBT_KEY_ADDR(mp, block, index) \ | ||
48 | ((xfs_inobt_key_t *) \ | ||
49 | ((char *)(block) + \ | ||
50 | XFS_INOBT_BLOCK_LEN(mp) + \ | ||
51 | ((index) - 1) * sizeof(xfs_inobt_key_t))) | ||
52 | |||
53 | #define XFS_INOBT_PTR_ADDR(mp, block, index, maxrecs) \ | ||
54 | ((xfs_inobt_ptr_t *) \ | ||
55 | ((char *)(block) + \ | ||
56 | XFS_INOBT_BLOCK_LEN(mp) + \ | ||
57 | (maxrecs) * sizeof(xfs_inobt_key_t) + \ | ||
58 | ((index) - 1) * sizeof(xfs_inobt_ptr_t))) | ||
59 | |||
60 | extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, | ||
61 | struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t, | ||
62 | xfs_btnum_t); | ||
63 | extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int); | ||
64 | |||
65 | #endif /* __XFS_IALLOC_BTREE_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h new file mode 100644 index 000000000000..9308c47f2a52 --- /dev/null +++ b/fs/xfs/libxfs/xfs_inode_buf.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_INODE_BUF_H__ | ||
19 | #define __XFS_INODE_BUF_H__ | ||
20 | |||
21 | struct xfs_inode; | ||
22 | struct xfs_dinode; | ||
23 | struct xfs_icdinode; | ||
24 | |||
25 | /* | ||
26 | * Inode location information. Stored in the inode and passed to | ||
27 | * xfs_imap_to_bp() to get a buffer and dinode for a given inode. | ||
28 | */ | ||
29 | struct xfs_imap { | ||
30 | xfs_daddr_t im_blkno; /* starting BB of inode chunk */ | ||
31 | ushort im_len; /* length in BBs of inode chunk */ | ||
32 | ushort im_boffset; /* inode offset in block in bytes */ | ||
33 | }; | ||
34 | |||
35 | int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, | ||
36 | struct xfs_imap *, struct xfs_dinode **, | ||
37 | struct xfs_buf **, uint, uint); | ||
38 | int xfs_iread(struct xfs_mount *, struct xfs_trans *, | ||
39 | struct xfs_inode *, uint); | ||
40 | void xfs_dinode_calc_crc(struct xfs_mount *, struct xfs_dinode *); | ||
41 | void xfs_dinode_to_disk(struct xfs_dinode *to, struct xfs_icdinode *from); | ||
42 | void xfs_dinode_from_disk(struct xfs_icdinode *to, struct xfs_dinode *from); | ||
43 | |||
44 | #if defined(DEBUG) | ||
45 | void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); | ||
46 | #else | ||
47 | #define xfs_inobp_check(mp, bp) | ||
48 | #endif /* DEBUG */ | ||
49 | |||
50 | #endif /* __XFS_INODE_BUF_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h new file mode 100644 index 000000000000..7d3b1ed6dcbe --- /dev/null +++ b/fs/xfs/libxfs/xfs_inode_fork.h | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_INODE_FORK_H__ | ||
19 | #define __XFS_INODE_FORK_H__ | ||
20 | |||
21 | struct xfs_inode_log_item; | ||
22 | struct xfs_dinode; | ||
23 | |||
24 | /* | ||
25 | * The following xfs_ext_irec_t struct introduces a second (top) level | ||
26 | * to the in-core extent allocation scheme. These structs are allocated | ||
27 | * in a contiguous block, creating an indirection array where each entry | ||
28 | * (irec) contains a pointer to a buffer of in-core extent records which | ||
29 | * it manages. Each extent buffer is 4k in size, since 4k is the system | ||
30 | * page size on Linux i386 and systems with larger page sizes don't seem | ||
31 | * to gain much, if anything, by using their native page size as the | ||
32 | * extent buffer size. Also, using 4k extent buffers everywhere provides | ||
33 | * a consistent interface for CXFS across different platforms. | ||
34 | * | ||
35 | * There is currently no limit on the number of irec's (extent lists) | ||
36 | * allowed, so heavily fragmented files may require an indirection array | ||
37 | * which spans multiple system pages of memory. The number of extents | ||
38 | * which would require this amount of contiguous memory is very large | ||
39 | * and should not cause problems in the foreseeable future. However, | ||
40 | * if the memory needed for the contiguous array ever becomes a problem, | ||
41 | * it is possible that a third level of indirection may be required. | ||
42 | */ | ||
43 | typedef struct xfs_ext_irec { | ||
44 | xfs_bmbt_rec_host_t *er_extbuf; /* block of extent records */ | ||
45 | xfs_extnum_t er_extoff; /* extent offset in file */ | ||
46 | xfs_extnum_t er_extcount; /* number of extents in page/block */ | ||
47 | } xfs_ext_irec_t; | ||
48 | |||
49 | /* | ||
50 | * File incore extent information, present for each of data & attr forks. | ||
51 | */ | ||
52 | #define XFS_IEXT_BUFSZ 4096 | ||
53 | #define XFS_LINEAR_EXTS (XFS_IEXT_BUFSZ / (uint)sizeof(xfs_bmbt_rec_t)) | ||
54 | #define XFS_INLINE_EXTS 2 | ||
55 | #define XFS_INLINE_DATA 32 | ||
56 | typedef struct xfs_ifork { | ||
57 | int if_bytes; /* bytes in if_u1 */ | ||
58 | int if_real_bytes; /* bytes allocated in if_u1 */ | ||
59 | struct xfs_btree_block *if_broot; /* file's incore btree root */ | ||
60 | short if_broot_bytes; /* bytes allocated for root */ | ||
61 | unsigned char if_flags; /* per-fork flags */ | ||
62 | union { | ||
63 | xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */ | ||
64 | xfs_ext_irec_t *if_ext_irec; /* irec map file exts */ | ||
65 | char *if_data; /* inline file data */ | ||
66 | } if_u1; | ||
67 | union { | ||
68 | xfs_bmbt_rec_host_t if_inline_ext[XFS_INLINE_EXTS]; | ||
69 | /* very small file extents */ | ||
70 | char if_inline_data[XFS_INLINE_DATA]; | ||
71 | /* very small file data */ | ||
72 | xfs_dev_t if_rdev; /* dev number if special */ | ||
73 | uuid_t if_uuid; /* mount point value */ | ||
74 | } if_u2; | ||
75 | } xfs_ifork_t; | ||
76 | |||
77 | /* | ||
78 | * Per-fork incore inode flags. | ||
79 | */ | ||
80 | #define XFS_IFINLINE 0x01 /* Inline data is read in */ | ||
81 | #define XFS_IFEXTENTS 0x02 /* All extent pointers are read in */ | ||
82 | #define XFS_IFBROOT 0x04 /* i_broot points to the bmap b-tree root */ | ||
83 | #define XFS_IFEXTIREC 0x08 /* Indirection array of extent blocks */ | ||
84 | |||
85 | /* | ||
86 | * Fork handling. | ||
87 | */ | ||
88 | |||
89 | #define XFS_IFORK_Q(ip) ((ip)->i_d.di_forkoff != 0) | ||
90 | #define XFS_IFORK_BOFF(ip) ((int)((ip)->i_d.di_forkoff << 3)) | ||
91 | |||
92 | #define XFS_IFORK_PTR(ip,w) \ | ||
93 | ((w) == XFS_DATA_FORK ? \ | ||
94 | &(ip)->i_df : \ | ||
95 | (ip)->i_afp) | ||
96 | #define XFS_IFORK_DSIZE(ip) \ | ||
97 | (XFS_IFORK_Q(ip) ? \ | ||
98 | XFS_IFORK_BOFF(ip) : \ | ||
99 | XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version)) | ||
100 | #define XFS_IFORK_ASIZE(ip) \ | ||
101 | (XFS_IFORK_Q(ip) ? \ | ||
102 | XFS_LITINO((ip)->i_mount, (ip)->i_d.di_version) - \ | ||
103 | XFS_IFORK_BOFF(ip) : \ | ||
104 | 0) | ||
105 | #define XFS_IFORK_SIZE(ip,w) \ | ||
106 | ((w) == XFS_DATA_FORK ? \ | ||
107 | XFS_IFORK_DSIZE(ip) : \ | ||
108 | XFS_IFORK_ASIZE(ip)) | ||
109 | #define XFS_IFORK_FORMAT(ip,w) \ | ||
110 | ((w) == XFS_DATA_FORK ? \ | ||
111 | (ip)->i_d.di_format : \ | ||
112 | (ip)->i_d.di_aformat) | ||
113 | #define XFS_IFORK_FMT_SET(ip,w,n) \ | ||
114 | ((w) == XFS_DATA_FORK ? \ | ||
115 | ((ip)->i_d.di_format = (n)) : \ | ||
116 | ((ip)->i_d.di_aformat = (n))) | ||
117 | #define XFS_IFORK_NEXTENTS(ip,w) \ | ||
118 | ((w) == XFS_DATA_FORK ? \ | ||
119 | (ip)->i_d.di_nextents : \ | ||
120 | (ip)->i_d.di_anextents) | ||
121 | #define XFS_IFORK_NEXT_SET(ip,w,n) \ | ||
122 | ((w) == XFS_DATA_FORK ? \ | ||
123 | ((ip)->i_d.di_nextents = (n)) : \ | ||
124 | ((ip)->i_d.di_anextents = (n))) | ||
125 | #define XFS_IFORK_MAXEXT(ip, w) \ | ||
126 | (XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t)) | ||
127 | |||
128 | int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); | ||
129 | void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, | ||
130 | struct xfs_inode_log_item *, int); | ||
131 | void xfs_idestroy_fork(struct xfs_inode *, int); | ||
132 | void xfs_idata_realloc(struct xfs_inode *, int, int); | ||
133 | void xfs_iroot_realloc(struct xfs_inode *, int, int); | ||
134 | int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); | ||
135 | int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, | ||
136 | int); | ||
137 | |||
138 | struct xfs_bmbt_rec_host * | ||
139 | xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t); | ||
140 | void xfs_iext_insert(struct xfs_inode *, xfs_extnum_t, xfs_extnum_t, | ||
141 | struct xfs_bmbt_irec *, int); | ||
142 | void xfs_iext_add(struct xfs_ifork *, xfs_extnum_t, int); | ||
143 | void xfs_iext_add_indirect_multi(struct xfs_ifork *, int, | ||
144 | xfs_extnum_t, int); | ||
145 | void xfs_iext_remove(struct xfs_inode *, xfs_extnum_t, int, int); | ||
146 | void xfs_iext_remove_inline(struct xfs_ifork *, xfs_extnum_t, int); | ||
147 | void xfs_iext_remove_direct(struct xfs_ifork *, xfs_extnum_t, int); | ||
148 | void xfs_iext_remove_indirect(struct xfs_ifork *, xfs_extnum_t, int); | ||
149 | void xfs_iext_realloc_direct(struct xfs_ifork *, int); | ||
150 | void xfs_iext_direct_to_inline(struct xfs_ifork *, xfs_extnum_t); | ||
151 | void xfs_iext_inline_to_direct(struct xfs_ifork *, int); | ||
152 | void xfs_iext_destroy(struct xfs_ifork *); | ||
153 | struct xfs_bmbt_rec_host * | ||
154 | xfs_iext_bno_to_ext(struct xfs_ifork *, xfs_fileoff_t, int *); | ||
155 | struct xfs_ext_irec * | ||
156 | xfs_iext_bno_to_irec(struct xfs_ifork *, xfs_fileoff_t, int *); | ||
157 | struct xfs_ext_irec * | ||
158 | xfs_iext_idx_to_irec(struct xfs_ifork *, xfs_extnum_t *, int *, | ||
159 | int); | ||
160 | void xfs_iext_irec_init(struct xfs_ifork *); | ||
161 | struct xfs_ext_irec * | ||
162 | xfs_iext_irec_new(struct xfs_ifork *, int); | ||
163 | void xfs_iext_irec_remove(struct xfs_ifork *, int); | ||
164 | void xfs_iext_irec_compact(struct xfs_ifork *); | ||
165 | void xfs_iext_irec_compact_pages(struct xfs_ifork *); | ||
166 | void xfs_iext_irec_compact_full(struct xfs_ifork *); | ||
167 | void xfs_iext_irec_update_extoffs(struct xfs_ifork *, int, int); | ||
168 | |||
169 | extern struct kmem_zone *xfs_ifork_zone; | ||
170 | |||
171 | #endif /* __XFS_INODE_FORK_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_inum.h b/fs/xfs/libxfs/xfs_inum.h new file mode 100644 index 000000000000..90efdaf1706f --- /dev/null +++ b/fs/xfs/libxfs/xfs_inum.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_INUM_H__ | ||
19 | #define __XFS_INUM_H__ | ||
20 | |||
21 | /* | ||
22 | * Inode number format: | ||
23 | * low inopblog bits - offset in block | ||
24 | * next agblklog bits - block number in ag | ||
25 | * next agno_log bits - ag number | ||
26 | * high agno_log-agblklog-inopblog bits - 0 | ||
27 | */ | ||
28 | |||
29 | struct xfs_mount; | ||
30 | |||
31 | #define XFS_INO_MASK(k) (__uint32_t)((1ULL << (k)) - 1) | ||
32 | #define XFS_INO_OFFSET_BITS(mp) (mp)->m_sb.sb_inopblog | ||
33 | #define XFS_INO_AGBNO_BITS(mp) (mp)->m_sb.sb_agblklog | ||
34 | #define XFS_INO_AGINO_BITS(mp) (mp)->m_agino_log | ||
35 | #define XFS_INO_AGNO_BITS(mp) (mp)->m_agno_log | ||
36 | #define XFS_INO_BITS(mp) \ | ||
37 | XFS_INO_AGNO_BITS(mp) + XFS_INO_AGINO_BITS(mp) | ||
38 | #define XFS_INO_TO_AGNO(mp,i) \ | ||
39 | ((xfs_agnumber_t)((i) >> XFS_INO_AGINO_BITS(mp))) | ||
40 | #define XFS_INO_TO_AGINO(mp,i) \ | ||
41 | ((xfs_agino_t)(i) & XFS_INO_MASK(XFS_INO_AGINO_BITS(mp))) | ||
42 | #define XFS_INO_TO_AGBNO(mp,i) \ | ||
43 | (((xfs_agblock_t)(i) >> XFS_INO_OFFSET_BITS(mp)) & \ | ||
44 | XFS_INO_MASK(XFS_INO_AGBNO_BITS(mp))) | ||
45 | #define XFS_INO_TO_OFFSET(mp,i) \ | ||
46 | ((int)(i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp))) | ||
47 | #define XFS_INO_TO_FSB(mp,i) \ | ||
48 | XFS_AGB_TO_FSB(mp, XFS_INO_TO_AGNO(mp,i), XFS_INO_TO_AGBNO(mp,i)) | ||
49 | #define XFS_AGINO_TO_INO(mp,a,i) \ | ||
50 | (((xfs_ino_t)(a) << XFS_INO_AGINO_BITS(mp)) | (i)) | ||
51 | #define XFS_AGINO_TO_AGBNO(mp,i) ((i) >> XFS_INO_OFFSET_BITS(mp)) | ||
52 | #define XFS_AGINO_TO_OFFSET(mp,i) \ | ||
53 | ((i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp))) | ||
54 | #define XFS_OFFBNO_TO_AGINO(mp,b,o) \ | ||
55 | ((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o))) | ||
56 | |||
57 | #if XFS_BIG_INUMS | ||
58 | #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL)) | ||
59 | #else | ||
60 | #define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 32) - 1ULL)) | ||
61 | #endif | ||
62 | #define XFS_MAXINUMBER_32 ((xfs_ino_t)((1ULL << 32) - 1ULL)) | ||
63 | |||
64 | #endif /* __XFS_INUM_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h new file mode 100644 index 000000000000..f0969c77bdbe --- /dev/null +++ b/fs/xfs/libxfs/xfs_log_format.h | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_LOG_FORMAT_H__ | ||
19 | #define __XFS_LOG_FORMAT_H__ | ||
20 | |||
21 | struct xfs_mount; | ||
22 | struct xfs_trans_res; | ||
23 | |||
24 | /* | ||
25 | * On-disk Log Format definitions. | ||
26 | * | ||
27 | * This file contains all the on-disk format definitions used within the log. It | ||
28 | * includes the physical log structure itself, as well as all the log item | ||
29 | * format structures that are written into the log and intepreted by log | ||
30 | * recovery. We start with the physical log format definitions, and then work | ||
31 | * through all the log items definitions and everything they encode into the | ||
32 | * log. | ||
33 | */ | ||
34 | typedef __uint32_t xlog_tid_t; | ||
35 | |||
36 | #define XLOG_MIN_ICLOGS 2 | ||
37 | #define XLOG_MAX_ICLOGS 8 | ||
38 | #define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe /* Invalid cycle number */ | ||
39 | #define XLOG_VERSION_1 1 | ||
40 | #define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */ | ||
41 | #define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2) | ||
42 | #define XLOG_MIN_RECORD_BSIZE (16*1024) /* eventually 32k */ | ||
43 | #define XLOG_BIG_RECORD_BSIZE (32*1024) /* 32k buffers */ | ||
44 | #define XLOG_MAX_RECORD_BSIZE (256*1024) | ||
45 | #define XLOG_HEADER_CYCLE_SIZE (32*1024) /* cycle data in header */ | ||
46 | #define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */ | ||
47 | #define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */ | ||
48 | #define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */ | ||
49 | #define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \ | ||
50 | (log)->l_mp->m_sb.sb_logsunit) | ||
51 | #define XLOG_LSUNITTOB(log, su) ((su) * (log)->l_mp->m_sb.sb_logsunit) | ||
52 | |||
53 | #define XLOG_HEADER_SIZE 512 | ||
54 | |||
55 | /* Minimum number of transactions that must fit in the log (defined by mkfs) */ | ||
56 | #define XFS_MIN_LOG_FACTOR 3 | ||
57 | |||
58 | #define XLOG_REC_SHIFT(log) \ | ||
59 | BTOBB(1 << (xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? \ | ||
60 | XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT)) | ||
61 | #define XLOG_TOTAL_REC_SHIFT(log) \ | ||
62 | BTOBB(XLOG_MAX_ICLOGS << (xfs_sb_version_haslogv2(&log->l_mp->m_sb) ? \ | ||
63 | XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT)) | ||
64 | |||
65 | /* get lsn fields */ | ||
66 | #define CYCLE_LSN(lsn) ((uint)((lsn)>>32)) | ||
67 | #define BLOCK_LSN(lsn) ((uint)(lsn)) | ||
68 | |||
69 | /* this is used in a spot where we might otherwise double-endian-flip */ | ||
70 | #define CYCLE_LSN_DISK(lsn) (((__be32 *)&(lsn))[0]) | ||
71 | |||
72 | static inline xfs_lsn_t xlog_assign_lsn(uint cycle, uint block) | ||
73 | { | ||
74 | return ((xfs_lsn_t)cycle << 32) | block; | ||
75 | } | ||
76 | |||
77 | static inline uint xlog_get_cycle(char *ptr) | ||
78 | { | ||
79 | if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM) | ||
80 | return be32_to_cpu(*((__be32 *)ptr + 1)); | ||
81 | else | ||
82 | return be32_to_cpu(*(__be32 *)ptr); | ||
83 | } | ||
84 | |||
85 | /* Log Clients */ | ||
86 | #define XFS_TRANSACTION 0x69 | ||
87 | #define XFS_VOLUME 0x2 | ||
88 | #define XFS_LOG 0xaa | ||
89 | |||
90 | #define XLOG_UNMOUNT_TYPE 0x556e /* Un for Unmount */ | ||
91 | |||
92 | /* Region types for iovec's i_type */ | ||
93 | #define XLOG_REG_TYPE_BFORMAT 1 | ||
94 | #define XLOG_REG_TYPE_BCHUNK 2 | ||
95 | #define XLOG_REG_TYPE_EFI_FORMAT 3 | ||
96 | #define XLOG_REG_TYPE_EFD_FORMAT 4 | ||
97 | #define XLOG_REG_TYPE_IFORMAT 5 | ||
98 | #define XLOG_REG_TYPE_ICORE 6 | ||
99 | #define XLOG_REG_TYPE_IEXT 7 | ||
100 | #define XLOG_REG_TYPE_IBROOT 8 | ||
101 | #define XLOG_REG_TYPE_ILOCAL 9 | ||
102 | #define XLOG_REG_TYPE_IATTR_EXT 10 | ||
103 | #define XLOG_REG_TYPE_IATTR_BROOT 11 | ||
104 | #define XLOG_REG_TYPE_IATTR_LOCAL 12 | ||
105 | #define XLOG_REG_TYPE_QFORMAT 13 | ||
106 | #define XLOG_REG_TYPE_DQUOT 14 | ||
107 | #define XLOG_REG_TYPE_QUOTAOFF 15 | ||
108 | #define XLOG_REG_TYPE_LRHEADER 16 | ||
109 | #define XLOG_REG_TYPE_UNMOUNT 17 | ||
110 | #define XLOG_REG_TYPE_COMMIT 18 | ||
111 | #define XLOG_REG_TYPE_TRANSHDR 19 | ||
112 | #define XLOG_REG_TYPE_ICREATE 20 | ||
113 | #define XLOG_REG_TYPE_MAX 20 | ||
114 | |||
115 | /* | ||
116 | * Flags to log operation header | ||
117 | * | ||
118 | * The first write of a new transaction will be preceded with a start | ||
119 | * record, XLOG_START_TRANS. Once a transaction is committed, a commit | ||
120 | * record is written, XLOG_COMMIT_TRANS. If a single region can not fit into | ||
121 | * the remainder of the current active in-core log, it is split up into | ||
122 | * multiple regions. Each partial region will be marked with a | ||
123 | * XLOG_CONTINUE_TRANS until the last one, which gets marked with XLOG_END_TRANS. | ||
124 | * | ||
125 | */ | ||
126 | #define XLOG_START_TRANS 0x01 /* Start a new transaction */ | ||
127 | #define XLOG_COMMIT_TRANS 0x02 /* Commit this transaction */ | ||
128 | #define XLOG_CONTINUE_TRANS 0x04 /* Cont this trans into new region */ | ||
129 | #define XLOG_WAS_CONT_TRANS 0x08 /* Cont this trans into new region */ | ||
130 | #define XLOG_END_TRANS 0x10 /* End a continued transaction */ | ||
131 | #define XLOG_UNMOUNT_TRANS 0x20 /* Unmount a filesystem transaction */ | ||
132 | |||
133 | |||
134 | typedef struct xlog_op_header { | ||
135 | __be32 oh_tid; /* transaction id of operation : 4 b */ | ||
136 | __be32 oh_len; /* bytes in data region : 4 b */ | ||
137 | __u8 oh_clientid; /* who sent me this : 1 b */ | ||
138 | __u8 oh_flags; /* : 1 b */ | ||
139 | __u16 oh_res2; /* 32 bit align : 2 b */ | ||
140 | } xlog_op_header_t; | ||
141 | |||
142 | /* valid values for h_fmt */ | ||
143 | #define XLOG_FMT_UNKNOWN 0 | ||
144 | #define XLOG_FMT_LINUX_LE 1 | ||
145 | #define XLOG_FMT_LINUX_BE 2 | ||
146 | #define XLOG_FMT_IRIX_BE 3 | ||
147 | |||
148 | /* our fmt */ | ||
149 | #ifdef XFS_NATIVE_HOST | ||
150 | #define XLOG_FMT XLOG_FMT_LINUX_BE | ||
151 | #else | ||
152 | #define XLOG_FMT XLOG_FMT_LINUX_LE | ||
153 | #endif | ||
154 | |||
155 | typedef struct xlog_rec_header { | ||
156 | __be32 h_magicno; /* log record (LR) identifier : 4 */ | ||
157 | __be32 h_cycle; /* write cycle of log : 4 */ | ||
158 | __be32 h_version; /* LR version : 4 */ | ||
159 | __be32 h_len; /* len in bytes; should be 64-bit aligned: 4 */ | ||
160 | __be64 h_lsn; /* lsn of this LR : 8 */ | ||
161 | __be64 h_tail_lsn; /* lsn of 1st LR w/ buffers not committed: 8 */ | ||
162 | __le32 h_crc; /* crc of log record : 4 */ | ||
163 | __be32 h_prev_block; /* block number to previous LR : 4 */ | ||
164 | __be32 h_num_logops; /* number of log operations in this LR : 4 */ | ||
165 | __be32 h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; | ||
166 | /* new fields */ | ||
167 | __be32 h_fmt; /* format of log record : 4 */ | ||
168 | uuid_t h_fs_uuid; /* uuid of FS : 16 */ | ||
169 | __be32 h_size; /* iclog size : 4 */ | ||
170 | } xlog_rec_header_t; | ||
171 | |||
172 | typedef struct xlog_rec_ext_header { | ||
173 | __be32 xh_cycle; /* write cycle of log : 4 */ | ||
174 | __be32 xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /* : 256 */ | ||
175 | } xlog_rec_ext_header_t; | ||
176 | |||
177 | /* | ||
178 | * Quite misnamed, because this union lays out the actual on-disk log buffer. | ||
179 | */ | ||
180 | typedef union xlog_in_core2 { | ||
181 | xlog_rec_header_t hic_header; | ||
182 | xlog_rec_ext_header_t hic_xheader; | ||
183 | char hic_sector[XLOG_HEADER_SIZE]; | ||
184 | } xlog_in_core_2_t; | ||
185 | |||
186 | /* not an on-disk structure, but needed by log recovery in userspace */ | ||
187 | typedef struct xfs_log_iovec { | ||
188 | void *i_addr; /* beginning address of region */ | ||
189 | int i_len; /* length in bytes of region */ | ||
190 | uint i_type; /* type of region */ | ||
191 | } xfs_log_iovec_t; | ||
192 | |||
193 | |||
194 | /* | ||
195 | * Transaction Header definitions. | ||
196 | * | ||
197 | * This is the structure written in the log at the head of every transaction. It | ||
198 | * identifies the type and id of the transaction, and contains the number of | ||
199 | * items logged by the transaction so we know how many to expect during | ||
200 | * recovery. | ||
201 | * | ||
202 | * Do not change the below structure without redoing the code in | ||
203 | * xlog_recover_add_to_trans() and xlog_recover_add_to_cont_trans(). | ||
204 | */ | ||
205 | typedef struct xfs_trans_header { | ||
206 | uint th_magic; /* magic number */ | ||
207 | uint th_type; /* transaction type */ | ||
208 | __int32_t th_tid; /* transaction id (unused) */ | ||
209 | uint th_num_items; /* num items logged by trans */ | ||
210 | } xfs_trans_header_t; | ||
211 | |||
212 | #define XFS_TRANS_HEADER_MAGIC 0x5452414e /* TRAN */ | ||
213 | |||
214 | /* | ||
215 | * Log item types. | ||
216 | */ | ||
217 | #define XFS_LI_EFI 0x1236 | ||
218 | #define XFS_LI_EFD 0x1237 | ||
219 | #define XFS_LI_IUNLINK 0x1238 | ||
220 | #define XFS_LI_INODE 0x123b /* aligned ino chunks, var-size ibufs */ | ||
221 | #define XFS_LI_BUF 0x123c /* v2 bufs, variable sized inode bufs */ | ||
222 | #define XFS_LI_DQUOT 0x123d | ||
223 | #define XFS_LI_QUOTAOFF 0x123e | ||
224 | #define XFS_LI_ICREATE 0x123f | ||
225 | |||
226 | #define XFS_LI_TYPE_DESC \ | ||
227 | { XFS_LI_EFI, "XFS_LI_EFI" }, \ | ||
228 | { XFS_LI_EFD, "XFS_LI_EFD" }, \ | ||
229 | { XFS_LI_IUNLINK, "XFS_LI_IUNLINK" }, \ | ||
230 | { XFS_LI_INODE, "XFS_LI_INODE" }, \ | ||
231 | { XFS_LI_BUF, "XFS_LI_BUF" }, \ | ||
232 | { XFS_LI_DQUOT, "XFS_LI_DQUOT" }, \ | ||
233 | { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ | ||
234 | { XFS_LI_ICREATE, "XFS_LI_ICREATE" } | ||
235 | |||
236 | /* | ||
237 | * Inode Log Item Format definitions. | ||
238 | * | ||
239 | * This is the structure used to lay out an inode log item in the | ||
240 | * log. The size of the inline data/extents/b-tree root to be logged | ||
241 | * (if any) is indicated in the ilf_dsize field. Changes to this structure | ||
242 | * must be added on to the end. | ||
243 | */ | ||
244 | typedef struct xfs_inode_log_format { | ||
245 | __uint16_t ilf_type; /* inode log item type */ | ||
246 | __uint16_t ilf_size; /* size of this item */ | ||
247 | __uint32_t ilf_fields; /* flags for fields logged */ | ||
248 | __uint16_t ilf_asize; /* size of attr d/ext/root */ | ||
249 | __uint16_t ilf_dsize; /* size of data/ext/root */ | ||
250 | __uint64_t ilf_ino; /* inode number */ | ||
251 | union { | ||
252 | __uint32_t ilfu_rdev; /* rdev value for dev inode*/ | ||
253 | uuid_t ilfu_uuid; /* mount point value */ | ||
254 | } ilf_u; | ||
255 | __int64_t ilf_blkno; /* blkno of inode buffer */ | ||
256 | __int32_t ilf_len; /* len of inode buffer */ | ||
257 | __int32_t ilf_boffset; /* off of inode in buffer */ | ||
258 | } xfs_inode_log_format_t; | ||
259 | |||
260 | typedef struct xfs_inode_log_format_32 { | ||
261 | __uint16_t ilf_type; /* inode log item type */ | ||
262 | __uint16_t ilf_size; /* size of this item */ | ||
263 | __uint32_t ilf_fields; /* flags for fields logged */ | ||
264 | __uint16_t ilf_asize; /* size of attr d/ext/root */ | ||
265 | __uint16_t ilf_dsize; /* size of data/ext/root */ | ||
266 | __uint64_t ilf_ino; /* inode number */ | ||
267 | union { | ||
268 | __uint32_t ilfu_rdev; /* rdev value for dev inode*/ | ||
269 | uuid_t ilfu_uuid; /* mount point value */ | ||
270 | } ilf_u; | ||
271 | __int64_t ilf_blkno; /* blkno of inode buffer */ | ||
272 | __int32_t ilf_len; /* len of inode buffer */ | ||
273 | __int32_t ilf_boffset; /* off of inode in buffer */ | ||
274 | } __attribute__((packed)) xfs_inode_log_format_32_t; | ||
275 | |||
276 | typedef struct xfs_inode_log_format_64 { | ||
277 | __uint16_t ilf_type; /* inode log item type */ | ||
278 | __uint16_t ilf_size; /* size of this item */ | ||
279 | __uint32_t ilf_fields; /* flags for fields logged */ | ||
280 | __uint16_t ilf_asize; /* size of attr d/ext/root */ | ||
281 | __uint16_t ilf_dsize; /* size of data/ext/root */ | ||
282 | __uint32_t ilf_pad; /* pad for 64 bit boundary */ | ||
283 | __uint64_t ilf_ino; /* inode number */ | ||
284 | union { | ||
285 | __uint32_t ilfu_rdev; /* rdev value for dev inode*/ | ||
286 | uuid_t ilfu_uuid; /* mount point value */ | ||
287 | } ilf_u; | ||
288 | __int64_t ilf_blkno; /* blkno of inode buffer */ | ||
289 | __int32_t ilf_len; /* len of inode buffer */ | ||
290 | __int32_t ilf_boffset; /* off of inode in buffer */ | ||
291 | } xfs_inode_log_format_64_t; | ||
292 | |||
293 | /* | ||
294 | * Flags for xfs_trans_log_inode flags field. | ||
295 | */ | ||
296 | #define XFS_ILOG_CORE 0x001 /* log standard inode fields */ | ||
297 | #define XFS_ILOG_DDATA 0x002 /* log i_df.if_data */ | ||
298 | #define XFS_ILOG_DEXT 0x004 /* log i_df.if_extents */ | ||
299 | #define XFS_ILOG_DBROOT 0x008 /* log i_df.i_broot */ | ||
300 | #define XFS_ILOG_DEV 0x010 /* log the dev field */ | ||
301 | #define XFS_ILOG_UUID 0x020 /* log the uuid field */ | ||
302 | #define XFS_ILOG_ADATA 0x040 /* log i_af.if_data */ | ||
303 | #define XFS_ILOG_AEXT 0x080 /* log i_af.if_extents */ | ||
304 | #define XFS_ILOG_ABROOT 0x100 /* log i_af.i_broot */ | ||
305 | #define XFS_ILOG_DOWNER 0x200 /* change the data fork owner on replay */ | ||
306 | #define XFS_ILOG_AOWNER 0x400 /* change the attr fork owner on replay */ | ||
307 | |||
308 | |||
309 | /* | ||
310 | * The timestamps are dirty, but not necessarily anything else in the inode | ||
311 | * core. Unlike the other fields above this one must never make it to disk | ||
312 | * in the ilf_fields of the inode_log_format, but is purely store in-memory in | ||
313 | * ili_fields in the inode_log_item. | ||
314 | */ | ||
315 | #define XFS_ILOG_TIMESTAMP 0x4000 | ||
316 | |||
317 | #define XFS_ILOG_NONCORE (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ | ||
318 | XFS_ILOG_DBROOT | XFS_ILOG_DEV | \ | ||
319 | XFS_ILOG_UUID | XFS_ILOG_ADATA | \ | ||
320 | XFS_ILOG_AEXT | XFS_ILOG_ABROOT | \ | ||
321 | XFS_ILOG_DOWNER | XFS_ILOG_AOWNER) | ||
322 | |||
323 | #define XFS_ILOG_DFORK (XFS_ILOG_DDATA | XFS_ILOG_DEXT | \ | ||
324 | XFS_ILOG_DBROOT) | ||
325 | |||
326 | #define XFS_ILOG_AFORK (XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ | ||
327 | XFS_ILOG_ABROOT) | ||
328 | |||
329 | #define XFS_ILOG_ALL (XFS_ILOG_CORE | XFS_ILOG_DDATA | \ | ||
330 | XFS_ILOG_DEXT | XFS_ILOG_DBROOT | \ | ||
331 | XFS_ILOG_DEV | XFS_ILOG_UUID | \ | ||
332 | XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ | ||
333 | XFS_ILOG_ABROOT | XFS_ILOG_TIMESTAMP | \ | ||
334 | XFS_ILOG_DOWNER | XFS_ILOG_AOWNER) | ||
335 | |||
336 | static inline int xfs_ilog_fbroot(int w) | ||
337 | { | ||
338 | return (w == XFS_DATA_FORK ? XFS_ILOG_DBROOT : XFS_ILOG_ABROOT); | ||
339 | } | ||
340 | |||
341 | static inline int xfs_ilog_fext(int w) | ||
342 | { | ||
343 | return (w == XFS_DATA_FORK ? XFS_ILOG_DEXT : XFS_ILOG_AEXT); | ||
344 | } | ||
345 | |||
346 | static inline int xfs_ilog_fdata(int w) | ||
347 | { | ||
348 | return (w == XFS_DATA_FORK ? XFS_ILOG_DDATA : XFS_ILOG_ADATA); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * Incore version of the on-disk inode core structures. We log this directly | ||
353 | * into the journal in host CPU format (for better or worse) and as such | ||
354 | * directly mirrors the xfs_dinode structure as it must contain all the same | ||
355 | * information. | ||
356 | */ | ||
357 | typedef struct xfs_ictimestamp { | ||
358 | __int32_t t_sec; /* timestamp seconds */ | ||
359 | __int32_t t_nsec; /* timestamp nanoseconds */ | ||
360 | } xfs_ictimestamp_t; | ||
361 | |||
362 | /* | ||
363 | * NOTE: This structure must be kept identical to struct xfs_dinode | ||
364 | * in xfs_dinode.h except for the endianness annotations. | ||
365 | */ | ||
366 | typedef struct xfs_icdinode { | ||
367 | __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ | ||
368 | __uint16_t di_mode; /* mode and type of file */ | ||
369 | __int8_t di_version; /* inode version */ | ||
370 | __int8_t di_format; /* format of di_c data */ | ||
371 | __uint16_t di_onlink; /* old number of links to file */ | ||
372 | __uint32_t di_uid; /* owner's user id */ | ||
373 | __uint32_t di_gid; /* owner's group id */ | ||
374 | __uint32_t di_nlink; /* number of links to file */ | ||
375 | __uint16_t di_projid_lo; /* lower part of owner's project id */ | ||
376 | __uint16_t di_projid_hi; /* higher part of owner's project id */ | ||
377 | __uint8_t di_pad[6]; /* unused, zeroed space */ | ||
378 | __uint16_t di_flushiter; /* incremented on flush */ | ||
379 | xfs_ictimestamp_t di_atime; /* time last accessed */ | ||
380 | xfs_ictimestamp_t di_mtime; /* time last modified */ | ||
381 | xfs_ictimestamp_t di_ctime; /* time created/inode modified */ | ||
382 | xfs_fsize_t di_size; /* number of bytes in file */ | ||
383 | xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */ | ||
384 | xfs_extlen_t di_extsize; /* basic/minimum extent size for file */ | ||
385 | xfs_extnum_t di_nextents; /* number of extents in data fork */ | ||
386 | xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/ | ||
387 | __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ | ||
388 | __int8_t di_aformat; /* format of attr fork's data */ | ||
389 | __uint32_t di_dmevmask; /* DMIG event mask */ | ||
390 | __uint16_t di_dmstate; /* DMIG state info */ | ||
391 | __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ | ||
392 | __uint32_t di_gen; /* generation number */ | ||
393 | |||
394 | /* di_next_unlinked is the only non-core field in the old dinode */ | ||
395 | xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ | ||
396 | |||
397 | /* start of the extended dinode, writable fields */ | ||
398 | __uint32_t di_crc; /* CRC of the inode */ | ||
399 | __uint64_t di_changecount; /* number of attribute changes */ | ||
400 | xfs_lsn_t di_lsn; /* flush sequence */ | ||
401 | __uint64_t di_flags2; /* more random flags */ | ||
402 | __uint8_t di_pad2[16]; /* more padding for future expansion */ | ||
403 | |||
404 | /* fields only written to during inode creation */ | ||
405 | xfs_ictimestamp_t di_crtime; /* time created */ | ||
406 | xfs_ino_t di_ino; /* inode number */ | ||
407 | uuid_t di_uuid; /* UUID of the filesystem */ | ||
408 | |||
409 | /* structure must be padded to 64 bit alignment */ | ||
410 | } xfs_icdinode_t; | ||
411 | |||
412 | static inline uint xfs_icdinode_size(int version) | ||
413 | { | ||
414 | if (version == 3) | ||
415 | return sizeof(struct xfs_icdinode); | ||
416 | return offsetof(struct xfs_icdinode, di_next_unlinked); | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Buffer Log Format defintions | ||
421 | * | ||
422 | * These are the physical dirty bitmap defintions for the log format structure. | ||
423 | */ | ||
424 | #define XFS_BLF_CHUNK 128 | ||
425 | #define XFS_BLF_SHIFT 7 | ||
426 | #define BIT_TO_WORD_SHIFT 5 | ||
427 | #define NBWORD (NBBY * sizeof(unsigned int)) | ||
428 | |||
429 | /* | ||
430 | * This flag indicates that the buffer contains on disk inodes | ||
431 | * and requires special recovery handling. | ||
432 | */ | ||
433 | #define XFS_BLF_INODE_BUF (1<<0) | ||
434 | |||
435 | /* | ||
436 | * This flag indicates that the buffer should not be replayed | ||
437 | * during recovery because its blocks are being freed. | ||
438 | */ | ||
439 | #define XFS_BLF_CANCEL (1<<1) | ||
440 | |||
441 | /* | ||
442 | * This flag indicates that the buffer contains on disk | ||
443 | * user or group dquots and may require special recovery handling. | ||
444 | */ | ||
445 | #define XFS_BLF_UDQUOT_BUF (1<<2) | ||
446 | #define XFS_BLF_PDQUOT_BUF (1<<3) | ||
447 | #define XFS_BLF_GDQUOT_BUF (1<<4) | ||
448 | |||
449 | /* | ||
450 | * This is the structure used to lay out a buf log item in the | ||
451 | * log. The data map describes which 128 byte chunks of the buffer | ||
452 | * have been logged. | ||
453 | */ | ||
454 | #define XFS_BLF_DATAMAP_SIZE ((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / NBWORD) | ||
455 | |||
456 | typedef struct xfs_buf_log_format { | ||
457 | unsigned short blf_type; /* buf log item type indicator */ | ||
458 | unsigned short blf_size; /* size of this item */ | ||
459 | ushort blf_flags; /* misc state */ | ||
460 | ushort blf_len; /* number of blocks in this buf */ | ||
461 | __int64_t blf_blkno; /* starting blkno of this buf */ | ||
462 | unsigned int blf_map_size; /* used size of data bitmap in words */ | ||
463 | unsigned int blf_data_map[XFS_BLF_DATAMAP_SIZE]; /* dirty bitmap */ | ||
464 | } xfs_buf_log_format_t; | ||
465 | |||
466 | /* | ||
467 | * All buffers now need to tell recovery where the magic number | ||
468 | * is so that it can verify and calculate the CRCs on the buffer correctly | ||
469 | * once the changes have been replayed into the buffer. | ||
470 | * | ||
471 | * The type value is held in the upper 5 bits of the blf_flags field, which is | ||
472 | * an unsigned 16 bit field. Hence we need to shift it 11 bits up and down. | ||
473 | */ | ||
474 | #define XFS_BLFT_BITS 5 | ||
475 | #define XFS_BLFT_SHIFT 11 | ||
476 | #define XFS_BLFT_MASK (((1 << XFS_BLFT_BITS) - 1) << XFS_BLFT_SHIFT) | ||
477 | |||
478 | enum xfs_blft { | ||
479 | XFS_BLFT_UNKNOWN_BUF = 0, | ||
480 | XFS_BLFT_UDQUOT_BUF, | ||
481 | XFS_BLFT_PDQUOT_BUF, | ||
482 | XFS_BLFT_GDQUOT_BUF, | ||
483 | XFS_BLFT_BTREE_BUF, | ||
484 | XFS_BLFT_AGF_BUF, | ||
485 | XFS_BLFT_AGFL_BUF, | ||
486 | XFS_BLFT_AGI_BUF, | ||
487 | XFS_BLFT_DINO_BUF, | ||
488 | XFS_BLFT_SYMLINK_BUF, | ||
489 | XFS_BLFT_DIR_BLOCK_BUF, | ||
490 | XFS_BLFT_DIR_DATA_BUF, | ||
491 | XFS_BLFT_DIR_FREE_BUF, | ||
492 | XFS_BLFT_DIR_LEAF1_BUF, | ||
493 | XFS_BLFT_DIR_LEAFN_BUF, | ||
494 | XFS_BLFT_DA_NODE_BUF, | ||
495 | XFS_BLFT_ATTR_LEAF_BUF, | ||
496 | XFS_BLFT_ATTR_RMT_BUF, | ||
497 | XFS_BLFT_SB_BUF, | ||
498 | XFS_BLFT_MAX_BUF = (1 << XFS_BLFT_BITS), | ||
499 | }; | ||
500 | |||
501 | static inline void | ||
502 | xfs_blft_to_flags(struct xfs_buf_log_format *blf, enum xfs_blft type) | ||
503 | { | ||
504 | ASSERT(type > XFS_BLFT_UNKNOWN_BUF && type < XFS_BLFT_MAX_BUF); | ||
505 | blf->blf_flags &= ~XFS_BLFT_MASK; | ||
506 | blf->blf_flags |= ((type << XFS_BLFT_SHIFT) & XFS_BLFT_MASK); | ||
507 | } | ||
508 | |||
509 | static inline __uint16_t | ||
510 | xfs_blft_from_flags(struct xfs_buf_log_format *blf) | ||
511 | { | ||
512 | return (blf->blf_flags & XFS_BLFT_MASK) >> XFS_BLFT_SHIFT; | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * EFI/EFD log format definitions | ||
517 | */ | ||
518 | typedef struct xfs_extent { | ||
519 | xfs_dfsbno_t ext_start; | ||
520 | xfs_extlen_t ext_len; | ||
521 | } xfs_extent_t; | ||
522 | |||
523 | /* | ||
524 | * Since an xfs_extent_t has types (start:64, len: 32) | ||
525 | * there are different alignments on 32 bit and 64 bit kernels. | ||
526 | * So we provide the different variants for use by a | ||
527 | * conversion routine. | ||
528 | */ | ||
529 | typedef struct xfs_extent_32 { | ||
530 | __uint64_t ext_start; | ||
531 | __uint32_t ext_len; | ||
532 | } __attribute__((packed)) xfs_extent_32_t; | ||
533 | |||
534 | typedef struct xfs_extent_64 { | ||
535 | __uint64_t ext_start; | ||
536 | __uint32_t ext_len; | ||
537 | __uint32_t ext_pad; | ||
538 | } xfs_extent_64_t; | ||
539 | |||
540 | /* | ||
541 | * This is the structure used to lay out an efi log item in the | ||
542 | * log. The efi_extents field is a variable size array whose | ||
543 | * size is given by efi_nextents. | ||
544 | */ | ||
545 | typedef struct xfs_efi_log_format { | ||
546 | __uint16_t efi_type; /* efi log item type */ | ||
547 | __uint16_t efi_size; /* size of this item */ | ||
548 | __uint32_t efi_nextents; /* # extents to free */ | ||
549 | __uint64_t efi_id; /* efi identifier */ | ||
550 | xfs_extent_t efi_extents[1]; /* array of extents to free */ | ||
551 | } xfs_efi_log_format_t; | ||
552 | |||
553 | typedef struct xfs_efi_log_format_32 { | ||
554 | __uint16_t efi_type; /* efi log item type */ | ||
555 | __uint16_t efi_size; /* size of this item */ | ||
556 | __uint32_t efi_nextents; /* # extents to free */ | ||
557 | __uint64_t efi_id; /* efi identifier */ | ||
558 | xfs_extent_32_t efi_extents[1]; /* array of extents to free */ | ||
559 | } __attribute__((packed)) xfs_efi_log_format_32_t; | ||
560 | |||
561 | typedef struct xfs_efi_log_format_64 { | ||
562 | __uint16_t efi_type; /* efi log item type */ | ||
563 | __uint16_t efi_size; /* size of this item */ | ||
564 | __uint32_t efi_nextents; /* # extents to free */ | ||
565 | __uint64_t efi_id; /* efi identifier */ | ||
566 | xfs_extent_64_t efi_extents[1]; /* array of extents to free */ | ||
567 | } xfs_efi_log_format_64_t; | ||
568 | |||
569 | /* | ||
570 | * This is the structure used to lay out an efd log item in the | ||
571 | * log. The efd_extents array is a variable size array whose | ||
572 | * size is given by efd_nextents; | ||
573 | */ | ||
574 | typedef struct xfs_efd_log_format { | ||
575 | __uint16_t efd_type; /* efd log item type */ | ||
576 | __uint16_t efd_size; /* size of this item */ | ||
577 | __uint32_t efd_nextents; /* # of extents freed */ | ||
578 | __uint64_t efd_efi_id; /* id of corresponding efi */ | ||
579 | xfs_extent_t efd_extents[1]; /* array of extents freed */ | ||
580 | } xfs_efd_log_format_t; | ||
581 | |||
582 | typedef struct xfs_efd_log_format_32 { | ||
583 | __uint16_t efd_type; /* efd log item type */ | ||
584 | __uint16_t efd_size; /* size of this item */ | ||
585 | __uint32_t efd_nextents; /* # of extents freed */ | ||
586 | __uint64_t efd_efi_id; /* id of corresponding efi */ | ||
587 | xfs_extent_32_t efd_extents[1]; /* array of extents freed */ | ||
588 | } __attribute__((packed)) xfs_efd_log_format_32_t; | ||
589 | |||
590 | typedef struct xfs_efd_log_format_64 { | ||
591 | __uint16_t efd_type; /* efd log item type */ | ||
592 | __uint16_t efd_size; /* size of this item */ | ||
593 | __uint32_t efd_nextents; /* # of extents freed */ | ||
594 | __uint64_t efd_efi_id; /* id of corresponding efi */ | ||
595 | xfs_extent_64_t efd_extents[1]; /* array of extents freed */ | ||
596 | } xfs_efd_log_format_64_t; | ||
597 | |||
598 | /* | ||
599 | * Dquot Log format definitions. | ||
600 | * | ||
601 | * The first two fields must be the type and size fitting into | ||
602 | * 32 bits : log_recovery code assumes that. | ||
603 | */ | ||
604 | typedef struct xfs_dq_logformat { | ||
605 | __uint16_t qlf_type; /* dquot log item type */ | ||
606 | __uint16_t qlf_size; /* size of this item */ | ||
607 | xfs_dqid_t qlf_id; /* usr/grp/proj id : 32 bits */ | ||
608 | __int64_t qlf_blkno; /* blkno of dquot buffer */ | ||
609 | __int32_t qlf_len; /* len of dquot buffer */ | ||
610 | __uint32_t qlf_boffset; /* off of dquot in buffer */ | ||
611 | } xfs_dq_logformat_t; | ||
612 | |||
613 | /* | ||
614 | * log format struct for QUOTAOFF records. | ||
615 | * The first two fields must be the type and size fitting into | ||
616 | * 32 bits : log_recovery code assumes that. | ||
617 | * We write two LI_QUOTAOFF logitems per quotaoff, the last one keeps a pointer | ||
618 | * to the first and ensures that the first logitem is taken out of the AIL | ||
619 | * only when the last one is securely committed. | ||
620 | */ | ||
621 | typedef struct xfs_qoff_logformat { | ||
622 | unsigned short qf_type; /* quotaoff log item type */ | ||
623 | unsigned short qf_size; /* size of this item */ | ||
624 | unsigned int qf_flags; /* USR and/or GRP */ | ||
625 | char qf_pad[12]; /* padding for future */ | ||
626 | } xfs_qoff_logformat_t; | ||
627 | |||
628 | /* | ||
629 | * Disk quotas status in m_qflags, and also sb_qflags. 16 bits. | ||
630 | */ | ||
631 | #define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */ | ||
632 | #define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */ | ||
633 | #define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */ | ||
634 | #define XFS_PQUOTA_ACCT 0x0008 /* project quota accounting ON */ | ||
635 | #define XFS_OQUOTA_ENFD 0x0010 /* other (grp/prj) quota limits enforced */ | ||
636 | #define XFS_OQUOTA_CHKD 0x0020 /* quotacheck run on other (grp/prj) quotas */ | ||
637 | #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */ | ||
638 | |||
639 | /* | ||
640 | * Conversion to and from the combined OQUOTA flag (if necessary) | ||
641 | * is done only in xfs_sb_qflags_to_disk() and xfs_sb_qflags_from_disk() | ||
642 | */ | ||
643 | #define XFS_GQUOTA_ENFD 0x0080 /* group quota limits enforced */ | ||
644 | #define XFS_GQUOTA_CHKD 0x0100 /* quotacheck run on group quotas */ | ||
645 | #define XFS_PQUOTA_ENFD 0x0200 /* project quota limits enforced */ | ||
646 | #define XFS_PQUOTA_CHKD 0x0400 /* quotacheck run on project quotas */ | ||
647 | |||
648 | #define XFS_ALL_QUOTA_ACCT \ | ||
649 | (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT) | ||
650 | #define XFS_ALL_QUOTA_ENFD \ | ||
651 | (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD | XFS_PQUOTA_ENFD) | ||
652 | #define XFS_ALL_QUOTA_CHKD \ | ||
653 | (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD | XFS_PQUOTA_CHKD) | ||
654 | |||
655 | #define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ | ||
656 | XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ | ||
657 | XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD|\ | ||
658 | XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD|\ | ||
659 | XFS_PQUOTA_CHKD) | ||
660 | |||
661 | /* | ||
662 | * Inode create log item structure | ||
663 | * | ||
664 | * Log recovery assumes the first two entries are the type and size and they fit | ||
665 | * in 32 bits. Also in host order (ugh) so they have to be 32 bit aligned so | ||
666 | * decoding can be done correctly. | ||
667 | */ | ||
668 | struct xfs_icreate_log { | ||
669 | __uint16_t icl_type; /* type of log format structure */ | ||
670 | __uint16_t icl_size; /* size of log format structure */ | ||
671 | __be32 icl_ag; /* ag being allocated in */ | ||
672 | __be32 icl_agbno; /* start block of inode range */ | ||
673 | __be32 icl_count; /* number of inodes to initialise */ | ||
674 | __be32 icl_isize; /* size of inodes */ | ||
675 | __be32 icl_length; /* length of extent to initialise */ | ||
676 | __be32 icl_gen; /* inode generation number to use */ | ||
677 | }; | ||
678 | |||
679 | #endif /* __XFS_LOG_FORMAT_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_log_recover.h b/fs/xfs/libxfs/xfs_log_recover.h new file mode 100644 index 000000000000..1c55ccbb379d --- /dev/null +++ b/fs/xfs/libxfs/xfs_log_recover.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_LOG_RECOVER_H__ | ||
19 | #define __XFS_LOG_RECOVER_H__ | ||
20 | |||
21 | /* | ||
22 | * Macros, structures, prototypes for internal log manager use. | ||
23 | */ | ||
24 | |||
25 | #define XLOG_RHASH_BITS 4 | ||
26 | #define XLOG_RHASH_SIZE 16 | ||
27 | #define XLOG_RHASH_SHIFT 2 | ||
28 | #define XLOG_RHASH(tid) \ | ||
29 | ((((__uint32_t)tid)>>XLOG_RHASH_SHIFT) & (XLOG_RHASH_SIZE-1)) | ||
30 | |||
31 | #define XLOG_MAX_REGIONS_IN_ITEM (XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK / 2 + 1) | ||
32 | |||
33 | |||
34 | /* | ||
35 | * item headers are in ri_buf[0]. Additional buffers follow. | ||
36 | */ | ||
37 | typedef struct xlog_recover_item { | ||
38 | struct list_head ri_list; | ||
39 | int ri_type; | ||
40 | int ri_cnt; /* count of regions found */ | ||
41 | int ri_total; /* total regions */ | ||
42 | xfs_log_iovec_t *ri_buf; /* ptr to regions buffer */ | ||
43 | } xlog_recover_item_t; | ||
44 | |||
45 | struct xlog_tid; | ||
46 | typedef struct xlog_recover { | ||
47 | struct hlist_node r_list; | ||
48 | xlog_tid_t r_log_tid; /* log's transaction id */ | ||
49 | xfs_trans_header_t r_theader; /* trans header for partial */ | ||
50 | int r_state; /* not needed */ | ||
51 | xfs_lsn_t r_lsn; /* xact lsn */ | ||
52 | struct list_head r_itemq; /* q for items */ | ||
53 | } xlog_recover_t; | ||
54 | |||
55 | #define ITEM_TYPE(i) (*(ushort *)(i)->ri_buf[0].i_addr) | ||
56 | |||
57 | /* | ||
58 | * This is the number of entries in the l_buf_cancel_table used during | ||
59 | * recovery. | ||
60 | */ | ||
61 | #define XLOG_BC_TABLE_SIZE 64 | ||
62 | |||
63 | #define XLOG_RECOVER_PASS1 1 | ||
64 | #define XLOG_RECOVER_PASS2 2 | ||
65 | |||
66 | #endif /* __XFS_LOG_RECOVER_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h new file mode 100644 index 000000000000..137e20937077 --- /dev/null +++ b/fs/xfs/libxfs/xfs_quota_defs.h | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_QUOTA_DEFS_H__ | ||
19 | #define __XFS_QUOTA_DEFS_H__ | ||
20 | |||
21 | /* | ||
22 | * Quota definitions shared between user and kernel source trees. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * Even though users may not have quota limits occupying all 64-bits, | ||
27 | * they may need 64-bit accounting. Hence, 64-bit quota-counters, | ||
28 | * and quota-limits. This is a waste in the common case, but hey ... | ||
29 | */ | ||
30 | typedef __uint64_t xfs_qcnt_t; | ||
31 | typedef __uint16_t xfs_qwarncnt_t; | ||
32 | |||
33 | /* | ||
34 | * flags for q_flags field in the dquot. | ||
35 | */ | ||
36 | #define XFS_DQ_USER 0x0001 /* a user quota */ | ||
37 | #define XFS_DQ_PROJ 0x0002 /* project quota */ | ||
38 | #define XFS_DQ_GROUP 0x0004 /* a group quota */ | ||
39 | #define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */ | ||
40 | #define XFS_DQ_FREEING 0x0010 /* dquot is beeing torn down */ | ||
41 | |||
42 | #define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP) | ||
43 | |||
44 | #define XFS_DQ_FLAGS \ | ||
45 | { XFS_DQ_USER, "USER" }, \ | ||
46 | { XFS_DQ_PROJ, "PROJ" }, \ | ||
47 | { XFS_DQ_GROUP, "GROUP" }, \ | ||
48 | { XFS_DQ_DIRTY, "DIRTY" }, \ | ||
49 | { XFS_DQ_FREEING, "FREEING" } | ||
50 | |||
51 | /* | ||
52 | * We have the possibility of all three quota types being active at once, and | ||
53 | * hence free space modification requires modification of all three current | ||
54 | * dquots in a single transaction. For this case we need to have a reservation | ||
55 | * of at least 3 dquots. | ||
56 | * | ||
57 | * However, a chmod operation can change both UID and GID in a single | ||
58 | * transaction, resulting in requiring {old, new} x {uid, gid} dquots to be | ||
59 | * modified. Hence for this case we need to reserve space for at least 4 dquots. | ||
60 | * | ||
61 | * And in the worst case, there's a rename operation that can be modifying up to | ||
62 | * 4 inodes with dquots attached to them. In reality, the only inodes that can | ||
63 | * have their dquots modified are the source and destination directory inodes | ||
64 | * due to directory name creation and removal. That can require space allocation | ||
65 | * and/or freeing on both directory inodes, and hence all three dquots on each | ||
66 | * inode can be modified. And if the directories are world writeable, all the | ||
67 | * dquots can be unique and so 6 dquots can be modified.... | ||
68 | * | ||
69 | * And, of course, we also need to take into account the dquot log format item | ||
70 | * used to describe each dquot. | ||
71 | */ | ||
72 | #define XFS_DQUOT_LOGRES(mp) \ | ||
73 | ((sizeof(struct xfs_dq_logformat) + sizeof(struct xfs_disk_dquot)) * 6) | ||
74 | |||
75 | #define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT) | ||
76 | #define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT) | ||
77 | #define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT) | ||
78 | #define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT) | ||
79 | #define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD) | ||
80 | #define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD) | ||
81 | #define XFS_IS_PQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_PQUOTA_ENFD) | ||
82 | |||
83 | /* | ||
84 | * Incore only flags for quotaoff - these bits get cleared when quota(s) | ||
85 | * are in the process of getting turned off. These flags are in m_qflags but | ||
86 | * never in sb_qflags. | ||
87 | */ | ||
88 | #define XFS_UQUOTA_ACTIVE 0x1000 /* uquotas are being turned off */ | ||
89 | #define XFS_GQUOTA_ACTIVE 0x2000 /* gquotas are being turned off */ | ||
90 | #define XFS_PQUOTA_ACTIVE 0x4000 /* pquotas are being turned off */ | ||
91 | #define XFS_ALL_QUOTA_ACTIVE \ | ||
92 | (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE) | ||
93 | |||
94 | /* | ||
95 | * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees | ||
96 | * quota will be not be switched off as long as that inode lock is held. | ||
97 | */ | ||
98 | #define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \ | ||
99 | XFS_GQUOTA_ACTIVE | \ | ||
100 | XFS_PQUOTA_ACTIVE)) | ||
101 | #define XFS_IS_OQUOTA_ON(mp) ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \ | ||
102 | XFS_PQUOTA_ACTIVE)) | ||
103 | #define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE) | ||
104 | #define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE) | ||
105 | #define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE) | ||
106 | |||
107 | /* | ||
108 | * Flags to tell various functions what to do. Not all of these are meaningful | ||
109 | * to a single function. None of these XFS_QMOPT_* flags are meant to have | ||
110 | * persistent values (ie. their values can and will change between versions) | ||
111 | */ | ||
112 | #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ | ||
113 | #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ | ||
114 | #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ | ||
115 | #define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */ | ||
116 | #define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */ | ||
117 | #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if needed */ | ||
118 | #define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot if damaged */ | ||
119 | #define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */ | ||
120 | #define XFS_QMOPT_ENOSPC 0x0004000 /* enospc instead of edquot (prj) */ | ||
121 | |||
122 | /* | ||
123 | * flags to xfs_trans_mod_dquot to indicate which field needs to be | ||
124 | * modified. | ||
125 | */ | ||
126 | #define XFS_QMOPT_RES_REGBLKS 0x0010000 | ||
127 | #define XFS_QMOPT_RES_RTBLKS 0x0020000 | ||
128 | #define XFS_QMOPT_BCOUNT 0x0040000 | ||
129 | #define XFS_QMOPT_ICOUNT 0x0080000 | ||
130 | #define XFS_QMOPT_RTBCOUNT 0x0100000 | ||
131 | #define XFS_QMOPT_DELBCOUNT 0x0200000 | ||
132 | #define XFS_QMOPT_DELRTBCOUNT 0x0400000 | ||
133 | #define XFS_QMOPT_RES_INOS 0x0800000 | ||
134 | |||
135 | /* | ||
136 | * flags for dqalloc. | ||
137 | */ | ||
138 | #define XFS_QMOPT_INHERIT 0x1000000 | ||
139 | |||
140 | /* | ||
141 | * flags to xfs_trans_mod_dquot. | ||
142 | */ | ||
143 | #define XFS_TRANS_DQ_RES_BLKS XFS_QMOPT_RES_REGBLKS | ||
144 | #define XFS_TRANS_DQ_RES_RTBLKS XFS_QMOPT_RES_RTBLKS | ||
145 | #define XFS_TRANS_DQ_RES_INOS XFS_QMOPT_RES_INOS | ||
146 | #define XFS_TRANS_DQ_BCOUNT XFS_QMOPT_BCOUNT | ||
147 | #define XFS_TRANS_DQ_DELBCOUNT XFS_QMOPT_DELBCOUNT | ||
148 | #define XFS_TRANS_DQ_ICOUNT XFS_QMOPT_ICOUNT | ||
149 | #define XFS_TRANS_DQ_RTBCOUNT XFS_QMOPT_RTBCOUNT | ||
150 | #define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT | ||
151 | |||
152 | |||
153 | #define XFS_QMOPT_QUOTALL \ | ||
154 | (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA) | ||
155 | #define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) | ||
156 | |||
157 | extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq, | ||
158 | xfs_dqid_t id, uint type, uint flags, char *str); | ||
159 | extern int xfs_calc_dquots_per_chunk(unsigned int nbblks); | ||
160 | |||
161 | #endif /* __XFS_QUOTA_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h new file mode 100644 index 000000000000..82404da2ca67 --- /dev/null +++ b/fs/xfs/libxfs/xfs_shared.h | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | ||
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it would be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write the Free Software Foundation, | ||
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | #ifndef __XFS_SHARED_H__ | ||
20 | #define __XFS_SHARED_H__ | ||
21 | |||
22 | /* | ||
23 | * Definitions shared between kernel and userspace that don't fit into any other | ||
24 | * header file that is shared with userspace. | ||
25 | */ | ||
26 | struct xfs_ifork; | ||
27 | struct xfs_buf; | ||
28 | struct xfs_buf_ops; | ||
29 | struct xfs_mount; | ||
30 | struct xfs_trans; | ||
31 | struct xfs_inode; | ||
32 | |||
33 | /* | ||
34 | * Buffer verifier operations are widely used, including userspace tools | ||
35 | */ | ||
36 | extern const struct xfs_buf_ops xfs_agf_buf_ops; | ||
37 | extern const struct xfs_buf_ops xfs_agi_buf_ops; | ||
38 | extern const struct xfs_buf_ops xfs_agf_buf_ops; | ||
39 | extern const struct xfs_buf_ops xfs_agfl_buf_ops; | ||
40 | extern const struct xfs_buf_ops xfs_allocbt_buf_ops; | ||
41 | extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; | ||
42 | extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; | ||
43 | extern const struct xfs_buf_ops xfs_bmbt_buf_ops; | ||
44 | extern const struct xfs_buf_ops xfs_da3_node_buf_ops; | ||
45 | extern const struct xfs_buf_ops xfs_dquot_buf_ops; | ||
46 | extern const struct xfs_buf_ops xfs_symlink_buf_ops; | ||
47 | extern const struct xfs_buf_ops xfs_agi_buf_ops; | ||
48 | extern const struct xfs_buf_ops xfs_inobt_buf_ops; | ||
49 | extern const struct xfs_buf_ops xfs_inode_buf_ops; | ||
50 | extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; | ||
51 | extern const struct xfs_buf_ops xfs_dquot_buf_ops; | ||
52 | extern const struct xfs_buf_ops xfs_sb_buf_ops; | ||
53 | extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops; | ||
54 | extern const struct xfs_buf_ops xfs_symlink_buf_ops; | ||
55 | |||
56 | /* | ||
57 | * Transaction types. Used to distinguish types of buffers. These never reach | ||
58 | * the log. | ||
59 | */ | ||
60 | #define XFS_TRANS_SETATTR_NOT_SIZE 1 | ||
61 | #define XFS_TRANS_SETATTR_SIZE 2 | ||
62 | #define XFS_TRANS_INACTIVE 3 | ||
63 | #define XFS_TRANS_CREATE 4 | ||
64 | #define XFS_TRANS_CREATE_TRUNC 5 | ||
65 | #define XFS_TRANS_TRUNCATE_FILE 6 | ||
66 | #define XFS_TRANS_REMOVE 7 | ||
67 | #define XFS_TRANS_LINK 8 | ||
68 | #define XFS_TRANS_RENAME 9 | ||
69 | #define XFS_TRANS_MKDIR 10 | ||
70 | #define XFS_TRANS_RMDIR 11 | ||
71 | #define XFS_TRANS_SYMLINK 12 | ||
72 | #define XFS_TRANS_SET_DMATTRS 13 | ||
73 | #define XFS_TRANS_GROWFS 14 | ||
74 | #define XFS_TRANS_STRAT_WRITE 15 | ||
75 | #define XFS_TRANS_DIOSTRAT 16 | ||
76 | /* 17 was XFS_TRANS_WRITE_SYNC */ | ||
77 | #define XFS_TRANS_WRITEID 18 | ||
78 | #define XFS_TRANS_ADDAFORK 19 | ||
79 | #define XFS_TRANS_ATTRINVAL 20 | ||
80 | #define XFS_TRANS_ATRUNCATE 21 | ||
81 | #define XFS_TRANS_ATTR_SET 22 | ||
82 | #define XFS_TRANS_ATTR_RM 23 | ||
83 | #define XFS_TRANS_ATTR_FLAG 24 | ||
84 | #define XFS_TRANS_CLEAR_AGI_BUCKET 25 | ||
85 | #define XFS_TRANS_QM_SBCHANGE 26 | ||
86 | /* | ||
87 | * Dummy entries since we use the transaction type to index into the | ||
88 | * trans_type[] in xlog_recover_print_trans_head() | ||
89 | */ | ||
90 | #define XFS_TRANS_DUMMY1 27 | ||
91 | #define XFS_TRANS_DUMMY2 28 | ||
92 | #define XFS_TRANS_QM_QUOTAOFF 29 | ||
93 | #define XFS_TRANS_QM_DQALLOC 30 | ||
94 | #define XFS_TRANS_QM_SETQLIM 31 | ||
95 | #define XFS_TRANS_QM_DQCLUSTER 32 | ||
96 | #define XFS_TRANS_QM_QINOCREATE 33 | ||
97 | #define XFS_TRANS_QM_QUOTAOFF_END 34 | ||
98 | #define XFS_TRANS_SB_UNIT 35 | ||
99 | #define XFS_TRANS_FSYNC_TS 36 | ||
100 | #define XFS_TRANS_GROWFSRT_ALLOC 37 | ||
101 | #define XFS_TRANS_GROWFSRT_ZERO 38 | ||
102 | #define XFS_TRANS_GROWFSRT_FREE 39 | ||
103 | #define XFS_TRANS_SWAPEXT 40 | ||
104 | #define XFS_TRANS_SB_COUNT 41 | ||
105 | #define XFS_TRANS_CHECKPOINT 42 | ||
106 | #define XFS_TRANS_ICREATE 43 | ||
107 | #define XFS_TRANS_CREATE_TMPFILE 44 | ||
108 | #define XFS_TRANS_TYPE_MAX 44 | ||
109 | /* new transaction types need to be reflected in xfs_logprint(8) */ | ||
110 | |||
111 | #define XFS_TRANS_TYPES \ | ||
112 | { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \ | ||
113 | { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ | ||
114 | { XFS_TRANS_INACTIVE, "INACTIVE" }, \ | ||
115 | { XFS_TRANS_CREATE, "CREATE" }, \ | ||
116 | { XFS_TRANS_CREATE_TMPFILE, "CREATE_TMPFILE" }, \ | ||
117 | { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ | ||
118 | { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ | ||
119 | { XFS_TRANS_REMOVE, "REMOVE" }, \ | ||
120 | { XFS_TRANS_LINK, "LINK" }, \ | ||
121 | { XFS_TRANS_RENAME, "RENAME" }, \ | ||
122 | { XFS_TRANS_MKDIR, "MKDIR" }, \ | ||
123 | { XFS_TRANS_RMDIR, "RMDIR" }, \ | ||
124 | { XFS_TRANS_SYMLINK, "SYMLINK" }, \ | ||
125 | { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \ | ||
126 | { XFS_TRANS_GROWFS, "GROWFS" }, \ | ||
127 | { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \ | ||
128 | { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \ | ||
129 | { XFS_TRANS_WRITEID, "WRITEID" }, \ | ||
130 | { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \ | ||
131 | { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \ | ||
132 | { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \ | ||
133 | { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \ | ||
134 | { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \ | ||
135 | { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \ | ||
136 | { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \ | ||
137 | { XFS_TRANS_QM_SBCHANGE, "QM_SBCHANGE" }, \ | ||
138 | { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \ | ||
139 | { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \ | ||
140 | { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \ | ||
141 | { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \ | ||
142 | { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \ | ||
143 | { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \ | ||
144 | { XFS_TRANS_SB_UNIT, "SB_UNIT" }, \ | ||
145 | { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \ | ||
146 | { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \ | ||
147 | { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \ | ||
148 | { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \ | ||
149 | { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \ | ||
150 | { XFS_TRANS_SB_COUNT, "SB_COUNT" }, \ | ||
151 | { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \ | ||
152 | { XFS_TRANS_DUMMY1, "DUMMY1" }, \ | ||
153 | { XFS_TRANS_DUMMY2, "DUMMY2" }, \ | ||
154 | { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" } | ||
155 | |||
156 | /* | ||
157 | * This structure is used to track log items associated with | ||
158 | * a transaction. It points to the log item and keeps some | ||
159 | * flags to track the state of the log item. It also tracks | ||
160 | * the amount of space needed to log the item it describes | ||
161 | * once we get to commit processing (see xfs_trans_commit()). | ||
162 | */ | ||
163 | struct xfs_log_item_desc { | ||
164 | struct xfs_log_item *lid_item; | ||
165 | struct list_head lid_trans; | ||
166 | unsigned char lid_flags; | ||
167 | }; | ||
168 | |||
169 | #define XFS_LID_DIRTY 0x1 | ||
170 | |||
171 | /* log size calculation functions */ | ||
172 | int xfs_log_calc_unit_res(struct xfs_mount *mp, int unit_bytes); | ||
173 | int xfs_log_calc_minimum_size(struct xfs_mount *); | ||
174 | |||
175 | |||
176 | /* | ||
177 | * Values for t_flags. | ||
178 | */ | ||
179 | #define XFS_TRANS_DIRTY 0x01 /* something needs to be logged */ | ||
180 | #define XFS_TRANS_SB_DIRTY 0x02 /* superblock is modified */ | ||
181 | #define XFS_TRANS_PERM_LOG_RES 0x04 /* xact took a permanent log res */ | ||
182 | #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ | ||
183 | #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ | ||
184 | #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ | ||
185 | #define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer | ||
186 | count in superblock */ | ||
187 | /* | ||
188 | * Values for call flags parameter. | ||
189 | */ | ||
190 | #define XFS_TRANS_RELEASE_LOG_RES 0x4 | ||
191 | #define XFS_TRANS_ABORT 0x8 | ||
192 | |||
193 | /* | ||
194 | * Field values for xfs_trans_mod_sb. | ||
195 | */ | ||
196 | #define XFS_TRANS_SB_ICOUNT 0x00000001 | ||
197 | #define XFS_TRANS_SB_IFREE 0x00000002 | ||
198 | #define XFS_TRANS_SB_FDBLOCKS 0x00000004 | ||
199 | #define XFS_TRANS_SB_RES_FDBLOCKS 0x00000008 | ||
200 | #define XFS_TRANS_SB_FREXTENTS 0x00000010 | ||
201 | #define XFS_TRANS_SB_RES_FREXTENTS 0x00000020 | ||
202 | #define XFS_TRANS_SB_DBLOCKS 0x00000040 | ||
203 | #define XFS_TRANS_SB_AGCOUNT 0x00000080 | ||
204 | #define XFS_TRANS_SB_IMAXPCT 0x00000100 | ||
205 | #define XFS_TRANS_SB_REXTSIZE 0x00000200 | ||
206 | #define XFS_TRANS_SB_RBMBLOCKS 0x00000400 | ||
207 | #define XFS_TRANS_SB_RBLOCKS 0x00000800 | ||
208 | #define XFS_TRANS_SB_REXTENTS 0x00001000 | ||
209 | #define XFS_TRANS_SB_REXTSLOG 0x00002000 | ||
210 | |||
211 | /* | ||
212 | * Here we centralize the specification of XFS meta-data buffer reference count | ||
213 | * values. This determines how hard the buffer cache tries to hold onto the | ||
214 | * buffer. | ||
215 | */ | ||
216 | #define XFS_AGF_REF 4 | ||
217 | #define XFS_AGI_REF 4 | ||
218 | #define XFS_AGFL_REF 3 | ||
219 | #define XFS_INO_BTREE_REF 3 | ||
220 | #define XFS_ALLOC_BTREE_REF 2 | ||
221 | #define XFS_BMAP_BTREE_REF 2 | ||
222 | #define XFS_DIR_BTREE_REF 2 | ||
223 | #define XFS_INO_REF 2 | ||
224 | #define XFS_ATTR_BTREE_REF 1 | ||
225 | #define XFS_DQUOT_REF 1 | ||
226 | |||
227 | /* | ||
228 | * Flags for xfs_trans_ichgtime(). | ||
229 | */ | ||
230 | #define XFS_ICHGTIME_MOD 0x1 /* data fork modification timestamp */ | ||
231 | #define XFS_ICHGTIME_CHG 0x2 /* inode field change timestamp */ | ||
232 | #define XFS_ICHGTIME_CREATE 0x4 /* inode create timestamp */ | ||
233 | |||
234 | |||
235 | /* | ||
236 | * Symlink decoding/encoding functions | ||
237 | */ | ||
238 | int xfs_symlink_blocks(struct xfs_mount *mp, int pathlen); | ||
239 | int xfs_symlink_hdr_set(struct xfs_mount *mp, xfs_ino_t ino, uint32_t offset, | ||
240 | uint32_t size, struct xfs_buf *bp); | ||
241 | bool xfs_symlink_hdr_ok(xfs_ino_t ino, uint32_t offset, | ||
242 | uint32_t size, struct xfs_buf *bp); | ||
243 | void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp, | ||
244 | struct xfs_inode *ip, struct xfs_ifork *ifp); | ||
245 | |||
246 | #endif /* __XFS_SHARED_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h new file mode 100644 index 000000000000..1097d14cd583 --- /dev/null +++ b/fs/xfs/libxfs/xfs_trans_resv.h | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_TRANS_RESV_H__ | ||
19 | #define __XFS_TRANS_RESV_H__ | ||
20 | |||
21 | struct xfs_mount; | ||
22 | |||
23 | /* | ||
24 | * structure for maintaining pre-calculated transaction reservations. | ||
25 | */ | ||
26 | struct xfs_trans_res { | ||
27 | uint tr_logres; /* log space unit in bytes per log ticket */ | ||
28 | int tr_logcount; /* number of log operations per log ticket */ | ||
29 | int tr_logflags; /* log flags, currently only used for indicating | ||
30 | * a reservation request is permanent or not */ | ||
31 | }; | ||
32 | |||
33 | struct xfs_trans_resv { | ||
34 | struct xfs_trans_res tr_write; /* extent alloc trans */ | ||
35 | struct xfs_trans_res tr_itruncate; /* truncate trans */ | ||
36 | struct xfs_trans_res tr_rename; /* rename trans */ | ||
37 | struct xfs_trans_res tr_link; /* link trans */ | ||
38 | struct xfs_trans_res tr_remove; /* unlink trans */ | ||
39 | struct xfs_trans_res tr_symlink; /* symlink trans */ | ||
40 | struct xfs_trans_res tr_create; /* create trans */ | ||
41 | struct xfs_trans_res tr_create_tmpfile; /* create O_TMPFILE trans */ | ||
42 | struct xfs_trans_res tr_mkdir; /* mkdir trans */ | ||
43 | struct xfs_trans_res tr_ifree; /* inode free trans */ | ||
44 | struct xfs_trans_res tr_ichange; /* inode update trans */ | ||
45 | struct xfs_trans_res tr_growdata; /* fs data section grow trans */ | ||
46 | struct xfs_trans_res tr_addafork; /* add inode attr fork trans */ | ||
47 | struct xfs_trans_res tr_writeid; /* write setuid/setgid file */ | ||
48 | struct xfs_trans_res tr_attrinval; /* attr fork buffer | ||
49 | * invalidation */ | ||
50 | struct xfs_trans_res tr_attrsetm; /* set/create an attribute at | ||
51 | * mount time */ | ||
52 | struct xfs_trans_res tr_attrsetrt; /* set/create an attribute at | ||
53 | * runtime */ | ||
54 | struct xfs_trans_res tr_attrrm; /* remove an attribute */ | ||
55 | struct xfs_trans_res tr_clearagi; /* clear agi unlinked bucket */ | ||
56 | struct xfs_trans_res tr_growrtalloc; /* grow realtime allocations */ | ||
57 | struct xfs_trans_res tr_growrtzero; /* grow realtime zeroing */ | ||
58 | struct xfs_trans_res tr_growrtfree; /* grow realtime freeing */ | ||
59 | struct xfs_trans_res tr_qm_sbchange; /* change quota flags */ | ||
60 | struct xfs_trans_res tr_qm_setqlim; /* adjust quota limits */ | ||
61 | struct xfs_trans_res tr_qm_dqalloc; /* allocate quota on disk */ | ||
62 | struct xfs_trans_res tr_qm_quotaoff; /* turn quota off */ | ||
63 | struct xfs_trans_res tr_qm_equotaoff;/* end of turn quota off */ | ||
64 | struct xfs_trans_res tr_sb; /* modify superblock */ | ||
65 | struct xfs_trans_res tr_fsyncts; /* update timestamps on fsync */ | ||
66 | }; | ||
67 | |||
68 | /* shorthand way of accessing reservation structure */ | ||
69 | #define M_RES(mp) (&(mp)->m_resv) | ||
70 | |||
71 | /* | ||
72 | * Per-extent log reservation for the allocation btree changes | ||
73 | * involved in freeing or allocating an extent. | ||
74 | * 2 trees * (2 blocks/level * max depth - 1) * block size | ||
75 | */ | ||
76 | #define XFS_ALLOCFREE_LOG_RES(mp,nx) \ | ||
77 | ((nx) * (2 * XFS_FSB_TO_B((mp), 2 * XFS_AG_MAXLEVELS(mp) - 1))) | ||
78 | #define XFS_ALLOCFREE_LOG_COUNT(mp,nx) \ | ||
79 | ((nx) * (2 * (2 * XFS_AG_MAXLEVELS(mp) - 1))) | ||
80 | |||
81 | /* | ||
82 | * Per-directory log reservation for any directory change. | ||
83 | * dir blocks: (1 btree block per level + data block + free block) * dblock size | ||
84 | * bmap btree: (levels + 2) * max depth * block size | ||
85 | * v2 directory blocks can be fragmented below the dirblksize down to the fsb | ||
86 | * size, so account for that in the DAENTER macros. | ||
87 | */ | ||
88 | #define XFS_DIROP_LOG_RES(mp) \ | ||
89 | (XFS_FSB_TO_B(mp, XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK)) + \ | ||
90 | (XFS_FSB_TO_B(mp, XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1))) | ||
91 | #define XFS_DIROP_LOG_COUNT(mp) \ | ||
92 | (XFS_DAENTER_BLOCKS(mp, XFS_DATA_FORK) + \ | ||
93 | XFS_DAENTER_BMAPS(mp, XFS_DATA_FORK) + 1) | ||
94 | |||
95 | /* | ||
96 | * Various log count values. | ||
97 | */ | ||
98 | #define XFS_DEFAULT_LOG_COUNT 1 | ||
99 | #define XFS_DEFAULT_PERM_LOG_COUNT 2 | ||
100 | #define XFS_ITRUNCATE_LOG_COUNT 2 | ||
101 | #define XFS_INACTIVE_LOG_COUNT 2 | ||
102 | #define XFS_CREATE_LOG_COUNT 2 | ||
103 | #define XFS_CREATE_TMPFILE_LOG_COUNT 2 | ||
104 | #define XFS_MKDIR_LOG_COUNT 3 | ||
105 | #define XFS_SYMLINK_LOG_COUNT 3 | ||
106 | #define XFS_REMOVE_LOG_COUNT 2 | ||
107 | #define XFS_LINK_LOG_COUNT 2 | ||
108 | #define XFS_RENAME_LOG_COUNT 2 | ||
109 | #define XFS_WRITE_LOG_COUNT 2 | ||
110 | #define XFS_ADDAFORK_LOG_COUNT 2 | ||
111 | #define XFS_ATTRINVAL_LOG_COUNT 1 | ||
112 | #define XFS_ATTRSET_LOG_COUNT 3 | ||
113 | #define XFS_ATTRRM_LOG_COUNT 3 | ||
114 | |||
115 | void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); | ||
116 | |||
117 | #endif /* __XFS_TRANS_RESV_H__ */ | ||
diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h new file mode 100644 index 000000000000..bf9c4579334d --- /dev/null +++ b/fs/xfs/libxfs/xfs_trans_space.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_TRANS_SPACE_H__ | ||
19 | #define __XFS_TRANS_SPACE_H__ | ||
20 | |||
21 | /* | ||
22 | * Components of space reservations. | ||
23 | */ | ||
24 | #define XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) \ | ||
25 | (((mp)->m_alloc_mxr[0]) - ((mp)->m_alloc_mnr[0])) | ||
26 | #define XFS_EXTENTADD_SPACE_RES(mp,w) (XFS_BM_MAXLEVELS(mp,w) - 1) | ||
27 | #define XFS_NEXTENTADD_SPACE_RES(mp,b,w)\ | ||
28 | (((b + XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp) - 1) / \ | ||
29 | XFS_MAX_CONTIG_EXTENTS_PER_BLOCK(mp)) * \ | ||
30 | XFS_EXTENTADD_SPACE_RES(mp,w)) | ||
31 | #define XFS_DAENTER_1B(mp,w) \ | ||
32 | ((w) == XFS_DATA_FORK ? (mp)->m_dir_geo->fsbcount : 1) | ||
33 | #define XFS_DAENTER_DBS(mp,w) \ | ||
34 | (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0)) | ||
35 | #define XFS_DAENTER_BLOCKS(mp,w) \ | ||
36 | (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) | ||
37 | #define XFS_DAENTER_BMAP1B(mp,w) \ | ||
38 | XFS_NEXTENTADD_SPACE_RES(mp, XFS_DAENTER_1B(mp, w), w) | ||
39 | #define XFS_DAENTER_BMAPS(mp,w) \ | ||
40 | (XFS_DAENTER_DBS(mp,w) * XFS_DAENTER_BMAP1B(mp,w)) | ||
41 | #define XFS_DAENTER_SPACE_RES(mp,w) \ | ||
42 | (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) | ||
43 | #define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) | ||
44 | #define XFS_DIRENTER_MAX_SPLIT(mp,nl) 1 | ||
45 | #define XFS_DIRENTER_SPACE_RES(mp,nl) \ | ||
46 | (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ | ||
47 | XFS_DIRENTER_MAX_SPLIT(mp,nl)) | ||
48 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ | ||
49 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) | ||
50 | #define XFS_IALLOC_SPACE_RES(mp) \ | ||
51 | ((mp)->m_ialloc_blks + \ | ||
52 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \ | ||
53 | ((mp)->m_in_maxlevels - 1))) | ||
54 | |||
55 | /* | ||
56 | * Space reservation values for various transactions. | ||
57 | */ | ||
58 | #define XFS_ADDAFORK_SPACE_RES(mp) \ | ||
59 | ((mp)->m_dir_geo->fsbcount + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)) | ||
60 | #define XFS_ATTRRM_SPACE_RES(mp) \ | ||
61 | XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) | ||
62 | /* This macro is not used - see inline code in xfs_attr_set */ | ||
63 | #define XFS_ATTRSET_SPACE_RES(mp, v) \ | ||
64 | (XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) + XFS_B_TO_FSB(mp, v)) | ||
65 | #define XFS_CREATE_SPACE_RES(mp,nl) \ | ||
66 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) | ||
67 | #define XFS_DIOSTRAT_SPACE_RES(mp, v) \ | ||
68 | (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + (v)) | ||
69 | #define XFS_GROWFS_SPACE_RES(mp) \ | ||
70 | (2 * XFS_AG_MAXLEVELS(mp)) | ||
71 | #define XFS_GROWFSRT_SPACE_RES(mp,b) \ | ||
72 | ((b) + XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK)) | ||
73 | #define XFS_LINK_SPACE_RES(mp,nl) \ | ||
74 | XFS_DIRENTER_SPACE_RES(mp,nl) | ||
75 | #define XFS_MKDIR_SPACE_RES(mp,nl) \ | ||
76 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) | ||
77 | #define XFS_QM_DQALLOC_SPACE_RES(mp) \ | ||
78 | (XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK) + \ | ||
79 | XFS_DQUOT_CLUSTER_SIZE_FSB) | ||
80 | #define XFS_QM_QINOCREATE_SPACE_RES(mp) \ | ||
81 | XFS_IALLOC_SPACE_RES(mp) | ||
82 | #define XFS_REMOVE_SPACE_RES(mp) \ | ||
83 | XFS_DIRREMOVE_SPACE_RES(mp) | ||
84 | #define XFS_RENAME_SPACE_RES(mp,nl) \ | ||
85 | (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) | ||
86 | #define XFS_SYMLINK_SPACE_RES(mp,nl,b) \ | ||
87 | (XFS_IALLOC_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl) + (b)) | ||
88 | #define XFS_IFREE_SPACE_RES(mp) \ | ||
89 | (xfs_sb_version_hasfinobt(&mp->m_sb) ? (mp)->m_in_maxlevels : 0) | ||
90 | |||
91 | |||
92 | #endif /* __XFS_TRANS_SPACE_H__ */ | ||