]>
Commit | Line | Data |
---|---|---|
32c5483a DC |
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 | #include "xfs.h" | |
20 | #include "xfs_fs.h" | |
21 | #include "xfs_format.h" | |
22 | #include "xfs_log_format.h" | |
23 | #include "xfs_trans_resv.h" | |
24 | #include "xfs_sb.h" | |
25 | #include "xfs_ag.h" | |
26 | #include "xfs_mount.h" | |
27 | #include "xfs_da_format.h" | |
28 | #include "xfs_inode.h" | |
29 | #include "xfs_dir2.h" | |
30 | ||
9d23fc85 DC |
31 | /* |
32 | * Shortform directory ops | |
33 | */ | |
32c5483a DC |
34 | static int |
35 | xfs_dir2_sf_entsize( | |
36 | struct xfs_dir2_sf_hdr *hdr, | |
37 | int len) | |
38 | { | |
39 | int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ | |
40 | ||
41 | count += len; /* name */ | |
42 | count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) : | |
43 | sizeof(xfs_dir2_ino4_t); /* ino # */ | |
44 | return count; | |
45 | } | |
46 | ||
47 | static int | |
48 | xfs_dir3_sf_entsize( | |
49 | struct xfs_dir2_sf_hdr *hdr, | |
50 | int len) | |
51 | { | |
52 | return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t); | |
53 | } | |
54 | ||
55 | static struct xfs_dir2_sf_entry * | |
56 | xfs_dir2_sf_nextentry( | |
57 | struct xfs_dir2_sf_hdr *hdr, | |
58 | struct xfs_dir2_sf_entry *sfep) | |
59 | { | |
60 | return (struct xfs_dir2_sf_entry *) | |
61 | ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen)); | |
62 | } | |
63 | ||
64 | static struct xfs_dir2_sf_entry * | |
65 | xfs_dir3_sf_nextentry( | |
66 | struct xfs_dir2_sf_hdr *hdr, | |
67 | struct xfs_dir2_sf_entry *sfep) | |
68 | { | |
69 | return (struct xfs_dir2_sf_entry *) | |
70 | ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen)); | |
71 | } | |
72 | ||
73 | ||
4740175e DC |
74 | /* |
75 | * For filetype enabled shortform directories, the file type field is stored at | |
76 | * the end of the name. Because it's only a single byte, endian conversion is | |
77 | * not necessary. For non-filetype enable directories, the type is always | |
78 | * unknown and we never store the value. | |
79 | */ | |
80 | static __uint8_t | |
81 | xfs_dir2_sfe_get_ftype( | |
82 | struct xfs_dir2_sf_entry *sfep) | |
83 | { | |
84 | return XFS_DIR3_FT_UNKNOWN; | |
85 | } | |
86 | ||
87 | static void | |
88 | xfs_dir2_sfe_put_ftype( | |
89 | struct xfs_dir2_sf_entry *sfep, | |
90 | __uint8_t ftype) | |
91 | { | |
92 | ASSERT(ftype < XFS_DIR3_FT_MAX); | |
93 | } | |
94 | ||
95 | static __uint8_t | |
96 | xfs_dir3_sfe_get_ftype( | |
97 | struct xfs_dir2_sf_entry *sfep) | |
98 | { | |
99 | __uint8_t ftype; | |
100 | ||
101 | ftype = sfep->name[sfep->namelen]; | |
102 | if (ftype >= XFS_DIR3_FT_MAX) | |
103 | return XFS_DIR3_FT_UNKNOWN; | |
104 | return ftype; | |
105 | } | |
106 | ||
107 | static void | |
108 | xfs_dir3_sfe_put_ftype( | |
109 | struct xfs_dir2_sf_entry *sfep, | |
110 | __uint8_t ftype) | |
111 | { | |
112 | ASSERT(ftype < XFS_DIR3_FT_MAX); | |
113 | ||
114 | sfep->name[sfep->namelen] = ftype; | |
115 | } | |
116 | ||
117 | /* | |
118 | * Inode numbers in short-form directories can come in two versions, | |
119 | * either 4 bytes or 8 bytes wide. These helpers deal with the | |
120 | * two forms transparently by looking at the headers i8count field. | |
121 | * | |
122 | * For 64-bit inode number the most significant byte must be zero. | |
123 | */ | |
124 | static xfs_ino_t | |
125 | xfs_dir2_sf_get_ino( | |
126 | struct xfs_dir2_sf_hdr *hdr, | |
127 | xfs_dir2_inou_t *from) | |
128 | { | |
129 | if (hdr->i8count) | |
130 | return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL; | |
131 | else | |
132 | return get_unaligned_be32(&from->i4.i); | |
133 | } | |
134 | ||
135 | static void | |
136 | xfs_dir2_sf_put_ino( | |
137 | struct xfs_dir2_sf_hdr *hdr, | |
138 | xfs_dir2_inou_t *to, | |
139 | xfs_ino_t ino) | |
140 | { | |
141 | ASSERT((ino & 0xff00000000000000ULL) == 0); | |
142 | ||
143 | if (hdr->i8count) | |
144 | put_unaligned_be64(ino, &to->i8.i); | |
145 | else | |
146 | put_unaligned_be32(ino, &to->i4.i); | |
147 | } | |
148 | ||
149 | static xfs_ino_t | |
150 | xfs_dir2_sf_get_parent_ino( | |
151 | struct xfs_dir2_sf_hdr *hdr) | |
152 | { | |
153 | return xfs_dir2_sf_get_ino(hdr, &hdr->parent); | |
154 | } | |
155 | ||
156 | static void | |
157 | xfs_dir2_sf_put_parent_ino( | |
158 | struct xfs_dir2_sf_hdr *hdr, | |
159 | xfs_ino_t ino) | |
160 | { | |
161 | xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino); | |
162 | } | |
163 | ||
164 | /* | |
165 | * In short-form directory entries the inode numbers are stored at variable | |
166 | * offset behind the entry name. If the entry stores a filetype value, then it | |
167 | * sits between the name and the inode number. Hence the inode numbers may only | |
168 | * be accessed through the helpers below. | |
169 | */ | |
170 | static xfs_ino_t | |
171 | xfs_dir2_sfe_get_ino( | |
172 | struct xfs_dir2_sf_hdr *hdr, | |
173 | struct xfs_dir2_sf_entry *sfep) | |
174 | { | |
175 | return xfs_dir2_sf_get_ino(hdr, | |
176 | (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]); | |
177 | } | |
178 | ||
179 | static void | |
180 | xfs_dir2_sfe_put_ino( | |
181 | struct xfs_dir2_sf_hdr *hdr, | |
182 | struct xfs_dir2_sf_entry *sfep, | |
183 | xfs_ino_t ino) | |
184 | { | |
185 | xfs_dir2_sf_put_ino(hdr, | |
186 | (xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino); | |
187 | } | |
188 | ||
189 | static xfs_ino_t | |
190 | xfs_dir3_sfe_get_ino( | |
191 | struct xfs_dir2_sf_hdr *hdr, | |
192 | struct xfs_dir2_sf_entry *sfep) | |
193 | { | |
194 | return xfs_dir2_sf_get_ino(hdr, | |
195 | (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]); | |
196 | } | |
197 | ||
198 | static void | |
199 | xfs_dir3_sfe_put_ino( | |
200 | struct xfs_dir2_sf_hdr *hdr, | |
201 | struct xfs_dir2_sf_entry *sfep, | |
202 | xfs_ino_t ino) | |
203 | { | |
204 | xfs_dir2_sf_put_ino(hdr, | |
205 | (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino); | |
206 | } | |
207 | ||
9d23fc85 DC |
208 | |
209 | /* | |
210 | * Directory data block operations | |
211 | */ | |
212 | static int | |
213 | __xfs_dir3_data_entsize( | |
214 | bool ftype, | |
215 | int n) | |
216 | { | |
217 | int size = offsetof(struct xfs_dir2_data_entry, name[0]); | |
218 | ||
219 | size += n; | |
220 | size += sizeof(xfs_dir2_data_off_t); | |
221 | if (ftype) | |
222 | size += sizeof(__uint8_t); | |
223 | return roundup(size, XFS_DIR2_DATA_ALIGN); | |
224 | } | |
225 | ||
226 | static int | |
227 | xfs_dir2_data_entsize( | |
228 | int n) | |
229 | { | |
230 | return __xfs_dir3_data_entsize(false, n); | |
231 | } | |
232 | static int | |
233 | xfs_dir3_data_entsize( | |
234 | int n) | |
235 | { | |
236 | return __xfs_dir3_data_entsize(true, n); | |
237 | } | |
238 | ||
239 | static __uint8_t | |
240 | xfs_dir2_data_get_ftype( | |
241 | struct xfs_dir2_data_entry *dep) | |
242 | { | |
243 | return XFS_DIR3_FT_UNKNOWN; | |
244 | } | |
245 | ||
246 | static void | |
247 | xfs_dir2_data_put_ftype( | |
248 | struct xfs_dir2_data_entry *dep, | |
249 | __uint8_t ftype) | |
250 | { | |
251 | ASSERT(ftype < XFS_DIR3_FT_MAX); | |
252 | } | |
253 | ||
254 | static __uint8_t | |
255 | xfs_dir3_data_get_ftype( | |
256 | struct xfs_dir2_data_entry *dep) | |
257 | { | |
258 | __uint8_t ftype = dep->name[dep->namelen]; | |
259 | ||
260 | ASSERT(ftype < XFS_DIR3_FT_MAX); | |
261 | if (ftype >= XFS_DIR3_FT_MAX) | |
262 | return XFS_DIR3_FT_UNKNOWN; | |
263 | return ftype; | |
264 | } | |
265 | ||
266 | static void | |
267 | xfs_dir3_data_put_ftype( | |
268 | struct xfs_dir2_data_entry *dep, | |
269 | __uint8_t type) | |
270 | { | |
271 | ASSERT(type < XFS_DIR3_FT_MAX); | |
272 | ASSERT(dep->namelen != 0); | |
273 | ||
274 | dep->name[dep->namelen] = type; | |
275 | } | |
276 | ||
277 | /* | |
278 | * Pointer to an entry's tag word. | |
279 | */ | |
280 | static __be16 * | |
281 | xfs_dir2_data_entry_tag_p( | |
282 | struct xfs_dir2_data_entry *dep) | |
283 | { | |
284 | return (__be16 *)((char *)dep + | |
285 | xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16)); | |
286 | } | |
287 | ||
288 | static __be16 * | |
289 | xfs_dir3_data_entry_tag_p( | |
290 | struct xfs_dir2_data_entry *dep) | |
291 | { | |
292 | return (__be16 *)((char *)dep + | |
293 | xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16)); | |
294 | } | |
295 | ||
296 | /* | |
297 | * Offsets of . and .. in data space (always block 0) | |
298 | */ | |
299 | static xfs_dir2_data_aoff_t | |
300 | xfs_dir2_data_dot_offset(void) | |
301 | { | |
302 | return sizeof(struct xfs_dir2_data_hdr); | |
303 | } | |
304 | ||
305 | static xfs_dir2_data_aoff_t | |
306 | xfs_dir2_data_dotdot_offset(void) | |
307 | { | |
308 | return xfs_dir2_data_dot_offset() + xfs_dir2_data_entsize(1); | |
309 | } | |
310 | ||
311 | static xfs_dir2_data_aoff_t | |
312 | xfs_dir2_data_first_offset(void) | |
313 | { | |
314 | return xfs_dir2_data_dotdot_offset() + xfs_dir2_data_entsize(2); | |
315 | } | |
316 | ||
317 | static xfs_dir2_data_aoff_t | |
318 | xfs_dir3_data_dot_offset(void) | |
319 | { | |
320 | return sizeof(struct xfs_dir3_data_hdr); | |
321 | } | |
322 | ||
323 | static xfs_dir2_data_aoff_t | |
324 | xfs_dir3_data_dotdot_offset(void) | |
325 | { | |
326 | return xfs_dir3_data_dot_offset() + xfs_dir3_data_entsize(1); | |
327 | } | |
328 | ||
329 | static xfs_dir2_data_aoff_t | |
330 | xfs_dir3_data_first_offset(void) | |
331 | { | |
332 | return xfs_dir3_data_dotdot_offset() + xfs_dir3_data_entsize(2); | |
333 | } | |
334 | ||
335 | /* | |
336 | * location of . and .. in data space (always block 0) | |
337 | */ | |
338 | static struct xfs_dir2_data_entry * | |
339 | xfs_dir2_data_dot_entry_p( | |
340 | struct xfs_dir2_data_hdr *hdr) | |
341 | { | |
342 | return (struct xfs_dir2_data_entry *) | |
343 | ((char *)hdr + xfs_dir2_data_dot_offset()); | |
344 | } | |
345 | ||
346 | static struct xfs_dir2_data_entry * | |
347 | xfs_dir2_data_dotdot_entry_p( | |
348 | struct xfs_dir2_data_hdr *hdr) | |
349 | { | |
350 | return (struct xfs_dir2_data_entry *) | |
351 | ((char *)hdr + xfs_dir2_data_dotdot_offset()); | |
352 | } | |
353 | ||
354 | static struct xfs_dir2_data_entry * | |
355 | xfs_dir2_data_first_entry_p( | |
356 | struct xfs_dir2_data_hdr *hdr) | |
357 | { | |
358 | return (struct xfs_dir2_data_entry *) | |
359 | ((char *)hdr + xfs_dir2_data_first_offset()); | |
360 | } | |
361 | ||
362 | static struct xfs_dir2_data_entry * | |
363 | xfs_dir3_data_dot_entry_p( | |
364 | struct xfs_dir2_data_hdr *hdr) | |
365 | { | |
366 | return (struct xfs_dir2_data_entry *) | |
367 | ((char *)hdr + xfs_dir3_data_dot_offset()); | |
368 | } | |
369 | ||
370 | static struct xfs_dir2_data_entry * | |
371 | xfs_dir3_data_dotdot_entry_p( | |
372 | struct xfs_dir2_data_hdr *hdr) | |
373 | { | |
374 | return (struct xfs_dir2_data_entry *) | |
375 | ((char *)hdr + xfs_dir3_data_dotdot_offset()); | |
376 | } | |
377 | ||
378 | static struct xfs_dir2_data_entry * | |
379 | xfs_dir3_data_first_entry_p( | |
380 | struct xfs_dir2_data_hdr *hdr) | |
381 | { | |
382 | return (struct xfs_dir2_data_entry *) | |
383 | ((char *)hdr + xfs_dir3_data_first_offset()); | |
384 | } | |
385 | ||
2ca98774 DC |
386 | static struct xfs_dir2_data_free * |
387 | xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) | |
388 | { | |
389 | return hdr->bestfree; | |
390 | } | |
391 | ||
392 | static struct xfs_dir2_data_free * | |
393 | xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr) | |
394 | { | |
395 | return ((struct xfs_dir3_data_hdr *)hdr)->best_free; | |
396 | } | |
397 | ||
398 | static size_t | |
399 | xfs_dir2_data_entry_offset(void) | |
400 | { | |
401 | return sizeof(struct xfs_dir2_data_hdr); | |
402 | } | |
403 | ||
404 | static struct xfs_dir2_data_entry * | |
405 | xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr) | |
406 | { | |
407 | return (struct xfs_dir2_data_entry *) | |
408 | ((char *)hdr + xfs_dir2_data_entry_offset()); | |
409 | } | |
410 | ||
411 | static struct xfs_dir2_data_unused * | |
412 | xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr) | |
413 | { | |
414 | return (struct xfs_dir2_data_unused *) | |
415 | ((char *)hdr + xfs_dir2_data_entry_offset()); | |
416 | } | |
417 | ||
418 | static size_t | |
419 | xfs_dir3_data_entry_offset(void) | |
420 | { | |
421 | return sizeof(struct xfs_dir3_data_hdr); | |
422 | } | |
423 | ||
424 | static struct xfs_dir2_data_entry * | |
425 | xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr) | |
426 | { | |
427 | return (struct xfs_dir2_data_entry *) | |
428 | ((char *)hdr + xfs_dir3_data_entry_offset()); | |
429 | } | |
430 | ||
431 | static struct xfs_dir2_data_unused * | |
432 | xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) | |
433 | { | |
434 | return (struct xfs_dir2_data_unused *) | |
435 | ((char *)hdr + xfs_dir3_data_entry_offset()); | |
436 | } | |
437 | ||
4141956a DC |
438 | |
439 | /* | |
440 | * Directory Leaf block operations | |
441 | */ | |
442 | static int | |
443 | xfs_dir2_leaf_hdr_size(void) | |
444 | { | |
445 | return sizeof(struct xfs_dir2_leaf_hdr); | |
446 | } | |
447 | ||
448 | static int | |
449 | xfs_dir2_max_leaf_ents(struct xfs_mount *mp) | |
450 | { | |
451 | return (mp->m_dirblksize - xfs_dir2_leaf_hdr_size()) / | |
452 | (uint)sizeof(struct xfs_dir2_leaf_entry); | |
453 | } | |
454 | ||
455 | static struct xfs_dir2_leaf_entry * | |
456 | xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp) | |
457 | { | |
458 | return lp->__ents; | |
459 | } | |
460 | ||
461 | static int | |
462 | xfs_dir3_leaf_hdr_size(void) | |
463 | { | |
464 | return sizeof(struct xfs_dir3_leaf_hdr); | |
465 | } | |
466 | ||
467 | static inline int | |
468 | xfs_dir3_max_leaf_ents(struct xfs_mount *mp) | |
469 | { | |
470 | return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size()) / | |
471 | (uint)sizeof(struct xfs_dir2_leaf_entry); | |
472 | } | |
473 | ||
474 | static inline struct xfs_dir2_leaf_entry * | |
475 | xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) | |
476 | { | |
477 | return ((struct xfs_dir3_leaf *)lp)->__ents; | |
478 | } | |
479 | ||
32c5483a DC |
480 | const struct xfs_dir_ops xfs_dir2_ops = { |
481 | .sf_entsize = xfs_dir2_sf_entsize, | |
482 | .sf_nextentry = xfs_dir2_sf_nextentry, | |
4740175e DC |
483 | .sf_get_ftype = xfs_dir2_sfe_get_ftype, |
484 | .sf_put_ftype = xfs_dir2_sfe_put_ftype, | |
485 | .sf_get_ino = xfs_dir2_sfe_get_ino, | |
486 | .sf_put_ino = xfs_dir2_sfe_put_ino, | |
487 | .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, | |
488 | .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, | |
9d23fc85 DC |
489 | |
490 | .data_entsize = xfs_dir2_data_entsize, | |
491 | .data_get_ftype = xfs_dir2_data_get_ftype, | |
492 | .data_put_ftype = xfs_dir2_data_put_ftype, | |
493 | .data_entry_tag_p = xfs_dir2_data_entry_tag_p, | |
2ca98774 | 494 | .data_bestfree_p = xfs_dir2_data_bestfree_p, |
9d23fc85 DC |
495 | |
496 | .data_dot_offset = xfs_dir2_data_dot_offset, | |
497 | .data_dotdot_offset = xfs_dir2_data_dotdot_offset, | |
498 | .data_first_offset = xfs_dir2_data_first_offset, | |
2ca98774 DC |
499 | .data_entry_offset = xfs_dir2_data_entry_offset, |
500 | ||
9d23fc85 DC |
501 | .data_dot_entry_p = xfs_dir2_data_dot_entry_p, |
502 | .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, | |
503 | .data_first_entry_p = xfs_dir2_data_first_entry_p, | |
2ca98774 DC |
504 | .data_entry_p = xfs_dir2_data_entry_p, |
505 | .data_unused_p = xfs_dir2_data_unused_p, | |
506 | ||
4141956a DC |
507 | .leaf_hdr_size = xfs_dir2_leaf_hdr_size, |
508 | .leaf_max_ents = xfs_dir2_max_leaf_ents, | |
509 | .leaf_ents_p = xfs_dir2_leaf_ents_p, | |
510 | ||
32c5483a DC |
511 | }; |
512 | ||
513 | const struct xfs_dir_ops xfs_dir2_ftype_ops = { | |
514 | .sf_entsize = xfs_dir3_sf_entsize, | |
515 | .sf_nextentry = xfs_dir3_sf_nextentry, | |
4740175e DC |
516 | .sf_get_ftype = xfs_dir3_sfe_get_ftype, |
517 | .sf_put_ftype = xfs_dir3_sfe_put_ftype, | |
518 | .sf_get_ino = xfs_dir3_sfe_get_ino, | |
519 | .sf_put_ino = xfs_dir3_sfe_put_ino, | |
520 | .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, | |
521 | .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, | |
9d23fc85 DC |
522 | |
523 | .data_entsize = xfs_dir3_data_entsize, | |
524 | .data_get_ftype = xfs_dir3_data_get_ftype, | |
525 | .data_put_ftype = xfs_dir3_data_put_ftype, | |
526 | .data_entry_tag_p = xfs_dir3_data_entry_tag_p, | |
2ca98774 | 527 | .data_bestfree_p = xfs_dir2_data_bestfree_p, |
9d23fc85 DC |
528 | |
529 | .data_dot_offset = xfs_dir2_data_dot_offset, | |
530 | .data_dotdot_offset = xfs_dir2_data_dotdot_offset, | |
531 | .data_first_offset = xfs_dir2_data_first_offset, | |
2ca98774 DC |
532 | .data_entry_offset = xfs_dir2_data_entry_offset, |
533 | ||
9d23fc85 DC |
534 | .data_dot_entry_p = xfs_dir2_data_dot_entry_p, |
535 | .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p, | |
536 | .data_first_entry_p = xfs_dir2_data_first_entry_p, | |
2ca98774 DC |
537 | .data_entry_p = xfs_dir2_data_entry_p, |
538 | .data_unused_p = xfs_dir2_data_unused_p, | |
4141956a DC |
539 | |
540 | .leaf_hdr_size = xfs_dir2_leaf_hdr_size, | |
541 | .leaf_max_ents = xfs_dir2_max_leaf_ents, | |
542 | .leaf_ents_p = xfs_dir2_leaf_ents_p, | |
32c5483a DC |
543 | }; |
544 | ||
545 | const struct xfs_dir_ops xfs_dir3_ops = { | |
546 | .sf_entsize = xfs_dir3_sf_entsize, | |
547 | .sf_nextentry = xfs_dir3_sf_nextentry, | |
4740175e DC |
548 | .sf_get_ftype = xfs_dir3_sfe_get_ftype, |
549 | .sf_put_ftype = xfs_dir3_sfe_put_ftype, | |
550 | .sf_get_ino = xfs_dir3_sfe_get_ino, | |
551 | .sf_put_ino = xfs_dir3_sfe_put_ino, | |
552 | .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino, | |
553 | .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino, | |
9d23fc85 DC |
554 | |
555 | .data_entsize = xfs_dir3_data_entsize, | |
556 | .data_get_ftype = xfs_dir3_data_get_ftype, | |
557 | .data_put_ftype = xfs_dir3_data_put_ftype, | |
558 | .data_entry_tag_p = xfs_dir3_data_entry_tag_p, | |
2ca98774 | 559 | .data_bestfree_p = xfs_dir3_data_bestfree_p, |
9d23fc85 DC |
560 | |
561 | .data_dot_offset = xfs_dir3_data_dot_offset, | |
562 | .data_dotdot_offset = xfs_dir3_data_dotdot_offset, | |
563 | .data_first_offset = xfs_dir3_data_first_offset, | |
2ca98774 DC |
564 | .data_entry_offset = xfs_dir3_data_entry_offset, |
565 | ||
9d23fc85 DC |
566 | .data_dot_entry_p = xfs_dir3_data_dot_entry_p, |
567 | .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p, | |
568 | .data_first_entry_p = xfs_dir3_data_first_entry_p, | |
2ca98774 DC |
569 | .data_entry_p = xfs_dir3_data_entry_p, |
570 | .data_unused_p = xfs_dir3_data_unused_p, | |
4141956a DC |
571 | |
572 | .leaf_hdr_size = xfs_dir3_leaf_hdr_size, | |
573 | .leaf_max_ents = xfs_dir3_max_leaf_ents, | |
574 | .leaf_ents_p = xfs_dir3_leaf_ents_p, | |
32c5483a | 575 | }; |
4141956a DC |
576 | |
577 | /* | |
578 | * Return the ops structure according to the current config. If we are passed | |
579 | * an inode, then that overrides the default config we use which is based on | |
580 | * feature bits. | |
581 | */ | |
582 | const struct xfs_dir_ops * | |
583 | xfs_dir_get_ops( | |
584 | struct xfs_mount *mp, | |
585 | struct xfs_inode *dp) | |
586 | { | |
587 | if (dp) | |
588 | return dp->d_ops; | |
589 | if (mp->m_dir_inode_ops) | |
590 | return mp->m_dir_inode_ops; | |
591 | if (xfs_sb_version_hascrc(&mp->m_sb)) | |
592 | return &xfs_dir3_ops; | |
593 | if (xfs_sb_version_hasftype(&mp->m_sb)) | |
594 | return &xfs_dir2_ftype_ops; | |
595 | return &xfs_dir2_ops; | |
596 | } |