fs/xfs/xfs_itable.c

Source file repositories/reference/linux-study-clean/fs/xfs/xfs_itable.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/xfs_itable.c
Extension
.c
Size
13494 bytes
Lines
485
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct xfs_bstat_chunk {
	bulkstat_one_fmt_pf	formatter;
	struct xfs_ibulk	*breq;
	struct xfs_bulkstat	*buf;
};

static inline bool
want_metadir_file(
	struct xfs_inode	*ip,
	struct xfs_ibulk	*breq)
{
	return xfs_is_metadir_inode(ip) && (breq->flags & XFS_IBULK_METADIR);
}

/*
 * Fill out the bulkstat info for a single inode and report it somewhere.
 *
 * bc->breq->lastino is effectively the inode cursor as we walk through the
 * filesystem.  Therefore, we update it any time we need to move the cursor
 * forward, regardless of whether or not we're sending any bstat information
 * back to userspace.  If the inode is internal metadata or, has been freed
 * out from under us, we just simply keep going.
 *
 * However, if any other type of error happens we want to stop right where we
 * are so that userspace will call back with exact number of the bad inode and
 * we can send back an error code.
 *
 * Note that if the formatter tells us there's no space left in the buffer we
 * move the cursor forward and abort the walk.
 */
STATIC int
xfs_bulkstat_one_int(
	struct xfs_mount	*mp,
	struct mnt_idmap	*idmap,
	struct xfs_trans	*tp,
	xfs_ino_t		ino,
	struct xfs_bstat_chunk	*bc)
{
	struct user_namespace	*sb_userns = mp->m_super->s_user_ns;
	struct xfs_inode	*ip;		/* incore inode pointer */
	struct inode		*inode;
	struct xfs_bulkstat	*buf = bc->buf;
	xfs_extnum_t		nextents;
	int			error = -EINVAL;
	vfsuid_t		vfsuid;
	vfsgid_t		vfsgid;

	error = xfs_iget(mp, tp, ino,
			 (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED),
			 XFS_ILOCK_SHARED, &ip);
	if (error == -ENOENT || error == -EINVAL)
		goto out_advance;
	if (error)
		goto out;

	/* Reload the incore unlinked list to avoid failure in inodegc. */
	if (xfs_inode_unlinked_incomplete(ip)) {
		error = xfs_inode_reload_unlinked_bucket(tp, ip);
		if (error) {
			xfs_iunlock(ip, XFS_ILOCK_SHARED);
			xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
			xfs_irele(ip);
			return error;
		}
	}

	ASSERT(ip != NULL);
	ASSERT(ip->i_imap.im_agbno != 0);
	inode = VFS_I(ip);
	vfsuid = i_uid_into_vfsuid(idmap, inode);
	vfsgid = i_gid_into_vfsgid(idmap, inode);

	/*
	 * If caller wants files from the metadata directories, push out the
	 * bare minimum information for enabling scrub.
	 */
	if (want_metadir_file(ip, bc->breq)) {
		memset(buf, 0, sizeof(*buf));
		buf->bs_ino = ino;
		buf->bs_gen = inode->i_generation;
		buf->bs_mode = inode->i_mode & S_IFMT;
		xfs_bulkstat_health(ip, buf);
		buf->bs_version = XFS_BULKSTAT_VERSION_V5;
		xfs_iunlock(ip, XFS_ILOCK_SHARED);
		xfs_irele(ip);

		error = bc->formatter(bc->breq, buf);
		if (!error || error == -ECANCELED)
			goto out_advance;
		goto out;

Annotation

Implementation Notes