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