aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index 6838b36d95a9..181dd90b29ce 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved. 3 * All Rights Reserved.
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -185,6 +185,61 @@ xfs_qm_mount(
185 return error; 185 return error;
186} 186}
187 187
188/*
189 * Directory tree accounting is implemented using project quotas, where
190 * the project identifier is inherited from parent directories.
191 * A statvfs (df, etc.) of a directory that is using project quota should
192 * return a statvfs of the project, not the entire filesystem.
193 * This makes such trees appear as if they are filesystems in themselves.
194 */
195STATIC int
196xfs_qm_statvfs(
197 struct bhv_desc *bhv,
198 xfs_statfs_t *statp,
199 struct vnode *vnode)
200{
201 xfs_mount_t *mp;
202 xfs_inode_t *ip;
203 xfs_dquot_t *dqp;
204 xfs_disk_dquot_t *dp;
205 __uint64_t limit;
206 int error;
207
208 error = PVFS_STATVFS(BHV_NEXT(bhv), statp, vnode);
209 if (error || !vnode)
210 return error;
211
212 mp = XFS_BHVTOM(bhv);
213 ip = xfs_vtoi(vnode);
214
215 if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
216 return 0;
217 if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
218 return 0;
219 if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
220 return 0;
221
222 if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
223 return 0;
224 dp = &dqp->q_core;
225
226 limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit;
227 if (limit && statp->f_blocks > limit) {
228 statp->f_blocks = limit;
229 statp->f_bfree = (statp->f_blocks > dp->d_bcount) ?
230 (statp->f_blocks - dp->d_bcount) : 0;
231 }
232 limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit;
233 if (limit && statp->f_files > limit) {
234 statp->f_files = limit;
235 statp->f_ffree = (statp->f_files > dp->d_icount) ?
236 (statp->f_ffree - dp->d_icount) : 0;
237 }
238
239 xfs_qm_dqput(dqp);
240 return 0;
241}
242
188STATIC int 243STATIC int
189xfs_qm_syncall( 244xfs_qm_syncall(
190 struct bhv_desc *bhv, 245 struct bhv_desc *bhv,
@@ -351,6 +406,7 @@ struct bhv_vfsops xfs_qmops = { {
351 .vfs_parseargs = xfs_qm_parseargs, 406 .vfs_parseargs = xfs_qm_parseargs,
352 .vfs_showargs = xfs_qm_showargs, 407 .vfs_showargs = xfs_qm_showargs,
353 .vfs_mount = xfs_qm_mount, 408 .vfs_mount = xfs_qm_mount,
409 .vfs_statvfs = xfs_qm_statvfs,
354 .vfs_sync = xfs_qm_syncall, 410 .vfs_sync = xfs_qm_syncall,
355 .vfs_quotactl = xfs_qm_quotactl, }, 411 .vfs_quotactl = xfs_qm_quotactl, },
356}; 412};