2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
38 #include "xfs_trans.h"
42 #include "xfs_alloc.h"
43 #include "xfs_dmapi.h"
44 #include "xfs_quota.h"
45 #include "xfs_mount.h"
46 #include "xfs_alloc_btree.h"
47 #include "xfs_bmap_btree.h"
48 #include "xfs_ialloc_btree.h"
49 #include "xfs_btree.h"
50 #include "xfs_ialloc.h"
51 #include "xfs_attr_sf.h"
52 #include "xfs_dir_sf.h"
53 #include "xfs_dir2_sf.h"
54 #include "xfs_dinode.h"
55 #include "xfs_inode.h"
58 #include "xfs_rtalloc.h"
59 #include "xfs_error.h"
60 #include "xfs_itable.h"
66 #include "xfs_buf_item.h"
70 #define MNTOPT_QUOTA "quota" /* disk quotas (user) */
71 #define MNTOPT_NOQUOTA "noquota" /* no quotas */
72 #define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
73 #define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
74 #define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
75 #define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
76 #define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
77 #define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
78 #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
79 #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
80 #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
81 #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
87 struct xfs_mount_args
*args
,
91 char *local_options
= options
;
94 int referenced
= update
;
96 while ((this_char
= strsep(&local_options
, ",")) != NULL
) {
97 length
= strlen(this_char
);
101 if (!strcmp(this_char
, MNTOPT_NOQUOTA
)) {
102 args
->flags
&= ~(XFSMNT_UQUOTAENF
|XFSMNT_UQUOTA
);
103 args
->flags
&= ~(XFSMNT_GQUOTAENF
|XFSMNT_GQUOTA
);
105 } else if (!strcmp(this_char
, MNTOPT_QUOTA
) ||
106 !strcmp(this_char
, MNTOPT_UQUOTA
) ||
107 !strcmp(this_char
, MNTOPT_USRQUOTA
)) {
108 args
->flags
|= XFSMNT_UQUOTA
| XFSMNT_UQUOTAENF
;
110 } else if (!strcmp(this_char
, MNTOPT_QUOTANOENF
) ||
111 !strcmp(this_char
, MNTOPT_UQUOTANOENF
)) {
112 args
->flags
|= XFSMNT_UQUOTA
;
113 args
->flags
&= ~XFSMNT_UQUOTAENF
;
115 } else if (!strcmp(this_char
, MNTOPT_PQUOTA
) ||
116 !strcmp(this_char
, MNTOPT_PRJQUOTA
)) {
117 args
->flags
|= XFSMNT_PQUOTA
| XFSMNT_PQUOTAENF
;
119 } else if (!strcmp(this_char
, MNTOPT_PQUOTANOENF
)) {
120 args
->flags
|= XFSMNT_PQUOTA
;
121 args
->flags
&= ~XFSMNT_PQUOTAENF
;
123 } else if (!strcmp(this_char
, MNTOPT_GQUOTA
) ||
124 !strcmp(this_char
, MNTOPT_GRPQUOTA
)) {
125 args
->flags
|= XFSMNT_GQUOTA
| XFSMNT_GQUOTAENF
;
127 } else if (!strcmp(this_char
, MNTOPT_GQUOTANOENF
)) {
128 args
->flags
|= XFSMNT_GQUOTA
;
129 args
->flags
&= ~XFSMNT_GQUOTAENF
;
133 *(local_options
-1) = ',';
141 if ((args
->flags
& XFSMNT_GQUOTA
) && (args
->flags
& XFSMNT_PQUOTA
)) {
143 "XFS: cannot mount with both project and group quota");
144 return XFS_ERROR(EINVAL
);
147 PVFS_PARSEARGS(BHV_NEXT(bhv
), options
, args
, update
, error
);
148 if (!error
&& !referenced
)
149 bhv_remove_vfsops(bhvtovfs(bhv
), VFS_POSITION_QM
);
155 struct bhv_desc
*bhv
,
158 struct vfs
*vfsp
= bhvtovfs(bhv
);
159 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
162 if (mp
->m_qflags
& XFS_UQUOTA_ACCT
) {
163 (mp
->m_qflags
& XFS_UQUOTA_ENFD
) ?
164 seq_puts(m
, "," MNTOPT_USRQUOTA
) :
165 seq_puts(m
, "," MNTOPT_UQUOTANOENF
);
168 if (mp
->m_qflags
& XFS_PQUOTA_ACCT
) {
169 (mp
->m_qflags
& XFS_OQUOTA_ENFD
) ?
170 seq_puts(m
, "," MNTOPT_PRJQUOTA
) :
171 seq_puts(m
, "," MNTOPT_PQUOTANOENF
);
174 if (mp
->m_qflags
& XFS_GQUOTA_ACCT
) {
175 (mp
->m_qflags
& XFS_OQUOTA_ENFD
) ?
176 seq_puts(m
, "," MNTOPT_GRPQUOTA
) :
177 seq_puts(m
, "," MNTOPT_GQUOTANOENF
);
180 if (!(mp
->m_qflags
& XFS_ALL_QUOTA_ACCT
))
181 seq_puts(m
, "," MNTOPT_NOQUOTA
);
183 PVFS_SHOWARGS(BHV_NEXT(bhv
), m
, error
);
189 struct bhv_desc
*bhv
,
190 struct xfs_mount_args
*args
,
193 struct vfs
*vfsp
= bhvtovfs(bhv
);
194 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
197 if (args
->flags
& (XFSMNT_UQUOTA
| XFSMNT_GQUOTA
| XFSMNT_PQUOTA
))
198 xfs_qm_mount_quotainit(mp
, args
->flags
);
199 PVFS_MOUNT(BHV_NEXT(bhv
), args
, cr
, error
);
205 struct bhv_desc
*bhv
,
209 struct vfs
*vfsp
= bhvtovfs(bhv
);
210 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
214 * Get the Quota Manager to flush the dquots.
216 if (XFS_IS_QUOTA_ON(mp
)) {
217 if ((error
= xfs_qm_sync(mp
, flags
))) {
219 * If we got an IO error, we will be shutting down.
220 * So, there's nothing more for us to do here.
222 ASSERT(error
!= EIO
|| XFS_FORCED_SHUTDOWN(mp
));
223 if (XFS_FORCED_SHUTDOWN(mp
)) {
224 return XFS_ERROR(error
);
228 PVFS_SYNC(BHV_NEXT(bhv
), flags
, credp
, error
);
235 uint
*needquotamount
,
239 uint uquotaondisk
= 0, gquotaondisk
= 0, pquotaondisk
= 0;
242 *needquotamount
= B_FALSE
;
244 quotaondisk
= XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
) &&
245 (mp
->m_sb
.sb_qflags
& XFS_ALL_QUOTA_ACCT
);
248 uquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
;
249 pquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
;
250 gquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
;
254 * If the device itself is read-only, we can't allow
255 * the user to change the state of quota on the mount -
256 * this would generate a transaction on the ro device,
257 * which would lead to an I/O error and shutdown
260 if (((uquotaondisk
&& !XFS_IS_UQUOTA_ON(mp
)) ||
261 (!uquotaondisk
&& XFS_IS_UQUOTA_ON(mp
)) ||
262 (pquotaondisk
&& !XFS_IS_PQUOTA_ON(mp
)) ||
263 (!pquotaondisk
&& XFS_IS_PQUOTA_ON(mp
)) ||
264 (gquotaondisk
&& !XFS_IS_GQUOTA_ON(mp
)) ||
265 (!gquotaondisk
&& XFS_IS_OQUOTA_ON(mp
))) &&
266 xfs_dev_is_read_only(mp
, "changing quota state")) {
268 "XFS: please mount with%s%s%s%s.",
269 (!quotaondisk
? "out quota" : ""),
270 (uquotaondisk
? " usrquota" : ""),
271 (pquotaondisk
? " prjquota" : ""),
272 (gquotaondisk
? " grpquota" : ""));
273 return XFS_ERROR(EPERM
);
276 if (XFS_IS_QUOTA_ON(mp
) || quotaondisk
) {
278 * Call mount_quotas at this point only if we won't have to do
281 if (quotaondisk
&& !XFS_QM_NEED_QUOTACHECK(mp
)) {
283 * If an error occured, qm_mount_quotas code
284 * has already disabled quotas. So, just finish
285 * mounting, and get on with the boring life
286 * without disk quotas.
288 xfs_qm_mount_quotas(mp
, 0);
291 * Clear the quota flags, but remember them. This
292 * is so that the quota code doesn't get invoked
293 * before we're ready. This can happen when an
294 * inode goes inactive and wants to free blocks,
295 * or via xfs_log_mount_finish.
297 *needquotamount
= B_TRUE
;
298 *quotaflags
= mp
->m_qflags
;
313 if (needquotamount
) {
314 ASSERT(mp
->m_qflags
== 0);
315 mp
->m_qflags
= quotaflags
;
316 xfs_qm_mount_quotas(mp
, mfsi_flags
);
319 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
320 if (! (XFS_IS_QUOTA_ON(mp
)))
321 xfs_fs_cmn_err(CE_NOTE
, mp
, "Disk quotas not turned on");
323 xfs_fs_cmn_err(CE_NOTE
, mp
, "Disk quotas turned on");
327 if (XFS_IS_QUOTA_ON(mp
) && xfs_qm_internalqcheck(mp
))
328 cmn_err(CE_WARN
, "XFS: mount internalqcheck failed");
339 * Called from XFS, where we always check first for a NULL dquot.
347 STATIC
struct xfs_qmops xfs_qmcore_xfs
= {
348 .xfs_qminit
= xfs_qm_newmount
,
349 .xfs_qmdone
= xfs_qm_unmount_quotadestroy
,
350 .xfs_qmmount
= xfs_qm_endmount
,
351 .xfs_qmunmount
= xfs_qm_unmount_quotas
,
352 .xfs_dqrele
= xfs_qm_dqrele_null
,
353 .xfs_dqattach
= xfs_qm_dqattach
,
354 .xfs_dqdetach
= xfs_qm_dqdetach
,
355 .xfs_dqpurgeall
= xfs_qm_dqpurge_all
,
356 .xfs_dqvopalloc
= xfs_qm_vop_dqalloc
,
357 .xfs_dqvopcreate
= xfs_qm_vop_dqattach_and_dqmod_newinode
,
358 .xfs_dqvoprename
= xfs_qm_vop_rename_dqattach
,
359 .xfs_dqvopchown
= xfs_qm_vop_chown
,
360 .xfs_dqvopchownresv
= xfs_qm_vop_chown_reserve
,
361 .xfs_dqtrxops
= &xfs_trans_dquot_ops
,
364 struct bhv_vfsops xfs_qmops
= { {
365 BHV_IDENTITY_INIT(VFS_BHV_QM
, VFS_POSITION_QM
),
366 .vfs_parseargs
= xfs_qm_parseargs
,
367 .vfs_showargs
= xfs_qm_showargs
,
368 .vfs_mount
= xfs_qm_mount
,
369 .vfs_sync
= xfs_qm_syncall
,
370 .vfs_quotactl
= xfs_qm_quotactl
, },
377 static char message
[] __initdata
=
378 KERN_INFO
"SGI XFS Quota Management subsystem\n";
381 mutex_init(&xfs_Gqm_lock
, MUTEX_DEFAULT
, "xfs_qmlock");
382 vfs_bhv_set_custom(&xfs_qmops
, &xfs_qmcore_xfs
);
383 xfs_qm_init_procfs();
389 vfs_bhv_clr_custom(&xfs_qmops
);
390 xfs_qm_cleanup_procfs();
392 kmem_cache_destroy(qm_dqzone
);
394 kmem_cache_destroy(qm_dqtrxzone
);