1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
8 #include "xfs_format.h"
9 #include "xfs_log_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_da_format.h"
13 #include "xfs_da_btree.h"
14 #include "xfs_inode.h"
15 #include "xfs_trans.h"
16 #include "xfs_inode_item.h"
17 #include "xfs_error.h"
19 #include "xfs_dir2_priv.h"
20 #include "xfs_trace.h"
23 * Prototypes for internal functions.
25 static void xfs_dir2_sf_addname_easy(xfs_da_args_t
*args
,
26 xfs_dir2_sf_entry_t
*sfep
,
27 xfs_dir2_data_aoff_t offset
,
29 static void xfs_dir2_sf_addname_hard(xfs_da_args_t
*args
, int objchange
,
31 static int xfs_dir2_sf_addname_pick(xfs_da_args_t
*args
, int objchange
,
32 xfs_dir2_sf_entry_t
**sfepp
,
33 xfs_dir2_data_aoff_t
*offsetp
);
35 static void xfs_dir2_sf_check(xfs_da_args_t
*args
);
37 #define xfs_dir2_sf_check(args)
40 static void xfs_dir2_sf_toino4(xfs_da_args_t
*args
);
41 static void xfs_dir2_sf_toino8(xfs_da_args_t
*args
);
44 * Given a block directory (dp/block), calculate its size as a shortform (sf)
45 * directory and a header for the sf directory, if it will fit it the
46 * space currently present in the inode. If it won't fit, the output
47 * size is too big (but not accurate).
49 int /* size for sf form */
50 xfs_dir2_block_sfsize(
51 xfs_inode_t
*dp
, /* incore inode pointer */
52 xfs_dir2_data_hdr_t
*hdr
, /* block directory data */
53 xfs_dir2_sf_hdr_t
*sfhp
) /* output: header for sf form */
55 xfs_dir2_dataptr_t addr
; /* data entry address */
56 xfs_dir2_leaf_entry_t
*blp
; /* leaf area of the block */
57 xfs_dir2_block_tail_t
*btp
; /* tail area of the block */
58 int count
; /* shortform entry count */
59 xfs_dir2_data_entry_t
*dep
; /* data entry in the block */
60 int i
; /* block entry index */
61 int i8count
; /* count of big-inode entries */
62 int isdot
; /* entry is "." */
63 int isdotdot
; /* entry is ".." */
64 xfs_mount_t
*mp
; /* mount structure pointer */
65 int namelen
; /* total name bytes */
66 xfs_ino_t parent
= 0; /* parent inode number */
67 int size
=0; /* total computed size */
69 struct xfs_da_geometry
*geo
;
75 * if there is a filetype field, add the extra byte to the namelen
76 * for each entry that we see.
78 has_ftype
= xfs_sb_version_hasftype(&mp
->m_sb
) ? 1 : 0;
80 count
= i8count
= namelen
= 0;
81 btp
= xfs_dir2_block_tail_p(geo
, hdr
);
82 blp
= xfs_dir2_block_leaf_p(btp
);
85 * Iterate over the block's data entries by using the leaf pointers.
87 for (i
= 0; i
< be32_to_cpu(btp
->count
); i
++) {
88 if ((addr
= be32_to_cpu(blp
[i
].address
)) == XFS_DIR2_NULL_DATAPTR
)
91 * Calculate the pointer to the entry at hand.
93 dep
= (xfs_dir2_data_entry_t
*)((char *)hdr
+
94 xfs_dir2_dataptr_to_off(geo
, addr
));
96 * Detect . and .., so we can special-case them.
97 * . is not included in sf directories.
98 * .. is included by just the parent inode number.
100 isdot
= dep
->namelen
== 1 && dep
->name
[0] == '.';
103 dep
->name
[0] == '.' && dep
->name
[1] == '.';
106 i8count
+= be64_to_cpu(dep
->inumber
) > XFS_DIR2_MAX_SHORT_INUM
;
108 /* take into account the file type field */
109 if (!isdot
&& !isdotdot
) {
111 namelen
+= dep
->namelen
+ has_ftype
;
113 parent
= be64_to_cpu(dep
->inumber
);
115 * Calculate the new size, see if we should give up yet.
117 size
= xfs_dir2_sf_hdr_size(i8count
) + /* header */
118 count
* 3 * sizeof(u8
) + /* namelen + offset */
120 (i8count
? /* inumber */
121 count
* XFS_INO64_SIZE
:
122 count
* XFS_INO32_SIZE
);
123 if (size
> XFS_IFORK_DSIZE(dp
))
124 return size
; /* size value is a failure */
127 * Create the output header, if it worked.
130 sfhp
->i8count
= i8count
;
131 dp
->d_ops
->sf_put_parent_ino(sfhp
, parent
);
136 * Convert a block format directory to shortform.
137 * Caller has already checked that it will fit, and built us a header.
140 xfs_dir2_block_to_sf(
141 xfs_da_args_t
*args
, /* operation arguments */
143 int size
, /* shortform directory size */
144 xfs_dir2_sf_hdr_t
*sfhp
) /* shortform directory hdr */
146 xfs_dir2_data_hdr_t
*hdr
; /* block header */
147 xfs_dir2_data_entry_t
*dep
; /* data entry pointer */
148 xfs_inode_t
*dp
; /* incore directory inode */
149 xfs_dir2_data_unused_t
*dup
; /* unused data pointer */
150 char *endptr
; /* end of data entries */
151 int error
; /* error return value */
152 int logflags
; /* inode logging flags */
153 xfs_mount_t
*mp
; /* filesystem mount point */
154 char *ptr
; /* current data pointer */
155 xfs_dir2_sf_entry_t
*sfep
; /* shortform entry */
156 xfs_dir2_sf_hdr_t
*sfp
; /* shortform directory header */
157 xfs_dir2_sf_hdr_t
*dst
; /* temporary data buffer */
159 trace_xfs_dir2_block_to_sf(args
);
165 * allocate a temporary destination buffer the size of the inode
166 * to format the data into. Once we have formatted the data, we
167 * can free the block and copy the formatted data into the inode literal
170 dst
= kmem_alloc(mp
->m_sb
.sb_inodesize
, KM_SLEEP
);
174 * Copy the header into the newly allocate local space.
176 sfp
= (xfs_dir2_sf_hdr_t
*)dst
;
177 memcpy(sfp
, sfhp
, xfs_dir2_sf_hdr_size(sfhp
->i8count
));
180 * Set up to loop over the block's entries.
182 ptr
= (char *)dp
->d_ops
->data_entry_p(hdr
);
183 endptr
= xfs_dir3_data_endp(args
->geo
, hdr
);
184 sfep
= xfs_dir2_sf_firstentry(sfp
);
186 * Loop over the active and unused entries.
187 * Stop when we reach the leaf/tail portion of the block.
189 while (ptr
< endptr
) {
191 * If it's unused, just skip over it.
193 dup
= (xfs_dir2_data_unused_t
*)ptr
;
194 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
) {
195 ptr
+= be16_to_cpu(dup
->length
);
198 dep
= (xfs_dir2_data_entry_t
*)ptr
;
202 if (dep
->namelen
== 1 && dep
->name
[0] == '.')
203 ASSERT(be64_to_cpu(dep
->inumber
) == dp
->i_ino
);
205 * Skip .., but make sure the inode number is right.
207 else if (dep
->namelen
== 2 &&
208 dep
->name
[0] == '.' && dep
->name
[1] == '.')
209 ASSERT(be64_to_cpu(dep
->inumber
) ==
210 dp
->d_ops
->sf_get_parent_ino(sfp
));
212 * Normal entry, copy it into shortform.
215 sfep
->namelen
= dep
->namelen
;
216 xfs_dir2_sf_put_offset(sfep
,
217 (xfs_dir2_data_aoff_t
)
218 ((char *)dep
- (char *)hdr
));
219 memcpy(sfep
->name
, dep
->name
, dep
->namelen
);
220 dp
->d_ops
->sf_put_ino(sfp
, sfep
,
221 be64_to_cpu(dep
->inumber
));
222 dp
->d_ops
->sf_put_ftype(sfep
,
223 dp
->d_ops
->data_get_ftype(dep
));
225 sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
);
227 ptr
+= dp
->d_ops
->data_entsize(dep
->namelen
);
229 ASSERT((char *)sfep
- (char *)sfp
== size
);
231 /* now we are done with the block, we can shrink the inode */
232 logflags
= XFS_ILOG_CORE
;
233 error
= xfs_dir2_shrink_inode(args
, args
->geo
->datablk
, bp
);
235 ASSERT(error
!= -ENOSPC
);
240 * The buffer is now unconditionally gone, whether
241 * xfs_dir2_shrink_inode worked or not.
243 * Convert the inode to local format and copy the data in.
245 ASSERT(dp
->i_df
.if_bytes
== 0);
246 xfs_init_local_fork(dp
, XFS_DATA_FORK
, dst
, size
);
247 dp
->i_d
.di_format
= XFS_DINODE_FMT_LOCAL
;
248 dp
->i_d
.di_size
= size
;
250 logflags
|= XFS_ILOG_DDATA
;
251 xfs_dir2_sf_check(args
);
253 xfs_trans_log_inode(args
->trans
, dp
, logflags
);
259 * Add a name to a shortform directory.
260 * There are two algorithms, "easy" and "hard" which we decide on
261 * before changing anything.
262 * Convert to block form if necessary, if the new entry won't fit.
266 xfs_da_args_t
*args
) /* operation arguments */
268 xfs_inode_t
*dp
; /* incore directory inode */
269 int error
; /* error return value */
270 int incr_isize
; /* total change in size */
271 int new_isize
; /* di_size after adding name */
272 int objchange
; /* changing to 8-byte inodes */
273 xfs_dir2_data_aoff_t offset
= 0; /* offset for new entry */
274 int pick
; /* which algorithm to use */
275 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
276 xfs_dir2_sf_entry_t
*sfep
= NULL
; /* shortform entry */
278 trace_xfs_dir2_sf_addname(args
);
280 ASSERT(xfs_dir2_sf_lookup(args
) == -ENOENT
);
282 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
284 * Make sure the shortform value has some of its header.
286 if (dp
->i_d
.di_size
< offsetof(xfs_dir2_sf_hdr_t
, parent
)) {
287 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
290 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
291 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
292 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
293 ASSERT(dp
->i_d
.di_size
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
295 * Compute entry (and change in) size.
297 incr_isize
= dp
->d_ops
->sf_entsize(sfp
, args
->namelen
);
301 * Do we have to change to 8 byte inodes?
303 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
&& sfp
->i8count
== 0) {
305 * Yes, adjust the inode size. old count + (parent + new)
307 incr_isize
+= (sfp
->count
+ 2) * XFS_INO64_DIFF
;
311 new_isize
= (int)dp
->i_d
.di_size
+ incr_isize
;
313 * Won't fit as shortform any more (due to size),
314 * or the pick routine says it won't (due to offset values).
316 if (new_isize
> XFS_IFORK_DSIZE(dp
) ||
318 xfs_dir2_sf_addname_pick(args
, objchange
, &sfep
, &offset
)) == 0) {
320 * Just checking or no space reservation, it doesn't fit.
322 if ((args
->op_flags
& XFS_DA_OP_JUSTCHECK
) || args
->total
== 0)
325 * Convert to block form then add the name.
327 error
= xfs_dir2_sf_to_block(args
);
330 return xfs_dir2_block_addname(args
);
333 * Just checking, it fits.
335 if (args
->op_flags
& XFS_DA_OP_JUSTCHECK
)
338 * Do it the easy way - just add it at the end.
341 xfs_dir2_sf_addname_easy(args
, sfep
, offset
, new_isize
);
343 * Do it the hard way - look for a place to insert the new entry.
344 * Convert to 8 byte inode numbers first if necessary.
349 xfs_dir2_sf_toino8(args
);
350 xfs_dir2_sf_addname_hard(args
, objchange
, new_isize
);
352 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
357 * Add the new entry the "easy" way.
358 * This is copying the old directory and adding the new entry at the end.
359 * Since it's sorted by "offset" we need room after the last offset
360 * that's already there, and then room to convert to a block directory.
361 * This is already checked by the pick routine.
364 xfs_dir2_sf_addname_easy(
365 xfs_da_args_t
*args
, /* operation arguments */
366 xfs_dir2_sf_entry_t
*sfep
, /* pointer to new entry */
367 xfs_dir2_data_aoff_t offset
, /* offset to use for new ent */
368 int new_isize
) /* new directory size */
370 int byteoff
; /* byte offset in sf dir */
371 xfs_inode_t
*dp
; /* incore directory inode */
372 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
376 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
377 byteoff
= (int)((char *)sfep
- (char *)sfp
);
379 * Grow the in-inode space.
381 xfs_idata_realloc(dp
, dp
->d_ops
->sf_entsize(sfp
, args
->namelen
),
384 * Need to set up again due to realloc of the inode data.
386 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
387 sfep
= (xfs_dir2_sf_entry_t
*)((char *)sfp
+ byteoff
);
389 * Fill in the new entry.
391 sfep
->namelen
= args
->namelen
;
392 xfs_dir2_sf_put_offset(sfep
, offset
);
393 memcpy(sfep
->name
, args
->name
, sfep
->namelen
);
394 dp
->d_ops
->sf_put_ino(sfp
, sfep
, args
->inumber
);
395 dp
->d_ops
->sf_put_ftype(sfep
, args
->filetype
);
398 * Update the header and inode.
401 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
)
403 dp
->i_d
.di_size
= new_isize
;
404 xfs_dir2_sf_check(args
);
408 * Add the new entry the "hard" way.
409 * The caller has already converted to 8 byte inode numbers if necessary,
410 * in which case we need to leave the i8count at 1.
411 * Find a hole that the new entry will fit into, and copy
412 * the first part of the entries, the new entry, and the last part of
417 xfs_dir2_sf_addname_hard(
418 xfs_da_args_t
*args
, /* operation arguments */
419 int objchange
, /* changing inode number size */
420 int new_isize
) /* new directory size */
422 int add_datasize
; /* data size need for new ent */
423 char *buf
; /* buffer for old */
424 xfs_inode_t
*dp
; /* incore directory inode */
425 int eof
; /* reached end of old dir */
426 int nbytes
; /* temp for byte copies */
427 xfs_dir2_data_aoff_t new_offset
; /* next offset value */
428 xfs_dir2_data_aoff_t offset
; /* current offset value */
429 int old_isize
; /* previous di_size */
430 xfs_dir2_sf_entry_t
*oldsfep
; /* entry in original dir */
431 xfs_dir2_sf_hdr_t
*oldsfp
; /* original shortform dir */
432 xfs_dir2_sf_entry_t
*sfep
; /* entry in new dir */
433 xfs_dir2_sf_hdr_t
*sfp
; /* new shortform dir */
436 * Copy the old directory to the stack buffer.
440 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
441 old_isize
= (int)dp
->i_d
.di_size
;
442 buf
= kmem_alloc(old_isize
, KM_SLEEP
);
443 oldsfp
= (xfs_dir2_sf_hdr_t
*)buf
;
444 memcpy(oldsfp
, sfp
, old_isize
);
446 * Loop over the old directory finding the place we're going
447 * to insert the new entry.
448 * If it's going to end up at the end then oldsfep will point there.
450 for (offset
= dp
->d_ops
->data_first_offset
,
451 oldsfep
= xfs_dir2_sf_firstentry(oldsfp
),
452 add_datasize
= dp
->d_ops
->data_entsize(args
->namelen
),
453 eof
= (char *)oldsfep
== &buf
[old_isize
];
455 offset
= new_offset
+ dp
->d_ops
->data_entsize(oldsfep
->namelen
),
456 oldsfep
= dp
->d_ops
->sf_nextentry(oldsfp
, oldsfep
),
457 eof
= (char *)oldsfep
== &buf
[old_isize
]) {
458 new_offset
= xfs_dir2_sf_get_offset(oldsfep
);
459 if (offset
+ add_datasize
<= new_offset
)
463 * Get rid of the old directory, then allocate space for
464 * the new one. We do this so xfs_idata_realloc won't copy
467 xfs_idata_realloc(dp
, -old_isize
, XFS_DATA_FORK
);
468 xfs_idata_realloc(dp
, new_isize
, XFS_DATA_FORK
);
470 * Reset the pointer since the buffer was reallocated.
472 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
474 * Copy the first part of the directory, including the header.
476 nbytes
= (int)((char *)oldsfep
- (char *)oldsfp
);
477 memcpy(sfp
, oldsfp
, nbytes
);
478 sfep
= (xfs_dir2_sf_entry_t
*)((char *)sfp
+ nbytes
);
480 * Fill in the new entry, and update the header counts.
482 sfep
->namelen
= args
->namelen
;
483 xfs_dir2_sf_put_offset(sfep
, offset
);
484 memcpy(sfep
->name
, args
->name
, sfep
->namelen
);
485 dp
->d_ops
->sf_put_ino(sfp
, sfep
, args
->inumber
);
486 dp
->d_ops
->sf_put_ftype(sfep
, args
->filetype
);
488 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
&& !objchange
)
491 * If there's more left to copy, do that.
494 sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
);
495 memcpy(sfep
, oldsfep
, old_isize
- nbytes
);
498 dp
->i_d
.di_size
= new_isize
;
499 xfs_dir2_sf_check(args
);
503 * Decide if the new entry will fit at all.
504 * If it will fit, pick between adding the new entry to the end (easy)
505 * or somewhere else (hard).
506 * Return 0 (won't fit), 1 (easy), 2 (hard).
509 static int /* pick result */
510 xfs_dir2_sf_addname_pick(
511 xfs_da_args_t
*args
, /* operation arguments */
512 int objchange
, /* inode # size changes */
513 xfs_dir2_sf_entry_t
**sfepp
, /* out(1): new entry ptr */
514 xfs_dir2_data_aoff_t
*offsetp
) /* out(1): new offset */
516 xfs_inode_t
*dp
; /* incore directory inode */
517 int holefit
; /* found hole it will fit in */
518 int i
; /* entry number */
519 xfs_dir2_data_aoff_t offset
; /* data block offset */
520 xfs_dir2_sf_entry_t
*sfep
; /* shortform entry */
521 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
522 int size
; /* entry's data size */
523 int used
; /* data bytes used */
527 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
528 size
= dp
->d_ops
->data_entsize(args
->namelen
);
529 offset
= dp
->d_ops
->data_first_offset
;
530 sfep
= xfs_dir2_sf_firstentry(sfp
);
533 * Loop over sf entries.
534 * Keep track of data offset and whether we've seen a place
535 * to insert the new entry.
537 for (i
= 0; i
< sfp
->count
; i
++) {
539 holefit
= offset
+ size
<= xfs_dir2_sf_get_offset(sfep
);
540 offset
= xfs_dir2_sf_get_offset(sfep
) +
541 dp
->d_ops
->data_entsize(sfep
->namelen
);
542 sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
);
545 * Calculate data bytes used excluding the new entry, if this
546 * was a data block (block form directory).
549 (sfp
->count
+ 3) * (uint
)sizeof(xfs_dir2_leaf_entry_t
) +
550 (uint
)sizeof(xfs_dir2_block_tail_t
);
552 * If it won't fit in a block form then we can't insert it,
553 * we'll go back, convert to block, then try the insert and convert
556 if (used
+ (holefit
? 0 : size
) > args
->geo
->blksize
)
559 * If changing the inode number size, do it the hard way.
564 * If it won't fit at the end then do it the hard way (use the hole).
566 if (used
+ size
> args
->geo
->blksize
)
569 * Do it the easy way.
578 * Check consistency of shortform directory, assert if bad.
582 xfs_da_args_t
*args
) /* operation arguments */
584 xfs_inode_t
*dp
; /* incore directory inode */
585 int i
; /* entry number */
586 int i8count
; /* number of big inode#s */
587 xfs_ino_t ino
; /* entry inode number */
588 int offset
; /* data offset */
589 xfs_dir2_sf_entry_t
*sfep
; /* shortform dir entry */
590 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
594 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
595 offset
= dp
->d_ops
->data_first_offset
;
596 ino
= dp
->d_ops
->sf_get_parent_ino(sfp
);
597 i8count
= ino
> XFS_DIR2_MAX_SHORT_INUM
;
599 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
);
601 i
++, sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
)) {
602 ASSERT(xfs_dir2_sf_get_offset(sfep
) >= offset
);
603 ino
= dp
->d_ops
->sf_get_ino(sfp
, sfep
);
604 i8count
+= ino
> XFS_DIR2_MAX_SHORT_INUM
;
606 xfs_dir2_sf_get_offset(sfep
) +
607 dp
->d_ops
->data_entsize(sfep
->namelen
);
608 ASSERT(dp
->d_ops
->sf_get_ftype(sfep
) < XFS_DIR3_FT_MAX
);
610 ASSERT(i8count
== sfp
->i8count
);
611 ASSERT((char *)sfep
- (char *)sfp
== dp
->i_d
.di_size
);
613 (sfp
->count
+ 2) * (uint
)sizeof(xfs_dir2_leaf_entry_t
) +
614 (uint
)sizeof(xfs_dir2_block_tail_t
) <= args
->geo
->blksize
);
618 /* Verify the consistency of an inline directory. */
621 struct xfs_inode
*ip
)
623 struct xfs_mount
*mp
= ip
->i_mount
;
624 struct xfs_dir2_sf_hdr
*sfp
;
625 struct xfs_dir2_sf_entry
*sfep
;
626 struct xfs_dir2_sf_entry
*next_sfep
;
628 const struct xfs_dir_ops
*dops
;
629 struct xfs_ifork
*ifp
;
638 ASSERT(ip
->i_d
.di_format
== XFS_DINODE_FMT_LOCAL
);
640 * xfs_iread calls us before xfs_setup_inode sets up ip->d_ops,
641 * so we can only trust the mountpoint to have the right pointer.
643 dops
= xfs_dir_get_ops(mp
, NULL
);
645 ifp
= XFS_IFORK_PTR(ip
, XFS_DATA_FORK
);
646 sfp
= (struct xfs_dir2_sf_hdr
*)ifp
->if_u1
.if_data
;
647 size
= ifp
->if_bytes
;
650 * Give up if the directory is way too short.
652 if (size
<= offsetof(struct xfs_dir2_sf_hdr
, parent
) ||
653 size
< xfs_dir2_sf_hdr_size(sfp
->i8count
))
654 return __this_address
;
656 endp
= (char *)sfp
+ size
;
659 ino
= dops
->sf_get_parent_ino(sfp
);
660 i8count
= ino
> XFS_DIR2_MAX_SHORT_INUM
;
661 error
= xfs_dir_ino_validate(mp
, ino
);
663 return __this_address
;
664 offset
= dops
->data_first_offset
;
666 /* Check all reported entries */
667 sfep
= xfs_dir2_sf_firstentry(sfp
);
668 for (i
= 0; i
< sfp
->count
; i
++) {
670 * struct xfs_dir2_sf_entry has a variable length.
671 * Check the fixed-offset parts of the structure are
672 * within the data buffer.
674 if (((char *)sfep
+ sizeof(*sfep
)) >= endp
)
675 return __this_address
;
677 /* Don't allow names with known bad length. */
678 if (sfep
->namelen
== 0)
679 return __this_address
;
682 * Check that the variable-length part of the structure is
683 * within the data buffer. The next entry starts after the
684 * name component, so nextentry is an acceptable test.
686 next_sfep
= dops
->sf_nextentry(sfp
, sfep
);
687 if (endp
< (char *)next_sfep
)
688 return __this_address
;
690 /* Check that the offsets always increase. */
691 if (xfs_dir2_sf_get_offset(sfep
) < offset
)
692 return __this_address
;
694 /* Check the inode number. */
695 ino
= dops
->sf_get_ino(sfp
, sfep
);
696 i8count
+= ino
> XFS_DIR2_MAX_SHORT_INUM
;
697 error
= xfs_dir_ino_validate(mp
, ino
);
699 return __this_address
;
701 /* Check the file type. */
702 filetype
= dops
->sf_get_ftype(sfep
);
703 if (filetype
>= XFS_DIR3_FT_MAX
)
704 return __this_address
;
706 offset
= xfs_dir2_sf_get_offset(sfep
) +
707 dops
->data_entsize(sfep
->namelen
);
711 if (i8count
!= sfp
->i8count
)
712 return __this_address
;
713 if ((void *)sfep
!= (void *)endp
)
714 return __this_address
;
716 /* Make sure this whole thing ought to be in local format. */
717 if (offset
+ (sfp
->count
+ 2) * (uint
)sizeof(xfs_dir2_leaf_entry_t
) +
718 (uint
)sizeof(xfs_dir2_block_tail_t
) > mp
->m_dir_geo
->blksize
)
719 return __this_address
;
725 * Create a new (shortform) directory.
727 int /* error, always 0 */
729 xfs_da_args_t
*args
, /* operation arguments */
730 xfs_ino_t pino
) /* parent inode number */
732 xfs_inode_t
*dp
; /* incore directory inode */
733 int i8count
; /* parent inode is an 8-byte number */
734 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
735 int size
; /* directory size */
737 trace_xfs_dir2_sf_create(args
);
742 ASSERT(dp
->i_d
.di_size
== 0);
744 * If it's currently a zero-length extent file,
745 * convert it to local format.
747 if (dp
->i_d
.di_format
== XFS_DINODE_FMT_EXTENTS
) {
748 dp
->i_df
.if_flags
&= ~XFS_IFEXTENTS
; /* just in case */
749 dp
->i_d
.di_format
= XFS_DINODE_FMT_LOCAL
;
750 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
);
751 dp
->i_df
.if_flags
|= XFS_IFINLINE
;
753 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
754 ASSERT(dp
->i_df
.if_bytes
== 0);
755 i8count
= pino
> XFS_DIR2_MAX_SHORT_INUM
;
756 size
= xfs_dir2_sf_hdr_size(i8count
);
758 * Make a buffer for the data.
760 xfs_idata_realloc(dp
, size
, XFS_DATA_FORK
);
762 * Fill in the header,
764 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
765 sfp
->i8count
= i8count
;
767 * Now can put in the inode number, since i8count is set.
769 dp
->d_ops
->sf_put_parent_ino(sfp
, pino
);
771 dp
->i_d
.di_size
= size
;
772 xfs_dir2_sf_check(args
);
773 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
778 * Lookup an entry in a shortform directory.
779 * Returns EEXIST if found, ENOENT if not found.
783 xfs_da_args_t
*args
) /* operation arguments */
785 xfs_inode_t
*dp
; /* incore directory inode */
786 int i
; /* entry index */
788 xfs_dir2_sf_entry_t
*sfep
; /* shortform directory entry */
789 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
790 enum xfs_dacmp cmp
; /* comparison result */
791 xfs_dir2_sf_entry_t
*ci_sfep
; /* case-insens. entry */
793 trace_xfs_dir2_sf_lookup(args
);
795 xfs_dir2_sf_check(args
);
798 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
800 * Bail out if the directory is way too short.
802 if (dp
->i_d
.di_size
< offsetof(xfs_dir2_sf_hdr_t
, parent
)) {
803 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
806 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
807 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
808 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
809 ASSERT(dp
->i_d
.di_size
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
813 if (args
->namelen
== 1 && args
->name
[0] == '.') {
814 args
->inumber
= dp
->i_ino
;
815 args
->cmpresult
= XFS_CMP_EXACT
;
816 args
->filetype
= XFS_DIR3_FT_DIR
;
820 * Special case for ..
822 if (args
->namelen
== 2 &&
823 args
->name
[0] == '.' && args
->name
[1] == '.') {
824 args
->inumber
= dp
->d_ops
->sf_get_parent_ino(sfp
);
825 args
->cmpresult
= XFS_CMP_EXACT
;
826 args
->filetype
= XFS_DIR3_FT_DIR
;
830 * Loop over all the entries trying to match ours.
833 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
); i
< sfp
->count
;
834 i
++, sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
)) {
836 * Compare name and if it's an exact match, return the inode
837 * number. If it's the first case-insensitive match, store the
838 * inode number and continue looking for an exact match.
840 cmp
= dp
->i_mount
->m_dirnameops
->compname(args
, sfep
->name
,
842 if (cmp
!= XFS_CMP_DIFFERENT
&& cmp
!= args
->cmpresult
) {
843 args
->cmpresult
= cmp
;
844 args
->inumber
= dp
->d_ops
->sf_get_ino(sfp
, sfep
);
845 args
->filetype
= dp
->d_ops
->sf_get_ftype(sfep
);
846 if (cmp
== XFS_CMP_EXACT
)
851 ASSERT(args
->op_flags
& XFS_DA_OP_OKNOENT
);
853 * Here, we can only be doing a lookup (not a rename or replace).
854 * If a case-insensitive match was not found, return -ENOENT.
858 /* otherwise process the CI match as required by the caller */
859 error
= xfs_dir_cilookup_result(args
, ci_sfep
->name
, ci_sfep
->namelen
);
864 * Remove an entry from a shortform directory.
867 xfs_dir2_sf_removename(
870 int byteoff
; /* offset of removed entry */
871 xfs_inode_t
*dp
; /* incore directory inode */
872 int entsize
; /* this entry's size */
873 int i
; /* shortform entry index */
874 int newsize
; /* new inode size */
875 int oldsize
; /* old inode size */
876 xfs_dir2_sf_entry_t
*sfep
; /* shortform directory entry */
877 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
879 trace_xfs_dir2_sf_removename(args
);
883 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
884 oldsize
= (int)dp
->i_d
.di_size
;
886 * Bail out if the directory is way too short.
888 if (oldsize
< offsetof(xfs_dir2_sf_hdr_t
, parent
)) {
889 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
892 ASSERT(dp
->i_df
.if_bytes
== oldsize
);
893 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
894 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
895 ASSERT(oldsize
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
897 * Loop over the old directory entries.
898 * Find the one we're deleting.
900 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
); i
< sfp
->count
;
901 i
++, sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
)) {
902 if (xfs_da_compname(args
, sfep
->name
, sfep
->namelen
) ==
904 ASSERT(dp
->d_ops
->sf_get_ino(sfp
, sfep
) ==
917 byteoff
= (int)((char *)sfep
- (char *)sfp
);
918 entsize
= dp
->d_ops
->sf_entsize(sfp
, args
->namelen
);
919 newsize
= oldsize
- entsize
;
921 * Copy the part if any after the removed entry, sliding it down.
923 if (byteoff
+ entsize
< oldsize
)
924 memmove((char *)sfp
+ byteoff
, (char *)sfp
+ byteoff
+ entsize
,
925 oldsize
- (byteoff
+ entsize
));
927 * Fix up the header and file size.
930 dp
->i_d
.di_size
= newsize
;
932 * Reallocate, making it smaller.
934 xfs_idata_realloc(dp
, newsize
- oldsize
, XFS_DATA_FORK
);
935 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
937 * Are we changing inode number size?
939 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
) {
940 if (sfp
->i8count
== 1)
941 xfs_dir2_sf_toino4(args
);
945 xfs_dir2_sf_check(args
);
946 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
951 * Replace the inode number of an entry in a shortform directory.
955 xfs_da_args_t
*args
) /* operation arguments */
957 xfs_inode_t
*dp
; /* incore directory inode */
958 int i
; /* entry index */
959 xfs_ino_t ino
=0; /* entry old inode number */
960 int i8elevated
; /* sf_toino8 set i8count=1 */
961 xfs_dir2_sf_entry_t
*sfep
; /* shortform directory entry */
962 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
964 trace_xfs_dir2_sf_replace(args
);
968 ASSERT(dp
->i_df
.if_flags
& XFS_IFINLINE
);
970 * Bail out if the shortform directory is way too small.
972 if (dp
->i_d
.di_size
< offsetof(xfs_dir2_sf_hdr_t
, parent
)) {
973 ASSERT(XFS_FORCED_SHUTDOWN(dp
->i_mount
));
976 ASSERT(dp
->i_df
.if_bytes
== dp
->i_d
.di_size
);
977 ASSERT(dp
->i_df
.if_u1
.if_data
!= NULL
);
978 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
979 ASSERT(dp
->i_d
.di_size
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
982 * New inode number is large, and need to convert to 8-byte inodes.
984 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
&& sfp
->i8count
== 0) {
985 int error
; /* error return value */
986 int newsize
; /* new inode size */
988 newsize
= dp
->i_df
.if_bytes
+ (sfp
->count
+ 1) * XFS_INO64_DIFF
;
990 * Won't fit as shortform, convert to block then do replace.
992 if (newsize
> XFS_IFORK_DSIZE(dp
)) {
993 error
= xfs_dir2_sf_to_block(args
);
997 return xfs_dir2_block_replace(args
);
1000 * Still fits, convert to 8-byte now.
1002 xfs_dir2_sf_toino8(args
);
1004 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
1008 ASSERT(args
->namelen
!= 1 || args
->name
[0] != '.');
1010 * Replace ..'s entry.
1012 if (args
->namelen
== 2 &&
1013 args
->name
[0] == '.' && args
->name
[1] == '.') {
1014 ino
= dp
->d_ops
->sf_get_parent_ino(sfp
);
1015 ASSERT(args
->inumber
!= ino
);
1016 dp
->d_ops
->sf_put_parent_ino(sfp
, args
->inumber
);
1019 * Normal entry, look for the name.
1022 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
); i
< sfp
->count
;
1023 i
++, sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
)) {
1024 if (xfs_da_compname(args
, sfep
->name
, sfep
->namelen
) ==
1026 ino
= dp
->d_ops
->sf_get_ino(sfp
, sfep
);
1027 ASSERT(args
->inumber
!= ino
);
1028 dp
->d_ops
->sf_put_ino(sfp
, sfep
, args
->inumber
);
1029 dp
->d_ops
->sf_put_ftype(sfep
, args
->filetype
);
1036 if (i
== sfp
->count
) {
1037 ASSERT(args
->op_flags
& XFS_DA_OP_OKNOENT
);
1039 xfs_dir2_sf_toino4(args
);
1044 * See if the old number was large, the new number is small.
1046 if (ino
> XFS_DIR2_MAX_SHORT_INUM
&&
1047 args
->inumber
<= XFS_DIR2_MAX_SHORT_INUM
) {
1049 * And the old count was one, so need to convert to small.
1051 if (sfp
->i8count
== 1)
1052 xfs_dir2_sf_toino4(args
);
1057 * See if the old number was small, the new number is large.
1059 if (ino
<= XFS_DIR2_MAX_SHORT_INUM
&&
1060 args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
) {
1062 * add to the i8count unless we just converted to 8-byte
1063 * inodes (which does an implied i8count = 1)
1065 ASSERT(sfp
->i8count
!= 0);
1069 xfs_dir2_sf_check(args
);
1070 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_DDATA
);
1075 * Convert from 8-byte inode numbers to 4-byte inode numbers.
1076 * The last 8-byte inode number is gone, but the count is still 1.
1080 xfs_da_args_t
*args
) /* operation arguments */
1082 char *buf
; /* old dir's buffer */
1083 xfs_inode_t
*dp
; /* incore directory inode */
1084 int i
; /* entry index */
1085 int newsize
; /* new inode size */
1086 xfs_dir2_sf_entry_t
*oldsfep
; /* old sf entry */
1087 xfs_dir2_sf_hdr_t
*oldsfp
; /* old sf directory */
1088 int oldsize
; /* old inode size */
1089 xfs_dir2_sf_entry_t
*sfep
; /* new sf entry */
1090 xfs_dir2_sf_hdr_t
*sfp
; /* new sf directory */
1092 trace_xfs_dir2_sf_toino4(args
);
1097 * Copy the old directory to the buffer.
1098 * Then nuke it from the inode, and add the new buffer to the inode.
1099 * Don't want xfs_idata_realloc copying the data here.
1101 oldsize
= dp
->i_df
.if_bytes
;
1102 buf
= kmem_alloc(oldsize
, KM_SLEEP
);
1103 oldsfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
1104 ASSERT(oldsfp
->i8count
== 1);
1105 memcpy(buf
, oldsfp
, oldsize
);
1107 * Compute the new inode size.
1109 newsize
= oldsize
- (oldsfp
->count
+ 1) * XFS_INO64_DIFF
;
1110 xfs_idata_realloc(dp
, -oldsize
, XFS_DATA_FORK
);
1111 xfs_idata_realloc(dp
, newsize
, XFS_DATA_FORK
);
1113 * Reset our pointers, the data has moved.
1115 oldsfp
= (xfs_dir2_sf_hdr_t
*)buf
;
1116 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
1118 * Fill in the new header.
1120 sfp
->count
= oldsfp
->count
;
1122 dp
->d_ops
->sf_put_parent_ino(sfp
, dp
->d_ops
->sf_get_parent_ino(oldsfp
));
1124 * Copy the entries field by field.
1126 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
),
1127 oldsfep
= xfs_dir2_sf_firstentry(oldsfp
);
1129 i
++, sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
),
1130 oldsfep
= dp
->d_ops
->sf_nextentry(oldsfp
, oldsfep
)) {
1131 sfep
->namelen
= oldsfep
->namelen
;
1132 memcpy(sfep
->offset
, oldsfep
->offset
, sizeof(sfep
->offset
));
1133 memcpy(sfep
->name
, oldsfep
->name
, sfep
->namelen
);
1134 dp
->d_ops
->sf_put_ino(sfp
, sfep
,
1135 dp
->d_ops
->sf_get_ino(oldsfp
, oldsfep
));
1136 dp
->d_ops
->sf_put_ftype(sfep
, dp
->d_ops
->sf_get_ftype(oldsfep
));
1139 * Clean up the inode.
1142 dp
->i_d
.di_size
= newsize
;
1143 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
1147 * Convert existing entries from 4-byte inode numbers to 8-byte inode numbers.
1148 * The new entry w/ an 8-byte inode number is not there yet; we leave with
1149 * i8count set to 1, but no corresponding 8-byte entry.
1153 xfs_da_args_t
*args
) /* operation arguments */
1155 char *buf
; /* old dir's buffer */
1156 xfs_inode_t
*dp
; /* incore directory inode */
1157 int i
; /* entry index */
1158 int newsize
; /* new inode size */
1159 xfs_dir2_sf_entry_t
*oldsfep
; /* old sf entry */
1160 xfs_dir2_sf_hdr_t
*oldsfp
; /* old sf directory */
1161 int oldsize
; /* old inode size */
1162 xfs_dir2_sf_entry_t
*sfep
; /* new sf entry */
1163 xfs_dir2_sf_hdr_t
*sfp
; /* new sf directory */
1165 trace_xfs_dir2_sf_toino8(args
);
1170 * Copy the old directory to the buffer.
1171 * Then nuke it from the inode, and add the new buffer to the inode.
1172 * Don't want xfs_idata_realloc copying the data here.
1174 oldsize
= dp
->i_df
.if_bytes
;
1175 buf
= kmem_alloc(oldsize
, KM_SLEEP
);
1176 oldsfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
1177 ASSERT(oldsfp
->i8count
== 0);
1178 memcpy(buf
, oldsfp
, oldsize
);
1180 * Compute the new inode size (nb: entry count + 1 for parent)
1182 newsize
= oldsize
+ (oldsfp
->count
+ 1) * XFS_INO64_DIFF
;
1183 xfs_idata_realloc(dp
, -oldsize
, XFS_DATA_FORK
);
1184 xfs_idata_realloc(dp
, newsize
, XFS_DATA_FORK
);
1186 * Reset our pointers, the data has moved.
1188 oldsfp
= (xfs_dir2_sf_hdr_t
*)buf
;
1189 sfp
= (xfs_dir2_sf_hdr_t
*)dp
->i_df
.if_u1
.if_data
;
1191 * Fill in the new header.
1193 sfp
->count
= oldsfp
->count
;
1195 dp
->d_ops
->sf_put_parent_ino(sfp
, dp
->d_ops
->sf_get_parent_ino(oldsfp
));
1197 * Copy the entries field by field.
1199 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
),
1200 oldsfep
= xfs_dir2_sf_firstentry(oldsfp
);
1202 i
++, sfep
= dp
->d_ops
->sf_nextentry(sfp
, sfep
),
1203 oldsfep
= dp
->d_ops
->sf_nextentry(oldsfp
, oldsfep
)) {
1204 sfep
->namelen
= oldsfep
->namelen
;
1205 memcpy(sfep
->offset
, oldsfep
->offset
, sizeof(sfep
->offset
));
1206 memcpy(sfep
->name
, oldsfep
->name
, sfep
->namelen
);
1207 dp
->d_ops
->sf_put_ino(sfp
, sfep
,
1208 dp
->d_ops
->sf_get_ino(oldsfp
, oldsfep
));
1209 dp
->d_ops
->sf_put_ftype(sfep
, dp
->d_ops
->sf_get_ftype(oldsfep
));
1212 * Clean up the inode.
1215 dp
->i_d
.di_size
= newsize
;
1216 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);