gfs2: lookup local statfs inodes prior to journal recovery
We need to lookup the master statfs inode and the local statfs inodes earlier in the mount process (in init_journal) so journal recovery can use them when it attempts to recover the statfs info. We lookup all the local statfs inodes and store them in a linked list to allow a node to recover statfs info for other nodes in the cluster. Signed-off-by: Abhi Das <adas@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
Родитель
730926982d
Коммит
97fd734ba1
|
@ -697,6 +697,13 @@ struct gfs2_pcpu_lkstats {
|
|||
struct gfs2_lkstats lkstats[10];
|
||||
};
|
||||
|
||||
/* List of local (per node) statfs inodes */
|
||||
struct local_statfs_inode {
|
||||
struct list_head si_list;
|
||||
struct inode *si_sc_inode;
|
||||
unsigned int si_jid; /* journal id this statfs inode corresponds to */
|
||||
};
|
||||
|
||||
struct gfs2_sbd {
|
||||
struct super_block *sd_vfs;
|
||||
struct gfs2_pcpu_lkstats __percpu *sd_lkstats;
|
||||
|
@ -748,6 +755,7 @@ struct gfs2_sbd {
|
|||
struct inode *sd_jindex;
|
||||
struct inode *sd_statfs_inode;
|
||||
struct inode *sd_sc_inode;
|
||||
struct list_head sd_sc_inodes_list;
|
||||
struct inode *sd_qc_inode;
|
||||
struct inode *sd_rindex;
|
||||
struct inode *sd_quota_inode;
|
||||
|
|
|
@ -110,6 +110,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
|
|||
spin_lock_init(&sdp->sd_trunc_lock);
|
||||
spin_lock_init(&sdp->sd_bitmap_lock);
|
||||
|
||||
INIT_LIST_HEAD(&sdp->sd_sc_inodes_list);
|
||||
|
||||
mapping = &sdp->sd_aspace;
|
||||
|
||||
address_space_init_once(mapping);
|
||||
|
@ -608,6 +610,90 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
|
|||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* init_statfs - look up and initialize master and local (per node) statfs inodes
|
||||
* @sdp: The GFS2 superblock
|
||||
*
|
||||
* This should be called after the jindex is initialized in init_journal() and
|
||||
* before gfs2_journal_recovery() is called because we need to be able to write
|
||||
* to these inodes during recovery.
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
static int init_statfs(struct gfs2_sbd *sdp)
|
||||
{
|
||||
int error = 0;
|
||||
struct inode *master = d_inode(sdp->sd_master_dir);
|
||||
struct inode *pn = NULL;
|
||||
char buf[30];
|
||||
struct gfs2_jdesc *jd;
|
||||
struct gfs2_inode *ip;
|
||||
|
||||
sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs");
|
||||
if (IS_ERR(sdp->sd_statfs_inode)) {
|
||||
error = PTR_ERR(sdp->sd_statfs_inode);
|
||||
fs_err(sdp, "can't read in statfs inode: %d\n", error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pn = gfs2_lookup_simple(master, "per_node");
|
||||
if (IS_ERR(pn)) {
|
||||
error = PTR_ERR(pn);
|
||||
fs_err(sdp, "can't find per_node directory: %d\n", error);
|
||||
goto put_statfs;
|
||||
}
|
||||
|
||||
/* For each jid, lookup the corresponding local statfs inode in the
|
||||
* per_node metafs directory and save it in the sdp->sd_sc_inodes_list. */
|
||||
list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
|
||||
struct local_statfs_inode *lsi =
|
||||
kmalloc(sizeof(struct local_statfs_inode), GFP_NOFS);
|
||||
if (!lsi) {
|
||||
error = -ENOMEM;
|
||||
goto free_local;
|
||||
}
|
||||
sprintf(buf, "statfs_change%u", jd->jd_jid);
|
||||
lsi->si_sc_inode = gfs2_lookup_simple(pn, buf);
|
||||
if (IS_ERR(lsi->si_sc_inode)) {
|
||||
error = PTR_ERR(lsi->si_sc_inode);
|
||||
fs_err(sdp, "can't find local \"sc\" file#%u: %d\n",
|
||||
jd->jd_jid, error);
|
||||
goto free_local;
|
||||
}
|
||||
lsi->si_jid = jd->jd_jid;
|
||||
if (jd->jd_jid == sdp->sd_jdesc->jd_jid)
|
||||
sdp->sd_sc_inode = lsi->si_sc_inode;
|
||||
|
||||
list_add_tail(&lsi->si_list, &sdp->sd_sc_inodes_list);
|
||||
}
|
||||
|
||||
iput(pn);
|
||||
ip = GFS2_I(sdp->sd_sc_inode);
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
|
||||
&sdp->sd_sc_gh);
|
||||
if (error) {
|
||||
fs_err(sdp, "can't lock local \"sc\" file: %d\n", error);
|
||||
goto free_local;
|
||||
}
|
||||
return 0;
|
||||
|
||||
free_local:
|
||||
free_local_statfs_inodes(sdp);
|
||||
iput(pn);
|
||||
put_statfs:
|
||||
iput(sdp->sd_statfs_inode);
|
||||
fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Uninitialize and free up memory used by the list of statfs inodes */
|
||||
static void uninit_statfs(struct gfs2_sbd *sdp)
|
||||
{
|
||||
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
|
||||
free_local_statfs_inodes(sdp);
|
||||
iput(sdp->sd_statfs_inode);
|
||||
}
|
||||
|
||||
static int init_journal(struct gfs2_sbd *sdp, int undo)
|
||||
{
|
||||
struct inode *master = d_inode(sdp->sd_master_dir);
|
||||
|
@ -694,6 +780,11 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
|||
}
|
||||
trace_gfs2_log_blocks(sdp, atomic_read(&sdp->sd_log_blks_free));
|
||||
|
||||
/* Lookup statfs inodes here so journal recovery can use them. */
|
||||
error = init_statfs(sdp);
|
||||
if (error)
|
||||
goto fail_jinode_gh;
|
||||
|
||||
if (sdp->sd_lockstruct.ls_first) {
|
||||
unsigned int x;
|
||||
for (x = 0; x < sdp->sd_journals; x++) {
|
||||
|
@ -702,14 +793,14 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
|||
if (sdp->sd_args.ar_spectator) {
|
||||
error = check_journal_clean(sdp, jd, true);
|
||||
if (error)
|
||||
goto fail_jinode_gh;
|
||||
goto fail_statfs;
|
||||
continue;
|
||||
}
|
||||
error = gfs2_recover_journal(jd, true);
|
||||
if (error) {
|
||||
fs_err(sdp, "error recovering journal %u: %d\n",
|
||||
x, error);
|
||||
goto fail_jinode_gh;
|
||||
goto fail_statfs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,7 +809,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
|||
error = gfs2_recover_journal(sdp->sd_jdesc, true);
|
||||
if (error) {
|
||||
fs_err(sdp, "error recovering my journal: %d\n", error);
|
||||
goto fail_jinode_gh;
|
||||
goto fail_statfs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,6 +820,8 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
|
|||
INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func);
|
||||
return 0;
|
||||
|
||||
fail_statfs:
|
||||
uninit_statfs(sdp);
|
||||
fail_jinode_gh:
|
||||
/* A withdraw may have done dq/uninit so now we need to check it */
|
||||
if (!sdp->sd_args.ar_spectator &&
|
||||
|
@ -762,20 +855,12 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
|
|||
if (error)
|
||||
goto fail;
|
||||
|
||||
/* Read in the master statfs inode */
|
||||
sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs");
|
||||
if (IS_ERR(sdp->sd_statfs_inode)) {
|
||||
error = PTR_ERR(sdp->sd_statfs_inode);
|
||||
fs_err(sdp, "can't read in statfs inode: %d\n", error);
|
||||
goto fail_journal;
|
||||
}
|
||||
|
||||
/* Read in the resource index inode */
|
||||
sdp->sd_rindex = gfs2_lookup_simple(master, "rindex");
|
||||
if (IS_ERR(sdp->sd_rindex)) {
|
||||
error = PTR_ERR(sdp->sd_rindex);
|
||||
fs_err(sdp, "can't get resource index inode: %d\n", error);
|
||||
goto fail_statfs;
|
||||
goto fail_journal;
|
||||
}
|
||||
sdp->sd_rindex_uptodate = 0;
|
||||
|
||||
|
@ -804,8 +889,6 @@ fail_qinode:
|
|||
fail_rindex:
|
||||
gfs2_clear_rgrpd(sdp);
|
||||
iput(sdp->sd_rindex);
|
||||
fail_statfs:
|
||||
iput(sdp->sd_statfs_inode);
|
||||
fail_journal:
|
||||
init_journal(sdp, UNDO);
|
||||
fail:
|
||||
|
@ -833,14 +916,6 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
|
|||
return error;
|
||||
}
|
||||
|
||||
sprintf(buf, "statfs_change%u", sdp->sd_jdesc->jd_jid);
|
||||
sdp->sd_sc_inode = gfs2_lookup_simple(pn, buf);
|
||||
if (IS_ERR(sdp->sd_sc_inode)) {
|
||||
error = PTR_ERR(sdp->sd_sc_inode);
|
||||
fs_err(sdp, "can't find local \"sc\" file: %d\n", error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sprintf(buf, "quota_change%u", sdp->sd_jdesc->jd_jid);
|
||||
sdp->sd_qc_inode = gfs2_lookup_simple(pn, buf);
|
||||
if (IS_ERR(sdp->sd_qc_inode)) {
|
||||
|
@ -852,33 +927,21 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
|
|||
iput(pn);
|
||||
pn = NULL;
|
||||
|
||||
ip = GFS2_I(sdp->sd_sc_inode);
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
|
||||
&sdp->sd_sc_gh);
|
||||
if (error) {
|
||||
fs_err(sdp, "can't lock local \"sc\" file: %d\n", error);
|
||||
goto fail_qc_i;
|
||||
}
|
||||
|
||||
ip = GFS2_I(sdp->sd_qc_inode);
|
||||
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
|
||||
&sdp->sd_qc_gh);
|
||||
if (error) {
|
||||
fs_err(sdp, "can't lock local \"qc\" file: %d\n", error);
|
||||
goto fail_ut_gh;
|
||||
goto fail_qc_i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_qc_gh:
|
||||
gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
|
||||
fail_ut_gh:
|
||||
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
|
||||
fail_qc_i:
|
||||
iput(sdp->sd_qc_inode);
|
||||
fail_ut_i:
|
||||
iput(sdp->sd_sc_inode);
|
||||
fail:
|
||||
iput(pn);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -729,7 +729,7 @@ restart:
|
|||
gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
|
||||
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
|
||||
gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
|
||||
iput(sdp->sd_sc_inode);
|
||||
free_local_statfs_inodes(sdp);
|
||||
iput(sdp->sd_qc_inode);
|
||||
}
|
||||
|
||||
|
@ -1561,6 +1561,35 @@ static void gfs2_free_inode(struct inode *inode)
|
|||
kmem_cache_free(gfs2_inode_cachep, GFS2_I(inode));
|
||||
}
|
||||
|
||||
extern void free_local_statfs_inodes(struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct local_statfs_inode *lsi, *safe;
|
||||
|
||||
/* Run through the statfs inodes list to iput and free memory */
|
||||
list_for_each_entry_safe(lsi, safe, &sdp->sd_sc_inodes_list, si_list) {
|
||||
if (lsi->si_jid == sdp->sd_jdesc->jd_jid)
|
||||
sdp->sd_sc_inode = NULL; /* belongs to this node */
|
||||
if (lsi->si_sc_inode)
|
||||
iput(lsi->si_sc_inode);
|
||||
list_del(&lsi->si_list);
|
||||
kfree(lsi);
|
||||
}
|
||||
}
|
||||
|
||||
extern struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
|
||||
unsigned int index)
|
||||
{
|
||||
struct local_statfs_inode *lsi;
|
||||
|
||||
/* Return the local (per node) statfs inode in the
|
||||
* sdp->sd_sc_inodes_list corresponding to the 'index'. */
|
||||
list_for_each_entry(lsi, &sdp->sd_sc_inodes_list, si_list) {
|
||||
if (lsi->si_jid == index)
|
||||
return lsi->si_sc_inode;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct super_operations gfs2_super_ops = {
|
||||
.alloc_inode = gfs2_alloc_inode,
|
||||
.free_inode = gfs2_free_inode,
|
||||
|
|
|
@ -44,6 +44,9 @@ extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
|
|||
extern int gfs2_statfs_sync(struct super_block *sb, int type);
|
||||
extern void gfs2_freeze_func(struct work_struct *work);
|
||||
|
||||
extern void free_local_statfs_inodes(struct gfs2_sbd *sdp);
|
||||
extern struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
|
||||
unsigned int index);
|
||||
extern void free_sbd(struct gfs2_sbd *sdp);
|
||||
|
||||
extern struct file_system_type gfs2_fs_type;
|
||||
|
|
Загрузка…
Ссылка в новой задаче