2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
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.
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.
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
24 #include "xfs_trans.h"
28 #include "xfs_alloc.h"
29 #include "xfs_dmapi.h"
30 #include "xfs_quota.h"
31 #include "xfs_mount.h"
32 #include "xfs_bmap_btree.h"
33 #include "xfs_alloc_btree.h"
34 #include "xfs_ialloc_btree.h"
35 #include "xfs_dir2_sf.h"
36 #include "xfs_attr_sf.h"
37 #include "xfs_dinode.h"
38 #include "xfs_inode.h"
39 #include "xfs_ialloc.h"
40 #include "xfs_itable.h"
41 #include "xfs_btree.h"
43 #include "xfs_rtalloc.h"
44 #include "xfs_error.h"
48 #include "xfs_buf_item.h"
51 #define MNTOPT_QUOTA "quota" /* disk quotas (user) */
52 #define MNTOPT_NOQUOTA "noquota" /* no quotas */
53 #define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
54 #define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
55 #define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
56 #define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
57 #define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
58 #define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
59 #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
60 #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
61 #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
62 #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
68 struct xfs_mount_args
*args
,
72 char *local_options
= options
;
75 int referenced
= update
;
77 while ((this_char
= strsep(&local_options
, ",")) != NULL
) {
78 length
= strlen(this_char
);
82 if (!strcmp(this_char
, MNTOPT_NOQUOTA
)) {
83 args
->flags
&= ~(XFSMNT_UQUOTAENF
|XFSMNT_UQUOTA
);
84 args
->flags
&= ~(XFSMNT_GQUOTAENF
|XFSMNT_GQUOTA
);
86 } else if (!strcmp(this_char
, MNTOPT_QUOTA
) ||
87 !strcmp(this_char
, MNTOPT_UQUOTA
) ||
88 !strcmp(this_char
, MNTOPT_USRQUOTA
)) {
89 args
->flags
|= XFSMNT_UQUOTA
| XFSMNT_UQUOTAENF
;
91 } else if (!strcmp(this_char
, MNTOPT_QUOTANOENF
) ||
92 !strcmp(this_char
, MNTOPT_UQUOTANOENF
)) {
93 args
->flags
|= XFSMNT_UQUOTA
;
94 args
->flags
&= ~XFSMNT_UQUOTAENF
;
96 } else if (!strcmp(this_char
, MNTOPT_PQUOTA
) ||
97 !strcmp(this_char
, MNTOPT_PRJQUOTA
)) {
98 args
->flags
|= XFSMNT_PQUOTA
| XFSMNT_PQUOTAENF
;
100 } else if (!strcmp(this_char
, MNTOPT_PQUOTANOENF
)) {
101 args
->flags
|= XFSMNT_PQUOTA
;
102 args
->flags
&= ~XFSMNT_PQUOTAENF
;
104 } else if (!strcmp(this_char
, MNTOPT_GQUOTA
) ||
105 !strcmp(this_char
, MNTOPT_GRPQUOTA
)) {
106 args
->flags
|= XFSMNT_GQUOTA
| XFSMNT_GQUOTAENF
;
108 } else if (!strcmp(this_char
, MNTOPT_GQUOTANOENF
)) {
109 args
->flags
|= XFSMNT_GQUOTA
;
110 args
->flags
&= ~XFSMNT_GQUOTAENF
;
114 *(local_options
-1) = ',';
122 if ((args
->flags
& XFSMNT_GQUOTA
) && (args
->flags
& XFSMNT_PQUOTA
)) {
124 "XFS: cannot mount with both project and group quota");
125 return XFS_ERROR(EINVAL
);
128 error
= bhv_next_vfs_parseargs(BHV_NEXT(bhv
), options
, args
, update
);
129 if (!error
&& !referenced
)
130 bhv_remove_vfsops(bhvtovfs(bhv
), VFS_POSITION_QM
);
136 struct bhv_desc
*bhv
,
139 struct bhv_vfs
*vfsp
= bhvtovfs(bhv
);
140 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
142 if (mp
->m_qflags
& XFS_UQUOTA_ACCT
) {
143 (mp
->m_qflags
& XFS_UQUOTA_ENFD
) ?
144 seq_puts(m
, "," MNTOPT_USRQUOTA
) :
145 seq_puts(m
, "," MNTOPT_UQUOTANOENF
);
148 if (mp
->m_qflags
& XFS_PQUOTA_ACCT
) {
149 (mp
->m_qflags
& XFS_OQUOTA_ENFD
) ?
150 seq_puts(m
, "," MNTOPT_PRJQUOTA
) :
151 seq_puts(m
, "," MNTOPT_PQUOTANOENF
);
154 if (mp
->m_qflags
& XFS_GQUOTA_ACCT
) {
155 (mp
->m_qflags
& XFS_OQUOTA_ENFD
) ?
156 seq_puts(m
, "," MNTOPT_GRPQUOTA
) :
157 seq_puts(m
, "," MNTOPT_GQUOTANOENF
);
160 if (!(mp
->m_qflags
& XFS_ALL_QUOTA_ACCT
))
161 seq_puts(m
, "," MNTOPT_NOQUOTA
);
163 return bhv_next_vfs_showargs(BHV_NEXT(bhv
), m
);
168 struct bhv_desc
*bhv
,
169 struct xfs_mount_args
*args
,
172 struct bhv_vfs
*vfsp
= bhvtovfs(bhv
);
173 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
175 if (args
->flags
& (XFSMNT_UQUOTA
| XFSMNT_GQUOTA
| XFSMNT_PQUOTA
))
176 xfs_qm_mount_quotainit(mp
, args
->flags
);
177 return bhv_next_vfs_mount(BHV_NEXT(bhv
), args
, cr
);
181 * Directory tree accounting is implemented using project quotas, where
182 * the project identifier is inherited from parent directories.
183 * A statvfs (df, etc.) of a directory that is using project quota should
184 * return a statvfs of the project, not the entire filesystem.
185 * This makes such trees appear as if they are filesystems in themselves.
189 struct bhv_desc
*bhv
,
190 bhv_statvfs_t
*statp
,
191 struct bhv_vnode
*vnode
)
196 xfs_disk_dquot_t
*dp
;
200 error
= bhv_next_vfs_statvfs(BHV_NEXT(bhv
), statp
, vnode
);
204 mp
= xfs_vfstom(bhvtovfs(bhv
));
205 ip
= xfs_vtoi(vnode
);
207 if (!(ip
->i_d
.di_flags
& XFS_DIFLAG_PROJINHERIT
))
209 if (!(mp
->m_qflags
& XFS_PQUOTA_ACCT
))
211 if (!(mp
->m_qflags
& XFS_OQUOTA_ENFD
))
214 if (xfs_qm_dqget(mp
, NULL
, ip
->i_d
.di_projid
, XFS_DQ_PROJ
, 0, &dqp
))
218 limit
= dp
->d_blk_softlimit
?
219 be64_to_cpu(dp
->d_blk_softlimit
) :
220 be64_to_cpu(dp
->d_blk_hardlimit
);
221 if (limit
&& statp
->f_blocks
> limit
) {
222 statp
->f_blocks
= limit
;
224 (statp
->f_blocks
> be64_to_cpu(dp
->d_bcount
)) ?
225 (statp
->f_blocks
- be64_to_cpu(dp
->d_bcount
)) : 0;
228 limit
= dp
->d_ino_softlimit
?
229 be64_to_cpu(dp
->d_ino_softlimit
) :
230 be64_to_cpu(dp
->d_ino_hardlimit
);
231 if (limit
&& statp
->f_files
> limit
) {
232 statp
->f_files
= limit
;
234 (statp
->f_files
> be64_to_cpu(dp
->d_icount
)) ?
235 (statp
->f_ffree
- be64_to_cpu(dp
->d_icount
)) : 0;
244 struct bhv_desc
*bhv
,
248 struct bhv_vfs
*vfsp
= bhvtovfs(bhv
);
249 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
253 * Get the Quota Manager to flush the dquots.
255 if (XFS_IS_QUOTA_ON(mp
)) {
256 if ((error
= xfs_qm_sync(mp
, flags
))) {
258 * If we got an IO error, we will be shutting down.
259 * So, there's nothing more for us to do here.
261 ASSERT(error
!= EIO
|| XFS_FORCED_SHUTDOWN(mp
));
262 if (XFS_FORCED_SHUTDOWN(mp
)) {
263 return XFS_ERROR(error
);
267 return bhv_next_vfs_sync(BHV_NEXT(bhv
), flags
, credp
);
273 uint
*needquotamount
,
277 uint uquotaondisk
= 0, gquotaondisk
= 0, pquotaondisk
= 0;
280 *needquotamount
= B_FALSE
;
282 quotaondisk
= XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
) &&
283 (mp
->m_sb
.sb_qflags
& XFS_ALL_QUOTA_ACCT
);
286 uquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
;
287 pquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
;
288 gquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
;
292 * If the device itself is read-only, we can't allow
293 * the user to change the state of quota on the mount -
294 * this would generate a transaction on the ro device,
295 * which would lead to an I/O error and shutdown
298 if (((uquotaondisk
&& !XFS_IS_UQUOTA_ON(mp
)) ||
299 (!uquotaondisk
&& XFS_IS_UQUOTA_ON(mp
)) ||
300 (pquotaondisk
&& !XFS_IS_PQUOTA_ON(mp
)) ||
301 (!pquotaondisk
&& XFS_IS_PQUOTA_ON(mp
)) ||
302 (gquotaondisk
&& !XFS_IS_GQUOTA_ON(mp
)) ||
303 (!gquotaondisk
&& XFS_IS_OQUOTA_ON(mp
))) &&
304 xfs_dev_is_read_only(mp
, "changing quota state")) {
306 "XFS: please mount with%s%s%s%s.",
307 (!quotaondisk
? "out quota" : ""),
308 (uquotaondisk
? " usrquota" : ""),
309 (pquotaondisk
? " prjquota" : ""),
310 (gquotaondisk
? " grpquota" : ""));
311 return XFS_ERROR(EPERM
);
314 if (XFS_IS_QUOTA_ON(mp
) || quotaondisk
) {
316 * Call mount_quotas at this point only if we won't have to do
319 if (quotaondisk
&& !XFS_QM_NEED_QUOTACHECK(mp
)) {
321 * If an error occured, qm_mount_quotas code
322 * has already disabled quotas. So, just finish
323 * mounting, and get on with the boring life
324 * without disk quotas.
326 xfs_qm_mount_quotas(mp
, 0);
329 * Clear the quota flags, but remember them. This
330 * is so that the quota code doesn't get invoked
331 * before we're ready. This can happen when an
332 * inode goes inactive and wants to free blocks,
333 * or via xfs_log_mount_finish.
335 *needquotamount
= B_TRUE
;
336 *quotaflags
= mp
->m_qflags
;
351 if (needquotamount
) {
352 ASSERT(mp
->m_qflags
== 0);
353 mp
->m_qflags
= quotaflags
;
354 xfs_qm_mount_quotas(mp
, mfsi_flags
);
357 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
358 if (! (XFS_IS_QUOTA_ON(mp
)))
359 xfs_fs_cmn_err(CE_NOTE
, mp
, "Disk quotas not turned on");
361 xfs_fs_cmn_err(CE_NOTE
, mp
, "Disk quotas turned on");
365 if (XFS_IS_QUOTA_ON(mp
) && xfs_qm_internalqcheck(mp
))
366 cmn_err(CE_WARN
, "XFS: mount internalqcheck failed");
377 * Called from XFS, where we always check first for a NULL dquot.
385 static struct xfs_qmops xfs_qmcore_xfs
= {
386 .xfs_qminit
= xfs_qm_newmount
,
387 .xfs_qmdone
= xfs_qm_unmount_quotadestroy
,
388 .xfs_qmmount
= xfs_qm_endmount
,
389 .xfs_qmunmount
= xfs_qm_unmount_quotas
,
390 .xfs_dqrele
= xfs_qm_dqrele_null
,
391 .xfs_dqattach
= xfs_qm_dqattach
,
392 .xfs_dqdetach
= xfs_qm_dqdetach
,
393 .xfs_dqpurgeall
= xfs_qm_dqpurge_all
,
394 .xfs_dqvopalloc
= xfs_qm_vop_dqalloc
,
395 .xfs_dqvopcreate
= xfs_qm_vop_dqattach_and_dqmod_newinode
,
396 .xfs_dqvoprename
= xfs_qm_vop_rename_dqattach
,
397 .xfs_dqvopchown
= xfs_qm_vop_chown
,
398 .xfs_dqvopchownresv
= xfs_qm_vop_chown_reserve
,
399 .xfs_dqtrxops
= &xfs_trans_dquot_ops
,
402 struct bhv_module_vfsops xfs_qmops
= { {
403 BHV_IDENTITY_INIT(VFS_BHV_QM
, VFS_POSITION_QM
),
404 .vfs_parseargs
= xfs_qm_parseargs
,
405 .vfs_showargs
= xfs_qm_showargs
,
406 .vfs_mount
= xfs_qm_mount
,
407 .vfs_statvfs
= xfs_qm_statvfs
,
408 .vfs_sync
= xfs_qm_syncall
,
409 .vfs_quotactl
= xfs_qm_quotactl
, },
416 static char message
[] __initdata
=
417 KERN_INFO
"SGI XFS Quota Management subsystem\n";
420 mutex_init(&xfs_Gqm_lock
);
421 vfs_bhv_set_custom(&xfs_qmops
, &xfs_qmcore_xfs
);
422 xfs_qm_init_procfs();
428 vfs_bhv_clr_custom(&xfs_qmops
);
429 xfs_qm_cleanup_procfs();
431 kmem_zone_destroy(qm_dqzone
);
433 kmem_zone_destroy(qm_dqtrxzone
);