]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_da_format.c
libxfs: refactor manage_zones()
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_da_format.c
CommitLineData
37b3b4d6 1// SPDX-License-Identifier: GPL-2.0
ff105f75
DC
2/*
3 * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
4 * Copyright (c) 2013 Red Hat, Inc.
5 * All Rights Reserved.
ff105f75 6 */
9c799827 7#include "libxfs_priv.h"
b626fb59
DC
8#include "xfs_fs.h"
9#include "xfs_shared.h"
10#include "xfs_format.h"
11#include "xfs_log_format.h"
12#include "xfs_trans_resv.h"
13#include "xfs_mount.h"
14#include "xfs_da_format.h"
15#include "xfs_da_btree.h"
16#include "xfs_inode.h"
17#include "xfs_dir2.h"
18#include "xfs_dir2_priv.h"
ff105f75
DC
19
20/*
21 * Shortform directory ops
22 */
23static int
24xfs_dir2_sf_entsize(
25 struct xfs_dir2_sf_hdr *hdr,
26 int len)
27{
28 int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
29
30 count += len; /* name */
d8bf9c63 31 count += hdr->i8count ? XFS_INO64_SIZE : XFS_INO32_SIZE; /* ino # */
ff105f75
DC
32 return count;
33}
34
35static int
36xfs_dir3_sf_entsize(
37 struct xfs_dir2_sf_hdr *hdr,
38 int len)
39{
4a492e72 40 return xfs_dir2_sf_entsize(hdr, len) + sizeof(uint8_t);
ff105f75
DC
41}
42
43static struct xfs_dir2_sf_entry *
44xfs_dir2_sf_nextentry(
45 struct xfs_dir2_sf_hdr *hdr,
46 struct xfs_dir2_sf_entry *sfep)
47{
48 return (struct xfs_dir2_sf_entry *)
49 ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen));
50}
51
52static struct xfs_dir2_sf_entry *
53xfs_dir3_sf_nextentry(
54 struct xfs_dir2_sf_hdr *hdr,
55 struct xfs_dir2_sf_entry *sfep)
56{
57 return (struct xfs_dir2_sf_entry *)
58 ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen));
59}
60
61
62/*
63 * For filetype enabled shortform directories, the file type field is stored at
64 * the end of the name. Because it's only a single byte, endian conversion is
65 * not necessary. For non-filetype enable directories, the type is always
66 * unknown and we never store the value.
67 */
4a492e72 68static uint8_t
ff105f75
DC
69xfs_dir2_sfe_get_ftype(
70 struct xfs_dir2_sf_entry *sfep)
71{
72 return XFS_DIR3_FT_UNKNOWN;
73}
74
75static void
76xfs_dir2_sfe_put_ftype(
77 struct xfs_dir2_sf_entry *sfep,
4a492e72 78 uint8_t ftype)
ff105f75
DC
79{
80 ASSERT(ftype < XFS_DIR3_FT_MAX);
81}
82
4a492e72 83static uint8_t
ff105f75
DC
84xfs_dir3_sfe_get_ftype(
85 struct xfs_dir2_sf_entry *sfep)
86{
4a492e72 87 uint8_t ftype;
ff105f75
DC
88
89 ftype = sfep->name[sfep->namelen];
90 if (ftype >= XFS_DIR3_FT_MAX)
91 return XFS_DIR3_FT_UNKNOWN;
92 return ftype;
93}
94
95static void
96xfs_dir3_sfe_put_ftype(
97 struct xfs_dir2_sf_entry *sfep,
4a492e72 98 uint8_t ftype)
ff105f75
DC
99{
100 ASSERT(ftype < XFS_DIR3_FT_MAX);
101
102 sfep->name[sfep->namelen] = ftype;
103}
104
105/*
106 * Inode numbers in short-form directories can come in two versions,
107 * either 4 bytes or 8 bytes wide. These helpers deal with the
108 * two forms transparently by looking at the headers i8count field.
109 *
110 * For 64-bit inode number the most significant byte must be zero.
111 */
112static xfs_ino_t
113xfs_dir2_sf_get_ino(
114 struct xfs_dir2_sf_hdr *hdr,
4a492e72 115 uint8_t *from)
ff105f75
DC
116{
117 if (hdr->i8count)
d8bf9c63 118 return get_unaligned_be64(from) & 0x00ffffffffffffffULL;
ff105f75 119 else
d8bf9c63 120 return get_unaligned_be32(from);
ff105f75
DC
121}
122
123static void
124xfs_dir2_sf_put_ino(
125 struct xfs_dir2_sf_hdr *hdr,
4a492e72 126 uint8_t *to,
ff105f75
DC
127 xfs_ino_t ino)
128{
129 ASSERT((ino & 0xff00000000000000ULL) == 0);
130
131 if (hdr->i8count)
d8bf9c63 132 put_unaligned_be64(ino, to);
ff105f75 133 else
d8bf9c63 134 put_unaligned_be32(ino, to);
ff105f75
DC
135}
136
137static xfs_ino_t
138xfs_dir2_sf_get_parent_ino(
139 struct xfs_dir2_sf_hdr *hdr)
140{
d8bf9c63 141 return xfs_dir2_sf_get_ino(hdr, hdr->parent);
ff105f75
DC
142}
143
144static void
145xfs_dir2_sf_put_parent_ino(
146 struct xfs_dir2_sf_hdr *hdr,
147 xfs_ino_t ino)
148{
d8bf9c63 149 xfs_dir2_sf_put_ino(hdr, hdr->parent, ino);
ff105f75
DC
150}
151
152/*
153 * In short-form directory entries the inode numbers are stored at variable
154 * offset behind the entry name. If the entry stores a filetype value, then it
155 * sits between the name and the inode number. Hence the inode numbers may only
156 * be accessed through the helpers below.
157 */
158static xfs_ino_t
159xfs_dir2_sfe_get_ino(
160 struct xfs_dir2_sf_hdr *hdr,
161 struct xfs_dir2_sf_entry *sfep)
162{
d8bf9c63 163 return xfs_dir2_sf_get_ino(hdr, &sfep->name[sfep->namelen]);
ff105f75
DC
164}
165
166static void
167xfs_dir2_sfe_put_ino(
168 struct xfs_dir2_sf_hdr *hdr,
169 struct xfs_dir2_sf_entry *sfep,
170 xfs_ino_t ino)
171{
d8bf9c63 172 xfs_dir2_sf_put_ino(hdr, &sfep->name[sfep->namelen], ino);
ff105f75
DC
173}
174
175static xfs_ino_t
176xfs_dir3_sfe_get_ino(
177 struct xfs_dir2_sf_hdr *hdr,
178 struct xfs_dir2_sf_entry *sfep)
179{
d8bf9c63 180 return xfs_dir2_sf_get_ino(hdr, &sfep->name[sfep->namelen + 1]);
ff105f75
DC
181}
182
183static void
184xfs_dir3_sfe_put_ino(
185 struct xfs_dir2_sf_hdr *hdr,
186 struct xfs_dir2_sf_entry *sfep,
187 xfs_ino_t ino)
188{
d8bf9c63 189 xfs_dir2_sf_put_ino(hdr, &sfep->name[sfep->namelen + 1], ino);
ff105f75
DC
190}
191
192
193/*
194 * Directory data block operations
195 */
196
197/*
198 * For special situations, the dirent size ends up fixed because we always know
199 * what the size of the entry is. That's true for the "." and "..", and
200 * therefore we know that they are a fixed size and hence their offsets are
201 * constant, as is the first entry.
202 *
203 * Hence, this calculation is written as a macro to be able to be calculated at
204 * compile time and so certain offsets can be calculated directly in the
205 * structure initaliser via the macro. There are two macros - one for dirents
206 * with ftype and without so there are no unresolvable conditionals in the
207 * calculations. We also use round_up() as XFS_DIR2_DATA_ALIGN is always a power
208 * of 2 and the compiler doesn't reject it (unlike roundup()).
209 */
210#define XFS_DIR2_DATA_ENTSIZE(n) \
211 round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \
212 sizeof(xfs_dir2_data_off_t)), XFS_DIR2_DATA_ALIGN)
213
214#define XFS_DIR3_DATA_ENTSIZE(n) \
215 round_up((offsetof(struct xfs_dir2_data_entry, name[0]) + (n) + \
4a492e72 216 sizeof(xfs_dir2_data_off_t) + sizeof(uint8_t)), \
ff105f75
DC
217 XFS_DIR2_DATA_ALIGN)
218
219static int
220xfs_dir2_data_entsize(
221 int n)
222{
223 return XFS_DIR2_DATA_ENTSIZE(n);
224}
225
226static int
227xfs_dir3_data_entsize(
228 int n)
229{
230 return XFS_DIR3_DATA_ENTSIZE(n);
231}
232
4a492e72 233static uint8_t
ff105f75
DC
234xfs_dir2_data_get_ftype(
235 struct xfs_dir2_data_entry *dep)
236{
237 return XFS_DIR3_FT_UNKNOWN;
238}
239
240static void
241xfs_dir2_data_put_ftype(
242 struct xfs_dir2_data_entry *dep,
4a492e72 243 uint8_t ftype)
ff105f75
DC
244{
245 ASSERT(ftype < XFS_DIR3_FT_MAX);
246}
247
4a492e72 248static uint8_t
ff105f75
DC
249xfs_dir3_data_get_ftype(
250 struct xfs_dir2_data_entry *dep)
251{
4a492e72 252 uint8_t ftype = dep->name[dep->namelen];
ff105f75 253
ff105f75
DC
254 if (ftype >= XFS_DIR3_FT_MAX)
255 return XFS_DIR3_FT_UNKNOWN;
256 return ftype;
257}
258
259static void
260xfs_dir3_data_put_ftype(
261 struct xfs_dir2_data_entry *dep,
4a492e72 262 uint8_t type)
ff105f75
DC
263{
264 ASSERT(type < XFS_DIR3_FT_MAX);
265 ASSERT(dep->namelen != 0);
266
267 dep->name[dep->namelen] = type;
268}
269
270/*
271 * Pointer to an entry's tag word.
272 */
273static __be16 *
274xfs_dir2_data_entry_tag_p(
275 struct xfs_dir2_data_entry *dep)
276{
277 return (__be16 *)((char *)dep +
278 xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
279}
280
281static __be16 *
282xfs_dir3_data_entry_tag_p(
283 struct xfs_dir2_data_entry *dep)
284{
285 return (__be16 *)((char *)dep +
286 xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16));
287}
288
289/*
290 * location of . and .. in data space (always block 0)
291 */
292static struct xfs_dir2_data_entry *
293xfs_dir2_data_dot_entry_p(
294 struct xfs_dir2_data_hdr *hdr)
295{
296 return (struct xfs_dir2_data_entry *)
297 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
298}
299
300static struct xfs_dir2_data_entry *
301xfs_dir2_data_dotdot_entry_p(
302 struct xfs_dir2_data_hdr *hdr)
303{
304 return (struct xfs_dir2_data_entry *)
305 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
306 XFS_DIR2_DATA_ENTSIZE(1));
307}
308
309static struct xfs_dir2_data_entry *
310xfs_dir2_data_first_entry_p(
311 struct xfs_dir2_data_hdr *hdr)
312{
313 return (struct xfs_dir2_data_entry *)
314 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
315 XFS_DIR2_DATA_ENTSIZE(1) +
316 XFS_DIR2_DATA_ENTSIZE(2));
317}
318
319static struct xfs_dir2_data_entry *
320xfs_dir2_ftype_data_dotdot_entry_p(
321 struct xfs_dir2_data_hdr *hdr)
322{
323 return (struct xfs_dir2_data_entry *)
324 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
325 XFS_DIR3_DATA_ENTSIZE(1));
326}
327
328static struct xfs_dir2_data_entry *
329xfs_dir2_ftype_data_first_entry_p(
330 struct xfs_dir2_data_hdr *hdr)
331{
332 return (struct xfs_dir2_data_entry *)
333 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr) +
334 XFS_DIR3_DATA_ENTSIZE(1) +
335 XFS_DIR3_DATA_ENTSIZE(2));
336}
337
338static struct xfs_dir2_data_entry *
339xfs_dir3_data_dot_entry_p(
340 struct xfs_dir2_data_hdr *hdr)
341{
342 return (struct xfs_dir2_data_entry *)
343 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
344}
345
346static struct xfs_dir2_data_entry *
347xfs_dir3_data_dotdot_entry_p(
348 struct xfs_dir2_data_hdr *hdr)
349{
350 return (struct xfs_dir2_data_entry *)
351 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) +
352 XFS_DIR3_DATA_ENTSIZE(1));
353}
354
355static struct xfs_dir2_data_entry *
356xfs_dir3_data_first_entry_p(
357 struct xfs_dir2_data_hdr *hdr)
358{
359 return (struct xfs_dir2_data_entry *)
360 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr) +
361 XFS_DIR3_DATA_ENTSIZE(1) +
362 XFS_DIR3_DATA_ENTSIZE(2));
363}
364
365static struct xfs_dir2_data_free *
366xfs_dir2_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
367{
368 return hdr->bestfree;
369}
370
371static struct xfs_dir2_data_free *
372xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
373{
374 return ((struct xfs_dir3_data_hdr *)hdr)->best_free;
375}
376
377static struct xfs_dir2_data_entry *
378xfs_dir2_data_entry_p(struct xfs_dir2_data_hdr *hdr)
379{
380 return (struct xfs_dir2_data_entry *)
381 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
382}
383
384static struct xfs_dir2_data_unused *
385xfs_dir2_data_unused_p(struct xfs_dir2_data_hdr *hdr)
386{
387 return (struct xfs_dir2_data_unused *)
388 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
389}
390
391static struct xfs_dir2_data_entry *
392xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
393{
394 return (struct xfs_dir2_data_entry *)
395 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
396}
397
398static struct xfs_dir2_data_unused *
399xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
400{
401 return (struct xfs_dir2_data_unused *)
402 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
403}
404
405
406/*
407 * Directory Leaf block operations
408 */
409static int
410xfs_dir2_max_leaf_ents(struct xfs_da_geometry *geo)
411{
412 return (geo->blksize - sizeof(struct xfs_dir2_leaf_hdr)) /
413 (uint)sizeof(struct xfs_dir2_leaf_entry);
414}
415
416static struct xfs_dir2_leaf_entry *
417xfs_dir2_leaf_ents_p(struct xfs_dir2_leaf *lp)
418{
419 return lp->__ents;
420}
421
422static int
423xfs_dir3_max_leaf_ents(struct xfs_da_geometry *geo)
424{
425 return (geo->blksize - sizeof(struct xfs_dir3_leaf_hdr)) /
426 (uint)sizeof(struct xfs_dir2_leaf_entry);
427}
428
429static struct xfs_dir2_leaf_entry *
430xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp)
431{
432 return ((struct xfs_dir3_leaf *)lp)->__ents;
433}
434
435static void
436xfs_dir2_leaf_hdr_from_disk(
437 struct xfs_dir3_icleaf_hdr *to,
438 struct xfs_dir2_leaf *from)
439{
440 to->forw = be32_to_cpu(from->hdr.info.forw);
441 to->back = be32_to_cpu(from->hdr.info.back);
442 to->magic = be16_to_cpu(from->hdr.info.magic);
443 to->count = be16_to_cpu(from->hdr.count);
444 to->stale = be16_to_cpu(from->hdr.stale);
445
446 ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC ||
447 to->magic == XFS_DIR2_LEAFN_MAGIC);
448}
449
450static void
451xfs_dir2_leaf_hdr_to_disk(
452 struct xfs_dir2_leaf *to,
453 struct xfs_dir3_icleaf_hdr *from)
454{
455 ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC ||
456 from->magic == XFS_DIR2_LEAFN_MAGIC);
457
458 to->hdr.info.forw = cpu_to_be32(from->forw);
459 to->hdr.info.back = cpu_to_be32(from->back);
460 to->hdr.info.magic = cpu_to_be16(from->magic);
461 to->hdr.count = cpu_to_be16(from->count);
462 to->hdr.stale = cpu_to_be16(from->stale);
463}
464
465static void
466xfs_dir3_leaf_hdr_from_disk(
467 struct xfs_dir3_icleaf_hdr *to,
468 struct xfs_dir2_leaf *from)
469{
470 struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from;
471
472 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
473 to->back = be32_to_cpu(hdr3->info.hdr.back);
474 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
475 to->count = be16_to_cpu(hdr3->count);
476 to->stale = be16_to_cpu(hdr3->stale);
477
478 ASSERT(to->magic == XFS_DIR3_LEAF1_MAGIC ||
479 to->magic == XFS_DIR3_LEAFN_MAGIC);
480}
481
482static void
483xfs_dir3_leaf_hdr_to_disk(
484 struct xfs_dir2_leaf *to,
485 struct xfs_dir3_icleaf_hdr *from)
486{
487 struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to;
488
489 ASSERT(from->magic == XFS_DIR3_LEAF1_MAGIC ||
490 from->magic == XFS_DIR3_LEAFN_MAGIC);
491
492 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
493 hdr3->info.hdr.back = cpu_to_be32(from->back);
494 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
495 hdr3->count = cpu_to_be16(from->count);
496 hdr3->stale = cpu_to_be16(from->stale);
497}
498
499
500/*
501 * Directory/Attribute Node block operations
502 */
503static struct xfs_da_node_entry *
504xfs_da2_node_tree_p(struct xfs_da_intnode *dap)
505{
506 return dap->__btree;
507}
508
509static struct xfs_da_node_entry *
510xfs_da3_node_tree_p(struct xfs_da_intnode *dap)
511{
512 return ((struct xfs_da3_intnode *)dap)->__btree;
513}
514
515static void
516xfs_da2_node_hdr_from_disk(
517 struct xfs_da3_icnode_hdr *to,
518 struct xfs_da_intnode *from)
519{
520 ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC));
521 to->forw = be32_to_cpu(from->hdr.info.forw);
522 to->back = be32_to_cpu(from->hdr.info.back);
523 to->magic = be16_to_cpu(from->hdr.info.magic);
524 to->count = be16_to_cpu(from->hdr.__count);
525 to->level = be16_to_cpu(from->hdr.__level);
526}
527
528static void
529xfs_da2_node_hdr_to_disk(
530 struct xfs_da_intnode *to,
531 struct xfs_da3_icnode_hdr *from)
532{
533 ASSERT(from->magic == XFS_DA_NODE_MAGIC);
534 to->hdr.info.forw = cpu_to_be32(from->forw);
535 to->hdr.info.back = cpu_to_be32(from->back);
536 to->hdr.info.magic = cpu_to_be16(from->magic);
537 to->hdr.__count = cpu_to_be16(from->count);
538 to->hdr.__level = cpu_to_be16(from->level);
539}
540
541static void
542xfs_da3_node_hdr_from_disk(
543 struct xfs_da3_icnode_hdr *to,
544 struct xfs_da_intnode *from)
545{
546 struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)from;
547
548 ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC));
549 to->forw = be32_to_cpu(hdr3->info.hdr.forw);
550 to->back = be32_to_cpu(hdr3->info.hdr.back);
551 to->magic = be16_to_cpu(hdr3->info.hdr.magic);
552 to->count = be16_to_cpu(hdr3->__count);
553 to->level = be16_to_cpu(hdr3->__level);
554}
555
556static void
557xfs_da3_node_hdr_to_disk(
558 struct xfs_da_intnode *to,
559 struct xfs_da3_icnode_hdr *from)
560{
561 struct xfs_da3_node_hdr *hdr3 = (struct xfs_da3_node_hdr *)to;
562
563 ASSERT(from->magic == XFS_DA3_NODE_MAGIC);
564 hdr3->info.hdr.forw = cpu_to_be32(from->forw);
565 hdr3->info.hdr.back = cpu_to_be32(from->back);
566 hdr3->info.hdr.magic = cpu_to_be16(from->magic);
567 hdr3->__count = cpu_to_be16(from->count);
568 hdr3->__level = cpu_to_be16(from->level);
569}
570
571
572/*
573 * Directory free space block operations
574 */
575static int
576xfs_dir2_free_max_bests(struct xfs_da_geometry *geo)
577{
578 return (geo->blksize - sizeof(struct xfs_dir2_free_hdr)) /
579 sizeof(xfs_dir2_data_off_t);
580}
581
582static __be16 *
583xfs_dir2_free_bests_p(struct xfs_dir2_free *free)
584{
585 return (__be16 *)((char *)free + sizeof(struct xfs_dir2_free_hdr));
586}
587
588/*
589 * Convert data space db to the corresponding free db.
590 */
591static xfs_dir2_db_t
592xfs_dir2_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
593{
594 return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) +
595 (db / xfs_dir2_free_max_bests(geo));
596}
597
598/*
599 * Convert data space db to the corresponding index in a free db.
600 */
601static int
602xfs_dir2_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
603{
604 return db % xfs_dir2_free_max_bests(geo);
605}
606
607static int
608xfs_dir3_free_max_bests(struct xfs_da_geometry *geo)
609{
610 return (geo->blksize - sizeof(struct xfs_dir3_free_hdr)) /
611 sizeof(xfs_dir2_data_off_t);
612}
613
614static __be16 *
615xfs_dir3_free_bests_p(struct xfs_dir2_free *free)
616{
617 return (__be16 *)((char *)free + sizeof(struct xfs_dir3_free_hdr));
618}
619
620/*
621 * Convert data space db to the corresponding free db.
622 */
623static xfs_dir2_db_t
624xfs_dir3_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
625{
626 return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) +
627 (db / xfs_dir3_free_max_bests(geo));
628}
629
630/*
631 * Convert data space db to the corresponding index in a free db.
632 */
633static int
634xfs_dir3_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db)
635{
636 return db % xfs_dir3_free_max_bests(geo);
637}
638
639static void
640xfs_dir2_free_hdr_from_disk(
641 struct xfs_dir3_icfree_hdr *to,
642 struct xfs_dir2_free *from)
643{
644 to->magic = be32_to_cpu(from->hdr.magic);
645 to->firstdb = be32_to_cpu(from->hdr.firstdb);
646 to->nvalid = be32_to_cpu(from->hdr.nvalid);
647 to->nused = be32_to_cpu(from->hdr.nused);
648 ASSERT(to->magic == XFS_DIR2_FREE_MAGIC);
649}
650
651static void
652xfs_dir2_free_hdr_to_disk(
653 struct xfs_dir2_free *to,
654 struct xfs_dir3_icfree_hdr *from)
655{
656 ASSERT(from->magic == XFS_DIR2_FREE_MAGIC);
657
658 to->hdr.magic = cpu_to_be32(from->magic);
659 to->hdr.firstdb = cpu_to_be32(from->firstdb);
660 to->hdr.nvalid = cpu_to_be32(from->nvalid);
661 to->hdr.nused = cpu_to_be32(from->nused);
662}
663
664static void
665xfs_dir3_free_hdr_from_disk(
666 struct xfs_dir3_icfree_hdr *to,
667 struct xfs_dir2_free *from)
668{
669 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from;
670
671 to->magic = be32_to_cpu(hdr3->hdr.magic);
672 to->firstdb = be32_to_cpu(hdr3->firstdb);
673 to->nvalid = be32_to_cpu(hdr3->nvalid);
674 to->nused = be32_to_cpu(hdr3->nused);
675
676 ASSERT(to->magic == XFS_DIR3_FREE_MAGIC);
677}
678
679static void
680xfs_dir3_free_hdr_to_disk(
681 struct xfs_dir2_free *to,
682 struct xfs_dir3_icfree_hdr *from)
683{
684 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to;
685
686 ASSERT(from->magic == XFS_DIR3_FREE_MAGIC);
687
688 hdr3->hdr.magic = cpu_to_be32(from->magic);
689 hdr3->firstdb = cpu_to_be32(from->firstdb);
690 hdr3->nvalid = cpu_to_be32(from->nvalid);
691 hdr3->nused = cpu_to_be32(from->nused);
692}
693
694static const struct xfs_dir_ops xfs_dir2_ops = {
695 .sf_entsize = xfs_dir2_sf_entsize,
696 .sf_nextentry = xfs_dir2_sf_nextentry,
697 .sf_get_ftype = xfs_dir2_sfe_get_ftype,
698 .sf_put_ftype = xfs_dir2_sfe_put_ftype,
699 .sf_get_ino = xfs_dir2_sfe_get_ino,
700 .sf_put_ino = xfs_dir2_sfe_put_ino,
701 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
702 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
703
704 .data_entsize = xfs_dir2_data_entsize,
705 .data_get_ftype = xfs_dir2_data_get_ftype,
706 .data_put_ftype = xfs_dir2_data_put_ftype,
707 .data_entry_tag_p = xfs_dir2_data_entry_tag_p,
708 .data_bestfree_p = xfs_dir2_data_bestfree_p,
709
710 .data_dot_offset = sizeof(struct xfs_dir2_data_hdr),
711 .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) +
712 XFS_DIR2_DATA_ENTSIZE(1),
713 .data_first_offset = sizeof(struct xfs_dir2_data_hdr) +
714 XFS_DIR2_DATA_ENTSIZE(1) +
715 XFS_DIR2_DATA_ENTSIZE(2),
716 .data_entry_offset = sizeof(struct xfs_dir2_data_hdr),
717
718 .data_dot_entry_p = xfs_dir2_data_dot_entry_p,
719 .data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
720 .data_first_entry_p = xfs_dir2_data_first_entry_p,
721 .data_entry_p = xfs_dir2_data_entry_p,
722 .data_unused_p = xfs_dir2_data_unused_p,
723
724 .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr),
725 .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk,
726 .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk,
727 .leaf_max_ents = xfs_dir2_max_leaf_ents,
728 .leaf_ents_p = xfs_dir2_leaf_ents_p,
729
730 .node_hdr_size = sizeof(struct xfs_da_node_hdr),
731 .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
732 .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
733 .node_tree_p = xfs_da2_node_tree_p,
734
735 .free_hdr_size = sizeof(struct xfs_dir2_free_hdr),
736 .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk,
737 .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk,
738 .free_max_bests = xfs_dir2_free_max_bests,
739 .free_bests_p = xfs_dir2_free_bests_p,
740 .db_to_fdb = xfs_dir2_db_to_fdb,
741 .db_to_fdindex = xfs_dir2_db_to_fdindex,
742};
743
744static const struct xfs_dir_ops xfs_dir2_ftype_ops = {
745 .sf_entsize = xfs_dir3_sf_entsize,
746 .sf_nextentry = xfs_dir3_sf_nextentry,
747 .sf_get_ftype = xfs_dir3_sfe_get_ftype,
748 .sf_put_ftype = xfs_dir3_sfe_put_ftype,
749 .sf_get_ino = xfs_dir3_sfe_get_ino,
750 .sf_put_ino = xfs_dir3_sfe_put_ino,
751 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
752 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
753
754 .data_entsize = xfs_dir3_data_entsize,
755 .data_get_ftype = xfs_dir3_data_get_ftype,
756 .data_put_ftype = xfs_dir3_data_put_ftype,
757 .data_entry_tag_p = xfs_dir3_data_entry_tag_p,
758 .data_bestfree_p = xfs_dir2_data_bestfree_p,
759
760 .data_dot_offset = sizeof(struct xfs_dir2_data_hdr),
761 .data_dotdot_offset = sizeof(struct xfs_dir2_data_hdr) +
762 XFS_DIR3_DATA_ENTSIZE(1),
763 .data_first_offset = sizeof(struct xfs_dir2_data_hdr) +
764 XFS_DIR3_DATA_ENTSIZE(1) +
765 XFS_DIR3_DATA_ENTSIZE(2),
766 .data_entry_offset = sizeof(struct xfs_dir2_data_hdr),
767
768 .data_dot_entry_p = xfs_dir2_data_dot_entry_p,
769 .data_dotdot_entry_p = xfs_dir2_ftype_data_dotdot_entry_p,
770 .data_first_entry_p = xfs_dir2_ftype_data_first_entry_p,
771 .data_entry_p = xfs_dir2_data_entry_p,
772 .data_unused_p = xfs_dir2_data_unused_p,
773
774 .leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr),
775 .leaf_hdr_to_disk = xfs_dir2_leaf_hdr_to_disk,
776 .leaf_hdr_from_disk = xfs_dir2_leaf_hdr_from_disk,
777 .leaf_max_ents = xfs_dir2_max_leaf_ents,
778 .leaf_ents_p = xfs_dir2_leaf_ents_p,
779
780 .node_hdr_size = sizeof(struct xfs_da_node_hdr),
781 .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
782 .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
783 .node_tree_p = xfs_da2_node_tree_p,
784
785 .free_hdr_size = sizeof(struct xfs_dir2_free_hdr),
786 .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk,
787 .free_hdr_from_disk = xfs_dir2_free_hdr_from_disk,
788 .free_max_bests = xfs_dir2_free_max_bests,
789 .free_bests_p = xfs_dir2_free_bests_p,
790 .db_to_fdb = xfs_dir2_db_to_fdb,
791 .db_to_fdindex = xfs_dir2_db_to_fdindex,
792};
793
794static const struct xfs_dir_ops xfs_dir3_ops = {
795 .sf_entsize = xfs_dir3_sf_entsize,
796 .sf_nextentry = xfs_dir3_sf_nextentry,
797 .sf_get_ftype = xfs_dir3_sfe_get_ftype,
798 .sf_put_ftype = xfs_dir3_sfe_put_ftype,
799 .sf_get_ino = xfs_dir3_sfe_get_ino,
800 .sf_put_ino = xfs_dir3_sfe_put_ino,
801 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
802 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
803
804 .data_entsize = xfs_dir3_data_entsize,
805 .data_get_ftype = xfs_dir3_data_get_ftype,
806 .data_put_ftype = xfs_dir3_data_put_ftype,
807 .data_entry_tag_p = xfs_dir3_data_entry_tag_p,
808 .data_bestfree_p = xfs_dir3_data_bestfree_p,
809
810 .data_dot_offset = sizeof(struct xfs_dir3_data_hdr),
811 .data_dotdot_offset = sizeof(struct xfs_dir3_data_hdr) +
812 XFS_DIR3_DATA_ENTSIZE(1),
813 .data_first_offset = sizeof(struct xfs_dir3_data_hdr) +
814 XFS_DIR3_DATA_ENTSIZE(1) +
815 XFS_DIR3_DATA_ENTSIZE(2),
816 .data_entry_offset = sizeof(struct xfs_dir3_data_hdr),
817
818 .data_dot_entry_p = xfs_dir3_data_dot_entry_p,
819 .data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p,
820 .data_first_entry_p = xfs_dir3_data_first_entry_p,
821 .data_entry_p = xfs_dir3_data_entry_p,
822 .data_unused_p = xfs_dir3_data_unused_p,
823
824 .leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr),
825 .leaf_hdr_to_disk = xfs_dir3_leaf_hdr_to_disk,
826 .leaf_hdr_from_disk = xfs_dir3_leaf_hdr_from_disk,
827 .leaf_max_ents = xfs_dir3_max_leaf_ents,
828 .leaf_ents_p = xfs_dir3_leaf_ents_p,
829
830 .node_hdr_size = sizeof(struct xfs_da3_node_hdr),
831 .node_hdr_to_disk = xfs_da3_node_hdr_to_disk,
832 .node_hdr_from_disk = xfs_da3_node_hdr_from_disk,
833 .node_tree_p = xfs_da3_node_tree_p,
834
835 .free_hdr_size = sizeof(struct xfs_dir3_free_hdr),
836 .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk,
837 .free_hdr_from_disk = xfs_dir3_free_hdr_from_disk,
838 .free_max_bests = xfs_dir3_free_max_bests,
839 .free_bests_p = xfs_dir3_free_bests_p,
840 .db_to_fdb = xfs_dir3_db_to_fdb,
841 .db_to_fdindex = xfs_dir3_db_to_fdindex,
842};
843
844static const struct xfs_dir_ops xfs_dir2_nondir_ops = {
845 .node_hdr_size = sizeof(struct xfs_da_node_hdr),
846 .node_hdr_to_disk = xfs_da2_node_hdr_to_disk,
847 .node_hdr_from_disk = xfs_da2_node_hdr_from_disk,
848 .node_tree_p = xfs_da2_node_tree_p,
849};
850
851static const struct xfs_dir_ops xfs_dir3_nondir_ops = {
852 .node_hdr_size = sizeof(struct xfs_da3_node_hdr),
853 .node_hdr_to_disk = xfs_da3_node_hdr_to_disk,
854 .node_hdr_from_disk = xfs_da3_node_hdr_from_disk,
855 .node_tree_p = xfs_da3_node_tree_p,
856};
857
858/*
859 * Return the ops structure according to the current config. If we are passed
860 * an inode, then that overrides the default config we use which is based on
861 * feature bits.
862 */
863const struct xfs_dir_ops *
864xfs_dir_get_ops(
865 struct xfs_mount *mp,
866 struct xfs_inode *dp)
867{
868 if (dp)
869 return dp->d_ops;
870 if (mp->m_dir_inode_ops)
871 return mp->m_dir_inode_ops;
872 if (xfs_sb_version_hascrc(&mp->m_sb))
873 return &xfs_dir3_ops;
874 if (xfs_sb_version_hasftype(&mp->m_sb))
875 return &xfs_dir2_ftype_ops;
876 return &xfs_dir2_ops;
877}
878
879const struct xfs_dir_ops *
880xfs_nondir_get_ops(
881 struct xfs_mount *mp,
882 struct xfs_inode *dp)
883{
884 if (dp)
885 return dp->d_ops;
886 if (mp->m_nondir_inode_ops)
887 return mp->m_nondir_inode_ops;
888 if (xfs_sb_version_hascrc(&mp->m_sb))
889 return &xfs_dir3_nondir_ops;
890 return &xfs_dir2_nondir_ops;
891}