STATIC int xfs_fs_set_xstate( struct super_block *sb, unsigned int uflags, int op) { struct xfs_mount *mp = XFS_M(sb); unsigned int flags = 0; if (sb->s_flags & MS_RDONLY) return -EROFS; if (!XFS_IS_QUOTA_RUNNING(mp)) return -ENOSYS; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (uflags & XFS_QUOTA_UDQ_ACCT) flags |= XFS_UQUOTA_ACCT; if (uflags & XFS_QUOTA_PDQ_ACCT) flags |= XFS_PQUOTA_ACCT; if (uflags & XFS_QUOTA_GDQ_ACCT) flags |= XFS_GQUOTA_ACCT; if (uflags & XFS_QUOTA_UDQ_ENFD) flags |= XFS_UQUOTA_ENFD; if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD)) flags |= XFS_OQUOTA_ENFD; switch (op) { case Q_XQUOTAON: return -xfs_qm_scall_quotaon(mp, flags); case Q_XQUOTAOFF: if (!XFS_IS_QUOTA_ON(mp)) return -EINVAL; return -xfs_qm_scall_quotaoff(mp, flags); case Q_XQUOTARM: if (XFS_IS_QUOTA_ON(mp)) return -EINVAL; return -xfs_qm_scall_trunc_qfiles(mp, flags); } return -EINVAL; }
STATIC int xfs_fs_rm_xquota( struct super_block *sb, unsigned int uflags) { struct xfs_mount *mp = XFS_M(sb); unsigned int flags = 0; if (sb->s_flags & MS_RDONLY) return -EROFS; if (XFS_IS_QUOTA_ON(mp)) return -EINVAL; if (uflags & FS_USER_QUOTA) flags |= XFS_DQ_USER; if (uflags & FS_GROUP_QUOTA) flags |= XFS_DQ_GROUP; if (uflags & FS_PROJ_QUOTA) flags |= XFS_DQ_PROJ; return xfs_qm_scall_trunc_qfiles(mp, flags); }
/* * The main distribution switch of all XFS quotactl system calls. */ int xfs_qm_quotactl( struct bhv_desc *bdp, int cmd, int id, xfs_caddr_t addr) { xfs_mount_t *mp; bhv_vfs_t *vfsp; int error; vfsp = bhvtovfs(bdp); mp = XFS_VFSTOM(vfsp); ASSERT(addr != NULL || cmd == Q_XQUOTASYNC); /* * The following commands are valid even when quotaoff. */ switch (cmd) { case Q_XQUOTARM: /* * Truncate quota files. quota must be off. */ if (XFS_IS_QUOTA_ON(mp)) return XFS_ERROR(EINVAL); if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); return (xfs_qm_scall_trunc_qfiles(mp, xfs_qm_import_qtype_flags(*(uint *)addr))); case Q_XGETQSTAT: /* * Get quota status information. */ return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); case Q_XQUOTAON: /* * QUOTAON - enabling quota enforcement. * Quota accounting must be turned on at mount time. */ if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); return (xfs_qm_scall_quotaon(mp, xfs_qm_import_flags(*(uint *)addr))); case Q_XQUOTAOFF: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); break; case Q_XQUOTASYNC: return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL)); default: break; } if (! XFS_IS_QUOTA_ON(mp)) return XFS_ERROR(ESRCH); switch (cmd) { case Q_XQUOTAOFF: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_quotaoff(mp, xfs_qm_import_flags(*(uint *)addr), B_FALSE); break; case Q_XGETQUOTA: error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, (fs_disk_quota_t *)addr); break; case Q_XGETGQUOTA: error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, (fs_disk_quota_t *)addr); break; case Q_XGETPQUOTA: error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ, (fs_disk_quota_t *)addr); break; case Q_XSETQLIM: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, (fs_disk_quota_t *)addr); break; case Q_XSETGQLIM: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, (fs_disk_quota_t *)addr); break; case Q_XSETPQLIM: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ, (fs_disk_quota_t *)addr); break; default: error = XFS_ERROR(EINVAL); break; } return (error); }
/* * The main distribution switch of all XFS quotactl system calls. */ int xfs_qm_quotactl( struct bhv_desc *bdp, int cmd, int id, xfs_caddr_t addr) { xfs_mount_t *mp; int error; struct vfs *vfsp; vfsp = bhvtovfs(bdp); mp = XFS_VFSTOM(vfsp); if (addr == NULL && cmd != Q_SYNC) return XFS_ERROR(EINVAL); if (id < 0 && cmd != Q_SYNC) return XFS_ERROR(EINVAL); /* * The following commands are valid even when quotaoff. */ switch (cmd) { /* * truncate quota files. quota must be off. */ case Q_XQUOTARM: if (XFS_IS_QUOTA_ON(mp) || addr == NULL) return XFS_ERROR(EINVAL); if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); return (xfs_qm_scall_trunc_qfiles(mp, xfs_qm_import_qtype_flags(*(uint *)addr))); /* * Get quota status information. */ case Q_XGETQSTAT: return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); /* * QUOTAON for root f/s and quota enforcement on others.. * Quota accounting for non-root f/s's must be turned on * at mount time. */ case Q_XQUOTAON: if (addr == NULL) return XFS_ERROR(EINVAL); if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); return (xfs_qm_scall_quotaon(mp, xfs_qm_import_flags(*(uint *)addr))); case Q_XQUOTAOFF: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); break; default: break; } if (! XFS_IS_QUOTA_ON(mp)) return XFS_ERROR(ESRCH); switch (cmd) { case Q_XQUOTAOFF: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_quotaoff(mp, xfs_qm_import_flags(*(uint *)addr), B_FALSE); break; /* * Defaults to XFS_GETUQUOTA. */ case Q_XGETQUOTA: error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, (fs_disk_quota_t *)addr); break; /* * Set limits, both hard and soft. Defaults to Q_SETUQLIM. */ case Q_XSETQLIM: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, (fs_disk_quota_t *)addr); break; case Q_XSETGQLIM: if (vfsp->vfs_flag & VFS_RDONLY) return XFS_ERROR(EROFS); error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, (fs_disk_quota_t *)addr); break; case Q_XGETGQUOTA: error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, (fs_disk_quota_t *)addr); break; /* * Quotas are entirely undefined after quotaoff in XFS quotas. * For instance, there's no way to set limits when quotaoff. */ default: error = XFS_ERROR(EINVAL); break; } return (error); }