source: bootcd/isolinux/syslinux-6.03/core/fs/xfs/xfs.h

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 25.1 KB
Line 
1/*
2 * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
3 *
4 * Some parts borrowed from Linux kernel tree (linux/fs/xfs):
5 *
6 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
7 * All Rights Reserved.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it would be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write the Free Software Foundation,
20 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 */
22
23#ifndef XFS_H_
24#define XFS_H_
25
26#include <disk.h>
27#include <fs.h>
28#include <dprintf.h>
29
30#include "xfs_types.h"
31#include "xfs_ag.h"
32
33#define xfs_error(fmt, args...)                                         \
34    ({                                                                  \
35        printf("%s:%u: xfs - [ERROR] " fmt "\n", __func__, __LINE__, ## args); \
36    })
37
38#define xfs_debug(fmt, args...)                                         \
39    ({                                                                  \
40        dprintf("%s:%u: xfs - [DEBUG] " fmt "\n", __func__, __LINE__,   \
41                ## args);                                               \
42    })
43
44struct xfs_fs_info;
45
46#define XFS_INFO(fs) ((struct xfs_fs_info *)((fs)->fs_info))
47#define XFS_PVT(ino) ((struct xfs_inode *)((ino)->pvt))
48
49#define XFS_INO_MASK(k)                 (uint32_t)((1ULL << (k)) - 1)
50#define XFS_INO_OFFSET_BITS(fs)         (fs)->inopb_shift
51#define XFS_INO_AGINO_BITS(fs) \
52    (XFS_INFO((fs))->inopb_shift + XFS_INFO((fs))->agblk_shift)
53
54#define XFS_INO_TO_AGINO(fs, i) \
55    ((xfs_agino_t)(i) & XFS_INO_MASK(XFS_INO_AGINO_BITS(fs)))
56
57#define XFS_INO_TO_AGNO(fs, ino) \
58    ((xfs_agnumber_t)((ino) >> (XFS_INFO((fs))->inopb_shift + \
59                                XFS_INFO((fs))->agblk_shift)))
60
61#define XFS_INO_TO_OFFSET(fs, i) \
62        ((int)(i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(fs)))
63
64#define XFS_AGNO_TO_FSB(fs, agno) \
65    ((block_t)((agno) << XFS_INFO((fs))->agblocks_shift))
66
67#define XFS_AGI_OFFS(fs, mp) \
68    ((xfs_agi_t *)((uint8_t *)(mp) + 2 * SECTOR_SIZE((fs))))
69
70#define XFS_GET_DIR_INO4(di) \
71    (((uint32_t)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | \
72                ((di).i[3]))
73
74#define XFS_DI_HI(di) \
75    (((uint32_t)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
76
77#define XFS_DI_LO(di) \
78    (((uint32_t)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | \
79                ((di).i[7]))
80
81#define XFS_GET_DIR_INO8(di) \
82    (((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
83     ((xfs_ino_t)XFS_DI_HI(di) << 32))
84
85#define XFS_FSB_TO_AGNO(fs, fsbno) \
86    ((xfs_agnumber_t)((fsbno) >> XFS_INFO((fs))->agblk_shift))
87#define XFS_FSB_TO_AGBNO(fs, fsbno) \
88    ((xfs_agblock_t)((fsbno) & (uint32_t)((1ULL << \
89                                           XFS_INFO((fs))->agblk_shift) - 1)))
90
91#define agblock_to_bytes(fs, x) \
92    ((uint64_t)(x) << BLOCK_SHIFT((fs)))
93#define agino_to_bytes(fs, x) \
94    ((uint64_t)(x) << XFS_INFO((fs))->inode_shift)
95#define agnumber_to_bytes(fs, x) \
96    agblock_to_bytes(fs, (uint64_t)(x) * XFS_INFO((fs))->agblocks)
97#define fsblock_to_bytes(fs,x)                          \
98    (agnumber_to_bytes(fs, XFS_FSB_TO_AGNO(fs, (x))) +  \
99     agblock_to_bytes(fs, XFS_FSB_TO_AGBNO(fs, (x))))
100#define ino_to_bytes(fs, x)                        \
101    (agnumber_to_bytes(fs, XFS_INO_TO_AGNO(fs, (x))) +  \
102     agino_to_bytes(fs, XFS_INO_TO_AGINO(fs, (x))))
103
104/* Superblock's LBA */
105#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */
106
107/* Magic numbers */
108#define XFS_AGI_MAGIC           "XAGI"
109#define XFS_IBT_MAGIC           "IABT"
110#define XFS_DINODE_MAGIC        "IN"
111
112#define XFS_DIR2_BLOCK_MAGIC    0x58443242U      /* XD2B: single block dirs */
113#define XFS_DIR2_DATA_MAGIC     0x58443244U      /* XD2D: multiblock dirs */
114#define XFS_DIR2_FREE_MAGIC     0x58443246U      /* XD2F: free index blocks */
115
116#define XFS_DIR2_NULL_DATAPTR   ((uint32_t)0)
117
118/* File types and modes */
119#define S_IFMT          00170000
120#define S_IFSOCK        0140000
121#define S_IFLNK         0120000
122#define S_IFREG         0100000
123#define S_IFBLK         0060000
124#define S_IFDIR         0040000
125#define S_IFCHR         0020000
126#define S_IFIFO         0010000
127#define S_ISUID         0004000
128#define S_ISGID         0002000
129#define S_ISVTX         0001000
130
131#define MAXPATHLEN 1024
132/*
133 * NOTE: The fields in the superblock are stored in big-endian format on disk.
134 */
135typedef struct xfs_sb {
136    uint32_t    sb_magicnum;    /* magic number == XFS_SB_MAGIC */
137    uint32_t    sb_blocksize;   /* logical block size, bytes */
138    xfs_drfsbno_t       sb_dblocks;     /* number of data blocks */
139    xfs_drfsbno_t       sb_rblocks;     /* number of realtime blocks */
140    xfs_drtbno_t        sb_rextents;    /* number of realtime extents */
141    uuid_t              sb_uuid;        /* file system unique id */
142    xfs_dfsbno_t        sb_logstart;    /* starting block of log if internal */
143    xfs_ino_t   sb_rootino;     /* root inode number */
144    xfs_ino_t   sb_rbmino;      /* bitmap inode for realtime extents */
145    xfs_ino_t   sb_rsumino;     /* summary inode for rt bitmap */
146    xfs_agblock_t       sb_rextsize;    /* realtime extent size, blocks */
147    xfs_agblock_t       sb_agblocks;    /* size of an allocation group */
148    xfs_agnumber_t      sb_agcount;     /* number of allocation groups */
149    xfs_extlen_t        sb_rbmblocks;   /* number of rt bitmap blocks */
150    xfs_extlen_t        sb_logblocks;   /* number of log blocks */
151    uint16_t    sb_versionnum;  /* header version == XFS_SB_VERSION */
152    uint16_t    sb_sectsize;    /* volume sector size, bytes */
153    uint16_t    sb_inodesize;   /* inode size, bytes */
154    uint16_t    sb_inopblock;   /* inodes per block */
155    char        sb_fname[12];   /* file system name */
156    uint8_t     sb_blocklog;    /* log2 of sb_blocksize */
157    uint8_t     sb_sectlog;     /* log2 of sb_sectsize */
158    uint8_t     sb_inodelog;    /* log2 of sb_inodesize */
159    uint8_t     sb_inopblog;    /* log2 of sb_inopblock */
160    uint8_t     sb_agblklog;    /* log2 of sb_agblocks (rounded up) */
161    uint8_t     sb_rextslog;    /* log2 of sb_rextents */
162    uint8_t     sb_inprogress;  /* mkfs is in progress, don't mount */
163    uint8_t     sb_imax_pct;    /* max % of fs for inode space */
164                                        /* statistics */
165    /*
166     * These fields must remain contiguous.  If you really
167     * want to change their layout, make sure you fix the
168     * code in xfs_trans_apply_sb_deltas().
169     */
170    uint64_t    sb_icount;      /* allocated inodes */
171    uint64_t    sb_ifree;       /* free inodes */
172    uint64_t    sb_fdblocks;    /* free data blocks */
173    uint64_t    sb_frextents;   /* free realtime extents */
174    /*
175     * End contiguous fields.
176     */
177    xfs_ino_t   sb_uquotino;    /* user quota inode */
178    xfs_ino_t   sb_gquotino;    /* group quota inode */
179    uint16_t    sb_qflags;      /* quota flags */
180    uint8_t     sb_flags;       /* misc. flags */
181    uint8_t     sb_shared_vn;   /* shared version number */
182    xfs_extlen_t        sb_inoalignmt;  /* inode chunk alignment, fsblocks */
183    uint32_t    sb_unit;        /* stripe or raid unit */
184    uint32_t    sb_width;       /* stripe or raid width */
185    uint8_t     sb_dirblklog;   /* log2 of dir block size (fsbs) */
186    uint8_t     sb_logsectlog;  /* log2 of the log sector size */
187    uint16_t    sb_logsectsize; /* sector size for the log, bytes */
188    uint32_t    sb_logsunit;    /* stripe unit size for the log */
189    uint32_t    sb_features2;   /* additional feature bits */
190
191    /*
192     * bad features2 field as a result of failing to pad the sb
193     * structure to 64 bits. Some machines will be using this field
194     * for features2 bits. Easiest just to mark it bad and not use
195     * it for anything else.
196     */
197    uint32_t    sb_bad_features2;
198    uint8_t     pad[304]; /* must be padded to a sector boundary */
199} __attribute__((__packed__)) xfs_sb_t;
200
201/* In-memory structure that stores filesystem-specific information.
202 * The information stored is basically retrieved from the XFS superblock
203 * to be used statically around the driver.
204 */
205struct xfs_fs_info {
206    uint32_t            blocksize; /* Filesystem block size */
207    uint8_t             block_shift; /* Filesystem block size in bits */
208    uint32_t            dirblksize;
209    uint8_t             dirblklog;
210    uint8_t             inopb_shift;
211    uint8_t             agblk_shift;
212    uint32_t            dirleafblk;
213
214    /* AG number bits (MSB of the inode number) */
215    uint8_t             ag_number_ino_shift;
216
217    xfs_ino_t           rootino; /* Root inode number for the filesystem */
218    xfs_agblock_t       agblocks; /* Size of each AG in blocks */
219    uint8_t             agblocks_shift; /* agblocks in bits */
220    xfs_agnumber_t      agcount; /* Number of AGs in the filesytem */
221    uint16_t            inodesize; /* Size of the inode in bytes */
222    uint8_t             inode_shift; /* Inode size in bits */
223} __attribute__((__packed__));
224
225typedef struct xfs_agi {
226        /*
227         * Common allocation group header information
228         */
229    uint32_t            agi_magicnum;   /* magic number == XFS_AGI_MAGIC */
230    uint32_t            agi_versionnum; /* header version == XFS_AGI_VERSION */
231    uint32_t            agi_seqno;      /* sequence # starting from 0 */
232    uint32_t            agi_length;     /* size in blocks of a.g. */
233    /*
234     * Inode information
235     * Inodes are mapped by interpreting the inode number, so no
236     * mapping data is needed here.
237     */
238    uint32_t            agi_count;      /* count of allocated inodes */
239    uint32_t            agi_root;       /* root of inode btree */
240    uint32_t            agi_level;      /* levels in inode btree */
241    uint32_t            agi_freecount;  /* number of free inodes */
242    uint32_t            agi_newino;     /* new inode just allocated */
243    uint32_t            agi_dirino;     /* last directory inode chunk */
244    /*
245     * Hash table of inodes which have been unlinked but are
246     * still being referenced.
247     */
248    uint32_t            agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
249} __attribute__((__packed__)) xfs_agi_t;
250
251/*
252 * Bmap btree record and extent descriptor.
253 *  l0:63 is an extent flag (value 1 indicates non-normal).
254 *  l0:9-62 are startoff.
255 *  l0:0-8 and l1:21-63 are startblock.
256 *  l1:0-20 are blockcount.
257 */
258typedef struct xfs_bmbt_rec {
259    uint64_t l0;
260    uint64_t l1;
261} __attribute__((__packed__)) xfs_bmbt_rec_t;
262
263typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
264
265/*
266 * Possible extent states.
267 */
268typedef enum {
269    XFS_EXT_NORM,
270    XFS_EXT_UNWRITTEN,
271    XFS_EXT_DMAPI_OFFLINE,
272    XFS_EXT_INVALID,
273} xfs_exntst_t;
274
275typedef struct xfs_bmbt_irec
276{
277    xfs_fileoff_t br_startoff;    /* starting file offset */
278    xfs_fsblock_t br_startblock;  /* starting block number */
279    xfs_filblks_t br_blockcount;  /* number of blocks */
280    xfs_exntst_t  br_state;       /* extent state */
281} __attribute__((__packed__)) xfs_bmbt_irec_t;
282
283static inline void bmbt_irec_get(xfs_bmbt_irec_t *dest,
284                                 const xfs_bmbt_rec_t *src)
285{
286    uint64_t l0, l1;
287
288    l0 = be64_to_cpu(src->l0);
289    l1 = be64_to_cpu(src->l1);
290
291    dest->br_startoff = ((xfs_fileoff_t)l0 & 0x7ffffffffffffe00ULL) >> 9;
292    dest->br_startblock = (((xfs_fsblock_t)l0 & 0x00000000000001ffULL) << 43) |
293                          (((xfs_fsblock_t)l1) >> 21);
294    dest->br_blockcount = (xfs_filblks_t)(l1 & 0x00000000001fffffULL);
295    dest->br_state = (l0 & 0x8000000000000000ULL) ?
296                                        XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
297}
298
299typedef struct xfs_timestamp {
300    int32_t t_sec;
301    int32_t t_nsec;
302} __attribute__((__packed__)) xfs_timestamp_t;
303
304/*
305 * Fork identifiers.
306 */
307#define XFS_DATA_FORK 0
308#define xFS_ATTR_FORK 1
309
310typedef enum xfs_dinode_fmt {
311    XFS_DINODE_FMT_DEV,
312    XFS_DINODE_FMT_LOCAL,
313    XFS_DINODE_FMT_EXTENTS,
314    XFS_DINODE_FMT_BTREE,
315    XFS_DINODE_FMT_UUID,
316} xfs_dinode_fmt_t;
317
318typedef struct xfs_dinode {
319    uint16_t            di_magic;       /* inode magic # = XFS_DINODE_MAGIC */
320    uint16_t            di_mode;        /* mode and type of file */
321    uint8_t             di_version;     /* inode version */
322    uint8_t             di_format;      /* format of di_c data */
323    uint16_t            di_onlink;      /* old number of links to file */
324    uint32_t            di_uid;         /* owner's user id */
325    uint32_t            di_gid;         /* owner's group id */
326    uint32_t            di_nlink;       /* number of links to file */
327    uint16_t            di_projid_lo;   /* lower part of owner's project id */
328    uint16_t            di_projid_hi;   /* higher part owner's project id */
329    uint8_t             di_pad[6];      /* unused, zeroed space */
330    uint16_t            di_flushiter;   /* incremented on flush */
331    xfs_timestamp_t     di_atime;       /* time last accessed */
332    xfs_timestamp_t     di_mtime;       /* time last modified */
333    xfs_timestamp_t     di_ctime;       /* time created/inode modified */
334    uint64_t            di_size;        /* number of bytes in file */
335    uint64_t            di_nblocks;     /* # of direct & btree blocks used */
336    uint32_t            di_extsize;     /* basic/minimum extent size for file */
337    uint32_t            di_nextents;    /* number of extents in data fork */
338    uint16_t            di_anextents;   /* number of extents in attribute fork*/
339    uint8_t             di_forkoff;     /* attr fork offs, <<3 for 64b align */
340    int8_t              di_aformat;     /* format of attr fork's data */
341    uint32_t            di_dmevmask;    /* DMIG event mask */
342    uint16_t            di_dmstate;     /* DMIG state info */
343    uint16_t            di_flags;       /* random flags, XFS_DIFLAG_... */
344    uint32_t            di_gen;         /* generation number */
345
346    /* di_next_unlinked is the only non-core field in the old dinode */
347    uint32_t            di_next_unlinked;/* agi unlinked list ptr */
348    uint8_t             di_literal_area[1];
349} __attribute__((packed)) xfs_dinode_t;
350
351/*
352 * Inode size for given fs.
353 */
354#define XFS_LITINO(fs) \
355        ((int)((XFS_INFO(fs)->inodesize) - sizeof(struct xfs_dinode) - 1))
356
357#define XFS_BROOT_SIZE_ADJ \
358        (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t))
359
360/*
361 * Inode data & attribute fork sizes, per inode.
362 */
363#define XFS_DFORK_Q(dip)        ((dip)->di_forkoff != 0)
364#define XFS_DFORK_BOFF(dip)     ((int)((dip)->di_forkoff << 3))
365
366#define XFS_DFORK_DSIZE(dip, fs) \
367        (XFS_DFORK_Q(dip) ? \
368                XFS_DFORK_BOFF(dip) : \
369                XFS_LITINO(fs))
370#define XFS_DFORK_ASIZE(dip, fs) \
371        (XFS_DFORK_Q(dip) ? \
372                XFS_LITINO(fs) - XFS_DFORK_BOFF(dip) : \
373                0)
374#define XFS_DFORK_SIZE(dip, fs, w) \
375        ((w) == XFS_DATA_FORK ? \
376                XFS_DFORK_DSIZE(dip, fs) : \
377                XFS_DFORK_ASIZE(dip, fs))
378
379struct xfs_inode {
380    xfs_agblock_t       i_agblock;
381    block_t             i_ino_blk;
382    uint64_t            i_block_offset;
383    uint64_t            i_offset;
384    uint32_t            i_cur_extent;
385    uint32_t            i_btree_offset;
386    uint16_t            i_leaf_ent_offset;
387};
388
389typedef struct { uint8_t i[8]; } __attribute__((__packed__)) xfs_dir2_ino8_t;
390typedef struct { uint8_t i[4]; } __attribute__((__packed__)) xfs_dir2_ino4_t;
391
392typedef union {
393    xfs_dir2_ino8_t i8;
394    xfs_dir2_ino4_t i4;
395} __attribute__((__packed__)) xfs_dir2_inou_t;
396
397typedef struct { uint8_t i[2]; } __attribute__((__packed__)) xfs_dir2_sf_off_t;
398
399typedef struct xfs_dir2_sf_hdr {
400    uint8_t             count;          /* count of entries */
401    uint8_t             i8count;        /* count of 8-byte inode #s */
402    xfs_dir2_inou_t     parent;         /* parent dir inode number */
403} __attribute__((__packed__)) xfs_dir2_sf_hdr_t;
404
405typedef struct xfs_dir2_sf_entry {
406    uint8_t             namelen;        /* actual name length */
407    xfs_dir2_sf_off_t   offset;         /* saved offset */
408    uint8_t             name[1];        /* name, variable size */
409    xfs_dir2_inou_t     inumber;        /* inode number, var. offset */
410} __attribute__((__packed__)) xfs_dir2_sf_entry_t;
411
412typedef struct xfs_dir2_sf {
413    xfs_dir2_sf_hdr_t       hdr;            /* shortform header */
414    xfs_dir2_sf_entry_t     list[1];        /* shortform entries */
415} __attribute__((__packed__)) xfs_dir2_sf_t;
416
417typedef xfs_ino_t       xfs_intino_t;
418
419static inline xfs_intino_t xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp,
420                                                   xfs_dir2_inou_t *from)
421{
422    return ((sfp)->hdr.i8count == 0 ? \
423            (xfs_intino_t)XFS_GET_DIR_INO4((from)->i4) : \
424            (xfs_intino_t)XFS_GET_DIR_INO8((from)->i8));
425}
426
427/*
428 * DIR2 Data block structures.
429 *
430 * A pure data block looks like the following drawing on disk:
431 *
432 *    +-------------------------------------------------+
433 *    | xfs_dir2_data_hdr_t                             |
434 *    +-------------------------------------------------+
435 *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
436 *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
437 *    | xfs_dir2_data_entry_t OR xfs_dir2_data_unused_t |
438 *    | ...                                             |
439 *    +-------------------------------------------------+
440 *    | unused space                                    |
441 *    +-------------------------------------------------+
442 *
443 * As all the entries are variable size structure the accessors below should
444 * be used to iterate over them.
445 *
446 * In addition to the pure data blocks for the data and node formats.
447 * most structures are also used for the combined data/freespace "block"
448 * format below.
449 */
450#define XFS_DIR2_DATA_ALIGN_LOG 3
451#define XFS_DIR2_DATA_ALIGN     (1 << XFS_DIR2_DATA_ALIGN_LOG)
452#define XFS_DIR2_DATA_FREE_TAG  0xffff
453#define XFS_DIR2_DATA_FD_COUNT  3
454
455/*
456 * Directory address space divided into sections.
457 * spaces separated by 32GB.
458 */
459#define XFS_DIR2_SPACE_SIZE     (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
460
461typedef struct xfs_dir2_data_free {
462    uint16_t offset;
463    uint16_t length;
464} __attribute__((__packed__)) xfs_dir2_data_free_t;
465
466typedef struct xfs_dir2_data_hdr {
467    uint32_t magic;
468    xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
469} __attribute__((__packed__)) xfs_dir2_data_hdr_t;
470
471typedef struct xfs_dir2_data_entry {
472    uint64_t inumber; /* inode number */
473    uint8_t  namelen; /* name length */
474    uint8_t  name[];  /* name types, no null */
475 /* uint16_t tag; */  /* starting offset of us */
476} __attribute__((__packed__)) xfs_dir2_data_entry_t;
477
478typedef struct xfs_dir2_data_unused {
479    uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */
480    uint16_t length;  /* total free length */
481                      /* variable offset */
482 /* uint16_t tag; */  /* starting offset of us */
483} __attribute__((__packed__)) xfs_dir2_data_unused_t;
484
485/**
486 * rol32 - rotate a 32-bit value left
487 * @word: value to rotate
488 * @shift: bits to roll
489 */
490static inline uint32_t rol32(uint32_t word, signed int shift)
491{
492    return (word << shift) | (word >> (32 - shift));
493}
494
495#define roundup(x, y) (                                 \
496{                                                       \
497        const typeof(y) __y = y;                        \
498        (((x) + (__y - 1)) / __y) * __y;                \
499}                                                       \
500)
501
502static inline int xfs_dir2_data_entsize(int n)
503{
504    return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n +
505                        (unsigned int)sizeof(uint16_t), XFS_DIR2_DATA_ALIGN);
506}
507
508static inline uint16_t *
509xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep)
510{
511    return (uint16_t *)((char *)dep +
512            xfs_dir2_data_entsize(dep->namelen) - sizeof(uint16_t));
513}
514
515static inline uint16_t *
516xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
517{
518    return (uint16_t *)((char *)dup +
519            be16_to_cpu(dup->length) - sizeof(uint16_t));
520}
521
522typedef struct xfs_dir2_block_tail {
523    uint32_t            count;                  /* count of leaf entries */
524    uint32_t            stale;                  /* count of stale lf entries */
525} __attribute__((__packed__)) xfs_dir2_block_tail_t;
526
527static inline struct xfs_dir2_block_tail *
528xfs_dir2_block_tail_p(struct xfs_fs_info *fs_info, struct xfs_dir2_data_hdr *hdr)
529{
530    return ((struct xfs_dir2_block_tail *)
531            ((char *)hdr + fs_info->dirblksize)) - 1;
532}
533
534static inline uint32_t
535xfs_dir2_db_to_da(struct fs_info *fs, uint32_t db)
536{
537    return db << XFS_INFO(fs)->dirblklog;
538}
539
540static inline int64_t
541xfs_dir2_dataptr_to_byte(uint32_t dp)
542{
543    return (int64_t)dp << XFS_DIR2_DATA_ALIGN_LOG;
544}
545
546static inline uint32_t
547xfs_dir2_byte_to_db(struct fs_info *fs, int64_t by)
548{
549    return (uint32_t)
550            (by >> (XFS_INFO(fs)->block_shift + XFS_INFO(fs)->dirblklog));
551}
552
553static inline uint32_t
554xfs_dir2_dataptr_to_db(struct fs_info *fs, uint32_t dp)
555{
556    return xfs_dir2_byte_to_db(fs, xfs_dir2_dataptr_to_byte(dp));
557}
558
559static inline unsigned int
560xfs_dir2_byte_to_off(struct fs_info *fs, int64_t by)
561{
562    return (unsigned int)(by &
563        (( 1 << (XFS_INFO(fs)->block_shift + XFS_INFO(fs)->dirblklog)) - 1));
564}
565
566static inline unsigned int
567xfs_dir2_dataptr_to_off(struct fs_info *fs, uint32_t dp)
568{
569    return xfs_dir2_byte_to_off(fs, xfs_dir2_dataptr_to_byte(dp));
570}
571
572#define XFS_DIR2_LEAF_SPACE     1
573#define XFS_DIR2_LEAF_OFFSET    (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
574#define XFS_DIR2_LEAF_FIRSTDB(fs)       \
575        xfs_dir2_byte_to_db(fs, XFS_DIR2_LEAF_OFFSET)
576
577typedef struct xfs_da_blkinfo {
578    uint32_t            forw;
579    uint32_t            back;
580    uint16_t            magic;
581    uint16_t            pad;
582} __attribute__((__packed__)) xfs_da_blkinfo_t;
583
584typedef struct xfs_dir2_leaf_hdr {
585    xfs_da_blkinfo_t    info;
586    uint16_t            count;
587    uint16_t            stale;
588} __attribute__((__packed__)) xfs_dir2_leaf_hdr_t;
589
590typedef struct xfs_dir2_leaf_entry {
591    uint32_t            hashval;                /* hash value of name */
592    uint32_t            address;                /* address of data entry */
593} __attribute__((__packed__)) xfs_dir2_leaf_entry_t;
594
595typedef struct xfs_dir2_leaf {
596    xfs_dir2_leaf_hdr_t         hdr;    /* leaf header */
597    xfs_dir2_leaf_entry_t       ents[]; /* entries */
598} __attribute__((__packed__)) xfs_dir2_leaf_t;
599
600#define XFS_DA_NODE_MAGIC       0xfebeU /* magic number: non-leaf blocks */
601#define XFS_ATTR_LEAF_MAGIC     0xfbeeU /* magic number: attribute leaf blks */
602#define XFS_DIR2_LEAF1_MAGIC    0xd2f1U /* magic number: v2 dirlf single blks */
603#define XFS_DIR2_LEAFN_MAGIC    0xd2ffU /* magic number: V2 dirlf multi blks */
604
605typedef struct xfs_da_intnode {
606    struct xfs_da_node_hdr {    /* constant-structure header block */
607        xfs_da_blkinfo_t info;  /* block type, links, etc. */
608        uint16_t count;         /* count of active entries */
609        uint16_t level;         /* level above leaves (leaf == 0) */
610    } hdr;
611    struct xfs_da_node_entry {
612        uint32_t hashval;       /* hash value for this descendant */
613        uint32_t before;        /* Btree block before this key */
614    } btree[1];
615} __attribute__((__packed__)) xfs_da_intnode_t;
616
617typedef struct xfs_da_node_hdr xfs_da_node_hdr_t;
618typedef struct xfs_da_node_entry xfs_da_node_entry_t;
619
620static inline bool xfs_is_valid_magicnum(const xfs_sb_t *sb)
621{
622    return sb->sb_magicnum == *(uint32_t *)XFS_SB_MAGIC;
623}
624
625static inline bool xfs_is_valid_agi(xfs_agi_t *agi)
626{
627    return agi->agi_magicnum == *(uint32_t *)XFS_AGI_MAGIC;
628}
629
630static inline struct inode *xfs_new_inode(struct fs_info *fs)
631{
632    struct inode *inode;
633
634    inode = alloc_inode(fs, 0, sizeof(struct xfs_inode));
635    if (!inode)
636        malloc_error("xfs_inode structure");
637
638    return inode;
639}
640
641static inline void fill_xfs_inode_pvt(struct fs_info *fs, struct inode *inode,
642                                      xfs_ino_t ino)
643{
644    XFS_PVT(inode)->i_agblock =
645        agnumber_to_bytes(fs, XFS_INO_TO_AGNO(fs, ino)) >> BLOCK_SHIFT(fs);
646    XFS_PVT(inode)->i_ino_blk = ino_to_bytes(fs, ino) >> BLOCK_SHIFT(fs);
647    XFS_PVT(inode)->i_block_offset = XFS_INO_TO_OFFSET(XFS_INFO(fs), ino) <<
648                                     XFS_INFO(fs)->inode_shift;
649}
650
651/*
652 * Generic btree header.
653 *
654 * This is a combination of the actual format used on disk for short and long
655 * format btrees. The first three fields are shared by both format, but
656 * the pointers are different and should be used with care.
657 *
658 * To get the size of the actual short or long form headers please use
659 * the size macros belows. Never use sizeof(xfs_btree_block);
660 */
661typedef struct xfs_btree_block {
662    uint32_t bb_magic;                  /* magic number for block type */
663    uint16_t bb_level;                  /* 0 is a leaf */
664    uint16_t bb_numrecs;                /* current # of data records */
665    union {
666        struct {
667            uint32_t bb_leftsib;
668            uint32_t bb_rightsib;
669        } s;                            /* short form pointers */
670        struct {
671            uint64_t bb_leftsib;
672            uint64_t bb_rightsib;
673        } l;                            /* long form pointers */
674    } bb_u;                             /* rest */
675} xfs_btree_block_t;
676
677#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */
678#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */
679
680/*
681 * Bmap root header, on-disk form only.
682 */
683typedef struct xfs_bmdr_block {
684    uint16_t bb_level;          /* 0 is a leaf */
685    uint16_t bb_numrecs;        /* current # of data records */
686} xfs_bmdr_block_t;
687
688/*
689 * Key structure for non-leaf levels of the tree.
690 */
691typedef struct xfs_bmbt_key {
692    uint64_t br_startoff;       /* starting file offset */
693} xfs_bmbt_key_t, xfs_bmdr_key_t;
694
695/* btree pointer type */
696typedef uint64_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
697
698/*
699 * Btree block header size depends on a superblock flag.
700 *
701 * (not quite yet, but soon)
702 */
703#define XFS_BMBT_BLOCK_LEN(fs) XFS_BTREE_LBLOCK_LEN
704
705#define XFS_BMBT_REC_ADDR(fs, block, index) \
706        ((xfs_bmbt_rec_t *) \
707                ((char *)(block) + \
708                 XFS_BMBT_BLOCK_LEN(fs) + \
709                 ((index) - 1) * sizeof(xfs_bmbt_rec_t)))
710
711#define XFS_BMBT_KEY_ADDR(fs, block, index) \
712        ((xfs_bmbt_key_t *) \
713                ((char *)(block) + \
714                 XFS_BMBT_BLOCK_LEN(fs) + \
715                 ((index) - 1) * sizeof(xfs_bmbt_key_t)))
716
717#define XFS_BMBT_PTR_ADDR(fs, block, index, maxrecs) \
718        ((xfs_bmbt_ptr_t *) \
719                ((char *)(block) + \
720                 XFS_BMBT_BLOCK_LEN(fs) + \
721                 (maxrecs) * sizeof(xfs_bmbt_key_t) + \
722                 ((index) - 1) * sizeof(xfs_bmbt_ptr_t)))
723
724#define XFS_BMDR_REC_ADDR(block, index) \
725        ((xfs_bmdr_rec_t *) \
726                ((char *)(block) + \
727                 sizeof(struct xfs_bmdr_block) + \
728                 ((index) - 1) * sizeof(xfs_bmdr_rec_t)))
729
730#define XFS_BMDR_KEY_ADDR(block, index) \
731        ((xfs_bmdr_key_t *) \
732                ((char *)(block) + \
733                 sizeof(struct xfs_bmdr_block) + \
734                 ((index) - 1) * sizeof(xfs_bmdr_key_t)))
735
736#define XFS_BMDR_PTR_ADDR(block, index, maxrecs) \
737        ((xfs_bmdr_ptr_t *) \
738                ((char *)(block) + \
739                 sizeof(struct xfs_bmdr_block) + \
740                 (maxrecs) * sizeof(xfs_bmdr_key_t) + \
741                 ((index) - 1) * sizeof(xfs_bmdr_ptr_t)))
742
743/*
744 * Calculate number of records in a bmap btree inode root.
745 */
746static inline int
747xfs_bmdr_maxrecs(int blocklen, int leaf)
748{
749    blocklen -= sizeof(xfs_bmdr_block_t);
750
751    if (leaf)
752        return blocklen / sizeof(xfs_bmdr_rec_t);
753
754    return blocklen / (sizeof(xfs_bmdr_key_t) + sizeof(xfs_bmdr_ptr_t));
755}
756
757#endif /* XFS_H_ */
Note: See TracBrowser for help on using the repository browser.