Commit 4529fb15 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-v5.14-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

Pull gfs2 updates from Andreas Gruenbacher:

 - Various withdraw related fixes (freeze glock recursion, thread
   initialization / destruction order, journal recovery, glock cleanup,
   withdraw under journal lock).

 - Some error message improvements.

 - Various minor cleanups.

* tag 'gfs2-v5.14-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Remove redundant check from gfs2_glock_dq
  gfs2: Delay withdraw from atomic context
  gfs2: Don't call dlm after protocol is unmounted
  gfs2: don't stop reads while withdraw in progress
  gfs2: Mark journal inodes as "don't cache"
  gfs2: nit: gfs2_drop_inode shouldn't return bool
  gfs2: Eliminate vestigial HIF_FIRST
  gfs2: Make recovery error more readable
  gfs2: Don't release and reacquire local statfs bh
  gfs2: init system threads before freeze lock
  gfs2: tiny cleanup in gfs2_log_reserve
  gfs2: trivial clean up of gfs2_ail_error
  gfs2: be more verbose replaying invalid rgrp blocks
  gfs2: Fix glock recursion in freeze_go_xmote_bh
  gfs2: Fix memory leak of object lsi on error return path
parents cd358208 08d73666
...@@ -574,10 +574,9 @@ void adjust_fs_space(struct inode *inode) ...@@ -574,10 +574,9 @@ void adjust_fs_space(struct inode *inode)
{ {
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
struct buffer_head *m_bh, *l_bh; struct buffer_head *m_bh;
u64 fs_total, new_free; u64 fs_total, new_free;
if (gfs2_trans_begin(sdp, 2 * RES_STATFS, 0) != 0) if (gfs2_trans_begin(sdp, 2 * RES_STATFS, 0) != 0)
...@@ -600,11 +599,7 @@ void adjust_fs_space(struct inode *inode) ...@@ -600,11 +599,7 @@ void adjust_fs_space(struct inode *inode)
(unsigned long long)new_free); (unsigned long long)new_free);
gfs2_statfs_change(sdp, new_free, new_free, 0); gfs2_statfs_change(sdp, new_free, new_free, 0);
if (gfs2_meta_inode_buffer(l_ip, &l_bh) != 0) update_statfs(sdp, m_bh);
goto out2;
update_statfs(sdp, m_bh, l_bh);
brelse(l_bh);
out2:
brelse(m_bh); brelse(m_bh);
out: out:
sdp->sd_rindex_uptodate = 0; sdp->sd_rindex_uptodate = 0;
......
...@@ -1494,12 +1494,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh) ...@@ -1494,12 +1494,11 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
list_del_init(&gh->gh_list); list_del_init(&gh->gh_list);
clear_bit(HIF_HOLDER, &gh->gh_iflags); clear_bit(HIF_HOLDER, &gh->gh_iflags);
if (find_first_holder(gl) == NULL) {
if (list_empty(&gl->gl_holders) && if (list_empty(&gl->gl_holders) &&
!test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && !test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
!test_bit(GLF_DEMOTE, &gl->gl_flags)) !test_bit(GLF_DEMOTE, &gl->gl_flags))
fast_path = 1; fast_path = 1;
}
if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl)) if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl))
gfs2_glock_add_to_lru(gl); gfs2_glock_add_to_lru(gl);
...@@ -2077,8 +2076,6 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags) ...@@ -2077,8 +2076,6 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
*p++ = 'H'; *p++ = 'H';
if (test_bit(HIF_WAIT, &iflags)) if (test_bit(HIF_WAIT, &iflags))
*p++ = 'W'; *p++ = 'W';
if (test_bit(HIF_FIRST, &iflags))
*p++ = 'F';
*p = 0; *p = 0;
return buf; return buf;
} }
......
...@@ -33,16 +33,18 @@ extern struct workqueue_struct *gfs2_control_wq; ...@@ -33,16 +33,18 @@ extern struct workqueue_struct *gfs2_control_wq;
static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh) static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
{ {
fs_err(gl->gl_name.ln_sbd, struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
fs_err(sdp,
"AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page " "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page "
"state 0x%lx\n", "state 0x%lx\n",
bh, (unsigned long long)bh->b_blocknr, bh->b_state, bh, (unsigned long long)bh->b_blocknr, bh->b_state,
bh->b_page->mapping, bh->b_page->flags); bh->b_page->mapping, bh->b_page->flags);
fs_err(gl->gl_name.ln_sbd, "AIL glock %u:%llu mapping %p\n", fs_err(sdp, "AIL glock %u:%llu mapping %p\n",
gl->gl_name.ln_type, gl->gl_name.ln_number, gl->gl_name.ln_type, gl->gl_name.ln_number,
gfs2_glock2aspace(gl)); gfs2_glock2aspace(gl));
gfs2_lm(gl->gl_name.ln_sbd, "AIL error\n"); gfs2_lm(sdp, "AIL error\n");
gfs2_withdraw(gl->gl_name.ln_sbd); gfs2_withdraw_delayed(sdp);
} }
/** /**
...@@ -610,17 +612,14 @@ static int freeze_go_xmote_bh(struct gfs2_glock *gl) ...@@ -610,17 +612,14 @@ static int freeze_go_xmote_bh(struct gfs2_glock *gl)
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
error = gfs2_find_jhead(sdp->sd_jdesc, &head, false); error = gfs2_find_jhead(sdp->sd_jdesc, &head, false);
if (error) if (gfs2_assert_withdraw_delayed(sdp, !error))
gfs2_consist(sdp); return error;
if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) if (gfs2_assert_withdraw_delayed(sdp, head.lh_flags &
gfs2_consist(sdp); GFS2_LOG_HEAD_UNMOUNT))
return -EIO;
/* Initialize some head of the log stuff */
if (!gfs2_withdrawn(sdp)) {
sdp->sd_log_sequence = head.lh_sequence + 1; sdp->sd_log_sequence = head.lh_sequence + 1;
gfs2_log_pointers_init(sdp, head.lh_blkno); gfs2_log_pointers_init(sdp, head.lh_blkno);
} }
}
return 0; return 0;
} }
......
...@@ -253,7 +253,6 @@ struct gfs2_lkstats { ...@@ -253,7 +253,6 @@ struct gfs2_lkstats {
enum { enum {
/* States */ /* States */
HIF_HOLDER = 6, /* Set for gh that "holds" the glock */ HIF_HOLDER = 6, /* Set for gh that "holds" the glock */
HIF_FIRST = 7,
HIF_WAIT = 10, HIF_WAIT = 10,
}; };
...@@ -768,6 +767,7 @@ struct gfs2_sbd { ...@@ -768,6 +767,7 @@ struct gfs2_sbd {
struct gfs2_glock *sd_jinode_gl; struct gfs2_glock *sd_jinode_gl;
struct gfs2_holder sd_sc_gh; struct gfs2_holder sd_sc_gh;
struct buffer_head *sd_sc_bh;
struct gfs2_holder sd_qc_gh; struct gfs2_holder sd_qc_gh;
struct completion sd_journal_ready; struct completion sd_journal_ready;
......
...@@ -299,6 +299,11 @@ static void gdlm_put_lock(struct gfs2_glock *gl) ...@@ -299,6 +299,11 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
gfs2_update_request_times(gl); gfs2_update_request_times(gl);
/* don't want to call dlm if we've unmounted the lock protocol */
if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
gfs2_glock_free(gl);
return;
}
/* don't want to skip dlm_unlock writing the lvb when lock has one */ /* don't want to skip dlm_unlock writing the lvb when lock has one */
if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
......
...@@ -594,7 +594,7 @@ void gfs2_log_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr, ...@@ -594,7 +594,7 @@ void gfs2_log_reserve(struct gfs2_sbd *sdp, struct gfs2_trans *tr,
{ {
unsigned int blks = tr->tr_reserved; unsigned int blks = tr->tr_reserved;
unsigned int revokes = tr->tr_revokes; unsigned int revokes = tr->tr_revokes;
unsigned int revoke_blks = 0; unsigned int revoke_blks;
*extra_revokes = 0; *extra_revokes = 0;
if (revokes) { if (revokes) {
......
...@@ -761,6 +761,32 @@ static void buf_lo_before_scan(struct gfs2_jdesc *jd, ...@@ -761,6 +761,32 @@ static void buf_lo_before_scan(struct gfs2_jdesc *jd,
jd->jd_replayed_blocks = 0; jd->jd_replayed_blocks = 0;
} }
#define obsolete_rgrp_replay \
"Replaying 0x%llx from jid=%d/0x%llx but we already have a bh!\n"
#define obsolete_rgrp_replay2 \
"busy:%d, pinned:%d rg_gen:0x%llx, j_gen:0x%llx\n"
static void obsolete_rgrp(struct gfs2_jdesc *jd, struct buffer_head *bh_log,
u64 blkno)
{
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
struct gfs2_rgrpd *rgd;
struct gfs2_rgrp *jrgd = (struct gfs2_rgrp *)bh_log->b_data;
rgd = gfs2_blk2rgrpd(sdp, blkno, false);
if (rgd && rgd->rd_addr == blkno &&
rgd->rd_bits && rgd->rd_bits->bi_bh) {
fs_info(sdp, obsolete_rgrp_replay, (unsigned long long)blkno,
jd->jd_jid, bh_log->b_blocknr);
fs_info(sdp, obsolete_rgrp_replay2,
buffer_busy(rgd->rd_bits->bi_bh) ? 1 : 0,
buffer_pinned(rgd->rd_bits->bi_bh),
rgd->rd_igeneration,
be64_to_cpu(jrgd->rg_igeneration));
gfs2_dump_glock(NULL, rgd->rd_gl, true);
}
}
static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
struct gfs2_log_descriptor *ld, __be64 *ptr, struct gfs2_log_descriptor *ld, __be64 *ptr,
int pass) int pass)
...@@ -799,21 +825,9 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, ...@@ -799,21 +825,9 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start,
struct gfs2_meta_header *mh = struct gfs2_meta_header *mh =
(struct gfs2_meta_header *)bh_ip->b_data; (struct gfs2_meta_header *)bh_ip->b_data;
if (mh->mh_type == cpu_to_be32(GFS2_METATYPE_RG)) { if (mh->mh_type == cpu_to_be32(GFS2_METATYPE_RG))
struct gfs2_rgrpd *rgd; obsolete_rgrp(jd, bh_log, blkno);
rgd = gfs2_blk2rgrpd(sdp, blkno, false);
if (rgd && rgd->rd_addr == blkno &&
rgd->rd_bits && rgd->rd_bits->bi_bh) {
fs_info(sdp, "Replaying 0x%llx but we "
"already have a bh!\n",
(unsigned long long)blkno);
fs_info(sdp, "busy:%d, pinned:%d\n",
buffer_busy(rgd->rd_bits->bi_bh) ? 1 : 0,
buffer_pinned(rgd->rd_bits->bi_bh));
gfs2_dump_glock(NULL, rgd->rd_gl, true);
}
}
mark_buffer_dirty(bh_ip); mark_buffer_dirty(bh_ip);
} }
brelse(bh_log); brelse(bh_log);
......
...@@ -258,8 +258,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, ...@@ -258,8 +258,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
struct buffer_head *bh, *bhs[2]; struct buffer_head *bh, *bhs[2];
int num = 0; int num = 0;
if (unlikely(gfs2_withdrawn(sdp)) && if (unlikely(gfs2_withdrawn(sdp)) && !gfs2_withdraw_in_prog(sdp)) {
(!sdp->sd_jdesc || gl != sdp->sd_jinode_gl)) {
*bhp = NULL; *bhp = NULL;
return -EIO; return -EIO;
} }
...@@ -317,7 +316,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, ...@@ -317,7 +316,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh) int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
{ {
if (unlikely(gfs2_withdrawn(sdp))) if (unlikely(gfs2_withdrawn(sdp)) && !gfs2_withdraw_in_prog(sdp))
return -EIO; return -EIO;
wait_on_buffer(bh); wait_on_buffer(bh);
...@@ -328,7 +327,7 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh) ...@@ -328,7 +327,7 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
gfs2_io_error_bh_wd(sdp, bh); gfs2_io_error_bh_wd(sdp, bh);
return -EIO; return -EIO;
} }
if (unlikely(gfs2_withdrawn(sdp))) if (unlikely(gfs2_withdrawn(sdp)) && !gfs2_withdraw_in_prog(sdp))
return -EIO; return -EIO;
return 0; return 0;
......
...@@ -614,6 +614,7 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) ...@@ -614,6 +614,7 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
break; break;
} }
d_mark_dontcache(jd->jd_inode);
spin_lock(&sdp->sd_jindex_spin); spin_lock(&sdp->sd_jindex_spin);
jd->jd_jid = sdp->sd_journals++; jd->jd_jid = sdp->sd_journals++;
jip = GFS2_I(jd->jd_inode); jip = GFS2_I(jd->jd_inode);
...@@ -677,6 +678,7 @@ static int init_statfs(struct gfs2_sbd *sdp) ...@@ -677,6 +678,7 @@ static int init_statfs(struct gfs2_sbd *sdp)
error = PTR_ERR(lsi->si_sc_inode); error = PTR_ERR(lsi->si_sc_inode);
fs_err(sdp, "can't find local \"sc\" file#%u: %d\n", fs_err(sdp, "can't find local \"sc\" file#%u: %d\n",
jd->jd_jid, error); jd->jd_jid, error);
kfree(lsi);
goto free_local; goto free_local;
} }
lsi->si_jid = jd->jd_jid; lsi->si_jid = jd->jd_jid;
...@@ -695,8 +697,16 @@ static int init_statfs(struct gfs2_sbd *sdp) ...@@ -695,8 +697,16 @@ static int init_statfs(struct gfs2_sbd *sdp)
fs_err(sdp, "can't lock local \"sc\" file: %d\n", error); fs_err(sdp, "can't lock local \"sc\" file: %d\n", error);
goto free_local; goto free_local;
} }
/* read in the local statfs buffer - other nodes don't change it. */
error = gfs2_meta_inode_buffer(ip, &sdp->sd_sc_bh);
if (error) {
fs_err(sdp, "Cannot read in local statfs: %d\n", error);
goto unlock_sd_gh;
}
return 0; return 0;
unlock_sd_gh:
gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
free_local: free_local:
free_local_statfs_inodes(sdp); free_local_statfs_inodes(sdp);
iput(pn); iput(pn);
...@@ -710,6 +720,7 @@ static int init_statfs(struct gfs2_sbd *sdp) ...@@ -710,6 +720,7 @@ static int init_statfs(struct gfs2_sbd *sdp)
static void uninit_statfs(struct gfs2_sbd *sdp) static void uninit_statfs(struct gfs2_sbd *sdp)
{ {
if (!sdp->sd_args.ar_spectator) { if (!sdp->sd_args.ar_spectator) {
brelse(sdp->sd_sc_bh);
gfs2_glock_dq_uninit(&sdp->sd_sc_gh); gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
free_local_statfs_inodes(sdp); free_local_statfs_inodes(sdp);
} }
...@@ -1088,6 +1099,34 @@ void gfs2_online_uevent(struct gfs2_sbd *sdp) ...@@ -1088,6 +1099,34 @@ void gfs2_online_uevent(struct gfs2_sbd *sdp)
kobject_uevent_env(&sdp->sd_kobj, KOBJ_ONLINE, envp); kobject_uevent_env(&sdp->sd_kobj, KOBJ_ONLINE, envp);
} }
static int init_threads(struct gfs2_sbd *sdp)
{
struct task_struct *p;
int error = 0;
p = kthread_run(gfs2_logd, sdp, "gfs2_logd");
if (IS_ERR(p)) {
error = PTR_ERR(p);
fs_err(sdp, "can't start logd thread: %d\n", error);
return error;
}
sdp->sd_logd_process = p;
p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad");
if (IS_ERR(p)) {
error = PTR_ERR(p);
fs_err(sdp, "can't start quotad thread: %d\n", error);
goto fail;
}
sdp->sd_quotad_process = p;
return 0;
fail:
kthread_stop(sdp->sd_logd_process);
sdp->sd_logd_process = NULL;
return error;
}
/** /**
* gfs2_fill_super - Read in superblock * gfs2_fill_super - Read in superblock
* @sb: The VFS superblock * @sb: The VFS superblock
...@@ -1216,6 +1255,14 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1216,6 +1255,14 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
goto fail_per_node; goto fail_per_node;
} }
if (!sb_rdonly(sb)) {
error = init_threads(sdp);
if (error) {
gfs2_withdraw_delayed(sdp);
goto fail_per_node;
}
}
error = gfs2_freeze_lock(sdp, &freeze_gh, 0); error = gfs2_freeze_lock(sdp, &freeze_gh, 0);
if (error) if (error)
goto fail_per_node; goto fail_per_node;
...@@ -1225,6 +1272,12 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1225,6 +1272,12 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
gfs2_freeze_unlock(&freeze_gh); gfs2_freeze_unlock(&freeze_gh);
if (error) { if (error) {
if (sdp->sd_quotad_process)
kthread_stop(sdp->sd_quotad_process);
sdp->sd_quotad_process = NULL;
if (sdp->sd_logd_process)
kthread_stop(sdp->sd_logd_process);
sdp->sd_logd_process = NULL;
fs_err(sdp, "can't make FS RW: %d\n", error); fs_err(sdp, "can't make FS RW: %d\n", error);
goto fail_per_node; goto fail_per_node;
} }
......
...@@ -119,34 +119,6 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) ...@@ -119,34 +119,6 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd)
return 0; return 0;
} }
static int init_threads(struct gfs2_sbd *sdp)
{
struct task_struct *p;
int error = 0;
p = kthread_run(gfs2_logd, sdp, "gfs2_logd");
if (IS_ERR(p)) {
error = PTR_ERR(p);
fs_err(sdp, "can't start logd thread: %d\n", error);
return error;
}
sdp->sd_logd_process = p;
p = kthread_run(gfs2_quotad, sdp, "gfs2_quotad");
if (IS_ERR(p)) {
error = PTR_ERR(p);
fs_err(sdp, "can't start quotad thread: %d\n", error);
goto fail;
}
sdp->sd_quotad_process = p;
return 0;
fail:
kthread_stop(sdp->sd_logd_process);
sdp->sd_logd_process = NULL;
return error;
}
/** /**
* gfs2_make_fs_rw - Turn a Read-Only FS into a Read-Write one * gfs2_make_fs_rw - Turn a Read-Only FS into a Read-Write one
* @sdp: the filesystem * @sdp: the filesystem
...@@ -161,26 +133,17 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) ...@@ -161,26 +133,17 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
struct gfs2_log_header_host head; struct gfs2_log_header_host head;
int error; int error;
error = init_threads(sdp);
if (error) {
gfs2_withdraw_delayed(sdp);
return error;
}
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
if (gfs2_withdrawn(sdp)) { if (gfs2_withdrawn(sdp))
error = -EIO; return -EIO;
goto fail;
}
error = gfs2_find_jhead(sdp->sd_jdesc, &head, false); error = gfs2_find_jhead(sdp->sd_jdesc, &head, false);
if (error || gfs2_withdrawn(sdp)) if (error || gfs2_withdrawn(sdp))
goto fail; return error;
if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) { if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
gfs2_consist(sdp); gfs2_consist(sdp);
error = -EIO; return -EIO;
goto fail;
} }
/* Initialize some head of the log stuff */ /* Initialize some head of the log stuff */
...@@ -188,20 +151,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) ...@@ -188,20 +151,8 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
gfs2_log_pointers_init(sdp, head.lh_blkno); gfs2_log_pointers_init(sdp, head.lh_blkno);
error = gfs2_quota_init(sdp); error = gfs2_quota_init(sdp);
if (error || gfs2_withdrawn(sdp)) if (!error && !gfs2_withdrawn(sdp))
goto fail;
set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags); set_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
return 0;
fail:
if (sdp->sd_quotad_process)
kthread_stop(sdp->sd_quotad_process);
sdp->sd_quotad_process = NULL;
if (sdp->sd_logd_process)
kthread_stop(sdp->sd_logd_process);
sdp->sd_logd_process = NULL;
return error; return error;
} }
...@@ -227,9 +178,8 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp) ...@@ -227,9 +178,8 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp)
{ {
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
struct buffer_head *m_bh, *l_bh; struct buffer_head *m_bh;
struct gfs2_holder gh; struct gfs2_holder gh;
int error; int error;
...@@ -248,21 +198,15 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp) ...@@ -248,21 +198,15 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp)
sizeof(struct gfs2_dinode)); sizeof(struct gfs2_dinode));
spin_unlock(&sdp->sd_statfs_spin); spin_unlock(&sdp->sd_statfs_spin);
} else { } else {
error = gfs2_meta_inode_buffer(l_ip, &l_bh);
if (error)
goto out_m_bh;
spin_lock(&sdp->sd_statfs_spin); spin_lock(&sdp->sd_statfs_spin);
gfs2_statfs_change_in(m_sc, m_bh->b_data + gfs2_statfs_change_in(m_sc, m_bh->b_data +
sizeof(struct gfs2_dinode)); sizeof(struct gfs2_dinode));
gfs2_statfs_change_in(l_sc, l_bh->b_data + gfs2_statfs_change_in(l_sc, sdp->sd_sc_bh->b_data +
sizeof(struct gfs2_dinode)); sizeof(struct gfs2_dinode));
spin_unlock(&sdp->sd_statfs_spin); spin_unlock(&sdp->sd_statfs_spin);
brelse(l_bh);
} }
out_m_bh:
brelse(m_bh); brelse(m_bh);
out: out:
gfs2_glock_dq_uninit(&gh); gfs2_glock_dq_uninit(&gh);
...@@ -275,22 +219,17 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, ...@@ -275,22 +219,17 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
struct buffer_head *l_bh;
s64 x, y; s64 x, y;
int need_sync = 0; int need_sync = 0;
int error;
error = gfs2_meta_inode_buffer(l_ip, &l_bh);
if (error)
return;
gfs2_trans_add_meta(l_ip->i_gl, l_bh); gfs2_trans_add_meta(l_ip->i_gl, sdp->sd_sc_bh);
spin_lock(&sdp->sd_statfs_spin); spin_lock(&sdp->sd_statfs_spin);
l_sc->sc_total += total; l_sc->sc_total += total;
l_sc->sc_free += free; l_sc->sc_free += free;
l_sc->sc_dinodes += dinodes; l_sc->sc_dinodes += dinodes;
gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); gfs2_statfs_change_out(l_sc, sdp->sd_sc_bh->b_data +
sizeof(struct gfs2_dinode));
if (sdp->sd_args.ar_statfs_percent) { if (sdp->sd_args.ar_statfs_percent) {
x = 100 * l_sc->sc_free; x = 100 * l_sc->sc_free;
y = m_sc->sc_free * sdp->sd_args.ar_statfs_percent; y = m_sc->sc_free * sdp->sd_args.ar_statfs_percent;
...@@ -299,20 +238,18 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, ...@@ -299,20 +238,18 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
} }
spin_unlock(&sdp->sd_statfs_spin); spin_unlock(&sdp->sd_statfs_spin);
brelse(l_bh);
if (need_sync) if (need_sync)
gfs2_wake_up_statfs(sdp); gfs2_wake_up_statfs(sdp);
} }
void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh)
struct buffer_head *l_bh)
{ {
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
gfs2_trans_add_meta(l_ip->i_gl, l_bh); gfs2_trans_add_meta(l_ip->i_gl, sdp->sd_sc_bh);
gfs2_trans_add_meta(m_ip->i_gl, m_bh); gfs2_trans_add_meta(m_ip->i_gl, m_bh);
spin_lock(&sdp->sd_statfs_spin); spin_lock(&sdp->sd_statfs_spin);
...@@ -320,7 +257,7 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, ...@@ -320,7 +257,7 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
m_sc->sc_free += l_sc->sc_free; m_sc->sc_free += l_sc->sc_free;
m_sc->sc_dinodes += l_sc->sc_dinodes; m_sc->sc_dinodes += l_sc->sc_dinodes;
memset(l_sc, 0, sizeof(struct gfs2_statfs_change)); memset(l_sc, 0, sizeof(struct gfs2_statfs_change));
memset(l_bh->b_data + sizeof(struct gfs2_dinode), memset(sdp->sd_sc_bh->b_data + sizeof(struct gfs2_dinode),
0, sizeof(struct gfs2_statfs_change)); 0, sizeof(struct gfs2_statfs_change));
gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode)); gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode));
spin_unlock(&sdp->sd_statfs_spin); spin_unlock(&sdp->sd_statfs_spin);
...@@ -330,11 +267,10 @@ int gfs2_statfs_sync(struct super_block *sb, int type) ...@@ -330,11 +267,10 @@ int gfs2_statfs_sync(struct super_block *sb, int type)
{ {
struct gfs2_sbd *sdp = sb->s_fs_info; struct gfs2_sbd *sdp = sb->s_fs_info;
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
struct gfs2_holder gh; struct gfs2_holder gh;
struct buffer_head *m_bh, *l_bh; struct buffer_head *m_bh;
int error; int error;
error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE,
...@@ -355,21 +291,15 @@ int gfs2_statfs_sync(struct super_block *sb, int type) ...@@ -355,21 +291,15 @@ int gfs2_statfs_sync(struct super_block *sb, int type)
} }
spin_unlock(&sdp->sd_statfs_spin); spin_unlock(&sdp->sd_statfs_spin);
error = gfs2_meta_inode_buffer(l_ip, &l_bh);
if (error)
goto out_bh;
error = gfs2_trans_begin(sdp, 2 * RES_DINODE, 0); error = gfs2_trans_begin(sdp, 2 * RES_DINODE, 0);
if (error) if (error)
goto out_bh2; goto out_bh;
update_statfs(sdp, m_bh, l_bh); update_statfs(sdp, m_bh);
sdp->sd_statfs_force_sync = 0; sdp->sd_statfs_force_sync = 0;
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out_bh2:
brelse(l_bh);
out_bh: out_bh:
brelse(m_bh); brelse(m_bh);
out_unlock: out_unlock:
...@@ -675,6 +605,7 @@ static void gfs2_put_super(struct super_block *sb) ...@@ -675,6 +605,7 @@ static void gfs2_put_super(struct super_block *sb)
gfs2_glock_dq_uninit(&sdp->sd_journal_gh); gfs2_glock_dq_uninit(&sdp->sd_journal_gh);
if (gfs2_holder_initialized(&sdp->sd_jinode_gh)) if (gfs2_holder_initialized(&sdp->sd_jinode_gh))
gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); gfs2_glock_dq_uninit(&sdp->sd_jinode_gh);
brelse(sdp->sd_sc_bh);
gfs2_glock_dq_uninit(&sdp->sd_sc_gh); gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
gfs2_glock_dq_uninit(&sdp->sd_qc_gh); gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
free_local_statfs_inodes(sdp); free_local_statfs_inodes(sdp);
...@@ -1016,7 +947,7 @@ static int gfs2_drop_inode(struct inode *inode) ...@@ -1016,7 +947,7 @@ static int gfs2_drop_inode(struct inode *inode)
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
if (!gfs2_queue_delete_work(gl, 0)) if (!gfs2_queue_delete_work(gl, 0))
gfs2_glock_queue_put(gl); gfs2_glock_queue_put(gl);
return false; return 0;
} }
return generic_drop_inode(inode); return generic_drop_inode(inode);
......
...@@ -43,8 +43,7 @@ extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, ...@@ -43,8 +43,7 @@ extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc,
const void *buf); const void *buf);
extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc,
void *buf); void *buf);
extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh);
struct buffer_head *l_bh);
extern int gfs2_statfs_sync(struct super_block *sb, int type); extern int gfs2_statfs_sync(struct super_block *sb, int type);
extern void gfs2_freeze_func(struct work_struct *work); extern void gfs2_freeze_func(struct work_struct *work);
......
...@@ -278,6 +278,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) ...@@ -278,6 +278,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
goto skip_recovery; goto skip_recovery;
} }
sdp->sd_jdesc->jd_inode = inode; sdp->sd_jdesc->jd_inode = inode;
d_mark_dontcache(inode);
/* /*
* Now wait until recovery is complete. * Now wait until recovery is complete.
...@@ -295,7 +296,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) ...@@ -295,7 +296,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
fs_warn(sdp, "Journal recovery complete for jid %d.\n", fs_warn(sdp, "Journal recovery complete for jid %d.\n",
sdp->sd_lockstruct.ls_jid); sdp->sd_lockstruct.ls_jid);
else else
fs_warn(sdp, "Journal recovery skipped for %d until next " fs_warn(sdp, "Journal recovery skipped for jid %d until next "
"mount.\n", sdp->sd_lockstruct.ls_jid); "mount.\n", sdp->sd_lockstruct.ls_jid);
fs_warn(sdp, "Glock dequeues delayed: %lu\n", sdp->sd_glock_dqs_held); fs_warn(sdp, "Glock dequeues delayed: %lu\n", sdp->sd_glock_dqs_held);
sdp->sd_glock_dqs_held = 0; sdp->sd_glock_dqs_held = 0;
......
...@@ -218,6 +218,11 @@ static inline bool gfs2_withdrawing(struct gfs2_sbd *sdp) ...@@ -218,6 +218,11 @@ static inline bool gfs2_withdrawing(struct gfs2_sbd *sdp)
!test_bit(SDF_WITHDRAWN, &sdp->sd_flags); !test_bit(SDF_WITHDRAWN, &sdp->sd_flags);
} }
static inline bool gfs2_withdraw_in_prog(struct gfs2_sbd *sdp)
{
return test_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags);
}
#define gfs2_tune_get(sdp, field) \ #define gfs2_tune_get(sdp, field) \
gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field) gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment