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,
* @folio: The folio to write
* @wbc: The writeback control
*
* This is shared between writepage and writepages and implements the
* core of the writepage operation. If a transaction is required then
* Implements the core of write back. If a transaction is required then
* the checked flag will have been set and the transaction will have
* already been started before this is called.
*/
......@@ -755,6 +754,7 @@ static const struct address_space_operations gfs2_jdata_aops = {
.readahead = gfs2_readahead,
.dirty_folio = jdata_dirty_folio,
.bmap = gfs2_bmap,
.migrate_folio = buffer_migrate_folio,
.invalidate_folio = gfs2_invalidate_folio,
.release_folio = gfs2_release_folio,
.is_partially_uptodate = block_is_partially_uptodate,
......
......@@ -1827,7 +1827,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
gfs2_assert_withdraw(sdp, bh);
if (gfs2_assert_withdraw(sdp,
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",
(unsigned long long)ip->i_no_addr,
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,
int ret = 0;
ret = gfs2_dirent_offset(GFS2_SB(inode), buf);
if (ret < 0)
goto consist_inode;
if (ret < 0) {
gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
offset = ret;
prev = NULL;
dent = buf + offset;
size = be16_to_cpu(dent->de_rec_len);
if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1))
goto consist_inode;
if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size, len, 1)) {
gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
do {
ret = scan(dent, name, opaque);
if (ret)
......@@ -582,8 +585,10 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
dent = buf + offset;
size = be16_to_cpu(dent->de_rec_len);
if (gfs2_check_dirent(GFS2_SB(inode), dent, offset, size,
len, 0))
goto consist_inode;
len, 0)) {
gfs2_consist_inode(GFS2_I(inode));
return ERR_PTR(-EIO);
}
} while(1);
switch(ret) {
......@@ -597,10 +602,6 @@ static struct gfs2_dirent *gfs2_dirent_scan(struct inode *inode, void *buf,
BUG_ON(ret > 0);
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,
......@@ -609,14 +610,16 @@ static int dirent_check_reclen(struct gfs2_inode *dip,
const void *ptr = d;
u16 rec_len = be16_to_cpu(d->de_rec_len);
if (unlikely(rec_len < sizeof(struct gfs2_dirent)))
goto broken;
if (unlikely(rec_len < sizeof(struct gfs2_dirent))) {
gfs2_consist_inode(dip);
return -EIO;
}
ptr += rec_len;
if (ptr < end_p)
return rec_len;
if (ptr == end_p)
return -ENOENT;
broken:
gfs2_consist_inode(dip);
return -EIO;
}
......
......@@ -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
* @page: The (locked) page to allocate backing for
* gfs2_allocate_folio_backing - Allocate blocks for a write fault
* @folio: The (locked) folio to allocate backing for
* @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
* 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.
*/
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 {
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;
if (length < iomap.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)
{
struct page *page = vmf->page;
struct folio *folio = page_folio(vmf->page);
struct inode *inode = file_inode(vmf->vma->vm_file);
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_alloc_parms ap = {};
u64 offset = page_offset(page);
u64 pos = folio_pos(folio);
unsigned int data_blocks, ind_blocks, rblocks;
vm_fault_t ret = VM_FAULT_LOCKED;
struct gfs2_holder gh;
unsigned int length;
size_t length;
loff_t size;
int err;
......@@ -436,23 +436,23 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
goto out_uninit;
}
/* Check page index against inode size */
/* Check folio index against inode size */
size = i_size_read(inode);
if (offset >= size) {
if (pos >= size) {
ret = VM_FAULT_SIGBUS;
goto out_unlock;
}
/* Update file times before taking page lock */
/* Update file times before taking folio lock */
file_update_time(vmf->vma->vm_file);
/* page is wholly or partially inside EOF */
if (size - offset < PAGE_SIZE)
length = size - offset;
/* folio is wholly or partially inside EOF */
if (size - pos < folio_size(folio))
length = size - pos;
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(GIF_SW_PAGED, &ip->i_flags);
......@@ -463,11 +463,12 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
*/
if (!gfs2_is_stuffed(ip) &&
!gfs2_write_alloc_required(ip, offset, length)) {
lock_page(page);
if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
!gfs2_write_alloc_required(ip, pos, length)) {
folio_lock(folio);
if (!folio_test_uptodate(folio) ||
folio->mapping != inode->i_mapping) {
ret = VM_FAULT_NOPAGE;
unlock_page(page);
folio_unlock(folio);
}
goto out_unlock;
}
......@@ -504,7 +505,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
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)) {
err = gfs2_unstuff_dinode(ip);
if (err) {
......@@ -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
* 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;
goto out_page_locked;
}
err = gfs2_allocate_page_backing(page, length);
err = gfs2_allocate_folio_backing(folio, length);
if (err)
ret = vmf_fs_error(err);
out_page_locked:
if (ret != VM_FAULT_LOCKED)
unlock_page(page);
folio_unlock(folio);
out_trans_end:
gfs2_trans_end(sdp);
out_trans_fail:
......@@ -540,8 +541,8 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf)
out_uninit:
gfs2_holder_uninit(&gh);
if (ret == VM_FAULT_LOCKED) {
set_page_dirty(page);
wait_for_stable_page(page);
folio_mark_dirty(folio);
folio_wait_stable(folio);
}
sb_end_pagefault(inode->i_sb);
return ret;
......
This diff is collapsed.
......@@ -172,7 +172,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
int create, struct gfs2_glock **glp);
struct gfs2_glock *gfs2_glock_hold(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,
u16 flags, struct gfs2_holder *gh,
......@@ -252,6 +252,7 @@ void gfs2_gl_dq_holders(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_free(struct gfs2_glock *gl);
void gfs2_glock_free_later(struct gfs2_glock *gl);
int __init gfs2_glock_init(void);
void gfs2_glock_exit(void);
......
......@@ -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));
spin_unlock(&sdp->sd_ail_lock);
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)
struct inode *inode = &ip->i_inode;
bool is_new = inode->i_state & I_NEW;
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
goto corrupt;
if (unlikely(!is_new && inode_wrong_type(inode, mode)))
goto corrupt;
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) {
gfs2_consist_inode(ip);
return -EIO;
}
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);
inode->i_mode = mode;
if (is_new) {
......@@ -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() */
gfs2_set_inode_flags(inode);
height = be16_to_cpu(str->di_height);
if (unlikely(height > sdp->sd_max_height))
goto corrupt;
if (unlikely(height > sdp->sd_max_height)) {
gfs2_consist_inode(ip);
return -EIO;
}
ip->i_height = (u8)height;
depth = be16_to_cpu(str->di_depth);
if (unlikely(depth > GFS2_DIR_MAX_DEPTH))
goto corrupt;
if (unlikely(depth > GFS2_DIR_MAX_DEPTH)) {
gfs2_consist_inode(ip);
return -EIO;
}
ip->i_depth = (u8)depth;
ip->i_entries = be32_to_cpu(str->di_entries);
if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip))
goto corrupt;
if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) {
gfs2_consist_inode(ip);
return -EIO;
}
if (S_ISREG(inode->i_mode))
gfs2_set_aops(inode);
return 0;
corrupt:
gfs2_consist_inode(ip);
return -EIO;
}
/**
......
......@@ -838,6 +838,7 @@ struct gfs2_sbd {
/* For quiescing the filesystem */
struct gfs2_holder sd_freeze_gh;
struct mutex sd_freeze_mutex;
struct list_head sd_dead_glocks;
char sd_fsname[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
char sd_table_name[GFS2_FSNAME_LEN];
......
......@@ -121,6 +121,11 @@ static void gdlm_ast(void *arg)
struct gfs2_glock *gl = arg;
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);
BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
......@@ -171,6 +176,9 @@ static void gdlm_bast(void *arg, int mode)
{
struct gfs2_glock *gl = arg;
if (__lockref_is_dead(&gl->gl_lockref))
return;
switch (mode) {
case DLM_LOCK_EX:
gfs2_glock_cb(gl, LM_ST_UNLOCKED);
......@@ -291,8 +299,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
int error;
if (gl->gl_lksb.sb_lkid == 0)
goto out_free;
BUG_ON(!__lockref_is_dead(&gl->gl_lockref));
if (gl->gl_lksb.sb_lkid == 0) {
gfs2_glock_free(gl);
return;
}
clear_bit(GLF_BLOCKING, &gl->gl_flags);
gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
......@@ -300,13 +312,23 @@ static void gdlm_put_lock(struct gfs2_glock *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))
goto out_free;
/* don't want to skip dlm_unlock writing the lvb when lock has one */
if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
gfs2_glock_free(gl);
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) &&
!gl->gl_lksb.sb_lvbptr)
goto out_free;
(!gl->gl_lksb.sb_lvbptr || gl->gl_state != LM_ST_EXCLUSIVE)) {
gfs2_glock_free_later(gl);
return;
}
again:
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)
gl->gl_name.ln_type,
(unsigned long long)gl->gl_name.ln_number, error);
}
return;
out_free:
gfs2_glock_free(gl);
}
static void gdlm_cancel(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) {
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)
lops_before_commit(sdp, tr);
if (gfs2_withdrawing_or_withdrawn(sdp))
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))
goto out_withdraw;
......
......@@ -32,14 +32,14 @@
static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc)
{
struct folio *folio = page_folio(page);
struct buffer_head *bh, *head;
int nr_underway = 0;
blk_opf_t write_flags = REQ_META | REQ_PRIO | wbc_to_write_flags(wbc);
BUG_ON(!PageLocked(page));
BUG_ON(!page_has_buffers(page));
BUG_ON(!folio_test_locked(folio));
head = page_buffers(page);
head = folio_buffers(folio);
bh = head;
do {
......@@ -55,7 +55,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
if (wbc->sync_mode != WB_SYNC_NONE) {
lock_buffer(bh);
} else if (!trylock_buffer(bh)) {
redirty_page_for_writepage(wbc, page);
folio_redirty_for_writepage(wbc, folio);
continue;
}
if (test_clear_buffer_dirty(bh)) {
......@@ -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
* drop the bh refcounts early.
*/
BUG_ON(PageWriteback(page));
set_page_writeback(page);
BUG_ON(folio_test_writeback(folio));
folio_start_writeback(folio);
do {
struct buffer_head *next = bh->b_this_page;
......@@ -80,10 +80,10 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
}
bh = next;
} while (bh != head);
unlock_page(page);
folio_unlock(folio);
if (nr_underway == 0)
end_page_writeback(page);
folio_end_writeback(folio);
return 0;
}
......
......@@ -136,6 +136,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
atomic_set(&sdp->sd_log_in_flight, 0);
init_waitqueue_head(&sdp->sd_log_flush_wait);
mutex_init(&sdp->sd_freeze_mutex);
INIT_LIST_HEAD(&sdp->sd_dead_glocks);
return sdp;
......@@ -184,22 +185,10 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)
return 0;
}
static void end_bio_io_page(struct bio *bio)
{
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)
static void gfs2_sb_in(struct gfs2_sbd *sdp, const struct gfs2_sb *str)
{
struct gfs2_sb_host *sb = &sdp->sd_sb;
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_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)
static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)
{
struct super_block *sb = sdp->sd_vfs;
struct gfs2_sb *p;
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))
return -ENOMEM;
ClearPageUptodate(page);
ClearPageDirty(page);
lock_page(page);
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_init(&bio, sb->s_bdev, &bvec, 1, REQ_OP_READ | REQ_META);
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;
bio->bi_private = page;
submit_bio(bio);
wait_on_page_locked(page);
bio_put(bio);
if (!PageUptodate(page)) {
err = submit_bio_wait(&bio);
if (err) {
pr_warn("error %d reading superblock\n", err);
__free_page(page);
return -EIO;
return err;
}
p = kmap(page);
gfs2_sb_in(sdp, p);
kunmap(page);
gfs2_sb_in(sdp, page_address(page));
__free_page(page);
return gfs2_check_sb(sdp, silent);
}
......@@ -1288,7 +1269,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
error = gfs2_make_fs_rw(sdp);
if (error) {
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
gfs2_freeze_unlock(sdp);
gfs2_destroy_threads(sdp);
fs_err(sdp, "can't make FS RW: %d\n", error);
goto fail_per_node;
......
......@@ -814,11 +814,11 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
bi = rgd->rd_bits + (length - 1);
if ((bi->bi_start + bi->bi_bytes) * GFS2_NBBY != rgd->rd_data) {
gfs2_lm(sdp,
"ri_addr = %llu\n"
"ri_length = %u\n"
"ri_data0 = %llu\n"
"ri_data = %u\n"
"ri_bitbytes = %u\n"
"ri_addr=%llu "
"ri_length=%u "
"ri_data0=%llu "
"ri_data=%u "
"ri_bitbytes=%u "
"start=%u len=%u offset=%u\n",
(unsigned long long)rgd->rd_addr,
rgd->rd_length,
......
......@@ -67,9 +67,13 @@ void gfs2_jindex_free(struct gfs2_sbd *sdp)
sdp->sd_journals = 0;
spin_unlock(&sdp->sd_jindex_spin);
down_write(&sdp->sd_log_flush_lock);
sdp->sd_jdesc = NULL;
up_write(&sdp->sd_log_flush_lock);
while (!list_empty(&list)) {
jd = list_first_entry(&list, struct gfs2_jdesc, jd_list);
BUG_ON(jd->jd_log_bio);
gfs2_free_journal_extents(jd);
list_del(&jd->jd_list);
iput(jd->jd_inode);
......@@ -354,7 +358,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
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,
LM_FLAG_NOEXP | GL_NOPID,
......@@ -378,7 +382,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
if (!error)
goto out; /* success */
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
gfs2_freeze_unlock(sdp);
relock_shared:
error2 = gfs2_freeze_lock_shared(sdp);
......@@ -617,7 +621,7 @@ static void gfs2_put_super(struct super_block *sb)
/* Release stuff */
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
gfs2_freeze_unlock(sdp);
iput(sdp->sd_jindex);
iput(sdp->sd_statfs_inode);
......@@ -646,10 +650,7 @@ static void gfs2_put_super(struct super_block *sb)
gfs2_gl_hash_clear(sdp);
truncate_inode_pages_final(&sdp->sd_aspace);
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);
free_sbd(sdp);
}
......@@ -706,7 +707,7 @@ void gfs2_freeze_func(struct work_struct *work)
if (error)
goto freeze_failed;
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
gfs2_freeze_unlock(sdp);
set_bit(SDF_FROZEN, &sdp->sd_flags);
error = gfs2_do_thaw(sdp);
......@@ -811,7 +812,7 @@ static int gfs2_thaw_super(struct super_block *sb, enum freeze_holder who)
}
atomic_inc(&sb->s_active);
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
gfs2_freeze_unlock(sdp);
error = gfs2_do_thaw(sdp);
......@@ -832,7 +833,7 @@ void gfs2_thaw_freeze_initiator(struct super_block *sb)
if (!test_bit(SDF_FREEZE_INITIATOR, &sdp->sd_flags))
goto out;
gfs2_freeze_unlock(&sdp->sd_freeze_gh);
gfs2_freeze_unlock(sdp);
out:
mutex_unlock(&sdp->sd_freeze_mutex);
......@@ -1045,7 +1046,7 @@ static int gfs2_drop_inode(struct inode *inode)
gfs2_glock_hold(gl);
if (!gfs2_queue_try_to_evict(gl))
gfs2_glock_queue_put(gl);
gfs2_glock_put_async(gl);
return 0;
}
......@@ -1251,7 +1252,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
static void gfs2_glock_put_eventually(struct gfs2_glock *gl)
{
if (current->flags & PF_MEMALLOC)
gfs2_glock_queue_put(gl);
gfs2_glock_put_async(gl);
else
gfs2_glock_put(gl);
}
......@@ -1261,7 +1262,6 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode)
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_holder *gh = &ip->i_iopen_gh;
long timeout = 5 * HZ;
int error;
gh->gh_flags |= GL_NOCACHE;
......@@ -1292,10 +1292,10 @@ static bool gfs2_upgrade_iopen_glock(struct inode *inode)
if (error)
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(GLF_DEMOTE, &ip->i_gl->gl_flags),
timeout);
5 * HZ);
if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) {
gfs2_glock_dq(gh);
return false;
......
......@@ -88,7 +88,7 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)
"Withdraw In Prog: %d\n"
"Remote Withdraw: %d\n"
"Withdraw Recovery: %d\n"
"Deactivating: %d\n"
"Killing: %d\n"
"sd_log_error: %d\n"
"sd_log_flush_lock: %d\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
return -EINVAL;
if (!test_and_set_bit(SDF_DEMOTE, &sdp->sd_flags))
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)
return rv;
gfs2_glock_cb(gl, glmode);
......
......@@ -109,10 +109,10 @@ int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp)
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))
gfs2_glock_dq_uninit(freeze_gh);
if (gfs2_holder_initialized(&sdp->sd_freeze_gh))
gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
}
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_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);
/*
......@@ -350,7 +350,6 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
fs_err(sdp, "telling LM to unmount\n");
lm->lm_unmount(sdp);
}
set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
fs_err(sdp, "File system withdrawn\n");
dump_stack();
clear_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags);
......@@ -376,8 +375,8 @@ void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
return;
fs_err(sdp,
"fatal: assertion \"%s\" failed\n"
" function = %s, file = %s, line = %u\n",
"fatal: assertion \"%s\" failed - "
"function = %s, file = %s, line = %u\n",
assertion, function, file, line);
/*
......@@ -407,7 +406,8 @@ void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
return;
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);
if (sdp->sd_args.ar_debug)
......@@ -416,10 +416,10 @@ void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
dump_stack();
if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
panic("GFS2: fsid=%s: warning: assertion \"%s\" failed\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
panic("GFS2: fsid=%s: warning: assertion \"%s\" failed - "
"function = %s, file = %s, line = %u\n",
sdp->sd_fsname, assertion,
sdp->sd_fsname, function, file, line);
function, file, line);
sdp->sd_last_warning = jiffies;
}
......@@ -432,7 +432,8 @@ void gfs2_consist_i(struct gfs2_sbd *sdp, const char *function,
char *file, unsigned int line)
{
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);
gfs2_withdraw(sdp);
}
......@@ -447,9 +448,9 @@ void gfs2_consist_inode_i(struct gfs2_inode *ip,
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
gfs2_lm(sdp,
"fatal: filesystem consistency error\n"
" inode = %llu %llu\n"
" function = %s, file = %s, line = %u\n",
"fatal: filesystem consistency error - "
"inode = %llu %llu, "
"function = %s, file = %s, line = %u\n",
(unsigned long long)ip->i_no_formal_ino,
(unsigned long long)ip->i_no_addr,
function, file, line);
......@@ -470,9 +471,9 @@ void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
gfs2_rgrp_dump(NULL, rgd, fs_id_buf);
gfs2_lm(sdp,
"fatal: filesystem consistency error\n"
" RG = %llu\n"
" function = %s, file = %s, line = %u\n",
"fatal: filesystem consistency error - "
"RG = %llu, "
"function = %s, file = %s, line = %u\n",
(unsigned long long)rgd->rd_addr,
function, file, line);
gfs2_dump_glock(NULL, rgd->rd_gl, 1);
......@@ -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,
const char *type, const char *function, char *file,
const char *function, char *file,
unsigned int line)
{
int me;
gfs2_lm(sdp,
"fatal: invalid metadata block\n"
" bh = %llu (%s)\n"
" function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr, type,
"fatal: invalid metadata block - "
"bh = %llu (bad magic number), "
"function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr,
function, file, line);
me = gfs2_withdraw(sdp);
return (me) ? -1 : -2;
......@@ -514,9 +515,9 @@ int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
int me;
gfs2_lm(sdp,
"fatal: invalid metadata block\n"
" bh = %llu (type: exp=%u, found=%u)\n"
" function = %s, file = %s, line = %u\n",
"fatal: invalid metadata block - "
"bh = %llu (type: exp=%u, found=%u), "
"function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr, type, t,
function, file, line);
me = gfs2_withdraw(sdp);
......@@ -533,8 +534,8 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
unsigned int line)
{
gfs2_lm(sdp,
"fatal: I/O error\n"
" function = %s, file = %s, line = %u\n",
"fatal: I/O error - "
"function = %s, file = %s, line = %u\n",
function, file, line);
return gfs2_withdraw(sdp);
}
......@@ -551,9 +552,9 @@ void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
if (gfs2_withdrawing_or_withdrawn(sdp))
return;
fs_err(sdp, "fatal: I/O error\n"
" block = %llu\n"
" function = %s, file = %s, line = %u\n",
fs_err(sdp, "fatal: I/O error - "
"block = %llu, "
"function = %s, file = %s, line = %u\n",
(unsigned long long)bh->b_blocknr, function, file, line);
if (withdraw)
gfs2_withdraw(sdp);
......
......@@ -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,
const char *type, const char *function,
const char *function,
char *file, unsigned int line);
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,
u32 magic = be32_to_cpu(mh->mh_magic);
u16 t = be32_to_cpu(mh->mh_type);
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);
if (unlikely(t != type))
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,
int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
bool verbose);
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) \
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,
return -EIO;
for (ea = GFS2_EA_BH2FIRST(bh);; prev = ea, ea = GFS2_EA2NEXT(ea)) {
if (!GFS2_EA_REC_LEN(ea))
goto fail;
if (!GFS2_EA_REC_LEN(ea)) {
gfs2_consist_inode(ip);
return -EIO;
}
if (!(bh->b_data <= (char *)ea && (char *)GFS2_EA2NEXT(ea) <=
bh->b_data + bh->b_size))
goto fail;
if (!gfs2_eatype_valid(sdp, ea->ea_type))
goto fail;
bh->b_data + bh->b_size)) {
gfs2_consist_inode(ip);
return -EIO;
}
if (!gfs2_eatype_valid(sdp, ea->ea_type)) {
gfs2_consist_inode(ip);
return -EIO;
}
error = ea_call(ip, bh, ea, prev, data);
if (error)
return error;
if (GFS2_EA_IS_LAST(ea)) {
if ((char *)GFS2_EA2NEXT(ea) !=
bh->b_data + bh->b_size)
goto fail;
bh->b_data + bh->b_size) {
gfs2_consist_inode(ip);
return -EIO;
}
break;
}
}
return error;
fail:
gfs2_consist_inode(ip);
return -EIO;
}
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