brintos

brintos / linux-shallow public Read only

0
0
Text · 16.0 KiB · 2db6350 Raw
668 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Meta data file for NILFS4 *5 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.6 *7 * Written by Ryusuke Konishi.8 */9 10#include <linux/buffer_head.h>11#include <linux/mpage.h>12#include <linux/mm.h>13#include <linux/writeback.h>14#include <linux/backing-dev.h>15#include <linux/swap.h>16#include <linux/slab.h>17#include "nilfs.h"18#include "btnode.h"19#include "segment.h"20#include "page.h"21#include "mdt.h"22#include "alloc.h"		/* nilfs_palloc_destroy_cache() */23 24#include <trace/events/nilfs2.h>25 26#define NILFS_MDT_MAX_RA_BLOCKS		(16 - 1)27 28 29static int30nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block,31			   struct buffer_head *bh,32			   void (*init_block)(struct inode *,33					      struct buffer_head *, void *))34{35	struct nilfs_inode_info *ii = NILFS_I(inode);36	void *kaddr;37	int ret;38 39	/* Caller exclude read accesses using page lock */40 41	/* set_buffer_new(bh); */42	bh->b_blocknr = 0;43 44	ret = nilfs_bmap_insert(ii->i_bmap, block, (unsigned long)bh);45	if (unlikely(ret))46		return ret;47 48	set_buffer_mapped(bh);49 50	kaddr = kmap_local_page(bh->b_page);51	memset(kaddr + bh_offset(bh), 0, i_blocksize(inode));52	if (init_block)53		init_block(inode, bh, kaddr);54	flush_dcache_page(bh->b_page);55	kunmap_local(kaddr);56 57	set_buffer_uptodate(bh);58	mark_buffer_dirty(bh);59	nilfs_mdt_mark_dirty(inode);60 61	trace_nilfs2_mdt_insert_new_block(inode, inode->i_ino, block);62 63	return 0;64}65 66static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,67				  struct buffer_head **out_bh,68				  void (*init_block)(struct inode *,69						     struct buffer_head *,70						     void *))71{72	struct super_block *sb = inode->i_sb;73	struct nilfs_transaction_info ti;74	struct buffer_head *bh;75	int err;76 77	nilfs_transaction_begin(sb, &ti, 0);78 79	err = -ENOMEM;80	bh = nilfs_grab_buffer(inode, inode->i_mapping, block, 0);81	if (unlikely(!bh))82		goto failed_unlock;83 84	err = -EEXIST;85	if (buffer_uptodate(bh))86		goto failed_bh;87 88	wait_on_buffer(bh);89	if (buffer_uptodate(bh))90		goto failed_bh;91 92	err = nilfs_mdt_insert_new_block(inode, block, bh, init_block);93	if (likely(!err)) {94		get_bh(bh);95		*out_bh = bh;96	}97 98 failed_bh:99	folio_unlock(bh->b_folio);100	folio_put(bh->b_folio);101	brelse(bh);102 103 failed_unlock:104	if (likely(!err))105		err = nilfs_transaction_commit(sb);106	else107		nilfs_transaction_abort(sb);108 109	return err;110}111 112static int113nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, blk_opf_t opf,114		       struct buffer_head **out_bh)115{116	struct buffer_head *bh;117	__u64 blknum = 0;118	int ret = -ENOMEM;119 120	bh = nilfs_grab_buffer(inode, inode->i_mapping, blkoff, 0);121	if (unlikely(!bh))122		goto failed;123 124	ret = -EEXIST; /* internal code */125	if (buffer_uptodate(bh))126		goto out;127 128	if (opf & REQ_RAHEAD) {129		if (!trylock_buffer(bh)) {130			ret = -EBUSY;131			goto failed_bh;132		}133	} else /* opf == REQ_OP_READ */134		lock_buffer(bh);135 136	if (buffer_uptodate(bh)) {137		unlock_buffer(bh);138		goto out;139	}140 141	ret = nilfs_bmap_lookup(NILFS_I(inode)->i_bmap, blkoff, &blknum);142	if (unlikely(ret)) {143		unlock_buffer(bh);144		goto failed_bh;145	}146	map_bh(bh, inode->i_sb, (sector_t)blknum);147 148	bh->b_end_io = end_buffer_read_sync;149	get_bh(bh);150	submit_bh(opf, bh);151	ret = 0;152 153	trace_nilfs2_mdt_submit_block(inode, inode->i_ino, blkoff,154				      opf & REQ_OP_MASK);155 out:156	get_bh(bh);157	*out_bh = bh;158 159 failed_bh:160	folio_unlock(bh->b_folio);161	folio_put(bh->b_folio);162	brelse(bh);163 failed:164	return ret;165}166 167static int nilfs_mdt_read_block(struct inode *inode, unsigned long block,168				int readahead, struct buffer_head **out_bh)169{170	struct buffer_head *first_bh, *bh;171	unsigned long blkoff;172	int i, nr_ra_blocks = NILFS_MDT_MAX_RA_BLOCKS;173	int err;174 175	err = nilfs_mdt_submit_block(inode, block, REQ_OP_READ, &first_bh);176	if (err == -EEXIST) /* internal code */177		goto out;178 179	if (unlikely(err))180		goto failed;181 182	if (readahead) {183		blkoff = block + 1;184		for (i = 0; i < nr_ra_blocks; i++, blkoff++) {185			err = nilfs_mdt_submit_block(inode, blkoff,186						REQ_OP_READ | REQ_RAHEAD, &bh);187			if (likely(!err || err == -EEXIST))188				brelse(bh);189			else if (err != -EBUSY)190				break;191				/* abort readahead if bmap lookup failed */192			if (!buffer_locked(first_bh))193				goto out_no_wait;194		}195	}196 197	wait_on_buffer(first_bh);198 199 out_no_wait:200	err = -EIO;201	if (!buffer_uptodate(first_bh)) {202		nilfs_err(inode->i_sb,203			  "I/O error reading meta-data file (ino=%lu, block-offset=%lu)",204			  inode->i_ino, block);205		goto failed_bh;206	}207 out:208	*out_bh = first_bh;209	return 0;210 211 failed_bh:212	brelse(first_bh);213 failed:214	return err;215}216 217/**218 * nilfs_mdt_get_block - read or create a buffer on meta data file.219 * @inode: inode of the meta data file220 * @blkoff: block offset221 * @create: create flag222 * @init_block: initializer used for newly allocated block223 * @out_bh: output of a pointer to the buffer_head224 *225 * nilfs_mdt_get_block() looks up the specified buffer and tries to create226 * a new buffer if @create is not zero.  On success, the returned buffer is227 * assured to be either existing or formatted using a buffer lock on success.228 * @out_bh is substituted only when zero is returned.229 *230 * Return Value: On success, it returns 0. On error, the following negative231 * error code is returned.232 *233 * %-ENOMEM - Insufficient memory available.234 *235 * %-EIO - I/O error236 *237 * %-ENOENT - the specified block does not exist (hole block)238 *239 * %-EROFS - Read only filesystem (for create mode)240 */241int nilfs_mdt_get_block(struct inode *inode, unsigned long blkoff, int create,242			void (*init_block)(struct inode *,243					   struct buffer_head *, void *),244			struct buffer_head **out_bh)245{246	int ret;247 248	/* Should be rewritten with merging nilfs_mdt_read_block() */249 retry:250	ret = nilfs_mdt_read_block(inode, blkoff, !create, out_bh);251	if (!create || ret != -ENOENT)252		return ret;253 254	ret = nilfs_mdt_create_block(inode, blkoff, out_bh, init_block);255	if (unlikely(ret == -EEXIST)) {256		/* create = 0; */  /* limit read-create loop retries */257		goto retry;258	}259	return ret;260}261 262/**263 * nilfs_mdt_find_block - find and get a buffer on meta data file.264 * @inode: inode of the meta data file265 * @start: start block offset (inclusive)266 * @end: end block offset (inclusive)267 * @blkoff: block offset268 * @out_bh: place to store a pointer to buffer_head struct269 *270 * nilfs_mdt_find_block() looks up an existing block in range of271 * [@start, @end] and stores pointer to a buffer head of the block to272 * @out_bh, and block offset to @blkoff, respectively.  @out_bh and273 * @blkoff are substituted only when zero is returned.274 *275 * Return Value: On success, it returns 0. On error, the following negative276 * error code is returned.277 *278 * %-ENOMEM - Insufficient memory available.279 *280 * %-EIO - I/O error281 *282 * %-ENOENT - no block was found in the range283 */284int nilfs_mdt_find_block(struct inode *inode, unsigned long start,285			 unsigned long end, unsigned long *blkoff,286			 struct buffer_head **out_bh)287{288	__u64 next;289	int ret;290 291	if (unlikely(start > end))292		return -ENOENT;293 294	ret = nilfs_mdt_read_block(inode, start, true, out_bh);295	if (!ret) {296		*blkoff = start;297		goto out;298	}299	if (unlikely(ret != -ENOENT || start == ULONG_MAX))300		goto out;301 302	ret = nilfs_bmap_seek_key(NILFS_I(inode)->i_bmap, start + 1, &next);303	if (!ret) {304		if (next <= end) {305			ret = nilfs_mdt_read_block(inode, next, true, out_bh);306			if (!ret)307				*blkoff = next;308		} else {309			ret = -ENOENT;310		}311	}312out:313	return ret;314}315 316/**317 * nilfs_mdt_delete_block - make a hole on the meta data file.318 * @inode: inode of the meta data file319 * @block: block offset320 *321 * Return Value: On success, zero is returned.322 * On error, one of the following negative error code is returned.323 *324 * %-ENOMEM - Insufficient memory available.325 *326 * %-EIO - I/O error327 */328int nilfs_mdt_delete_block(struct inode *inode, unsigned long block)329{330	struct nilfs_inode_info *ii = NILFS_I(inode);331	int err;332 333	err = nilfs_bmap_delete(ii->i_bmap, block);334	if (!err || err == -ENOENT) {335		nilfs_mdt_mark_dirty(inode);336		nilfs_mdt_forget_block(inode, block);337	}338	return err;339}340 341/**342 * nilfs_mdt_forget_block - discard dirty state and try to remove the page343 * @inode: inode of the meta data file344 * @block: block offset345 *346 * nilfs_mdt_forget_block() clears a dirty flag of the specified buffer, and347 * tries to release the page including the buffer from a page cache.348 *349 * Return Value: On success, 0 is returned. On error, one of the following350 * negative error code is returned.351 *352 * %-EBUSY - page has an active buffer.353 *354 * %-ENOENT - page cache has no page addressed by the offset.355 */356int nilfs_mdt_forget_block(struct inode *inode, unsigned long block)357{358	pgoff_t index = block >> (PAGE_SHIFT - inode->i_blkbits);359	struct folio *folio;360	struct buffer_head *bh;361	int ret = 0;362	int still_dirty;363 364	folio = filemap_lock_folio(inode->i_mapping, index);365	if (IS_ERR(folio))366		return -ENOENT;367 368	folio_wait_writeback(folio);369 370	bh = folio_buffers(folio);371	if (bh) {372		unsigned long first_block = index <<373				(PAGE_SHIFT - inode->i_blkbits);374		bh = get_nth_bh(bh, block - first_block);375		nilfs_forget_buffer(bh);376	}377	still_dirty = folio_test_dirty(folio);378	folio_unlock(folio);379	folio_put(folio);380 381	if (still_dirty ||382	    invalidate_inode_pages2_range(inode->i_mapping, index, index) != 0)383		ret = -EBUSY;384	return ret;385}386 387int nilfs_mdt_fetch_dirty(struct inode *inode)388{389	struct nilfs_inode_info *ii = NILFS_I(inode);390 391	if (nilfs_bmap_test_and_clear_dirty(ii->i_bmap)) {392		set_bit(NILFS_I_DIRTY, &ii->i_state);393		return 1;394	}395	return test_bit(NILFS_I_DIRTY, &ii->i_state);396}397 398static int399nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)400{401	struct folio *folio = page_folio(page);402	struct inode *inode = folio->mapping->host;403	struct super_block *sb;404	int err = 0;405 406	if (inode && sb_rdonly(inode->i_sb)) {407		/*408		 * It means that filesystem was remounted in read-only409		 * mode because of error or metadata corruption. But we410		 * have dirty folios that try to be flushed in background.411		 * So, here we simply discard this dirty folio.412		 */413		nilfs_clear_folio_dirty(folio);414		folio_unlock(folio);415		return -EROFS;416	}417 418	folio_redirty_for_writepage(wbc, folio);419	folio_unlock(folio);420 421	if (!inode)422		return 0;423 424	sb = inode->i_sb;425 426	if (wbc->sync_mode == WB_SYNC_ALL)427		err = nilfs_construct_segment(sb);428	else if (wbc->for_reclaim)429		nilfs_flush_segment(sb, inode->i_ino);430 431	return err;432}433 434 435static const struct address_space_operations def_mdt_aops = {436	.dirty_folio		= block_dirty_folio,437	.invalidate_folio	= block_invalidate_folio,438	.writepage		= nilfs_mdt_write_page,439};440 441static const struct inode_operations def_mdt_iops;442static const struct file_operations def_mdt_fops;443 444 445int nilfs_mdt_init(struct inode *inode, gfp_t gfp_mask, size_t objsz)446{447	struct nilfs_mdt_info *mi;448 449	mi = kzalloc(max(sizeof(*mi), objsz), GFP_NOFS);450	if (!mi)451		return -ENOMEM;452 453	init_rwsem(&mi->mi_sem);454	inode->i_private = mi;455 456	inode->i_mode = S_IFREG;457	mapping_set_gfp_mask(inode->i_mapping, gfp_mask);458 459	inode->i_op = &def_mdt_iops;460	inode->i_fop = &def_mdt_fops;461	inode->i_mapping->a_ops = &def_mdt_aops;462 463	return 0;464}465 466/**467 * nilfs_mdt_clear - do cleanup for the metadata file468 * @inode: inode of the metadata file469 */470void nilfs_mdt_clear(struct inode *inode)471{472	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);473	struct nilfs_shadow_map *shadow = mdi->mi_shadow;474 475	if (mdi->mi_palloc_cache)476		nilfs_palloc_destroy_cache(inode);477 478	if (shadow) {479		struct inode *s_inode = shadow->inode;480 481		shadow->inode = NULL;482		iput(s_inode);483		mdi->mi_shadow = NULL;484	}485}486 487/**488 * nilfs_mdt_destroy - release resources used by the metadata file489 * @inode: inode of the metadata file490 */491void nilfs_mdt_destroy(struct inode *inode)492{493	struct nilfs_mdt_info *mdi = NILFS_MDT(inode);494 495	kfree(mdi->mi_bgl); /* kfree(NULL) is safe */496	kfree(mdi);497}498 499void nilfs_mdt_set_entry_size(struct inode *inode, unsigned int entry_size,500			      unsigned int header_size)501{502	struct nilfs_mdt_info *mi = NILFS_MDT(inode);503 504	mi->mi_entry_size = entry_size;505	mi->mi_entries_per_block = i_blocksize(inode) / entry_size;506	mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size);507}508 509/**510 * nilfs_mdt_setup_shadow_map - setup shadow map and bind it to metadata file511 * @inode: inode of the metadata file512 * @shadow: shadow mapping513 */514int nilfs_mdt_setup_shadow_map(struct inode *inode,515			       struct nilfs_shadow_map *shadow)516{517	struct nilfs_mdt_info *mi = NILFS_MDT(inode);518	struct inode *s_inode;519 520	INIT_LIST_HEAD(&shadow->frozen_buffers);521 522	s_inode = nilfs_iget_for_shadow(inode);523	if (IS_ERR(s_inode))524		return PTR_ERR(s_inode);525 526	shadow->inode = s_inode;527	mi->mi_shadow = shadow;528	return 0;529}530 531/**532 * nilfs_mdt_save_to_shadow_map - copy bmap and dirty pages to shadow map533 * @inode: inode of the metadata file534 */535int nilfs_mdt_save_to_shadow_map(struct inode *inode)536{537	struct nilfs_mdt_info *mi = NILFS_MDT(inode);538	struct nilfs_inode_info *ii = NILFS_I(inode);539	struct nilfs_shadow_map *shadow = mi->mi_shadow;540	struct inode *s_inode = shadow->inode;541	int ret;542 543	ret = nilfs_copy_dirty_pages(s_inode->i_mapping, inode->i_mapping);544	if (ret)545		goto out;546 547	ret = nilfs_copy_dirty_pages(NILFS_I(s_inode)->i_assoc_inode->i_mapping,548				     ii->i_assoc_inode->i_mapping);549	if (ret)550		goto out;551 552	nilfs_bmap_save(ii->i_bmap, &shadow->bmap_store);553 out:554	return ret;555}556 557int nilfs_mdt_freeze_buffer(struct inode *inode, struct buffer_head *bh)558{559	struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow;560	struct buffer_head *bh_frozen;561	struct folio *folio;562	int blkbits = inode->i_blkbits;563 564	folio = filemap_grab_folio(shadow->inode->i_mapping,565			bh->b_folio->index);566	if (IS_ERR(folio))567		return PTR_ERR(folio);568 569	bh_frozen = folio_buffers(folio);570	if (!bh_frozen)571		bh_frozen = create_empty_buffers(folio, 1 << blkbits, 0);572 573	bh_frozen = get_nth_bh(bh_frozen, bh_offset(bh) >> blkbits);574 575	if (!buffer_uptodate(bh_frozen))576		nilfs_copy_buffer(bh_frozen, bh);577	if (list_empty(&bh_frozen->b_assoc_buffers)) {578		list_add_tail(&bh_frozen->b_assoc_buffers,579			      &shadow->frozen_buffers);580		set_buffer_nilfs_redirected(bh);581	} else {582		brelse(bh_frozen); /* already frozen */583	}584 585	folio_unlock(folio);586	folio_put(folio);587	return 0;588}589 590struct buffer_head *591nilfs_mdt_get_frozen_buffer(struct inode *inode, struct buffer_head *bh)592{593	struct nilfs_shadow_map *shadow = NILFS_MDT(inode)->mi_shadow;594	struct buffer_head *bh_frozen = NULL;595	struct folio *folio;596	int n;597 598	folio = filemap_lock_folio(shadow->inode->i_mapping,599			bh->b_folio->index);600	if (!IS_ERR(folio)) {601		bh_frozen = folio_buffers(folio);602		if (bh_frozen) {603			n = bh_offset(bh) >> inode->i_blkbits;604			bh_frozen = get_nth_bh(bh_frozen, n);605		}606		folio_unlock(folio);607		folio_put(folio);608	}609	return bh_frozen;610}611 612static void nilfs_release_frozen_buffers(struct nilfs_shadow_map *shadow)613{614	struct list_head *head = &shadow->frozen_buffers;615	struct buffer_head *bh;616 617	while (!list_empty(head)) {618		bh = list_first_entry(head, struct buffer_head,619				      b_assoc_buffers);620		list_del_init(&bh->b_assoc_buffers);621		brelse(bh); /* drop ref-count to make it releasable */622	}623}624 625/**626 * nilfs_mdt_restore_from_shadow_map - restore dirty pages and bmap state627 * @inode: inode of the metadata file628 */629void nilfs_mdt_restore_from_shadow_map(struct inode *inode)630{631	struct nilfs_mdt_info *mi = NILFS_MDT(inode);632	struct nilfs_inode_info *ii = NILFS_I(inode);633	struct nilfs_shadow_map *shadow = mi->mi_shadow;634 635	down_write(&mi->mi_sem);636 637	if (mi->mi_palloc_cache)638		nilfs_palloc_clear_cache(inode);639 640	nilfs_clear_dirty_pages(inode->i_mapping);641	nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping);642 643	nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping);644	nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping,645			      NILFS_I(shadow->inode)->i_assoc_inode->i_mapping);646 647	nilfs_bmap_restore(ii->i_bmap, &shadow->bmap_store);648 649	up_write(&mi->mi_sem);650}651 652/**653 * nilfs_mdt_clear_shadow_map - truncate pages in shadow map caches654 * @inode: inode of the metadata file655 */656void nilfs_mdt_clear_shadow_map(struct inode *inode)657{658	struct nilfs_mdt_info *mi = NILFS_MDT(inode);659	struct nilfs_shadow_map *shadow = mi->mi_shadow;660	struct inode *shadow_btnc_inode = NILFS_I(shadow->inode)->i_assoc_inode;661 662	down_write(&mi->mi_sem);663	nilfs_release_frozen_buffers(shadow);664	truncate_inode_pages(shadow->inode->i_mapping, 0);665	truncate_inode_pages(shadow_btnc_inode->i_mapping, 0);666	up_write(&mi->mi_sem);667}668