2005-04-17 02:20:36 +04:00
/*
2006-06-09 09:29:58 +04:00
* Copyright ( c ) 2000 - 2006 Silicon Graphics , Inc .
2005-11-02 06:59:41 +03:00
* All Rights Reserved .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:59:41 +03:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
2005-04-17 02:20:36 +04:00
* published by the Free Software Foundation .
*
2005-11-02 06:59:41 +03:00
* This program is distributed in the hope that it would be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:59:41 +03:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-04-17 02:20:36 +04:00
*/
# include "xfs.h"
# include "xfs_fs.h"
2013-08-12 14:49:26 +04:00
# include "xfs_format.h"
2013-10-23 03:50:10 +04:00
# include "xfs_log_format.h"
# include "xfs_trans_resv.h"
2005-04-17 02:20:36 +04:00
# include "xfs_quota.h"
# include "xfs_mount.h"
# include "xfs_inode.h"
# include "xfs_error.h"
2013-10-23 03:50:10 +04:00
# include "xfs_trans.h"
2005-04-17 02:20:36 +04:00
# include "xfs_qm.h"
2007-08-30 11:19:57 +04:00
STATIC void
xfs_fill_statvfs_from_dquot (
2008-11-28 06:23:36 +03:00
struct kstatfs * statp ,
2012-02-20 06:28:17 +04:00
struct xfs_dquot * dqp )
2006-06-09 09:29:58 +04:00
{
__uint64_t limit ;
2012-02-20 06:28:17 +04:00
limit = dqp - > q_core . d_blk_softlimit ?
be64_to_cpu ( dqp - > q_core . d_blk_softlimit ) :
be64_to_cpu ( dqp - > q_core . d_blk_hardlimit ) ;
2006-06-09 09:29:58 +04:00
if ( limit & & statp - > f_blocks > limit ) {
statp - > f_blocks = limit ;
2010-01-21 14:17:20 +03:00
statp - > f_bfree = statp - > f_bavail =
2012-02-20 06:28:17 +04:00
( statp - > f_blocks > dqp - > q_res_bcount ) ?
( statp - > f_blocks - dqp - > q_res_bcount ) : 0 ;
2006-06-09 09:29:58 +04:00
}
2006-07-28 11:04:26 +04:00
2012-02-20 06:28:17 +04:00
limit = dqp - > q_core . d_ino_softlimit ?
be64_to_cpu ( dqp - > q_core . d_ino_softlimit ) :
be64_to_cpu ( dqp - > q_core . d_ino_hardlimit ) ;
2006-06-09 09:29:58 +04:00
if ( limit & & statp - > f_files > limit ) {
statp - > f_files = limit ;
2006-07-28 11:04:26 +04:00
statp - > f_ffree =
2012-02-20 06:28:17 +04:00
( statp - > f_files > dqp - > q_res_icount ) ?
( statp - > f_ffree - dqp - > q_res_icount ) : 0 ;
2006-06-09 09:29:58 +04:00
}
}
2007-08-30 11:19:57 +04:00
/*
* 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 .
*/
2009-06-08 17:33:32 +04:00
void
2007-08-30 11:19:57 +04:00
xfs_qm_statvfs (
xfs_inode_t * ip ,
2008-11-28 06:23:36 +03:00
struct kstatfs * statp )
2005-04-17 02:20:36 +04:00
{
2007-08-30 11:19:57 +04:00
xfs_mount_t * mp = ip - > i_mount ;
xfs_dquot_t * dqp ;
2005-04-17 02:20:36 +04:00
2010-09-26 10:10:18 +04:00
if ( ! xfs_qm_dqget ( mp , NULL , xfs_get_projid ( ip ) , XFS_DQ_PROJ , 0 , & dqp ) ) {
2012-02-20 06:28:17 +04:00
xfs_fill_statvfs_from_dquot ( statp , dqp ) ;
2007-08-30 11:19:57 +04:00
xfs_qm_dqput ( dqp ) ;
2005-04-17 02:20:36 +04:00
}
}
2009-06-08 17:33:32 +04:00
int
2005-04-17 02:20:36 +04:00
xfs_qm_newmount (
xfs_mount_t * mp ,
uint * needquotamount ,
uint * quotaflags )
{
uint quotaondisk ;
2005-06-21 09:38:48 +04:00
uint uquotaondisk = 0 , gquotaondisk = 0 , pquotaondisk = 0 ;
2005-04-17 02:20:36 +04:00
2008-03-06 05:44:28 +03:00
quotaondisk = xfs_sb_version_hasquota ( & mp - > m_sb ) & &
2005-06-21 09:38:48 +04:00
( mp - > m_sb . sb_qflags & XFS_ALL_QUOTA_ACCT ) ;
2005-04-17 02:20:36 +04:00
if ( quotaondisk ) {
uquotaondisk = mp - > m_sb . sb_qflags & XFS_UQUOTA_ACCT ;
2005-06-21 09:38:48 +04:00
pquotaondisk = mp - > m_sb . sb_qflags & XFS_PQUOTA_ACCT ;
2005-04-17 02:20:36 +04:00
gquotaondisk = mp - > m_sb . sb_qflags & XFS_GQUOTA_ACCT ;
}
/*
* If the device itself is read - only , we can ' t allow
* the user to change the state of quota on the mount -
* this would generate a transaction on the ro device ,
* which would lead to an I / O error and shutdown
*/
if ( ( ( uquotaondisk & & ! XFS_IS_UQUOTA_ON ( mp ) ) | |
( ! uquotaondisk & & XFS_IS_UQUOTA_ON ( mp ) ) | |
( gquotaondisk & & ! XFS_IS_GQUOTA_ON ( mp ) ) | |
2013-07-11 09:00:40 +04:00
( ! gquotaondisk & & XFS_IS_GQUOTA_ON ( mp ) ) | |
( pquotaondisk & & ! XFS_IS_PQUOTA_ON ( mp ) ) | |
( ! pquotaondisk & & XFS_IS_PQUOTA_ON ( mp ) ) ) & &
2005-04-17 02:20:36 +04:00
xfs_dev_is_read_only ( mp , " changing quota state " ) ) {
2011-03-07 02:08:35 +03:00
xfs_warn ( mp , " please mount with%s%s%s%s. " ,
2005-04-17 02:20:36 +04:00
( ! quotaondisk ? " out quota " : " " ) ,
( uquotaondisk ? " usrquota " : " " ) ,
2013-07-11 09:00:40 +04:00
( gquotaondisk ? " grpquota " : " " ) ,
( pquotaondisk ? " prjquota " : " " ) ) ;
2014-06-25 08:58:08 +04:00
return - EPERM ;
2005-04-17 02:20:36 +04:00
}
if ( XFS_IS_QUOTA_ON ( mp ) | | quotaondisk ) {
/*
* Call mount_quotas at this point only if we won ' t have to do
* a quotacheck .
*/
if ( quotaondisk & & ! XFS_QM_NEED_QUOTACHECK ( mp ) ) {
/*
2011-03-31 05:57:33 +04:00
* If an error occurred , qm_mount_quotas code
2005-04-17 02:20:36 +04:00
* has already disabled quotas . So , just finish
* mounting , and get on with the boring life
* without disk quotas .
*/
2008-08-13 10:49:32 +04:00
xfs_qm_mount_quotas ( mp ) ;
2005-04-17 02:20:36 +04:00
} else {
/*
* Clear the quota flags , but remember them . This
* is so that the quota code doesn ' t get invoked
* before we ' re ready . This can happen when an
* inode goes inactive and wants to free blocks ,
* or via xfs_log_mount_finish .
*/
2012-11-13 03:32:59 +04:00
* needquotamount = true ;
2005-04-17 02:20:36 +04:00
* quotaflags = mp - > m_qflags ;
mp - > m_qflags = 0 ;
}
}
return 0 ;
}