xref: /openbmc/linux/fs/xfs/libxfs/xfs_dir2.c (revision 3b34441309f364bba59a6ee5d1aa32206456142f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4  * All Rights Reserved.
5  */
6 #include "xfs.h"
7 #include "xfs_fs.h"
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"
15 #include "xfs_bmap.h"
16 #include "xfs_dir2.h"
17 #include "xfs_dir2_priv.h"
18 #include "xfs_errortag.h"
19 #include "xfs_error.h"
20 #include "xfs_trace.h"
21 
22 struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
23 
24 /*
25  * Convert inode mode to directory entry filetype
26  */
27 unsigned char
28 xfs_mode_to_ftype(
29 	int		mode)
30 {
31 	switch (mode & S_IFMT) {
32 	case S_IFREG:
33 		return XFS_DIR3_FT_REG_FILE;
34 	case S_IFDIR:
35 		return XFS_DIR3_FT_DIR;
36 	case S_IFCHR:
37 		return XFS_DIR3_FT_CHRDEV;
38 	case S_IFBLK:
39 		return XFS_DIR3_FT_BLKDEV;
40 	case S_IFIFO:
41 		return XFS_DIR3_FT_FIFO;
42 	case S_IFSOCK:
43 		return XFS_DIR3_FT_SOCK;
44 	case S_IFLNK:
45 		return XFS_DIR3_FT_SYMLINK;
46 	default:
47 		return XFS_DIR3_FT_UNKNOWN;
48 	}
49 }
50 
51 /*
52  * ASCII case-insensitive (ie. A-Z) support for directories that was
53  * used in IRIX.
54  */
55 STATIC xfs_dahash_t
56 xfs_ascii_ci_hashname(
57 	struct xfs_name	*name)
58 {
59 	xfs_dahash_t	hash;
60 	int		i;
61 
62 	for (i = 0, hash = 0; i < name->len; i++)
63 		hash = tolower(name->name[i]) ^ rol32(hash, 7);
64 
65 	return hash;
66 }
67 
68 STATIC enum xfs_dacmp
69 xfs_ascii_ci_compname(
70 	struct xfs_da_args *args,
71 	const unsigned char *name,
72 	int		len)
73 {
74 	enum xfs_dacmp	result;
75 	int		i;
76 
77 	if (args->namelen != len)
78 		return XFS_CMP_DIFFERENT;
79 
80 	result = XFS_CMP_EXACT;
81 	for (i = 0; i < len; i++) {
82 		if (args->name[i] == name[i])
83 			continue;
84 		if (tolower(args->name[i]) != tolower(name[i]))
85 			return XFS_CMP_DIFFERENT;
86 		result = XFS_CMP_CASE;
87 	}
88 
89 	return result;
90 }
91 
92 static const struct xfs_nameops xfs_ascii_ci_nameops = {
93 	.hashname	= xfs_ascii_ci_hashname,
94 	.compname	= xfs_ascii_ci_compname,
95 };
96 
97 int
98 xfs_da_mount(
99 	struct xfs_mount	*mp)
100 {
101 	struct xfs_da_geometry	*dageo;
102 
103 
104 	ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
105 	ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
106 
107 	mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
108 
109 	mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
110 				    KM_MAYFAIL);
111 	mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
112 				     KM_MAYFAIL);
113 	if (!mp->m_dir_geo || !mp->m_attr_geo) {
114 		kmem_free(mp->m_dir_geo);
115 		kmem_free(mp->m_attr_geo);
116 		return -ENOMEM;
117 	}
118 
119 	/* set up directory geometry */
120 	dageo = mp->m_dir_geo;
121 	dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
122 	dageo->fsblog = mp->m_sb.sb_blocklog;
123 	dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
124 	dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
125 	if (xfs_sb_version_hascrc(&mp->m_sb))
126 		dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
127 	else
128 		dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
129 
130 	/*
131 	 * Now we've set up the block conversion variables, we can calculate the
132 	 * segment block constants using the geometry structure.
133 	 */
134 	dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
135 	dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
136 	dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
137 	dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
138 				(uint)sizeof(xfs_da_node_entry_t);
139 	dageo->magicpct = (dageo->blksize * 37) / 100;
140 
141 	/* set up attribute geometry - single fsb only */
142 	dageo = mp->m_attr_geo;
143 	dageo->blklog = mp->m_sb.sb_blocklog;
144 	dageo->fsblog = mp->m_sb.sb_blocklog;
145 	dageo->blksize = 1 << dageo->blklog;
146 	dageo->fsbcount = 1;
147 	dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
148 	dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
149 				(uint)sizeof(xfs_da_node_entry_t);
150 	dageo->magicpct = (dageo->blksize * 37) / 100;
151 
152 	if (xfs_sb_version_hasasciici(&mp->m_sb))
153 		mp->m_dirnameops = &xfs_ascii_ci_nameops;
154 	else
155 		mp->m_dirnameops = &xfs_default_nameops;
156 
157 	return 0;
158 }
159 
160 void
161 xfs_da_unmount(
162 	struct xfs_mount	*mp)
163 {
164 	kmem_free(mp->m_dir_geo);
165 	kmem_free(mp->m_attr_geo);
166 }
167 
168 /*
169  * Return 1 if directory contains only "." and "..".
170  */
171 int
172 xfs_dir_isempty(
173 	xfs_inode_t	*dp)
174 {
175 	xfs_dir2_sf_hdr_t	*sfp;
176 
177 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
178 	if (dp->i_d.di_size == 0)	/* might happen during shutdown. */
179 		return 1;
180 	if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
181 		return 0;
182 	sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
183 	return !sfp->count;
184 }
185 
186 /*
187  * Validate a given inode number.
188  */
189 int
190 xfs_dir_ino_validate(
191 	xfs_mount_t	*mp,
192 	xfs_ino_t	ino)
193 {
194 	bool		ino_ok = xfs_verify_dir_ino(mp, ino);
195 
196 	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE))) {
197 		xfs_warn(mp, "Invalid inode number 0x%Lx",
198 				(unsigned long long) ino);
199 		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
200 		return -EFSCORRUPTED;
201 	}
202 	return 0;
203 }
204 
205 /*
206  * Initialize a directory with its "." and ".." entries.
207  */
208 int
209 xfs_dir_init(
210 	xfs_trans_t	*tp,
211 	xfs_inode_t	*dp,
212 	xfs_inode_t	*pdp)
213 {
214 	struct xfs_da_args *args;
215 	int		error;
216 
217 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
218 	error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
219 	if (error)
220 		return error;
221 
222 	args = kmem_zalloc(sizeof(*args), KM_NOFS);
223 	if (!args)
224 		return -ENOMEM;
225 
226 	args->geo = dp->i_mount->m_dir_geo;
227 	args->dp = dp;
228 	args->trans = tp;
229 	error = xfs_dir2_sf_create(args, pdp->i_ino);
230 	kmem_free(args);
231 	return error;
232 }
233 
234 /*
235  * Enter a name in a directory, or check for available space.
236  * If inum is 0, only the available space test is performed.
237  */
238 int
239 xfs_dir_createname(
240 	struct xfs_trans	*tp,
241 	struct xfs_inode	*dp,
242 	struct xfs_name		*name,
243 	xfs_ino_t		inum,		/* new entry inode number */
244 	xfs_extlen_t		total)		/* bmap's total block count */
245 {
246 	struct xfs_da_args	*args;
247 	int			rval;
248 	int			v;		/* type-checking value */
249 
250 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
251 
252 	if (inum) {
253 		rval = xfs_dir_ino_validate(tp->t_mountp, inum);
254 		if (rval)
255 			return rval;
256 		XFS_STATS_INC(dp->i_mount, xs_dir_create);
257 	}
258 
259 	args = kmem_zalloc(sizeof(*args), KM_NOFS);
260 	if (!args)
261 		return -ENOMEM;
262 
263 	args->geo = dp->i_mount->m_dir_geo;
264 	args->name = name->name;
265 	args->namelen = name->len;
266 	args->filetype = name->type;
267 	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
268 	args->inumber = inum;
269 	args->dp = dp;
270 	args->total = total;
271 	args->whichfork = XFS_DATA_FORK;
272 	args->trans = tp;
273 	args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
274 	if (!inum)
275 		args->op_flags |= XFS_DA_OP_JUSTCHECK;
276 
277 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
278 		rval = xfs_dir2_sf_addname(args);
279 		goto out_free;
280 	}
281 
282 	rval = xfs_dir2_isblock(args, &v);
283 	if (rval)
284 		goto out_free;
285 	if (v) {
286 		rval = xfs_dir2_block_addname(args);
287 		goto out_free;
288 	}
289 
290 	rval = xfs_dir2_isleaf(args, &v);
291 	if (rval)
292 		goto out_free;
293 	if (v)
294 		rval = xfs_dir2_leaf_addname(args);
295 	else
296 		rval = xfs_dir2_node_addname(args);
297 
298 out_free:
299 	kmem_free(args);
300 	return rval;
301 }
302 
303 /*
304  * If doing a CI lookup and case-insensitive match, dup actual name into
305  * args.value. Return EEXIST for success (ie. name found) or an error.
306  */
307 int
308 xfs_dir_cilookup_result(
309 	struct xfs_da_args *args,
310 	const unsigned char *name,
311 	int		len)
312 {
313 	if (args->cmpresult == XFS_CMP_DIFFERENT)
314 		return -ENOENT;
315 	if (args->cmpresult != XFS_CMP_CASE ||
316 					!(args->op_flags & XFS_DA_OP_CILOOKUP))
317 		return -EEXIST;
318 
319 	args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
320 	if (!args->value)
321 		return -ENOMEM;
322 
323 	memcpy(args->value, name, len);
324 	args->valuelen = len;
325 	return -EEXIST;
326 }
327 
328 /*
329  * Lookup a name in a directory, give back the inode number.
330  * If ci_name is not NULL, returns the actual name in ci_name if it differs
331  * to name, or ci_name->name is set to NULL for an exact match.
332  */
333 
334 int
335 xfs_dir_lookup(
336 	xfs_trans_t	*tp,
337 	xfs_inode_t	*dp,
338 	struct xfs_name	*name,
339 	xfs_ino_t	*inum,		/* out: inode number */
340 	struct xfs_name *ci_name)	/* out: actual name if CI match */
341 {
342 	struct xfs_da_args *args;
343 	int		rval;
344 	int		v;		/* type-checking value */
345 	int		lock_mode;
346 
347 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
348 	XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
349 
350 	/*
351 	 * We need to use KM_NOFS here so that lockdep will not throw false
352 	 * positive deadlock warnings on a non-transactional lookup path. It is
353 	 * safe to recurse into inode recalim in that case, but lockdep can't
354 	 * easily be taught about it. Hence KM_NOFS avoids having to add more
355 	 * lockdep Doing this avoids having to add a bunch of lockdep class
356 	 * annotations into the reclaim path for the ilock.
357 	 */
358 	args = kmem_zalloc(sizeof(*args), KM_NOFS);
359 	args->geo = dp->i_mount->m_dir_geo;
360 	args->name = name->name;
361 	args->namelen = name->len;
362 	args->filetype = name->type;
363 	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
364 	args->dp = dp;
365 	args->whichfork = XFS_DATA_FORK;
366 	args->trans = tp;
367 	args->op_flags = XFS_DA_OP_OKNOENT;
368 	if (ci_name)
369 		args->op_flags |= XFS_DA_OP_CILOOKUP;
370 
371 	lock_mode = xfs_ilock_data_map_shared(dp);
372 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
373 		rval = xfs_dir2_sf_lookup(args);
374 		goto out_check_rval;
375 	}
376 
377 	rval = xfs_dir2_isblock(args, &v);
378 	if (rval)
379 		goto out_free;
380 	if (v) {
381 		rval = xfs_dir2_block_lookup(args);
382 		goto out_check_rval;
383 	}
384 
385 	rval = xfs_dir2_isleaf(args, &v);
386 	if (rval)
387 		goto out_free;
388 	if (v)
389 		rval = xfs_dir2_leaf_lookup(args);
390 	else
391 		rval = xfs_dir2_node_lookup(args);
392 
393 out_check_rval:
394 	if (rval == -EEXIST)
395 		rval = 0;
396 	if (!rval) {
397 		*inum = args->inumber;
398 		if (ci_name) {
399 			ci_name->name = args->value;
400 			ci_name->len = args->valuelen;
401 		}
402 	}
403 out_free:
404 	xfs_iunlock(dp, lock_mode);
405 	kmem_free(args);
406 	return rval;
407 }
408 
409 /*
410  * Remove an entry from a directory.
411  */
412 int
413 xfs_dir_removename(
414 	struct xfs_trans	*tp,
415 	struct xfs_inode	*dp,
416 	struct xfs_name		*name,
417 	xfs_ino_t		ino,
418 	xfs_extlen_t		total)		/* bmap's total block count */
419 {
420 	struct xfs_da_args	*args;
421 	int			rval;
422 	int			v;		/* type-checking value */
423 
424 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
425 	XFS_STATS_INC(dp->i_mount, xs_dir_remove);
426 
427 	args = kmem_zalloc(sizeof(*args), KM_NOFS);
428 	if (!args)
429 		return -ENOMEM;
430 
431 	args->geo = dp->i_mount->m_dir_geo;
432 	args->name = name->name;
433 	args->namelen = name->len;
434 	args->filetype = name->type;
435 	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
436 	args->inumber = ino;
437 	args->dp = dp;
438 	args->total = total;
439 	args->whichfork = XFS_DATA_FORK;
440 	args->trans = tp;
441 
442 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
443 		rval = xfs_dir2_sf_removename(args);
444 		goto out_free;
445 	}
446 
447 	rval = xfs_dir2_isblock(args, &v);
448 	if (rval)
449 		goto out_free;
450 	if (v) {
451 		rval = xfs_dir2_block_removename(args);
452 		goto out_free;
453 	}
454 
455 	rval = xfs_dir2_isleaf(args, &v);
456 	if (rval)
457 		goto out_free;
458 	if (v)
459 		rval = xfs_dir2_leaf_removename(args);
460 	else
461 		rval = xfs_dir2_node_removename(args);
462 out_free:
463 	kmem_free(args);
464 	return rval;
465 }
466 
467 /*
468  * Replace the inode number of a directory entry.
469  */
470 int
471 xfs_dir_replace(
472 	struct xfs_trans	*tp,
473 	struct xfs_inode	*dp,
474 	struct xfs_name		*name,		/* name of entry to replace */
475 	xfs_ino_t		inum,		/* new inode number */
476 	xfs_extlen_t		total)		/* bmap's total block count */
477 {
478 	struct xfs_da_args	*args;
479 	int			rval;
480 	int			v;		/* type-checking value */
481 
482 	ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
483 
484 	rval = xfs_dir_ino_validate(tp->t_mountp, inum);
485 	if (rval)
486 		return rval;
487 
488 	args = kmem_zalloc(sizeof(*args), KM_NOFS);
489 	if (!args)
490 		return -ENOMEM;
491 
492 	args->geo = dp->i_mount->m_dir_geo;
493 	args->name = name->name;
494 	args->namelen = name->len;
495 	args->filetype = name->type;
496 	args->hashval = dp->i_mount->m_dirnameops->hashname(name);
497 	args->inumber = inum;
498 	args->dp = dp;
499 	args->total = total;
500 	args->whichfork = XFS_DATA_FORK;
501 	args->trans = tp;
502 
503 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
504 		rval = xfs_dir2_sf_replace(args);
505 		goto out_free;
506 	}
507 
508 	rval = xfs_dir2_isblock(args, &v);
509 	if (rval)
510 		goto out_free;
511 	if (v) {
512 		rval = xfs_dir2_block_replace(args);
513 		goto out_free;
514 	}
515 
516 	rval = xfs_dir2_isleaf(args, &v);
517 	if (rval)
518 		goto out_free;
519 	if (v)
520 		rval = xfs_dir2_leaf_replace(args);
521 	else
522 		rval = xfs_dir2_node_replace(args);
523 out_free:
524 	kmem_free(args);
525 	return rval;
526 }
527 
528 /*
529  * See if this entry can be added to the directory without allocating space.
530  */
531 int
532 xfs_dir_canenter(
533 	xfs_trans_t	*tp,
534 	xfs_inode_t	*dp,
535 	struct xfs_name	*name)		/* name of entry to add */
536 {
537 	return xfs_dir_createname(tp, dp, name, 0, 0);
538 }
539 
540 /*
541  * Utility routines.
542  */
543 
544 /*
545  * Add a block to the directory.
546  *
547  * This routine is for data and free blocks, not leaf/node blocks which are
548  * handled by xfs_da_grow_inode.
549  */
550 int
551 xfs_dir2_grow_inode(
552 	struct xfs_da_args	*args,
553 	int			space,	/* v2 dir's space XFS_DIR2_xxx_SPACE */
554 	xfs_dir2_db_t		*dbp)	/* out: block number added */
555 {
556 	struct xfs_inode	*dp = args->dp;
557 	struct xfs_mount	*mp = dp->i_mount;
558 	xfs_fileoff_t		bno;	/* directory offset of new block */
559 	int			count;	/* count of filesystem blocks */
560 	int			error;
561 
562 	trace_xfs_dir2_grow_inode(args, space);
563 
564 	/*
565 	 * Set lowest possible block in the space requested.
566 	 */
567 	bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
568 	count = args->geo->fsbcount;
569 
570 	error = xfs_da_grow_inode_int(args, &bno, count);
571 	if (error)
572 		return error;
573 
574 	*dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
575 
576 	/*
577 	 * Update file's size if this is the data space and it grew.
578 	 */
579 	if (space == XFS_DIR2_DATA_SPACE) {
580 		xfs_fsize_t	size;		/* directory file (data) size */
581 
582 		size = XFS_FSB_TO_B(mp, bno + count);
583 		if (size > dp->i_d.di_size) {
584 			dp->i_d.di_size = size;
585 			xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
586 		}
587 	}
588 	return 0;
589 }
590 
591 /*
592  * See if the directory is a single-block form directory.
593  */
594 int
595 xfs_dir2_isblock(
596 	struct xfs_da_args	*args,
597 	int			*vp)	/* out: 1 is block, 0 is not block */
598 {
599 	xfs_fileoff_t		last;	/* last file offset */
600 	int			rval;
601 
602 	if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
603 		return rval;
604 	rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
605 	if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) {
606 		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount);
607 		return -EFSCORRUPTED;
608 	}
609 	*vp = rval;
610 	return 0;
611 }
612 
613 /*
614  * See if the directory is a single-leaf form directory.
615  */
616 int
617 xfs_dir2_isleaf(
618 	struct xfs_da_args	*args,
619 	int			*vp)	/* out: 1 is block, 0 is not block */
620 {
621 	xfs_fileoff_t		last;	/* last file offset */
622 	int			rval;
623 
624 	if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
625 		return rval;
626 	*vp = last == args->geo->leafblk + args->geo->fsbcount;
627 	return 0;
628 }
629 
630 /*
631  * Remove the given block from the directory.
632  * This routine is used for data and free blocks, leaf/node are done
633  * by xfs_da_shrink_inode.
634  */
635 int
636 xfs_dir2_shrink_inode(
637 	struct xfs_da_args	*args,
638 	xfs_dir2_db_t		db,
639 	struct xfs_buf		*bp)
640 {
641 	xfs_fileoff_t		bno;		/* directory file offset */
642 	xfs_dablk_t		da;		/* directory file offset */
643 	int			done;		/* bunmap is finished */
644 	struct xfs_inode	*dp;
645 	int			error;
646 	struct xfs_mount	*mp;
647 	struct xfs_trans	*tp;
648 
649 	trace_xfs_dir2_shrink_inode(args, db);
650 
651 	dp = args->dp;
652 	mp = dp->i_mount;
653 	tp = args->trans;
654 	da = xfs_dir2_db_to_da(args->geo, db);
655 
656 	/* Unmap the fsblock(s). */
657 	error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
658 	if (error) {
659 		/*
660 		 * ENOSPC actually can happen if we're in a removename with no
661 		 * space reservation, and the resulting block removal would
662 		 * cause a bmap btree split or conversion from extents to btree.
663 		 * This can only happen for un-fragmented directory blocks,
664 		 * since you need to be punching out the middle of an extent.
665 		 * In this case we need to leave the block in the file, and not
666 		 * binval it.  So the block has to be in a consistent empty
667 		 * state and appropriately logged.  We don't free up the buffer,
668 		 * the caller can tell it hasn't happened since it got an error
669 		 * back.
670 		 */
671 		return error;
672 	}
673 	ASSERT(done);
674 	/*
675 	 * Invalidate the buffer from the transaction.
676 	 */
677 	xfs_trans_binval(tp, bp);
678 	/*
679 	 * If it's not a data block, we're done.
680 	 */
681 	if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
682 		return 0;
683 	/*
684 	 * If the block isn't the last one in the directory, we're done.
685 	 */
686 	if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
687 		return 0;
688 	bno = da;
689 	if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
690 		/*
691 		 * This can't really happen unless there's kernel corruption.
692 		 */
693 		return error;
694 	}
695 	if (db == args->geo->datablk)
696 		ASSERT(bno == 0);
697 	else
698 		ASSERT(bno > 0);
699 	/*
700 	 * Set the size to the new last block.
701 	 */
702 	dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
703 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
704 	return 0;
705 }
706 
707 /* Returns true if the directory entry name is valid. */
708 bool
709 xfs_dir2_namecheck(
710 	const void	*name,
711 	size_t		length)
712 {
713 	/*
714 	 * MAXNAMELEN includes the trailing null, but (name/length) leave it
715 	 * out, so use >= for the length check.
716 	 */
717 	if (length >= MAXNAMELEN)
718 		return false;
719 
720 	/* There shouldn't be any slashes or nulls here */
721 	return !memchr(name, '/', length) && !memchr(name, 0, length);
722 }
723