Commit 9518ae6e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gfs2-for-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

Pull gfs2 updates from Andreas Gruenbacher:

 - Properly fix the glock shrinker this time: it broke in commit "gfs2:
   Make glock lru list scanning safer" and commit "gfs2: fix glock
   shrinker ref issues" wasn't actually enough to fix it

 - On unmount, keep glocks around long enough that no more dlm callbacks
   can occur on them

 - Some more folio conversion patches from Matthew Wilcox

 - Lots of other smaller fixes and cleanups

* tag 'gfs2-for-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (27 commits)
  gfs2: make timeout values more explicit
  gfs2: Convert gfs2_aspace_writepage() to use a folio
  gfs2: Add a migrate_folio operation for journalled files
  gfs2: Simplify gfs2_read_super
  gfs2: Convert gfs2_page_mkwrite() to use a folio
  gfs2: gfs2_freeze_unlock cleanup
  gfs2: Remove and replace gfs2_glock_queue_work
  gfs2: do_xmote fixes
  gfs2: finish_xmote cleanup
  gfs2: Unlock fewer glocks on unmount
  gfs2: Fix potential glock use-after-free on unmount
  gfs2: Remove ill-placed consistency check
  gfs2: Fix lru_count accounting
  gfs2: Fix "Make glock lru list scanning safer"
  Revert "gfs2: fix glock shrinker ref issues"
  gfs2: Fix "ignore unlock failures after withdraw"
  gfs2: Get rid of unnecessary test_and_set_bit
  gfs2: Don't set GLF_LOCK in gfs2_dispose_glock_lru
  gfs2: Replace gfs2_glock_queue_put with gfs2_glock_put_async
  gfs2: Get rid of gfs2_glock_queue_put in signal_our_withdraw
  ...
