Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * btnode.c - NILFS B-tree node cache
  4 *
  5 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
  6 *
 
 
 
 
 
 
 
 
 
 
  7 * Originally written by Seiji Kihara.
  8 * Fully revised by Ryusuke Konishi for stabilization and simplification.
  9 *
 10 */
 11
 12#include <linux/types.h>
 13#include <linux/buffer_head.h>
 14#include <linux/mm.h>
 15#include <linux/backing-dev.h>
 16#include <linux/gfp.h>
 17#include "nilfs.h"
 18#include "mdt.h"
 19#include "dat.h"
 20#include "page.h"
 21#include "btnode.h"
 22
 23void nilfs_btnode_cache_clear(struct address_space *btnc)
 24{
 25	invalidate_mapping_pages(btnc, 0, -1);
 26	truncate_inode_pages(btnc, 0);
 27}
 28
 29struct buffer_head *
 30nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
 31{
 32	struct inode *inode = NILFS_BTNC_I(btnc);
 33	struct buffer_head *bh;
 34
 35	bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node));
 36	if (unlikely(!bh))
 37		return NULL;
 38
 39	if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
 40		     buffer_dirty(bh))) {
 41		brelse(bh);
 42		BUG();
 43	}
 44	memset(bh->b_data, 0, i_blocksize(inode));
 45	bh->b_bdev = inode->i_sb->s_bdev;
 46	bh->b_blocknr = blocknr;
 47	set_buffer_mapped(bh);
 48	set_buffer_uptodate(bh);
 49
 50	unlock_page(bh->b_page);
 51	put_page(bh->b_page);
 52	return bh;
 53}
 54
 55int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
 56			      sector_t pblocknr, int mode, int mode_flags,
 57			      struct buffer_head **pbh, sector_t *submit_ptr)
 58{
 59	struct buffer_head *bh;
 60	struct inode *inode = NILFS_BTNC_I(btnc);
 61	struct page *page;
 62	int err;
 63
 64	bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node));
 65	if (unlikely(!bh))
 66		return -ENOMEM;
 67
 68	err = -EEXIST; /* internal code */
 69	page = bh->b_page;
 70
 71	if (buffer_uptodate(bh) || buffer_dirty(bh))
 72		goto found;
 73
 74	if (pblocknr == 0) {
 75		pblocknr = blocknr;
 76		if (inode->i_ino != NILFS_DAT_INO) {
 77			struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 78
 79			/* blocknr is a virtual block number */
 80			err = nilfs_dat_translate(nilfs->ns_dat, blocknr,
 81						  &pblocknr);
 82			if (unlikely(err)) {
 83				brelse(bh);
 84				goto out_locked;
 85			}
 86		}
 87	}
 88
 89	if (mode_flags & REQ_RAHEAD) {
 90		if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) {
 91			err = -EBUSY; /* internal code */
 92			brelse(bh);
 93			goto out_locked;
 94		}
 95	} else { /* mode == READ */
 96		lock_buffer(bh);
 97	}
 98	if (buffer_uptodate(bh)) {
 99		unlock_buffer(bh);
100		err = -EEXIST; /* internal code */
101		goto found;
102	}
103	set_buffer_mapped(bh);
104	bh->b_bdev = inode->i_sb->s_bdev;
105	bh->b_blocknr = pblocknr; /* set block address for read */
106	bh->b_end_io = end_buffer_read_sync;
107	get_bh(bh);
108	submit_bh(mode, mode_flags, bh);
109	bh->b_blocknr = blocknr; /* set back to the given block address */
110	*submit_ptr = pblocknr;
111	err = 0;
112found:
113	*pbh = bh;
114
115out_locked:
116	unlock_page(page);
117	put_page(page);
118	return err;
119}
120
121/**
122 * nilfs_btnode_delete - delete B-tree node buffer
123 * @bh: buffer to be deleted
124 *
125 * nilfs_btnode_delete() invalidates the specified buffer and delete the page
126 * including the buffer if the page gets unbusy.
127 */
128void nilfs_btnode_delete(struct buffer_head *bh)
129{
130	struct address_space *mapping;
131	struct page *page = bh->b_page;
132	pgoff_t index = page_index(page);
133	int still_dirty;
134
135	get_page(page);
136	lock_page(page);
137	wait_on_page_writeback(page);
138
139	nilfs_forget_buffer(bh);
140	still_dirty = PageDirty(page);
141	mapping = page->mapping;
142	unlock_page(page);
143	put_page(page);
144
145	if (!still_dirty && mapping)
146		invalidate_inode_pages2_range(mapping, index, index);
147}
148
149/**
150 * nilfs_btnode_prepare_change_key
151 *  prepare to move contents of the block for old key to one of new key.
152 *  the old buffer will not be removed, but might be reused for new buffer.
153 *  it might return -ENOMEM because of memory allocation errors,
154 *  and might return -EIO because of disk read errors.
155 */
156int nilfs_btnode_prepare_change_key(struct address_space *btnc,
157				    struct nilfs_btnode_chkey_ctxt *ctxt)
158{
159	struct buffer_head *obh, *nbh;
160	struct inode *inode = NILFS_BTNC_I(btnc);
161	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
162	int err;
163
164	if (oldkey == newkey)
165		return 0;
166
167	obh = ctxt->bh;
168	ctxt->newbh = NULL;
169
170	if (inode->i_blkbits == PAGE_SHIFT) {
171		struct page *opage = obh->b_page;
172		lock_page(opage);
 
 
 
173retry:
 
 
 
174		/* BUG_ON(oldkey != obh->b_page->index); */
175		if (unlikely(oldkey != opage->index))
176			NILFS_PAGE_BUG(opage,
177				       "invalid oldkey %lld (newkey=%lld)",
178				       (unsigned long long)oldkey,
179				       (unsigned long long)newkey);
180
181		xa_lock_irq(&btnc->i_pages);
182		err = __xa_insert(&btnc->i_pages, newkey, opage, GFP_NOFS);
183		xa_unlock_irq(&btnc->i_pages);
184		/*
185		 * Note: page->index will not change to newkey until
186		 * nilfs_btnode_commit_change_key() will be called.
187		 * To protect the page in intermediate state, the page lock
188		 * is held.
189		 */
 
190		if (!err)
191			return 0;
192		else if (err != -EBUSY)
193			goto failed_unlock;
194
195		err = invalidate_inode_pages2_range(btnc, newkey, newkey);
196		if (!err)
197			goto retry;
198		/* fallback to copy mode */
199		unlock_page(opage);
200	}
201
202	nbh = nilfs_btnode_create_block(btnc, newkey);
203	if (!nbh)
204		return -ENOMEM;
205
206	BUG_ON(nbh == obh);
207	ctxt->newbh = nbh;
208	return 0;
209
210 failed_unlock:
211	unlock_page(obh->b_page);
212	return err;
213}
214
215/**
216 * nilfs_btnode_commit_change_key
217 *  commit the change_key operation prepared by prepare_change_key().
218 */
219void nilfs_btnode_commit_change_key(struct address_space *btnc,
220				    struct nilfs_btnode_chkey_ctxt *ctxt)
221{
222	struct buffer_head *obh = ctxt->bh, *nbh = ctxt->newbh;
223	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
224	struct page *opage;
225
226	if (oldkey == newkey)
227		return;
228
229	if (nbh == NULL) {	/* blocksize == pagesize */
230		opage = obh->b_page;
231		if (unlikely(oldkey != opage->index))
232			NILFS_PAGE_BUG(opage,
233				       "invalid oldkey %lld (newkey=%lld)",
234				       (unsigned long long)oldkey,
235				       (unsigned long long)newkey);
236		mark_buffer_dirty(obh);
237
238		xa_lock_irq(&btnc->i_pages);
239		__xa_erase(&btnc->i_pages, oldkey);
240		__xa_set_mark(&btnc->i_pages, newkey, PAGECACHE_TAG_DIRTY);
241		xa_unlock_irq(&btnc->i_pages);
 
242
243		opage->index = obh->b_blocknr = newkey;
244		unlock_page(opage);
245	} else {
246		nilfs_copy_buffer(nbh, obh);
247		mark_buffer_dirty(nbh);
248
249		nbh->b_blocknr = newkey;
250		ctxt->bh = nbh;
251		nilfs_btnode_delete(obh); /* will decrement bh->b_count */
252	}
253}
254
255/**
256 * nilfs_btnode_abort_change_key
257 *  abort the change_key operation prepared by prepare_change_key().
258 */
259void nilfs_btnode_abort_change_key(struct address_space *btnc,
260				   struct nilfs_btnode_chkey_ctxt *ctxt)
261{
262	struct buffer_head *nbh = ctxt->newbh;
263	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
264
265	if (oldkey == newkey)
266		return;
267
268	if (nbh == NULL) {	/* blocksize == pagesize */
269		xa_erase_irq(&btnc->i_pages, newkey);
 
 
270		unlock_page(ctxt->bh->b_page);
271	} else
272		brelse(nbh);
273}
v4.10.11
 
  1/*
  2 * btnode.c - NILFS B-tree node cache
  3 *
  4 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License as published by
  8 * the Free Software Foundation; either version 2 of the License, or
  9 * (at your option) any later version.
 10 *
 11 * This program is distributed in the hope that it will be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 * GNU General Public License for more details.
 15 *
 16 * Originally written by Seiji Kihara.
 17 * Fully revised by Ryusuke Konishi for stabilization and simplification.
 18 *
 19 */
 20
 21#include <linux/types.h>
 22#include <linux/buffer_head.h>
 23#include <linux/mm.h>
 24#include <linux/backing-dev.h>
 25#include <linux/gfp.h>
 26#include "nilfs.h"
 27#include "mdt.h"
 28#include "dat.h"
 29#include "page.h"
 30#include "btnode.h"
 31
 32void nilfs_btnode_cache_clear(struct address_space *btnc)
 33{
 34	invalidate_mapping_pages(btnc, 0, -1);
 35	truncate_inode_pages(btnc, 0);
 36}
 37
 38struct buffer_head *
 39nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
 40{
 41	struct inode *inode = NILFS_BTNC_I(btnc);
 42	struct buffer_head *bh;
 43
 44	bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node));
 45	if (unlikely(!bh))
 46		return NULL;
 47
 48	if (unlikely(buffer_mapped(bh) || buffer_uptodate(bh) ||
 49		     buffer_dirty(bh))) {
 50		brelse(bh);
 51		BUG();
 52	}
 53	memset(bh->b_data, 0, 1 << inode->i_blkbits);
 54	bh->b_bdev = inode->i_sb->s_bdev;
 55	bh->b_blocknr = blocknr;
 56	set_buffer_mapped(bh);
 57	set_buffer_uptodate(bh);
 58
 59	unlock_page(bh->b_page);
 60	put_page(bh->b_page);
 61	return bh;
 62}
 63
 64int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
 65			      sector_t pblocknr, int mode, int mode_flags,
 66			      struct buffer_head **pbh, sector_t *submit_ptr)
 67{
 68	struct buffer_head *bh;
 69	struct inode *inode = NILFS_BTNC_I(btnc);
 70	struct page *page;
 71	int err;
 72
 73	bh = nilfs_grab_buffer(inode, btnc, blocknr, BIT(BH_NILFS_Node));
 74	if (unlikely(!bh))
 75		return -ENOMEM;
 76
 77	err = -EEXIST; /* internal code */
 78	page = bh->b_page;
 79
 80	if (buffer_uptodate(bh) || buffer_dirty(bh))
 81		goto found;
 82
 83	if (pblocknr == 0) {
 84		pblocknr = blocknr;
 85		if (inode->i_ino != NILFS_DAT_INO) {
 86			struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 87
 88			/* blocknr is a virtual block number */
 89			err = nilfs_dat_translate(nilfs->ns_dat, blocknr,
 90						  &pblocknr);
 91			if (unlikely(err)) {
 92				brelse(bh);
 93				goto out_locked;
 94			}
 95		}
 96	}
 97
 98	if (mode_flags & REQ_RAHEAD) {
 99		if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) {
100			err = -EBUSY; /* internal code */
101			brelse(bh);
102			goto out_locked;
103		}
104	} else { /* mode == READ */
105		lock_buffer(bh);
106	}
107	if (buffer_uptodate(bh)) {
108		unlock_buffer(bh);
109		err = -EEXIST; /* internal code */
110		goto found;
111	}
112	set_buffer_mapped(bh);
113	bh->b_bdev = inode->i_sb->s_bdev;
114	bh->b_blocknr = pblocknr; /* set block address for read */
115	bh->b_end_io = end_buffer_read_sync;
116	get_bh(bh);
117	submit_bh(mode, mode_flags, bh);
118	bh->b_blocknr = blocknr; /* set back to the given block address */
119	*submit_ptr = pblocknr;
120	err = 0;
121found:
122	*pbh = bh;
123
124out_locked:
125	unlock_page(page);
126	put_page(page);
127	return err;
128}
129
130/**
131 * nilfs_btnode_delete - delete B-tree node buffer
132 * @bh: buffer to be deleted
133 *
134 * nilfs_btnode_delete() invalidates the specified buffer and delete the page
135 * including the buffer if the page gets unbusy.
136 */
137void nilfs_btnode_delete(struct buffer_head *bh)
138{
139	struct address_space *mapping;
140	struct page *page = bh->b_page;
141	pgoff_t index = page_index(page);
142	int still_dirty;
143
144	get_page(page);
145	lock_page(page);
146	wait_on_page_writeback(page);
147
148	nilfs_forget_buffer(bh);
149	still_dirty = PageDirty(page);
150	mapping = page->mapping;
151	unlock_page(page);
152	put_page(page);
153
154	if (!still_dirty && mapping)
155		invalidate_inode_pages2_range(mapping, index, index);
156}
157
158/**
159 * nilfs_btnode_prepare_change_key
160 *  prepare to move contents of the block for old key to one of new key.
161 *  the old buffer will not be removed, but might be reused for new buffer.
162 *  it might return -ENOMEM because of memory allocation errors,
163 *  and might return -EIO because of disk read errors.
164 */
165int nilfs_btnode_prepare_change_key(struct address_space *btnc,
166				    struct nilfs_btnode_chkey_ctxt *ctxt)
167{
168	struct buffer_head *obh, *nbh;
169	struct inode *inode = NILFS_BTNC_I(btnc);
170	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
171	int err;
172
173	if (oldkey == newkey)
174		return 0;
175
176	obh = ctxt->bh;
177	ctxt->newbh = NULL;
178
179	if (inode->i_blkbits == PAGE_SHIFT) {
180		lock_page(obh->b_page);
181		/*
182		 * We cannot call radix_tree_preload for the kernels older
183		 * than 2.6.23, because it is not exported for modules.
184		 */
185retry:
186		err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
187		if (err)
188			goto failed_unlock;
189		/* BUG_ON(oldkey != obh->b_page->index); */
190		if (unlikely(oldkey != obh->b_page->index))
191			NILFS_PAGE_BUG(obh->b_page,
192				       "invalid oldkey %lld (newkey=%lld)",
193				       (unsigned long long)oldkey,
194				       (unsigned long long)newkey);
195
196		spin_lock_irq(&btnc->tree_lock);
197		err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page);
198		spin_unlock_irq(&btnc->tree_lock);
199		/*
200		 * Note: page->index will not change to newkey until
201		 * nilfs_btnode_commit_change_key() will be called.
202		 * To protect the page in intermediate state, the page lock
203		 * is held.
204		 */
205		radix_tree_preload_end();
206		if (!err)
207			return 0;
208		else if (err != -EEXIST)
209			goto failed_unlock;
210
211		err = invalidate_inode_pages2_range(btnc, newkey, newkey);
212		if (!err)
213			goto retry;
214		/* fallback to copy mode */
215		unlock_page(obh->b_page);
216	}
217
218	nbh = nilfs_btnode_create_block(btnc, newkey);
219	if (!nbh)
220		return -ENOMEM;
221
222	BUG_ON(nbh == obh);
223	ctxt->newbh = nbh;
224	return 0;
225
226 failed_unlock:
227	unlock_page(obh->b_page);
228	return err;
229}
230
231/**
232 * nilfs_btnode_commit_change_key
233 *  commit the change_key operation prepared by prepare_change_key().
234 */
235void nilfs_btnode_commit_change_key(struct address_space *btnc,
236				    struct nilfs_btnode_chkey_ctxt *ctxt)
237{
238	struct buffer_head *obh = ctxt->bh, *nbh = ctxt->newbh;
239	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
240	struct page *opage;
241
242	if (oldkey == newkey)
243		return;
244
245	if (nbh == NULL) {	/* blocksize == pagesize */
246		opage = obh->b_page;
247		if (unlikely(oldkey != opage->index))
248			NILFS_PAGE_BUG(opage,
249				       "invalid oldkey %lld (newkey=%lld)",
250				       (unsigned long long)oldkey,
251				       (unsigned long long)newkey);
252		mark_buffer_dirty(obh);
253
254		spin_lock_irq(&btnc->tree_lock);
255		radix_tree_delete(&btnc->page_tree, oldkey);
256		radix_tree_tag_set(&btnc->page_tree, newkey,
257				   PAGECACHE_TAG_DIRTY);
258		spin_unlock_irq(&btnc->tree_lock);
259
260		opage->index = obh->b_blocknr = newkey;
261		unlock_page(opage);
262	} else {
263		nilfs_copy_buffer(nbh, obh);
264		mark_buffer_dirty(nbh);
265
266		nbh->b_blocknr = newkey;
267		ctxt->bh = nbh;
268		nilfs_btnode_delete(obh); /* will decrement bh->b_count */
269	}
270}
271
272/**
273 * nilfs_btnode_abort_change_key
274 *  abort the change_key operation prepared by prepare_change_key().
275 */
276void nilfs_btnode_abort_change_key(struct address_space *btnc,
277				   struct nilfs_btnode_chkey_ctxt *ctxt)
278{
279	struct buffer_head *nbh = ctxt->newbh;
280	__u64 oldkey = ctxt->oldkey, newkey = ctxt->newkey;
281
282	if (oldkey == newkey)
283		return;
284
285	if (nbh == NULL) {	/* blocksize == pagesize */
286		spin_lock_irq(&btnc->tree_lock);
287		radix_tree_delete(&btnc->page_tree, newkey);
288		spin_unlock_irq(&btnc->tree_lock);
289		unlock_page(ctxt->bh->b_page);
290	} else
291		brelse(nbh);
292}