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