fs/xfs/xfs_ioctl.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/xfs_ioctl.c
Extension
.c
Size
36136 bytes
Lines
1473
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

switch (hdr->ino) {
		case XFS_BULK_IREQ_SPECIAL_ROOT:
			breq->startino = mp->m_sb.sb_rootino;
			break;
		default:
			return -EINVAL;
		}
		breq->icount = 1;
	}

	/*
	 * The IREQ_AGNO flag means that we only want results from a given AG.
	 * If @hdr->ino is zero, we start iterating in that AG.  If @hdr->ino is
	 * beyond the specified AG then we return no results.
	 */
	if (hdr->flags & XFS_BULK_IREQ_AGNO) {
		if (hdr->agno >= mp->m_sb.sb_agcount)
			return -EINVAL;

		if (breq->startino == 0)
			breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
		else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
			return -EINVAL;

		breq->iwalk_flags |= XFS_IWALK_SAME_AG;

		/* Asking for an inode past the end of the AG?  We're done! */
		if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
			return -ECANCELED;
	} else if (hdr->agno)
		return -EINVAL;

	/* Asking for an inode past the end of the FS?  We're done! */
	if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
		return -ECANCELED;

	if (hdr->flags & XFS_BULK_IREQ_NREXT64)
		breq->flags |= XFS_IBULK_NREXT64;

	/* Caller wants to see metadata directories in bulkstat output. */
	if (hdr->flags & XFS_BULK_IREQ_METADIR)
		breq->flags |= XFS_IBULK_METADIR;

	return 0;
}

/*
 * Update the userspace bulk request @hdr to reflect the end state of the
 * internal bulk request @breq.
 */
static void
xfs_bulk_ireq_teardown(
	struct xfs_bulk_ireq	*hdr,
	struct xfs_ibulk	*breq)
{
	hdr->ino = breq->startino;
	hdr->ocount = breq->ocount;
}

/* Handle the v5 bulkstat ioctl. */
STATIC int
xfs_ioc_bulkstat(
	struct file			*file,
	unsigned int			cmd,
	struct xfs_bulkstat_req __user	*arg)
{
	struct xfs_mount		*mp = XFS_I(file_inode(file))->i_mount;
	struct xfs_bulk_ireq		hdr;
	struct xfs_ibulk		breq = {
		.mp			= mp,
		.idmap			= file_mnt_idmap(file),
	};
	int				error;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (xfs_is_shutdown(mp))
		return -EIO;

	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
		return -EFAULT;

	error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);
	if (error == -ECANCELED)
		goto out_teardown;
	if (error < 0)
		return error;

	error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);

Annotation

Implementation Notes