/* * Metadata Directory Tree * ======================= * * These functions provide an abstraction layer for looking up, creating, and * deleting metadata inodes that live within a special metadata directory tree. * * This code does not manage the five existing metadata inodes: real time * bitmap & summary; and the user, group, and quotas. All other metadata * inodes must use only the xfs_meta{dir,file}_* functions. * * Callers wishing to create or hardlink a metadata inode must create an * xfs_metadir_update structure, call the appropriate xfs_metadir* function, * and then call xfs_metadir_commit or xfs_metadir_cancel to commit or cancel * the update. Files in the metadata directory tree currently cannot be * unlinked. * * When the metadir feature is enabled, all metadata inodes must have the * "metadata" inode flag set to prevent them from being exposed to the outside * world. * * Callers must take the ILOCK of any inode in the metadata directory tree to * synchronize access to that inode. It is never necessary to take the IOLOCK * or the MMAPLOCK since metadata inodes must not be exposed to user space.
*/
/* * Unlock and release resources after committing (or cancelling) a metadata * directory tree operation. The caller retains its reference to @upd->ip * and must release it explicitly.
*/ staticinlinevoid
xfs_metadir_teardown( struct xfs_metadir_update *upd, int error)
{
trace_xfs_metadir_teardown(upd, error);
if (upd->ppargs) {
xfs_parent_finish(upd->dp->i_mount, upd->ppargs);
upd->ppargs = NULL;
}
if (upd->ip) { if (upd->ip_locked)
xfs_iunlock(upd->ip, XFS_ILOCK_EXCL);
upd->ip_locked = false;
}
if (upd->dp_locked)
xfs_iunlock(upd->dp, XFS_ILOCK_EXCL);
upd->dp_locked = false;
}
/* * Begin the process of creating a metadata file by allocating transactions * and taking whatever resources we're going to need.
*/ int
xfs_metadir_start_create( struct xfs_metadir_update *upd)
{ struct xfs_mount *mp = upd->dp->i_mount; int error;
error = xfs_parent_start(mp, &upd->ppargs); if (error) return error;
/* * If we ever need the ability to create rt metadata files on a * pre-metadir filesystem, we'll need to dqattach the parent here. * Currently we assume that mkfs will create the files and quotacheck * will account for them.
*/
/* * Lock the parent directory if there is one. We can't ijoin it to * the transaction until after the child file has been created.
*/
xfs_ilock(upd->dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
upd->dp_locked = true;
/* * Create a metadata inode with the given @mode, and insert it into the * metadata directory tree at the given @upd->path. The path up to the final * component must already exist. The final path component must not exist. * * The new metadata inode will be attached to the update structure @upd->ip, * with the ILOCK held until the caller releases it. * * NOTE: This function may return a new inode to the caller even if it returns * a negative error code. If an inode is passed back, the caller must finish * setting up the inode before releasing it.
*/ int
xfs_metadir_create( struct xfs_metadir_update *upd,
umode_t mode)
{ struct xfs_icreate_args args = {
.pip = upd->dp,
.mode = mode,
}; struct xfs_name xname; struct xfs_dir_update du = {
.dp = upd->dp,
.name = &xname,
.ppargs = upd->ppargs,
}; struct xfs_mount *mp = upd->dp->i_mount;
xfs_ino_t ino; unsignedint resblks; int error;
xfs_assert_ilocked(upd->dp, XFS_ILOCK_EXCL);
/* Check that the name does not already exist in the directory. */
xfs_metadir_set_xname(&xname, upd->path, XFS_DIR3_FT_UNKNOWN);
error = xfs_metadir_lookup(upd->tp, upd->dp, &xname, &ino); switch (error) { case -ENOENT: break; case 0:
error = -EEXIST;
fallthrough; default: return error;
}
/* * A newly created regular or special file just has one directory * entry pointing to them, but a directory also the "." entry * pointing to itself.
*/
error = xfs_dialloc(&upd->tp, &args, &ino); if (error) return error;
error = xfs_icreate(upd->tp, ino, &args, &upd->ip); if (error) return error;
du.ip = upd->ip;
xfs_metafile_set_iflag(upd->tp, upd->ip, upd->metafile_type);
upd->ip_locked = true;
/* * Join the directory inode to the transaction. We do not do it * earlier because xfs_dialloc rolls the transaction.
*/
xfs_trans_ijoin(upd->tp, upd->dp, 0);
/* Create the entry. */ if (S_ISDIR(args.mode))
resblks = xfs_mkdir_space_res(mp, xname.len); else
resblks = xfs_create_space_res(mp, xname.len);
xname.type = xfs_mode_to_ftype(args.mode);
trace_xfs_metadir_try_create(upd);
error = xfs_dir_create_child(upd->tp, resblks, &du); if (error) return error;
/* Metadir files are not accounted to quota. */
trace_xfs_metadir_create(upd);
return 0;
}
#ifndef __KERNEL__ /* * Begin the process of linking a metadata file by allocating transactions * and locking whatever resources we're going to need.
*/ int
xfs_metadir_start_link( struct xfs_metadir_update *upd)
{ struct xfs_mount *mp = upd->dp->i_mount; unsignedint resblks; int nospace_error = 0; int error;
/* * Link the metadata directory given by @path to the inode @upd->ip. * The path (up to the final component) must already exist, but the final * component must not already exist.
*/ int
xfs_metadir_link( struct xfs_metadir_update *upd)
{ struct xfs_name xname; struct xfs_dir_update du = {
.dp = upd->dp,
.name = &xname,
.ip = upd->ip,
.ppargs = upd->ppargs,
}; struct xfs_mount *mp = upd->dp->i_mount;
xfs_ino_t ino; unsignedint resblks; int error;
/* Look up the name in the current directory. */
xfs_metadir_set_xname(&xname, upd->path,
xfs_mode_to_ftype(VFS_I(upd->ip)->i_mode));
error = xfs_metadir_lookup(upd->tp, upd->dp, &xname, &ino); switch (error) { case -ENOENT: break; case 0:
error = -EEXIST;
fallthrough; default: return error;
}
/* Cancel a metadir update and unlock/drop all resources. */ void
xfs_metadir_cancel( struct xfs_metadir_update *upd, int error)
{
trace_xfs_metadir_cancel(upd);
xfs_trans_cancel(upd->tp);
upd->tp = NULL;
xfs_metadir_teardown(upd, error);
}
/* Create a metadata for the last component of the path. */ int
xfs_metadir_mkdir( struct xfs_inode *dp, constchar *path, struct xfs_inode **ipp)
{ struct xfs_metadir_update upd = {
.dp = dp,
.path = path,
.metafile_type = XFS_METAFILE_DIR,
}; int error;
if (xfs_is_shutdown(dp->i_mount)) return -EIO;
/* Allocate a transaction to create the last directory. */
error = xfs_metadir_start_create(&upd); if (error) return error;
/* Create the subdirectory and take our reference. */
error = xfs_metadir_create(&upd, S_IFDIR); if (error) goto out_cancel;
error = xfs_metadir_commit(&upd); if (error) goto out_irele;
out_cancel:
xfs_metadir_cancel(&upd, error);
out_irele: /* Have to finish setting up the inode to ensure it's deleted. */ if (upd.ip) {
xfs_finish_inode_setup(upd.ip);
xfs_irele(upd.ip);
} return error;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.