hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/xfs/libxfs/xfs_dir2.c
....@@ -5,20 +5,16 @@
55 */
66 #include "xfs.h"
77 #include "xfs_fs.h"
8
+#include "xfs_shared.h"
89 #include "xfs_format.h"
910 #include "xfs_log_format.h"
1011 #include "xfs_trans_resv.h"
1112 #include "xfs_mount.h"
12
-#include "xfs_defer.h"
13
-#include "xfs_da_format.h"
14
-#include "xfs_da_btree.h"
1513 #include "xfs_inode.h"
1614 #include "xfs_trans.h"
17
-#include "xfs_inode_item.h"
1815 #include "xfs_bmap.h"
1916 #include "xfs_dir2.h"
2017 #include "xfs_dir2_priv.h"
21
-#include "xfs_ialloc.h"
2218 #include "xfs_errortag.h"
2319 #include "xfs_error.h"
2420 #include "xfs_trace.h"
....@@ -56,7 +52,7 @@
5652 * ASCII case-insensitive (ie. A-Z) support for directories that was
5753 * used in IRIX.
5854 */
59
-STATIC xfs_dahash_t
55
+xfs_dahash_t
6056 xfs_ascii_ci_hashname(
6157 struct xfs_name *name)
6258 {
....@@ -69,14 +65,14 @@
6965 return hash;
7066 }
7167
72
-STATIC enum xfs_dacmp
68
+enum xfs_dacmp
7369 xfs_ascii_ci_compname(
74
- struct xfs_da_args *args,
75
- const unsigned char *name,
76
- int len)
70
+ struct xfs_da_args *args,
71
+ const unsigned char *name,
72
+ int len)
7773 {
78
- enum xfs_dacmp result;
79
- int i;
74
+ enum xfs_dacmp result;
75
+ int i;
8076
8177 if (args->namelen != len)
8278 return XFS_CMP_DIFFERENT;
....@@ -93,30 +89,20 @@
9389 return result;
9490 }
9591
96
-static const struct xfs_nameops xfs_ascii_ci_nameops = {
97
- .hashname = xfs_ascii_ci_hashname,
98
- .compname = xfs_ascii_ci_compname,
99
-};
100
-
10192 int
10293 xfs_da_mount(
10394 struct xfs_mount *mp)
10495 {
10596 struct xfs_da_geometry *dageo;
106
- int nodehdr_size;
10797
10898
10999 ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
110100 ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
111101
112
- mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL);
113
- mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL);
114
-
115
- nodehdr_size = mp->m_dir_inode_ops->node_hdr_size;
116102 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
117
- KM_SLEEP | KM_MAYFAIL);
103
+ KM_MAYFAIL);
118104 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
119
- KM_SLEEP | KM_MAYFAIL);
105
+ KM_MAYFAIL);
120106 if (!mp->m_dir_geo || !mp->m_attr_geo) {
121107 kmem_free(mp->m_dir_geo);
122108 kmem_free(mp->m_attr_geo);
....@@ -129,6 +115,27 @@
129115 dageo->fsblog = mp->m_sb.sb_blocklog;
130116 dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
131117 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
118
+ if (xfs_sb_version_hascrc(&mp->m_sb)) {
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);
132139
133140 /*
134141 * Now we've set up the block conversion variables, we can calculate the
....@@ -137,7 +144,7 @@
137144 dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
138145 dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
139146 dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
140
- dageo->node_ents = (dageo->blksize - nodehdr_size) /
147
+ dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
141148 (uint)sizeof(xfs_da_node_entry_t);
142149 dageo->magicpct = (dageo->blksize * 37) / 100;
143150
....@@ -147,15 +154,10 @@
147154 dageo->fsblog = mp->m_sb.sb_blocklog;
148155 dageo->blksize = 1 << dageo->blklog;
149156 dageo->fsbcount = 1;
150
- dageo->node_ents = (dageo->blksize - nodehdr_size) /
157
+ dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
158
+ dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
151159 (uint)sizeof(xfs_da_node_entry_t);
152160 dageo->magicpct = (dageo->blksize * 37) / 100;
153
-
154
- if (xfs_sb_version_hasasciici(&mp->m_sb))
155
- mp->m_dirnameops = &xfs_ascii_ci_nameops;
156
- else
157
- mp->m_dirnameops = &xfs_default_nameops;
158
-
159161 return 0;
160162 }
161163
....@@ -195,10 +197,10 @@
195197 {
196198 bool ino_ok = xfs_verify_dir_ino(mp, ino);
197199
198
- if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE))) {
200
+ if (XFS_IS_CORRUPT(mp, !ino_ok) ||
201
+ XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
199202 xfs_warn(mp, "Invalid inode number 0x%Lx",
200203 (unsigned long long) ino);
201
- XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
202204 return -EFSCORRUPTED;
203205 }
204206 return 0;
....@@ -221,7 +223,7 @@
221223 if (error)
222224 return error;
223225
224
- args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
226
+ args = kmem_zalloc(sizeof(*args), KM_NOFS);
225227 if (!args)
226228 return -ENOMEM;
227229
....@@ -258,7 +260,7 @@
258260 XFS_STATS_INC(dp->i_mount, xs_dir_create);
259261 }
260262
261
- args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
263
+ args = kmem_zalloc(sizeof(*args), KM_NOFS);
262264 if (!args)
263265 return -ENOMEM;
264266
....@@ -266,7 +268,7 @@
266268 args->name = name->name;
267269 args->namelen = name->len;
268270 args->filetype = name->type;
269
- args->hashval = dp->i_mount->m_dirnameops->hashname(name);
271
+ args->hashval = xfs_dir2_hashname(dp->i_mount, name);
270272 args->inumber = inum;
271273 args->dp = dp;
272274 args->total = total;
....@@ -276,7 +278,7 @@
276278 if (!inum)
277279 args->op_flags |= XFS_DA_OP_JUSTCHECK;
278280
279
- if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
281
+ if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
280282 rval = xfs_dir2_sf_addname(args);
281283 goto out_free;
282284 }
....@@ -357,12 +359,12 @@
357359 * lockdep Doing this avoids having to add a bunch of lockdep class
358360 * annotations into the reclaim path for the ilock.
359361 */
360
- args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
362
+ args = kmem_zalloc(sizeof(*args), KM_NOFS);
361363 args->geo = dp->i_mount->m_dir_geo;
362364 args->name = name->name;
363365 args->namelen = name->len;
364366 args->filetype = name->type;
365
- args->hashval = dp->i_mount->m_dirnameops->hashname(name);
367
+ args->hashval = xfs_dir2_hashname(dp->i_mount, name);
366368 args->dp = dp;
367369 args->whichfork = XFS_DATA_FORK;
368370 args->trans = tp;
....@@ -371,7 +373,7 @@
371373 args->op_flags |= XFS_DA_OP_CILOOKUP;
372374
373375 lock_mode = xfs_ilock_data_map_shared(dp);
374
- if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
376
+ if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
375377 rval = xfs_dir2_sf_lookup(args);
376378 goto out_check_rval;
377379 }
....@@ -426,7 +428,7 @@
426428 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
427429 XFS_STATS_INC(dp->i_mount, xs_dir_remove);
428430
429
- args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
431
+ args = kmem_zalloc(sizeof(*args), KM_NOFS);
430432 if (!args)
431433 return -ENOMEM;
432434
....@@ -434,14 +436,14 @@
434436 args->name = name->name;
435437 args->namelen = name->len;
436438 args->filetype = name->type;
437
- args->hashval = dp->i_mount->m_dirnameops->hashname(name);
439
+ args->hashval = xfs_dir2_hashname(dp->i_mount, name);
438440 args->inumber = ino;
439441 args->dp = dp;
440442 args->total = total;
441443 args->whichfork = XFS_DATA_FORK;
442444 args->trans = tp;
443445
444
- if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
446
+ if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
445447 rval = xfs_dir2_sf_removename(args);
446448 goto out_free;
447449 }
....@@ -487,7 +489,7 @@
487489 if (rval)
488490 return rval;
489491
490
- args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS);
492
+ args = kmem_zalloc(sizeof(*args), KM_NOFS);
491493 if (!args)
492494 return -ENOMEM;
493495
....@@ -495,14 +497,14 @@
495497 args->name = name->name;
496498 args->namelen = name->len;
497499 args->filetype = name->type;
498
- args->hashval = dp->i_mount->m_dirnameops->hashname(name);
500
+ args->hashval = xfs_dir2_hashname(dp->i_mount, name);
499501 args->inumber = inum;
500502 args->dp = dp;
501503 args->total = total;
502504 args->whichfork = XFS_DATA_FORK;
503505 args->trans = tp;
504506
505
- if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
507
+ if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
506508 rval = xfs_dir2_sf_replace(args);
507509 goto out_free;
508510 }
....@@ -604,7 +606,9 @@
604606 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
605607 return rval;
606608 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
607
- if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
609
+ if (XFS_IS_CORRUPT(args->dp->i_mount,
610
+ rval != 0 &&
611
+ args->dp->i_d.di_size != args->geo->blksize))
608612 return -EFSCORRUPTED;
609613 *vp = rval;
610614 return 0;
....@@ -703,3 +707,41 @@
703707 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
704708 return 0;
705709 }
710
+
711
+/* Returns true if the directory entry name is valid. */
712
+bool
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
729
+xfs_dir2_hashname(
730
+ struct xfs_mount *mp,
731
+ struct xfs_name *name)
732
+{
733
+ if (unlikely(xfs_sb_version_hasasciici(&mp->m_sb)))
734
+ return xfs_ascii_ci_hashname(name);
735
+ return xfs_da_hashname(name->name, name->len);
736
+}
737
+
738
+enum xfs_dacmp
739
+xfs_dir2_compname(
740
+ struct xfs_da_args *args,
741
+ const unsigned char *name,
742
+ int len)
743
+{
744
+ if (unlikely(xfs_sb_version_hasasciici(&args->dp->i_mount->m_sb)))
745
+ return xfs_ascii_ci_compname(args, name, len);
746
+ return xfs_da_compname(args, name, len);
747
+}