linux/fs/xfs/quota/xfs_qm_bhv.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
   3 * All Rights Reserved.
   4 *
   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.
   8 *
   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.
  13 *
  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
  17 */
  18#include "xfs.h"
  19#include "xfs_fs.h"
  20#include "xfs_bit.h"
  21#include "xfs_log.h"
  22#include "xfs_inum.h"
  23#include "xfs_trans.h"
  24#include "xfs_sb.h"
  25#include "xfs_ag.h"
  26#include "xfs_alloc.h"
  27#include "xfs_quota.h"
  28#include "xfs_mount.h"
  29#include "xfs_bmap_btree.h"
  30#include "xfs_inode.h"
  31#include "xfs_itable.h"
  32#include "xfs_bmap.h"
  33#include "xfs_rtalloc.h"
  34#include "xfs_error.h"
  35#include "xfs_attr.h"
  36#include "xfs_buf_item.h"
  37#include "xfs_qm.h"
  38
  39
  40STATIC void
  41xfs_fill_statvfs_from_dquot(
  42        struct kstatfs          *statp,
  43        xfs_disk_dquot_t        *dp)
  44{
  45        __uint64_t              limit;
  46
  47        limit = dp->d_blk_softlimit ?
  48                be64_to_cpu(dp->d_blk_softlimit) :
  49                be64_to_cpu(dp->d_blk_hardlimit);
  50        if (limit && statp->f_blocks > limit) {
  51                statp->f_blocks = limit;
  52                statp->f_bfree = statp->f_bavail =
  53                        (statp->f_blocks > be64_to_cpu(dp->d_bcount)) ?
  54                         (statp->f_blocks - be64_to_cpu(dp->d_bcount)) : 0;
  55        }
  56
  57        limit = dp->d_ino_softlimit ?
  58                be64_to_cpu(dp->d_ino_softlimit) :
  59                be64_to_cpu(dp->d_ino_hardlimit);
  60        if (limit && statp->f_files > limit) {
  61                statp->f_files = limit;
  62                statp->f_ffree =
  63                        (statp->f_files > be64_to_cpu(dp->d_icount)) ?
  64                         (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
  65        }
  66}
  67
  68
  69/*
  70 * Directory tree accounting is implemented using project quotas, where
  71 * the project identifier is inherited from parent directories.
  72 * A statvfs (df, etc.) of a directory that is using project quota should
  73 * return a statvfs of the project, not the entire filesystem.
  74 * This makes such trees appear as if they are filesystems in themselves.
  75 */
  76void
  77xfs_qm_statvfs(
  78        xfs_inode_t             *ip,
  79        struct kstatfs          *statp)
  80{
  81        xfs_mount_t             *mp = ip->i_mount;
  82        xfs_dquot_t             *dqp;
  83
  84        if (!xfs_qm_dqget(mp, NULL, xfs_get_projid(ip), XFS_DQ_PROJ, 0, &dqp)) {
  85                xfs_fill_statvfs_from_dquot(statp, &dqp->q_core);
  86                xfs_qm_dqput(dqp);
  87        }
  88}
  89
  90int
  91xfs_qm_newmount(
  92        xfs_mount_t     *mp,
  93        uint            *needquotamount,
  94        uint            *quotaflags)
  95{
  96        uint            quotaondisk;
  97        uint            uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
  98
  99        quotaondisk = xfs_sb_version_hasquota(&mp->m_sb) &&
 100                                (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
 101
 102        if (quotaondisk) {
 103                uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
 104                pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
 105                gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
 106        }
 107
 108        /*
 109         * If the device itself is read-only, we can't allow
 110         * the user to change the state of quota on the mount -
 111         * this would generate a transaction on the ro device,
 112         * which would lead to an I/O error and shutdown
 113         */
 114
 115        if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
 116            (!uquotaondisk &&  XFS_IS_UQUOTA_ON(mp)) ||
 117             (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
 118            (!pquotaondisk &&  XFS_IS_PQUOTA_ON(mp)) ||
 119             (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
 120            (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&
 121            xfs_dev_is_read_only(mp, "changing quota state")) {
 122                cmn_err(CE_WARN,
 123                        "XFS: please mount with%s%s%s%s.",
 124                        (!quotaondisk ? "out quota" : ""),
 125                        (uquotaondisk ? " usrquota" : ""),
 126                        (pquotaondisk ? " prjquota" : ""),
 127                        (gquotaondisk ? " grpquota" : ""));
 128                return XFS_ERROR(EPERM);
 129        }
 130
 131        if (XFS_IS_QUOTA_ON(mp) || quotaondisk) {
 132                /*
 133                 * Call mount_quotas at this point only if we won't have to do
 134                 * a quotacheck.
 135                 */
 136                if (quotaondisk && !XFS_QM_NEED_QUOTACHECK(mp)) {
 137                        /*
 138                         * If an error occured, qm_mount_quotas code
 139                         * has already disabled quotas. So, just finish
 140                         * mounting, and get on with the boring life
 141                         * without disk quotas.
 142                         */
 143                        xfs_qm_mount_quotas(mp);
 144                } else {
 145                        /*
 146                         * Clear the quota flags, but remember them. This
 147                         * is so that the quota code doesn't get invoked
 148                         * before we're ready. This can happen when an
 149                         * inode goes inactive and wants to free blocks,
 150                         * or via xfs_log_mount_finish.
 151                         */
 152                        *needquotamount = B_TRUE;
 153                        *quotaflags = mp->m_qflags;
 154                        mp->m_qflags = 0;
 155                }
 156        }
 157
 158        return 0;
 159}
 160
 161void __init
 162xfs_qm_init(void)
 163{
 164        printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
 165        mutex_init(&xfs_Gqm_lock);
 166        xfs_qm_init_procfs();
 167}
 168
 169void __exit
 170xfs_qm_exit(void)
 171{
 172        xfs_qm_cleanup_procfs();
 173        if (qm_dqzone)
 174                kmem_zone_destroy(qm_dqzone);
 175        if (qm_dqtrxzone)
 176                kmem_zone_destroy(qm_dqtrxzone);
 177}
 178