// SPDX-License-Identifier: GPL-2.0+ /* * Meta data file for NILFS * * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. * * Written by Ryusuke Konishi.
*/
/** * nilfs_mdt_get_block - read or create a buffer on meta data file. * @inode: inode of the meta data file * @blkoff: block offset * @create: create flag * @init_block: initializer used for newly allocated block * @out_bh: output of a pointer to the buffer_head * * nilfs_mdt_get_block() looks up the specified buffer and tries to create * a new buffer if @create is not zero. If (and only if) this function * succeeds, it stores a pointer to the retrieved buffer head in the location * pointed to by @out_bh. * * The retrieved buffer may be either an existing one or a newly allocated one. * For a newly created buffer, if the callback function argument @init_block * is non-NULL, the callback will be called with the buffer locked to format * the block. * * Return: 0 on success, or one of the following negative error codes on * failure: * * %-EIO - I/O error (including metadata corruption). * * %-ENOENT - The specified block does not exist (hole block). * * %-ENOMEM - Insufficient memory available. * * %-EROFS - Read only filesystem (for create mode).
*/ int nilfs_mdt_get_block(struct inode *inode, unsignedlong blkoff, int create, void (*init_block)(struct inode *, struct buffer_head *, void *), struct buffer_head **out_bh)
{ int ret;
/* Should be rewritten with merging nilfs_mdt_read_block() */
retry:
ret = nilfs_mdt_read_block(inode, blkoff, !create, out_bh); if (!create || ret != -ENOENT) return ret;
/** * nilfs_mdt_find_block - find and get a buffer on meta data file. * @inode: inode of the meta data file * @start: start block offset (inclusive) * @end: end block offset (inclusive) * @blkoff: block offset * @out_bh: place to store a pointer to buffer_head struct * * nilfs_mdt_find_block() looks up an existing block in range of * [@start, @end] and stores pointer to a buffer head of the block to * @out_bh, and block offset to @blkoff, respectively. @out_bh and * @blkoff are substituted only when zero is returned. * * Return: 0 on success, or one of the following negative error codes on * failure: * * %-EIO - I/O error (including metadata corruption). * * %-ENOENT - No block was found in the range. * * %-ENOMEM - Insufficient memory available.
*/ int nilfs_mdt_find_block(struct inode *inode, unsignedlong start, unsignedlong end, unsignedlong *blkoff, struct buffer_head **out_bh)
{
__u64 next; int ret;
if (unlikely(start > end)) return -ENOENT;
ret = nilfs_mdt_read_block(inode, start, true, out_bh); if (!ret) {
*blkoff = start; goto out;
} if (unlikely(ret != -ENOENT || start == ULONG_MAX)) goto out;
ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next); if (!ret) { if (next <= end) {
ret = nilfs_mdt_read_block(inode, next, true, out_bh); if (!ret)
*blkoff = next;
} else {
ret = -ENOENT;
}
}
out: return ret;
}
/** * nilfs_mdt_delete_block - make a hole on the meta data file. * @inode: inode of the meta data file * @block: block offset * * Return: 0 on success, or one of the following negative error codes on * failure: * * %-EIO - I/O error (including metadata corruption). * * %-ENOENT - Non-existent block. * * %-ENOMEM - Insufficient memory available.
*/ int nilfs_mdt_delete_block(struct inode *inode, unsignedlong block)
{ struct nilfs_inode_info *ii = NILFS_I(inode); int err;
/** * nilfs_mdt_forget_block - discard dirty state and try to remove the page * @inode: inode of the meta data file * @block: block offset * * nilfs_mdt_forget_block() clears a dirty flag of the specified buffer, and * tries to release the page including the buffer from a page cache. * * Return: 0 on success, or one of the following negative error codes on * failure: * * %-EBUSY - Page has an active buffer. * * %-ENOENT - Page cache has no page addressed by the offset.
*/ int nilfs_mdt_forget_block(struct inode *inode, unsignedlong block)
{
pgoff_t index = block >> (PAGE_SHIFT - inode->i_blkbits); struct folio *folio; struct buffer_head *bh; int ret = 0; int still_dirty;
folio = filemap_lock_folio(inode->i_mapping, index); if (IS_ERR(folio)) return -ENOENT;
if (inode && sb_rdonly(inode->i_sb)) { /* * It means that filesystem was remounted in read-only * mode because of error or metadata corruption. But we * have dirty folios that try to be flushed in background. * So, here we simply discard this dirty folio.
*/
nilfs_clear_folio_dirty(folio);
folio_unlock(folio); return -EROFS;
}
while (!list_empty(head)) {
bh = list_first_entry(head, struct buffer_head,
b_assoc_buffers);
list_del_init(&bh->b_assoc_buffers);
brelse(bh); /* drop ref-count to make it releasable */
}
}
/** * nilfs_mdt_restore_from_shadow_map - restore dirty pages and bmap state * @inode: inode of the metadata file
*/ void nilfs_mdt_restore_from_shadow_map(struct inode *inode)
{ struct nilfs_mdt_info *mi = NILFS_MDT(inode); struct nilfs_inode_info *ii = NILFS_I(inode); struct nilfs_shadow_map *shadow = mi->mi_shadow;
down_write(&mi->mi_sem);
if (mi->mi_palloc_cache)
nilfs_palloc_clear_cache(inode);
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.