parents 6fffab66 c1c53c26
...@@ -116,8 +116,7 @@ static int gfs2_write_jdata_folio(struct folio *folio, ...@@ -116,8 +116,7 @@ static int gfs2_write_jdata_folio(struct folio *folio,
* @folio: The folio to write * @folio: The folio to write
* @wbc: The writeback control * @wbc: The writeback control
* *
* This is shared between writepage and writepages and implements the * Implements the core of write back. If a transaction is required then
* core of the writepage operation. If a transaction is required then
* the checked flag will have been set and the transaction will have * the checked flag will have been set and the transaction will have
* already been started before this is called. * already been started before this is called.
*/ */
...@@ -755,6 +754,7 @@ static const struct address_space_operations gfs2_jdata_aops = { ...@@ -755,6 +754,7 @@ static const struct address_space_operations gfs2_jdata_aops = {
.readahead = gfs2_readahead, .readahead = gfs2_readahead,
.dirty_folio = jdata_dirty_folio, .dirty_folio = jdata_dirty_folio,
.bmap = gfs2_bmap, .bmap = gfs2_bmap,
.migrate_folio = buffer_migrate_folio,
.invalidate_folio = gfs2_invalidate_folio, .invalidate_folio = gfs2_invalidate_folio,
.release_folio = gfs2_release_folio, .release_folio = gfs2_release_folio,
.is_partially_uptodate = block_is_partially_uptodate, .is_partially_uptodate = block_is_partially_uptodate,
......
...@@ -1827,7 +1827,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) ...@@ -1827,7 +1827,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
gfs2_assert_withdraw(sdp, bh); gfs2_assert_withdraw(sdp, bh);
if (gfs2_assert_withdraw(sdp, if (gfs2_assert_withdraw(sdp,
prev_bnr != bh->b_blocknr)) { prev_bnr != bh->b_blocknr)) {
fs_emerg(sdp, "inode %llu, block:%llu, i_h:%u," fs_emerg(sdp, "inode %llu, block:%llu, i_h:%u, "
"s_h:%u, mp_h:%u\n", "s_h:%u, mp_h:%u\n",
(unsigned long long)ip->i_no_addr, (unsigned long long)ip->i_no_addr,
prev_bnr, ip->i_height, strip_h, mp_h); prev_bnr, ip->i_height, strip_h, mp_h);
......
...@@ -562,15 +562,18 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, ...@@ -562,15 +562,18 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
int ret = 0; int ret = 0;
ret = gfs2_dirent_offset(GFS2_SB(inode), buf); ret = gfs2_dirent_offset(GFS2_SB(inode), buf);
if (ret < 0) if (ret < 0) {
goto consist_inode; gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
offset = ret; offset = ret;
prev = NULL; prev = NULL;
dent = buf + offset; dent = buf + offset;
size = be16_to_cpu(dent->de_rec_len); size = be16_to_cpu(dent->de_rec_len);
if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) {
goto consist_inode; gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
do { do {
ret = scan(dent, name, opaque); ret = scan(dent, name, opaque);
if (ret) if (ret)
...@@ -582,8 +585,10 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, ...@@ -582,8 +585,10 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
dent = buf + offset; dent = buf + offset;
size = be16_to_cpu(dent->de_rec_len); size = be16_to_cpu(dent->de_rec_len);
if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size,
len, 0)) len, 0)) {
goto consist_inode; gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
} while(1); } while(1);
switch(ret) { switch(ret) {
...@@ -597,10 +602,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf, ...@@ -597,10 +602,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
BUG_ON(ret > 0); BUG_ON(ret > 0);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
consist_inode:
gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
} }
static int dirent_check_reclen(struct gfs2_inode *dip, static int dirent_check_reclen(struct gfs2_inode *dip,
...@@ -609,14 +610,16 @@ static int dirent_check_reclen(struct gfs2_inode *dip, ...@@ -609,14 +610,16 @@ static int dirent_check_reclen(struct gfs2_inode *dip,
const void *ptr = d; const void *ptr = d;
u16 rec_len = be16_to_cpu(d->de_rec_len); u16 rec_len = be16_to_cpu(d->de_rec_len);
if (unlikely(rec_len < sizeof(struct gfs2_dirent))) if (unlikely(rec_len < sizeof(struct gfs2_dirent))) {
goto broken; gfs2_consist_inode(dip);
return -EIO;
}
ptr += rec_len; ptr += rec_len;
if (ptr < end_p) if (ptr < end_p)
return rec_len; return rec_len;
if (ptr == end_p) if (ptr == end_p)
return -ENOENT; return -ENOENT;
broken:
gfs2_consist_inode(dip); gfs2_consist_inode(dip);
return -EIO; return -EIO;
} }
......
...@@ -376,23 +376,23 @@ static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size) ...@@ -376,23 +376,23 @@ static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size)
} }
/** /**
* gfs2_allocate_page_backing - Allocate blocks for a write fault * gfs2_allocate_folio_backing - Allocate blocks for a write fault
* @page: The (locked) page to allocate backing for * @folio: The (locked) folio to allocate backing for
* @length: Size of the allocation * @length: Size of the allocation
* *
* We try to allocate all the blocks required for the page in one go. This * We try to allocate all the blocks required for the folio in one go. This
* might fail for various reasons, so we keep trying until all the blocks to * might fail for various reasons, so we keep trying until all the blocks to
* back this page are allocated. If some of the blocks are already allocated, * back this folio are allocated. If some of the blocks are already allocated,
* that is ok too. * that is ok too.
*/ */
static int gfs2_allocate_page_backing(struct page *page, unsigned int length) static int gfs2_allocate_folio_backing(struct folio *folio, size_t length)
{ {
u64 pos = page_offset(page); u64 pos = folio_pos(folio);
do { do {
struct iomap iomap = { }; struct iomap iomap = { };
if (gfs2_iomap_alloc(page->mapping->host, pos, length, &iomap)) if (gfs2_iomap_alloc(folio->mapping->host, pos, length, &iomap))
return -EIO; return -EIO;
if (length < iomap.length) if (length < iomap.length)
...@@ -414,16 +414,16 @@ static int gfs2_allocate_page_backing(struct page *page, unsigned int length) ...@@ -414,16 +414,16 @@ static int gfs2_allocate_page_backing(struct page *page, unsigned int length)
static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
{ {
struct page *page = vmf->page; struct folio *folio = page_folio(vmf->page);
struct inode *inode = file_inode(vmf->vma->vm_file); struct inode *inode = file_inode(vmf->vma->vm_file);
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_alloc_parms ap = {}; struct gfs2_alloc_parms ap = {};
u64 offset = page_offset(page); u64 pos = folio_pos(folio);
unsigned int data_blocks, ind_blocks, rblocks; unsigned int data_blocks, ind_blocks, rblocks;
vm_fault_t ret = VM_FAULT_LOCKED; vm_fault_t ret = VM_FAULT_LOCKED;
struct gfs2_holder gh; struct gfs2_holder gh;
unsigned int length; size_t length;
loff_t size; loff_t size;
int err; int err;
...@@ -436,23 +436,23 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) ...@@ -436,23 +436,23 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
goto out_uninit; goto out_uninit;
} }
/* Check page index against inode size */ /* Check folio index against inode size */
size = i_size_read(inode); size = i_size_read(inode);
if (offset >= size) { if (pos >= size) {
ret = VM_FAULT_SIGBUS; ret = VM_FAULT_SIGBUS;
goto out_unlock; goto out_unlock;
} }
/* Update file times before taking page lock */ /* Update file times before taking folio lock */
file_update_time(vmf->vma->vm_file); file_update_time(vmf->vma->vm_file);
/* page is wholly or partially inside EOF */ /* folio is wholly or partially inside EOF */
if (size - offset < PAGE_SIZE) if (size - pos < folio_size(folio))
length = size - offset; length = size - pos;
else else
length = PAGE_SIZE; length = folio_size(folio);
gfs2_size_hint(vmf->vma->vm_file, offset, length); gfs2_size_hint(vmf->vma->vm_file, pos, length);
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); set_bit(GLF_DIRTY, &ip->i_gl->gl_flags);
set_bit(GIF_SW_PAGED, &ip->i_flags); set_bit(GIF_SW_PAGED, &ip->i_flags);
...@@ -463,11 +463,12 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) ...@@ -463,11 +463,12 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
*/ */
if (!gfs2_is_stuffed(ip) && if (!gfs2_is_stuffed(ip) &&
!gfs2_write_alloc_required(ip, offset, length)) { !gfs2_write_alloc_required(ip, pos, length)) {
lock_page(page); folio_lock(folio);
if (!PageUptodate(page) || page->mapping != inode->i_mapping) { if (!folio_test_uptodate(folio) ||
folio->mapping != inode->i_mapping) {
ret = VM_FAULT_NOPAGE; ret = VM_FAULT_NOPAGE;
unlock_page(page); folio_unlock(folio);
} }
goto out_unlock; goto out_unlock;
} }
...@@ -504,7 +505,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) ...@@ -504,7 +505,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
goto out_trans_fail; goto out_trans_fail;
} }
/* Unstuff, if required, and allocate backing blocks for page */ /* Unstuff, if required, and allocate backing blocks for folio */
if (gfs2_is_stuffed(ip)) { if (gfs2_is_stuffed(ip)) {
err = gfs2_unstuff_dinode(ip); err = gfs2_unstuff_dinode(ip);
if (err) { if (err) {
...@@ -513,22 +514,22 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) ...@@ -513,22 +514,22 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
} }
} }
lock_page(page); folio_lock(folio);
/* If truncated, we must retry the operation, we may have raced /* If truncated, we must retry the operation, we may have raced
* with the glock demotion code. * with the glock demotion code.
*/ */
if (!PageUptodate(page) || page->mapping != inode->i_mapping) { if (!folio_test_uptodate(folio) || folio->mapping != inode->i_mapping) {
ret = VM_FAULT_NOPAGE; ret = VM_FAULT_NOPAGE;
goto out_page_locked; goto out_page_locked;
} }
err = gfs2_allocate_page_backing(page, length); err = gfs2_allocate_folio_backing(folio, length);
if (err) if (err)
ret = vmf_fs_error(err); ret = vmf_fs_error(err);
out_page_locked: out_page_locked:
if (ret != VM_FAULT_LOCKED) if (ret != VM_FAULT_LOCKED)
unlock_page(page); folio_unlock(folio);
out_trans_end: out_trans_end:
gfs2_trans_end(sdp); gfs2_trans_end(sdp);
out_trans_fail: out_trans_fail:
...@@ -540,8 +541,8 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) ...@@ -540,8 +541,8 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
out_uninit: out_uninit:
gfs2_holder_uninit(&gh); gfs2_holder_uninit(&gh);
if (ret == VM_FAULT_LOCKED) { if (ret == VM_FAULT_LOCKED) {
set_page_dirty(page); folio_mark_dirty(folio);
wait_for_stable_page(page); folio_wait_stable(folio);
} }
sb_end_pagefault(inode->i_sb); sb_end_pagefault(inode->i_sb);
return ret; return ret;
......
This diff is collapsed.
...@@ -172,7 +172,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, ...@@ -172,7 +172,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
int create, struct gfs2_glock **glp); int create, struct gfs2_glock **glp);
struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl); struct gfs2_glock *gfs2_glock_hold(struct gfs2_glock *gl);
void gfs2_glock_put(struct gfs2_glock *gl); void gfs2_glock_put(struct gfs2_glock *gl);
void gfs2_glock_queue_put(struct gfs2_glock *gl); void gfs2_glock_put_async(struct gfs2_glock *gl);
void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, void __gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
u16 flags, struct gfs2_holder *gh, u16 flags, struct gfs2_holder *gh,
...@@ -252,6 +252,7 @@ void gfs2_gl_dq_holders(struct gfs2_sbd *sdp); ...@@ -252,6 +252,7 @@ void gfs2_gl_dq_holders(struct gfs2_sbd *sdp);
void gfs2_glock_thaw(struct gfs2_sbd *sdp); void gfs2_glock_thaw(struct gfs2_sbd *sdp);
void gfs2_glock_add_to_lru(struct gfs2_glock *gl); void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
void gfs2_glock_free(struct gfs2_glock *gl); void gfs2_glock_free(struct gfs2_glock *gl);
void gfs2_glock_free_later(struct gfs2_glock *gl);
int __init gfs2_glock_init(void); int __init gfs2_glock_init(void);
void gfs2_glock_exit(void); void gfs2_glock_exit(void);
......
...@@ -82,6 +82,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync, ...@@ -82,6 +82,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count)); GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
spin_unlock(&sdp->sd_ail_lock); spin_unlock(&sdp->sd_ail_lock);
gfs2_log_unlock(sdp); gfs2_log_unlock(sdp);
if (gfs2_withdrawing(sdp))
gfs2_withdraw(sdp);
} }
...@@ -409,10 +412,14 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -409,10 +412,14 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
struct inode *inode = &ip->i_inode; struct inode *inode = &ip->i_inode;
bool is_new = inode->i_state & I_NEW; bool is_new = inode->i_state & I_NEW;
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) {
goto corrupt; gfs2_consist_inode(ip);
if (unlikely(!is_new && inode_wrong_type(inode, mode))) return -EIO;
goto corrupt; }
if (unlikely(!is_new && inode_wrong_type(inode, mode))) {
gfs2_consist_inode(ip);
return -EIO;
}
ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
inode->i_mode = mode; inode->i_mode = mode;
if (is_new) { if (is_new) {
...@@ -449,26 +456,28 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ...@@ -449,26 +456,28 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
/* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */ /* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */
gfs2_set_inode_flags(inode); gfs2_set_inode_flags(inode);
height = be16_to_cpu(str->di_height); height = be16_to_cpu(str->di_height);
if (unlikely(height > sdp->sd_max_height)) if (unlikely(height > sdp->sd_max_height)) {
goto corrupt; gfs2_consist_inode(ip);
return -EIO;
}
ip->i_height = (u8)height; ip->i_height = (u8)height;
depth = be16_to_cpu(str->di_depth); depth = be16_to_cpu(str->di_depth);
if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) {
goto corrupt; gfs2_consist_inode(ip);
return -EIO;
}
ip->i_depth = (u8)depth; ip->i_depth = (u8)depth;
ip->i_entries = be32_to_cpu(str->di_entries); ip->i_entries = be32_to_cpu(str->di_entries);
if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) {
goto corrupt; gfs2_consist_inode(ip);
return -EIO;
}
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
gfs2_set_aops(inode); gfs2_set_aops(inode);
return 0; return 0;
corrupt:
gfs2_consist_inode(ip);
return -EIO;
} }
/** /**
......
...@@ -838,6 +838,7 @@ struct gfs2_sbd { ...@@ -838,6 +838,7 @@ struct gfs2_sbd {
/* For quiescing the filesystem */ /* For quiescing the filesystem */
struct gfs2_holder sd_freeze_gh; struct gfs2_holder sd_freeze_gh;
struct mutex sd_freeze_mutex; struct mutex sd_freeze_mutex;
struct list_head sd_dead_glocks;
char sd_fsname[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2]; char sd_fsname[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
char sd_table_name[GFS2_FSNAME_LEN]; char sd_table_name[GFS2_FSNAME_LEN];
......
...@@ -121,6 +121,11 @@ static void gdlm_ast(void *arg) ...@@ -121,6 +121,11 @@ static void gdlm_ast(void *arg)
struct gfs2_glock *gl = arg; struct gfs2_glock *gl = arg;
unsigned ret = gl->gl_state; unsigned ret = gl->gl_state;
/* If the glock is dead, we only react to a dlm_unlock() reply. */
if (__lockref_is_dead(&gl->gl_lockref) &&
gl->gl_lksb.sb_status != -DLM_EUNLOCK)
return;
gfs2_update_reply_times(gl); gfs2_update_reply_times(gl);
BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED); BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
...@@ -171,6 +176,9 @@ static void gdlm_bast(void *arg, int mode) ...@@ -171,6 +176,9 @@ static void gdlm_bast(void *arg, int mode)
{ {
struct gfs2_glock *gl = arg; struct gfs2_glock *gl = arg;
if (__lockref_is_dead(&gl->gl_lockref))
return;
switch (mode) { switch (mode) {
case DLM_LOCK_EX: case DLM_LOCK_EX:
gfs2_glock_cb(gl, LM_ST_UNLOCKED); gfs2_glock_cb(gl, LM_ST_UNLOCKED);
...@@ -291,8 +299,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl) ...@@ -291,8 +299,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
struct lm_lockstruct *ls = &sdp->sd_lockstruct; struct lm_lockstruct *ls = &sdp->sd_lockstruct;
int error; int error;
if (gl->gl_lksb.sb_lkid == 0) BUG_ON(!__lockref_is_dead(&gl->gl_lockref));
goto out_free;
if (gl->gl_lksb.sb_lkid == 0) {
gfs2_glock_free(gl);
return;
}
clear_bit(GLF_BLOCKING, &gl->gl_flags); clear_bit(GLF_BLOCKING, &gl->gl_flags);
gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
...@@ -300,13 +312,23 @@ static void gdlm_put_lock(struct gfs2_glock *gl) ...@@ -300,13 +312,23 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
gfs2_update_request_times(gl); gfs2_update_request_times(gl);
/* don't want to call dlm if we've unmounted the lock protocol */ /* don't want to call dlm if we've unmounted the lock protocol */
if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
goto out_free; gfs2_glock_free(gl);
/* don't want to skip dlm_unlock writing the lvb when lock has one */ return;
}
/*
* When the lockspace is released, all remaining glocks will be
* unlocked automatically. This is more efficient than unlocking them
* individually, but when the lock is held in DLM_LOCK_EX or
* DLM_LOCK_PW mode, the lock value block (LVB) will be lost.
*/
if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
!gl->gl_lksb.sb_lvbptr) (!gl->gl_lksb.sb_lvbptr || gl->gl_state != LM_ST_EXCLUSIVE)) {
goto out_free; gfs2_glock_free_later(gl);
return;
}
again: again:
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK, error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
...@@ -321,10 +343,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl) ...@@ -321,10 +343,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
gl->gl_name.ln_type, gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number, error); (unsigned long long)gl->gl_name.ln_number, error);
} }
return;
out_free:
gfs2_glock_free(gl);
} }
static void gdlm_cancel(struct gfs2_glock *gl) static void gdlm_cancel(struct gfs2_glock *gl)
......
...@@ -786,7 +786,7 @@ void gfs2_glock_remove_revoke(struct gfs2_glock *gl) ...@@ -786,7 +786,7 @@ void gfs2_glock_remove_revoke(struct gfs2_glock *gl)
{ {
if (atomic_dec_return(&gl->gl_revokes) == 0) { if (atomic_dec_return(&gl->gl_revokes) == 0) {
clear_bit(GLF_LFLUSH, &gl->gl_flags); clear_bit(GLF_LFLUSH, &gl->gl_flags);
gfs2_glock_queue_put(gl); gfs2_glock_put_async(gl);
} }
} }
...@@ -1108,7 +1108,8 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) ...@@ -1108,7 +1108,8 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
lops_before_commit(sdp, tr); lops_before_commit(sdp, tr);
if (gfs2_withdrawing_or_withdrawn(sdp)) if (gfs2_withdrawing_or_withdrawn(sdp))
goto out_withdraw; goto out_withdraw;
gfs2_log_submit_bio(&sdp->sd_jdesc->jd_log_bio, REQ_OP_WRITE); if (sdp->sd_jdesc)
gfs2_log_submit_bio(&sdp->sd_jdesc->jd_log_bio, REQ_OP_WRITE);
if (gfs2_withdrawing_or_withdrawn(sdp)) if (gfs2_withdrawing_or_withdrawn(sdp))
goto out_withdraw; goto out_withdraw;
......
...@@ -32,14 +32,14 @@ ...@@ -32,14 +32,14 @@
static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc) static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc)
{ {
struct folio *folio = page_folio(page);
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
int nr_underway = 0; int nr_underway = 0;
blk_opf_t write_flags = REQ_META | REQ_PRIO | wbc_to_write_flags(wbc); blk_opf_t write_flags = REQ_META | REQ_PRIO | wbc_to_write_flags(wbc);
BUG_ON(!PageLocked(page)); BUG_ON(!folio_test_locked(folio));
BUG_ON(!page_has_buffers(page));
head = page_buffers(page); head = folio_buffers(folio);
bh = head; bh = head;
do { do {
...@@ -55,7 +55,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb ...@@ -55,7 +55,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
if (wbc->sync_mode != WB_SYNC_NONE) { if (wbc->sync_mode != WB_SYNC_NONE) {
lock_buffer(bh); lock_buffer(bh);
} else if (!trylock_buffer(bh)) { } else if (!trylock_buffer(bh)) {
redirty_page_for_writepage(wbc, page); folio_redirty_for_writepage(wbc, folio);
continue; continue;
} }
if (test_clear_buffer_dirty(bh)) { if (test_clear_buffer_dirty(bh)) {
...@@ -69,8 +69,8 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb ...@@ -69,8 +69,8 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
* The page and its buffers are protected by PageWriteback(), so we can * The page and its buffers are protected by PageWriteback(), so we can
* drop the bh refcounts early. * drop the bh refcounts early.
*/ */
BUG_ON(PageWriteback(page)); BUG_ON(folio_test_writeback(folio));
set_page_writeback(page); folio_start_writeback(folio);
do { do {
struct buffer_head *next = bh->b_this_page; struct buffer_head *next = bh->b_this_page;
...@@ -80,10 +80,10 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb ...@@ -80,10 +80,10 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
} }
bh = next; bh = next;
} while (bh != head); } while (bh != head);
unlock_page(page); folio_unlock(folio);
if (nr_underway == 0) if (nr_underway == 0)
end_page_writeback(page); folio_end_writeback(folio);
return 0; return 0;
} }
......
...@@ -136,6 +136,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) ...@@ -136,6 +136,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
atomic_set(&sdp->sd_log_in_flight, 0); atomic_set(&sdp->sd_log_in_flight, 0);
init_waitqueue_head(&sdp->sd_log_flush_wait); init_waitqueue_head(&sdp->sd_log_flush_wait);
mutex_init(&sdp->sd_freeze_mutex); mutex_init(&sdp->sd_freeze_mutex);
INIT_LIST_HEAD(&sdp->sd_dead_glocks);
return sdp; return sdp;
...@@ -184,22 +185,10 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent) ...@@ -184,22 +185,10 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)
return 0; return 0;
} }
static void end_bio_io_page(struct bio *bio) static void gfs2_sb_in(struct gfs2_sbd *sdp, const struct gfs2_sb *str)
{
struct page *page = bio->bi_private;
if (!bio->bi_status)
SetPageUptodate(page);
else
pr_warn("error %d reading superblock\n", bio->bi_status);
unlock_page(page);
}
static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf)
{ {
struct gfs2_sb_host *sb = &sdp->sd_sb; struct gfs2_sb_host *sb = &sdp->sd_sb;
struct super_block *s = sdp->sd_vfs; struct super_block *s = sdp->sd_vfs;
const struct gfs2_sb *str = buf;
sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic); sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
sb->sb_type = be32_to_cpu(str->sb_header.mh_type); sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
...@@ -239,34 +228,26 @@ static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf) ...@@ -239,34 +228,26 @@ static void gfs2_sb_in(struct gfs2_sbd *sdp, const void *buf)
static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)
{ {
struct super_block *sb = sdp->sd_vfs; struct super_block *sb = sdp->sd_vfs;
struct gfs2_sb *p;
struct page *page; struct page *page;
struct bio *bio; struct bio_vec bvec;
struct bio bio;
int err;
page = alloc_page(GFP_NOFS); page = alloc_page(GFP_KERNEL);
if (unlikely(!page)) if (unlikely(!page))
return -ENOMEM; return -ENOMEM;
ClearPageUptodate(page); bio_init(&bio, sb->s_bdev, &bvec, 1, REQ_OP_READ | REQ_META);
ClearPageDirty(page); bio.bi_iter.bi_sector = sector * (sb->s_blocksize >> 9);
lock_page(page); __bio_add_page(&bio, page, PAGE_SIZE, 0);
bio = bio_alloc(sb->s_bdev, 1, REQ_OP_READ | REQ_META, GFP_NOFS);
bio->bi_iter.bi_sector = sector * (sb->s_blocksize >> 9);
__bio_add_page(bio, page, PAGE_SIZE, 0);
bio->bi_end_io = end_bio_io_page; err = submit_bio_wait(&bio);
bio->bi_private = page; if (err) {
submit_bio(bio); pr_warn("error %d reading superblock\n", err);
wait_on_page_locked(page);
bio_put(bio);
if (!PageUptodate(page)) {
__free_page(page); __free_page(page);
return -EIO; return err;
} }
p = kmap(page); gfs2_sb_in(sdp, page_address(page));
gfs2_sb_in(sdp, p);
kunmap(page);
__free_page(page); __free_page(page);
return gfs2_check_sb(sdp, silent); return gfs2_check_sb(sdp, silent);
} }
...@@ -1288,7 +1269,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -1288,7 +1269,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
error = gfs2_make_fs_rw(sdp); error = gfs2_make_fs_rw(sdp);
if (error) { if (error) {
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
gfs2_destroy_threads(sdp); gfs2_destroy_threads(sdp);
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;
......
...@@ -814,11 +814,11 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) ...@@ -814,11 +814,11 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
bi = rgd->rd_bits + (length - 1); bi = rgd->rd_bits + (length - 1);
if ((bi->bi_start + bi->bi_bytes) * GFS2_NBBY != rgd->rd_data) { if ((bi->bi_start + bi->bi_bytes) * GFS2_NBBY != rgd->rd_data) {
gfs2_lm(sdp, gfs2_lm(sdp,
"ri_addr = %llu\n" "ri_addr=%llu "
"ri_length = %u\n" "ri_length=%u "
"ri_data0 = %llu\n" "ri_data0=%llu "
"ri_data = %u\n" "ri_data=%u "
"ri_bitbytes = %u\n" "ri_bitbytes=%u "
"start=%u len=%u offset=%u\n", "start=%u len=%u offset=%u\n",
(unsigned long long)rgd->rd_addr, (unsigned long long)rgd->rd_addr,
rgd->rd_length, rgd->rd_length,
......
...@@ -67,9 +67,13 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp) ...@@ -67,9 +67,13 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp)
sdp->sd_journals = 0; sdp->sd_journals = 0;
spin_unlock(&sdp->sd_jindex_spin); spin_unlock(&sdp->sd_jindex_spin);
down_write(&sdp->sd_log_flush_lock);
sdp->sd_jdesc = NULL; sdp->sd_jdesc = NULL;
up_write(&sdp->sd_log_flush_lock);
while (!list_empty(&list)) { while (!list_empty(&list)) {
jd = list_first_entry(&list, struct gfs2_jdesc, jd_list); jd = list_first_entry(&list, struct gfs2_jdesc, jd_list);
BUG_ON(jd->jd_log_bio);
gfs2_free_journal_extents(jd); gfs2_free_journal_extents(jd);
list_del(&jd->jd_list); list_del(&jd->jd_list);
iput(jd->jd_inode); iput(jd->jd_inode);
...@@ -354,7 +358,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp) ...@@ -354,7 +358,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
list_add(&lfcc->list, &list); list_add(&lfcc->list, &list);
} }
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE, error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_EXCLUSIVE,
LM_FLAG_NOEXP | GL_NOPID, LM_FLAG_NOEXP | GL_NOPID,
...@@ -378,7 +382,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp) ...@@ -378,7 +382,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
if (!error) if (!error)
goto out; /* success */ goto out; /* success */
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
relock_shared: relock_shared:
error2 = gfs2_freeze_lock_shared(sdp); error2 = gfs2_freeze_lock_shared(sdp);
...@@ -617,7 +621,7 @@ static void gfs2_put_super(struct super_block *sb) ...@@ -617,7 +621,7 @@ static void gfs2_put_super(struct super_block *sb)
/* Release stuff */ /* Release stuff */
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
iput(sdp->sd_jindex); iput(sdp->sd_jindex);
iput(sdp->sd_statfs_inode); iput(sdp->sd_statfs_inode);
...@@ -646,10 +650,7 @@ static void gfs2_put_super(struct super_block *sb) ...@@ -646,10 +650,7 @@ static void gfs2_put_super(struct super_block *sb)
gfs2_gl_hash_clear(sdp); gfs2_gl_hash_clear(sdp);
truncate_inode_pages_final(&sdp->sd_aspace); truncate_inode_pages_final(&sdp->sd_aspace);
gfs2_delete_debugfs_file(sdp); gfs2_delete_debugfs_file(sdp);
/* Unmount the locking protocol */
gfs2_lm_unmount(sdp);
/* At this point, we're through participating in the lockspace */
gfs2_sys_fs_del(sdp); gfs2_sys_fs_del(sdp);
free_sbd(sdp); free_sbd(sdp);
} }
...@@ -706,7 +707,7 @@ void gfs2_freeze_func(struct work_struct *work) ...@@ -706,7 +707,7 @@ void gfs2_freeze_func(struct work_struct *work)
if (error) if (error)
goto freeze_failed; goto freeze_failed;
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
set_bit(SDF_FROZEN, &sdp->sd_flags); set_bit(SDF_FROZEN, &sdp->sd_flags);
error = gfs2_do_thaw(sdp); error = gfs2_do_thaw(sdp);
...@@ -811,7 +812,7 @@ static int gfs2_thaw_super(struct super_block *sb, enum freeze_holder who) ...@@ -811,7 +812,7 @@ static int gfs2_thaw_super(struct super_block *sb, enum freeze_holder who)
} }
atomic_inc(&sb->s_active); atomic_inc(&sb->s_active);
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
error = gfs2_do_thaw(sdp); error = gfs2_do_thaw(sdp);
...@@ -832,7 +833,7 @@ void gfs2_thaw_freeze_initiator(struct super_block *sb) ...@@ -832,7 +833,7 @@ void gfs2_thaw_freeze_initiator(struct super_block *sb)
if (!test_bit(SDF_FREEZE_INITIATOR, &sdp->sd_flags)) if (!test_bit(SDF_FREEZE_INITIATOR, &sdp->sd_flags))
goto out; goto out;
gfs2_freeze_unlock(&sdp->sd_freeze_gh); gfs2_freeze_unlock(sdp);
out: out:
mutex_unlock(&sdp->sd_freeze_mutex); mutex_unlock(&sdp->sd_freeze_mutex);
...@@ -1045,7 +1046,7 @@ static int gfs2_drop_inode(struct inode *inode) ...@@ -1045,7 +1046,7 @@ static int gfs2_drop_inode(struct inode *inode)
gfs2_glock_hold(gl); gfs2_glock_hold(gl);
if (!gfs2_queue_try_to_evict(gl)) if (!gfs2_queue_try_to_evict(gl))
gfs2_glock_queue_put(gl); gfs2_glock_put_async(gl);
return 0; return 0;
} }
...@@ -1251,7 +1252,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip) ...@@ -1251,7 +1252,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
static void gfs2_glock_put_eventually(struct gfs2_glock *gl) static void gfs2_glock_put_eventually(struct gfs2_glock *gl)
{ {
if (current->flags & PF_MEMALLOC) if (current->flags & PF_MEMALLOC)
gfs2_glock_queue_put(gl); gfs2_glock_put_async(gl);
else else
gfs2_glock_put(gl); gfs2_glock_put(gl);
} }
...@@ -1261,7 +1262,6 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode) ...@@ -1261,7 +1262,6 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode)
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_holder *gh = &ip->i_iopen_gh; struct gfs2_holder *gh = &ip->i_iopen_gh;
long timeout = 5 * HZ;
int error; int error;
gh->gh_flags |= GL_NOCACHE; gh->gh_flags |= GL_NOCACHE;
...@@ -1292,10 +1292,10 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode) ...@@ -1292,10 +1292,10 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode)
if (error) if (error)
return false; return false;
timeout = wait_event_interruptible_timeout(sdp->sd_async_glock_wait, wait_event_interruptible_timeout(sdp->sd_async_glock_wait,
!test_bit(HIF_WAIT, &gh->gh_iflags) || !test_bit(HIF_WAIT, &gh->gh_iflags) ||
test_bit(GLF_DEMOTE, &ip->i_gl->gl_flags), test_bit(GLF_DEMOTE, &ip->i_gl->gl_flags),
timeout); 5 * HZ);
if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) { if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) {
gfs2_glock_dq(gh); gfs2_glock_dq(gh);
return false; return false;
......
...@@ -88,7 +88,7 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf) ...@@ -88,7 +88,7 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)
"Withdraw In Prog: %d\n" "Withdraw In Prog: %d\n"
"Remote Withdraw: %d\n" "Remote Withdraw: %d\n"
"Withdraw Recovery: %d\n" "Withdraw Recovery: %d\n"
"Deactivating: %d\n" "Killing: %d\n"
"sd_log_error: %d\n" "sd_log_error: %d\n"
"sd_log_flush_lock: %d\n" "sd_log_flush_lock: %d\n"
"sd_log_num_revoke: %u\n" "sd_log_num_revoke: %u\n"
...@@ -336,7 +336,7 @@ static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len ...@@ -336,7 +336,7 @@ static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len
return -EINVAL; return -EINVAL;
if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags)) if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags))
fs_info(sdp, "demote interface used\n"); fs_info(sdp, "demote interface used\n");
rv = gfs2_glock_get(sdp, glnum, glops, 0, &gl); rv = gfs2_glock_get(sdp, glnum, glops, NO_CREATE, &gl);
if (rv) if (rv)
return rv; return rv;
gfs2_glock_cb(gl, glmode); gfs2_glock_cb(gl, glmode);
......
...@@ -109,10 +109,10 @@ int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp) ...@@ -109,10 +109,10 @@ int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp)
return error; return error;
} }
void gfs2_freeze_unlock(struct gfs2_holder *freeze_gh) void gfs2_freeze_unlock(struct gfs2_sbd *sdp)
{ {
if (gfs2_holder_initialized(freeze_gh)) if (gfs2_holder_initialized(&sdp->sd_freeze_gh))
gfs2_glock_dq_uninit(freeze_gh); gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
} }
static void signal_our_withdraw(struct gfs2_sbd *sdp) static void signal_our_withdraw(struct gfs2_sbd *sdp)
...@@ -255,7 +255,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) ...@@ -255,7 +255,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)
gfs2_glock_nq(&sdp->sd_live_gh); gfs2_glock_nq(&sdp->sd_live_gh);
} }
gfs2_glock_queue_put(live_gl); /* drop extra reference we acquired */ gfs2_glock_put(live_gl); /* drop extra reference we acquired */
clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags); clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
/* /*
...@@ -350,7 +350,6 @@ int gfs2_withdraw(struct gfs2_sbd *sdp) ...@@ -350,7 +350,6 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
fs_err(sdp, "telling LM to unmount\n"); fs_err(sdp, "telling LM to unmount\n");
lm->lm_unmount(sdp); lm->lm_unmount(sdp);
} }
set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
fs_err(sdp, "File system withdrawn\n"); fs_err(sdp, "File system withdrawn\n");
dump_stack(); dump_stack();
clear_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags); clear_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags);
...@@ -376,8 +375,8 @@ void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, ...@@ -376,8 +375,8 @@ void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
return; return;
fs_err(sdp, fs_err(sdp,
"fatal: assertion \"%s\" failed\n" "fatal: assertion \"%s\" failed - "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
assertion, function, file, line); assertion, function, file, line);
/* /*
...@@ -407,7 +406,8 @@ void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, ...@@ -407,7 +406,8 @@ void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
return; return;
if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW)
fs_warn(sdp, "warning: assertion \"%s\" failed at function = %s, file = %s, line = %u\n", fs_warn(sdp, "warning: assertion \"%s\" failed - "
"function = %s, file = %s, line = %u\n",
assertion, function, file, line); assertion, function, file, line);
if (sdp->sd_args.ar_debug) if (sdp->sd_args.ar_debug)
...@@ -416,10 +416,10 @@ void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, ...@@ -416,10 +416,10 @@ void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
dump_stack(); dump_stack();
if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC) if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
panic("GFS2: fsid=%s: warning: assertion \"%s\" failed\n" panic("GFS2: fsid=%s: warning: assertion \"%s\" failed - "
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
sdp->sd_fsname, assertion, sdp->sd_fsname, assertion,
sdp->sd_fsname, function, file, line); function, file, line);
sdp->sd_last_warning = jiffies; sdp->sd_last_warning = jiffies;
} }
...@@ -432,7 +432,8 @@ void gfs2_consist_i(struct gfs2_sbd *sdp, const char *function, ...@@ -432,7 +432,8 @@ void gfs2_consist_i(struct gfs2_sbd *sdp, const char *function,
char *file, unsigned int line) char *file, unsigned int line)
{ {
gfs2_lm(sdp, gfs2_lm(sdp,
"fatal: filesystem consistency error - function = %s, file = %s, line = %u\n", "fatal: filesystem consistency error - "
"function = %s, file = %s, line = %u\n",
function, file, line); function, file, line);
gfs2_withdraw(sdp); gfs2_withdraw(sdp);
} }
...@@ -447,9 +448,9 @@ void gfs2_consist_inode_i(struct gfs2_inode *ip, ...@@ -447,9 +448,9 @@ void gfs2_consist_inode_i(struct gfs2_inode *ip,
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
gfs2_lm(sdp, gfs2_lm(sdp,
"fatal: filesystem consistency error\n" "fatal: filesystem consistency error - "
" inode = %llu %llu\n" "inode = %llu %llu, "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
(unsigned long long)ip->i_no_formal_ino, (unsigned long long)ip->i_no_formal_ino,
(unsigned long long)ip->i_no_addr, (unsigned long long)ip->i_no_addr,
function, file, line); function, file, line);
...@@ -470,9 +471,9 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, ...@@ -470,9 +471,9 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname); sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
gfs2_rgrp_dump(NULL, rgd, fs_id_buf); gfs2_rgrp_dump(NULL, rgd, fs_id_buf);
gfs2_lm(sdp, gfs2_lm(sdp,
"fatal: filesystem consistency error\n" "fatal: filesystem consistency error - "
" RG = %llu\n" "RG = %llu, "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
(unsigned long long)rgd->rd_addr, (unsigned long long)rgd->rd_addr,
function, file, line); function, file, line);
gfs2_dump_glock(NULL, rgd->rd_gl, 1); gfs2_dump_glock(NULL, rgd->rd_gl, 1);
...@@ -486,16 +487,16 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, ...@@ -486,16 +487,16 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
*/ */
int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
const char *type, const char *function, char *file, const char *function, char *file,
unsigned int line) unsigned int line)
{ {
int me; int me;
gfs2_lm(sdp, gfs2_lm(sdp,
"fatal: invalid metadata block\n" "fatal: invalid metadata block - "
" bh = %llu (%s)\n" "bh = %llu (bad magic number), "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr, type, (unsigned long long)bh->b_blocknr,
function, file, line); function, file, line);
me = gfs2_withdraw(sdp); me = gfs2_withdraw(sdp);
return (me) ? -1 : -2; return (me) ? -1 : -2;
...@@ -514,9 +515,9 @@ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, ...@@ -514,9 +515,9 @@ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
int me; int me;
gfs2_lm(sdp, gfs2_lm(sdp,
"fatal: invalid metadata block\n" "fatal: invalid metadata block - "
" bh = %llu (type: exp=%u, found=%u)\n" "bh = %llu (type: exp=%u, found=%u), "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr, type, t, (unsigned long long)bh->b_blocknr, type, t,
function, file, line); function, file, line);
me = gfs2_withdraw(sdp); me = gfs2_withdraw(sdp);
...@@ -533,8 +534,8 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file, ...@@ -533,8 +534,8 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
unsigned int line) unsigned int line)
{ {
gfs2_lm(sdp, gfs2_lm(sdp,
"fatal: I/O error\n" "fatal: I/O error - "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
function, file, line); function, file, line);
return gfs2_withdraw(sdp); return gfs2_withdraw(sdp);
} }
...@@ -551,9 +552,9 @@ void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh, ...@@ -551,9 +552,9 @@ void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
if (gfs2_withdrawing_or_withdrawn(sdp)) if (gfs2_withdrawing_or_withdrawn(sdp))
return; return;
fs_err(sdp, "fatal: I/O error\n" fs_err(sdp, "fatal: I/O error - "
" block = %llu\n" "block = %llu, "
" function = %s, file = %s, line = %u\n", "function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr, function, file, line); (unsigned long long)bh->b_blocknr, function, file, line);
if (withdraw) if (withdraw)
gfs2_withdraw(sdp); gfs2_withdraw(sdp);
......
...@@ -92,7 +92,7 @@ gfs2_consist_rgrpd_i((rgd), __func__, __FILE__, __LINE__) ...@@ -92,7 +92,7 @@ gfs2_consist_rgrpd_i((rgd), __func__, __FILE__, __LINE__)
int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
const char *type, const char *function, const char *function,
char *file, unsigned int line); char *file, unsigned int line);
static inline int gfs2_meta_check(struct gfs2_sbd *sdp, static inline int gfs2_meta_check(struct gfs2_sbd *sdp,
...@@ -123,7 +123,7 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp, ...@@ -123,7 +123,7 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp,
u32 magic = be32_to_cpu(mh->mh_magic); u32 magic = be32_to_cpu(mh->mh_magic);
u16 t = be32_to_cpu(mh->mh_type); u16 t = be32_to_cpu(mh->mh_type);
if (unlikely(magic != GFS2_MAGIC)) if (unlikely(magic != GFS2_MAGIC))
return gfs2_meta_check_ii(sdp, bh, "magic number", function, return gfs2_meta_check_ii(sdp, bh, function,
file, line); file, line);
if (unlikely(t != type)) if (unlikely(t != type))
return gfs2_metatype_check_ii(sdp, bh, type, t, function, return gfs2_metatype_check_ii(sdp, bh, type, t, function,
...@@ -150,7 +150,7 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, ...@@ -150,7 +150,7 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,
int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd, int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
bool verbose); bool verbose);
int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp); int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp);
void gfs2_freeze_unlock(struct gfs2_holder *freeze_gh); void gfs2_freeze_unlock(struct gfs2_sbd *sdp);
#define gfs2_io_error(sdp) \ #define gfs2_io_error(sdp) \
gfs2_io_error_i((sdp), __func__, __FILE__, __LINE__) gfs2_io_error_i((sdp), __func__, __FILE__, __LINE__)
......
...@@ -96,30 +96,34 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh, ...@@ -96,30 +96,34 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh,
return -EIO; return -EIO;
for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) { for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) {
if (!GFS2_EA_REC_LEN(ea)) if (!GFS2_EA_REC_LEN(ea)) {
goto fail; gfs2_consist_inode(ip);
return -EIO;
}
if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <= if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <=
bh->b_data + bh->b_size)) bh->b_data + bh->b_size)) {
goto fail; gfs2_consist_inode(ip);
if (!gfs2_eatype_valid(sdp, ea->ea_type)) return -EIO;
goto fail; }
if (!gfs2_eatype_valid(sdp, ea->ea_type)) {
gfs2_consist_inode(ip);
return -EIO;
}
error = ea_call(ip, bh, ea, prev, data); error = ea_call(ip, bh, ea, prev, data);
if (error) if (error)
return error; return error;
if (GFS2_EA_IS_LAST(ea)) { if (GFS2_EA_IS_LAST(ea)) {
if ((char *)GFS2_EA2NEXT(ea) != if ((char *)GFS2_EA2NEXT(ea) !=
bh->b_data + bh->b_size) bh->b_data + bh->b_size) {
goto fail; gfs2_consist_inode(ip);
return -EIO;
}
break; break;
} }
} }
return error; return error;
fail:
gfs2_consist_inode(ip);
return -EIO;
} }
static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
......
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