Deleted Added
sdiff udiff text old ( 234483 ) new ( 241896 )
full compact
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

--- 19 unchanged lines hidden (view full) ---

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: head/sys/ufs/ufs/ufs_quota.c 241896 2012-10-22 17:50:54Z kib $");
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>

--- 447 unchanged lines hidden (view full) ---

492 */
493int
494quotaon(struct thread *td, struct mount *mp, int type, void *fname)
495{
496 struct ufsmount *ump;
497 struct vnode *vp, **vpp;
498 struct vnode *mvp;
499 struct dquot *dq;
500 int error, flags;
501 struct nameidata nd;
502
503 error = priv_check(td, PRIV_UFS_QUOTAON);
504 if (error)
505 return (error);
506
507 if (mp->mnt_flag & MNT_RDONLY)
508 return (EROFS);
509
510 ump = VFSTOUFS(mp);
511 dq = NODQUOT;
512
513 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fname, td);
514 flags = FREAD | FWRITE;
515 vfs_ref(mp);
516 vfs_unbusy(mp);
517 error = vn_open(&nd, &flags, 0, NULL);
518 if (error != 0) {
519 vfs_rel(mp);
520 return (error);
521 }
522 NDFREE(&nd, NDF_ONLY_PNBUF);
523 vp = nd.ni_vp;
524 error = vfs_busy(mp, MBF_NOWAIT);
525 vfs_rel(mp);
526 if (error == 0) {
527 if (vp->v_type != VREG) {
528 error = EACCES;
529 vfs_unbusy(mp);
530 }
531 }
532 if (error != 0) {
533 VOP_UNLOCK(vp, 0);
534 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
535 return (error);
536 }
537
538 UFS_LOCK(ump);
539 if ((ump->um_qflags[type] & (QTF_OPENING|QTF_CLOSING)) != 0) {
540 UFS_UNLOCK(ump);
541 VOP_UNLOCK(vp, 0);
542 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
543 vfs_unbusy(mp);
544 return (EALREADY);
545 }
546 ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING;
547 UFS_UNLOCK(ump);
548 if ((error = dqopen(vp, ump, type)) != 0) {
549 VOP_UNLOCK(vp, 0);
550 UFS_LOCK(ump);
551 ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING);
552 UFS_UNLOCK(ump);
553 (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td);
554 vfs_unbusy(mp);
555 return (error);
556 }
557 VOP_UNLOCK(vp, 0);
558 MNT_ILOCK(mp);
559 mp->mnt_flag |= MNT_QUOTA;
560 MNT_IUNLOCK(mp);
561
562 vpp = &ump->um_quotas[type];
563 if (*vpp != vp)
564 quotaoff1(td, mp, type);
565
566 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
567 vp->v_vflag |= VV_SYSTEM;
568 VOP_UNLOCK(vp, 0);
569 *vpp = vp;
570 /*
571 * Save the credential of the process that turned on quotas.
572 * Set up the time limits for this quota.
573 */
574 ump->um_cred[type] = crhold(td->td_ucred);
575 ump->um_btime[type] = MAX_DQ_TIME;
576 ump->um_itime[type] = MAX_IQ_TIME;
577 if (dqget(NULLVP, 0, ump, type, &dq) == 0) {

--- 55 unchanged lines hidden (view full) ---

633quotaoff1(struct thread *td, struct mount *mp, int type)
634{
635 struct vnode *vp;
636 struct vnode *qvp, *mvp;
637 struct ufsmount *ump;
638 struct dquot *dq;
639 struct inode *ip;
640 struct ucred *cr;
641 int error;
642
643 ump = VFSTOUFS(mp);
644
645 UFS_LOCK(ump);
646 KASSERT((ump->um_qflags[type] & QTF_CLOSING) != 0,
647 ("quotaoff1: flags are invalid"));
648 if ((qvp = ump->um_quotas[type]) == NULLVP) {

--- 29 unchanged lines hidden (view full) ---

678 /* Clear um_quotas before closing the quota vnode to prevent
679 * access to the closed vnode from dqget/dqsync
680 */
681 UFS_LOCK(ump);
682 ump->um_quotas[type] = NULLVP;
683 ump->um_cred[type] = NOCRED;
684 UFS_UNLOCK(ump);
685
686 vn_lock(qvp, LK_EXCLUSIVE | LK_RETRY);
687 qvp->v_vflag &= ~VV_SYSTEM;
688 VOP_UNLOCK(qvp, 0);
689 error = vn_close(qvp, FREAD|FWRITE, td->td_ucred, td);
690 crfree(cr);
691
692 return (error);
693}
694
695/*
696 * Turns off quotas, assumes that ump->um_qflags are already checked
697 * and QTF_CLOSING is set to indicate operation in progress. Fixes

--- 535 unchanged lines hidden (view full) ---

1233{
1234 uint8_t buf[sizeof(struct dqblk64)];
1235 off_t base, recsize;
1236 struct dquot *dq, *dq1;
1237 struct dqhash *dqh;
1238 struct vnode *dqvp;
1239 struct iovec aiov;
1240 struct uio auio;
1241 int dqvplocked, error;
1242
1243#ifdef DEBUG_VFS_LOCKS
1244 if (vp != NULLVP)
1245 ASSERT_VOP_ELOCKED(vp, "dqget");
1246#endif
1247
1248 if (vp != NULLVP && *dqp != NODQUOT) {
1249 return (0);

--- 29 unchanged lines hidden (view full) ---

1279 DQI_WAIT(dq, PINOD+1, "dqget");
1280 DQI_UNLOCK(dq);
1281 if (dq->dq_ump == NULL) {
1282 dqrele(vp, dq);
1283 dq = NODQUOT;
1284 error = EIO;
1285 }
1286 *dqp = dq;
1287 if (dqvplocked)
1288 vput(dqvp);
1289 else
1290 vrele(dqvp);
1291 return (error);
1292 }
1293
1294 /*
1295 * Quota vnode lock is before DQ_LOCK. Acquire dqvp lock there
1296 * since new dq will appear on the hash chain DQ_LOCKed.
1297 */
1298 if (vp != dqvp) {

--- 36 unchanged lines hidden (view full) ---

1335 goto hfound;
1336 }
1337 dq = dq1;
1338 } else {
1339 if ((dq = TAILQ_FIRST(&dqfreelist)) == NULL) {
1340 DQH_UNLOCK();
1341 tablefull("dquot");
1342 *dqp = NODQUOT;
1343 if (dqvplocked)
1344 vput(dqvp);
1345 else
1346 vrele(dqvp);
1347 return (EUSERS);
1348 }
1349 if (dq->dq_cnt || (dq->dq_flags & DQ_MOD))
1350 panic("dqget: free dquot isn't %p", dq);
1351 TAILQ_REMOVE(&dqfreelist, dq, dq_freelist);
1352 if (dq->dq_ump != NULL)
1353 LIST_REMOVE(dq, dq_hash);
1354 }

--- 26 unchanged lines hidden (view full) ---

1381 aiov.iov_base = buf;
1382 aiov.iov_len = recsize;
1383 auio.uio_resid = recsize;
1384 auio.uio_offset = base + id * recsize;
1385 auio.uio_segflg = UIO_SYSSPACE;
1386 auio.uio_rw = UIO_READ;
1387 auio.uio_td = (struct thread *)0;
1388
1389 error = VOP_READ(dqvp, &auio, 0, ump->um_cred[type]);
1390 if (auio.uio_resid == recsize && error == 0) {
1391 bzero(&dq->dq_dqb, sizeof(dq->dq_dqb));
1392 } else {
1393 if (ump->um_qflags[type] & QTF_64BIT)
1394 dqb64_dq((struct dqblk64 *)buf, dq);
1395 else
1396 dqb32_dq((struct dqblk32 *)buf, dq);
1397 }
1398 if (dqvplocked)
1399 vput(dqvp);
1400 else
1401 vrele(dqvp);
1402 /*
1403 * I/O error in reading quota file, release
1404 * quota structure and reflect problem to caller.
1405 */
1406 if (error) {
1407 DQH_LOCK();
1408 dq->dq_ump = NULL;
1409 LIST_REMOVE(dq, dq_hash);

--- 96 unchanged lines hidden (view full) ---

1506static int
1507dqsync(struct vnode *vp, struct dquot *dq)
1508{
1509 uint8_t buf[sizeof(struct dqblk64)];
1510 off_t base, recsize;
1511 struct vnode *dqvp;
1512 struct iovec aiov;
1513 struct uio auio;
1514 int error;
1515 struct mount *mp;
1516 struct ufsmount *ump;
1517
1518#ifdef DEBUG_VFS_LOCKS
1519 if (vp != NULL)
1520 ASSERT_VOP_ELOCKED(vp, "dqsync");
1521#endif
1522

--- 4 unchanged lines hidden (view full) ---

1527 if ((ump = dq->dq_ump) == NULL)
1528 return (0);
1529 UFS_LOCK(ump);
1530 if ((dqvp = ump->um_quotas[dq->dq_type]) == NULLVP)
1531 panic("dqsync: file");
1532 vref(dqvp);
1533 UFS_UNLOCK(ump);
1534
1535 DQI_LOCK(dq);
1536 if ((dq->dq_flags & DQ_MOD) == 0) {
1537 DQI_UNLOCK(dq);
1538 vrele(dqvp);
1539 return (0);
1540 }
1541 DQI_UNLOCK(dq);
1542
1543 (void) vn_start_secondary_write(dqvp, &mp, V_WAIT);
1544 if (vp != dqvp)
1545 vn_lock(dqvp, LK_EXCLUSIVE | LK_RETRY);
1546
1547 DQI_LOCK(dq);
1548 DQI_WAIT(dq, PINOD+2, "dqsync");
1549 if ((dq->dq_flags & DQ_MOD) == 0)
1550 goto out;
1551 dq->dq_flags |= DQ_LOCK;
1552 DQI_UNLOCK(dq);
1553
1554 /*

--- 14 unchanged lines hidden (view full) ---

1569 auio.uio_iovcnt = 1;
1570 aiov.iov_base = buf;
1571 aiov.iov_len = recsize;
1572 auio.uio_resid = recsize;
1573 auio.uio_offset = base + dq->dq_id * recsize;
1574 auio.uio_segflg = UIO_SYSSPACE;
1575 auio.uio_rw = UIO_WRITE;
1576 auio.uio_td = (struct thread *)0;
1577 error = VOP_WRITE(dqvp, &auio, 0, dq->dq_ump->um_cred[dq->dq_type]);
1578 if (auio.uio_resid && error == 0)
1579 error = EIO;
1580
1581 DQI_LOCK(dq);
1582 DQI_WAKEUP(dq);
1583 dq->dq_flags &= ~DQ_MOD;
1584out:
1585 DQI_UNLOCK(dq);
1586 if (vp != dqvp)
1587 vput(dqvp);
1588 else
1589 vrele(dqvp);
1590 vn_finished_secondary_write(mp);
1591 return (error);
1592}
1593
1594/*
1595 * Flush all entries from the cache for a particular vnode.
1596 */
1597static void
1598dqflush(struct vnode *vp)

--- 233 unchanged lines hidden ---