// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*/
do { if (!buffer_mapped(bh)) continue; /* * If it's a fully non-blocking write attempt and we cannot * lock the buffer then redirty the page. Note that this can * potentially cause a busy-wait loop from flusher thread and kswapd * activity, but those code paths have their own higher-level * throttling.
*/ if (wbc->sync_mode != WB_SYNC_NONE) {
lock_buffer(bh);
} elseif (!trylock_buffer(bh)) {
folio_redirty_for_writepage(wbc, folio); continue;
} if (test_clear_buffer_dirty(bh)) {
mark_buffer_async_write(bh);
} else {
unlock_buffer(bh);
}
} while ((bh = bh->b_this_page) != head);
/* * The folio and its buffers are protected from truncation by * the writeback flag, so we can drop the bh refcounts early.
*/
BUG_ON(folio_test_writeback(folio));
folio_start_writeback(folio);
do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) {
submit_bh(REQ_OP_WRITE | write_flags, bh);
nr_underway++;
}
bh = next;
} while (bh != head);
folio_unlock(folio);
if (nr_underway == 0)
folio_end_writeback(folio);
}
/** * gfs2_getbuf - Get a buffer with a given address space * @gl: the glock * @blkno: the block number (filesystem scope) * @create: 1 if the buffer should be created * * Returns: the buffer
*/
while (bh_offset(bh) < fi.offset)
bh = bh->b_this_page; do { struct buffer_head *next = bh->b_this_page;
len -= bh->b_size;
bh->b_end_io(bh, !bio->bi_status);
bh = next;
} while (bh && len);
}
bio_put(bio);
}
/* * Submit several consecutive buffer head I/O requests as a single bio I/O * request. (See submit_bh_wbc.)
*/ staticvoid gfs2_submit_bhs(blk_opf_t opf, struct buffer_head *bhs[], int num)
{ while (num > 0) { struct buffer_head *bh = *bhs; struct bio *bio;
/** * gfs2_meta_read - Read a block from disk * @gl: The glock covering the block * @blkno: The block number * @flags: flags * @rahead: Do read-ahead * @bhp: the place where the buffer is returned (NULL on failure) * * Returns: errno
*/
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, int rahead, struct buffer_head **bhp)
{ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct buffer_head *bh, *bhs[2]; int num = 0;
/** * gfs2_ail1_wipe - remove deleted/freed buffers from the ail1 list * @sdp: superblock * @bstart: starting block address of buffers to remove * @blen: length of buffers to be removed * * This function is called from gfs2_journal wipe, whose job is to remove * buffers, corresponding to deleted blocks, from the journal. If we find any * bufdata elements on the system ail1 list, they haven't been written to * the journal yet. So we remove them.
*/ staticvoid gfs2_ail1_wipe(struct gfs2_sbd *sdp, u64 bstart, u32 blen)
{ struct gfs2_trans *tr, *s; struct gfs2_bufdata *bd, *bs; struct buffer_head *bh;
u64 end = bstart + blen;
/** * gfs2_journal_wipe - make inode's buffers so they aren't dirty/pinned anymore * @ip: the inode who owns the buffers * @bstart: the first buffer in the run * @blen: the number of buffers in the run *
*/
/* This can only happen during incomplete inode creation. */ if (!ip->i_gl) return;
gfs2_ail1_wipe(sdp, bstart, blen); while (blen) {
ty = REMOVE_META;
bh = gfs2_getbuf(ip->i_gl, bstart, NO_CREATE); if (!bh && gfs2_is_jdata(ip)) {
bh = gfs2_getjdatabuf(ip, bstart);
ty = REMOVE_JDATA;
} if (bh) {
lock_buffer(bh);
gfs2_log_lock(sdp);
spin_lock(&sdp->sd_ail_lock);
gfs2_remove_from_journal(bh, ty);
spin_unlock(&sdp->sd_ail_lock);
gfs2_log_unlock(sdp);
unlock_buffer(bh);
brelse(bh);
}
bstart++;
blen--;
}
}
/** * gfs2_meta_buffer - Get a metadata buffer * @ip: The GFS2 inode * @mtype: The block type (GFS2_METATYPE_*) * @num: The block number (device relative) of the buffer * @bhp: the buffer is returned here * * Returns: errno
*/
int gfs2_meta_buffer(struct gfs2_inode *ip, u32 mtype, u64 num, struct buffer_head **bhp)
{ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_glock *gl = ip->i_gl; struct buffer_head *bh; int ret = 0; int rahead = 0;
if (num == ip->i_no_addr)
rahead = ip->i_rahead;
ret = gfs2_meta_read(gl, num, DIO_WAIT, rahead, &bh); if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) {
brelse(bh);
ret = -EIO;
} else {
*bhp = bh;
} return ret;
}
/** * gfs2_meta_ra - start readahead on an extent of a file * @gl: the glock the blocks belong to * @dblock: the starting disk block * @extlen: the number of blocks in the extent * * returns: the first buffer in the extent
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.