brintos

brintos / linux-shallow public Read only

0
0
Text · 5.2 KiB · ace2225 Raw
191 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Dummy inodes to buffer blocks for garbage collection4 *5 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.6 *7 * Written by Seiji Kihara, Amagai Yoshiji, and Ryusuke Konishi.8 * Revised by Ryusuke Konishi.9 *10 */11/*12 * This file adds the cache of on-disk blocks to be moved in garbage13 * collection.  The disk blocks are held with dummy inodes (called14 * gcinodes), and this file provides lookup function of the dummy15 * inodes and their buffer read function.16 *17 * Buffers and pages held by the dummy inodes will be released each18 * time after they are copied to a new log.  Dirty blocks made on the19 * current generation and the blocks to be moved by GC never overlap20 * because the dirty blocks make a new generation; they rather must be21 * written individually.22 */23 24#include <linux/buffer_head.h>25#include <linux/mpage.h>26#include <linux/hash.h>27#include <linux/slab.h>28#include <linux/swap.h>29#include "nilfs.h"30#include "btree.h"31#include "btnode.h"32#include "page.h"33#include "mdt.h"34#include "dat.h"35#include "ifile.h"36 37/*38 * nilfs_gccache_submit_read_data() - add data buffer and submit read request39 * @inode - gc inode40 * @blkoff - dummy offset treated as the key for the page cache41 * @pbn - physical block number of the block42 * @vbn - virtual block number of the block, 0 for non-virtual block43 * @out_bh - indirect pointer to a buffer_head struct to receive the results44 *45 * Description: nilfs_gccache_submit_read_data() registers the data buffer46 * specified by @pbn to the GC pagecache with the key @blkoff.47 * This function sets @vbn (@pbn if @vbn is zero) in b_blocknr of the buffer.48 *49 * Return Value: On success, 0 is returned. On Error, one of the following50 * negative error code is returned.51 *52 * %-EIO - I/O error.53 *54 * %-ENOMEM - Insufficient amount of memory available.55 *56 * %-ENOENT - The block specified with @pbn does not exist.57 */58int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff,59				   sector_t pbn, __u64 vbn,60				   struct buffer_head **out_bh)61{62	struct buffer_head *bh;63	int err;64 65	bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0);66	if (unlikely(!bh))67		return -ENOMEM;68 69	if (buffer_uptodate(bh))70		goto out;71 72	if (pbn == 0) {73		struct the_nilfs *nilfs = inode->i_sb->s_fs_info;74 75		err = nilfs_dat_translate(nilfs->ns_dat, vbn, &pbn);76		if (unlikely(err)) /* -EIO, -ENOMEM, -ENOENT */77			goto failed;78	}79 80	lock_buffer(bh);81	if (buffer_uptodate(bh)) {82		unlock_buffer(bh);83		goto out;84	}85 86	if (!buffer_mapped(bh))87		set_buffer_mapped(bh);88	bh->b_blocknr = pbn;89	bh->b_end_io = end_buffer_read_sync;90	get_bh(bh);91	submit_bh(REQ_OP_READ, bh);92	if (vbn)93		bh->b_blocknr = vbn;94 out:95	err = 0;96	*out_bh = bh;97 98 failed:99	folio_unlock(bh->b_folio);100	folio_put(bh->b_folio);101	if (unlikely(err))102		brelse(bh);103	return err;104}105 106/*107 * nilfs_gccache_submit_read_node() - add node buffer and submit read request108 * @inode - gc inode109 * @pbn - physical block number for the block110 * @vbn - virtual block number for the block111 * @out_bh - indirect pointer to a buffer_head struct to receive the results112 *113 * Description: nilfs_gccache_submit_read_node() registers the node buffer114 * specified by @vbn to the GC pagecache.  @pbn can be supplied by the115 * caller to avoid translation of the disk block address.116 *117 * Return Value: On success, 0 is returned. On Error, one of the following118 * negative error code is returned.119 *120 * %-EIO - I/O error.121 *122 * %-ENOMEM - Insufficient amount of memory available.123 */124int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn,125				   __u64 vbn, struct buffer_head **out_bh)126{127	struct inode *btnc_inode = NILFS_I(inode)->i_assoc_inode;128	int ret;129 130	ret = nilfs_btnode_submit_block(btnc_inode->i_mapping, vbn ? : pbn, pbn,131					REQ_OP_READ, out_bh, &pbn);132	if (ret == -EEXIST) /* internal code (cache hit) */133		ret = 0;134	return ret;135}136 137int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)138{139	wait_on_buffer(bh);140	if (!buffer_uptodate(bh)) {141		struct inode *inode = bh->b_folio->mapping->host;142 143		nilfs_err(inode->i_sb,144			  "I/O error reading %s block for GC (ino=%lu, vblocknr=%llu)",145			  buffer_nilfs_node(bh) ? "node" : "data",146			  inode->i_ino, (unsigned long long)bh->b_blocknr);147		return -EIO;148	}149	if (buffer_dirty(bh))150		return -EEXIST;151 152	if (buffer_nilfs_node(bh) && nilfs_btree_broken_node_block(bh)) {153		clear_buffer_uptodate(bh);154		return -EIO;155	}156	mark_buffer_dirty(bh);157	return 0;158}159 160int nilfs_init_gcinode(struct inode *inode)161{162	struct nilfs_inode_info *ii = NILFS_I(inode);163 164	inode->i_mode = S_IFREG;165	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);166	inode->i_mapping->a_ops = &empty_aops;167 168	ii->i_flags = 0;169	nilfs_bmap_init_gc(ii->i_bmap);170 171	return nilfs_attach_btree_node_cache(inode);172}173 174/**175 * nilfs_remove_all_gcinodes() - remove all unprocessed gc inodes176 * @nilfs: NILFS filesystem instance177 */178void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs)179{180	struct list_head *head = &nilfs->ns_gc_inodes;181	struct nilfs_inode_info *ii;182 183	while (!list_empty(head)) {184		ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);185		list_del_init(&ii->i_dirty);186		truncate_inode_pages(&ii->vfs_inode.i_data, 0);187		nilfs_btnode_cache_clear(ii->i_assoc_inode->i_mapping);188		iput(&ii->vfs_inode);189	}190}191