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