aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/quota
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/quota
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/quota')
-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
4 files changed, 39 insertions, 254 deletions
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