]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - sys/ufs/ufs/ufs_quota.c
Copy stable/10@r272459 to releng/10.1 as part of
[FreeBSD/releng/10.1.git] / sys / ufs / ufs / ufs_quota.c
1 /*-
2  * Copyright (c) 1982, 1986, 1990, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Elz at The University of Melbourne.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include "opt_ffs.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/endian.h>
43 #include <sys/fcntl.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
50 #include <sys/priv.h>
51 #include <sys/proc.h>
52 #include <sys/socket.h>
53 #include <sys/stat.h>
54 #include <sys/sysctl.h>
55 #include <sys/vnode.h>
56
57 #include <ufs/ufs/extattr.h>
58 #include <ufs/ufs/quota.h>
59 #include <ufs/ufs/inode.h>
60 #include <ufs/ufs/ufsmount.h>
61 #include <ufs/ufs/ufs_extern.h>
62
63 CTASSERT(sizeof(struct dqblk64) == sizeof(struct dqhdr64));
64
65 static int unprivileged_get_quota = 0;
66 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_get_quota, CTLFLAG_RW,
67     &unprivileged_get_quota, 0,
68     "Unprivileged processes may retrieve quotas for other uids and gids");
69
70 static MALLOC_DEFINE(M_DQUOT, "ufs_quota", "UFS quota entries");
71
72 /*
73  * Quota name to error message mapping.
74  */
75 static char *quotatypes[] = INITQFNAMES;
76
77 static int chkdqchg(struct inode *, ufs2_daddr_t, struct ucred *, int, int *);
78 static int chkiqchg(struct inode *, int, struct ucred *, int, int *);
79 static int dqopen(struct vnode *, struct ufsmount *, int);
80 static int dqget(struct vnode *,
81         u_long, struct ufsmount *, int, struct dquot **);
82 static int dqsync(struct vnode *, struct dquot *);
83 static int dqflush(struct vnode *);
84 static int quotaoff1(struct thread *td, struct mount *mp, int type);
85 static int quotaoff_inchange(struct thread *td, struct mount *mp, int type);
86
87 /* conversion functions - from_to() */
88 static void dqb32_dq(const struct dqblk32 *, struct dquot *);
89 static void dqb64_dq(const struct dqblk64 *, struct dquot *);
90 static void dq_dqb32(const struct dquot *, struct dqblk32 *);
91 static void dq_dqb64(const struct dquot *, struct dqblk64 *);
92 static void dqb32_dqb64(const struct dqblk32 *, struct dqblk64 *);
93 static void dqb64_dqb32(const struct dqblk64 *, struct dqblk32 *);
94
95 #ifdef DIAGNOSTIC
96 static void dqref(struct dquot *);
97 static void chkdquot(struct inode *);
98 #endif
99
100 /*
101  * Set up the quotas for an inode.
102  *
103  * This routine completely defines the semantics of quotas.
104  * If other criterion want to be used to establish quotas, the
105  * MAXQUOTAS value in quota.h should be increased, and the
106  * additional dquots set up here.
107  */
108 int
109 getinoquota(struct inode *ip)
110 {
111         struct ufsmount *ump;
112         struct vnode *vp;
113         int error;
114
115         vp = ITOV(ip);
116
117         /*
118          * Disk quotas must be turned off for system files.  Currently
119          * snapshot and quota files.
120          */
121         if ((vp->v_vflag & VV_SYSTEM) != 0)
122                 return (0);
123         /*
124          * XXX: Turn off quotas for files with a negative UID or GID.
125          * This prevents the creation of 100GB+ quota files.
126          */
127         if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0)
128                 return (0);
129         ump = VFSTOUFS(vp->v_mount);
130         /*
131          * Set up the user quota based on file uid.
132          * EINVAL means that quotas are not enabled.
133          */
134         if ((error =
135                 dqget(vp, ip->i_uid, ump, USRQUOTA, &ip->i_dquot[USRQUOTA])) &&
136             error != EINVAL)
137                 return (error);
138         /*
139          * Set up the group quota based on file gid.
140          * EINVAL means that quotas are not enabled.
141          */
142         if ((error =
143                 dqget(vp, ip->i_gid, ump, GRPQUOTA, &ip->i_dquot[GRPQUOTA])) &&
144             error != EINVAL)
145                 return (error);
146         return (0);
147 }
148
149 /*
150  * Update disk usage, and take corrective action.
151  */
152 int
153 chkdq(struct inode *ip, ufs2_daddr_t change, struct ucred *cred, int flags)
154 {
155         struct dquot *dq;
156         ufs2_daddr_t ncurblocks;
157         struct vnode *vp = ITOV(ip);
158         int i, error, warn, do_check;
159
160         /*
161          * Disk quotas must be turned off for system files.  Currently
162          * snapshot and quota files.
163          */
164         if ((vp->v_vflag & VV_SYSTEM) != 0)
165                 return (0);
166         /*
167          * XXX: Turn off quotas for files with a negative UID or GID.
168          * This prevents the creation of 100GB+ quota files.
169          */
170         if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0)
171                 return (0);
172 #ifdef DIAGNOSTIC
173         if ((flags & CHOWN) == 0)
174                 chkdquot(ip);
175 #endif
176         if (change == 0)
177                 return (0);
178         if (change < 0) {
179                 for (i = 0; i < MAXQUOTAS; i++) {
180                         if ((dq = ip->i_dquot[i]) == NODQUOT)
181                                 continue;
182                         DQI_LOCK(dq);
183                         DQI_WAIT(dq, PINOD+1, "chkdq1");
184                         ncurblocks = dq->dq_curblocks + change;
185                         if (ncurblocks >= 0)
186                                 dq->dq_curblocks = ncurblocks;
187                         else
188                                 dq->dq_curblocks = 0;
189                         dq->dq_flags &= ~DQ_BLKS;
190                         dq->dq_flags |= DQ_MOD;
191                         DQI_UNLOCK(dq);
192                 }
193                 return (0);
194         }
195         if ((flags & FORCE) == 0 &&
196             priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
197                 do_check = 1;
198         else
199                 do_check = 0;
200         for (i = 0; i < MAXQUOTAS; i++) {
201                 if ((dq = ip->i_dquot[i]) == NODQUOT)
202                         continue;
203                 warn = 0;
204                 DQI_LOCK(dq);
205                 DQI_WAIT(dq, PINOD+1, "chkdq2");
206                 if (do_check) {
207                         error = chkdqchg(ip, change, cred, i, &warn);
208                         if (error) {
209                                 /*
210                                  * Roll back user quota changes when
211                                  * group quota failed.
212                                  */
213                                 while (i > 0) {
214                                         --i;
215                                         dq = ip->i_dquot[i];
216                                         if (dq == NODQUOT)
217                                                 continue;
218                                         DQI_LOCK(dq);
219                                         DQI_WAIT(dq, PINOD+1, "chkdq3");
220                                         ncurblocks = dq->dq_curblocks - change;
221                                         if (ncurblocks >= 0)
222                                                 dq->dq_curblocks = ncurblocks;
223                                         else
224                                                 dq->dq_curblocks = 0;
225                                         dq->dq_flags &= ~DQ_BLKS;
226                                         dq->dq_flags |= DQ_MOD;
227                                         DQI_UNLOCK(dq);
228                                 }
229                                 return (error);
230                         }
231                 }
232                 /* Reset timer when crossing soft limit */
233                 if (dq->dq_curblocks + change >= dq->dq_bsoftlimit &&
234                     dq->dq_curblocks < dq->dq_bsoftlimit)
235                         dq->dq_btime = time_second + ip->i_ump->um_btime[i];
236                 dq->dq_curblocks += change;
237                 dq->dq_flags |= DQ_MOD;
238                 DQI_UNLOCK(dq);
239                 if (warn)
240                         uprintf("\n%s: warning, %s disk quota exceeded\n",
241                             ITOV(ip)->v_mount->mnt_stat.f_mntonname,
242                             quotatypes[i]);
243         }
244         return (0);
245 }
246
247 /*
248  * Check for a valid change to a users allocation.
249  * Issue an error message if appropriate.
250  */
251 static int
252 chkdqchg(struct inode *ip, ufs2_daddr_t change, struct ucred *cred,
253     int type, int *warn)
254 {
255         struct dquot *dq = ip->i_dquot[type];
256         ufs2_daddr_t ncurblocks = dq->dq_curblocks + change;
257
258         /*
259          * If user would exceed their hard limit, disallow space allocation.
260          */
261         if (ncurblocks >= dq->dq_bhardlimit && dq->dq_bhardlimit) {
262                 if ((dq->dq_flags & DQ_BLKS) == 0 &&
263                     ip->i_uid == cred->cr_uid) {
264                         dq->dq_flags |= DQ_BLKS;
265                         DQI_UNLOCK(dq);
266                         uprintf("\n%s: write failed, %s disk limit reached\n",
267                             ITOV(ip)->v_mount->mnt_stat.f_mntonname,
268                             quotatypes[type]);
269                         return (EDQUOT);
270                 }
271                 DQI_UNLOCK(dq);
272                 return (EDQUOT);
273         }
274         /*
275          * If user is over their soft limit for too long, disallow space
276          * allocation. Reset time limit as they cross their soft limit.
277          */
278         if (ncurblocks >= dq->dq_bsoftlimit && dq->dq_bsoftlimit) {
279                 if (dq->dq_curblocks < dq->dq_bsoftlimit) {
280                         dq->dq_btime = time_second + ip->i_ump->um_btime[type];
281                         if (ip->i_uid == cred->cr_uid)
282                                 *warn = 1;
283                         return (0);
284                 }
285                 if (time_second > dq->dq_btime) {
286                         if ((dq->dq_flags & DQ_BLKS) == 0 &&
287                             ip->i_uid == cred->cr_uid) {
288                                 dq->dq_flags |= DQ_BLKS;
289                                 DQI_UNLOCK(dq);
290                                 uprintf("\n%s: write failed, %s "
291                                     "disk quota exceeded for too long\n",
292                                     ITOV(ip)->v_mount->mnt_stat.f_mntonname,
293                                     quotatypes[type]);
294                                 return (EDQUOT);
295                         }
296                         DQI_UNLOCK(dq);
297                         return (EDQUOT);
298                 }
299         }
300         return (0);
301 }
302
303 /*
304  * Check the inode limit, applying corrective action.
305  */
306 int
307 chkiq(struct inode *ip, int change, struct ucred *cred, int flags)
308 {
309         struct dquot *dq;
310         int i, error, warn, do_check;
311
312 #ifdef DIAGNOSTIC
313         if ((flags & CHOWN) == 0)
314                 chkdquot(ip);
315 #endif
316         if (change == 0)
317                 return (0);
318         if (change < 0) {
319                 for (i = 0; i < MAXQUOTAS; i++) {
320                         if ((dq = ip->i_dquot[i]) == NODQUOT)
321                                 continue;
322                         DQI_LOCK(dq);
323                         DQI_WAIT(dq, PINOD+1, "chkiq1");
324                         if (dq->dq_curinodes >= -change)
325                                 dq->dq_curinodes += change;
326                         else
327                                 dq->dq_curinodes = 0;
328                         dq->dq_flags &= ~DQ_INODS;
329                         dq->dq_flags |= DQ_MOD;
330                         DQI_UNLOCK(dq);
331                 }
332                 return (0);
333         }
334         if ((flags & FORCE) == 0 &&
335             priv_check_cred(cred, PRIV_VFS_EXCEEDQUOTA, 0))
336                 do_check = 1;
337         else
338                 do_check = 0;
339         for (i = 0; i < MAXQUOTAS; i++) {
340                 if ((dq = ip->i_dquot[i]) == NODQUOT)
341                         continue;
342                 warn = 0;
343                 DQI_LOCK(dq);
344                 DQI_WAIT(dq, PINOD+1, "chkiq2");
345                 if (do_check) {
346                         error = chkiqchg(ip, change, cred, i, &warn);
347                         if (error) {
348                                 /*
349                                  * Roll back user quota changes when
350                                  * group quota failed.
351                                  */
352                                 while (i > 0) {
353                                         --i;
354                                         dq = ip->i_dquot[i];
355                                         if (dq == NODQUOT)
356                                                 continue;
357                                         DQI_LOCK(dq);
358                                         DQI_WAIT(dq, PINOD+1, "chkiq3");
359                                         if (dq->dq_curinodes >= change)
360                                                 dq->dq_curinodes -= change;
361                                         else
362                                                 dq->dq_curinodes = 0;
363                                         dq->dq_flags &= ~DQ_INODS;
364                                         dq->dq_flags |= DQ_MOD;
365                                         DQI_UNLOCK(dq);
366                                 }
367                                 return (error);
368                         }
369                 }
370                 /* Reset timer when crossing soft limit */
371                 if (dq->dq_curinodes + change >= dq->dq_isoftlimit &&
372                     dq->dq_curinodes < dq->dq_isoftlimit)
373                         dq->dq_itime = time_second + ip->i_ump->um_itime[i];
374                 dq->dq_curinodes += change;
375                 dq->dq_flags |= DQ_MOD;
376                 DQI_UNLOCK(dq);
377                 if (warn)
378                         uprintf("\n%s: warning, %s inode quota exceeded\n",
379                             ITOV(ip)->v_mount->mnt_stat.f_mntonname,
380                             quotatypes[i]);
381         }
382         return (0);
383 }
384
385 /*
386  * Check for a valid change to a users allocation.
387  * Issue an error message if appropriate.
388  */
389 static int
390 chkiqchg(struct inode *ip, int change, struct ucred *cred, int type, int *warn)
391 {
392         struct dquot *dq = ip->i_dquot[type];
393         ino_t ncurinodes = dq->dq_curinodes + change;
394
395         /*
396          * If user would exceed their hard limit, disallow inode allocation.
397          */
398         if (ncurinodes >= dq->dq_ihardlimit && dq->dq_ihardlimit) {
399                 if ((dq->dq_flags & DQ_INODS) == 0 &&
400                     ip->i_uid == cred->cr_uid) {
401                         dq->dq_flags |= DQ_INODS;
402                         DQI_UNLOCK(dq);
403                         uprintf("\n%s: write failed, %s inode limit reached\n",
404                             ITOV(ip)->v_mount->mnt_stat.f_mntonname,
405                             quotatypes[type]);
406                         return (EDQUOT);
407                 }
408                 DQI_UNLOCK(dq);
409                 return (EDQUOT);
410         }
411         /*
412          * If user is over their soft limit for too long, disallow inode
413          * allocation. Reset time limit as they cross their soft limit.
414          */
415         if (ncurinodes >= dq->dq_isoftlimit && dq->dq_isoftlimit) {
416                 if (dq->dq_curinodes < dq->dq_isoftlimit) {
417                         dq->dq_itime = time_second + ip->i_ump->um_itime[type];
418                         if (ip->i_uid == cred->cr_uid)
419                                 *warn = 1;
420                         return (0);
421                 }
422                 if (time_second > dq->dq_itime) {
423                         if ((dq->dq_flags & DQ_INODS) == 0 &&
424                             ip->i_uid == cred->cr_uid) {
425                                 dq->dq_flags |= DQ_INODS;
426                                 DQI_UNLOCK(dq);
427                                 uprintf("\n%s: write failed, %s "
428                                     "inode quota exceeded for too long\n",
429                                     ITOV(ip)->v_mount->mnt_stat.f_mntonname,
430                                     quotatypes[type]);
431                                 return (EDQUOT);
432                         }
433                         DQI_UNLOCK(dq);
434                         return (EDQUOT);
435                 }
436         }
437         return (0);
438 }
439
440 #ifdef DIAGNOSTIC
441 /*
442  * On filesystems with quotas enabled, it is an error for a file to change
443  * size and not to have a dquot structure associated with it.
444  */
445 static void
446 chkdquot(struct inode *ip)
447 {
448         struct ufsmount *ump = ip->i_ump;
449         struct vnode *vp = ITOV(ip);
450         int i;
451
452         /*
453          * Disk quotas must be turned off for system files.  Currently
454          * these are snapshots and quota files.
455          */
456         if ((vp->v_vflag & VV_SYSTEM) != 0)
457                 return;
458         /*
459          * XXX: Turn off quotas for files with a negative UID or GID.
460          * This prevents the creation of 100GB+ quota files.
461          */
462         if ((int)ip->i_uid < 0 || (int)ip->i_gid < 0)
463                 return;
464
465         UFS_LOCK(ump);
466         for (i = 0; i < MAXQUOTAS; i++) {
467                 if (ump->um_quotas[i] == NULLVP ||
468                     (ump->um_qflags[i] & (QTF_OPENING|QTF_CLOSING)))
469                         continue;
470                 if (ip->i_dquot[i] == NODQUOT) {
471                         UFS_UNLOCK(ump);
472                         vprint("chkdquot: missing dquot", ITOV(ip));
473                         panic("chkdquot: missing dquot");
474                 }
475         }
476         UFS_UNLOCK(ump);
477 }
478 #endif
479
480 /*
481  * Code to process quotactl commands.
482  */
483
484 /*
485  * Q_QUOTAON - set up a quota file for a particular filesystem.
486  */
487 int
488 quotaon(struct thread *td, struct mount *mp, int type, void *fname)
489 {
490         struct ufsmount *ump;
491         struct vnode *vp, **vpp;
492         struct vnode *mvp;
493         struct dquot *dq;
494         int error, flags;
495         struct nameidata nd;
496
497         error = priv_check(td, PRIV_UFS_QUOTAON);
498         if (error)
499                 return (error);
500
501         if (mp->mnt_flag & MNT_RDONLY)
502                 return (EROFS);
503
504         ump = VFSTOUFS(mp);
505         dq = NODQUOT;
506
507         NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, td);
508         flags = FREAD | FWRITE;
509         vfs_ref(mp);
510         vfs_unbusy(mp);
511         error = vn_open(&nd, &flags, 0, NULL);
512         if (error != 0) {
513                 vfs_rel(mp);
514                 return (error);
515         }
516         NDFREE(&nd, NDF_ONLY_PNBUF);
517         vp = nd.ni_vp;
518         error = vfs_busy(mp, MBF_NOWAIT);
519         vfs_rel(mp);
520         if (error == 0) {
521                 if (vp->v_type != VREG) {
522                         error = EACCES;
523                         vfs_unbusy(mp);
524                 }
525         }
526         if (error != 0) {
527                 VOP_UNLOCK(vp, 0);
528                 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
529                 return (error);
530         }
531
532         UFS_LOCK(ump);
533         if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) {
534                 UFS_UNLOCK(ump);
535                 VOP_UNLOCK(vp, 0);
536                 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
537                 vfs_unbusy(mp);
538                 return (EALREADY);
539         }
540         ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING;
541         UFS_UNLOCK(ump);
542         if ((error = dqopen(vp, ump, type)) != 0) {
543                 VOP_UNLOCK(vp, 0);
544                 UFS_LOCK(ump);
545                 ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING);
546                 UFS_UNLOCK(ump);
547                 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
548                 vfs_unbusy(mp);
549                 return (error);
550         }
551         VOP_UNLOCK(vp, 0);
552         MNT_ILOCK(mp);
553         mp->mnt_flag |= MNT_QUOTA;
554         MNT_IUNLOCK(mp);
555
556         vpp = &ump->um_quotas[type];
557         if (*vpp != vp)
558                 quotaoff1(td, mp, type);
559
560         /*
561          * When the directory vnode containing the quota file is
562          * inactivated, due to the shared lookup of the quota file
563          * vput()ing the dvp, the qsyncvp() call for the containing
564          * directory would try to acquire the quota lock exclusive.
565          * At the same time, lookup already locked the quota vnode
566          * shared.  Mark the quota vnode lock as allowing recursion
567          * and automatically converting shared locks to exclusive.
568          *
569          * Also mark quota vnode as system.
570          */
571         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
572         vp->v_vflag |= VV_SYSTEM;
573         VN_LOCK_AREC(vp);
574         VN_LOCK_DSHARE(vp);
575         VOP_UNLOCK(vp, 0);
576         *vpp = vp;
577         /*
578          * Save the credential of the process that turned on quotas.
579          * Set up the time limits for this quota.
580          */
581         ump->um_cred[type] = crhold(td->td_ucred);
582         ump->um_btime[type] = MAX_DQ_TIME;
583         ump->um_itime[type] = MAX_IQ_TIME;
584         if (dqget(NULLVP, 0, ump, type, &dq) == 0) {
585                 if (dq->dq_btime > 0)
586                         ump->um_btime[type] = dq->dq_btime;
587                 if (dq->dq_itime > 0)
588                         ump->um_itime[type] = dq->dq_itime;
589                 dqrele(NULLVP, dq);
590         }
591         /*
592          * Allow the getdq from getinoquota below to read the quota
593          * from file.
594          */
595         UFS_LOCK(ump);
596         ump->um_qflags[type] &= ~QTF_CLOSING;
597         UFS_UNLOCK(ump);
598         /*
599          * Search vnodes associated with this mount point,
600          * adding references to quota file being opened.
601          * NB: only need to add dquot's for inodes being modified.
602          */
603 again:
604         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
605                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
606                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
607                         goto again;
608                 }
609                 if (vp->v_type == VNON || vp->v_writecount == 0) {
610                         VOP_UNLOCK(vp, 0);
611                         vrele(vp);
612                         continue;
613                 }
614                 error = getinoquota(VTOI(vp));
615                 VOP_UNLOCK(vp, 0);
616                 vrele(vp);
617                 if (error) {
618                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
619                         break;
620                 }
621         }
622
623         if (error)
624                 quotaoff_inchange(td, mp, type);
625         UFS_LOCK(ump);
626         ump->um_qflags[type] &= ~QTF_OPENING;
627         KASSERT((ump->um_qflags[type] & QTF_CLOSING) == 0,
628                 ("quotaon: leaking flags"));
629         UFS_UNLOCK(ump);
630
631         vfs_unbusy(mp);
632         return (error);
633 }
634
635 /*
636  * Main code to turn off disk quotas for a filesystem. Does not change
637  * flags.
638  */
639 static int
640 quotaoff1(struct thread *td, struct mount *mp, int type)
641 {
642         struct vnode *vp;
643         struct vnode *qvp, *mvp;
644         struct ufsmount *ump;
645         struct dquot *dq;
646         struct inode *ip;
647         struct ucred *cr;
648         int error;
649
650         ump = VFSTOUFS(mp);
651
652         UFS_LOCK(ump);
653         KASSERT((ump->um_qflags[type] & QTF_CLOSING) != 0,
654                 ("quotaoff1: flags are invalid"));
655         if ((qvp = ump->um_quotas[type]) == NULLVP) {
656                 UFS_UNLOCK(ump);
657                 return (0);
658         }
659         cr = ump->um_cred[type];
660         UFS_UNLOCK(ump);
661
662         /*
663          * Search vnodes associated with this mount point,
664          * deleting any references to quota file being closed.
665          */
666 again:
667         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
668                 if (vp->v_type == VNON) {
669                         VI_UNLOCK(vp);
670                         continue;
671                 }
672                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
673                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
674                         goto again;
675                 }
676                 ip = VTOI(vp);
677                 dq = ip->i_dquot[type];
678                 ip->i_dquot[type] = NODQUOT;
679                 dqrele(vp, dq);
680                 VOP_UNLOCK(vp, 0);
681                 vrele(vp);
682         }
683
684         error = dqflush(qvp);
685         if (error != 0)
686                 return (error);
687
688         /*
689          * Clear um_quotas before closing the quota vnode to prevent
690          * access to the closed vnode from dqget/dqsync
691          */
692         UFS_LOCK(ump);
693         ump->um_quotas[type] = NULLVP;
694         ump->um_cred[type] = NOCRED;
695         UFS_UNLOCK(ump);
696
697         vn_lock(qvp, LK_EXCLUSIVE | LK_RETRY);
698         qvp->v_vflag &= ~VV_SYSTEM;
699         VOP_UNLOCK(qvp, 0);
700         error = vn_close(qvp, FREAD|FWRITE, td->td_ucred, td);
701         crfree(cr);
702
703         return (error);
704 }
705
706 /*
707  * Turns off quotas, assumes that ump->um_qflags are already checked
708  * and QTF_CLOSING is set to indicate operation in progress. Fixes
709  * ump->um_qflags and mp->mnt_flag after.
710  */
711 int
712 quotaoff_inchange(struct thread *td, struct mount *mp, int type)
713 {
714         struct ufsmount *ump;
715         int i;
716         int error;
717
718         error = quotaoff1(td, mp, type);
719
720         ump = VFSTOUFS(mp);
721         UFS_LOCK(ump);
722         ump->um_qflags[type] &= ~QTF_CLOSING;
723         for (i = 0; i < MAXQUOTAS; i++)
724                 if (ump->um_quotas[i] != NULLVP)
725                         break;
726         if (i == MAXQUOTAS) {
727                 MNT_ILOCK(mp);
728                 mp->mnt_flag &= ~MNT_QUOTA;
729                 MNT_IUNLOCK(mp);
730         }
731         UFS_UNLOCK(ump);
732         return (error);
733 }
734
735 /*
736  * Q_QUOTAOFF - turn off disk quotas for a filesystem.
737  */
738 int
739 quotaoff(struct thread *td, struct mount *mp, int type)
740 {
741         struct ufsmount *ump;
742         int error;
743
744         error = priv_check(td, PRIV_UFS_QUOTAOFF);
745         if (error)
746                 return (error);
747
748         ump = VFSTOUFS(mp);
749         UFS_LOCK(ump);
750         if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) {
751                 UFS_UNLOCK(ump);
752                 return (EALREADY);
753         }
754         ump->um_qflags[type] |= QTF_CLOSING;
755         UFS_UNLOCK(ump);
756
757         return (quotaoff_inchange(td, mp, type));
758 }
759
760 /*
761  * Q_GETQUOTA - return current values in a dqblk structure.
762  */
763 static int
764 _getquota(struct thread *td, struct mount *mp, u_long id, int type,
765     struct dqblk64 *dqb)
766 {
767         struct dquot *dq;
768         int error;
769
770         switch (type) {
771         case USRQUOTA:
772                 if ((td->td_ucred->cr_uid != id) && !unprivileged_get_quota) {
773                         error = priv_check(td, PRIV_VFS_GETQUOTA);
774                         if (error)
775                                 return (error);
776                 }
777                 break;
778
779         case GRPQUOTA:
780                 if (!groupmember(id, td->td_ucred) &&
781                     !unprivileged_get_quota) {
782                         error = priv_check(td, PRIV_VFS_GETQUOTA);
783                         if (error)
784                                 return (error);
785                 }
786                 break;
787
788         default:
789                 return (EINVAL);
790         }
791
792         dq = NODQUOT;
793         error = dqget(NULLVP, id, VFSTOUFS(mp), type, &dq);
794         if (error)
795                 return (error);
796         *dqb = dq->dq_dqb;
797         dqrele(NULLVP, dq);
798         return (error);
799 }
800
801 /*
802  * Q_SETQUOTA - assign an entire dqblk structure.
803  */
804 static int
805 _setquota(struct thread *td, struct mount *mp, u_long id, int type,
806     struct dqblk64 *dqb)
807 {
808         struct dquot *dq;
809         struct dquot *ndq;
810         struct ufsmount *ump;
811         struct dqblk64 newlim;
812         int error;
813
814         error = priv_check(td, PRIV_VFS_SETQUOTA);
815         if (error)
816                 return (error);
817
818         newlim = *dqb;
819
820         ndq = NODQUOT;
821         ump = VFSTOUFS(mp);
822
823         error = dqget(NULLVP, id, ump, type, &ndq);
824         if (error)
825                 return (error);
826         dq = ndq;
827         DQI_LOCK(dq);
828         DQI_WAIT(dq, PINOD+1, "setqta");
829         /*
830          * Copy all but the current values.
831          * Reset time limit if previously had no soft limit or were
832          * under it, but now have a soft limit and are over it.
833          */
834         newlim.dqb_curblocks = dq->dq_curblocks;
835         newlim.dqb_curinodes = dq->dq_curinodes;
836         if (dq->dq_id != 0) {
837                 newlim.dqb_btime = dq->dq_btime;
838                 newlim.dqb_itime = dq->dq_itime;
839         }
840         if (newlim.dqb_bsoftlimit &&
841             dq->dq_curblocks >= newlim.dqb_bsoftlimit &&
842             (dq->dq_bsoftlimit == 0 || dq->dq_curblocks < dq->dq_bsoftlimit))
843                 newlim.dqb_btime = time_second + ump->um_btime[type];
844         if (newlim.dqb_isoftlimit &&
845             dq->dq_curinodes >= newlim.dqb_isoftlimit &&
846             (dq->dq_isoftlimit == 0 || dq->dq_curinodes < dq->dq_isoftlimit))
847                 newlim.dqb_itime = time_second + ump->um_itime[type];
848         dq->dq_dqb = newlim;
849         if (dq->dq_curblocks < dq->dq_bsoftlimit)
850                 dq->dq_flags &= ~DQ_BLKS;
851         if (dq->dq_curinodes < dq->dq_isoftlimit)
852                 dq->dq_flags &= ~DQ_INODS;
853         if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 &&
854             dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0)
855                 dq->dq_flags |= DQ_FAKE;
856         else
857                 dq->dq_flags &= ~DQ_FAKE;
858         dq->dq_flags |= DQ_MOD;
859         DQI_UNLOCK(dq);
860         dqrele(NULLVP, dq);
861         return (0);
862 }
863
864 /*
865  * Q_SETUSE - set current inode and block usage.
866  */
867 static int
868 _setuse(struct thread *td, struct mount *mp, u_long id, int type,
869     struct dqblk64 *dqb)
870 {
871         struct dquot *dq;
872         struct ufsmount *ump;
873         struct dquot *ndq;
874         struct dqblk64 usage;
875         int error;
876
877         error = priv_check(td, PRIV_UFS_SETUSE);
878         if (error)
879                 return (error);
880
881         usage = *dqb;
882
883         ump = VFSTOUFS(mp);
884         ndq = NODQUOT;
885
886         error = dqget(NULLVP, id, ump, type, &ndq);
887         if (error)
888                 return (error);
889         dq = ndq;
890         DQI_LOCK(dq);
891         DQI_WAIT(dq, PINOD+1, "setuse");
892         /*
893          * Reset time limit if have a soft limit and were
894          * previously under it, but are now over it.
895          */
896         if (dq->dq_bsoftlimit && dq->dq_curblocks < dq->dq_bsoftlimit &&
897             usage.dqb_curblocks >= dq->dq_bsoftlimit)
898                 dq->dq_btime = time_second + ump->um_btime[type];
899         if (dq->dq_isoftlimit && dq->dq_curinodes < dq->dq_isoftlimit &&
900             usage.dqb_curinodes >= dq->dq_isoftlimit)
901                 dq->dq_itime = time_second + ump->um_itime[type];
902         dq->dq_curblocks = usage.dqb_curblocks;
903         dq->dq_curinodes = usage.dqb_curinodes;
904         if (dq->dq_curblocks < dq->dq_bsoftlimit)
905                 dq->dq_flags &= ~DQ_BLKS;
906         if (dq->dq_curinodes < dq->dq_isoftlimit)
907                 dq->dq_flags &= ~DQ_INODS;
908         dq->dq_flags |= DQ_MOD;
909         DQI_UNLOCK(dq);
910         dqrele(NULLVP, dq);
911         return (0);
912 }
913
914 int
915 getquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
916 {
917         struct dqblk32 dqb32;
918         struct dqblk64 dqb64;
919         int error;
920
921         error = _getquota(td, mp, id, type, &dqb64);
922         if (error)
923                 return (error);
924         dqb64_dqb32(&dqb64, &dqb32);
925         error = copyout(&dqb32, addr, sizeof(dqb32));
926         return (error);
927 }
928
929 int
930 setquota32(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
931 {
932         struct dqblk32 dqb32;
933         struct dqblk64 dqb64;
934         int error;
935
936         error = copyin(addr, &dqb32, sizeof(dqb32));
937         if (error)
938                 return (error);
939         dqb32_dqb64(&dqb32, &dqb64);
940         error = _setquota(td, mp, id, type, &dqb64);
941         return (error);
942 }
943
944 int
945 setuse32(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
946 {
947         struct dqblk32 dqb32;
948         struct dqblk64 dqb64;
949         int error;
950
951         error = copyin(addr, &dqb32, sizeof(dqb32));
952         if (error)
953                 return (error);
954         dqb32_dqb64(&dqb32, &dqb64);
955         error = _setuse(td, mp, id, type, &dqb64);
956         return (error);
957 }
958
959 int
960 getquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
961 {
962         struct dqblk64 dqb64;
963         int error;
964
965         error = _getquota(td, mp, id, type, &dqb64);
966         if (error)
967                 return (error);
968         error = copyout(&dqb64, addr, sizeof(dqb64));
969         return (error);
970 }
971
972 int
973 setquota(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
974 {
975         struct dqblk64 dqb64;
976         int error;
977
978         error = copyin(addr, &dqb64, sizeof(dqb64));
979         if (error)
980                 return (error);
981         error = _setquota(td, mp, id, type, &dqb64);
982         return (error);
983 }
984
985 int
986 setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr)
987 {
988         struct dqblk64 dqb64;
989         int error;
990
991         error = copyin(addr, &dqb64, sizeof(dqb64));
992         if (error)
993                 return (error);
994         error = _setuse(td, mp, id, type, &dqb64);
995         return (error);
996 }
997
998 /*
999  * Q_GETQUOTASIZE - get bit-size of quota file fields
1000  */
1001 int
1002 getquotasize(struct thread *td, struct mount *mp, u_long id, int type,
1003     void *sizep)
1004 {
1005         struct ufsmount *ump = VFSTOUFS(mp);
1006         int bitsize;
1007
1008         UFS_LOCK(ump);
1009         if (ump->um_quotas[type] == NULLVP ||
1010             (ump->um_qflags[type] & QTF_CLOSING)) {
1011                 UFS_UNLOCK(ump);
1012                 return (EINVAL);
1013         }
1014         if ((ump->um_qflags[type] & QTF_64BIT) != 0)
1015                 bitsize = 64;
1016         else
1017                 bitsize = 32;
1018         UFS_UNLOCK(ump);
1019         return (copyout(&bitsize, sizep, sizeof(int)));
1020 }
1021
1022 /*
1023  * Q_SYNC - sync quota files to disk.
1024  */
1025 int
1026 qsync(struct mount *mp)
1027 {
1028         struct ufsmount *ump = VFSTOUFS(mp);
1029         struct thread *td = curthread;          /* XXX */
1030         struct vnode *vp, *mvp;
1031         struct dquot *dq;
1032         int i, error;
1033
1034         /*
1035          * Check if the mount point has any quotas.
1036          * If not, simply return.
1037          */
1038         UFS_LOCK(ump);
1039         for (i = 0; i < MAXQUOTAS; i++)
1040                 if (ump->um_quotas[i] != NULLVP)
1041                         break;
1042         UFS_UNLOCK(ump);
1043         if (i == MAXQUOTAS)
1044                 return (0);
1045         /*
1046          * Search vnodes associated with this mount point,
1047          * synchronizing any modified dquot structures.
1048          */
1049 again:
1050         MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) {
1051                 if (vp->v_type == VNON) {
1052                         VI_UNLOCK(vp);
1053                         continue;
1054                 }
1055                 error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td);
1056                 if (error) {
1057                         if (error == ENOENT) {
1058                                 MNT_VNODE_FOREACH_ACTIVE_ABORT(mp, mvp);
1059                                 goto again;
1060                         }
1061                         continue;
1062                 }
1063                 for (i = 0; i < MAXQUOTAS; i++) {
1064                         dq = VTOI(vp)->i_dquot[i];
1065                         if (dq != NODQUOT)
1066                                 dqsync(vp, dq);
1067                 }
1068                 vput(vp);
1069         }
1070         return (0);
1071 }
1072
1073 /*
1074  * Sync quota file for given vnode to disk.
1075  */
1076 int
1077 qsyncvp(struct vnode *vp)
1078 {
1079         struct ufsmount *ump = VFSTOUFS(vp->v_mount);
1080         struct dquot *dq;
1081         int i;
1082
1083         /*
1084          * Check if the mount point has any quotas.
1085          * If not, simply return.
1086          */
1087         UFS_LOCK(ump);
1088         for (i = 0; i < MAXQUOTAS; i++)
1089                 if (ump->um_quotas[i] != NULLVP)
1090                         break;
1091         UFS_UNLOCK(ump);
1092         if (i == MAXQUOTAS)
1093                 return (0);
1094         /*
1095          * Search quotas associated with this vnode
1096          * synchronizing any modified dquot structures.
1097          */
1098         for (i = 0; i < MAXQUOTAS; i++) {
1099                 dq = VTOI(vp)->i_dquot[i];
1100                 if (dq != NODQUOT)
1101                         dqsync(vp, dq);
1102         }
1103         return (0);
1104 }
1105
1106 /*
1107  * Code pertaining to management of the in-core dquot data structures.
1108  */
1109 #define DQHASH(dqvp, id) \
1110         (&dqhashtbl[((((intptr_t)(dqvp)) >> 8) + id) & dqhash])
1111 static LIST_HEAD(dqhash, dquot) *dqhashtbl;
1112 static u_long dqhash;
1113
1114 /*
1115  * Dquot free list.
1116  */
1117 #define DQUOTINC        5       /* minimum free dquots desired */
1118 static TAILQ_HEAD(dqfreelist, dquot) dqfreelist;
1119 static long numdquot, desireddquot = DQUOTINC;
1120
1121 /*
1122  * Lock to protect quota hash, dq free list and dq_cnt ref counters of
1123  * _all_ dqs.
1124  */
1125 struct mtx dqhlock;
1126
1127 #define DQH_LOCK()      mtx_lock(&dqhlock)
1128 #define DQH_UNLOCK()    mtx_unlock(&dqhlock)
1129
1130 static struct dquot *dqhashfind(struct dqhash *dqh, u_long id,
1131         struct vnode *dqvp);
1132
1133 /*
1134  * Initialize the quota system.
1135  */
1136 void
1137 dqinit(void)
1138 {
1139
1140         mtx_init(&dqhlock, "dqhlock", NULL, MTX_DEF);
1141         dqhashtbl = hashinit(desiredvnodes, M_DQUOT, &dqhash);
1142         TAILQ_INIT(&dqfreelist);
1143 }
1144
1145 /*
1146  * Shut down the quota system.
1147  */
1148 void
1149 dquninit(void)
1150 {
1151         struct dquot *dq;
1152
1153         hashdestroy(dqhashtbl, M_DQUOT, dqhash);
1154         while ((dq = TAILQ_FIRST(&dqfreelist)) != NULL) {
1155                 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
1156                 mtx_destroy(&dq->dq_lock);
1157                 free(dq, M_DQUOT);
1158         }
1159         mtx_destroy(&dqhlock);
1160 }
1161
1162 static struct dquot *
1163 dqhashfind(struct dqhash *dqh, u_long id, struct vnode *dqvp)
1164 {
1165         struct dquot *dq;
1166
1167         mtx_assert(&dqhlock, MA_OWNED);
1168         LIST_FOREACH(dq, dqh, dq_hash) {
1169                 if (dq->dq_id != id ||
1170                     dq->dq_ump->um_quotas[dq->dq_type] != dqvp)
1171                         continue;
1172                 /*
1173                  * Cache hit with no references.  Take
1174                  * the structure off the free list.
1175                  */
1176                 if (dq->dq_cnt == 0)
1177                         TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
1178                 DQREF(dq);
1179                 return (dq);
1180         }
1181         return (NODQUOT);
1182 }
1183
1184 /*
1185  * Determine the quota file type.
1186  *
1187  * A 32-bit quota file is simply an array of struct dqblk32.
1188  *
1189  * A 64-bit quota file is a struct dqhdr64 followed by an array of struct
1190  * dqblk64.  The header contains various magic bits which allow us to be
1191  * reasonably confident that it is indeeda 64-bit quota file and not just
1192  * a 32-bit quota file that just happens to "look right".
1193  *
1194  */
1195 static int
1196 dqopen(struct vnode *vp, struct ufsmount *ump, int type)
1197 {
1198         struct dqhdr64 dqh;
1199         struct iovec aiov;
1200         struct uio auio;
1201         int error;
1202
1203         ASSERT_VOP_LOCKED(vp, "dqopen");
1204         auio.uio_iov = &aiov;
1205         auio.uio_iovcnt = 1;
1206         aiov.iov_base = &dqh;
1207         aiov.iov_len = sizeof(dqh);
1208         auio.uio_resid = sizeof(dqh);
1209         auio.uio_offset = 0;
1210         auio.uio_segflg = UIO_SYSSPACE;
1211         auio.uio_rw = UIO_READ;
1212         auio.uio_td = (struct thread *)0;
1213         error = VOP_READ(vp, &auio, 0, ump->um_cred[type]);
1214
1215         if (error != 0)
1216                 return (error);
1217         if (auio.uio_resid > 0) {
1218                 /* assume 32 bits */
1219                 return (0);
1220         }
1221
1222         UFS_LOCK(ump);
1223         if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) == 0 &&
1224             be32toh(dqh.dqh_version) == Q_DQHDR64_VERSION &&
1225             be32toh(dqh.dqh_hdrlen) == (uint32_t)sizeof(struct dqhdr64) &&
1226             be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64)) {
1227                 /* XXX: what if the magic matches, but the sizes are wrong? */
1228                 ump->um_qflags[type] |= QTF_64BIT;
1229         } else {
1230                 ump->um_qflags[type] &= ~QTF_64BIT;
1231         }
1232         UFS_UNLOCK(ump);
1233
1234         return (0);
1235 }
1236
1237 /*
1238  * Obtain a dquot structure for the specified identifier and quota file
1239  * reading the information from the file if necessary.
1240  */
1241 static int
1242 dqget(struct vnode *vp, u_long id, struct ufsmount *ump, int type,
1243     struct dquot **dqp)
1244 {
1245         uint8_t buf[sizeof(struct dqblk64)];
1246         off_t base, recsize;
1247         struct dquot *dq, *dq1;
1248         struct dqhash *dqh;
1249         struct vnode *dqvp;
1250         struct iovec aiov;
1251         struct uio auio;
1252         int dqvplocked, error;
1253
1254 #ifdef DEBUG_VFS_LOCKS
1255         if (vp != NULLVP)
1256                 ASSERT_VOP_ELOCKED(vp, "dqget");
1257 #endif
1258
1259         if (vp != NULLVP && *dqp != NODQUOT) {
1260                 return (0);
1261         }
1262
1263         /* XXX: Disallow negative id values to prevent the
1264         * creation of 100GB+ quota data files.
1265         */
1266         if ((int)id < 0)
1267                 return (EINVAL);
1268
1269         UFS_LOCK(ump);
1270         dqvp = ump->um_quotas[type];
1271         if (dqvp == NULLVP || (ump->um_qflags[type] & QTF_CLOSING)) {
1272                 *dqp = NODQUOT;
1273                 UFS_UNLOCK(ump);
1274                 return (EINVAL);
1275         }
1276         vref(dqvp);
1277         UFS_UNLOCK(ump);
1278         error = 0;
1279         dqvplocked = 0;
1280
1281         /*
1282          * Check the cache first.
1283          */
1284         dqh = DQHASH(dqvp, id);
1285         DQH_LOCK();
1286         dq = dqhashfind(dqh, id, dqvp);
1287         if (dq != NULL) {
1288                 DQH_UNLOCK();
1289 hfound:         DQI_LOCK(dq);
1290                 DQI_WAIT(dq, PINOD+1, "dqget");
1291                 DQI_UNLOCK(dq);
1292                 if (dq->dq_ump == NULL) {
1293                         dqrele(vp, dq);
1294                         dq = NODQUOT;
1295                         error = EIO;
1296                 }
1297                 *dqp = dq;
1298                 if (dqvplocked)
1299                         vput(dqvp);
1300                 else
1301                         vrele(dqvp);
1302                 return (error);
1303         }
1304
1305         /*
1306          * Quota vnode lock is before DQ_LOCK. Acquire dqvp lock there
1307          * since new dq will appear on the hash chain DQ_LOCKed.
1308          */
1309         if (vp != dqvp) {
1310                 DQH_UNLOCK();
1311                 vn_lock(dqvp, LK_SHARED | LK_RETRY);
1312                 dqvplocked = 1;
1313                 DQH_LOCK();
1314                 /*
1315                  * Recheck the cache after sleep for quota vnode lock.
1316                  */
1317                 dq = dqhashfind(dqh, id, dqvp);
1318                 if (dq != NULL) {
1319                         DQH_UNLOCK();
1320                         goto hfound;
1321                 }
1322         }
1323
1324         /*
1325          * Not in cache, allocate a new one or take it from the
1326          * free list.
1327          */
1328         if (TAILQ_FIRST(&dqfreelist) == NODQUOT &&
1329             numdquot < MAXQUOTAS * desiredvnodes)
1330                 desireddquot += DQUOTINC;
1331         if (numdquot < desireddquot) {
1332                 numdquot++;
1333                 DQH_UNLOCK();
1334                 dq1 = malloc(sizeof *dq1, M_DQUOT, M_WAITOK | M_ZERO);
1335                 mtx_init(&dq1->dq_lock, "dqlock", NULL, MTX_DEF);
1336                 DQH_LOCK();
1337                 /*
1338                  * Recheck the cache after sleep for memory.
1339                  */
1340                 dq = dqhashfind(dqh, id, dqvp);
1341                 if (dq != NULL) {
1342                         numdquot--;
1343                         DQH_UNLOCK();
1344                         mtx_destroy(&dq1->dq_lock);
1345                         free(dq1, M_DQUOT);
1346                         goto hfound;
1347                 }
1348                 dq = dq1;
1349         } else {
1350                 if ((dq = TAILQ_FIRST(&dqfreelist)) == NULL) {
1351                         DQH_UNLOCK();
1352                         tablefull("dquot");
1353                         *dqp = NODQUOT;
1354                         if (dqvplocked)
1355                                 vput(dqvp);
1356                         else
1357                                 vrele(dqvp);
1358                         return (EUSERS);
1359                 }
1360                 if (dq->dq_cnt || (dq->dq_flags & DQ_MOD))
1361                         panic("dqget: free dquot isn't %p", dq);
1362                 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
1363                 if (dq->dq_ump != NULL)
1364                         LIST_REMOVE(dq, dq_hash);
1365         }
1366
1367         /*
1368          * Dq is put into hash already locked to prevent parallel
1369          * usage while it is being read from file.
1370          */
1371         dq->dq_flags = DQ_LOCK;
1372         dq->dq_id = id;
1373         dq->dq_type = type;
1374         dq->dq_ump = ump;
1375         LIST_INSERT_HEAD(dqh, dq, dq_hash);
1376         DQREF(dq);
1377         DQH_UNLOCK();
1378
1379         /*
1380          * Read the requested quota record from the quota file, performing
1381          * any necessary conversions.
1382          */
1383         if (ump->um_qflags[type] & QTF_64BIT) {
1384                 recsize = sizeof(struct dqblk64);
1385                 base = sizeof(struct dqhdr64);
1386         } else {
1387                 recsize = sizeof(struct dqblk32);
1388                 base = 0;
1389         }
1390         auio.uio_iov = &aiov;
1391         auio.uio_iovcnt = 1;
1392         aiov.iov_base = buf;
1393         aiov.iov_len = recsize;
1394         auio.uio_resid = recsize;
1395         auio.uio_offset = base + id * recsize;
1396         auio.uio_segflg = UIO_SYSSPACE;
1397         auio.uio_rw = UIO_READ;
1398         auio.uio_td = (struct thread *)0;
1399
1400         error = VOP_READ(dqvp, &auio, 0, ump->um_cred[type]);
1401         if (auio.uio_resid == recsize && error == 0) {
1402                 bzero(&dq->dq_dqb, sizeof(dq->dq_dqb));
1403         } else {
1404                 if (ump->um_qflags[type] & QTF_64BIT)
1405                         dqb64_dq((struct dqblk64 *)buf, dq);
1406                 else
1407                         dqb32_dq((struct dqblk32 *)buf, dq);
1408         }
1409         if (dqvplocked)
1410                 vput(dqvp);
1411         else
1412                 vrele(dqvp);
1413         /*
1414          * I/O error in reading quota file, release
1415          * quota structure and reflect problem to caller.
1416          */
1417         if (error) {
1418                 DQH_LOCK();
1419                 dq->dq_ump = NULL;
1420                 LIST_REMOVE(dq, dq_hash);
1421                 DQH_UNLOCK();
1422                 DQI_LOCK(dq);
1423                 if (dq->dq_flags & DQ_WANT)
1424                         wakeup(dq);
1425                 dq->dq_flags = 0;
1426                 DQI_UNLOCK(dq);
1427                 dqrele(vp, dq);
1428                 *dqp = NODQUOT;
1429                 return (error);
1430         }
1431         DQI_LOCK(dq);
1432         /*
1433          * Check for no limit to enforce.
1434          * Initialize time values if necessary.
1435          */
1436         if (dq->dq_isoftlimit == 0 && dq->dq_bsoftlimit == 0 &&
1437             dq->dq_ihardlimit == 0 && dq->dq_bhardlimit == 0)
1438                 dq->dq_flags |= DQ_FAKE;
1439         if (dq->dq_id != 0) {
1440                 if (dq->dq_btime == 0) {
1441                         dq->dq_btime = time_second + ump->um_btime[type];
1442                         if (dq->dq_bsoftlimit &&
1443                             dq->dq_curblocks >= dq->dq_bsoftlimit)
1444                                 dq->dq_flags |= DQ_MOD;
1445                 }
1446                 if (dq->dq_itime == 0) {
1447                         dq->dq_itime = time_second + ump->um_itime[type];
1448                         if (dq->dq_isoftlimit &&
1449                             dq->dq_curinodes >= dq->dq_isoftlimit)
1450                                 dq->dq_flags |= DQ_MOD;
1451                 }
1452         }
1453         DQI_WAKEUP(dq);
1454         DQI_UNLOCK(dq);
1455         *dqp = dq;
1456         return (0);
1457 }
1458
1459 #ifdef DIAGNOSTIC
1460 /*
1461  * Obtain a reference to a dquot.
1462  */
1463 static void
1464 dqref(struct dquot *dq)
1465 {
1466
1467         dq->dq_cnt++;
1468 }
1469 #endif
1470
1471 /*
1472  * Release a reference to a dquot.
1473  */
1474 void
1475 dqrele(struct vnode *vp, struct dquot *dq)
1476 {
1477
1478         if (dq == NODQUOT)
1479                 return;
1480         DQH_LOCK();
1481         KASSERT(dq->dq_cnt > 0, ("Lost dq %p reference 1", dq));
1482         if (dq->dq_cnt > 1) {
1483                 dq->dq_cnt--;
1484                 DQH_UNLOCK();
1485                 return;
1486         }
1487         DQH_UNLOCK();
1488 sync:
1489         (void) dqsync(vp, dq);
1490
1491         DQH_LOCK();
1492         KASSERT(dq->dq_cnt > 0, ("Lost dq %p reference 2", dq));
1493         if (--dq->dq_cnt > 0)
1494         {
1495                 DQH_UNLOCK();
1496                 return;
1497         }
1498
1499         /*
1500          * The dq may become dirty after it is synced but before it is
1501          * put to the free list. Checking the DQ_MOD there without
1502          * locking dq should be safe since no other references to the
1503          * dq exist.
1504          */
1505         if ((dq->dq_flags & DQ_MOD) != 0) {
1506                 dq->dq_cnt++;
1507                 DQH_UNLOCK();
1508                 goto sync;
1509         }
1510         TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist);
1511         DQH_UNLOCK();
1512 }
1513
1514 /*
1515  * Update the disk quota in the quota file.
1516  */
1517 static int
1518 dqsync(struct vnode *vp, struct dquot *dq)
1519 {
1520         uint8_t buf[sizeof(struct dqblk64)];
1521         off_t base, recsize;
1522         struct vnode *dqvp;
1523         struct iovec aiov;
1524         struct uio auio;
1525         int error;
1526         struct mount *mp;
1527         struct ufsmount *ump;
1528
1529 #ifdef DEBUG_VFS_LOCKS
1530         if (vp != NULL)
1531                 ASSERT_VOP_ELOCKED(vp, "dqsync");
1532 #endif
1533
1534         mp = NULL;
1535         error = 0;
1536         if (dq == NODQUOT)
1537                 panic("dqsync: dquot");
1538         if ((ump = dq->dq_ump) == NULL)
1539                 return (0);
1540         UFS_LOCK(ump);
1541         if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP)
1542                 panic("dqsync: file");
1543         vref(dqvp);
1544         UFS_UNLOCK(ump);
1545
1546         DQI_LOCK(dq);
1547         if ((dq->dq_flags & DQ_MOD) == 0) {
1548                 DQI_UNLOCK(dq);
1549                 vrele(dqvp);
1550                 return (0);
1551         }
1552         DQI_UNLOCK(dq);
1553
1554         (void) vn_start_secondary_write(dqvp, &mp, V_WAIT);
1555         if (vp != dqvp)
1556                 vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY);
1557
1558         DQI_LOCK(dq);
1559         DQI_WAIT(dq, PINOD+2, "dqsync");
1560         if ((dq->dq_flags & DQ_MOD) == 0)
1561                 goto out;
1562         dq->dq_flags |= DQ_LOCK;
1563         DQI_UNLOCK(dq);
1564
1565         /*
1566          * Write the quota record to the quota file, performing any
1567          * necessary conversions.  See dqget() for additional details.
1568          */
1569         if (ump->um_qflags[dq->dq_type] & QTF_64BIT) {
1570                 dq_dqb64(dq, (struct dqblk64 *)buf);
1571                 recsize = sizeof(struct dqblk64);
1572                 base = sizeof(struct dqhdr64);
1573         } else {
1574                 dq_dqb32(dq, (struct dqblk32 *)buf);
1575                 recsize = sizeof(struct dqblk32);
1576                 base = 0;
1577         }
1578
1579         auio.uio_iov = &aiov;
1580         auio.uio_iovcnt = 1;
1581         aiov.iov_base = buf;
1582         aiov.iov_len = recsize;
1583         auio.uio_resid = recsize;
1584         auio.uio_offset = base + dq->dq_id * recsize;
1585         auio.uio_segflg = UIO_SYSSPACE;
1586         auio.uio_rw = UIO_WRITE;
1587         auio.uio_td = (struct thread *)0;
1588         error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]);
1589         if (auio.uio_resid && error == 0)
1590                 error = EIO;
1591
1592         DQI_LOCK(dq);
1593         DQI_WAKEUP(dq);
1594         dq->dq_flags &= ~DQ_MOD;
1595 out:
1596         DQI_UNLOCK(dq);
1597         if (vp != dqvp)
1598                 vput(dqvp);
1599         else
1600                 vrele(dqvp);
1601         vn_finished_secondary_write(mp);
1602         return (error);
1603 }
1604
1605 /*
1606  * Flush all entries from the cache for a particular vnode.
1607  */
1608 static int
1609 dqflush(struct vnode *vp)
1610 {
1611         struct dquot *dq, *nextdq;
1612         struct dqhash *dqh;
1613         int error;
1614
1615         /*
1616          * Move all dquot's that used to refer to this quota
1617          * file off their hash chains (they will eventually
1618          * fall off the head of the free list and be re-used).
1619          */
1620         error = 0;
1621         DQH_LOCK();
1622         for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) {
1623                 for (dq = LIST_FIRST(dqh); dq; dq = nextdq) {
1624                         nextdq = LIST_NEXT(dq, dq_hash);
1625                         if (dq->dq_ump->um_quotas[dq->dq_type] != vp)
1626                                 continue;
1627                         if (dq->dq_cnt)
1628                                 error = EBUSY;
1629                         else {
1630                                 LIST_REMOVE(dq, dq_hash);
1631                                 dq->dq_ump = NULL;
1632                         }
1633                 }
1634         }
1635         DQH_UNLOCK();
1636         return (error);
1637 }
1638
1639 /*
1640  * The following three functions are provided for the adjustment of
1641  * quotas by the soft updates code.
1642  */
1643 #ifdef SOFTUPDATES
1644 /*
1645  * Acquire a reference to the quota structures associated with a vnode.
1646  * Return count of number of quota structures found.
1647  */
1648 int
1649 quotaref(vp, qrp)
1650         struct vnode *vp;
1651         struct dquot **qrp;
1652 {
1653         struct inode *ip;
1654         struct dquot *dq;
1655         int i, found;
1656
1657         for (i = 0; i < MAXQUOTAS; i++)
1658                 qrp[i] = NODQUOT;
1659         /*
1660          * Disk quotas must be turned off for system files.  Currently
1661          * snapshot and quota files.
1662          */
1663         if ((vp->v_vflag & VV_SYSTEM) != 0)
1664                 return (0);
1665         /*
1666          * Iterate through and copy active quotas.
1667          */
1668         found = 0;
1669         ip = VTOI(vp);
1670         mtx_lock(&dqhlock);
1671         for (i = 0; i < MAXQUOTAS; i++) {
1672                 if ((dq = ip->i_dquot[i]) == NODQUOT)
1673                         continue;
1674                 DQREF(dq);
1675                 qrp[i] = dq;
1676                 found++;
1677         }
1678         mtx_unlock(&dqhlock);
1679         return (found);
1680 }
1681
1682 /*
1683  * Release a set of quota structures obtained from a vnode.
1684  */
1685 void
1686 quotarele(qrp)
1687         struct dquot **qrp;
1688 {
1689         struct dquot *dq;
1690         int i;
1691
1692         for (i = 0; i < MAXQUOTAS; i++) {
1693                 if ((dq = qrp[i]) == NODQUOT)
1694                         continue;
1695                 dqrele(NULL, dq);
1696         }
1697 }
1698
1699 /*
1700  * Adjust the number of blocks associated with a quota.
1701  * Positive numbers when adding blocks; negative numbers when freeing blocks.
1702  */
1703 void
1704 quotaadj(qrp, ump, blkcount)
1705         struct dquot **qrp;
1706         struct ufsmount *ump;
1707         int64_t blkcount;
1708 {
1709         struct dquot *dq;
1710         ufs2_daddr_t ncurblocks;
1711         int i;
1712
1713         if (blkcount == 0)
1714                 return;
1715         for (i = 0; i < MAXQUOTAS; i++) {
1716                 if ((dq = qrp[i]) == NODQUOT)
1717                         continue;
1718                 DQI_LOCK(dq);
1719                 DQI_WAIT(dq, PINOD+1, "adjqta");
1720                 ncurblocks = dq->dq_curblocks + blkcount;
1721                 if (ncurblocks >= 0)
1722                         dq->dq_curblocks = ncurblocks;
1723                 else
1724                         dq->dq_curblocks = 0;
1725                 if (blkcount < 0)
1726                         dq->dq_flags &= ~DQ_BLKS;
1727                 else if (dq->dq_curblocks + blkcount >= dq->dq_bsoftlimit &&
1728                          dq->dq_curblocks < dq->dq_bsoftlimit)
1729                         dq->dq_btime = time_second + ump->um_btime[i];
1730                 dq->dq_flags |= DQ_MOD;
1731                 DQI_UNLOCK(dq);
1732         }
1733 }
1734 #endif /* SOFTUPDATES */
1735
1736 /*
1737  * 32-bit / 64-bit conversion functions.
1738  *
1739  * 32-bit quota records are stored in native byte order.  Attention must
1740  * be paid to overflow issues.
1741  *
1742  * 64-bit quota records are stored in network byte order.
1743  */
1744
1745 #define CLIP32(u64) (u64 > UINT32_MAX ? UINT32_MAX : (uint32_t)u64)
1746
1747 /*
1748  * Convert 32-bit host-order structure to dquot.
1749  */
1750 static void
1751 dqb32_dq(const struct dqblk32 *dqb32, struct dquot *dq)
1752 {
1753
1754         dq->dq_bhardlimit = dqb32->dqb_bhardlimit;
1755         dq->dq_bsoftlimit = dqb32->dqb_bsoftlimit;
1756         dq->dq_curblocks = dqb32->dqb_curblocks;
1757         dq->dq_ihardlimit = dqb32->dqb_ihardlimit;
1758         dq->dq_isoftlimit = dqb32->dqb_isoftlimit;
1759         dq->dq_curinodes = dqb32->dqb_curinodes;
1760         dq->dq_btime = dqb32->dqb_btime;
1761         dq->dq_itime = dqb32->dqb_itime;
1762 }
1763
1764 /*
1765  * Convert 64-bit network-order structure to dquot.
1766  */
1767 static void
1768 dqb64_dq(const struct dqblk64 *dqb64, struct dquot *dq)
1769 {
1770
1771         dq->dq_bhardlimit = be64toh(dqb64->dqb_bhardlimit);
1772         dq->dq_bsoftlimit = be64toh(dqb64->dqb_bsoftlimit);
1773         dq->dq_curblocks = be64toh(dqb64->dqb_curblocks);
1774         dq->dq_ihardlimit = be64toh(dqb64->dqb_ihardlimit);
1775         dq->dq_isoftlimit = be64toh(dqb64->dqb_isoftlimit);
1776         dq->dq_curinodes = be64toh(dqb64->dqb_curinodes);
1777         dq->dq_btime = be64toh(dqb64->dqb_btime);
1778         dq->dq_itime = be64toh(dqb64->dqb_itime);
1779 }
1780
1781 /*
1782  * Convert dquot to 32-bit host-order structure.
1783  */
1784 static void
1785 dq_dqb32(const struct dquot *dq, struct dqblk32 *dqb32)
1786 {
1787
1788         dqb32->dqb_bhardlimit = CLIP32(dq->dq_bhardlimit);
1789         dqb32->dqb_bsoftlimit = CLIP32(dq->dq_bsoftlimit);
1790         dqb32->dqb_curblocks = CLIP32(dq->dq_curblocks);
1791         dqb32->dqb_ihardlimit = CLIP32(dq->dq_ihardlimit);
1792         dqb32->dqb_isoftlimit = CLIP32(dq->dq_isoftlimit);
1793         dqb32->dqb_curinodes = CLIP32(dq->dq_curinodes);
1794         dqb32->dqb_btime = CLIP32(dq->dq_btime);
1795         dqb32->dqb_itime = CLIP32(dq->dq_itime);
1796 }
1797
1798 /*
1799  * Convert dquot to 64-bit network-order structure.
1800  */
1801 static void
1802 dq_dqb64(const struct dquot *dq, struct dqblk64 *dqb64)
1803 {
1804
1805         dqb64->dqb_bhardlimit = htobe64(dq->dq_bhardlimit);
1806         dqb64->dqb_bsoftlimit = htobe64(dq->dq_bsoftlimit);
1807         dqb64->dqb_curblocks = htobe64(dq->dq_curblocks);
1808         dqb64->dqb_ihardlimit = htobe64(dq->dq_ihardlimit);
1809         dqb64->dqb_isoftlimit = htobe64(dq->dq_isoftlimit);
1810         dqb64->dqb_curinodes = htobe64(dq->dq_curinodes);
1811         dqb64->dqb_btime = htobe64(dq->dq_btime);
1812         dqb64->dqb_itime = htobe64(dq->dq_itime);
1813 }
1814
1815 /*
1816  * Convert 64-bit host-order structure to 32-bit host-order structure.
1817  */
1818 static void
1819 dqb64_dqb32(const struct dqblk64 *dqb64, struct dqblk32 *dqb32)
1820 {
1821
1822         dqb32->dqb_bhardlimit = CLIP32(dqb64->dqb_bhardlimit);
1823         dqb32->dqb_bsoftlimit = CLIP32(dqb64->dqb_bsoftlimit);
1824         dqb32->dqb_curblocks = CLIP32(dqb64->dqb_curblocks);
1825         dqb32->dqb_ihardlimit = CLIP32(dqb64->dqb_ihardlimit);
1826         dqb32->dqb_isoftlimit = CLIP32(dqb64->dqb_isoftlimit);
1827         dqb32->dqb_curinodes = CLIP32(dqb64->dqb_curinodes);
1828         dqb32->dqb_btime = CLIP32(dqb64->dqb_btime);
1829         dqb32->dqb_itime = CLIP32(dqb64->dqb_itime);
1830 }
1831
1832 /*
1833  * Convert 32-bit host-order structure to 64-bit host-order structure.
1834  */
1835 static void
1836 dqb32_dqb64(const struct dqblk32 *dqb32, struct dqblk64 *dqb64)
1837 {
1838
1839         dqb64->dqb_bhardlimit = dqb32->dqb_bhardlimit;
1840         dqb64->dqb_bsoftlimit = dqb32->dqb_bsoftlimit;
1841         dqb64->dqb_curblocks = dqb32->dqb_curblocks;
1842         dqb64->dqb_ihardlimit = dqb32->dqb_ihardlimit;
1843         dqb64->dqb_isoftlimit = dqb32->dqb_isoftlimit;
1844         dqb64->dqb_curinodes = dqb32->dqb_curinodes;
1845         dqb64->dqb_btime = dqb32->dqb_btime;
1846         dqb64->dqb_itime = dqb32->dqb_itime;
1847 }