aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dquot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dquot.c')
-rw-r--r--fs/dquot.c77
1 files changed, 68 insertions, 9 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index fc26d1097d3c..dfba1623cccb 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -1449,31 +1449,43 @@ static inline void set_enable_flags(struct quota_info *dqopt, int type)
1449 switch (type) { 1449 switch (type) {
1450 case USRQUOTA: 1450 case USRQUOTA:
1451 dqopt->flags |= DQUOT_USR_ENABLED; 1451 dqopt->flags |= DQUOT_USR_ENABLED;
1452 dqopt->flags &= ~DQUOT_USR_SUSPENDED;
1452 break; 1453 break;
1453 case GRPQUOTA: 1454 case GRPQUOTA:
1454 dqopt->flags |= DQUOT_GRP_ENABLED; 1455 dqopt->flags |= DQUOT_GRP_ENABLED;
1456 dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
1455 break; 1457 break;
1456 } 1458 }
1457} 1459}
1458 1460
1459static inline void reset_enable_flags(struct quota_info *dqopt, int type) 1461static inline void reset_enable_flags(struct quota_info *dqopt, int type,
1462 int remount)
1460{ 1463{
1461 switch (type) { 1464 switch (type) {
1462 case USRQUOTA: 1465 case USRQUOTA:
1463 dqopt->flags &= ~DQUOT_USR_ENABLED; 1466 dqopt->flags &= ~DQUOT_USR_ENABLED;
1467 if (remount)
1468 dqopt->flags |= DQUOT_USR_SUSPENDED;
1469 else
1470 dqopt->flags &= ~DQUOT_USR_SUSPENDED;
1464 break; 1471 break;
1465 case GRPQUOTA: 1472 case GRPQUOTA:
1466 dqopt->flags &= ~DQUOT_GRP_ENABLED; 1473 dqopt->flags &= ~DQUOT_GRP_ENABLED;
1474 if (remount)
1475 dqopt->flags |= DQUOT_GRP_SUSPENDED;
1476 else
1477 dqopt->flags &= ~DQUOT_GRP_SUSPENDED;
1467 break; 1478 break;
1468 } 1479 }
1469} 1480}
1470 1481
1482
1471/* 1483/*
1472 * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) 1484 * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
1473 */ 1485 */
1474int vfs_quota_off(struct super_block *sb, int type) 1486int vfs_quota_off(struct super_block *sb, int type, int remount)
1475{ 1487{
1476 int cnt; 1488 int cnt, ret = 0;
1477 struct quota_info *dqopt = sb_dqopt(sb); 1489 struct quota_info *dqopt = sb_dqopt(sb);
1478 struct inode *toputinode[MAXQUOTAS]; 1490 struct inode *toputinode[MAXQUOTAS];
1479 1491
@@ -1483,9 +1495,17 @@ int vfs_quota_off(struct super_block *sb, int type)
1483 toputinode[cnt] = NULL; 1495 toputinode[cnt] = NULL;
1484 if (type != -1 && cnt != type) 1496 if (type != -1 && cnt != type)
1485 continue; 1497 continue;
1498 /* If we keep inodes of quota files after remount and quotaoff
1499 * is called, drop kept inodes. */
1500 if (!remount && sb_has_quota_suspended(sb, cnt)) {
1501 iput(dqopt->files[cnt]);
1502 dqopt->files[cnt] = NULL;
1503 reset_enable_flags(dqopt, cnt, 0);
1504 continue;
1505 }
1486 if (!sb_has_quota_enabled(sb, cnt)) 1506 if (!sb_has_quota_enabled(sb, cnt))
1487 continue; 1507 continue;
1488 reset_enable_flags(dqopt, cnt); 1508 reset_enable_flags(dqopt, cnt, remount);
1489 1509
1490 /* Note: these are blocking operations */ 1510 /* Note: these are blocking operations */
1491 drop_dquot_ref(sb, cnt); 1511 drop_dquot_ref(sb, cnt);
@@ -1501,7 +1521,8 @@ int vfs_quota_off(struct super_block *sb, int type)
1501 put_quota_format(dqopt->info[cnt].dqi_format); 1521 put_quota_format(dqopt->info[cnt].dqi_format);
1502 1522
1503 toputinode[cnt] = dqopt->files[cnt]; 1523 toputinode[cnt] = dqopt->files[cnt];
1504 dqopt->files[cnt] = NULL; 1524 if (!remount)
1525 dqopt->files[cnt] = NULL;
1505 dqopt->info[cnt].dqi_flags = 0; 1526 dqopt->info[cnt].dqi_flags = 0;
1506 dqopt->info[cnt].dqi_igrace = 0; 1527 dqopt->info[cnt].dqi_igrace = 0;
1507 dqopt->info[cnt].dqi_bgrace = 0; 1528 dqopt->info[cnt].dqi_bgrace = 0;
@@ -1531,12 +1552,19 @@ int vfs_quota_off(struct super_block *sb, int type)
1531 mutex_unlock(&toputinode[cnt]->i_mutex); 1552 mutex_unlock(&toputinode[cnt]->i_mutex);
1532 mark_inode_dirty(toputinode[cnt]); 1553 mark_inode_dirty(toputinode[cnt]);
1533 } 1554 }
1534 iput(toputinode[cnt]);
1535 mutex_unlock(&dqopt->dqonoff_mutex); 1555 mutex_unlock(&dqopt->dqonoff_mutex);
1556 /* On remount RO, we keep the inode pointer so that we
1557 * can reenable quota on the subsequent remount RW.
1558 * But we have better not keep inode pointer when there
1559 * is pending delete on the quota file... */
1560 if (!remount)
1561 iput(toputinode[cnt]);
1562 else if (!toputinode[cnt]->i_nlink)
1563 ret = -EBUSY;
1536 } 1564 }
1537 if (sb->s_bdev) 1565 if (sb->s_bdev)
1538 invalidate_bdev(sb->s_bdev); 1566 invalidate_bdev(sb->s_bdev);
1539 return 0; 1567 return ret;
1540} 1568}
1541 1569
1542/* 1570/*
@@ -1574,7 +1602,8 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
1574 invalidate_bdev(sb->s_bdev); 1602 invalidate_bdev(sb->s_bdev);
1575 mutex_lock(&inode->i_mutex); 1603 mutex_lock(&inode->i_mutex);
1576 mutex_lock(&dqopt->dqonoff_mutex); 1604 mutex_lock(&dqopt->dqonoff_mutex);
1577 if (sb_has_quota_enabled(sb, type)) { 1605 if (sb_has_quota_enabled(sb, type) ||
1606 sb_has_quota_suspended(sb, type)) {
1578 error = -EBUSY; 1607 error = -EBUSY;
1579 goto out_lock; 1608 goto out_lock;
1580 } 1609 }
@@ -1597,6 +1626,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
1597 1626
1598 dqopt->ops[type] = fmt->qf_ops; 1627 dqopt->ops[type] = fmt->qf_ops;
1599 dqopt->info[type].dqi_format = fmt; 1628 dqopt->info[type].dqi_format = fmt;
1629 dqopt->info[type].dqi_fmt_id = format_id;
1600 INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); 1630 INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
1601 mutex_lock(&dqopt->dqio_mutex); 1631 mutex_lock(&dqopt->dqio_mutex);
1602 if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0) { 1632 if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0) {
@@ -1632,12 +1662,41 @@ out_fmt:
1632 return error; 1662 return error;
1633} 1663}
1634 1664
1665/* Reenable quotas on remount RW */
1666static int vfs_quota_on_remount(struct super_block *sb, int type)
1667{
1668 struct quota_info *dqopt = sb_dqopt(sb);
1669 struct inode *inode;
1670 int ret;
1671
1672 mutex_lock(&dqopt->dqonoff_mutex);
1673 if (!sb_has_quota_suspended(sb, type)) {
1674 mutex_unlock(&dqopt->dqonoff_mutex);
1675 return 0;
1676 }
1677 BUG_ON(sb_has_quota_enabled(sb, type));
1678
1679 inode = dqopt->files[type];
1680 dqopt->files[type] = NULL;
1681 reset_enable_flags(dqopt, type, 0);
1682 mutex_unlock(&dqopt->dqonoff_mutex);
1683
1684 ret = vfs_quota_on_inode(inode, type, dqopt->info[type].dqi_fmt_id);
1685 iput(inode);
1686
1687 return ret;
1688}
1689
1635/* Actual function called from quotactl() */ 1690/* Actual function called from quotactl() */
1636int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) 1691int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path,
1692 int remount)
1637{ 1693{
1638 struct nameidata nd; 1694 struct nameidata nd;
1639 int error; 1695 int error;
1640 1696
1697 if (remount)
1698 return vfs_quota_on_remount(sb, type);
1699
1641 error = path_lookup(path, LOOKUP_FOLLOW, &nd); 1700 error = path_lookup(path, LOOKUP_FOLLOW, &nd);
1642 if (error < 0) 1701 if (error < 0)
1643 return error; 1702 return error;