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"
50 #include "xfs_buf_item.h"
53 #define MNTOPT_QUOTA "quota" /* disk quotas (user) */
54 #define MNTOPT_NOQUOTA "noquota" /* no quotas */
55 #define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
56 #define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
57 #define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
58 #define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
59 #define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
60 #define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
61 #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
62 #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
63 #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
64 #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
70 struct xfs_mount_args
*args
,
74 char *local_options
= options
;
77 int referenced
= update
;
79 while ((this_char
= strsep(&local_options
, ",")) != NULL
) {
80 length
= strlen(this_char
);
84 if (!strcmp(this_char
, MNTOPT_NOQUOTA
)) {
85 args
->flags
&= ~(XFSMNT_UQUOTAENF
|XFSMNT_UQUOTA
);
86 args
->flags
&= ~(XFSMNT_GQUOTAENF
|XFSMNT_GQUOTA
);
88 } else if (!strcmp(this_char
, MNTOPT_QUOTA
) ||
89 !strcmp(this_char
, MNTOPT_UQUOTA
) ||
90 !strcmp(this_char
, MNTOPT_USRQUOTA
)) {
91 args
->flags
|= XFSMNT_UQUOTA
| XFSMNT_UQUOTAENF
;
93 } else if (!strcmp(this_char
, MNTOPT_QUOTANOENF
) ||
94 !strcmp(this_char
, MNTOPT_UQUOTANOENF
)) {
95 args
->flags
|= XFSMNT_UQUOTA
;
96 args
->flags
&= ~XFSMNT_UQUOTAENF
;
98 } else if (!strcmp(this_char
, MNTOPT_PQUOTA
) ||
99 !strcmp(this_char
, MNTOPT_PRJQUOTA
)) {
100 args
->flags
|= XFSMNT_PQUOTA
| XFSMNT_PQUOTAENF
;
102 } else if (!strcmp(this_char
, MNTOPT_PQUOTANOENF
)) {
103 args
->flags
|= XFSMNT_PQUOTA
;
104 args
->flags
&= ~XFSMNT_PQUOTAENF
;
106 } else if (!strcmp(this_char
, MNTOPT_GQUOTA
) ||
107 !strcmp(this_char
, MNTOPT_GRPQUOTA
)) {
108 args
->flags
|= XFSMNT_GQUOTA
| XFSMNT_GQUOTAENF
;
110 } else if (!strcmp(this_char
, MNTOPT_GQUOTANOENF
)) {
111 args
->flags
|= XFSMNT_GQUOTA
;
112 args
->flags
&= ~XFSMNT_GQUOTAENF
;
116 *(local_options
-1) = ',';
124 if ((args
->flags
& XFSMNT_GQUOTA
) && (args
->flags
& XFSMNT_PQUOTA
)) {
126 "XFS: cannot mount with both project and group quota");
127 return XFS_ERROR(EINVAL
);
130 error
= bhv_next_vfs_parseargs(BHV_NEXT(bhv
), options
, args
, update
);
131 if (!error
&& !referenced
)
132 bhv_remove_vfsops(bhvtovfs(bhv
), VFS_POSITION_QM
);
138 struct bhv_desc
*bhv
,
141 struct bhv_vfs
*vfsp
= bhvtovfs(bhv
);
142 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
144 if (mp
->m_qflags
& XFS_UQUOTA_ACCT
) {
145 (mp
->m_qflags
& XFS_UQUOTA_ENFD
) ?
146 seq_puts(m
, "," MNTOPT_USRQUOTA
) :
147 seq_puts(m
, "," MNTOPT_UQUOTANOENF
);
150 if (mp
->m_qflags
& XFS_PQUOTA_ACCT
) {
151 (mp
->m_qflags
& XFS_OQUOTA_ENFD
) ?
152 seq_puts(m
, "," MNTOPT_PRJQUOTA
) :
153 seq_puts(m
, "," MNTOPT_PQUOTANOENF
);
156 if (mp
->m_qflags
& XFS_GQUOTA_ACCT
) {
157 (mp
->m_qflags
& XFS_OQUOTA_ENFD
) ?
158 seq_puts(m
, "," MNTOPT_GRPQUOTA
) :
159 seq_puts(m
, "," MNTOPT_GQUOTANOENF
);
162 if (!(mp
->m_qflags
& XFS_ALL_QUOTA_ACCT
))
163 seq_puts(m
, "," MNTOPT_NOQUOTA
);
165 return bhv_next_vfs_showargs(BHV_NEXT(bhv
), m
);
170 struct bhv_desc
*bhv
,
171 struct xfs_mount_args
*args
,
174 struct bhv_vfs
*vfsp
= bhvtovfs(bhv
);
175 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
177 if (args
->flags
& (XFSMNT_UQUOTA
| XFSMNT_GQUOTA
| XFSMNT_PQUOTA
))
178 xfs_qm_mount_quotainit(mp
, args
->flags
);
179 return bhv_next_vfs_mount(BHV_NEXT(bhv
), args
, cr
);
183 * Directory tree accounting is implemented using project quotas, where
184 * the project identifier is inherited from parent directories.
185 * A statvfs (df, etc.) of a directory that is using project quota should
186 * return a statvfs of the project, not the entire filesystem.
187 * This makes such trees appear as if they are filesystems in themselves.
191 struct bhv_desc
*bhv
,
192 bhv_statvfs_t
*statp
,
193 struct bhv_vnode
*vnode
)
198 xfs_disk_dquot_t
*dp
;
202 error
= bhv_next_vfs_statvfs(BHV_NEXT(bhv
), statp
, vnode
);
206 mp
= xfs_vfstom(bhvtovfs(bhv
));
207 ip
= xfs_vtoi(vnode
);
209 if (!(ip
->i_d
.di_flags
& XFS_DIFLAG_PROJINHERIT
))
211 if (!(mp
->m_qflags
& XFS_PQUOTA_ACCT
))
213 if (!(mp
->m_qflags
& XFS_OQUOTA_ENFD
))
216 if (xfs_qm_dqget(mp
, NULL
, ip
->i_d
.di_projid
, XFS_DQ_PROJ
, 0, &dqp
))
220 limit
= dp
->d_blk_softlimit
?
221 be64_to_cpu(dp
->d_blk_softlimit
) :
222 be64_to_cpu(dp
->d_blk_hardlimit
);
223 if (limit
&& statp
->f_blocks
> limit
) {
224 statp
->f_blocks
= limit
;
226 (statp
->f_blocks
> be64_to_cpu(dp
->d_bcount
)) ?
227 (statp
->f_blocks
- be64_to_cpu(dp
->d_bcount
)) : 0;
230 limit
= dp
->d_ino_softlimit
?
231 be64_to_cpu(dp
->d_ino_softlimit
) :
232 be64_to_cpu(dp
->d_ino_hardlimit
);
233 if (limit
&& statp
->f_files
> limit
) {
234 statp
->f_files
= limit
;
236 (statp
->f_files
> be64_to_cpu(dp
->d_icount
)) ?
237 (statp
->f_ffree
- be64_to_cpu(dp
->d_icount
)) : 0;
246 struct bhv_desc
*bhv
,
250 struct bhv_vfs
*vfsp
= bhvtovfs(bhv
);
251 struct xfs_mount
*mp
= XFS_VFSTOM(vfsp
);
255 * Get the Quota Manager to flush the dquots.
257 if (XFS_IS_QUOTA_ON(mp
)) {
258 if ((error
= xfs_qm_sync(mp
, flags
))) {
260 * If we got an IO error, we will be shutting down.
261 * So, there's nothing more for us to do here.
263 ASSERT(error
!= EIO
|| XFS_FORCED_SHUTDOWN(mp
));
264 if (XFS_FORCED_SHUTDOWN(mp
)) {
265 return XFS_ERROR(error
);
269 return bhv_next_vfs_sync(BHV_NEXT(bhv
), flags
, credp
);
275 uint
*needquotamount
,
279 uint uquotaondisk
= 0, gquotaondisk
= 0, pquotaondisk
= 0;
282 *needquotamount
= B_FALSE
;
284 quotaondisk
= XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
) &&
285 (mp
->m_sb
.sb_qflags
& XFS_ALL_QUOTA_ACCT
);
288 uquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
;
289 pquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
;
290 gquotaondisk
= mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
;
294 * If the device itself is read-only, we can't allow
295 * the user to change the state of quota on the mount -
296 * this would generate a transaction on the ro device,
297 * which would lead to an I/O error and shutdown
300 if (((uquotaondisk
&& !XFS_IS_UQUOTA_ON(mp
)) ||
301 (!uquotaondisk
&& XFS_IS_UQUOTA_ON(mp
)) ||
302 (pquotaondisk
&& !XFS_IS_PQUOTA_ON(mp
)) ||
303 (!pquotaondisk
&& XFS_IS_PQUOTA_ON(mp
)) ||
304 (gquotaondisk
&& !XFS_IS_GQUOTA_ON(mp
)) ||
305 (!gquotaondisk
&& XFS_IS_OQUOTA_ON(mp
))) &&
306 xfs_dev_is_read_only(mp
, "changing quota state")) {
308 "XFS: please mount with%s%s%s%s.",
309 (!quotaondisk
? "out quota" : ""),
310 (uquotaondisk
? " usrquota" : ""),
311 (pquotaondisk
? " prjquota" : ""),
312 (gquotaondisk
? " grpquota" : ""));
313 return XFS_ERROR(EPERM
);
316 if (XFS_IS_QUOTA_ON(mp
) || quotaondisk
) {
318 * Call mount_quotas at this point only if we won't have to do
321 if (quotaondisk
&& !XFS_QM_NEED_QUOTACHECK(mp
)) {
323 * If an error occured, qm_mount_quotas code
324 * has already disabled quotas. So, just finish
325 * mounting, and get on with the boring life
326 * without disk quotas.
328 xfs_qm_mount_quotas(mp
, 0);
331 * Clear the quota flags, but remember them. This
332 * is so that the quota code doesn't get invoked
333 * before we're ready. This can happen when an
334 * inode goes inactive and wants to free blocks,
335 * or via xfs_log_mount_finish.
337 *needquotamount
= B_TRUE
;
338 *quotaflags
= mp
->m_qflags
;
353 if (needquotamount
) {
354 ASSERT(mp
->m_qflags
== 0);
355 mp
->m_qflags
= quotaflags
;
356 xfs_qm_mount_quotas(mp
, mfsi_flags
);
359 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
360 if (! (XFS_IS_QUOTA_ON(mp
)))
361 xfs_fs_cmn_err(CE_NOTE
, mp
, "Disk quotas not turned on");
363 xfs_fs_cmn_err(CE_NOTE
, mp
, "Disk quotas turned on");
367 if (XFS_IS_QUOTA_ON(mp
) && xfs_qm_internalqcheck(mp
))
368 cmn_err(CE_WARN
, "XFS: mount internalqcheck failed");
379 * Called from XFS, where we always check first for a NULL dquot.
387 STATIC
struct xfs_qmops xfs_qmcore_xfs
= {
388 .xfs_qminit
= xfs_qm_newmount
,
389 .xfs_qmdone
= xfs_qm_unmount_quotadestroy
,
390 .xfs_qmmount
= xfs_qm_endmount
,
391 .xfs_qmunmount
= xfs_qm_unmount_quotas
,
392 .xfs_dqrele
= xfs_qm_dqrele_null
,
393 .xfs_dqattach
= xfs_qm_dqattach
,
394 .xfs_dqdetach
= xfs_qm_dqdetach
,
395 .xfs_dqpurgeall
= xfs_qm_dqpurge_all
,
396 .xfs_dqvopalloc
= xfs_qm_vop_dqalloc
,
397 .xfs_dqvopcreate
= xfs_qm_vop_dqattach_and_dqmod_newinode
,
398 .xfs_dqvoprename
= xfs_qm_vop_rename_dqattach
,
399 .xfs_dqvopchown
= xfs_qm_vop_chown
,
400 .xfs_dqvopchownresv
= xfs_qm_vop_chown_reserve
,
401 .xfs_dqtrxops
= &xfs_trans_dquot_ops
,
404 struct bhv_module_vfsops xfs_qmops
= { {
405 BHV_IDENTITY_INIT(VFS_BHV_QM
, VFS_POSITION_QM
),
406 .vfs_parseargs
= xfs_qm_parseargs
,
407 .vfs_showargs
= xfs_qm_showargs
,
408 .vfs_mount
= xfs_qm_mount
,
409 .vfs_statvfs
= xfs_qm_statvfs
,
410 .vfs_sync
= xfs_qm_syncall
,
411 .vfs_quotactl
= xfs_qm_quotactl
, },
418 static char message
[] __initdata
=
419 KERN_INFO
"SGI XFS Quota Management subsystem\n";
422 mutex_init(&xfs_Gqm_lock
);
423 vfs_bhv_set_custom(&xfs_qmops
, &xfs_qmcore_xfs
);
424 xfs_qm_init_procfs();
430 vfs_bhv_clr_custom(&xfs_qmops
);
431 xfs_qm_cleanup_procfs();
433 kmem_zone_destroy(qm_dqzone
);
435 kmem_zone_destroy(qm_dqtrxzone
);