1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_mount.h"
13 #include "xfs_inode.h"
14 #include "xfs_trans.h"
16 #include "xfs_dir2_priv.h"
17 #include "xfs_trace.h"
20 * Prototypes for internal functions.
22 static void xfs_dir2_sf_addname_easy(xfs_da_args_t
*args
,
23 xfs_dir2_sf_entry_t
*sfep
,
24 xfs_dir2_data_aoff_t offset
,
26 static void xfs_dir2_sf_addname_hard(xfs_da_args_t
*args
, int objchange
,
28 static int xfs_dir2_sf_addname_pick(xfs_da_args_t
*args
, int objchange
,
29 xfs_dir2_sf_entry_t
**sfepp
,
30 xfs_dir2_data_aoff_t
*offsetp
);
32 static void xfs_dir2_sf_check(xfs_da_args_t
*args
);
34 #define xfs_dir2_sf_check(args)
37 static void xfs_dir2_sf_toino4(xfs_da_args_t
*args
);
38 static void xfs_dir2_sf_toino8(xfs_da_args_t
*args
);
43 struct xfs_dir2_sf_hdr
*hdr
,
48 count
+= sizeof(struct xfs_dir2_sf_entry
); /* namelen + offset */
49 count
+= hdr
->i8count
? XFS_INO64_SIZE
: XFS_INO32_SIZE
; /* ino # */
51 if (xfs_has_ftype(mp
))
52 count
+= sizeof(uint8_t);
56 struct xfs_dir2_sf_entry
*
57 xfs_dir2_sf_nextentry(
59 struct xfs_dir2_sf_hdr
*hdr
,
60 struct xfs_dir2_sf_entry
*sfep
)
62 return (void *)sfep
+ xfs_dir2_sf_entsize(mp
, hdr
, sfep
->namelen
);
66 * In short-form directory entries the inode numbers are stored at variable
67 * offset behind the entry name. If the entry stores a filetype value, then it
68 * sits between the name and the inode number. The actual inode numbers can
69 * come in two formats as well, either 4 bytes or 8 bytes wide.
74 struct xfs_dir2_sf_hdr
*hdr
,
75 struct xfs_dir2_sf_entry
*sfep
)
77 uint8_t *from
= sfep
->name
+ sfep
->namelen
;
79 if (xfs_has_ftype(mp
))
83 return get_unaligned_be32(from
);
84 return get_unaligned_be64(from
) & XFS_MAXINUMBER
;
90 struct xfs_dir2_sf_hdr
*hdr
,
91 struct xfs_dir2_sf_entry
*sfep
,
94 uint8_t *to
= sfep
->name
+ sfep
->namelen
;
96 ASSERT(ino
<= XFS_MAXINUMBER
);
98 if (xfs_has_ftype(mp
))
102 put_unaligned_be64(ino
, to
);
104 put_unaligned_be32(ino
, to
);
108 xfs_dir2_sf_get_parent_ino(
109 struct xfs_dir2_sf_hdr
*hdr
)
112 return get_unaligned_be32(hdr
->parent
);
113 return get_unaligned_be64(hdr
->parent
) & XFS_MAXINUMBER
;
117 xfs_dir2_sf_put_parent_ino(
118 struct xfs_dir2_sf_hdr
*hdr
,
121 ASSERT(ino
<= XFS_MAXINUMBER
);
124 put_unaligned_be64(ino
, hdr
->parent
);
126 put_unaligned_be32(ino
, hdr
->parent
);
130 * The file type field is stored at the end of the name for filetype enabled
131 * shortform directories, or not at all otherwise.
134 xfs_dir2_sf_get_ftype(
135 struct xfs_mount
*mp
,
136 struct xfs_dir2_sf_entry
*sfep
)
138 if (xfs_has_ftype(mp
)) {
139 uint8_t ftype
= sfep
->name
[sfep
->namelen
];
141 if (ftype
< XFS_DIR3_FT_MAX
)
145 return XFS_DIR3_FT_UNKNOWN
;
149 xfs_dir2_sf_put_ftype(
150 struct xfs_mount
*mp
,
151 struct xfs_dir2_sf_entry
*sfep
,
154 ASSERT(ftype
< XFS_DIR3_FT_MAX
);
156 if (xfs_has_ftype(mp
))
157 sfep
->name
[sfep
->namelen
] = ftype
;
161 * Given a block directory (dp/block), calculate its size as a shortform (sf)
162 * directory and a header for the sf directory, if it will fit it the
163 * space currently present in the inode. If it won't fit, the output
164 * size is too big (but not accurate).
166 int /* size for sf form */
167 xfs_dir2_block_sfsize(
168 xfs_inode_t
*dp
, /* incore inode pointer */
169 xfs_dir2_data_hdr_t
*hdr
, /* block directory data */
170 xfs_dir2_sf_hdr_t
*sfhp
) /* output: header for sf form */
172 xfs_dir2_dataptr_t addr
; /* data entry address */
173 xfs_dir2_leaf_entry_t
*blp
; /* leaf area of the block */
174 xfs_dir2_block_tail_t
*btp
; /* tail area of the block */
175 int count
; /* shortform entry count */
176 xfs_dir2_data_entry_t
*dep
; /* data entry in the block */
177 int i
; /* block entry index */
178 int i8count
; /* count of big-inode entries */
179 int isdot
; /* entry is "." */
180 int isdotdot
; /* entry is ".." */
181 xfs_mount_t
*mp
; /* mount structure pointer */
182 int namelen
; /* total name bytes */
183 xfs_ino_t parent
= 0; /* parent inode number */
184 int size
=0; /* total computed size */
186 struct xfs_da_geometry
*geo
;
192 * if there is a filetype field, add the extra byte to the namelen
193 * for each entry that we see.
195 has_ftype
= xfs_has_ftype(mp
) ? 1 : 0;
197 count
= i8count
= namelen
= 0;
198 btp
= xfs_dir2_block_tail_p(geo
, hdr
);
199 blp
= xfs_dir2_block_leaf_p(btp
);
202 * Iterate over the block's data entries by using the leaf pointers.
204 for (i
= 0; i
< be32_to_cpu(btp
->count
); i
++) {
205 if ((addr
= be32_to_cpu(blp
[i
].address
)) == XFS_DIR2_NULL_DATAPTR
)
208 * Calculate the pointer to the entry at hand.
210 dep
= (xfs_dir2_data_entry_t
*)((char *)hdr
+
211 xfs_dir2_dataptr_to_off(geo
, addr
));
213 * Detect . and .., so we can special-case them.
214 * . is not included in sf directories.
215 * .. is included by just the parent inode number.
217 isdot
= dep
->namelen
== 1 && dep
->name
[0] == '.';
220 dep
->name
[0] == '.' && dep
->name
[1] == '.';
223 i8count
+= be64_to_cpu(dep
->inumber
) > XFS_DIR2_MAX_SHORT_INUM
;
225 /* take into account the file type field */
226 if (!isdot
&& !isdotdot
) {
228 namelen
+= dep
->namelen
+ has_ftype
;
230 parent
= be64_to_cpu(dep
->inumber
);
232 * Calculate the new size, see if we should give up yet.
234 size
= xfs_dir2_sf_hdr_size(i8count
) + /* header */
235 count
* 3 * sizeof(u8
) + /* namelen + offset */
237 (i8count
? /* inumber */
238 count
* XFS_INO64_SIZE
:
239 count
* XFS_INO32_SIZE
);
240 if (size
> xfs_inode_data_fork_size(dp
))
241 return size
; /* size value is a failure */
244 * Create the output header, if it worked.
247 sfhp
->i8count
= i8count
;
248 xfs_dir2_sf_put_parent_ino(sfhp
, parent
);
253 * Convert a block format directory to shortform.
254 * Caller has already checked that it will fit, and built us a header.
257 xfs_dir2_block_to_sf(
258 struct xfs_da_args
*args
, /* operation arguments */
260 int size
, /* shortform directory size */
261 struct xfs_dir2_sf_hdr
*sfhp
) /* shortform directory hdr */
263 struct xfs_inode
*dp
= args
->dp
;
264 struct xfs_mount
*mp
= dp
->i_mount
;
265 int error
; /* error return value */
266 int logflags
; /* inode logging flags */
267 struct xfs_dir2_sf_entry
*sfep
; /* shortform entry */
268 struct xfs_dir2_sf_hdr
*sfp
; /* shortform directory header */
269 unsigned int offset
= args
->geo
->data_entry_offset
;
272 trace_xfs_dir2_block_to_sf(args
);
275 * Allocate a temporary destination buffer the size of the inode to
276 * format the data into. Once we have formatted the data, we can free
277 * the block and copy the formatted data into the inode literal area.
279 sfp
= kmalloc(mp
->m_sb
.sb_inodesize
, GFP_KERNEL
| __GFP_NOFAIL
);
280 memcpy(sfp
, sfhp
, xfs_dir2_sf_hdr_size(sfhp
->i8count
));
283 * Loop over the active and unused entries. Stop when we reach the
284 * leaf/tail portion of the block.
286 end
= xfs_dir3_data_end_offset(args
->geo
, bp
->b_addr
);
287 sfep
= xfs_dir2_sf_firstentry(sfp
);
288 while (offset
< end
) {
289 struct xfs_dir2_data_unused
*dup
= bp
->b_addr
+ offset
;
290 struct xfs_dir2_data_entry
*dep
= bp
->b_addr
+ offset
;
293 * If it's unused, just skip over it.
295 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
) {
296 offset
+= be16_to_cpu(dup
->length
);
303 if (dep
->namelen
== 1 && dep
->name
[0] == '.')
304 ASSERT(be64_to_cpu(dep
->inumber
) == dp
->i_ino
);
306 * Skip .., but make sure the inode number is right.
308 else if (dep
->namelen
== 2 &&
309 dep
->name
[0] == '.' && dep
->name
[1] == '.')
310 ASSERT(be64_to_cpu(dep
->inumber
) ==
311 xfs_dir2_sf_get_parent_ino(sfp
));
313 * Normal entry, copy it into shortform.
316 sfep
->namelen
= dep
->namelen
;
317 xfs_dir2_sf_put_offset(sfep
, offset
);
318 memcpy(sfep
->name
, dep
->name
, dep
->namelen
);
319 xfs_dir2_sf_put_ino(mp
, sfp
, sfep
,
320 be64_to_cpu(dep
->inumber
));
321 xfs_dir2_sf_put_ftype(mp
, sfep
,
322 xfs_dir2_data_get_ftype(mp
, dep
));
324 sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
);
326 offset
+= xfs_dir2_data_entsize(mp
, dep
->namelen
);
328 ASSERT((char *)sfep
- (char *)sfp
== size
);
330 /* now we are done with the block, we can shrink the inode */
331 logflags
= XFS_ILOG_CORE
;
332 error
= xfs_dir2_shrink_inode(args
, args
->geo
->datablk
, bp
);
334 ASSERT(error
!= -ENOSPC
);
339 * The buffer is now unconditionally gone, whether
340 * xfs_dir2_shrink_inode worked or not.
342 * Convert the inode to local format and copy the data in.
344 ASSERT(dp
->i_df
.if_bytes
== 0);
345 xfs_init_local_fork(dp
, XFS_DATA_FORK
, sfp
, size
);
346 dp
->i_df
.if_format
= XFS_DINODE_FMT_LOCAL
;
347 dp
->i_disk_size
= size
;
349 logflags
|= XFS_ILOG_DDATA
;
350 xfs_dir2_sf_check(args
);
352 xfs_trans_log_inode(args
->trans
, dp
, logflags
);
358 * Add a name to a shortform directory.
359 * There are two algorithms, "easy" and "hard" which we decide on
360 * before changing anything.
361 * Convert to block form if necessary, if the new entry won't fit.
365 xfs_da_args_t
*args
) /* operation arguments */
367 struct xfs_inode
*dp
= args
->dp
;
368 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
369 int error
; /* error return value */
370 int incr_isize
; /* total change in size */
371 int new_isize
; /* size after adding name */
372 int objchange
; /* changing to 8-byte inodes */
373 xfs_dir2_data_aoff_t offset
= 0; /* offset for new entry */
374 int pick
; /* which algorithm to use */
375 xfs_dir2_sf_entry_t
*sfep
= NULL
; /* shortform entry */
377 trace_xfs_dir2_sf_addname(args
);
379 ASSERT(xfs_dir2_sf_lookup(args
) == -ENOENT
);
380 ASSERT(dp
->i_df
.if_format
== XFS_DINODE_FMT_LOCAL
);
381 ASSERT(dp
->i_disk_size
>= offsetof(struct xfs_dir2_sf_hdr
, parent
));
382 ASSERT(dp
->i_df
.if_bytes
== dp
->i_disk_size
);
384 ASSERT(dp
->i_disk_size
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
386 * Compute entry (and change in) size.
388 incr_isize
= xfs_dir2_sf_entsize(dp
->i_mount
, sfp
, args
->namelen
);
392 * Do we have to change to 8 byte inodes?
394 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
&& sfp
->i8count
== 0) {
396 * Yes, adjust the inode size. old count + (parent + new)
398 incr_isize
+= (sfp
->count
+ 2) * XFS_INO64_DIFF
;
402 new_isize
= (int)dp
->i_disk_size
+ incr_isize
;
404 * Won't fit as shortform any more (due to size),
405 * or the pick routine says it won't (due to offset values).
407 if (new_isize
> xfs_inode_data_fork_size(dp
) ||
409 xfs_dir2_sf_addname_pick(args
, objchange
, &sfep
, &offset
)) == 0) {
411 * Just checking or no space reservation, it doesn't fit.
413 if ((args
->op_flags
& XFS_DA_OP_JUSTCHECK
) || args
->total
== 0)
416 * Convert to block form then add the name.
418 error
= xfs_dir2_sf_to_block(args
);
421 return xfs_dir2_block_addname(args
);
424 * Just checking, it fits.
426 if (args
->op_flags
& XFS_DA_OP_JUSTCHECK
)
429 * Do it the easy way - just add it at the end.
432 xfs_dir2_sf_addname_easy(args
, sfep
, offset
, new_isize
);
434 * Do it the hard way - look for a place to insert the new entry.
435 * Convert to 8 byte inode numbers first if necessary.
440 xfs_dir2_sf_toino8(args
);
441 xfs_dir2_sf_addname_hard(args
, objchange
, new_isize
);
443 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
448 * Add the new entry the "easy" way.
449 * This is copying the old directory and adding the new entry at the end.
450 * Since it's sorted by "offset" we need room after the last offset
451 * that's already there, and then room to convert to a block directory.
452 * This is already checked by the pick routine.
455 xfs_dir2_sf_addname_easy(
456 xfs_da_args_t
*args
, /* operation arguments */
457 xfs_dir2_sf_entry_t
*sfep
, /* pointer to new entry */
458 xfs_dir2_data_aoff_t offset
, /* offset to use for new ent */
459 int new_isize
) /* new directory size */
461 struct xfs_inode
*dp
= args
->dp
;
462 struct xfs_mount
*mp
= dp
->i_mount
;
463 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
464 int byteoff
= (int)((char *)sfep
- (char *)sfp
);
467 * Grow the in-inode space.
469 sfp
= xfs_idata_realloc(dp
, xfs_dir2_sf_entsize(mp
, sfp
, args
->namelen
),
472 * Need to set up again due to realloc of the inode data.
474 sfep
= (xfs_dir2_sf_entry_t
*)((char *)sfp
+ byteoff
);
476 * Fill in the new entry.
478 sfep
->namelen
= args
->namelen
;
479 xfs_dir2_sf_put_offset(sfep
, offset
);
480 memcpy(sfep
->name
, args
->name
, sfep
->namelen
);
481 xfs_dir2_sf_put_ino(mp
, sfp
, sfep
, args
->inumber
);
482 xfs_dir2_sf_put_ftype(mp
, sfep
, args
->filetype
);
485 * Update the header and inode.
488 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
)
490 dp
->i_disk_size
= new_isize
;
491 xfs_dir2_sf_check(args
);
495 * Add the new entry the "hard" way.
496 * The caller has already converted to 8 byte inode numbers if necessary,
497 * in which case we need to leave the i8count at 1.
498 * Find a hole that the new entry will fit into, and copy
499 * the first part of the entries, the new entry, and the last part of
504 xfs_dir2_sf_addname_hard(
505 xfs_da_args_t
*args
, /* operation arguments */
506 int objchange
, /* changing inode number size */
507 int new_isize
) /* new directory size */
509 struct xfs_inode
*dp
= args
->dp
;
510 struct xfs_mount
*mp
= dp
->i_mount
;
511 int add_datasize
; /* data size need for new ent */
512 char *buf
; /* buffer for old */
513 int eof
; /* reached end of old dir */
514 int nbytes
; /* temp for byte copies */
515 xfs_dir2_data_aoff_t new_offset
; /* next offset value */
516 xfs_dir2_data_aoff_t offset
; /* current offset value */
517 int old_isize
; /* previous size */
518 xfs_dir2_sf_entry_t
*oldsfep
; /* entry in original dir */
519 xfs_dir2_sf_hdr_t
*oldsfp
; /* original shortform dir */
520 xfs_dir2_sf_entry_t
*sfep
; /* entry in new dir */
521 xfs_dir2_sf_hdr_t
*sfp
; /* new shortform dir */
524 * Copy the old directory to the stack buffer.
526 old_isize
= (int)dp
->i_disk_size
;
527 buf
= kmalloc(old_isize
, GFP_KERNEL
| __GFP_NOFAIL
);
528 oldsfp
= (xfs_dir2_sf_hdr_t
*)buf
;
529 memcpy(oldsfp
, dp
->i_df
.if_data
, old_isize
);
531 * Loop over the old directory finding the place we're going
532 * to insert the new entry.
533 * If it's going to end up at the end then oldsfep will point there.
535 for (offset
= args
->geo
->data_first_offset
,
536 oldsfep
= xfs_dir2_sf_firstentry(oldsfp
),
537 add_datasize
= xfs_dir2_data_entsize(mp
, args
->namelen
),
538 eof
= (char *)oldsfep
== &buf
[old_isize
];
540 offset
= new_offset
+ xfs_dir2_data_entsize(mp
, oldsfep
->namelen
),
541 oldsfep
= xfs_dir2_sf_nextentry(mp
, oldsfp
, oldsfep
),
542 eof
= (char *)oldsfep
== &buf
[old_isize
]) {
543 new_offset
= xfs_dir2_sf_get_offset(oldsfep
);
544 if (offset
+ add_datasize
<= new_offset
)
548 * Get rid of the old directory, then allocate space for
549 * the new one. We do this so xfs_idata_realloc won't copy
552 xfs_idata_realloc(dp
, -old_isize
, XFS_DATA_FORK
);
553 sfp
= xfs_idata_realloc(dp
, new_isize
, XFS_DATA_FORK
);
556 * Copy the first part of the directory, including the header.
558 nbytes
= (int)((char *)oldsfep
- (char *)oldsfp
);
559 memcpy(sfp
, oldsfp
, nbytes
);
560 sfep
= (xfs_dir2_sf_entry_t
*)((char *)sfp
+ nbytes
);
562 * Fill in the new entry, and update the header counts.
564 sfep
->namelen
= args
->namelen
;
565 xfs_dir2_sf_put_offset(sfep
, offset
);
566 memcpy(sfep
->name
, args
->name
, sfep
->namelen
);
567 xfs_dir2_sf_put_ino(mp
, sfp
, sfep
, args
->inumber
);
568 xfs_dir2_sf_put_ftype(mp
, sfep
, args
->filetype
);
570 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
&& !objchange
)
573 * If there's more left to copy, do that.
576 sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
);
577 memcpy(sfep
, oldsfep
, old_isize
- nbytes
);
580 dp
->i_disk_size
= new_isize
;
581 xfs_dir2_sf_check(args
);
585 * Decide if the new entry will fit at all.
586 * If it will fit, pick between adding the new entry to the end (easy)
587 * or somewhere else (hard).
588 * Return 0 (won't fit), 1 (easy), 2 (hard).
591 static int /* pick result */
592 xfs_dir2_sf_addname_pick(
593 xfs_da_args_t
*args
, /* operation arguments */
594 int objchange
, /* inode # size changes */
595 xfs_dir2_sf_entry_t
**sfepp
, /* out(1): new entry ptr */
596 xfs_dir2_data_aoff_t
*offsetp
) /* out(1): new offset */
598 struct xfs_inode
*dp
= args
->dp
;
599 struct xfs_mount
*mp
= dp
->i_mount
;
600 int holefit
; /* found hole it will fit in */
601 int i
; /* entry number */
602 xfs_dir2_data_aoff_t offset
; /* data block offset */
603 xfs_dir2_sf_entry_t
*sfep
; /* shortform entry */
604 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
605 int size
; /* entry's data size */
606 int used
; /* data bytes used */
608 size
= xfs_dir2_data_entsize(mp
, args
->namelen
);
609 offset
= args
->geo
->data_first_offset
;
610 sfep
= xfs_dir2_sf_firstentry(sfp
);
613 * Loop over sf entries.
614 * Keep track of data offset and whether we've seen a place
615 * to insert the new entry.
617 for (i
= 0; i
< sfp
->count
; i
++) {
619 holefit
= offset
+ size
<= xfs_dir2_sf_get_offset(sfep
);
620 offset
= xfs_dir2_sf_get_offset(sfep
) +
621 xfs_dir2_data_entsize(mp
, sfep
->namelen
);
622 sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
);
625 * Calculate data bytes used excluding the new entry, if this
626 * was a data block (block form directory).
629 (sfp
->count
+ 3) * (uint
)sizeof(xfs_dir2_leaf_entry_t
) +
630 (uint
)sizeof(xfs_dir2_block_tail_t
);
632 * If it won't fit in a block form then we can't insert it,
633 * we'll go back, convert to block, then try the insert and convert
636 if (used
+ (holefit
? 0 : size
) > args
->geo
->blksize
)
639 * If changing the inode number size, do it the hard way.
644 * If it won't fit at the end then do it the hard way (use the hole).
646 if (used
+ size
> args
->geo
->blksize
)
649 * Do it the easy way.
658 * Check consistency of shortform directory, assert if bad.
662 xfs_da_args_t
*args
) /* operation arguments */
664 struct xfs_inode
*dp
= args
->dp
;
665 struct xfs_mount
*mp
= dp
->i_mount
;
666 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
667 int i
; /* entry number */
668 int i8count
; /* number of big inode#s */
669 xfs_ino_t ino
; /* entry inode number */
670 int offset
; /* data offset */
671 xfs_dir2_sf_entry_t
*sfep
; /* shortform dir entry */
673 offset
= args
->geo
->data_first_offset
;
674 ino
= xfs_dir2_sf_get_parent_ino(sfp
);
675 i8count
= ino
> XFS_DIR2_MAX_SHORT_INUM
;
677 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
);
679 i
++, sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
)) {
680 ASSERT(xfs_dir2_sf_get_offset(sfep
) >= offset
);
681 ino
= xfs_dir2_sf_get_ino(mp
, sfp
, sfep
);
682 i8count
+= ino
> XFS_DIR2_MAX_SHORT_INUM
;
684 xfs_dir2_sf_get_offset(sfep
) +
685 xfs_dir2_data_entsize(mp
, sfep
->namelen
);
686 ASSERT(xfs_dir2_sf_get_ftype(mp
, sfep
) < XFS_DIR3_FT_MAX
);
688 ASSERT(i8count
== sfp
->i8count
);
689 ASSERT((char *)sfep
- (char *)sfp
== dp
->i_disk_size
);
691 (sfp
->count
+ 2) * (uint
)sizeof(xfs_dir2_leaf_entry_t
) +
692 (uint
)sizeof(xfs_dir2_block_tail_t
) <= args
->geo
->blksize
);
696 /* Verify the consistency of an inline directory. */
699 struct xfs_mount
*mp
,
700 struct xfs_dir2_sf_hdr
*sfp
,
703 struct xfs_dir2_sf_entry
*sfep
;
704 struct xfs_dir2_sf_entry
*next_sfep
;
714 * Give up if the directory is way too short.
716 if (size
<= offsetof(struct xfs_dir2_sf_hdr
, parent
) ||
717 size
< xfs_dir2_sf_hdr_size(sfp
->i8count
))
718 return __this_address
;
720 endp
= (char *)sfp
+ size
;
723 ino
= xfs_dir2_sf_get_parent_ino(sfp
);
724 i8count
= ino
> XFS_DIR2_MAX_SHORT_INUM
;
725 error
= xfs_dir_ino_validate(mp
, ino
);
727 return __this_address
;
728 offset
= mp
->m_dir_geo
->data_first_offset
;
730 /* Check all reported entries */
731 sfep
= xfs_dir2_sf_firstentry(sfp
);
732 for (i
= 0; i
< sfp
->count
; i
++) {
734 * struct xfs_dir2_sf_entry has a variable length.
735 * Check the fixed-offset parts of the structure are
736 * within the data buffer.
738 if (((char *)sfep
+ sizeof(*sfep
)) >= endp
)
739 return __this_address
;
741 /* Don't allow names with known bad length. */
742 if (sfep
->namelen
== 0)
743 return __this_address
;
746 * Check that the variable-length part of the structure is
747 * within the data buffer. The next entry starts after the
748 * name component, so nextentry is an acceptable test.
750 next_sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
);
751 if (endp
< (char *)next_sfep
)
752 return __this_address
;
754 /* Check that the offsets always increase. */
755 if (xfs_dir2_sf_get_offset(sfep
) < offset
)
756 return __this_address
;
758 /* Check the inode number. */
759 ino
= xfs_dir2_sf_get_ino(mp
, sfp
, sfep
);
760 i8count
+= ino
> XFS_DIR2_MAX_SHORT_INUM
;
761 error
= xfs_dir_ino_validate(mp
, ino
);
763 return __this_address
;
765 /* Check the file type. */
766 filetype
= xfs_dir2_sf_get_ftype(mp
, sfep
);
767 if (filetype
>= XFS_DIR3_FT_MAX
)
768 return __this_address
;
770 offset
= xfs_dir2_sf_get_offset(sfep
) +
771 xfs_dir2_data_entsize(mp
, sfep
->namelen
);
775 if (i8count
!= sfp
->i8count
)
776 return __this_address
;
777 if ((void *)sfep
!= (void *)endp
)
778 return __this_address
;
780 /* Make sure this whole thing ought to be in local format. */
781 if (offset
+ (sfp
->count
+ 2) * (uint
)sizeof(xfs_dir2_leaf_entry_t
) +
782 (uint
)sizeof(xfs_dir2_block_tail_t
) > mp
->m_dir_geo
->blksize
)
783 return __this_address
;
789 * Create a new (shortform) directory.
791 int /* error, always 0 */
793 xfs_da_args_t
*args
, /* operation arguments */
794 xfs_ino_t pino
) /* parent inode number */
796 xfs_inode_t
*dp
; /* incore directory inode */
797 int i8count
; /* parent inode is an 8-byte number */
798 xfs_dir2_sf_hdr_t
*sfp
; /* shortform structure */
799 int size
; /* directory size */
801 trace_xfs_dir2_sf_create(args
);
806 ASSERT(dp
->i_disk_size
== 0);
808 * If it's currently a zero-length extent file,
809 * convert it to local format.
811 if (dp
->i_df
.if_format
== XFS_DINODE_FMT_EXTENTS
) {
812 dp
->i_df
.if_format
= XFS_DINODE_FMT_LOCAL
;
813 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
);
815 ASSERT(dp
->i_df
.if_format
== XFS_DINODE_FMT_LOCAL
);
816 ASSERT(dp
->i_df
.if_bytes
== 0);
817 i8count
= pino
> XFS_DIR2_MAX_SHORT_INUM
;
818 size
= xfs_dir2_sf_hdr_size(i8count
);
821 * Make a buffer for the data and fill in the header.
823 sfp
= xfs_idata_realloc(dp
, size
, XFS_DATA_FORK
);
824 sfp
->i8count
= i8count
;
827 * Now can put in the inode number, since i8count is set.
829 xfs_dir2_sf_put_parent_ino(sfp
, pino
);
831 dp
->i_disk_size
= size
;
832 xfs_dir2_sf_check(args
);
833 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
838 * Lookup an entry in a shortform directory.
839 * Returns EEXIST if found, ENOENT if not found.
843 xfs_da_args_t
*args
) /* operation arguments */
845 struct xfs_inode
*dp
= args
->dp
;
846 struct xfs_mount
*mp
= dp
->i_mount
;
847 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
848 int i
; /* entry index */
849 xfs_dir2_sf_entry_t
*sfep
; /* shortform directory entry */
850 enum xfs_dacmp cmp
; /* comparison result */
851 xfs_dir2_sf_entry_t
*ci_sfep
; /* case-insens. entry */
853 trace_xfs_dir2_sf_lookup(args
);
855 xfs_dir2_sf_check(args
);
857 ASSERT(dp
->i_df
.if_format
== XFS_DINODE_FMT_LOCAL
);
858 ASSERT(dp
->i_disk_size
>= offsetof(struct xfs_dir2_sf_hdr
, parent
));
859 ASSERT(dp
->i_df
.if_bytes
== dp
->i_disk_size
);
861 ASSERT(dp
->i_disk_size
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
865 if (args
->namelen
== 1 && args
->name
[0] == '.') {
866 args
->inumber
= dp
->i_ino
;
867 args
->cmpresult
= XFS_CMP_EXACT
;
868 args
->filetype
= XFS_DIR3_FT_DIR
;
872 * Special case for ..
874 if (args
->namelen
== 2 &&
875 args
->name
[0] == '.' && args
->name
[1] == '.') {
876 args
->inumber
= xfs_dir2_sf_get_parent_ino(sfp
);
877 args
->cmpresult
= XFS_CMP_EXACT
;
878 args
->filetype
= XFS_DIR3_FT_DIR
;
882 * Loop over all the entries trying to match ours.
885 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
); i
< sfp
->count
;
886 i
++, sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
)) {
888 * Compare name and if it's an exact match, return the inode
889 * number. If it's the first case-insensitive match, store the
890 * inode number and continue looking for an exact match.
892 cmp
= xfs_dir2_compname(args
, sfep
->name
, sfep
->namelen
);
893 if (cmp
!= XFS_CMP_DIFFERENT
&& cmp
!= args
->cmpresult
) {
894 args
->cmpresult
= cmp
;
895 args
->inumber
= xfs_dir2_sf_get_ino(mp
, sfp
, sfep
);
896 args
->filetype
= xfs_dir2_sf_get_ftype(mp
, sfep
);
897 if (cmp
== XFS_CMP_EXACT
)
902 ASSERT(args
->op_flags
& XFS_DA_OP_OKNOENT
);
904 * Here, we can only be doing a lookup (not a rename or replace).
905 * If a case-insensitive match was not found, return -ENOENT.
909 /* otherwise process the CI match as required by the caller */
910 return xfs_dir_cilookup_result(args
, ci_sfep
->name
, ci_sfep
->namelen
);
914 * Remove an entry from a shortform directory.
917 xfs_dir2_sf_removename(
920 struct xfs_inode
*dp
= args
->dp
;
921 struct xfs_mount
*mp
= dp
->i_mount
;
922 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
923 int byteoff
; /* offset of removed entry */
924 int entsize
; /* this entry's size */
925 int i
; /* shortform entry index */
926 int newsize
; /* new inode size */
927 int oldsize
; /* old inode size */
928 xfs_dir2_sf_entry_t
*sfep
; /* shortform directory entry */
930 trace_xfs_dir2_sf_removename(args
);
932 ASSERT(dp
->i_df
.if_format
== XFS_DINODE_FMT_LOCAL
);
933 oldsize
= (int)dp
->i_disk_size
;
934 ASSERT(oldsize
>= offsetof(struct xfs_dir2_sf_hdr
, parent
));
935 ASSERT(dp
->i_df
.if_bytes
== oldsize
);
937 ASSERT(oldsize
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
939 * Loop over the old directory entries.
940 * Find the one we're deleting.
942 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
); i
< sfp
->count
;
943 i
++, sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
)) {
944 if (xfs_da_compname(args
, sfep
->name
, sfep
->namelen
) ==
946 ASSERT(xfs_dir2_sf_get_ino(mp
, sfp
, sfep
) ==
959 byteoff
= (int)((char *)sfep
- (char *)sfp
);
960 entsize
= xfs_dir2_sf_entsize(mp
, sfp
, args
->namelen
);
961 newsize
= oldsize
- entsize
;
963 * Copy the part if any after the removed entry, sliding it down.
965 if (byteoff
+ entsize
< oldsize
)
966 memmove((char *)sfp
+ byteoff
, (char *)sfp
+ byteoff
+ entsize
,
967 oldsize
- (byteoff
+ entsize
));
969 * Fix up the header and file size.
972 dp
->i_disk_size
= newsize
;
975 * Reallocate, making it smaller.
977 sfp
= xfs_idata_realloc(dp
, newsize
- oldsize
, XFS_DATA_FORK
);
980 * Are we changing inode number size?
982 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
) {
983 if (sfp
->i8count
== 1)
984 xfs_dir2_sf_toino4(args
);
988 xfs_dir2_sf_check(args
);
989 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
994 * Check whether the sf dir replace operation need more blocks.
997 xfs_dir2_sf_replace_needblock(
998 struct xfs_inode
*dp
,
1001 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
1004 if (dp
->i_df
.if_format
!= XFS_DINODE_FMT_LOCAL
)
1007 newsize
= dp
->i_df
.if_bytes
+ (sfp
->count
+ 1) * XFS_INO64_DIFF
;
1009 return inum
> XFS_DIR2_MAX_SHORT_INUM
&&
1010 sfp
->i8count
== 0 && newsize
> xfs_inode_data_fork_size(dp
);
1014 * Replace the inode number of an entry in a shortform directory.
1017 xfs_dir2_sf_replace(
1018 xfs_da_args_t
*args
) /* operation arguments */
1020 struct xfs_inode
*dp
= args
->dp
;
1021 struct xfs_mount
*mp
= dp
->i_mount
;
1022 struct xfs_dir2_sf_hdr
*sfp
= dp
->i_df
.if_data
;
1023 int i
; /* entry index */
1024 xfs_ino_t ino
=0; /* entry old inode number */
1025 int i8elevated
; /* sf_toino8 set i8count=1 */
1026 xfs_dir2_sf_entry_t
*sfep
; /* shortform directory entry */
1028 trace_xfs_dir2_sf_replace(args
);
1030 ASSERT(dp
->i_df
.if_format
== XFS_DINODE_FMT_LOCAL
);
1031 ASSERT(dp
->i_disk_size
>= offsetof(struct xfs_dir2_sf_hdr
, parent
));
1032 ASSERT(dp
->i_df
.if_bytes
== dp
->i_disk_size
);
1033 ASSERT(sfp
!= NULL
);
1034 ASSERT(dp
->i_disk_size
>= xfs_dir2_sf_hdr_size(sfp
->i8count
));
1037 * New inode number is large, and need to convert to 8-byte inodes.
1039 if (args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
&& sfp
->i8count
== 0) {
1040 int error
; /* error return value */
1043 * Won't fit as shortform, convert to block then do replace.
1045 if (xfs_dir2_sf_replace_needblock(dp
, args
->inumber
)) {
1046 error
= xfs_dir2_sf_to_block(args
);
1049 return xfs_dir2_block_replace(args
);
1052 * Still fits, convert to 8-byte now.
1054 xfs_dir2_sf_toino8(args
);
1056 sfp
= dp
->i_df
.if_data
;
1060 ASSERT(args
->namelen
!= 1 || args
->name
[0] != '.');
1062 * Replace ..'s entry.
1064 if (args
->namelen
== 2 &&
1065 args
->name
[0] == '.' && args
->name
[1] == '.') {
1066 ino
= xfs_dir2_sf_get_parent_ino(sfp
);
1067 ASSERT(args
->inumber
!= ino
);
1068 xfs_dir2_sf_put_parent_ino(sfp
, args
->inumber
);
1071 * Normal entry, look for the name.
1074 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
); i
< sfp
->count
;
1075 i
++, sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
)) {
1076 if (xfs_da_compname(args
, sfep
->name
, sfep
->namelen
) ==
1078 ino
= xfs_dir2_sf_get_ino(mp
, sfp
, sfep
);
1079 ASSERT(args
->inumber
!= ino
);
1080 xfs_dir2_sf_put_ino(mp
, sfp
, sfep
,
1082 xfs_dir2_sf_put_ftype(mp
, sfep
, args
->filetype
);
1089 if (i
== sfp
->count
) {
1090 ASSERT(args
->op_flags
& XFS_DA_OP_OKNOENT
);
1092 xfs_dir2_sf_toino4(args
);
1097 * See if the old number was large, the new number is small.
1099 if (ino
> XFS_DIR2_MAX_SHORT_INUM
&&
1100 args
->inumber
<= XFS_DIR2_MAX_SHORT_INUM
) {
1102 * And the old count was one, so need to convert to small.
1104 if (sfp
->i8count
== 1)
1105 xfs_dir2_sf_toino4(args
);
1110 * See if the old number was small, the new number is large.
1112 if (ino
<= XFS_DIR2_MAX_SHORT_INUM
&&
1113 args
->inumber
> XFS_DIR2_MAX_SHORT_INUM
) {
1115 * add to the i8count unless we just converted to 8-byte
1116 * inodes (which does an implied i8count = 1)
1118 ASSERT(sfp
->i8count
!= 0);
1122 xfs_dir2_sf_check(args
);
1123 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_DDATA
);
1128 * Convert from 8-byte inode numbers to 4-byte inode numbers.
1129 * The last 8-byte inode number is gone, but the count is still 1.
1133 xfs_da_args_t
*args
) /* operation arguments */
1135 struct xfs_inode
*dp
= args
->dp
;
1136 struct xfs_mount
*mp
= dp
->i_mount
;
1137 struct xfs_dir2_sf_hdr
*oldsfp
= dp
->i_df
.if_data
;
1138 char *buf
; /* old dir's buffer */
1139 int i
; /* entry index */
1140 int newsize
; /* new inode size */
1141 xfs_dir2_sf_entry_t
*oldsfep
; /* old sf entry */
1142 int oldsize
; /* old inode size */
1143 xfs_dir2_sf_entry_t
*sfep
; /* new sf entry */
1144 xfs_dir2_sf_hdr_t
*sfp
; /* new sf directory */
1146 trace_xfs_dir2_sf_toino4(args
);
1149 * Copy the old directory to the buffer.
1150 * Then nuke it from the inode, and add the new buffer to the inode.
1151 * Don't want xfs_idata_realloc copying the data here.
1153 oldsize
= dp
->i_df
.if_bytes
;
1154 buf
= kmalloc(oldsize
, GFP_KERNEL
| __GFP_NOFAIL
);
1155 ASSERT(oldsfp
->i8count
== 1);
1156 memcpy(buf
, oldsfp
, oldsize
);
1158 * Compute the new inode size.
1160 newsize
= oldsize
- (oldsfp
->count
+ 1) * XFS_INO64_DIFF
;
1161 xfs_idata_realloc(dp
, -oldsize
, XFS_DATA_FORK
);
1162 xfs_idata_realloc(dp
, newsize
, XFS_DATA_FORK
);
1164 * Reset our pointers, the data has moved.
1166 oldsfp
= (xfs_dir2_sf_hdr_t
*)buf
;
1167 sfp
= dp
->i_df
.if_data
;
1169 * Fill in the new header.
1171 sfp
->count
= oldsfp
->count
;
1173 xfs_dir2_sf_put_parent_ino(sfp
, xfs_dir2_sf_get_parent_ino(oldsfp
));
1175 * Copy the entries field by field.
1177 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
),
1178 oldsfep
= xfs_dir2_sf_firstentry(oldsfp
);
1180 i
++, sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
),
1181 oldsfep
= xfs_dir2_sf_nextentry(mp
, oldsfp
, oldsfep
)) {
1182 sfep
->namelen
= oldsfep
->namelen
;
1183 memcpy(sfep
->offset
, oldsfep
->offset
, sizeof(sfep
->offset
));
1184 memcpy(sfep
->name
, oldsfep
->name
, sfep
->namelen
);
1185 xfs_dir2_sf_put_ino(mp
, sfp
, sfep
,
1186 xfs_dir2_sf_get_ino(mp
, oldsfp
, oldsfep
));
1187 xfs_dir2_sf_put_ftype(mp
, sfep
,
1188 xfs_dir2_sf_get_ftype(mp
, oldsfep
));
1191 * Clean up the inode.
1194 dp
->i_disk_size
= newsize
;
1195 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);
1199 * Convert existing entries from 4-byte inode numbers to 8-byte inode numbers.
1200 * The new entry w/ an 8-byte inode number is not there yet; we leave with
1201 * i8count set to 1, but no corresponding 8-byte entry.
1205 xfs_da_args_t
*args
) /* operation arguments */
1207 struct xfs_inode
*dp
= args
->dp
;
1208 struct xfs_mount
*mp
= dp
->i_mount
;
1209 struct xfs_dir2_sf_hdr
*oldsfp
= dp
->i_df
.if_data
;
1210 char *buf
; /* old dir's buffer */
1211 int i
; /* entry index */
1212 int newsize
; /* new inode size */
1213 xfs_dir2_sf_entry_t
*oldsfep
; /* old sf entry */
1214 int oldsize
; /* old inode size */
1215 xfs_dir2_sf_entry_t
*sfep
; /* new sf entry */
1216 xfs_dir2_sf_hdr_t
*sfp
; /* new sf directory */
1218 trace_xfs_dir2_sf_toino8(args
);
1221 * Copy the old directory to the buffer.
1222 * Then nuke it from the inode, and add the new buffer to the inode.
1223 * Don't want xfs_idata_realloc copying the data here.
1225 oldsize
= dp
->i_df
.if_bytes
;
1226 buf
= kmalloc(oldsize
, GFP_KERNEL
| __GFP_NOFAIL
);
1227 ASSERT(oldsfp
->i8count
== 0);
1228 memcpy(buf
, oldsfp
, oldsize
);
1230 * Compute the new inode size (nb: entry count + 1 for parent)
1232 newsize
= oldsize
+ (oldsfp
->count
+ 1) * XFS_INO64_DIFF
;
1233 xfs_idata_realloc(dp
, -oldsize
, XFS_DATA_FORK
);
1234 xfs_idata_realloc(dp
, newsize
, XFS_DATA_FORK
);
1236 * Reset our pointers, the data has moved.
1238 oldsfp
= (xfs_dir2_sf_hdr_t
*)buf
;
1239 sfp
= dp
->i_df
.if_data
;
1241 * Fill in the new header.
1243 sfp
->count
= oldsfp
->count
;
1245 xfs_dir2_sf_put_parent_ino(sfp
, xfs_dir2_sf_get_parent_ino(oldsfp
));
1247 * Copy the entries field by field.
1249 for (i
= 0, sfep
= xfs_dir2_sf_firstentry(sfp
),
1250 oldsfep
= xfs_dir2_sf_firstentry(oldsfp
);
1252 i
++, sfep
= xfs_dir2_sf_nextentry(mp
, sfp
, sfep
),
1253 oldsfep
= xfs_dir2_sf_nextentry(mp
, oldsfp
, oldsfep
)) {
1254 sfep
->namelen
= oldsfep
->namelen
;
1255 memcpy(sfep
->offset
, oldsfep
->offset
, sizeof(sfep
->offset
));
1256 memcpy(sfep
->name
, oldsfep
->name
, sfep
->namelen
);
1257 xfs_dir2_sf_put_ino(mp
, sfp
, sfep
,
1258 xfs_dir2_sf_get_ino(mp
, oldsfp
, oldsfep
));
1259 xfs_dir2_sf_put_ftype(mp
, sfep
,
1260 xfs_dir2_sf_get_ftype(mp
, oldsfep
));
1263 * Clean up the inode.
1266 dp
->i_disk_size
= newsize
;
1267 xfs_trans_log_inode(args
->trans
, dp
, XFS_ILOG_CORE
| XFS_ILOG_DDATA
);