aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2008-04-28 05:14:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:33 -0400
commit0ff5af8340aa6be44220d7237ef4a654314cf795 (patch)
treea9536ea573725931cd4eb3139f4885887e3f8bf8 /fs
parent03f6e92bdd467aed9d7571a571868563ae6ad288 (diff)
quota: quota core changes for quotaon on remount
Currently, we just turn quotas off on remount of filesystem to read-only state. The patch below adds necessary framework so that we can turn quotas off on remount RO but we are able to automatically reenable them again when filesystem is remounted to RW state. All we need to do is to keep references to inodes of quota files when remounting RO and using these references to reenable quotas when remounting RW. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/dquot.c77
-rw-r--r--fs/quota.c5
-rw-r--r--fs/super.c10
3 files changed, 78 insertions, 14 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;
diff --git a/fs/quota.c b/fs/quota.c
index 84f28dd72116..db1cc9f3c7aa 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -69,7 +69,6 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid
69 switch (cmd) { 69 switch (cmd) {
70 case Q_GETFMT: 70 case Q_GETFMT:
71 case Q_GETINFO: 71 case Q_GETINFO:
72 case Q_QUOTAOFF:
73 case Q_SETINFO: 72 case Q_SETINFO:
74 case Q_SETQUOTA: 73 case Q_SETQUOTA:
75 case Q_GETQUOTA: 74 case Q_GETQUOTA:
@@ -229,12 +228,12 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void
229 228
230 if (IS_ERR(pathname = getname(addr))) 229 if (IS_ERR(pathname = getname(addr)))
231 return PTR_ERR(pathname); 230 return PTR_ERR(pathname);
232 ret = sb->s_qcop->quota_on(sb, type, id, pathname); 231 ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0);
233 putname(pathname); 232 putname(pathname);
234 return ret; 233 return ret;
235 } 234 }
236 case Q_QUOTAOFF: 235 case Q_QUOTAOFF:
237 return sb->s_qcop->quota_off(sb, type); 236 return sb->s_qcop->quota_off(sb, type, 0);
238 237
239 case Q_GETFMT: { 238 case Q_GETFMT: {
240 __u32 fmt; 239 __u32 fmt;
diff --git a/fs/super.c b/fs/super.c
index 4798350b2bc9..a5a4aca7e22f 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -179,7 +179,7 @@ void deactivate_super(struct super_block *s)
179 if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { 179 if (atomic_dec_and_lock(&s->s_active, &sb_lock)) {
180 s->s_count -= S_BIAS-1; 180 s->s_count -= S_BIAS-1;
181 spin_unlock(&sb_lock); 181 spin_unlock(&sb_lock);
182 DQUOT_OFF(s); 182 DQUOT_OFF(s, 0);
183 down_write(&s->s_umount); 183 down_write(&s->s_umount);
184 fs->kill_sb(s); 184 fs->kill_sb(s);
185 put_filesystem(fs); 185 put_filesystem(fs);
@@ -608,6 +608,7 @@ retry:
608int do_remount_sb(struct super_block *sb, int flags, void *data, int force) 608int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
609{ 609{
610 int retval; 610 int retval;
611 int remount_rw;
611 612
612#ifdef CONFIG_BLOCK 613#ifdef CONFIG_BLOCK
613 if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) 614 if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev))
@@ -625,8 +626,11 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
625 mark_files_ro(sb); 626 mark_files_ro(sb);
626 else if (!fs_may_remount_ro(sb)) 627 else if (!fs_may_remount_ro(sb))
627 return -EBUSY; 628 return -EBUSY;
628 DQUOT_OFF(sb); 629 retval = DQUOT_OFF(sb, 1);
630 if (retval < 0 && retval != -ENOSYS)
631 return -EBUSY;
629 } 632 }
633 remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY);
630 634
631 if (sb->s_op->remount_fs) { 635 if (sb->s_op->remount_fs) {
632 lock_super(sb); 636 lock_super(sb);
@@ -636,6 +640,8 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
636 return retval; 640 return retval;
637 } 641 }
638 sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); 642 sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK);
643 if (remount_rw)
644 DQUOT_ON_REMOUNT(sb);
639 return 0; 645 return 0;
640} 646}
641 647