Begin adding quota cursor/iteration interface to VFS_QUOTACTL. Add struct quotakcursor. Add QUOTACTL_CURSOROPEN and QUOTACTL_CURSORCLOSE operations. Implement the plumbing for them. Add trivial implementations of them for quota2. (iteration is not supported on quota1 for the time being, just as getall isn't) Have the proplib interpreter open and close a cursor around doing QUOTACTL_GETALL. Note: this change requires a kernel version bump.diff -r1.20 -r1.21 src/sys/kern/vfs_quotactl.c
(dholland)
--- src/sys/kern/vfs_quotactl.c 2012/01/29 06:55:44 1.20
+++ src/sys/kern/vfs_quotactl.c 2012/01/29 06:57:15 1.21
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: vfs_quotactl.c,v 1.20 2012/01/29 06:55:44 dholland Exp $ */ | 1 | /* $NetBSD: vfs_quotactl.c,v 1.21 2012/01/29 06:57:15 dholland Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1991, 1993, 1994 | 4 | * Copyright (c) 1991, 1993, 1994 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * (c) UNIX System Laboratories, Inc. | 6 | * (c) UNIX System Laboratories, Inc. | |
7 | * All or some portions of this file are derived from material licensed | 7 | * All or some portions of this file are derived from material licensed | |
8 | * to the University of California by American Telephone and Telegraph | 8 | * to the University of California by American Telephone and Telegraph | |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
10 | * the permission of UNIX System Laboratories, Inc. | 10 | * the permission of UNIX System Laboratories, Inc. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -70,27 +70,27 @@ | @@ -70,27 +70,27 @@ | |||
70 | * | 70 | * | |
71 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | 71 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | |
72 | * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp | 72 | * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp | |
73 | */ | 73 | */ | |
74 | 74 | |||
75 | /* | 75 | /* | |
76 | * Note that both of the copyrights above are moderately spurious; | 76 | * Note that both of the copyrights above are moderately spurious; | |
77 | * this code should almost certainly have the Copyright 2010 Manuel | 77 | * this code should almost certainly have the Copyright 2010 Manuel | |
78 | * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c. | 78 | * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c. | |
79 | * However, they're what was on the files this code was sliced out of. | 79 | * However, they're what was on the files this code was sliced out of. | |
80 | */ | 80 | */ | |
81 | 81 | |||
82 | #include <sys/cdefs.h> | 82 | #include <sys/cdefs.h> | |
83 | __KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.20 2012/01/29 06:55:44 dholland Exp $"); | 83 | __KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.21 2012/01/29 06:57:15 dholland Exp $"); | |
84 | 84 | |||
85 | #include <sys/mount.h> | 85 | #include <sys/mount.h> | |
86 | #include <sys/quota.h> | 86 | #include <sys/quota.h> | |
87 | #include <sys/quotactl.h> | 87 | #include <sys/quotactl.h> | |
88 | #include <quota/quotaprop.h> | 88 | #include <quota/quotaprop.h> | |
89 | 89 | |||
90 | static int | 90 | static int | |
91 | vfs_quotactl_getversion(struct mount *mp, | 91 | vfs_quotactl_getversion(struct mount *mp, | |
92 | prop_dictionary_t cmddict, int q2type, | 92 | prop_dictionary_t cmddict, int q2type, | |
93 | prop_array_t datas) | 93 | prop_array_t datas) | |
94 | { | 94 | { | |
95 | prop_array_t replies; | 95 | prop_array_t replies; | |
96 | prop_dictionary_t data; | 96 | prop_dictionary_t data; | |
@@ -432,33 +432,52 @@ vfs_quotactl_put(struct mount *mp, | @@ -432,33 +432,52 @@ vfs_quotactl_put(struct mount *mp, | |||
432 | } | 432 | } | |
433 | return error; | 433 | return error; | |
434 | err: | 434 | err: | |
435 | prop_object_iterator_release(iter); | 435 | prop_object_iterator_release(iter); | |
436 | prop_object_release(replies); | 436 | prop_object_release(replies); | |
437 | return error; | 437 | return error; | |
438 | } | 438 | } | |
439 | 439 | |||
440 | static int | 440 | static int | |
441 | vfs_quotactl_getall(struct mount *mp, | 441 | vfs_quotactl_getall(struct mount *mp, | |
442 | prop_dictionary_t cmddict, int q2type, | 442 | prop_dictionary_t cmddict, int q2type, | |
443 | prop_array_t datas) | 443 | prop_array_t datas) | |
444 | { | 444 | { | |
445 | struct quotakcursor cursor; | |||
445 | struct vfs_quotactl_args args; | 446 | struct vfs_quotactl_args args; | |
447 | int error, error2; | |||
448 | ||||
449 | args.qc_type = QCT_CURSOROPEN; | |||
450 | args.u.cursoropen.qc_cursor = &cursor; | |||
451 | error = VFS_QUOTACTL(mp, QUOTACTL_CURSOROPEN, &args); | |||
452 | if (error) { | |||
453 | return error; | |||
454 | } | |||
446 | 455 | |||
447 | args.qc_type = QCT_PROPLIB; | 456 | args.qc_type = QCT_PROPLIB; | |
448 | args.u.proplib.qc_cmddict = cmddict; | 457 | args.u.proplib.qc_cmddict = cmddict; | |
449 | args.u.proplib.qc_q2type = q2type; | 458 | args.u.proplib.qc_q2type = q2type; | |
450 | args.u.proplib.qc_datas = datas; | 459 | args.u.proplib.qc_datas = datas; | |
451 | return VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args); | 460 | error = VFS_QUOTACTL(mp, QUOTACTL_GETALL, &args); | |
461 | ||||
462 | args.qc_type = QCT_CURSORCLOSE; | |||
463 | args.u.cursorclose.qc_cursor = &cursor; | |||
464 | error2 = VFS_QUOTACTL(mp, QUOTACTL_CURSORCLOSE, &args); | |||
465 | ||||
466 | if (error) { | |||
467 | return error; | |||
468 | } | |||
469 | error = error2; | |||
470 | return error; | |||
452 | } | 471 | } | |
453 | 472 | |||
454 | static int | 473 | static int | |
455 | vfs_quotactl_clear(struct mount *mp, | 474 | vfs_quotactl_clear(struct mount *mp, | |
456 | prop_dictionary_t cmddict, int q2type, | 475 | prop_dictionary_t cmddict, int q2type, | |
457 | prop_array_t datas) | 476 | prop_array_t datas) | |
458 | { | 477 | { | |
459 | prop_array_t replies; | 478 | prop_array_t replies; | |
460 | prop_object_iterator_t iter; | 479 | prop_object_iterator_t iter; | |
461 | prop_dictionary_t data; | 480 | prop_dictionary_t data; | |
462 | uint32_t id; | 481 | uint32_t id; | |
463 | int defaultq; | 482 | int defaultq; | |
464 | const char *idstr; | 483 | const char *idstr; |
--- src/sys/sys/quotactl.h 2012/01/29 06:55:44 1.18
+++ src/sys/sys/quotactl.h 2012/01/29 06:57:15 1.19
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: quotactl.h,v 1.18 2012/01/29 06:55:44 dholland Exp $ */ | 1 | /* $NetBSD: quotactl.h,v 1.19 2012/01/29 06:57:15 dholland Exp $ */ | |
2 | /*- | 2 | /*- | |
3 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 3 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * This code is derived from software contributed to The NetBSD Foundation | 6 | * This code is derived from software contributed to The NetBSD Foundation | |
7 | * by David A. Holland. | 7 | * by David A. Holland. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -27,56 +27,80 @@ | @@ -27,56 +27,80 @@ | |||
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
28 | * POSSIBILITY OF SUCH DAMAGE. | 28 | * POSSIBILITY OF SUCH DAMAGE. | |
29 | */ | 29 | */ | |
30 | 30 | |||
31 | #ifndef _SYS_QUOTACTL_H_ | 31 | #ifndef _SYS_QUOTACTL_H_ | |
32 | #define _SYS_QUOTACTL_H_ | 32 | #define _SYS_QUOTACTL_H_ | |
33 | 33 | |||
34 | /* | 34 | /* | |
35 | * Note - this is an internal interface. Application code (and, | 35 | * Note - this is an internal interface. Application code (and, | |
36 | * really, anything that isn't libquota or inside the kernel) should | 36 | * really, anything that isn't libquota or inside the kernel) should | |
37 | * use the <quota.h> API instead. | 37 | * use the <quota.h> API instead. | |
38 | */ | 38 | */ | |
39 | 39 | |||
40 | /* | |||
41 | * Semi-opaque structure for cursors. This holds the cursor state in | |||
42 | * userland; the size is exposed only to libquota, not to client code, | |||
43 | * and is meant to be large enough to accomodate all likely future | |||
44 | * expansion without being unduly bloated, as it will need to be | |||
45 | * copied in and out for every call using it. | |||
46 | */ | |||
47 | struct quotakcursor { | |||
48 | union { | |||
49 | char qkc_space[64]; | |||
50 | uintmax_t __qkc_forcealign; | |||
51 | } u; | |||
52 | }; | |||
53 | ||||
40 | /* Command codes. */ | 54 | /* Command codes. */ | |
41 | #define QUOTACTL_GETVERSION 0 | 55 | #define QUOTACTL_GETVERSION 0 | |
42 | #define QUOTACTL_QUOTAON 1 | 56 | #define QUOTACTL_QUOTAON 1 | |
43 | #define QUOTACTL_QUOTAOFF 2 | 57 | #define QUOTACTL_QUOTAOFF 2 | |
44 | #define QUOTACTL_GET 3 | 58 | #define QUOTACTL_GET 3 | |
45 | #define QUOTACTL_PUT 4 | 59 | #define QUOTACTL_PUT 4 | |
46 | #define QUOTACTL_GETALL 5 | 60 | #define QUOTACTL_GETALL 5 | |
47 | #define QUOTACTL_DELETE 6 | 61 | #define QUOTACTL_DELETE 6 | |
62 | #define QUOTACTL_CURSOROPEN 7 | |||
63 | #define QUOTACTL_CURSORCLOSE 8 | |||
48 | 64 | |||
49 | /* Argument encoding. */ | 65 | /* Argument encoding. */ | |
50 | enum vfs_quotactl_argtypes { | 66 | enum vfs_quotactl_argtypes { | |
51 | QCT_PROPLIB, /* quotaon/off, getall */ | 67 | QCT_PROPLIB, /* quotaon/off, getall */ | |
52 | QCT_GETVERSION, /* getversion */ | 68 | QCT_GETVERSION, /* getversion */ | |
53 | QCT_GET, /* get */ | 69 | QCT_GET, /* get */ | |
54 | QCT_PUT, /* put */ | 70 | QCT_PUT, /* put */ | |
55 | QCT_DELETE, /* delete */ | 71 | QCT_DELETE, /* delete */ | |
72 | QCT_CURSOROPEN, /* open cursor */ | |||
73 | QCT_CURSORCLOSE,/* close cursor */ | |||
56 | }; | 74 | }; | |
57 | struct vfs_quotactl_args { | 75 | struct vfs_quotactl_args { | |
58 | enum vfs_quotactl_argtypes qc_type; | 76 | enum vfs_quotactl_argtypes qc_type; | |
59 | union { | 77 | union { | |
60 | struct { | 78 | struct { | |
61 | prop_dictionary_t qc_cmddict; | 79 | prop_dictionary_t qc_cmddict; | |
62 | int qc_q2type; | 80 | int qc_q2type; | |
63 | prop_array_t qc_datas; | 81 | prop_array_t qc_datas; | |
64 | } proplib; | 82 | } proplib; | |
65 | struct { | 83 | struct { | |
66 | int *qc_version_ret; | 84 | int *qc_version_ret; | |
67 | } getversion; | 85 | } getversion; | |
68 | struct { | 86 | struct { | |
69 | const struct quotakey *qc_key; | 87 | const struct quotakey *qc_key; | |
70 | struct quotaval *qc_ret; | 88 | struct quotaval *qc_ret; | |
71 | } get; | 89 | } get; | |
72 | struct { | 90 | struct { | |
73 | const struct quotakey *qc_key; | 91 | const struct quotakey *qc_key; | |
74 | const struct quotaval *qc_val; | 92 | const struct quotaval *qc_val; | |
75 | } put; | 93 | } put; | |
76 | struct { | 94 | struct { | |
77 | const struct quotakey *qc_key; | 95 | const struct quotakey *qc_key; | |
78 | } delete; | 96 | } delete; | |
97 | struct { | |||
98 | struct quotakcursor *qc_cursor; | |||
99 | } cursoropen; | |||
100 | struct { | |||
101 | struct quotakcursor *qc_cursor; | |||
102 | } cursorclose; | |||
79 | } u; | 103 | } u; | |
80 | }; | 104 | }; | |
81 | 105 | |||
82 | #endif /* _SYS_QUOTACTL_H_ */ | 106 | #endif /* _SYS_QUOTACTL_H_ */ |
--- src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:55:44 1.92
+++ src/sys/ufs/ufs/ufs_quota.c 2012/01/29 06:57:15 1.93
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ufs_quota.c,v 1.92 2012/01/29 06:55:44 dholland Exp $ */ | 1 | /* $NetBSD: ufs_quota.c,v 1.93 2012/01/29 06:57:15 dholland Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1986, 1990, 1993, 1995 | 4 | * Copyright (c) 1982, 1986, 1990, 1993, 1995 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Robert Elz at The University of Melbourne. | 8 | * Robert Elz at The University of Melbourne. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | 32 | * SUCH DAMAGE. | |
33 | * | 33 | * | |
34 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | 34 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.92 2012/01/29 06:55:44 dholland Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota.c,v 1.93 2012/01/29 06:57:15 dholland Exp $"); | |
39 | 39 | |||
40 | #if defined(_KERNEL_OPT) | 40 | #if defined(_KERNEL_OPT) | |
41 | #include "opt_quota.h" | 41 | #include "opt_quota.h" | |
42 | #endif | 42 | #endif | |
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <sys/kernel.h> | 44 | #include <sys/kernel.h> | |
45 | #include <sys/systm.h> | 45 | #include <sys/systm.h> | |
46 | #include <sys/namei.h> | 46 | #include <sys/namei.h> | |
47 | #include <sys/file.h> | 47 | #include <sys/file.h> | |
48 | #include <sys/proc.h> | 48 | #include <sys/proc.h> | |
49 | #include <sys/vnode.h> | 49 | #include <sys/vnode.h> | |
50 | #include <sys/mount.h> | 50 | #include <sys/mount.h> | |
51 | #include <sys/kauth.h> | 51 | #include <sys/kauth.h> | |
@@ -75,26 +75,30 @@ static int quota_handle_cmd_get_version( | @@ -75,26 +75,30 @@ static int quota_handle_cmd_get_version( | |||
75 | struct vfs_quotactl_args *args); | 75 | struct vfs_quotactl_args *args); | |
76 | static int quota_handle_cmd_get(struct mount *, struct lwp *, | 76 | static int quota_handle_cmd_get(struct mount *, struct lwp *, | |
77 | struct vfs_quotactl_args *args); | 77 | struct vfs_quotactl_args *args); | |
78 | static int quota_handle_cmd_put(struct mount *, struct lwp *, | 78 | static int quota_handle_cmd_put(struct mount *, struct lwp *, | |
79 | struct vfs_quotactl_args *args); | 79 | struct vfs_quotactl_args *args); | |
80 | static int quota_handle_cmd_getall(struct mount *, struct lwp *, | 80 | static int quota_handle_cmd_getall(struct mount *, struct lwp *, | |
81 | struct vfs_quotactl_args *args); | 81 | struct vfs_quotactl_args *args); | |
82 | static int quota_handle_cmd_delete(struct mount *, struct lwp *, | 82 | static int quota_handle_cmd_delete(struct mount *, struct lwp *, | |
83 | struct vfs_quotactl_args *args); | 83 | struct vfs_quotactl_args *args); | |
84 | static int quota_handle_cmd_quotaon(struct mount *, struct lwp *, | 84 | static int quota_handle_cmd_quotaon(struct mount *, struct lwp *, | |
85 | struct vfs_quotactl_args *args); | 85 | struct vfs_quotactl_args *args); | |
86 | static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *, | 86 | static int quota_handle_cmd_quotaoff(struct mount *, struct lwp *, | |
87 | struct vfs_quotactl_args *args); | 87 | struct vfs_quotactl_args *args); | |
88 | static int quota_handle_cmd_cursoropen(struct mount *, struct lwp *, | |||
89 | struct vfs_quotactl_args *args); | |||
90 | static int quota_handle_cmd_cursorclose(struct mount *, struct lwp *, | |||
91 | struct vfs_quotactl_args *args); | |||
88 | 92 | |||
89 | /* | 93 | /* | |
90 | * Initialize the quota fields of an inode. | 94 | * Initialize the quota fields of an inode. | |
91 | */ | 95 | */ | |
92 | void | 96 | void | |
93 | ufsquota_init(struct inode *ip) | 97 | ufsquota_init(struct inode *ip) | |
94 | { | 98 | { | |
95 | int i; | 99 | int i; | |
96 | 100 | |||
97 | for (i = 0; i < MAXQUOTAS; i++) | 101 | for (i = 0; i < MAXQUOTAS; i++) | |
98 | ip->i_dquot[i] = NODQUOT; | 102 | ip->i_dquot[i] = NODQUOT; | |
99 | } | 103 | } | |
100 | 104 | |||
@@ -171,26 +175,32 @@ quota_handle_cmd(struct mount *mp, struc | @@ -171,26 +175,32 @@ quota_handle_cmd(struct mount *mp, struc | |||
171 | break; | 175 | break; | |
172 | case QUOTACTL_GET: | 176 | case QUOTACTL_GET: | |
173 | error = quota_handle_cmd_get(mp, l, args); | 177 | error = quota_handle_cmd_get(mp, l, args); | |
174 | break; | 178 | break; | |
175 | case QUOTACTL_PUT: | 179 | case QUOTACTL_PUT: | |
176 | error = quota_handle_cmd_put(mp, l, args); | 180 | error = quota_handle_cmd_put(mp, l, args); | |
177 | break; | 181 | break; | |
178 | case QUOTACTL_GETALL: | 182 | case QUOTACTL_GETALL: | |
179 | error = quota_handle_cmd_getall(mp, l, args); | 183 | error = quota_handle_cmd_getall(mp, l, args); | |
180 | break; | 184 | break; | |
181 | case QUOTACTL_DELETE: | 185 | case QUOTACTL_DELETE: | |
182 | error = quota_handle_cmd_delete(mp, l, args); | 186 | error = quota_handle_cmd_delete(mp, l, args); | |
183 | break; | 187 | break; | |
188 | case QUOTACTL_CURSOROPEN: | |||
189 | error = quota_handle_cmd_cursoropen(mp, l, args); | |||
190 | break; | |||
191 | case QUOTACTL_CURSORCLOSE: | |||
192 | error = quota_handle_cmd_cursorclose(mp, l, args); | |||
193 | break; | |||
184 | default: | 194 | default: | |
185 | panic("Invalid quotactl operation %d\n", op); | 195 | panic("Invalid quotactl operation %d\n", op); | |
186 | } | 196 | } | |
187 | 197 | |||
188 | return error; | 198 | return error; | |
189 | } | 199 | } | |
190 | 200 | |||
191 | static int | 201 | static int | |
192 | quota_handle_cmd_get_version(struct mount *mp, struct lwp *l, | 202 | quota_handle_cmd_get_version(struct mount *mp, struct lwp *l, | |
193 | struct vfs_quotactl_args *args) | 203 | struct vfs_quotactl_args *args) | |
194 | { | 204 | { | |
195 | struct ufsmount *ump = VFSTOUFS(mp); | 205 | struct ufsmount *ump = VFSTOUFS(mp); | |
196 | int *version_ret; | 206 | int *version_ret; | |
@@ -390,26 +400,78 @@ quota_handle_cmd_getall(struct mount *mp | @@ -390,26 +400,78 @@ quota_handle_cmd_getall(struct mount *mp | |||
390 | error = quota2_handle_cmd_getall(ump, q2type, replies); | 400 | error = quota2_handle_cmd_getall(ump, q2type, replies); | |
391 | } else | 401 | } else | |
392 | #endif | 402 | #endif | |
393 | panic("quota_handle_cmd_getall: no support ?"); | 403 | panic("quota_handle_cmd_getall: no support ?"); | |
394 | if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { | 404 | if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { | |
395 | error = ENOMEM; | 405 | error = ENOMEM; | |
396 | } else { | 406 | } else { | |
397 | error = 0; | 407 | error = 0; | |
398 | } | 408 | } | |
399 | return error; | 409 | return error; | |
400 | } | 410 | } | |
401 | 411 | |||
402 | static int | 412 | static int | |
413 | quota_handle_cmd_cursoropen(struct mount *mp, struct lwp *l, | |||
414 | struct vfs_quotactl_args *args) | |||
415 | { | |||
416 | struct ufsmount *ump = VFSTOUFS(mp); | |||
417 | struct quotakcursor *cursor; | |||
418 | int error; | |||
419 | ||||
420 | KASSERT(args->qc_type == QCT_CURSOROPEN); | |||
421 | cursor = args->u.cursoropen.qc_cursor; | |||
422 | ||||
423 | error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, | |||
424 | KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); | |||
425 | if (error) | |||
426 | return error; | |||
427 | ||||
428 | #ifdef QUOTA2 | |||
429 | if (ump->um_flags & UFS_QUOTA2) { | |||
430 | error = quota2_handle_cmd_cursoropen(ump, cursor); | |||
431 | } else | |||
432 | #endif | |||
433 | error = EOPNOTSUPP; | |||
434 | ||||
435 | return error; | |||
436 | } | |||
437 | ||||
438 | static int | |||
439 | quota_handle_cmd_cursorclose(struct mount *mp, struct lwp *l, | |||
440 | struct vfs_quotactl_args *args) | |||
441 | { | |||
442 | struct ufsmount *ump = VFSTOUFS(mp); | |||
443 | struct quotakcursor *cursor; | |||
444 | int error; | |||
445 | ||||
446 | KASSERT(args->qc_type == QCT_CURSORCLOSE); | |||
447 | cursor = args->u.cursorclose.qc_cursor; | |||
448 | ||||
449 | error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA, | |||
450 | KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, NULL, NULL); | |||
451 | if (error) | |||
452 | return error; | |||
453 | ||||
454 | #ifdef QUOTA2 | |||
455 | if (ump->um_flags & UFS_QUOTA2) { | |||
456 | error = quota2_handle_cmd_cursorclose(ump, cursor); | |||
457 | } else | |||
458 | #endif | |||
459 | error = EOPNOTSUPP; | |||
460 | ||||
461 | return error; | |||
462 | } | |||
463 | ||||
464 | static int | |||
403 | quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l, | 465 | quota_handle_cmd_quotaon(struct mount *mp, struct lwp *l, | |
404 | struct vfs_quotactl_args *args) | 466 | struct vfs_quotactl_args *args) | |
405 | { | 467 | { | |
406 | prop_dictionary_t data; | 468 | prop_dictionary_t data; | |
407 | struct ufsmount *ump = VFSTOUFS(mp); | 469 | struct ufsmount *ump = VFSTOUFS(mp); | |
408 | int error; | 470 | int error; | |
409 | const char *qfile; | 471 | const char *qfile; | |
410 | prop_dictionary_t cmddict; | 472 | prop_dictionary_t cmddict; | |
411 | int q2type; | 473 | int q2type; | |
412 | prop_array_t datas; | 474 | prop_array_t datas; | |
413 | 475 | |||
414 | KASSERT(args->qc_type == QCT_PROPLIB); | 476 | KASSERT(args->qc_type == QCT_PROPLIB); | |
415 | cmddict = args->u.proplib.qc_cmddict; | 477 | cmddict = args->u.proplib.qc_cmddict; |
--- src/sys/ufs/ufs/ufs_quota.h 2012/01/29 06:55:44 1.14
+++ src/sys/ufs/ufs/ufs_quota.h 2012/01/29 06:57:15 1.15
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ufs_quota.h,v 1.14 2012/01/29 06:55:44 dholland Exp $ */ | 1 | /* $NetBSD: ufs_quota.h,v 1.15 2012/01/29 06:57:15 dholland Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1982, 1986, 1990, 1993, 1995 | 4 | * Copyright (c) 1982, 1986, 1990, 1993, 1995 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Robert Elz at The University of Melbourne. | 8 | * Robert Elz at The University of Melbourne. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -26,26 +26,29 @@ | @@ -26,26 +26,29 @@ | |||
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | 32 | * SUCH DAMAGE. | |
33 | * | 33 | * | |
34 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | 34 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | |
35 | */ | 35 | */ | |
36 | #include <ufs/ufs/quota1.h> | 36 | #include <ufs/ufs/quota1.h> | |
37 | #include <ufs/ufs/quota2.h> | 37 | #include <ufs/ufs/quota2.h> | |
38 | 38 | |||
39 | struct quotakcursor; /* from <sys/quotactl.h> */ | |||
40 | ||||
41 | ||||
39 | /* link to this quota in the quota inode (for QUOTA2) */ | 42 | /* link to this quota in the quota inode (for QUOTA2) */ | |
40 | struct dq2_desc { | 43 | struct dq2_desc { | |
41 | uint64_t dq2_lblkno; /* logical disk block holding this quota */ | 44 | uint64_t dq2_lblkno; /* logical disk block holding this quota */ | |
42 | u_int dq2_blkoff; /* offset in disk block holding this quota */ | 45 | u_int dq2_blkoff; /* offset in disk block holding this quota */ | |
43 | }; | 46 | }; | |
44 | 47 | |||
45 | /* | 48 | /* | |
46 | * The following structure records disk usage for a user or group on a | 49 | * The following structure records disk usage for a user or group on a | |
47 | * filesystem. There is one allocated for each quota that exists on any | 50 | * filesystem. There is one allocated for each quota that exists on any | |
48 | * filesystem for the current user or group. A cache is kept of recently | 51 | * filesystem for the current user or group. A cache is kept of recently | |
49 | * used entries. | 52 | * used entries. | |
50 | * Field markings and the corresponding locks: | 53 | * Field markings and the corresponding locks: | |
51 | * h: dqlock | 54 | * h: dqlock | |
@@ -119,16 +122,18 @@ int quota1_handle_cmd_put(struct ufsmoun | @@ -119,16 +122,18 @@ int quota1_handle_cmd_put(struct ufsmoun | |||
119 | const struct quotaval *); | 122 | const struct quotaval *); | |
120 | int quota1_handle_cmd_quotaon(struct lwp *, struct ufsmount *, int, | 123 | int quota1_handle_cmd_quotaon(struct lwp *, struct ufsmount *, int, | |
121 | const char *); | 124 | const char *); | |
122 | int quota1_handle_cmd_quotaoff(struct lwp *, struct ufsmount *, int); | 125 | int quota1_handle_cmd_quotaoff(struct lwp *, struct ufsmount *, int); | |
123 | 126 | |||
124 | int chkdq2(struct inode *, int64_t, kauth_cred_t, int); | 127 | int chkdq2(struct inode *, int64_t, kauth_cred_t, int); | |
125 | int chkiq2(struct inode *, int32_t, kauth_cred_t, int); | 128 | int chkiq2(struct inode *, int32_t, kauth_cred_t, int); | |
126 | int quota2_handle_cmd_get(struct ufsmount *, const struct quotakey *, | 129 | int quota2_handle_cmd_get(struct ufsmount *, const struct quotakey *, | |
127 | struct quotaval *); | 130 | struct quotaval *); | |
128 | int quota2_handle_cmd_put(struct ufsmount *, const struct quotakey *, | 131 | int quota2_handle_cmd_put(struct ufsmount *, const struct quotakey *, | |
129 | const struct quotaval *); | 132 | const struct quotaval *); | |
130 | int quota2_handle_cmd_delete(struct ufsmount *, const struct quotakey *); | 133 | int quota2_handle_cmd_delete(struct ufsmount *, const struct quotakey *); | |
131 | int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t); | 134 | int quota2_handle_cmd_getall(struct ufsmount *, int, prop_array_t); | |
135 | int quota2_handle_cmd_cursoropen(struct ufsmount *, struct quotakcursor *); | |||
136 | int quota2_handle_cmd_cursorclose(struct ufsmount *, struct quotakcursor *); | |||
132 | int q2sync(struct mount *); | 137 | int q2sync(struct mount *); | |
133 | int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); | 138 | int dq2get(struct vnode *, u_long, struct ufsmount *, int, struct dquot *); | |
134 | int dq2sync(struct vnode *, struct dquot *); | 139 | int dq2sync(struct vnode *, struct dquot *); |
--- src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 06:55:44 1.15
+++ src/sys/ufs/ufs/ufs_quota2.c 2012/01/29 06:57:15 1.16
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: ufs_quota2.c,v 1.15 2012/01/29 06:55:44 dholland Exp $ */ | 1 | /* $NetBSD: ufs_quota2.c,v 1.16 2012/01/29 06:57:15 dholland Exp $ */ | |
2 | /*- | 2 | /*- | |
3 | * Copyright (c) 2010 Manuel Bouyer | 3 | * Copyright (c) 2010 Manuel Bouyer | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * | 14 | * | |
@@ -16,42 +16,43 @@ | @@ -16,42 +16,43 @@ | |||
16 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 16 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
17 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 17 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
18 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 18 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
19 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
25 | * POSSIBILITY OF SUCH DAMAGE. | 25 | * POSSIBILITY OF SUCH DAMAGE. | |
26 | */ | 26 | */ | |
27 | 27 | |||
28 | #include <sys/cdefs.h> | 28 | #include <sys/cdefs.h> | |
29 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.15 2012/01/29 06:55:44 dholland Exp $"); | 29 | __KERNEL_RCSID(0, "$NetBSD: ufs_quota2.c,v 1.16 2012/01/29 06:57:15 dholland Exp $"); | |
30 | 30 | |||
31 | #include <sys/buf.h> | 31 | #include <sys/buf.h> | |
32 | #include <sys/param.h> | 32 | #include <sys/param.h> | |
33 | #include <sys/kernel.h> | 33 | #include <sys/kernel.h> | |
34 | #include <sys/systm.h> | 34 | #include <sys/systm.h> | |
35 | #include <sys/malloc.h> | 35 | #include <sys/malloc.h> | |
36 | #include <sys/namei.h> | 36 | #include <sys/namei.h> | |
37 | #include <sys/file.h> | 37 | #include <sys/file.h> | |
38 | #include <sys/proc.h> | 38 | #include <sys/proc.h> | |
39 | #include <sys/vnode.h> | 39 | #include <sys/vnode.h> | |
40 | #include <sys/mount.h> | 40 | #include <sys/mount.h> | |
41 | #include <sys/fstrans.h> | 41 | #include <sys/fstrans.h> | |
42 | #include <sys/kauth.h> | 42 | #include <sys/kauth.h> | |
43 | #include <sys/wapbl.h> | 43 | #include <sys/wapbl.h> | |
44 | #include <sys/quota.h> | 44 | #include <sys/quota.h> | |
45 | #include <sys/quotactl.h> | |||
45 | 46 | |||
46 | #include <ufs/ufs/quota2.h> | 47 | #include <ufs/ufs/quota2.h> | |
47 | #include <ufs/ufs/inode.h> | 48 | #include <ufs/ufs/inode.h> | |
48 | #include <ufs/ufs/ufsmount.h> | 49 | #include <ufs/ufs/ufsmount.h> | |
49 | #include <ufs/ufs/ufs_bswap.h> | 50 | #include <ufs/ufs/ufs_bswap.h> | |
50 | #include <ufs/ufs/ufs_extern.h> | 51 | #include <ufs/ufs/ufs_extern.h> | |
51 | #include <ufs/ufs/ufs_quota.h> | 52 | #include <ufs/ufs/ufs_quota.h> | |
52 | #include <ufs/ufs/ufs_wapbl.h> | 53 | #include <ufs/ufs/ufs_wapbl.h> | |
53 | #include <quota/quotaprop.h> | 54 | #include <quota/quotaprop.h> | |
54 | 55 | |||
55 | /* | 56 | /* | |
56 | * LOCKING: | 57 | * LOCKING: | |
57 | * Data in the entries are protected by the associated struct dquot's | 58 | * Data in the entries are protected by the associated struct dquot's | |
@@ -1028,26 +1029,59 @@ error_bp: | @@ -1028,26 +1029,59 @@ error_bp: | |||
1028 | brelse(hbp, 0); | 1029 | brelse(hbp, 0); | |
1029 | if (error) | 1030 | if (error) | |
1030 | return error; | 1031 | return error; | |
1031 | for (j = 0; j < gu.nuids; j++) { | 1032 | for (j = 0; j < gu.nuids; j++) { | |
1032 | error = quota2_array_add_q2e(ump, type, | 1033 | error = quota2_array_add_q2e(ump, type, | |
1033 | gu.uids[j], replies); | 1034 | gu.uids[j], replies); | |
1034 | if (error && error != ENOENT) | 1035 | if (error && error != ENOENT) | |
1035 | break; | 1036 | break; | |
1036 | } | 1037 | } | |
1037 | free(gu.uids, M_TEMP); | 1038 | free(gu.uids, M_TEMP); | |
1038 | return error; | 1039 | return error; | |
1039 | } | 1040 | } | |
1040 | 1041 | |||
1042 | struct ufsq2_cursor { | |||
1043 | uint32_t q2c_magic; | |||
1044 | }; | |||
1045 | ||||
1046 | #define Q2C_MAGIC (0xbeebe111) | |||
1047 | ||||
1048 | #define Q2CURSOR(qkc) ((struct ufsq2_cursor *)&qkc->u.qkc_space[0]) | |||
1049 | ||||
1050 | int | |||
1051 | quota2_handle_cmd_cursoropen(struct ufsmount *ump, struct quotakcursor *qkc) | |||
1052 | { | |||
1053 | struct ufsq2_cursor *cursor; | |||
1054 | ||||
1055 | CTASSERT(sizeof(*cursor) <= sizeof(qkc->u.qkc_space)); | |||
1056 | cursor = Q2CURSOR(qkc); | |||
1057 | ||||
1058 | cursor->q2c_magic = Q2C_MAGIC; | |||
1059 | return 0; | |||
1060 | } | |||
1061 | ||||
1062 | int | |||
1063 | quota2_handle_cmd_cursorclose(struct ufsmount *ump, struct quotakcursor *qkc) | |||
1064 | { | |||
1065 | struct ufsq2_cursor *cursor; | |||
1066 | ||||
1067 | cursor = Q2CURSOR(qkc); | |||
1068 | if (cursor->q2c_magic != Q2C_MAGIC) { | |||
1069 | return EINVAL; | |||
1070 | } | |||
1071 | ||||
1072 | return 0; | |||
1073 | } | |||
1074 | ||||
1041 | int | 1075 | int | |
1042 | q2sync(struct mount *mp) | 1076 | q2sync(struct mount *mp) | |
1043 | { | 1077 | { | |
1044 | return 0; | 1078 | return 0; | |
1045 | } | 1079 | } | |
1046 | 1080 | |||
1047 | struct dq2get_callback { | 1081 | struct dq2get_callback { | |
1048 | uid_t id; | 1082 | uid_t id; | |
1049 | struct dquot *dq; | 1083 | struct dquot *dq; | |
1050 | }; | 1084 | }; | |
1051 | 1085 | |||
1052 | static int | 1086 | static int | |
1053 | dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e, | 1087 | dq2get_callback(struct ufsmount *ump, uint64_t *offp, struct quota2_entry *q2e, |