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