2 Unix SMB/CIFS implementation.
3 System QUOTA function wrappers for XFS
4 Copyright (C) Stefan (metze) Metzmacher 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #define DBGC_CLASS DBGC_QUOTA
26 #if defined(HAVE_SYS_QUOTAS) && defined(HAVE_XFS_QUOTAS)
28 #ifdef HAVE_SYS_QUOTA_H
29 #include <sys/quota.h>
32 /* this one should actually come from glibc: */
33 /* #include "samba_linux_quota.h" */
39 #define HAVE_GROUP_QUOTA
43 #define Q_XQUOTAON Q_QUOTAON
44 #endif /* Q_XQUOTAON */
46 #define Q_XQUOTAOFF Q_QUOTAOFF
47 #endif /* Q_XQUOTAOFF */
49 #define Q_XGETQSTAT Q_GETQSTAT
50 #endif /* Q_XGETQSTAT */
52 /* currently doesn't support Group and Project quotas on IRIX
60 * IRIX has BBSIZE in <sys/param.h>
66 #define BBSIZE (1<<BBSHIFT)
69 /****************************************************************************
70 Abstract out the XFS Quota Manager quota get call.
71 ****************************************************************************/
72 int sys_get_xfs_quota(const char *path
, const char *bdev
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
76 uint64_t bsize
= (uint64_t)BBSIZE
;
77 struct fs_disk_quota D
;
78 struct fs_quota_stat F
;
83 smb_panic("sys_get_xfs_quota: called with NULL pointer");
89 case SMB_USER_QUOTA_TYPE
:
90 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
91 path
, bdev
, (unsigned)id
.uid
));
93 ret
=quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
94 /* XFS fails with ENOENT if the user has no
95 * quota. Our protocol in that case is to
96 * succeed and return 0 as quota.
98 if (ret
!= 0 && errno
!= ENOENT
) {
104 #ifdef HAVE_GROUP_QUOTA
105 case SMB_GROUP_QUOTA_TYPE
:
106 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
107 path
, bdev
, (unsigned)id
.gid
));
109 ret
=quotactl(QCMD(Q_XGETQUOTA
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
110 /* XFS fails with ENOENT if the user has no
111 * quota. Our protocol in that case is to
112 * succeed and return 0 as quota.
114 if (ret
!= 0 && errno
!= ENOENT
) {
118 #endif /* HAVE_GROUP_QUOTA */
119 case SMB_USER_FS_QUOTA_TYPE
:
120 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
121 path
, bdev
, (unsigned)id
.uid
));
123 quotactl(QCMD(Q_XGETQSTAT
,USRQUOTA
), bdev
, -1, (caddr_t
)&F
);
125 if (F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
) {
126 qflags
|= QUOTAS_DENY_DISK
;
128 else if (F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
) {
129 qflags
|= QUOTAS_ENABLED
;
135 #ifdef HAVE_GROUP_QUOTA
136 case SMB_GROUP_FS_QUOTA_TYPE
:
137 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
138 path
, bdev
, (unsigned)id
.gid
));
140 quotactl(QCMD(Q_XGETQSTAT
,GRPQUOTA
), bdev
, -1, (caddr_t
)&F
);
142 if (F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
) {
143 qflags
|= QUOTAS_DENY_DISK
;
145 else if (F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
) {
146 qflags
|= QUOTAS_ENABLED
;
152 #endif /* HAVE_GROUP_QUOTA */
159 dp
->softlimit
= (uint64_t)D
.d_blk_softlimit
;
160 dp
->hardlimit
= (uint64_t)D
.d_blk_hardlimit
;
161 dp
->ihardlimit
= (uint64_t)D
.d_ino_hardlimit
;
162 dp
->isoftlimit
= (uint64_t)D
.d_ino_softlimit
;
163 dp
->curinodes
= (uint64_t)D
.d_icount
;
164 dp
->curblocks
= (uint64_t)D
.d_bcount
;
170 /****************************************************************************
171 Abstract out the XFS Quota Manager quota set call.
172 ****************************************************************************/
173 int sys_set_xfs_quota(const char *path
, const char *bdev
, enum SMB_QUOTA_TYPE qtype
, unid_t id
, SMB_DISK_QUOTA
*dp
)
177 uint64_t bsize
= (uint64_t)BBSIZE
;
178 struct fs_disk_quota D
;
179 struct fs_quota_stat F
;
186 smb_panic("sys_set_xfs_quota: called with NULL pointer");
188 if (bsize
== dp
->bsize
) {
189 D
.d_blk_softlimit
= dp
->softlimit
;
190 D
.d_blk_hardlimit
= dp
->hardlimit
;
191 D
.d_ino_hardlimit
= dp
->ihardlimit
;
192 D
.d_ino_softlimit
= dp
->isoftlimit
;
194 D
.d_blk_softlimit
= (dp
->softlimit
*dp
->bsize
)/bsize
;
195 D
.d_blk_hardlimit
= (dp
->hardlimit
*dp
->bsize
)/bsize
;
196 D
.d_ino_hardlimit
= (dp
->ihardlimit
*dp
->bsize
)/bsize
;
197 D
.d_ino_softlimit
= (dp
->isoftlimit
*dp
->bsize
)/bsize
;
203 case SMB_USER_QUOTA_TYPE
:
204 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
205 path
, bdev
, (unsigned)id
.uid
));
207 D
.d_fieldmask
|= FS_DQ_LIMIT_MASK
;
208 ret
= quotactl(QCMD(Q_XSETQLIM
,USRQUOTA
), bdev
, id
.uid
, (caddr_t
)&D
);
210 #ifdef HAVE_GROUP_QUOTA
211 case SMB_GROUP_QUOTA_TYPE
:
212 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
213 path
, bdev
, (unsigned)id
.gid
));
215 D
.d_fieldmask
|= FS_DQ_LIMIT_MASK
;
216 ret
= quotactl(QCMD(Q_XSETQLIM
,GRPQUOTA
), bdev
, id
.gid
, (caddr_t
)&D
);
218 #endif /* HAVE_GROUP_QUOTA */
219 case SMB_USER_FS_QUOTA_TYPE
:
220 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
221 path
, bdev
, (unsigned)id
.uid
));
223 quotactl(QCMD(Q_XGETQSTAT
,USRQUOTA
), bdev
, -1, (caddr_t
)&F
);
225 if (qflags
& QUOTAS_DENY_DISK
) {
226 if (!(F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
))
227 q_on
|= XFS_QUOTA_UDQ_ENFD
;
228 if (!(F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
))
229 q_on
|= XFS_QUOTA_UDQ_ACCT
;
232 ret
= quotactl(QCMD(Q_XQUOTAON
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
237 } else if (qflags
& QUOTAS_ENABLED
) {
238 if (F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
)
239 q_off
|= XFS_QUOTA_UDQ_ENFD
;
242 ret
= quotactl(QCMD(Q_XQUOTAOFF
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
247 if (!(F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
))
248 q_on
|= XFS_QUOTA_UDQ_ACCT
;
251 ret
= quotactl(QCMD(Q_XQUOTAON
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
257 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
258 * only swittching off XFS_QUOTA_UDQ_ACCT work
260 if (F
.qs_flags
& XFS_QUOTA_UDQ_ENFD
)
261 q_off
|= XFS_QUOTA_UDQ_ENFD
;
262 if (F
.qs_flags
& XFS_QUOTA_UDQ_ACCT
)
263 q_off
|= XFS_QUOTA_UDQ_ACCT
;
266 ret
= quotactl(QCMD(Q_XQUOTAOFF
,USRQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
276 #ifdef HAVE_GROUP_QUOTA
277 case SMB_GROUP_FS_QUOTA_TYPE
:
278 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
279 path
, bdev
, (unsigned)id
.gid
));
281 quotactl(QCMD(Q_XGETQSTAT
,GRPQUOTA
), bdev
, -1, (caddr_t
)&F
);
283 if (qflags
& QUOTAS_DENY_DISK
) {
284 if (!(F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
))
285 q_on
|= XFS_QUOTA_GDQ_ENFD
;
286 if (!(F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
))
287 q_on
|= XFS_QUOTA_GDQ_ACCT
;
290 ret
= quotactl(QCMD(Q_XQUOTAON
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
295 } else if (qflags
& QUOTAS_ENABLED
) {
296 if (F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
)
297 q_off
|= XFS_QUOTA_GDQ_ENFD
;
300 ret
= quotactl(QCMD(Q_XQUOTAOFF
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
305 if (!(F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
))
306 q_on
|= XFS_QUOTA_GDQ_ACCT
;
309 ret
= quotactl(QCMD(Q_XQUOTAON
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_on
);
315 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
316 * only swittching off XFS_QUOTA_UDQ_ACCT work
318 if (F
.qs_flags
& XFS_QUOTA_GDQ_ENFD
)
319 q_off
|= XFS_QUOTA_GDQ_ENFD
;
320 if (F
.qs_flags
& XFS_QUOTA_GDQ_ACCT
)
321 q_off
|= XFS_QUOTA_GDQ_ACCT
;
324 ret
= quotactl(QCMD(Q_XQUOTAOFF
,GRPQUOTA
),bdev
, -1, (caddr_t
)&q_off
);
334 #endif /* HAVE_GROUP_QUOTA */
343 #else /* HAVE_XFS_QUOTAS */
344 void dummy_sysquotas_xfs(void);
346 void dummy_sysquotas_xfs(void){}
347 #endif /* HAVE_XFS_QUOTAS */