aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2007-08-30 03:19:57 -0400
committerTim Shimmin <tes@chook.melbourne.sgi.com>2007-10-15 21:43:26 -0400
commitb09cc77109dbf33463480952de10511a2b67bba6 (patch)
tree722ed205af03de0f33b955aeb3a573565242497a /fs/xfs
parent293688ec420f1160ed93ea4c7948ed5baf8bafa7 (diff)
[XFS] remove dependency of the quota module on behaviors
Mount options are now parsed by the main XFS module and rejected if quota support is not available, and there are some new quota operation for the quotactl syscall and calls to quote in the mount, unmount and sync callchains. SGI-PV: 969608 SGI-Modid: xfs-linux-melb:xfs-kern:29503a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: David Chinner <dgc@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c10
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.c15
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h5
-rw-r--r--fs/xfs/quota/xfs_qm.c41
-rw-r--r--fs/xfs/quota/xfs_qm.h6
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c239
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c7
-rw-r--r--fs/xfs/xfs_mount.h43
-rw-r--r--fs/xfs/xfs_qmops.c38
-rw-r--r--fs/xfs/xfs_quota.h10
-rw-r--r--fs/xfs/xfs_vfsops.c110
12 files changed, 224 insertions, 303 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 24073f8a292b..103add6eccb6 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -729,7 +729,7 @@ xfs_fs_quotasync(
729 struct super_block *sb, 729 struct super_block *sb,
730 int type) 730 int type)
731{ 731{
732 return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL); 732 return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL);
733} 733}
734 734
735STATIC int 735STATIC int
@@ -737,7 +737,7 @@ xfs_fs_getxstate(
737 struct super_block *sb, 737 struct super_block *sb,
738 struct fs_quota_stat *fqs) 738 struct fs_quota_stat *fqs)
739{ 739{
740 return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs); 740 return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
741} 741}
742 742
743STATIC int 743STATIC int
@@ -746,7 +746,7 @@ xfs_fs_setxstate(
746 unsigned int flags, 746 unsigned int flags,
747 int op) 747 int op)
748{ 748{
749 return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags); 749 return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags);
750} 750}
751 751
752STATIC int 752STATIC int
@@ -756,7 +756,7 @@ xfs_fs_getxquota(
756 qid_t id, 756 qid_t id,
757 struct fs_disk_quota *fdq) 757 struct fs_disk_quota *fdq)
758{ 758{
759 return -bhv_vfs_quotactl(vfs_from_sb(sb), 759 return -XFS_QM_QUOTACTL(XFS_M(sb),
760 (type == USRQUOTA) ? Q_XGETQUOTA : 760 (type == USRQUOTA) ? Q_XGETQUOTA :
761 ((type == GRPQUOTA) ? Q_XGETGQUOTA : 761 ((type == GRPQUOTA) ? Q_XGETGQUOTA :
762 Q_XGETPQUOTA), id, (caddr_t)fdq); 762 Q_XGETPQUOTA), id, (caddr_t)fdq);
@@ -769,7 +769,7 @@ xfs_fs_setxquota(
769 qid_t id, 769 qid_t id,
770 struct fs_disk_quota *fdq) 770 struct fs_disk_quota *fdq)
771{ 771{
772 return -bhv_vfs_quotactl(vfs_from_sb(sb), 772 return -XFS_QM_QUOTACTL(XFS_M(sb),
773 (type == USRQUOTA) ? Q_XSETQLIM : 773 (type == USRQUOTA) ? Q_XSETQLIM :
774 ((type == GRPQUOTA) ? Q_XSETGQLIM : 774 ((type == GRPQUOTA) ? Q_XSETGQLIM :
775 Q_XSETPQLIM), id, (caddr_t)fdq); 775 Q_XSETPQLIM), id, (caddr_t)fdq);
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index ea2ee5a92637..4bbf985a7de7 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -119,4 +119,7 @@ extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
119 119
120extern struct export_operations xfs_export_operations; 120extern struct export_operations xfs_export_operations;
121 121
122#define XFS_M(sb) \
123 XFS_VFSTOM(vfs_from_sb(sb))
124
122#endif /* __XFS_SUPER_H__ */ 125#endif /* __XFS_SUPER_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index 1ce15706458a..5f616ccaea8d 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -155,21 +155,6 @@ vfs_vget(
155 return ((*bhvtovfsops(next)->vfs_vget)(next, vpp, fidp)); 155 return ((*bhvtovfsops(next)->vfs_vget)(next, vpp, fidp));
156} 156}
157 157
158int
159vfs_quotactl(
160 struct bhv_desc *bdp,
161 int cmd,
162 int id,
163 caddr_t addr)
164{
165 struct bhv_desc *next = bdp;
166
167 ASSERT(next);
168 while (! (bhvtovfsops(next))->vfs_quotactl)
169 next = BHV_NEXT(next);
170 return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr));
171}
172
173void 158void
174vfs_init_vnode( 159vfs_init_vnode(
175 struct bhv_desc *bdp, 160 struct bhv_desc *bdp,
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index e63dbdbfd8a0..e63b2d012f0c 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -127,7 +127,6 @@ typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *,
127 struct inode *); 127 struct inode *);
128typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); 128typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
129typedef int (*vfs_vget_t)(bhv_desc_t *, struct inode **, struct fid *); 129typedef int (*vfs_vget_t)(bhv_desc_t *, struct inode **, struct fid *);
130typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
131typedef void (*vfs_init_vnode_t)(bhv_desc_t *, 130typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
132 struct inode *, struct xfs_inode *, int); 131 struct inode *, struct xfs_inode *, int);
133typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); 132typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
@@ -144,7 +143,6 @@ typedef struct bhv_vfsops {
144 vfs_statvfs_t vfs_statvfs; /* file system statistics */ 143 vfs_statvfs_t vfs_statvfs; /* file system statistics */
145 vfs_sync_t vfs_sync; /* flush files */ 144 vfs_sync_t vfs_sync; /* flush files */
146 vfs_vget_t vfs_vget; /* get vnode from fid */ 145 vfs_vget_t vfs_vget; /* get vnode from fid */
147 vfs_quotactl_t vfs_quotactl; /* disk quota */
148 vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ 146 vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
149 vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ 147 vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
150 vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ 148 vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */
@@ -163,7 +161,6 @@ typedef struct bhv_vfsops {
163#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp) 161#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp)
164#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr) 162#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr)
165#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp) 163#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp)
166#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p)
167#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul) 164#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul)
168#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l) 165#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l)
169#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v)) 166#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v))
@@ -180,7 +177,6 @@ typedef struct bhv_vfsops {
180#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp) 177#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp)
181#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr) 178#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr)
182#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp) 179#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp)
183#define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p)
184#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul) 180#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul)
185#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l) 181#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l)
186#define bhv_next_vfs_freeze(b) vfs_freeze(b) 182#define bhv_next_vfs_freeze(b) vfs_freeze(b)
@@ -194,7 +190,6 @@ extern int vfs_root(bhv_desc_t *, struct inode **);
194extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct inode *); 190extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct inode *);
195extern int vfs_sync(bhv_desc_t *, int, struct cred *); 191extern int vfs_sync(bhv_desc_t *, int, struct cred *);
196extern int vfs_vget(bhv_desc_t *, struct inode **, struct fid *); 192extern int vfs_vget(bhv_desc_t *, struct inode **, struct fid *);
197extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
198extern void vfs_init_vnode(bhv_desc_t *, struct inode *, struct xfs_inode *, int); 193extern void vfs_init_vnode(bhv_desc_t *, struct inode *, struct xfs_inode *, int);
199extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); 194extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
200extern void vfs_freeze(bhv_desc_t *); 195extern void vfs_freeze(bhv_desc_t *);
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 9567d1846ee5..8f5a43669297 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -288,45 +288,6 @@ xfs_qm_rele_quotafs_ref(
288} 288}
289 289
290/* 290/*
291 * This is called at mount time from xfs_mountfs to initialize the quotainfo
292 * structure and start the global quota manager (xfs_Gqm) if it hasn't done
293 * so already. Note that the superblock has not been read in yet.
294 */
295void
296xfs_qm_mount_quotainit(
297 xfs_mount_t *mp,
298 uint flags)
299{
300 /*
301 * User, projects or group quotas has to be on.
302 */
303 ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
304
305 /*
306 * Initialize the flags in the mount structure. From this point
307 * onwards we look at m_qflags to figure out if quotas's ON/OFF, etc.
308 * Note that we enforce nothing if accounting is off.
309 * ie. XFSMNT_*QUOTA must be ON for XFSMNT_*QUOTAENF.
310 * It isn't necessary to take the quotaoff lock to do this; this is
311 * called from mount.
312 */
313 if (flags & XFSMNT_UQUOTA) {
314 mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
315 if (flags & XFSMNT_UQUOTAENF)
316 mp->m_qflags |= XFS_UQUOTA_ENFD;
317 }
318 if (flags & XFSMNT_GQUOTA) {
319 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
320 if (flags & XFSMNT_GQUOTAENF)
321 mp->m_qflags |= XFS_OQUOTA_ENFD;
322 } else if (flags & XFSMNT_PQUOTA) {
323 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
324 if (flags & XFSMNT_PQUOTAENF)
325 mp->m_qflags |= XFS_OQUOTA_ENFD;
326 }
327}
328
329/*
330 * Just destroy the quotainfo structure. 291 * Just destroy the quotainfo structure.
331 */ 292 */
332void 293void
@@ -1039,7 +1000,7 @@ xfs_qm_dqdetach(
1039int 1000int
1040xfs_qm_sync( 1001xfs_qm_sync(
1041 xfs_mount_t *mp, 1002 xfs_mount_t *mp,
1042 short flags) 1003 int flags)
1043{ 1004{
1044 int recl, restarts; 1005 int recl, restarts;
1045 xfs_dquot_t *dqp; 1006 xfs_dquot_t *dqp;
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 689407de0a20..23ccaa5fceaf 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -166,12 +166,11 @@ typedef struct xfs_dquot_acct {
166 166
167extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); 167extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
168extern int xfs_qm_mount_quotas(xfs_mount_t *, int); 168extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
169extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
170extern int xfs_qm_quotacheck(xfs_mount_t *); 169extern int xfs_qm_quotacheck(xfs_mount_t *);
171extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *); 170extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *);
172extern int xfs_qm_unmount_quotas(xfs_mount_t *); 171extern int xfs_qm_unmount_quotas(xfs_mount_t *);
173extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); 172extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
174extern int xfs_qm_sync(xfs_mount_t *, short); 173extern int xfs_qm_sync(xfs_mount_t *, int);
175 174
176/* dquot stuff */ 175/* dquot stuff */
177extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **); 176extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **);
@@ -199,7 +198,8 @@ extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
199extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *); 198extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
200 199
201/* system call interface */ 200/* system call interface */
202extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t); 201extern int xfs_qm_quotactl(struct xfs_mount *, int, int,
202 xfs_caddr_t);
203 203
204#ifdef DEBUG 204#ifdef DEBUG
205extern int xfs_qm_internalqcheck(xfs_mount_t *); 205extern int xfs_qm_internalqcheck(xfs_mount_t *);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index ca25ee31a02f..97bb32937585 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -48,172 +48,13 @@
48#include "xfs_buf_item.h" 48#include "xfs_buf_item.h"
49#include "xfs_qm.h" 49#include "xfs_qm.h"
50 50
51#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
52#define MNTOPT_NOQUOTA "noquota" /* no quotas */
53#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
54#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
55#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
56#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
57#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
58#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
59#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
60#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
61#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
62#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
63 51
64STATIC int 52STATIC void
65xfs_qm_parseargs( 53xfs_fill_statvfs_from_dquot(
66 struct bhv_desc *bhv,
67 char *options,
68 struct xfs_mount_args *args,
69 int update)
70{
71 size_t length;
72 char *local_options = options;
73 char *this_char;
74 int error;
75 int referenced = update;
76
77 while ((this_char = strsep(&local_options, ",")) != NULL) {
78 length = strlen(this_char);
79 if (local_options)
80 length++;
81
82 if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
83 args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
84 args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
85 referenced = update;
86 } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
87 !strcmp(this_char, MNTOPT_UQUOTA) ||
88 !strcmp(this_char, MNTOPT_USRQUOTA)) {
89 args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
90 referenced = 1;
91 } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
92 !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
93 args->flags |= XFSMNT_UQUOTA;
94 args->flags &= ~XFSMNT_UQUOTAENF;
95 referenced = 1;
96 } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
97 !strcmp(this_char, MNTOPT_PRJQUOTA)) {
98 args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
99 referenced = 1;
100 } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
101 args->flags |= XFSMNT_PQUOTA;
102 args->flags &= ~XFSMNT_PQUOTAENF;
103 referenced = 1;
104 } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
105 !strcmp(this_char, MNTOPT_GRPQUOTA)) {
106 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
107 referenced = 1;
108 } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
109 args->flags |= XFSMNT_GQUOTA;
110 args->flags &= ~XFSMNT_GQUOTAENF;
111 referenced = 1;
112 } else {
113 if (local_options)
114 *(local_options-1) = ',';
115 continue;
116 }
117
118 while (length--)
119 *this_char++ = ',';
120 }
121
122 if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
123 cmn_err(CE_WARN,
124 "XFS: cannot mount with both project and group quota");
125 return XFS_ERROR(EINVAL);
126 }
127
128 error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
129 if (!error && !referenced)
130 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
131 return error;
132}
133
134STATIC int
135xfs_qm_showargs(
136 struct bhv_desc *bhv,
137 struct seq_file *m)
138{
139 struct bhv_vfs *vfsp = bhvtovfs(bhv);
140 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
141
142 if (mp->m_qflags & XFS_UQUOTA_ACCT) {
143 (mp->m_qflags & XFS_UQUOTA_ENFD) ?
144 seq_puts(m, "," MNTOPT_USRQUOTA) :
145 seq_puts(m, "," MNTOPT_UQUOTANOENF);
146 }
147
148 if (mp->m_qflags & XFS_PQUOTA_ACCT) {
149 (mp->m_qflags & XFS_OQUOTA_ENFD) ?
150 seq_puts(m, "," MNTOPT_PRJQUOTA) :
151 seq_puts(m, "," MNTOPT_PQUOTANOENF);
152 }
153
154 if (mp->m_qflags & XFS_GQUOTA_ACCT) {
155 (mp->m_qflags & XFS_OQUOTA_ENFD) ?
156 seq_puts(m, "," MNTOPT_GRPQUOTA) :
157 seq_puts(m, "," MNTOPT_GQUOTANOENF);
158 }
159
160 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
161 seq_puts(m, "," MNTOPT_NOQUOTA);
162
163 return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
164}
165
166STATIC int
167xfs_qm_mount(
168 struct bhv_desc *bhv,
169 struct xfs_mount_args *args,
170 struct cred *cr)
171{
172 struct bhv_vfs *vfsp = bhvtovfs(bhv);
173 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
174
175 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
176 xfs_qm_mount_quotainit(mp, args->flags);
177 return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
178}
179
180/*
181 * Directory tree accounting is implemented using project quotas, where
182 * the project identifier is inherited from parent directories.
183 * A statvfs (df, etc.) of a directory that is using project quota should
184 * return a statvfs of the project, not the entire filesystem.
185 * This makes such trees appear as if they are filesystems in themselves.
186 */
187STATIC int
188xfs_qm_statvfs(
189 struct bhv_desc *bhv,
190 bhv_statvfs_t *statp, 54 bhv_statvfs_t *statp,
191 bhv_vnode_t *vnode) 55 xfs_disk_dquot_t *dp)
192{ 56{
193 xfs_mount_t *mp;
194 xfs_inode_t *ip;
195 xfs_dquot_t *dqp;
196 xfs_disk_dquot_t *dp;
197 __uint64_t limit; 57 __uint64_t limit;
198 int error;
199
200 error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
201 if (error || !vnode)
202 return error;
203
204 mp = xfs_vfstom(bhvtovfs(bhv));
205 ip = xfs_vtoi(vnode);
206
207 if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
208 return 0;
209 if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
210 return 0;
211 if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
212 return 0;
213
214 if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
215 return 0;
216 dp = &dqp->q_core;
217 58
218 limit = dp->d_blk_softlimit ? 59 limit = dp->d_blk_softlimit ?
219 be64_to_cpu(dp->d_blk_softlimit) : 60 be64_to_cpu(dp->d_blk_softlimit) :
@@ -234,37 +75,35 @@ xfs_qm_statvfs(
234 (statp->f_files > be64_to_cpu(dp->d_icount)) ? 75 (statp->f_files > be64_to_cpu(dp->d_icount)) ?
235 (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0; 76 (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
236 } 77 }
237
238 xfs_qm_dqput(dqp);
239 return 0;
240} 78}
241 79
242STATIC int 80
243xfs_qm_syncall( 81/*
244 struct bhv_desc *bhv, 82 * Directory tree accounting is implemented using project quotas, where
245 int flags, 83 * the project identifier is inherited from parent directories.
246 cred_t *credp) 84 * A statvfs (df, etc.) of a directory that is using project quota should
85 * return a statvfs of the project, not the entire filesystem.
86 * This makes such trees appear as if they are filesystems in themselves.
87 */
88STATIC void
89xfs_qm_statvfs(
90 xfs_inode_t *ip,
91 bhv_statvfs_t *statp)
247{ 92{
248 struct bhv_vfs *vfsp = bhvtovfs(bhv); 93 xfs_mount_t *mp = ip->i_mount;
249 struct xfs_mount *mp = XFS_VFSTOM(vfsp); 94 xfs_dquot_t *dqp;
250 int error;
251 95
252 /* 96 if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) ||
253 * Get the Quota Manager to flush the dquots. 97 !((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))) ==
254 */ 98 (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
255 if (XFS_IS_QUOTA_ON(mp)) { 99 return;
256 if ((error = xfs_qm_sync(mp, flags))) { 100
257 /* 101 if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
258 * If we got an IO error, we will be shutting down. 102 xfs_disk_dquot_t *dp = &dqp->q_core;
259 * So, there's nothing more for us to do here. 103
260 */ 104 xfs_fill_statvfs_from_dquot(statp, dp);
261 ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp)); 105 xfs_qm_dqput(dqp);
262 if (XFS_FORCED_SHUTDOWN(mp)) {
263 return XFS_ERROR(error);
264 }
265 }
266 } 106 }
267 return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp);
268} 107}
269 108
270STATIC int 109STATIC int
@@ -382,7 +221,7 @@ xfs_qm_dqrele_null(
382} 221}
383 222
384 223
385static struct xfs_qmops xfs_qmcore_xfs = { 224struct xfs_qmops xfs_qmcore_xfs = {
386 .xfs_qminit = xfs_qm_newmount, 225 .xfs_qminit = xfs_qm_newmount,
387 .xfs_qmdone = xfs_qm_unmount_quotadestroy, 226 .xfs_qmdone = xfs_qm_unmount_quotadestroy,
388 .xfs_qmmount = xfs_qm_endmount, 227 .xfs_qmmount = xfs_qm_endmount,
@@ -396,36 +235,24 @@ static struct xfs_qmops xfs_qmcore_xfs = {
396 .xfs_dqvoprename = xfs_qm_vop_rename_dqattach, 235 .xfs_dqvoprename = xfs_qm_vop_rename_dqattach,
397 .xfs_dqvopchown = xfs_qm_vop_chown, 236 .xfs_dqvopchown = xfs_qm_vop_chown,
398 .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve, 237 .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve,
238 .xfs_dqstatvfs = xfs_qm_statvfs,
239 .xfs_dqsync = xfs_qm_sync,
240 .xfs_quotactl = xfs_qm_quotactl,
399 .xfs_dqtrxops = &xfs_trans_dquot_ops, 241 .xfs_dqtrxops = &xfs_trans_dquot_ops,
400}; 242};
401 243EXPORT_SYMBOL(xfs_qmcore_xfs);
402struct bhv_module_vfsops xfs_qmops = { {
403 BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM),
404 .vfs_parseargs = xfs_qm_parseargs,
405 .vfs_showargs = xfs_qm_showargs,
406 .vfs_mount = xfs_qm_mount,
407 .vfs_statvfs = xfs_qm_statvfs,
408 .vfs_sync = xfs_qm_syncall,
409 .vfs_quotactl = xfs_qm_quotactl, },
410};
411
412 244
413void __init 245void __init
414xfs_qm_init(void) 246xfs_qm_init(void)
415{ 247{
416 static char message[] __initdata = 248 printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
417 KERN_INFO "SGI XFS Quota Management subsystem\n";
418
419 printk(message);
420 mutex_init(&xfs_Gqm_lock); 249 mutex_init(&xfs_Gqm_lock);
421 vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs);
422 xfs_qm_init_procfs(); 250 xfs_qm_init_procfs();
423} 251}
424 252
425void __exit 253void __exit
426xfs_qm_exit(void) 254xfs_qm_exit(void)
427{ 255{
428 vfs_bhv_clr_custom(&xfs_qmops);
429 xfs_qm_cleanup_procfs(); 256 xfs_qm_cleanup_procfs();
430 if (qm_dqzone) 257 if (qm_dqzone)
431 kmem_zone_destroy(qm_dqzone); 258 kmem_zone_destroy(qm_dqzone);
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 2df67fd913e5..e0d024e73453 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -81,17 +81,14 @@ STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
81 */ 81 */
82int 82int
83xfs_qm_quotactl( 83xfs_qm_quotactl(
84 struct bhv_desc *bdp, 84 xfs_mount_t *mp,
85 int cmd, 85 int cmd,
86 int id, 86 int id,
87 xfs_caddr_t addr) 87 xfs_caddr_t addr)
88{ 88{
89 xfs_mount_t *mp; 89 bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
90 bhv_vfs_t *vfsp;
91 int error; 90 int error;
92 91
93 vfsp = bhvtovfs(bdp);
94 mp = XFS_VFSTOM(vfsp);
95 92
96 ASSERT(addr != NULL || cmd == Q_XQUOTASYNC); 93 ASSERT(addr != NULL || cmd == Q_XQUOTASYNC);
97 94
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index a7cd596ec6d2..594d7856c77e 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -142,6 +142,9 @@ typedef struct xfs_dquot * (*xfs_dqvopchown_t)(
142 struct xfs_dquot **, struct xfs_dquot *); 142 struct xfs_dquot **, struct xfs_dquot *);
143typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *, 143typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *,
144 struct xfs_dquot *, struct xfs_dquot *, uint); 144 struct xfs_dquot *, struct xfs_dquot *, uint);
145typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, bhv_statvfs_t *);
146typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags);
147typedef int (*xfs_quotactl_t)(struct xfs_mount *, int, int, xfs_caddr_t);
145 148
146typedef struct xfs_qmops { 149typedef struct xfs_qmops {
147 xfs_qminit_t xfs_qminit; 150 xfs_qminit_t xfs_qminit;
@@ -157,35 +160,44 @@ typedef struct xfs_qmops {
157 xfs_dqvoprename_t xfs_dqvoprename; 160 xfs_dqvoprename_t xfs_dqvoprename;
158 xfs_dqvopchown_t xfs_dqvopchown; 161 xfs_dqvopchown_t xfs_dqvopchown;
159 xfs_dqvopchownresv_t xfs_dqvopchownresv; 162 xfs_dqvopchownresv_t xfs_dqvopchownresv;
163 xfs_dqstatvfs_t xfs_dqstatvfs;
164 xfs_dqsync_t xfs_dqsync;
165 xfs_quotactl_t xfs_quotactl;
160 struct xfs_dqtrxops *xfs_dqtrxops; 166 struct xfs_dqtrxops *xfs_dqtrxops;
161} xfs_qmops_t; 167} xfs_qmops_t;
162 168
163#define XFS_QM_INIT(mp, mnt, fl) \ 169#define XFS_QM_INIT(mp, mnt, fl) \
164 (*(mp)->m_qm_ops.xfs_qminit)(mp, mnt, fl) 170 (*(mp)->m_qm_ops->xfs_qminit)(mp, mnt, fl)
165#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \ 171#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \
166 (*(mp)->m_qm_ops.xfs_qmmount)(mp, mnt, fl, mfsi_flags) 172 (*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl, mfsi_flags)
167#define XFS_QM_UNMOUNT(mp) \ 173#define XFS_QM_UNMOUNT(mp) \
168 (*(mp)->m_qm_ops.xfs_qmunmount)(mp) 174 (*(mp)->m_qm_ops->xfs_qmunmount)(mp)
169#define XFS_QM_DONE(mp) \ 175#define XFS_QM_DONE(mp) \
170 (*(mp)->m_qm_ops.xfs_qmdone)(mp) 176 (*(mp)->m_qm_ops->xfs_qmdone)(mp)
171#define XFS_QM_DQRELE(mp, dq) \ 177#define XFS_QM_DQRELE(mp, dq) \
172 (*(mp)->m_qm_ops.xfs_dqrele)(dq) 178 (*(mp)->m_qm_ops->xfs_dqrele)(dq)
173#define XFS_QM_DQATTACH(mp, ip, fl) \ 179#define XFS_QM_DQATTACH(mp, ip, fl) \
174 (*(mp)->m_qm_ops.xfs_dqattach)(ip, fl) 180 (*(mp)->m_qm_ops->xfs_dqattach)(ip, fl)
175#define XFS_QM_DQDETACH(mp, ip) \ 181#define XFS_QM_DQDETACH(mp, ip) \
176 (*(mp)->m_qm_ops.xfs_dqdetach)(ip) 182 (*(mp)->m_qm_ops->xfs_dqdetach)(ip)
177#define XFS_QM_DQPURGEALL(mp, fl) \ 183#define XFS_QM_DQPURGEALL(mp, fl) \
178 (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl) 184 (*(mp)->m_qm_ops->xfs_dqpurgeall)(mp, fl)
179#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \ 185#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
180 (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2) 186 (*(mp)->m_qm_ops->xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
181#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \ 187#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
182 (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2) 188 (*(mp)->m_qm_ops->xfs_dqvopcreate)(tp, ip, dq1, dq2)
183#define XFS_QM_DQVOPRENAME(mp, ip) \ 189#define XFS_QM_DQVOPRENAME(mp, ip) \
184 (*(mp)->m_qm_ops.xfs_dqvoprename)(ip) 190 (*(mp)->m_qm_ops->xfs_dqvoprename)(ip)
185#define XFS_QM_DQVOPCHOWN(mp, tp, ip, dqp, dq) \ 191#define XFS_QM_DQVOPCHOWN(mp, tp, ip, dqp, dq) \
186 (*(mp)->m_qm_ops.xfs_dqvopchown)(tp, ip, dqp, dq) 192 (*(mp)->m_qm_ops->xfs_dqvopchown)(tp, ip, dqp, dq)
187#define XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, dq1, dq2, fl) \ 193#define XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, dq1, dq2, fl) \
188 (*(mp)->m_qm_ops.xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl) 194 (*(mp)->m_qm_ops->xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl)
195#define XFS_QM_DQSTATVFS(ip, statp) \
196 (*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp)
197#define XFS_QM_DQSYNC(mp, flags) \
198 (*(mp)->m_qm_ops->xfs_dqsync)(mp, flags)
199#define XFS_QM_QUOTACTL(mp, cmd, id, addr) \
200 (*(mp)->m_qm_ops->xfs_quotactl)(mp, cmd, id, addr)
189 201
190 202
191/* 203/*
@@ -413,7 +425,7 @@ typedef struct xfs_mount {
413 struct xfs_chash *m_chash; /* fs private inode per-cluster 425 struct xfs_chash *m_chash; /* fs private inode per-cluster
414 * hash table */ 426 * hash table */
415 struct xfs_dmops *m_dm_ops; /* vector of DMI ops */ 427 struct xfs_dmops *m_dm_ops; /* vector of DMI ops */
416 struct xfs_qmops m_qm_ops; /* vector of XQM ops */ 428 struct xfs_qmops *m_qm_ops; /* vector of XQM ops */
417 struct xfs_ioops m_io_ops; /* vector of I/O ops */ 429 struct xfs_ioops m_io_ops; /* vector of I/O ops */
418 atomic_t m_active_trans; /* number trans frozen */ 430 atomic_t m_active_trans; /* number trans frozen */
419#ifdef HAVE_PERCPU_SB 431#ifdef HAVE_PERCPU_SB
@@ -649,9 +661,10 @@ extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
649 661
650extern int xfs_dmops_get(struct xfs_mount *, struct xfs_mount_args *); 662extern int xfs_dmops_get(struct xfs_mount *, struct xfs_mount_args *);
651extern void xfs_dmops_put(struct xfs_mount *); 663extern void xfs_dmops_put(struct xfs_mount *);
664extern int xfs_qmops_get(struct xfs_mount *, struct xfs_mount_args *);
665extern void xfs_qmops_put(struct xfs_mount *);
652 666
653extern struct xfs_dmops xfs_dmcore_xfs; 667extern struct xfs_dmops xfs_dmcore_xfs;
654extern struct xfs_qmops xfs_qmcore_stub;
655extern struct xfs_ioops xfs_iocore_xfs; 668extern struct xfs_ioops xfs_iocore_xfs;
656 669
657extern int xfs_init(void); 670extern int xfs_init(void);
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 0d594ed7efef..ea08bd8e8b80 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -28,6 +28,8 @@
28#include "xfs_mount.h" 28#include "xfs_mount.h"
29#include "xfs_quota.h" 29#include "xfs_quota.h"
30#include "xfs_error.h" 30#include "xfs_error.h"
31#include "xfs_clnt.h"
32
31 33
32STATIC struct xfs_dquot * 34STATIC struct xfs_dquot *
33xfs_dqvopchown_default( 35xfs_dqvopchown_default(
@@ -110,7 +112,7 @@ xfs_noquota_init(
110 return error; 112 return error;
111} 113}
112 114
113xfs_qmops_t xfs_qmcore_stub = { 115static struct xfs_qmops xfs_qmcore_stub = {
114 .xfs_qminit = (xfs_qminit_t) xfs_noquota_init, 116 .xfs_qminit = (xfs_qminit_t) xfs_noquota_init,
115 .xfs_qmdone = (xfs_qmdone_t) fs_noerr, 117 .xfs_qmdone = (xfs_qmdone_t) fs_noerr,
116 .xfs_qmmount = (xfs_qmmount_t) fs_noerr, 118 .xfs_qmmount = (xfs_qmmount_t) fs_noerr,
@@ -124,4 +126,38 @@ xfs_qmops_t xfs_qmcore_stub = {
124 .xfs_dqvoprename = (xfs_dqvoprename_t) fs_noerr, 126 .xfs_dqvoprename = (xfs_dqvoprename_t) fs_noerr,
125 .xfs_dqvopchown = xfs_dqvopchown_default, 127 .xfs_dqvopchown = xfs_dqvopchown_default,
126 .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr, 128 .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr,
129 .xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval,
130 .xfs_dqsync = (xfs_dqsync_t) fs_noerr,
131 .xfs_quotactl = (xfs_quotactl_t) fs_nosys,
127}; 132};
133
134int
135xfs_qmops_get(struct xfs_mount *mp, struct xfs_mount_args *args)
136{
137 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA)) {
138 struct xfs_qmops *ops;
139
140 ops = symbol_get(xfs_qmcore_xfs);
141 if (!ops) {
142 request_module("xfs_quota");
143 ops = symbol_get(xfs_qmcore_xfs);
144 }
145
146 if (!ops) {
147 cmn_err(CE_WARN, "XFS: no quota support available.");
148 return EINVAL;
149 }
150 mp->m_qm_ops = ops;
151 } else {
152 mp->m_qm_ops = &xfs_qmcore_stub;
153 }
154
155 return 0;
156}
157
158void
159xfs_qmops_put(struct xfs_mount *mp)
160{
161 if (mp->m_qm_ops != &xfs_qmcore_stub)
162 symbol_put(xfs_qmcore_xfs);
163}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 6f14df976f73..12c4ec775af8 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -330,12 +330,12 @@ typedef struct xfs_dqtrxops {
330} xfs_dqtrxops_t; 330} xfs_dqtrxops_t;
331 331
332#define XFS_DQTRXOP(mp, tp, op, args...) \ 332#define XFS_DQTRXOP(mp, tp, op, args...) \
333 ((mp)->m_qm_ops.xfs_dqtrxops ? \ 333 ((mp)->m_qm_ops->xfs_dqtrxops ? \
334 ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0) 334 ((mp)->m_qm_ops->xfs_dqtrxops->op)(tp, ## args) : 0)
335 335
336#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \ 336#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
337 ((mp)->m_qm_ops.xfs_dqtrxops ? \ 337 ((mp)->m_qm_ops->xfs_dqtrxops ? \
338 ((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0) 338 ((mp)->m_qm_ops->xfs_dqtrxops->op)(tp, ## args) : (void)0)
339 339
340#define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \ 340#define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
341 XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp) 341 XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
@@ -364,7 +364,7 @@ typedef struct xfs_dqtrxops {
364extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); 364extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
365extern int xfs_mount_reset_sbqflags(struct xfs_mount *); 365extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
366 366
367extern struct bhv_module_vfsops xfs_qmops; 367extern struct xfs_qmops xfs_qmcore_xfs;
368 368
369#endif /* __KERNEL__ */ 369#endif /* __KERNEL__ */
370 370
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 1cf8f54d8aa9..f62f6e486f23 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -402,6 +402,22 @@ xfs_finish_flags(
402 return XFS_ERROR(EINVAL); 402 return XFS_ERROR(EINVAL);
403 } 403 }
404 404
405 if (ap->flags & XFSMNT_UQUOTA) {
406 mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
407 if (ap->flags & XFSMNT_UQUOTAENF)
408 mp->m_qflags |= XFS_UQUOTA_ENFD;
409 }
410
411 if (ap->flags & XFSMNT_GQUOTA) {
412 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
413 if (ap->flags & XFSMNT_GQUOTAENF)
414 mp->m_qflags |= XFS_OQUOTA_ENFD;
415 } else if (ap->flags & XFSMNT_PQUOTA) {
416 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
417 if (ap->flags & XFSMNT_PQUOTAENF)
418 mp->m_qflags |= XFS_OQUOTA_ENFD;
419 }
420
405 return 0; 421 return 0;
406} 422}
407 423
@@ -435,12 +451,13 @@ xfs_mount(
435 error = xfs_dmops_get(mp, args); 451 error = xfs_dmops_get(mp, args);
436 if (error) 452 if (error)
437 return error; 453 return error;
454 error = xfs_qmops_get(mp, args);
455 if (error)
456 return error;
438 457
439 /* 458 /*
440 * Setup xfs_mount function vectors from available behaviors 459 * Setup xfs_mount function vectors from available behaviors
441 */ 460 */
442 p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
443 mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
444 p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); 461 p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
445 mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; 462 mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
446 463
@@ -556,6 +573,7 @@ error1:
556 xfs_binval(mp->m_rtdev_targp); 573 xfs_binval(mp->m_rtdev_targp);
557error0: 574error0:
558 xfs_unmountfs_close(mp, credp); 575 xfs_unmountfs_close(mp, credp);
576 xfs_qmops_put(mp);
559 xfs_dmops_put(mp); 577 xfs_dmops_put(mp);
560 return error; 578 return error;
561} 579}
@@ -647,6 +665,7 @@ out:
647 * and free the super block buffer & mount structures. 665 * and free the super block buffer & mount structures.
648 */ 666 */
649 xfs_unmountfs(mp, credp); 667 xfs_unmountfs(mp, credp);
668 xfs_qmops_put(mp);
650 xfs_dmops_put(mp); 669 xfs_dmops_put(mp);
651 kmem_free(mp, sizeof(xfs_mount_t)); 670 kmem_free(mp, sizeof(xfs_mount_t));
652 } 671 }
@@ -887,6 +906,8 @@ xfs_statvfs(
887 xfs_statvfs_fsid(statp, mp); 906 xfs_statvfs_fsid(statp, mp);
888 statp->f_namelen = MAXNAMELEN - 1; 907 statp->f_namelen = MAXNAMELEN - 1;
889 908
909 if (vp)
910 XFS_QM_DQSTATVFS(xfs_vtoi(vp), statp);
890 return 0; 911 return 0;
891} 912}
892 913
@@ -941,6 +962,25 @@ xfs_sync(
941 cred_t *credp) 962 cred_t *credp)
942{ 963{
943 xfs_mount_t *mp = XFS_BHVTOM(bdp); 964 xfs_mount_t *mp = XFS_BHVTOM(bdp);
965 int error;
966
967 /*
968 * Get the Quota Manager to flush the dquots.
969 *
970 * If XFS quota support is not enabled or this filesystem
971 * instance does not use quotas XFS_QM_DQSYNC will always
972 * return zero.
973 */
974 error = XFS_QM_DQSYNC(mp, flags);
975 if (error) {
976 /*
977 * If we got an IO error, we will be shutting down.
978 * So, there's nothing more for us to do here.
979 */
980 ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
981 if (XFS_FORCED_SHUTDOWN(mp))
982 return XFS_ERROR(error);
983 }
944 984
945 if (flags & SYNC_IOWAIT) 985 if (flags & SYNC_IOWAIT)
946 xfs_filestream_flush(mp); 986 xfs_filestream_flush(mp);
@@ -1696,6 +1736,18 @@ xfs_vget(
1696#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */ 1736#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */
1697#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */ 1737#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
1698#define MNTOPT_FILESTREAM "filestreams" /* use filestreams allocator */ 1738#define MNTOPT_FILESTREAM "filestreams" /* use filestreams allocator */
1739#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
1740#define MNTOPT_NOQUOTA "noquota" /* no quotas */
1741#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
1742#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
1743#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
1744#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
1745#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
1746#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
1747#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
1748#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
1749#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
1750#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
1699#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */ 1751#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */
1700#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */ 1752#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
1701#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */ 1753#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */
@@ -1889,6 +1941,29 @@ xfs_parseargs(
1889 args->flags &= ~XFSMNT_ATTR2; 1941 args->flags &= ~XFSMNT_ATTR2;
1890 } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) { 1942 } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
1891 args->flags2 |= XFSMNT2_FILESTREAMS; 1943 args->flags2 |= XFSMNT2_FILESTREAMS;
1944 } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
1945 args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
1946 args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
1947 } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
1948 !strcmp(this_char, MNTOPT_UQUOTA) ||
1949 !strcmp(this_char, MNTOPT_USRQUOTA)) {
1950 args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
1951 } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
1952 !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
1953 args->flags |= XFSMNT_UQUOTA;
1954 args->flags &= ~XFSMNT_UQUOTAENF;
1955 } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
1956 !strcmp(this_char, MNTOPT_PRJQUOTA)) {
1957 args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
1958 } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
1959 args->flags |= XFSMNT_PQUOTA;
1960 args->flags &= ~XFSMNT_PQUOTAENF;
1961 } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
1962 !strcmp(this_char, MNTOPT_GRPQUOTA)) {
1963 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
1964 } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
1965 args->flags |= XFSMNT_GQUOTA;
1966 args->flags &= ~XFSMNT_GQUOTAENF;
1892 } else if (!strcmp(this_char, MNTOPT_DMAPI)) { 1967 } else if (!strcmp(this_char, MNTOPT_DMAPI)) {
1893 args->flags |= XFSMNT_DMAPI; 1968 args->flags |= XFSMNT_DMAPI;
1894 } else if (!strcmp(this_char, MNTOPT_XDSM)) { 1969 } else if (!strcmp(this_char, MNTOPT_XDSM)) {
@@ -1926,6 +2001,12 @@ xfs_parseargs(
1926 return EINVAL; 2001 return EINVAL;
1927 } 2002 }
1928 2003
2004 if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
2005 cmn_err(CE_WARN,
2006 "XFS: cannot mount with both project and group quota");
2007 return EINVAL;
2008 }
2009
1929 if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') { 2010 if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
1930 printk("XFS: %s option needs the mount point option as well\n", 2011 printk("XFS: %s option needs the mount point option as well\n",
1931 MNTOPT_DMAPI); 2012 MNTOPT_DMAPI);
@@ -2025,9 +2106,32 @@ xfs_showargs(
2025 if (vfsp->vfs_flag & VFS_GRPID) 2106 if (vfsp->vfs_flag & VFS_GRPID)
2026 seq_printf(m, "," MNTOPT_GRPID); 2107 seq_printf(m, "," MNTOPT_GRPID);
2027 2108
2109 if (mp->m_qflags & XFS_UQUOTA_ACCT) {
2110 if (mp->m_qflags & XFS_UQUOTA_ENFD)
2111 seq_puts(m, "," MNTOPT_USRQUOTA);
2112 else
2113 seq_puts(m, "," MNTOPT_UQUOTANOENF);
2114 }
2115
2116 if (mp->m_qflags & XFS_PQUOTA_ACCT) {
2117 if (mp->m_qflags & XFS_OQUOTA_ENFD)
2118 seq_puts(m, "," MNTOPT_PRJQUOTA);
2119 else
2120 seq_puts(m, "," MNTOPT_PQUOTANOENF);
2121 }
2122
2123 if (mp->m_qflags & XFS_GQUOTA_ACCT) {
2124 if (mp->m_qflags & XFS_OQUOTA_ENFD)
2125 seq_puts(m, "," MNTOPT_GRPQUOTA);
2126 else
2127 seq_puts(m, "," MNTOPT_GQUOTANOENF);
2128 }
2129
2130 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
2131 seq_puts(m, "," MNTOPT_NOQUOTA);
2132
2028 if (vfsp->vfs_flag & VFS_DMI) 2133 if (vfsp->vfs_flag & VFS_DMI)
2029 seq_puts(m, "," MNTOPT_DMAPI); 2134 seq_puts(m, "," MNTOPT_DMAPI);
2030
2031 return 0; 2135 return 0;
2032} 2136}
2033 2137