1 /* 2 * Copyright (c) 2008, Christoph Hellwig 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 #include "xfs.h" 19 #include "xfs_format.h" 20 #include "xfs_trans_resv.h" 21 #include "xfs_log.h" 22 #include "xfs_sb.h" 23 #include "xfs_ag.h" 24 #include "xfs_mount.h" 25 #include "xfs_quota.h" 26 #include "xfs_trans.h" 27 #include "xfs_bmap_btree.h" 28 #include "xfs_inode.h" 29 #include "xfs_qm.h" 30 #include <linux/quota.h> 31 32 33 STATIC int 34 xfs_quota_type(int type) 35 { 36 switch (type) { 37 case USRQUOTA: 38 return XFS_DQ_USER; 39 case GRPQUOTA: 40 return XFS_DQ_GROUP; 41 default: 42 return XFS_DQ_PROJ; 43 } 44 } 45 46 STATIC int 47 xfs_fs_get_xstate( 48 struct super_block *sb, 49 struct fs_quota_stat *fqs) 50 { 51 struct xfs_mount *mp = XFS_M(sb); 52 53 if (!XFS_IS_QUOTA_RUNNING(mp)) 54 return -ENOSYS; 55 return -xfs_qm_scall_getqstat(mp, fqs); 56 } 57 58 STATIC int 59 xfs_fs_get_xstatev( 60 struct super_block *sb, 61 struct fs_quota_statv *fqs) 62 { 63 struct xfs_mount *mp = XFS_M(sb); 64 65 if (!XFS_IS_QUOTA_RUNNING(mp)) 66 return -ENOSYS; 67 return -xfs_qm_scall_getqstatv(mp, fqs); 68 } 69 70 STATIC int 71 xfs_fs_set_xstate( 72 struct super_block *sb, 73 unsigned int uflags, 74 int op) 75 { 76 struct xfs_mount *mp = XFS_M(sb); 77 unsigned int flags = 0; 78 79 if (sb->s_flags & MS_RDONLY) 80 return -EROFS; 81 if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp)) 82 return -ENOSYS; 83 84 if (uflags & FS_QUOTA_UDQ_ACCT) 85 flags |= XFS_UQUOTA_ACCT; 86 if (uflags & FS_QUOTA_PDQ_ACCT) 87 flags |= XFS_PQUOTA_ACCT; 88 if (uflags & FS_QUOTA_GDQ_ACCT) 89 flags |= XFS_GQUOTA_ACCT; 90 if (uflags & FS_QUOTA_UDQ_ENFD) 91 flags |= XFS_UQUOTA_ENFD; 92 if (uflags & FS_QUOTA_GDQ_ENFD) 93 flags |= XFS_GQUOTA_ENFD; 94 if (uflags & FS_QUOTA_PDQ_ENFD) 95 flags |= XFS_PQUOTA_ENFD; 96 97 switch (op) { 98 case Q_XQUOTAON: 99 return -xfs_qm_scall_quotaon(mp, flags); 100 case Q_XQUOTAOFF: 101 if (!XFS_IS_QUOTA_ON(mp)) 102 return -EINVAL; 103 return -xfs_qm_scall_quotaoff(mp, flags); 104 case Q_XQUOTARM: 105 if (XFS_IS_QUOTA_ON(mp)) 106 return -EINVAL; 107 return -xfs_qm_scall_trunc_qfiles(mp, flags); 108 } 109 110 return -EINVAL; 111 } 112 113 STATIC int 114 xfs_fs_get_dqblk( 115 struct super_block *sb, 116 struct kqid qid, 117 struct fs_disk_quota *fdq) 118 { 119 struct xfs_mount *mp = XFS_M(sb); 120 121 if (!XFS_IS_QUOTA_RUNNING(mp)) 122 return -ENOSYS; 123 if (!XFS_IS_QUOTA_ON(mp)) 124 return -ESRCH; 125 126 return -xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid), 127 xfs_quota_type(qid.type), fdq); 128 } 129 130 STATIC int 131 xfs_fs_set_dqblk( 132 struct super_block *sb, 133 struct kqid qid, 134 struct fs_disk_quota *fdq) 135 { 136 struct xfs_mount *mp = XFS_M(sb); 137 138 if (sb->s_flags & MS_RDONLY) 139 return -EROFS; 140 if (!XFS_IS_QUOTA_RUNNING(mp)) 141 return -ENOSYS; 142 if (!XFS_IS_QUOTA_ON(mp)) 143 return -ESRCH; 144 145 return -xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid), 146 xfs_quota_type(qid.type), fdq); 147 } 148 149 const struct quotactl_ops xfs_quotactl_operations = { 150 .get_xstatev = xfs_fs_get_xstatev, 151 .get_xstate = xfs_fs_get_xstate, 152 .set_xstate = xfs_fs_set_xstate, 153 .get_dqblk = xfs_fs_get_dqblk, 154 .set_dqblk = xfs_fs_set_dqblk, 155 }; 156