|
@@ -48,172 +48,13 @@
|
|
#include "xfs_buf_item.h"
|
|
#include "xfs_buf_item.h"
|
|
#include "xfs_qm.h"
|
|
#include "xfs_qm.h"
|
|
|
|
|
|
-#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
|
|
|
|
-#define MNTOPT_NOQUOTA "noquota" /* no quotas */
|
|
|
|
-#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
|
|
|
|
-#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
|
|
|
|
-#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
|
|
|
|
-#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
|
|
|
|
-#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
|
|
|
|
-#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
|
|
|
|
-#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
|
|
|
|
-#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
|
|
|
|
-#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
|
|
|
|
-#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
|
|
|
|
|
|
|
|
-STATIC int
|
|
|
|
-xfs_qm_parseargs(
|
|
|
|
- struct bhv_desc *bhv,
|
|
|
|
- char *options,
|
|
|
|
- struct xfs_mount_args *args,
|
|
|
|
- int update)
|
|
|
|
-{
|
|
|
|
- size_t length;
|
|
|
|
- char *local_options = options;
|
|
|
|
- char *this_char;
|
|
|
|
- int error;
|
|
|
|
- int referenced = update;
|
|
|
|
-
|
|
|
|
- while ((this_char = strsep(&local_options, ",")) != NULL) {
|
|
|
|
- length = strlen(this_char);
|
|
|
|
- if (local_options)
|
|
|
|
- length++;
|
|
|
|
-
|
|
|
|
- if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
|
|
|
|
- args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
|
|
|
|
- args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
|
|
|
|
- referenced = update;
|
|
|
|
- } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
|
|
|
|
- !strcmp(this_char, MNTOPT_UQUOTA) ||
|
|
|
|
- !strcmp(this_char, MNTOPT_USRQUOTA)) {
|
|
|
|
- args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
|
|
|
|
- referenced = 1;
|
|
|
|
- } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
|
|
|
|
- !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
|
|
|
|
- args->flags |= XFSMNT_UQUOTA;
|
|
|
|
- args->flags &= ~XFSMNT_UQUOTAENF;
|
|
|
|
- referenced = 1;
|
|
|
|
- } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
|
|
|
|
- !strcmp(this_char, MNTOPT_PRJQUOTA)) {
|
|
|
|
- args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
|
|
|
|
- referenced = 1;
|
|
|
|
- } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
|
|
|
|
- args->flags |= XFSMNT_PQUOTA;
|
|
|
|
- args->flags &= ~XFSMNT_PQUOTAENF;
|
|
|
|
- referenced = 1;
|
|
|
|
- } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
|
|
|
|
- !strcmp(this_char, MNTOPT_GRPQUOTA)) {
|
|
|
|
- args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
|
|
|
|
- referenced = 1;
|
|
|
|
- } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
|
|
|
|
- args->flags |= XFSMNT_GQUOTA;
|
|
|
|
- args->flags &= ~XFSMNT_GQUOTAENF;
|
|
|
|
- referenced = 1;
|
|
|
|
- } else {
|
|
|
|
- if (local_options)
|
|
|
|
- *(local_options-1) = ',';
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- while (length--)
|
|
|
|
- *this_char++ = ',';
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
|
|
|
|
- cmn_err(CE_WARN,
|
|
|
|
- "XFS: cannot mount with both project and group quota");
|
|
|
|
- return XFS_ERROR(EINVAL);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
|
|
|
|
- if (!error && !referenced)
|
|
|
|
- bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
|
|
|
|
- return error;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-STATIC int
|
|
|
|
-xfs_qm_showargs(
|
|
|
|
- struct bhv_desc *bhv,
|
|
|
|
- struct seq_file *m)
|
|
|
|
-{
|
|
|
|
- struct bhv_vfs *vfsp = bhvtovfs(bhv);
|
|
|
|
- struct xfs_mount *mp = XFS_VFSTOM(vfsp);
|
|
|
|
-
|
|
|
|
- if (mp->m_qflags & XFS_UQUOTA_ACCT) {
|
|
|
|
- (mp->m_qflags & XFS_UQUOTA_ENFD) ?
|
|
|
|
- seq_puts(m, "," MNTOPT_USRQUOTA) :
|
|
|
|
- seq_puts(m, "," MNTOPT_UQUOTANOENF);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (mp->m_qflags & XFS_PQUOTA_ACCT) {
|
|
|
|
- (mp->m_qflags & XFS_OQUOTA_ENFD) ?
|
|
|
|
- seq_puts(m, "," MNTOPT_PRJQUOTA) :
|
|
|
|
- seq_puts(m, "," MNTOPT_PQUOTANOENF);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (mp->m_qflags & XFS_GQUOTA_ACCT) {
|
|
|
|
- (mp->m_qflags & XFS_OQUOTA_ENFD) ?
|
|
|
|
- seq_puts(m, "," MNTOPT_GRPQUOTA) :
|
|
|
|
- seq_puts(m, "," MNTOPT_GQUOTANOENF);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
|
|
|
|
- seq_puts(m, "," MNTOPT_NOQUOTA);
|
|
|
|
-
|
|
|
|
- return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-STATIC int
|
|
|
|
-xfs_qm_mount(
|
|
|
|
- struct bhv_desc *bhv,
|
|
|
|
- struct xfs_mount_args *args,
|
|
|
|
- struct cred *cr)
|
|
|
|
-{
|
|
|
|
- struct bhv_vfs *vfsp = bhvtovfs(bhv);
|
|
|
|
- struct xfs_mount *mp = XFS_VFSTOM(vfsp);
|
|
|
|
-
|
|
|
|
- if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
|
|
|
|
- xfs_qm_mount_quotainit(mp, args->flags);
|
|
|
|
- return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * Directory tree accounting is implemented using project quotas, where
|
|
|
|
- * the project identifier is inherited from parent directories.
|
|
|
|
- * A statvfs (df, etc.) of a directory that is using project quota should
|
|
|
|
- * return a statvfs of the project, not the entire filesystem.
|
|
|
|
- * This makes such trees appear as if they are filesystems in themselves.
|
|
|
|
- */
|
|
|
|
-STATIC int
|
|
|
|
-xfs_qm_statvfs(
|
|
|
|
- struct bhv_desc *bhv,
|
|
|
|
|
|
+STATIC void
|
|
|
|
+xfs_fill_statvfs_from_dquot(
|
|
bhv_statvfs_t *statp,
|
|
bhv_statvfs_t *statp,
|
|
- bhv_vnode_t *vnode)
|
|
|
|
|
|
+ xfs_disk_dquot_t *dp)
|
|
{
|
|
{
|
|
- xfs_mount_t *mp;
|
|
|
|
- xfs_inode_t *ip;
|
|
|
|
- xfs_dquot_t *dqp;
|
|
|
|
- xfs_disk_dquot_t *dp;
|
|
|
|
__uint64_t limit;
|
|
__uint64_t limit;
|
|
- int error;
|
|
|
|
-
|
|
|
|
- error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
|
|
|
|
- if (error || !vnode)
|
|
|
|
- return error;
|
|
|
|
-
|
|
|
|
- mp = xfs_vfstom(bhvtovfs(bhv));
|
|
|
|
- ip = xfs_vtoi(vnode);
|
|
|
|
-
|
|
|
|
- if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
|
|
|
|
- return 0;
|
|
|
|
- if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
|
|
|
|
- return 0;
|
|
|
|
- if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
|
|
|
|
- return 0;
|
|
|
|
- dp = &dqp->q_core;
|
|
|
|
|
|
|
|
limit = dp->d_blk_softlimit ?
|
|
limit = dp->d_blk_softlimit ?
|
|
be64_to_cpu(dp->d_blk_softlimit) :
|
|
be64_to_cpu(dp->d_blk_softlimit) :
|
|
@@ -234,37 +75,35 @@ xfs_qm_statvfs(
|
|
(statp->f_files > be64_to_cpu(dp->d_icount)) ?
|
|
(statp->f_files > be64_to_cpu(dp->d_icount)) ?
|
|
(statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
|
|
(statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
|
|
}
|
|
}
|
|
-
|
|
|
|
- xfs_qm_dqput(dqp);
|
|
|
|
- return 0;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-STATIC int
|
|
|
|
-xfs_qm_syncall(
|
|
|
|
- struct bhv_desc *bhv,
|
|
|
|
- int flags,
|
|
|
|
- cred_t *credp)
|
|
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Directory tree accounting is implemented using project quotas, where
|
|
|
|
+ * the project identifier is inherited from parent directories.
|
|
|
|
+ * A statvfs (df, etc.) of a directory that is using project quota should
|
|
|
|
+ * return a statvfs of the project, not the entire filesystem.
|
|
|
|
+ * This makes such trees appear as if they are filesystems in themselves.
|
|
|
|
+ */
|
|
|
|
+STATIC void
|
|
|
|
+xfs_qm_statvfs(
|
|
|
|
+ xfs_inode_t *ip,
|
|
|
|
+ bhv_statvfs_t *statp)
|
|
{
|
|
{
|
|
- struct bhv_vfs *vfsp = bhvtovfs(bhv);
|
|
|
|
- struct xfs_mount *mp = XFS_VFSTOM(vfsp);
|
|
|
|
- int error;
|
|
|
|
|
|
+ xfs_mount_t *mp = ip->i_mount;
|
|
|
|
+ xfs_dquot_t *dqp;
|
|
|
|
|
|
- /*
|
|
|
|
- * Get the Quota Manager to flush the dquots.
|
|
|
|
- */
|
|
|
|
- if (XFS_IS_QUOTA_ON(mp)) {
|
|
|
|
- if ((error = xfs_qm_sync(mp, flags))) {
|
|
|
|
- /*
|
|
|
|
- * If we got an IO error, we will be shutting down.
|
|
|
|
- * So, there's nothing more for us to do here.
|
|
|
|
- */
|
|
|
|
- ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
|
|
|
|
- if (XFS_FORCED_SHUTDOWN(mp)) {
|
|
|
|
- return XFS_ERROR(error);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) ||
|
|
|
|
+ !((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))) ==
|
|
|
|
+ (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
|
|
|
|
+ xfs_disk_dquot_t *dp = &dqp->q_core;
|
|
|
|
+
|
|
|
|
+ xfs_fill_statvfs_from_dquot(statp, dp);
|
|
|
|
+ xfs_qm_dqput(dqp);
|
|
}
|
|
}
|
|
- return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
STATIC int
|
|
STATIC int
|
|
@@ -382,7 +221,7 @@ xfs_qm_dqrele_null(
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static struct xfs_qmops xfs_qmcore_xfs = {
|
|
|
|
|
|
+struct xfs_qmops xfs_qmcore_xfs = {
|
|
.xfs_qminit = xfs_qm_newmount,
|
|
.xfs_qminit = xfs_qm_newmount,
|
|
.xfs_qmdone = xfs_qm_unmount_quotadestroy,
|
|
.xfs_qmdone = xfs_qm_unmount_quotadestroy,
|
|
.xfs_qmmount = xfs_qm_endmount,
|
|
.xfs_qmmount = xfs_qm_endmount,
|
|
@@ -396,36 +235,24 @@ static struct xfs_qmops xfs_qmcore_xfs = {
|
|
.xfs_dqvoprename = xfs_qm_vop_rename_dqattach,
|
|
.xfs_dqvoprename = xfs_qm_vop_rename_dqattach,
|
|
.xfs_dqvopchown = xfs_qm_vop_chown,
|
|
.xfs_dqvopchown = xfs_qm_vop_chown,
|
|
.xfs_dqvopchownresv = xfs_qm_vop_chown_reserve,
|
|
.xfs_dqvopchownresv = xfs_qm_vop_chown_reserve,
|
|
|
|
+ .xfs_dqstatvfs = xfs_qm_statvfs,
|
|
|
|
+ .xfs_dqsync = xfs_qm_sync,
|
|
|
|
+ .xfs_quotactl = xfs_qm_quotactl,
|
|
.xfs_dqtrxops = &xfs_trans_dquot_ops,
|
|
.xfs_dqtrxops = &xfs_trans_dquot_ops,
|
|
};
|
|
};
|
|
-
|
|
|
|
-struct bhv_module_vfsops xfs_qmops = { {
|
|
|
|
- BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM),
|
|
|
|
- .vfs_parseargs = xfs_qm_parseargs,
|
|
|
|
- .vfs_showargs = xfs_qm_showargs,
|
|
|
|
- .vfs_mount = xfs_qm_mount,
|
|
|
|
- .vfs_statvfs = xfs_qm_statvfs,
|
|
|
|
- .vfs_sync = xfs_qm_syncall,
|
|
|
|
- .vfs_quotactl = xfs_qm_quotactl, },
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
|
|
+EXPORT_SYMBOL(xfs_qmcore_xfs);
|
|
|
|
|
|
void __init
|
|
void __init
|
|
xfs_qm_init(void)
|
|
xfs_qm_init(void)
|
|
{
|
|
{
|
|
- static char message[] __initdata =
|
|
|
|
- KERN_INFO "SGI XFS Quota Management subsystem\n";
|
|
|
|
-
|
|
|
|
- printk(message);
|
|
|
|
|
|
+ printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
|
|
mutex_init(&xfs_Gqm_lock);
|
|
mutex_init(&xfs_Gqm_lock);
|
|
- vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs);
|
|
|
|
xfs_qm_init_procfs();
|
|
xfs_qm_init_procfs();
|
|
}
|
|
}
|
|
|
|
|
|
void __exit
|
|
void __exit
|
|
xfs_qm_exit(void)
|
|
xfs_qm_exit(void)
|
|
{
|
|
{
|
|
- vfs_bhv_clr_custom(&xfs_qmops);
|
|
|
|
xfs_qm_cleanup_procfs();
|
|
xfs_qm_cleanup_procfs();
|
|
if (qm_dqzone)
|
|
if (qm_dqzone)
|
|
kmem_zone_destroy(qm_dqzone);
|
|
kmem_zone_destroy(qm_dqzone);
|