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 1459700637 : xfs_mode_to_ftype(
33 : int mode)
34 : {
35 1459700637 : switch (mode & S_IFMT) {
36 : case S_IFREG:
37 : return XFS_DIR3_FT_REG_FILE;
38 357581413 : case S_IFDIR:
39 357581413 : return XFS_DIR3_FT_DIR;
40 252243726 : case S_IFCHR:
41 252243726 : return XFS_DIR3_FT_CHRDEV;
42 311 : case S_IFBLK:
43 311 : return XFS_DIR3_FT_BLKDEV;
44 9116 : case S_IFIFO:
45 9116 : return XFS_DIR3_FT_FIFO;
46 88 : case S_IFSOCK:
47 88 : return XFS_DIR3_FT_SOCK;
48 360468374 : case S_IFLNK:
49 360468374 : return XFS_DIR3_FT_SYMLINK;
50 33125723 : default:
51 33125723 : 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 6780552 : xfs_ascii_ci_hashname(
61 : const struct xfs_name *name)
62 : {
63 6780552 : xfs_dahash_t hash;
64 6780552 : int i;
65 :
66 160781635 : for (i = 0, hash = 0; i < name->len; i++)
67 154001083 : hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7);
68 :
69 6780552 : return hash;
70 : }
71 :
72 : enum xfs_dacmp
73 1906247819 : xfs_ascii_ci_compname(
74 : struct xfs_da_args *args,
75 : const unsigned char *name,
76 : int len)
77 : {
78 1906247819 : enum xfs_dacmp result;
79 1906247819 : int i;
80 :
81 1906247819 : if (args->namelen != len)
82 : return XFS_CMP_DIFFERENT;
83 :
84 : result = XFS_CMP_EXACT;
85 101987843 : for (i = 0; i < len; i++) {
86 101214194 : if (args->name[i] == name[i])
87 20725511 : continue;
88 80488683 : if (xfs_ascii_ci_xfrm(args->name[i]) !=
89 80488683 : 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 59289 : xfs_da_mount(
99 : struct xfs_mount *mp)
100 : {
101 59289 : struct xfs_da_geometry *dageo;
102 :
103 :
104 59289 : ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
105 59289 : ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
106 :
107 59289 : mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
108 : KM_MAYFAIL);
109 59289 : mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
110 : KM_MAYFAIL);
111 59289 : 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 59289 : dageo = mp->m_dir_geo;
119 59289 : dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
120 59289 : dageo->fsblog = mp->m_sb.sb_blocklog;
121 59289 : dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
122 59289 : dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
123 59289 : if (xfs_has_crc(mp)) {
124 59094 : dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
125 59094 : dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
126 59094 : dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
127 59094 : dageo->data_entry_offset =
128 : sizeof(struct xfs_dir3_data_hdr);
129 : } else {
130 195 : dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
131 195 : dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr);
132 195 : dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr);
133 195 : dageo->data_entry_offset =
134 : sizeof(struct xfs_dir2_data_hdr);
135 : }
136 59289 : dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) /
137 : sizeof(struct xfs_dir2_leaf_entry);
138 59289 : dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) /
139 : sizeof(xfs_dir2_data_off_t);
140 :
141 59289 : dageo->data_first_offset = dageo->data_entry_offset +
142 59289 : 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 59289 : dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
150 59289 : dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
151 59289 : dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
152 59289 : 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 59289 : mp->m_sb.sb_blocklog;
156 59289 : dageo->magicpct = (dageo->blksize * 37) / 100;
157 :
158 : /* set up attribute geometry - single fsb only */
159 59289 : dageo = mp->m_attr_geo;
160 59289 : dageo->blklog = mp->m_sb.sb_blocklog;
161 59289 : dageo->fsblog = mp->m_sb.sb_blocklog;
162 59289 : dageo->blksize = 1 << dageo->blklog;
163 59289 : dageo->fsbcount = 1;
164 59289 : dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
165 59289 : dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
166 : (uint)sizeof(xfs_da_node_entry_t);
167 :
168 59289 : if (xfs_has_large_extent_counts(mp))
169 59040 : dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
170 : else
171 249 : dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
172 :
173 59289 : dageo->magicpct = (dageo->blksize * 37) / 100;
174 59289 : return 0;
175 : }
176 :
177 : void
178 59296 : xfs_da_unmount(
179 : struct xfs_mount *mp)
180 : {
181 59296 : kmem_free(mp->m_dir_geo);
182 59296 : kmem_free(mp->m_attr_geo);
183 59296 : }
184 :
185 : /*
186 : * Return 1 if directory contains only "." and "..".
187 : */
188 : int
189 1583491 : xfs_dir_isempty(
190 : xfs_inode_t *dp)
191 : {
192 1583491 : xfs_dir2_sf_hdr_t *sfp;
193 :
194 1583491 : ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
195 1583491 : if (dp->i_disk_size == 0) /* might happen during shutdown. */
196 : return 1;
197 1583491 : if (dp->i_disk_size > xfs_inode_data_fork_size(dp))
198 : return 0;
199 1582967 : sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
200 1582967 : return !sfp->count;
201 : }
202 :
203 : /*
204 : * Validate a given inode number.
205 : */
206 : int
207 807153838 : xfs_dir_ino_validate(
208 : xfs_mount_t *mp,
209 : xfs_ino_t ino)
210 : {
211 807153838 : bool ino_ok = xfs_verify_dir_ino(mp, ino);
212 :
213 1614221054 : if (XFS_IS_CORRUPT(mp, !ino_ok) ||
214 807151410 : XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
215 11 : xfs_warn(mp, "Invalid inode number 0x%Lx",
216 : (unsigned long long) ino);
217 11 : return -EFSCORRUPTED;
218 : }
219 : return 0;
220 : }
221 :
222 : /*
223 : * Initialize a directory with its "." and ".." entries.
224 : */
225 : int
226 6561261 : xfs_dir_init(
227 : xfs_trans_t *tp,
228 : xfs_inode_t *dp,
229 : xfs_inode_t *pdp)
230 : {
231 6561261 : struct xfs_da_args *args;
232 6561261 : int error;
233 :
234 6561261 : ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
235 6561261 : error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
236 6560842 : if (error)
237 : return error;
238 :
239 6560945 : args = kmem_zalloc(sizeof(*args), KM_NOFS);
240 6560410 : if (!args)
241 : return -ENOMEM;
242 :
243 6560410 : args->geo = dp->i_mount->m_dir_geo;
244 6560410 : args->dp = dp;
245 6560410 : args->trans = tp;
246 6560410 : error = xfs_dir2_sf_create(args, pdp->i_ino);
247 6561803 : kmem_free(args);
248 6561803 : 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 115706814 : 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 115706814 : struct xfs_da_args *args;
264 115706814 : int rval;
265 115706814 : bool v;
266 :
267 115706814 : ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
268 :
269 115706814 : if (inum) {
270 115384438 : rval = xfs_dir_ino_validate(tp->t_mountp, inum);
271 115270144 : if (rval)
272 : return rval;
273 115270144 : XFS_STATS_INC(dp->i_mount, xs_dir_create);
274 : }
275 :
276 115629698 : args = kmem_zalloc(sizeof(*args), KM_NOFS);
277 115619468 : if (!args)
278 : return -ENOMEM;
279 :
280 115619468 : args->geo = dp->i_mount->m_dir_geo;
281 115619468 : args->name = name->name;
282 115619468 : args->namelen = name->len;
283 115619468 : args->filetype = name->type;
284 115619468 : args->hashval = xfs_dir2_hashname(dp->i_mount, name);
285 115605324 : args->inumber = inum;
286 115605324 : args->dp = dp;
287 115605324 : args->total = total;
288 115605324 : args->whichfork = XFS_DATA_FORK;
289 115605324 : args->trans = tp;
290 115605324 : args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
291 115605324 : if (!inum)
292 311524 : args->op_flags |= XFS_DA_OP_JUSTCHECK;
293 :
294 115605324 : if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
295 57710519 : rval = xfs_dir2_sf_addname(args);
296 57725917 : goto out_free;
297 : }
298 :
299 57894805 : rval = xfs_dir2_isblock(args, &v);
300 57949522 : if (rval)
301 0 : goto out_free;
302 57949522 : if (v) {
303 4816106 : rval = xfs_dir2_block_addname(args);
304 4820399 : goto out_free;
305 : }
306 :
307 53133416 : rval = xfs_dir2_isleaf(args, &v);
308 53184627 : if (rval)
309 0 : goto out_free;
310 53184627 : if (v)
311 14091194 : rval = xfs_dir2_leaf_addname(args);
312 : else
313 39093433 : rval = xfs_dir2_node_addname(args);
314 :
315 115725884 : out_free:
316 115725884 : kmem_free(args);
317 115725884 : 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 13593472 : xfs_dir_cilookup_result(
326 : struct xfs_da_args *args,
327 : const unsigned char *name,
328 : int len)
329 : {
330 13593472 : if (args->cmpresult == XFS_CMP_DIFFERENT)
331 : return -ENOENT;
332 13593472 : if (args->cmpresult != XFS_CMP_CASE ||
333 : !(args->op_flags & XFS_DA_OP_CILOOKUP))
334 : return -EEXIST;
335 :
336 484528 : args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
337 484528 : if (!args->value)
338 : return -ENOMEM;
339 :
340 969056 : memcpy(args->value, name, len);
341 484528 : args->valuelen = len;
342 484528 : 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 170483816 : 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 170483816 : struct xfs_da_args *args;
360 170483816 : int rval;
361 170483816 : bool v;
362 170483816 : int lock_mode;
363 :
364 170483816 : ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
365 170483816 : 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 170423196 : args = kmem_zalloc(sizeof(*args), KM_NOFS);
376 170551948 : args->geo = dp->i_mount->m_dir_geo;
377 170551948 : args->name = name->name;
378 170551948 : args->namelen = name->len;
379 170551948 : args->filetype = name->type;
380 170551948 : args->hashval = xfs_dir2_hashname(dp->i_mount, name);
381 170310212 : args->dp = dp;
382 170310212 : args->whichfork = XFS_DATA_FORK;
383 170310212 : args->trans = tp;
384 170310212 : args->op_flags = XFS_DA_OP_OKNOENT;
385 170310212 : if (ci_name)
386 1077139 : args->op_flags |= XFS_DA_OP_CILOOKUP;
387 :
388 170310212 : lock_mode = xfs_ilock_data_map_shared(dp);
389 170372623 : if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
390 101252725 : rval = xfs_dir2_sf_lookup(args);
391 101291123 : goto out_check_rval;
392 : }
393 :
394 69119898 : rval = xfs_dir2_isblock(args, &v);
395 69324436 : if (rval)
396 0 : goto out_free;
397 69324436 : if (v) {
398 7888318 : rval = xfs_dir2_block_lookup(args);
399 7904972 : goto out_check_rval;
400 : }
401 :
402 61436118 : rval = xfs_dir2_isleaf(args, &v);
403 61644578 : if (rval)
404 0 : goto out_free;
405 61644578 : if (v)
406 28299373 : rval = xfs_dir2_leaf_lookup(args);
407 : else
408 33345205 : rval = xfs_dir2_node_lookup(args);
409 :
410 170761565 : out_check_rval:
411 170761565 : if (rval == -EEXIST)
412 : rval = 0;
413 122930190 : if (!rval) {
414 47842887 : *inum = args->inumber;
415 47842887 : if (ci_name) {
416 684834 : ci_name->name = args->value;
417 684834 : ci_name->len = args->valuelen;
418 : }
419 : }
420 170076731 : out_free:
421 170761565 : xfs_iunlock(dp, lock_mode);
422 170399244 : kmem_free(args);
423 170619063 : return rval;
424 : }
425 :
426 : /*
427 : * Remove an entry from a directory.
428 : */
429 : int
430 85330825 : 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 85330825 : struct xfs_da_args *args;
438 85330825 : int rval;
439 85330825 : bool v;
440 :
441 85330825 : ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
442 85330825 : XFS_STATS_INC(dp->i_mount, xs_dir_remove);
443 :
444 85298603 : args = kmem_zalloc(sizeof(*args), KM_NOFS);
445 85297223 : if (!args)
446 : return -ENOMEM;
447 :
448 85297223 : args->geo = dp->i_mount->m_dir_geo;
449 85297223 : args->name = name->name;
450 85297223 : args->namelen = name->len;
451 85297223 : args->filetype = name->type;
452 85297223 : args->hashval = xfs_dir2_hashname(dp->i_mount, name);
453 85306119 : args->inumber = ino;
454 85306119 : args->dp = dp;
455 85306119 : args->total = total;
456 85306119 : args->whichfork = XFS_DATA_FORK;
457 85306119 : args->trans = tp;
458 :
459 85306119 : if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
460 34608364 : rval = xfs_dir2_sf_removename(args);
461 34609597 : goto out_free;
462 : }
463 :
464 50697755 : rval = xfs_dir2_isblock(args, &v);
465 50695063 : if (rval)
466 0 : goto out_free;
467 50695063 : if (v) {
468 2337249 : rval = xfs_dir2_block_removename(args);
469 2337888 : goto out_free;
470 : }
471 :
472 48357814 : rval = xfs_dir2_isleaf(args, &v);
473 48397548 : if (rval)
474 0 : goto out_free;
475 48397548 : if (v)
476 13137732 : rval = xfs_dir2_leaf_removename(args);
477 : else
478 35259816 : rval = xfs_dir2_node_removename(args);
479 85352889 : out_free:
480 85352889 : kmem_free(args);
481 85352889 : return rval;
482 : }
483 :
484 : /*
485 : * Replace the inode number of a directory entry.
486 : */
487 : int
488 47631976 : 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 47631976 : struct xfs_da_args *args;
496 47631976 : int rval;
497 47631976 : bool v;
498 :
499 47631976 : ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
500 :
501 47631976 : rval = xfs_dir_ino_validate(tp->t_mountp, inum);
502 47631940 : if (rval)
503 : return rval;
504 :
505 47631875 : args = kmem_zalloc(sizeof(*args), KM_NOFS);
506 47631931 : if (!args)
507 : return -ENOMEM;
508 :
509 47631931 : args->geo = dp->i_mount->m_dir_geo;
510 47631931 : args->name = name->name;
511 47631931 : args->namelen = name->len;
512 47631931 : args->filetype = name->type;
513 47631931 : args->hashval = xfs_dir2_hashname(dp->i_mount, name);
514 47631860 : args->inumber = inum;
515 47631860 : args->dp = dp;
516 47631860 : args->total = total;
517 47631860 : args->whichfork = XFS_DATA_FORK;
518 47631860 : args->trans = tp;
519 :
520 47631860 : if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
521 45921823 : rval = xfs_dir2_sf_replace(args);
522 45922034 : goto out_free;
523 : }
524 :
525 1710037 : rval = xfs_dir2_isblock(args, &v);
526 1710039 : if (rval)
527 0 : goto out_free;
528 1710039 : if (v) {
529 403231 : rval = xfs_dir2_block_replace(args);
530 403240 : goto out_free;
531 : }
532 :
533 1306808 : rval = xfs_dir2_isleaf(args, &v);
534 1306819 : if (rval)
535 0 : goto out_free;
536 1306819 : if (v)
537 617897 : rval = xfs_dir2_leaf_replace(args);
538 : else
539 688922 : rval = xfs_dir2_node_replace(args);
540 47632086 : out_free:
541 47632086 : kmem_free(args);
542 47632086 : return rval;
543 : }
544 :
545 : /*
546 : * See if this entry can be added to the directory without allocating space.
547 : */
548 : int
549 311534 : 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 311534 : 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 344676 : 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 344676 : struct xfs_inode *dp = args->dp;
574 344676 : struct xfs_mount *mp = dp->i_mount;
575 344676 : xfs_fileoff_t bno; /* directory offset of new block */
576 344676 : int count; /* count of filesystem blocks */
577 344676 : int error;
578 :
579 344676 : trace_xfs_dir2_grow_inode(args, space);
580 :
581 : /*
582 : * Set lowest possible block in the space requested.
583 : */
584 344666 : bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
585 344666 : count = args->geo->fsbcount;
586 :
587 344666 : error = xfs_da_grow_inode_int(args, &bno, count);
588 344666 : if (error)
589 : return error;
590 :
591 344656 : *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 344634 : if (space == XFS_DIR2_DATA_SPACE) {
597 335351 : xfs_fsize_t size; /* directory file (data) size */
598 :
599 335351 : size = XFS_FSB_TO_B(mp, bno + count);
600 335351 : if (size > dp->i_disk_size) {
601 334837 : dp->i_disk_size = size;
602 334837 : 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 325666242 : xfs_dir2_isblock(
613 : struct xfs_da_args *args,
614 : bool *isblock)
615 : {
616 325666242 : struct xfs_mount *mp = args->dp->i_mount;
617 325666242 : xfs_fileoff_t eof;
618 325666242 : int error;
619 :
620 325666242 : error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
621 325291800 : if (error)
622 : return error;
623 :
624 325291800 : *isblock = false;
625 325291800 : if (XFS_FSB_TO_B(mp, eof) != args->geo->blksize)
626 : return 0;
627 :
628 22868923 : *isblock = true;
629 22868923 : 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 281090582 : xfs_dir2_isleaf(
639 : struct xfs_da_args *args,
640 : bool *isleaf)
641 : {
642 281090582 : xfs_fileoff_t eof;
643 281090582 : int error;
644 :
645 281090582 : error = xfs_bmap_last_offset(args->dp, &eof, XFS_DATA_FORK);
646 281922293 : if (error)
647 : return error;
648 :
649 281922293 : *isleaf = false;
650 281922293 : if (eof != args->geo->leafblk + args->geo->fsbcount)
651 : return 0;
652 :
653 62806952 : *isleaf = true;
654 62806952 : 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 243597 : xfs_dir2_shrink_inode(
664 : struct xfs_da_args *args,
665 : xfs_dir2_db_t db,
666 : struct xfs_buf *bp)
667 : {
668 243597 : xfs_fileoff_t bno; /* directory file offset */
669 243597 : xfs_dablk_t da; /* directory file offset */
670 243597 : int done; /* bunmap is finished */
671 243597 : struct xfs_inode *dp;
672 243597 : int error;
673 243597 : struct xfs_mount *mp;
674 243597 : struct xfs_trans *tp;
675 :
676 243597 : trace_xfs_dir2_shrink_inode(args, db);
677 :
678 243595 : dp = args->dp;
679 243595 : mp = dp->i_mount;
680 243595 : tp = args->trans;
681 243595 : da = xfs_dir2_db_to_da(args->geo, db);
682 :
683 : /* Unmap the fsblock(s). */
684 243596 : error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
685 243593 : 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 243593 : ASSERT(done);
701 : /*
702 : * Invalidate the buffer from the transaction.
703 : */
704 243593 : xfs_trans_binval(tp, bp);
705 : /*
706 : * If it's not a data block, we're done.
707 : */
708 243598 : 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 236114 : if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
714 : return 0;
715 130696 : bno = da;
716 130696 : 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 130693 : if (db == args->geo->datablk)
723 118251 : ASSERT(bno == 0);
724 : else
725 12442 : ASSERT(bno > 0);
726 : /*
727 : * Set the size to the new last block.
728 : */
729 130693 : dp->i_disk_size = XFS_FSB_TO_B(mp, bno);
730 130693 : xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
731 130693 : return 0;
732 : }
733 :
734 : /* Returns true if the directory entry name is valid. */
735 : bool
736 16676974216 : 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 16676974216 : if (length >= MAXNAMELEN)
745 : return false;
746 :
747 : /* There shouldn't be any slashes or nulls here */
748 50151576711 : return !memchr(name, '/', length) && !memchr(name, 0, length);
749 : }
750 :
751 : xfs_dahash_t
752 2970519912 : xfs_dir2_hashname(
753 : struct xfs_mount *mp,
754 : const struct xfs_name *name)
755 : {
756 2970519912 : if (unlikely(xfs_has_asciici(mp)))
757 6775552 : return xfs_ascii_ci_hashname(name);
758 2963744360 : return xfs_da_hashname(name->name, name->len);
759 : }
760 :
761 : enum xfs_dacmp
762 3995226051 : xfs_dir2_compname(
763 : struct xfs_da_args *args,
764 : const unsigned char *name,
765 : int len)
766 : {
767 3995226051 : if (unlikely(xfs_has_asciici(args->dp->i_mount)))
768 1906247819 : return xfs_ascii_ci_compname(args, name, len);
769 2088978232 : return xfs_da_compname(args, name, len);
770 : }
|