diff options
Diffstat (limited to 'fs/dquot.c')
-rw-r--r-- | fs/dquot.c | 77 |
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 | ||
1459 | static inline void reset_enable_flags(struct quota_info *dqopt, int type) | 1461 | static 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 | */ |
1474 | int vfs_quota_off(struct super_block *sb, int type) | 1486 | int 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 */ | ||
1666 | static 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() */ |
1636 | int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) | 1691 | int 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; |