summaryrefslogtreecommitdiff
path: root/fs/gfs2/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/super.c')
-rw-r--r--fs/gfs2/super.c126
1 files changed, 51 insertions, 75 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 713e621c240b..e5639dec66c4 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -78,6 +78,8 @@ enum {
Opt_quota_quantum,
Opt_barrier,
Opt_nobarrier,
+ Opt_rgrplvb,
+ Opt_norgrplvb,
Opt_error,
};
@@ -115,6 +117,8 @@ static const match_table_t tokens = {
{Opt_quota_quantum, "quota_quantum=%d"},
{Opt_barrier, "barrier"},
{Opt_nobarrier, "nobarrier"},
+ {Opt_rgrplvb, "rgrplvb"},
+ {Opt_norgrplvb, "norgrplvb"},
{Opt_error, NULL}
};
@@ -267,6 +271,12 @@ int gfs2_mount_args(struct gfs2_args *args, char *options)
case Opt_nobarrier:
args->ar_nobarrier = 1;
break;
+ case Opt_rgrplvb:
+ args->ar_rgrplvb = 1;
+ break;
+ case Opt_norgrplvb:
+ args->ar_rgrplvb = 0;
+ break;
case Opt_error:
default:
printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o);
@@ -490,7 +500,7 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
if (error)
return;
- gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
+ gfs2_trans_add_meta(l_ip->i_gl, l_bh);
spin_lock(&sdp->sd_statfs_spin);
l_sc->sc_total += total;
@@ -518,7 +528,7 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
- gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
+ gfs2_trans_add_meta(l_ip->i_gl, l_bh);
spin_lock(&sdp->sd_statfs_spin);
m_sc->sc_total += l_sc->sc_total;
@@ -529,7 +539,7 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
0, sizeof(struct gfs2_statfs_change));
spin_unlock(&sdp->sd_statfs_spin);
- gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1);
+ gfs2_trans_add_meta(m_ip->i_gl, m_bh);
gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode));
}
@@ -653,54 +663,6 @@ out:
return error;
}
-/**
- * gfs2_freeze_fs - freezes the file system
- * @sdp: the file system
- *
- * This function flushes data and meta data for all machines by
- * acquiring the transaction log exclusively. All journals are
- * ensured to be in a clean state as well.
- *
- * Returns: errno
- */
-
-int gfs2_freeze_fs(struct gfs2_sbd *sdp)
-{
- int error = 0;
-
- mutex_lock(&sdp->sd_freeze_lock);
-
- if (!sdp->sd_freeze_count++) {
- error = gfs2_lock_fs_check_clean(sdp, &sdp->sd_freeze_gh);
- if (error)
- sdp->sd_freeze_count--;
- }
-
- mutex_unlock(&sdp->sd_freeze_lock);
-
- return error;
-}
-
-/**
- * gfs2_unfreeze_fs - unfreezes the file system
- * @sdp: the file system
- *
- * This function allows the file system to proceed by unlocking
- * the exclusively held transaction lock. Other GFS2 nodes are
- * now free to acquire the lock shared and go on with their lives.
- *
- */
-
-void gfs2_unfreeze_fs(struct gfs2_sbd *sdp)
-{
- mutex_lock(&sdp->sd_freeze_lock);
-
- if (sdp->sd_freeze_count && !--sdp->sd_freeze_count)
- gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
-
- mutex_unlock(&sdp->sd_freeze_lock);
-}
-
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
{
struct gfs2_dinode *str = buf;
@@ -711,8 +673,8 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
- str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
- str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+ str->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode));
+ str->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode));
str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
str->di_size = cpu_to_be64(i_size_read(&ip->i_inode));
str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode));
@@ -800,7 +762,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
return;
}
need_unlock = 1;
- }
+ } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE))
+ return;
if (current->journal_info == NULL) {
ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
@@ -813,7 +776,7 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
ret = gfs2_meta_inode_buffer(ip, &bh);
if (ret == 0) {
- gfs2_trans_add_bh(ip->i_gl, bh, 1);
+ gfs2_trans_add_meta(ip->i_gl, bh);
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
}
@@ -838,7 +801,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
int error;
flush_workqueue(gfs2_delete_workqueue);
- gfs2_quota_sync(sdp->sd_vfs, 0, 1);
+ gfs2_quota_sync(sdp->sd_vfs, 0);
gfs2_statfs_sync(sdp->sd_vfs, 0);
error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
@@ -877,13 +840,6 @@ static void gfs2_put_super(struct super_block *sb)
int error;
struct gfs2_jdesc *jd;
- /* Unfreeze the filesystem, if we need to */
-
- mutex_lock(&sdp->sd_freeze_lock);
- if (sdp->sd_freeze_count)
- gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
- mutex_unlock(&sdp->sd_freeze_lock);
-
/* No more recovery requests */
set_bit(SDF_NORECOVERY, &sdp->sd_flags);
smp_mb();
@@ -952,6 +908,8 @@ restart:
static int gfs2_sync_fs(struct super_block *sb, int wait)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
+
+ gfs2_quota_sync(sb, -1);
if (wait && sdp)
gfs2_log_flush(sdp, NULL);
return 0;
@@ -972,7 +930,7 @@ static int gfs2_freeze(struct super_block *sb)
return -EINVAL;
for (;;) {
- error = gfs2_freeze_fs(sdp);
+ error = gfs2_lock_fs_check_clean(sdp, &sdp->sd_freeze_gh);
if (!error)
break;
@@ -1000,7 +958,9 @@ static int gfs2_freeze(struct super_block *sb)
static int gfs2_unfreeze(struct super_block *sb)
{
- gfs2_unfreeze_fs(sb->s_fs_info);
+ struct gfs2_sbd *sdp = sb->s_fs_info;
+
+ gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
return 0;
}
@@ -1354,6 +1314,8 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
val = sdp->sd_tune.gt_statfs_quantum;
if (val != 30)
seq_printf(s, ",statfs_quantum=%d", val);
+ else if (sdp->sd_tune.gt_statfs_slow)
+ seq_puts(s, ",statfs_quantum=0");
val = sdp->sd_tune.gt_quota_quantum;
if (val != 60)
seq_printf(s, ",quota_quantum=%d", val);
@@ -1379,6 +1341,8 @@ static int gfs2_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",nobarrier");
if (test_bit(SDF_DEMOTE, &sdp->sd_flags))
seq_printf(s, ",demote_interface_used");
+ if (args->ar_rgrplvb)
+ seq_printf(s, ",rgrplvb");
return 0;
}
@@ -1399,7 +1363,6 @@ static void gfs2_final_release_pages(struct gfs2_inode *ip)
static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
- struct gfs2_qadata *qa;
struct gfs2_rgrpd *rgd;
struct gfs2_holder gh;
int error;
@@ -1409,13 +1372,13 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
return -EIO;
}
- qa = gfs2_qadata_get(ip);
- if (!qa)
- return -ENOMEM;
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
- error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
+ error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE);
if (error)
- goto out;
+ return error;
rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1);
if (!rgd) {
@@ -1443,8 +1406,6 @@ out_rg_gunlock:
gfs2_glock_dq_uninit(&gh);
out_qs:
gfs2_quota_unhold(ip);
-out:
- gfs2_qadata_put(ip);
return error;
}
@@ -1483,6 +1444,7 @@ static void gfs2_evict_inode(struct inode *inode)
/* Must not read inode block until block type has been verified */
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
if (unlikely(error)) {
+ ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
goto out;
}
@@ -1532,6 +1494,11 @@ static void gfs2_evict_inode(struct inode *inode)
out_truncate:
gfs2_log_flush(sdp, ip->i_gl);
+ if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
+ struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl);
+ filemap_fdatawrite(metamapping);
+ filemap_fdatawait(metamapping);
+ }
write_inode_now(inode, 1);
gfs2_ail_flush(ip->i_gl, 0);
@@ -1545,8 +1512,13 @@ out_truncate:
out_unlock:
/* Error path for case 1 */
- if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
+ if (gfs2_rs_active(ip->i_res))
+ gfs2_rs_deltree(ip->i_res);
+
+ if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
+ ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq(&ip->i_iopen_gh);
+ }
gfs2_holder_uninit(&ip->i_iopen_gh);
gfs2_glock_dq_uninit(&gh);
if (error && error != GLR_TRYFAILED && error != -EROFS)
@@ -1554,15 +1526,18 @@ out_unlock:
out:
/* Case 3 starts here */
truncate_inode_pages(&inode->i_data, 0);
+ gfs2_rs_delete(ip);
+ gfs2_ordered_del_inode(ip);
clear_inode(inode);
gfs2_dir_hash_inval(ip);
ip->i_gl->gl_object = NULL;
- flush_delayed_work_sync(&ip->i_gl->gl_work);
+ flush_delayed_work(&ip->i_gl->gl_work);
gfs2_glock_add_to_lru(ip->i_gl);
gfs2_glock_put(ip->i_gl);
ip->i_gl = NULL;
if (ip->i_iopen_gh.gh_gl) {
ip->i_iopen_gh.gh_gl->gl_object = NULL;
+ ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
}
}
@@ -1576,6 +1551,7 @@ static struct inode *gfs2_alloc_inode(struct super_block *sb)
ip->i_flags = 0;
ip->i_gl = NULL;
ip->i_rgd = NULL;
+ ip->i_res = NULL;
}
return &ip->i_inode;
}