Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
0004  * All Rights Reserved.
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_quota.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_inode.h"
0015 #include "xfs_trans.h"
0016 #include "xfs_qm.h"
0017 
0018 
0019 STATIC void
0020 xfs_fill_statvfs_from_dquot(
0021     struct kstatfs      *statp,
0022     struct xfs_dquot    *dqp)
0023 {
0024     uint64_t        limit;
0025 
0026     limit = dqp->q_blk.softlimit ?
0027         dqp->q_blk.softlimit :
0028         dqp->q_blk.hardlimit;
0029     if (limit && statp->f_blocks > limit) {
0030         statp->f_blocks = limit;
0031         statp->f_bfree = statp->f_bavail =
0032             (statp->f_blocks > dqp->q_blk.reserved) ?
0033              (statp->f_blocks - dqp->q_blk.reserved) : 0;
0034     }
0035 
0036     limit = dqp->q_ino.softlimit ?
0037         dqp->q_ino.softlimit :
0038         dqp->q_ino.hardlimit;
0039     if (limit && statp->f_files > limit) {
0040         statp->f_files = limit;
0041         statp->f_ffree =
0042             (statp->f_files > dqp->q_ino.reserved) ?
0043              (statp->f_files - dqp->q_ino.reserved) : 0;
0044     }
0045 }
0046 
0047 
0048 /*
0049  * Directory tree accounting is implemented using project quotas, where
0050  * the project identifier is inherited from parent directories.
0051  * A statvfs (df, etc.) of a directory that is using project quota should
0052  * return a statvfs of the project, not the entire filesystem.
0053  * This makes such trees appear as if they are filesystems in themselves.
0054  */
0055 void
0056 xfs_qm_statvfs(
0057     struct xfs_inode    *ip,
0058     struct kstatfs      *statp)
0059 {
0060     struct xfs_mount    *mp = ip->i_mount;
0061     struct xfs_dquot    *dqp;
0062 
0063     if (!xfs_qm_dqget(mp, ip->i_projid, XFS_DQTYPE_PROJ, false, &dqp)) {
0064         xfs_fill_statvfs_from_dquot(statp, dqp);
0065         xfs_qm_dqput(dqp);
0066     }
0067 }
0068 
0069 int
0070 xfs_qm_newmount(
0071     xfs_mount_t *mp,
0072     uint        *needquotamount,
0073     uint        *quotaflags)
0074 {
0075     uint        quotaondisk;
0076     uint        uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
0077 
0078     quotaondisk = xfs_has_quota(mp) &&
0079                 (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
0080 
0081     if (quotaondisk) {
0082         uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
0083         pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
0084         gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
0085     }
0086 
0087     /*
0088      * If the device itself is read-only, we can't allow
0089      * the user to change the state of quota on the mount -
0090      * this would generate a transaction on the ro device,
0091      * which would lead to an I/O error and shutdown
0092      */
0093 
0094     if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
0095         (!uquotaondisk &&  XFS_IS_UQUOTA_ON(mp)) ||
0096          (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
0097         (!gquotaondisk &&  XFS_IS_GQUOTA_ON(mp)) ||
0098          (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
0099         (!pquotaondisk &&  XFS_IS_PQUOTA_ON(mp)))  &&
0100         xfs_dev_is_read_only(mp, "changing quota state")) {
0101         xfs_warn(mp, "please mount with%s%s%s%s.",
0102             (!quotaondisk ? "out quota" : ""),
0103             (uquotaondisk ? " usrquota" : ""),
0104             (gquotaondisk ? " grpquota" : ""),
0105             (pquotaondisk ? " prjquota" : ""));
0106         return -EPERM;
0107     }
0108 
0109     if (XFS_IS_QUOTA_ON(mp) || quotaondisk) {
0110         /*
0111          * Call mount_quotas at this point only if we won't have to do
0112          * a quotacheck.
0113          */
0114         if (quotaondisk && !XFS_QM_NEED_QUOTACHECK(mp)) {
0115             /*
0116              * If an error occurred, qm_mount_quotas code
0117              * has already disabled quotas. So, just finish
0118              * mounting, and get on with the boring life
0119              * without disk quotas.
0120              */
0121             xfs_qm_mount_quotas(mp);
0122         } else {
0123             /*
0124              * Clear the quota flags, but remember them. This
0125              * is so that the quota code doesn't get invoked
0126              * before we're ready. This can happen when an
0127              * inode goes inactive and wants to free blocks,
0128              * or via xfs_log_mount_finish.
0129              */
0130             *needquotamount = true;
0131             *quotaflags = mp->m_qflags;
0132             mp->m_qflags = 0;
0133         }
0134     }
0135 
0136     return 0;
0137 }