summaryrefslogtreecommitdiff
path: root/fs/reiserfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/reiserfs/super.c')
-rw-r--r--fs/reiserfs/super.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 393cc22c1717..ed424d708e69 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -304,7 +304,7 @@ static int finish_unfinished(struct super_block *s)
/* Turn quotas off */
for (i = 0; i < MAXQUOTAS; i++) {
if (sb_dqopt(s)->files[i])
- vfs_quota_off_mount(s, i);
+ vfs_quota_off(s, i, 0);
}
if (ms_active_set)
/* Restore the flag back */
@@ -634,7 +634,7 @@ static int reiserfs_acquire_dquot(struct dquot *);
static int reiserfs_release_dquot(struct dquot *);
static int reiserfs_mark_dquot_dirty(struct dquot *);
static int reiserfs_write_info(struct super_block *, int);
-static int reiserfs_quota_on(struct super_block *, int, int, char *);
+static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
static struct dquot_operations reiserfs_quota_operations = {
.initialize = reiserfs_dquot_initialize,
@@ -1890,8 +1890,14 @@ static int reiserfs_dquot_drop(struct inode *inode)
ret =
journal_begin(&th, inode->i_sb,
2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
- if (ret)
+ if (ret) {
+ /*
+ * We call dquot_drop() anyway to at least release references
+ * to quota structures so that umount does not hang.
+ */
+ dquot_drop(inode);
goto out;
+ }
ret = dquot_drop(inode);
err =
journal_end(&th, inode->i_sb,
@@ -2015,13 +2021,17 @@ static int reiserfs_quota_on_mount(struct super_block *sb, int type)
* Standard function to be called on quota_on
*/
static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
- char *path)
+ char *path, int remount)
{
int err;
struct nameidata nd;
+ struct inode *inode;
if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
return -EINVAL;
+ /* No more checks needed? Path and format_id are bogus anyway... */
+ if (remount)
+ return vfs_quota_on(sb, type, format_id, path, 1);
err = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (err)
return err;
@@ -2030,18 +2040,24 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
path_put(&nd.path);
return -EXDEV;
}
+ inode = nd.path.dentry->d_inode;
/* We must not pack tails for quota files on reiserfs for quota IO to work */
- if (!(REISERFS_I(nd.path.dentry->d_inode)->i_flags & i_nopack_mask)) {
- reiserfs_warning(sb,
- "reiserfs: Quota file must have tail packing disabled.");
- path_put(&nd.path);
- return -EINVAL;
+ if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) {
+ err = reiserfs_unpack(inode, NULL);
+ if (err) {
+ reiserfs_warning(sb,
+ "reiserfs: Unpacking tail of quota file failed"
+ " (%d). Cannot turn on quotas.", err);
+ path_put(&nd.path);
+ return -EINVAL;
+ }
+ mark_inode_dirty(inode);
}
/* Not journalling quota? No more tests needed... */
if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] &&
!REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) {
path_put(&nd.path);
- return vfs_quota_on(sb, type, format_id, path);
+ return vfs_quota_on(sb, type, format_id, path, 0);
}
/* Quotafile not of fs root? */
if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
@@ -2049,7 +2065,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
"reiserfs: Quota file not on filesystem root. "
"Journalled quota will not work.");
path_put(&nd.path);
- return vfs_quota_on(sb, type, format_id, path);
+ return vfs_quota_on(sb, type, format_id, path, 0);
}
/* Read data from quotafile - avoid pagecache and such because we cannot afford