1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2018-2024 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
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_bit.h"
13 #include "xfs_sb.h"
14 #include "xfs_mount.h"
15 #include "xfs_defer.h"
16 #include "xfs_trans.h"
17 #include "xfs_metafile.h"
18 #include "xfs_metadir.h"
19 #include "xfs_trace.h"
20 #include "xfs_inode.h"
21 #include "xfs_quota.h"
22 #include "xfs_ialloc.h"
23 #include "xfs_bmap_btree.h"
24 #include "xfs_da_format.h"
25 #include "xfs_da_btree.h"
26 #include "xfs_trans_space.h"
27 #include "xfs_ag.h"
28 #include "xfs_dir2.h"
29 #include "xfs_dir2_priv.h"
30 #include "xfs_parent.h"
31 #include "xfs_health.h"
32 #include "xfs_errortag.h"
33 #include "xfs_error.h"
34 #include "xfs_btree.h"
35 #include "xfs_alloc.h"
36
37 /*
38 * Metadata Directory Tree
39 * =======================
40 *
41 * These functions provide an abstraction layer for looking up, creating, and
42 * deleting metadata inodes that live within a special metadata directory tree.
43 *
44 * This code does not manage the five existing metadata inodes: real time
45 * bitmap & summary; and the user, group, and quotas. All other metadata
46 * inodes must use only the xfs_meta{dir,file}_* functions.
47 *
48 * Callers wishing to create or hardlink a metadata inode must create an
49 * xfs_metadir_update structure, call the appropriate xfs_metadir* function,
50 * and then call xfs_metadir_commit or xfs_metadir_cancel to commit or cancel
51 * the update. Files in the metadata directory tree currently cannot be
52 * unlinked.
53 *
54 * When the metadir feature is enabled, all metadata inodes must have the
55 * "metadata" inode flag set to prevent them from being exposed to the outside
56 * world.
57 *
58 * Callers must take the ILOCK of any inode in the metadata directory tree to
59 * synchronize access to that inode. It is never necessary to take the IOLOCK
60 * or the MMAPLOCK since metadata inodes must not be exposed to user space.
61 */
62
63 static inline void
xfs_metadir_set_xname(struct xfs_name * xname,const char * path,unsigned char ftype)64 xfs_metadir_set_xname(
65 struct xfs_name *xname,
66 const char *path,
67 unsigned char ftype)
68 {
69 xname->name = (const unsigned char *)path;
70 xname->len = strlen(path);
71 xname->type = ftype;
72 }
73
74 /*
75 * Given a parent directory @dp and a metadata inode path component @xname,
76 * Look up the inode number in the directory, returning it in @ino.
77 * @xname.type must match the directory entry's ftype.
78 *
79 * Caller must hold ILOCK_EXCL.
80 */
81 static inline int
xfs_metadir_lookup(struct xfs_trans * tp,struct xfs_inode * dp,struct xfs_name * xname,xfs_ino_t * ino)82 xfs_metadir_lookup(
83 struct xfs_trans *tp,
84 struct xfs_inode *dp,
85 struct xfs_name *xname,
86 xfs_ino_t *ino)
87 {
88 struct xfs_mount *mp = dp->i_mount;
89 struct xfs_da_args args = {
90 .trans = tp,
91 .dp = dp,
92 .geo = mp->m_dir_geo,
93 .name = xname->name,
94 .namelen = xname->len,
95 .hashval = xfs_dir2_hashname(mp, xname),
96 .whichfork = XFS_DATA_FORK,
97 .op_flags = XFS_DA_OP_OKNOENT,
98 .owner = dp->i_ino,
99 };
100 int error;
101
102 if (!S_ISDIR(VFS_I(dp)->i_mode)) {
103 xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
104 return -EFSCORRUPTED;
105 }
106 if (xfs_is_shutdown(mp))
107 return -EIO;
108
109 error = xfs_dir_lookup_args(&args);
110 if (error)
111 return error;
112
113 if (!xfs_verify_ino(mp, args.inumber)) {
114 xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
115 return -EFSCORRUPTED;
116 }
117 if (xname->type != XFS_DIR3_FT_UNKNOWN && xname->type != args.filetype) {
118 xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR);
119 return -EFSCORRUPTED;
120 }
121
122 trace_xfs_metadir_lookup(dp, xname, args.inumber);
123 *ino = args.inumber;
124 return 0;
125 }
126
127 /*
128 * Look up and read a metadata inode from the metadata directory. If the path
129 * component doesn't exist, return -ENOENT.
130 */
131 int
xfs_metadir_load(struct xfs_trans * tp,struct xfs_inode * dp,const char * path,enum xfs_metafile_type metafile_type,struct xfs_inode ** ipp)132 xfs_metadir_load(
133 struct xfs_trans *tp,
134 struct xfs_inode *dp,
135 const char *path,
136 enum xfs_metafile_type metafile_type,
137 struct xfs_inode **ipp)
138 {
139 struct xfs_name xname;
140 xfs_ino_t ino;
141 int error;
142
143 xfs_metadir_set_xname(&xname, path, XFS_DIR3_FT_UNKNOWN);
144
145 xfs_ilock(dp, XFS_ILOCK_EXCL);
146 error = xfs_metadir_lookup(tp, dp, &xname, &ino);
147 xfs_iunlock(dp, XFS_ILOCK_EXCL);
148 if (error)
149 return error;
150 return xfs_trans_metafile_iget(tp, ino, metafile_type, ipp);
151 }
152
153 /*
154 * Unlock and release resources after committing (or cancelling) a metadata
155 * directory tree operation. The caller retains its reference to @upd->ip
156 * and must release it explicitly.
157 */
158 static inline void
xfs_metadir_teardown(struct xfs_metadir_update * upd,int error)159 xfs_metadir_teardown(
160 struct xfs_metadir_update *upd,
161 int error)
162 {
163 trace_xfs_metadir_teardown(upd, error);
164
165 if (upd->ppargs) {
166 xfs_parent_finish(upd->dp->i_mount, upd->ppargs);
167 upd->ppargs = NULL;
168 }
169
170 if (upd->ip) {
171 if (upd->ip_locked)
172 xfs_iunlock(upd->ip, XFS_ILOCK_EXCL);
173 upd->ip_locked = false;
174 }
175
176 if (upd->dp_locked)
177 xfs_iunlock(upd->dp, XFS_ILOCK_EXCL);
178 upd->dp_locked = false;
179 }
180
181 /*
182 * Begin the process of creating a metadata file by allocating transactions
183 * and taking whatever resources we're going to need.
184 */
185 int
xfs_metadir_start_create(struct xfs_metadir_update * upd)186 xfs_metadir_start_create(
187 struct xfs_metadir_update *upd)
188 {
189 struct xfs_mount *mp = upd->dp->i_mount;
190 int error;
191
192 ASSERT(upd->dp != NULL);
193 ASSERT(upd->ip == NULL);
194 ASSERT(xfs_has_metadir(mp));
195 ASSERT(upd->metafile_type != XFS_METAFILE_UNKNOWN);
196
197 error = xfs_parent_start(mp, &upd->ppargs);
198 if (error)
199 return error;
200
201 /*
202 * If we ever need the ability to create rt metadata files on a
203 * pre-metadir filesystem, we'll need to dqattach the parent here.
204 * Currently we assume that mkfs will create the files and quotacheck
205 * will account for them.
206 */
207
208 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_create,
209 xfs_create_space_res(mp, MAXNAMELEN), 0, 0, &upd->tp);
210 if (error)
211 goto out_teardown;
212
213 /*
214 * Lock the parent directory if there is one. We can't ijoin it to
215 * the transaction until after the child file has been created.
216 */
217 xfs_ilock(upd->dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
218 upd->dp_locked = true;
219
220 trace_xfs_metadir_start_create(upd);
221 return 0;
222 out_teardown:
223 xfs_metadir_teardown(upd, error);
224 return error;
225 }
226
227 /*
228 * Create a metadata inode with the given @mode, and insert it into the
229 * metadata directory tree at the given @upd->path. The path up to the final
230 * component must already exist. The final path component must not exist.
231 *
232 * The new metadata inode will be attached to the update structure @upd->ip,
233 * with the ILOCK held until the caller releases it.
234 *
235 * NOTE: This function may return a new inode to the caller even if it returns
236 * a negative error code. If an inode is passed back, the caller must finish
237 * setting up the inode before releasing it.
238 */
239 int
xfs_metadir_create(struct xfs_metadir_update * upd,umode_t mode)240 xfs_metadir_create(
241 struct xfs_metadir_update *upd,
242 umode_t mode)
243 {
244 struct xfs_icreate_args args = {
245 .pip = upd->dp,
246 .mode = mode,
247 };
248 struct xfs_name xname;
249 struct xfs_dir_update du = {
250 .dp = upd->dp,
251 .name = &xname,
252 .ppargs = upd->ppargs,
253 };
254 struct xfs_mount *mp = upd->dp->i_mount;
255 xfs_ino_t ino;
256 unsigned int resblks;
257 int error;
258
259 xfs_assert_ilocked(upd->dp, XFS_ILOCK_EXCL);
260
261 /* Check that the name does not already exist in the directory. */
262 xfs_metadir_set_xname(&xname, upd->path, XFS_DIR3_FT_UNKNOWN);
263 error = xfs_metadir_lookup(upd->tp, upd->dp, &xname, &ino);
264 switch (error) {
265 case -ENOENT:
266 break;
267 case 0:
268 error = -EEXIST;
269 fallthrough;
270 default:
271 return error;
272 }
273
274 /*
275 * A newly created regular or special file just has one directory
276 * entry pointing to them, but a directory also the "." entry
277 * pointing to itself.
278 */
279 error = xfs_dialloc(&upd->tp, &args, &ino);
280 if (error)
281 return error;
282 error = xfs_icreate(upd->tp, ino, &args, &upd->ip);
283 if (error)
284 return error;
285 du.ip = upd->ip;
286 xfs_metafile_set_iflag(upd->tp, upd->ip, upd->metafile_type);
287 upd->ip_locked = true;
288
289 /*
290 * Join the directory inode to the transaction. We do not do it
291 * earlier because xfs_dialloc rolls the transaction.
292 */
293 xfs_trans_ijoin(upd->tp, upd->dp, 0);
294
295 /* Create the entry. */
296 if (S_ISDIR(args.mode))
297 resblks = xfs_mkdir_space_res(mp, xname.len);
298 else
299 resblks = xfs_create_space_res(mp, xname.len);
300 xname.type = xfs_mode_to_ftype(args.mode);
301
302 trace_xfs_metadir_try_create(upd);
303
304 error = xfs_dir_create_child(upd->tp, resblks, &du);
305 if (error)
306 return error;
307
308 /* Metadir files are not accounted to quota. */
309
310 trace_xfs_metadir_create(upd);
311
312 return 0;
313 }
314
315 #ifndef __KERNEL__
316 /*
317 * Begin the process of linking a metadata file by allocating transactions
318 * and locking whatever resources we're going to need.
319 */
320 int
xfs_metadir_start_link(struct xfs_metadir_update * upd)321 xfs_metadir_start_link(
322 struct xfs_metadir_update *upd)
323 {
324 struct xfs_mount *mp = upd->dp->i_mount;
325 unsigned int resblks;
326 int nospace_error = 0;
327 int error;
328
329 ASSERT(upd->dp != NULL);
330 ASSERT(upd->ip != NULL);
331 ASSERT(xfs_has_metadir(mp));
332
333 error = xfs_parent_start(mp, &upd->ppargs);
334 if (error)
335 return error;
336
337 resblks = xfs_link_space_res(mp, MAXNAMELEN);
338 error = xfs_trans_alloc_dir(upd->dp, &M_RES(mp)->tr_link, upd->ip,
339 &resblks, &upd->tp, &nospace_error);
340 if (error)
341 goto out_teardown;
342 if (!resblks) {
343 /* We don't allow reservationless updates. */
344 xfs_trans_cancel(upd->tp);
345 upd->tp = NULL;
346 xfs_iunlock(upd->dp, XFS_ILOCK_EXCL);
347 xfs_iunlock(upd->ip, XFS_ILOCK_EXCL);
348 error = nospace_error;
349 goto out_teardown;
350 }
351
352 upd->dp_locked = true;
353 upd->ip_locked = true;
354
355 trace_xfs_metadir_start_link(upd);
356 return 0;
357 out_teardown:
358 xfs_metadir_teardown(upd, error);
359 return error;
360 }
361
362 /*
363 * Link the metadata directory given by @path to the inode @upd->ip.
364 * The path (up to the final component) must already exist, but the final
365 * component must not already exist.
366 */
367 int
xfs_metadir_link(struct xfs_metadir_update * upd)368 xfs_metadir_link(
369 struct xfs_metadir_update *upd)
370 {
371 struct xfs_name xname;
372 struct xfs_dir_update du = {
373 .dp = upd->dp,
374 .name = &xname,
375 .ip = upd->ip,
376 .ppargs = upd->ppargs,
377 };
378 struct xfs_mount *mp = upd->dp->i_mount;
379 xfs_ino_t ino;
380 unsigned int resblks;
381 int error;
382
383 xfs_assert_ilocked(upd->dp, XFS_ILOCK_EXCL);
384 xfs_assert_ilocked(upd->ip, XFS_ILOCK_EXCL);
385
386 /* Look up the name in the current directory. */
387 xfs_metadir_set_xname(&xname, upd->path,
388 xfs_mode_to_ftype(VFS_I(upd->ip)->i_mode));
389 error = xfs_metadir_lookup(upd->tp, upd->dp, &xname, &ino);
390 switch (error) {
391 case -ENOENT:
392 break;
393 case 0:
394 error = -EEXIST;
395 fallthrough;
396 default:
397 return error;
398 }
399
400 resblks = xfs_link_space_res(mp, xname.len);
401 error = xfs_dir_add_child(upd->tp, resblks, &du);
402 if (error)
403 return error;
404
405 trace_xfs_metadir_link(upd);
406
407 return 0;
408 }
409 #endif /* ! __KERNEL__ */
410
411 /* Commit a metadir update and unlock/drop all resources. */
412 int
xfs_metadir_commit(struct xfs_metadir_update * upd)413 xfs_metadir_commit(
414 struct xfs_metadir_update *upd)
415 {
416 int error;
417
418 trace_xfs_metadir_commit(upd);
419
420 error = xfs_trans_commit(upd->tp);
421 upd->tp = NULL;
422
423 xfs_metadir_teardown(upd, error);
424 return error;
425 }
426
427 /* Cancel a metadir update and unlock/drop all resources. */
428 void
xfs_metadir_cancel(struct xfs_metadir_update * upd,int error)429 xfs_metadir_cancel(
430 struct xfs_metadir_update *upd,
431 int error)
432 {
433 trace_xfs_metadir_cancel(upd);
434
435 xfs_trans_cancel(upd->tp);
436 upd->tp = NULL;
437
438 xfs_metadir_teardown(upd, error);
439 }
440
441 /* Create a metadata for the last component of the path. */
442 int
xfs_metadir_mkdir(struct xfs_inode * dp,const char * path,struct xfs_inode ** ipp)443 xfs_metadir_mkdir(
444 struct xfs_inode *dp,
445 const char *path,
446 struct xfs_inode **ipp)
447 {
448 struct xfs_metadir_update upd = {
449 .dp = dp,
450 .path = path,
451 .metafile_type = XFS_METAFILE_DIR,
452 };
453 int error;
454
455 if (xfs_is_shutdown(dp->i_mount))
456 return -EIO;
457
458 /* Allocate a transaction to create the last directory. */
459 error = xfs_metadir_start_create(&upd);
460 if (error)
461 return error;
462
463 /* Create the subdirectory and take our reference. */
464 error = xfs_metadir_create(&upd, S_IFDIR);
465 if (error)
466 goto out_cancel;
467
468 error = xfs_metadir_commit(&upd);
469 if (error)
470 goto out_irele;
471
472 xfs_finish_inode_setup(upd.ip);
473 *ipp = upd.ip;
474 return 0;
475
476 out_cancel:
477 xfs_metadir_cancel(&upd, error);
478 out_irele:
479 /* Have to finish setting up the inode to ensure it's deleted. */
480 if (upd.ip) {
481 xfs_finish_inode_setup(upd.ip);
482 xfs_irele(upd.ip);
483 }
484 return error;
485 }
486