xref: /linux/fs/xfs/libxfs/xfs_metadir.c (revision b477ff98d903618a1ab8247861f2ea6e70c0f0f8)
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