cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bmap.c (14749B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * NILFS block mapping.
      4 *
      5 * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
      6 *
      7 * Written by Koji Sato.
      8 */
      9
     10#include <linux/fs.h>
     11#include <linux/string.h>
     12#include <linux/errno.h>
     13#include "nilfs.h"
     14#include "bmap.h"
     15#include "btree.h"
     16#include "direct.h"
     17#include "btnode.h"
     18#include "mdt.h"
     19#include "dat.h"
     20#include "alloc.h"
     21
     22struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
     23{
     24	struct the_nilfs *nilfs = bmap->b_inode->i_sb->s_fs_info;
     25
     26	return nilfs->ns_dat;
     27}
     28
     29static int nilfs_bmap_convert_error(struct nilfs_bmap *bmap,
     30				     const char *fname, int err)
     31{
     32	struct inode *inode = bmap->b_inode;
     33
     34	if (err == -EINVAL) {
     35		__nilfs_error(inode->i_sb, fname,
     36			      "broken bmap (inode number=%lu)", inode->i_ino);
     37		err = -EIO;
     38	}
     39	return err;
     40}
     41
     42/**
     43 * nilfs_bmap_lookup_at_level - find a data block or node block
     44 * @bmap: bmap
     45 * @key: key
     46 * @level: level
     47 * @ptrp: place to store the value associated to @key
     48 *
     49 * Description: nilfs_bmap_lookup_at_level() finds a record whose key
     50 * matches @key in the block at @level of the bmap.
     51 *
     52 * Return Value: On success, 0 is returned and the record associated with @key
     53 * is stored in the place pointed by @ptrp. On error, one of the following
     54 * negative error codes is returned.
     55 *
     56 * %-EIO - I/O error.
     57 *
     58 * %-ENOMEM - Insufficient amount of memory available.
     59 *
     60 * %-ENOENT - A record associated with @key does not exist.
     61 */
     62int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
     63			       __u64 *ptrp)
     64{
     65	sector_t blocknr;
     66	int ret;
     67
     68	down_read(&bmap->b_sem);
     69	ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
     70	if (ret < 0) {
     71		ret = nilfs_bmap_convert_error(bmap, __func__, ret);
     72		goto out;
     73	}
     74	if (NILFS_BMAP_USE_VBN(bmap)) {
     75		ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
     76					  &blocknr);
     77		if (!ret)
     78			*ptrp = blocknr;
     79	}
     80
     81 out:
     82	up_read(&bmap->b_sem);
     83	return ret;
     84}
     85
     86int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
     87			     unsigned int maxblocks)
     88{
     89	int ret;
     90
     91	down_read(&bmap->b_sem);
     92	ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
     93	up_read(&bmap->b_sem);
     94
     95	return nilfs_bmap_convert_error(bmap, __func__, ret);
     96}
     97
     98static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
     99{
    100	__u64 keys[NILFS_BMAP_SMALL_HIGH + 1];
    101	__u64 ptrs[NILFS_BMAP_SMALL_HIGH + 1];
    102	int ret, n;
    103
    104	if (bmap->b_ops->bop_check_insert != NULL) {
    105		ret = bmap->b_ops->bop_check_insert(bmap, key);
    106		if (ret > 0) {
    107			n = bmap->b_ops->bop_gather_data(
    108				bmap, keys, ptrs, NILFS_BMAP_SMALL_HIGH + 1);
    109			if (n < 0)
    110				return n;
    111			ret = nilfs_btree_convert_and_insert(
    112				bmap, key, ptr, keys, ptrs, n);
    113			if (ret == 0)
    114				bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
    115
    116			return ret;
    117		} else if (ret < 0)
    118			return ret;
    119	}
    120
    121	return bmap->b_ops->bop_insert(bmap, key, ptr);
    122}
    123
    124/**
    125 * nilfs_bmap_insert - insert a new key-record pair into a bmap
    126 * @bmap: bmap
    127 * @key: key
    128 * @rec: record
    129 *
    130 * Description: nilfs_bmap_insert() inserts the new key-record pair specified
    131 * by @key and @rec into @bmap.
    132 *
    133 * Return Value: On success, 0 is returned. On error, one of the following
    134 * negative error codes is returned.
    135 *
    136 * %-EIO - I/O error.
    137 *
    138 * %-ENOMEM - Insufficient amount of memory available.
    139 *
    140 * %-EEXIST - A record associated with @key already exist.
    141 */
    142int nilfs_bmap_insert(struct nilfs_bmap *bmap, __u64 key, unsigned long rec)
    143{
    144	int ret;
    145
    146	down_write(&bmap->b_sem);
    147	ret = nilfs_bmap_do_insert(bmap, key, rec);
    148	up_write(&bmap->b_sem);
    149
    150	return nilfs_bmap_convert_error(bmap, __func__, ret);
    151}
    152
    153static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
    154{
    155	__u64 keys[NILFS_BMAP_LARGE_LOW + 1];
    156	__u64 ptrs[NILFS_BMAP_LARGE_LOW + 1];
    157	int ret, n;
    158
    159	if (bmap->b_ops->bop_check_delete != NULL) {
    160		ret = bmap->b_ops->bop_check_delete(bmap, key);
    161		if (ret > 0) {
    162			n = bmap->b_ops->bop_gather_data(
    163				bmap, keys, ptrs, NILFS_BMAP_LARGE_LOW + 1);
    164			if (n < 0)
    165				return n;
    166			ret = nilfs_direct_delete_and_convert(
    167				bmap, key, keys, ptrs, n);
    168			if (ret == 0)
    169				bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
    170
    171			return ret;
    172		} else if (ret < 0)
    173			return ret;
    174	}
    175
    176	return bmap->b_ops->bop_delete(bmap, key);
    177}
    178
    179/**
    180 * nilfs_bmap_seek_key - seek a valid entry and return its key
    181 * @bmap: bmap struct
    182 * @start: start key number
    183 * @keyp: place to store valid key
    184 *
    185 * Description: nilfs_bmap_seek_key() seeks a valid key on @bmap
    186 * starting from @start, and stores it to @keyp if found.
    187 *
    188 * Return Value: On success, 0 is returned. On error, one of the following
    189 * negative error codes is returned.
    190 *
    191 * %-EIO - I/O error.
    192 *
    193 * %-ENOMEM - Insufficient amount of memory available.
    194 *
    195 * %-ENOENT - No valid entry was found
    196 */
    197int nilfs_bmap_seek_key(struct nilfs_bmap *bmap, __u64 start, __u64 *keyp)
    198{
    199	int ret;
    200
    201	down_read(&bmap->b_sem);
    202	ret = bmap->b_ops->bop_seek_key(bmap, start, keyp);
    203	up_read(&bmap->b_sem);
    204
    205	if (ret < 0)
    206		ret = nilfs_bmap_convert_error(bmap, __func__, ret);
    207	return ret;
    208}
    209
    210int nilfs_bmap_last_key(struct nilfs_bmap *bmap, __u64 *keyp)
    211{
    212	int ret;
    213
    214	down_read(&bmap->b_sem);
    215	ret = bmap->b_ops->bop_last_key(bmap, keyp);
    216	up_read(&bmap->b_sem);
    217
    218	if (ret < 0)
    219		ret = nilfs_bmap_convert_error(bmap, __func__, ret);
    220	return ret;
    221}
    222
    223/**
    224 * nilfs_bmap_delete - delete a key-record pair from a bmap
    225 * @bmap: bmap
    226 * @key: key
    227 *
    228 * Description: nilfs_bmap_delete() deletes the key-record pair specified by
    229 * @key from @bmap.
    230 *
    231 * Return Value: On success, 0 is returned. On error, one of the following
    232 * negative error codes is returned.
    233 *
    234 * %-EIO - I/O error.
    235 *
    236 * %-ENOMEM - Insufficient amount of memory available.
    237 *
    238 * %-ENOENT - A record associated with @key does not exist.
    239 */
    240int nilfs_bmap_delete(struct nilfs_bmap *bmap, __u64 key)
    241{
    242	int ret;
    243
    244	down_write(&bmap->b_sem);
    245	ret = nilfs_bmap_do_delete(bmap, key);
    246	up_write(&bmap->b_sem);
    247
    248	return nilfs_bmap_convert_error(bmap, __func__, ret);
    249}
    250
    251static int nilfs_bmap_do_truncate(struct nilfs_bmap *bmap, __u64 key)
    252{
    253	__u64 lastkey;
    254	int ret;
    255
    256	ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
    257	if (ret < 0) {
    258		if (ret == -ENOENT)
    259			ret = 0;
    260		return ret;
    261	}
    262
    263	while (key <= lastkey) {
    264		ret = nilfs_bmap_do_delete(bmap, lastkey);
    265		if (ret < 0)
    266			return ret;
    267		ret = bmap->b_ops->bop_last_key(bmap, &lastkey);
    268		if (ret < 0) {
    269			if (ret == -ENOENT)
    270				ret = 0;
    271			return ret;
    272		}
    273	}
    274	return 0;
    275}
    276
    277/**
    278 * nilfs_bmap_truncate - truncate a bmap to a specified key
    279 * @bmap: bmap
    280 * @key: key
    281 *
    282 * Description: nilfs_bmap_truncate() removes key-record pairs whose keys are
    283 * greater than or equal to @key from @bmap.
    284 *
    285 * Return Value: On success, 0 is returned. On error, one of the following
    286 * negative error codes is returned.
    287 *
    288 * %-EIO - I/O error.
    289 *
    290 * %-ENOMEM - Insufficient amount of memory available.
    291 */
    292int nilfs_bmap_truncate(struct nilfs_bmap *bmap, __u64 key)
    293{
    294	int ret;
    295
    296	down_write(&bmap->b_sem);
    297	ret = nilfs_bmap_do_truncate(bmap, key);
    298	up_write(&bmap->b_sem);
    299
    300	return nilfs_bmap_convert_error(bmap, __func__, ret);
    301}
    302
    303/**
    304 * nilfs_bmap_clear - free resources a bmap holds
    305 * @bmap: bmap
    306 *
    307 * Description: nilfs_bmap_clear() frees resources associated with @bmap.
    308 */
    309void nilfs_bmap_clear(struct nilfs_bmap *bmap)
    310{
    311	down_write(&bmap->b_sem);
    312	if (bmap->b_ops->bop_clear != NULL)
    313		bmap->b_ops->bop_clear(bmap);
    314	up_write(&bmap->b_sem);
    315}
    316
    317/**
    318 * nilfs_bmap_propagate - propagate dirty state
    319 * @bmap: bmap
    320 * @bh: buffer head
    321 *
    322 * Description: nilfs_bmap_propagate() marks the buffers that directly or
    323 * indirectly refer to the block specified by @bh dirty.
    324 *
    325 * Return Value: On success, 0 is returned. On error, one of the following
    326 * negative error codes is returned.
    327 *
    328 * %-EIO - I/O error.
    329 *
    330 * %-ENOMEM - Insufficient amount of memory available.
    331 */
    332int nilfs_bmap_propagate(struct nilfs_bmap *bmap, struct buffer_head *bh)
    333{
    334	int ret;
    335
    336	down_write(&bmap->b_sem);
    337	ret = bmap->b_ops->bop_propagate(bmap, bh);
    338	up_write(&bmap->b_sem);
    339
    340	return nilfs_bmap_convert_error(bmap, __func__, ret);
    341}
    342
    343/**
    344 * nilfs_bmap_lookup_dirty_buffers -
    345 * @bmap: bmap
    346 * @listp: pointer to buffer head list
    347 */
    348void nilfs_bmap_lookup_dirty_buffers(struct nilfs_bmap *bmap,
    349				     struct list_head *listp)
    350{
    351	if (bmap->b_ops->bop_lookup_dirty_buffers != NULL)
    352		bmap->b_ops->bop_lookup_dirty_buffers(bmap, listp);
    353}
    354
    355/**
    356 * nilfs_bmap_assign - assign a new block number to a block
    357 * @bmap: bmap
    358 * @bh: pointer to buffer head
    359 * @blocknr: block number
    360 * @binfo: block information
    361 *
    362 * Description: nilfs_bmap_assign() assigns the block number @blocknr to the
    363 * buffer specified by @bh.
    364 *
    365 * Return Value: On success, 0 is returned and the buffer head of a newly
    366 * create buffer and the block information associated with the buffer are
    367 * stored in the place pointed by @bh and @binfo, respectively. On error, one
    368 * of the following negative error codes is returned.
    369 *
    370 * %-EIO - I/O error.
    371 *
    372 * %-ENOMEM - Insufficient amount of memory available.
    373 */
    374int nilfs_bmap_assign(struct nilfs_bmap *bmap,
    375		      struct buffer_head **bh,
    376		      unsigned long blocknr,
    377		      union nilfs_binfo *binfo)
    378{
    379	int ret;
    380
    381	down_write(&bmap->b_sem);
    382	ret = bmap->b_ops->bop_assign(bmap, bh, blocknr, binfo);
    383	up_write(&bmap->b_sem);
    384
    385	return nilfs_bmap_convert_error(bmap, __func__, ret);
    386}
    387
    388/**
    389 * nilfs_bmap_mark - mark block dirty
    390 * @bmap: bmap
    391 * @key: key
    392 * @level: level
    393 *
    394 * Description: nilfs_bmap_mark() marks the block specified by @key and @level
    395 * as dirty.
    396 *
    397 * Return Value: On success, 0 is returned. On error, one of the following
    398 * negative error codes is returned.
    399 *
    400 * %-EIO - I/O error.
    401 *
    402 * %-ENOMEM - Insufficient amount of memory available.
    403 */
    404int nilfs_bmap_mark(struct nilfs_bmap *bmap, __u64 key, int level)
    405{
    406	int ret;
    407
    408	if (bmap->b_ops->bop_mark == NULL)
    409		return 0;
    410
    411	down_write(&bmap->b_sem);
    412	ret = bmap->b_ops->bop_mark(bmap, key, level);
    413	up_write(&bmap->b_sem);
    414
    415	return nilfs_bmap_convert_error(bmap, __func__, ret);
    416}
    417
    418/**
    419 * nilfs_bmap_test_and_clear_dirty - test and clear a bmap dirty state
    420 * @bmap: bmap
    421 *
    422 * Description: nilfs_test_and_clear() is the atomic operation to test and
    423 * clear the dirty state of @bmap.
    424 *
    425 * Return Value: 1 is returned if @bmap is dirty, or 0 if clear.
    426 */
    427int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
    428{
    429	int ret;
    430
    431	down_write(&bmap->b_sem);
    432	ret = nilfs_bmap_dirty(bmap);
    433	nilfs_bmap_clear_dirty(bmap);
    434	up_write(&bmap->b_sem);
    435	return ret;
    436}
    437
    438
    439/*
    440 * Internal use only
    441 */
    442__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
    443			      const struct buffer_head *bh)
    444{
    445	struct buffer_head *pbh;
    446	__u64 key;
    447
    448	key = page_index(bh->b_page) << (PAGE_SHIFT -
    449					 bmap->b_inode->i_blkbits);
    450	for (pbh = page_buffers(bh->b_page); pbh != bh; pbh = pbh->b_this_page)
    451		key++;
    452
    453	return key;
    454}
    455
    456__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
    457{
    458	__s64 diff;
    459
    460	diff = key - bmap->b_last_allocated_key;
    461	if ((nilfs_bmap_keydiff_abs(diff) < NILFS_INODE_BMAP_SIZE) &&
    462	    (bmap->b_last_allocated_ptr != NILFS_BMAP_INVALID_PTR) &&
    463	    (bmap->b_last_allocated_ptr + diff > 0))
    464		return bmap->b_last_allocated_ptr + diff;
    465	else
    466		return NILFS_BMAP_INVALID_PTR;
    467}
    468
    469#define NILFS_BMAP_GROUP_DIV	8
    470__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
    471{
    472	struct inode *dat = nilfs_bmap_get_dat(bmap);
    473	unsigned long entries_per_group = nilfs_palloc_entries_per_group(dat);
    474	unsigned long group = bmap->b_inode->i_ino / entries_per_group;
    475
    476	return group * entries_per_group +
    477		(bmap->b_inode->i_ino % NILFS_BMAP_GROUP_DIV) *
    478		(entries_per_group / NILFS_BMAP_GROUP_DIV);
    479}
    480
    481static struct lock_class_key nilfs_bmap_dat_lock_key;
    482static struct lock_class_key nilfs_bmap_mdt_lock_key;
    483
    484/**
    485 * nilfs_bmap_read - read a bmap from an inode
    486 * @bmap: bmap
    487 * @raw_inode: on-disk inode
    488 *
    489 * Description: nilfs_bmap_read() initializes the bmap @bmap.
    490 *
    491 * Return Value: On success, 0 is returned. On error, the following negative
    492 * error code is returned.
    493 *
    494 * %-ENOMEM - Insufficient amount of memory available.
    495 */
    496int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
    497{
    498	if (raw_inode == NULL)
    499		memset(bmap->b_u.u_data, 0, NILFS_BMAP_SIZE);
    500	else
    501		memcpy(bmap->b_u.u_data, raw_inode->i_bmap, NILFS_BMAP_SIZE);
    502
    503	init_rwsem(&bmap->b_sem);
    504	bmap->b_state = 0;
    505	bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
    506	switch (bmap->b_inode->i_ino) {
    507	case NILFS_DAT_INO:
    508		bmap->b_ptr_type = NILFS_BMAP_PTR_P;
    509		bmap->b_last_allocated_key = 0;
    510		bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
    511		lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
    512		break;
    513	case NILFS_CPFILE_INO:
    514	case NILFS_SUFILE_INO:
    515		bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
    516		bmap->b_last_allocated_key = 0;
    517		bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
    518		lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
    519		break;
    520	case NILFS_IFILE_INO:
    521		lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
    522		fallthrough;
    523	default:
    524		bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
    525		bmap->b_last_allocated_key = 0;
    526		bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
    527		break;
    528	}
    529
    530	return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
    531		nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
    532}
    533
    534/**
    535 * nilfs_bmap_write - write back a bmap to an inode
    536 * @bmap: bmap
    537 * @raw_inode: on-disk inode
    538 *
    539 * Description: nilfs_bmap_write() stores @bmap in @raw_inode.
    540 */
    541void nilfs_bmap_write(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
    542{
    543	down_write(&bmap->b_sem);
    544	memcpy(raw_inode->i_bmap, bmap->b_u.u_data,
    545	       NILFS_INODE_BMAP_SIZE * sizeof(__le64));
    546	if (bmap->b_inode->i_ino == NILFS_DAT_INO)
    547		bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
    548
    549	up_write(&bmap->b_sem);
    550}
    551
    552void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
    553{
    554	memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
    555	init_rwsem(&bmap->b_sem);
    556	bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
    557	bmap->b_ptr_type = NILFS_BMAP_PTR_U;
    558	bmap->b_last_allocated_key = 0;
    559	bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
    560	bmap->b_state = 0;
    561	nilfs_btree_init_gc(bmap);
    562}
    563
    564void nilfs_bmap_save(const struct nilfs_bmap *bmap,
    565		     struct nilfs_bmap_store *store)
    566{
    567	memcpy(store->data, bmap->b_u.u_data, sizeof(store->data));
    568	store->last_allocated_key = bmap->b_last_allocated_key;
    569	store->last_allocated_ptr = bmap->b_last_allocated_ptr;
    570	store->state = bmap->b_state;
    571}
    572
    573void nilfs_bmap_restore(struct nilfs_bmap *bmap,
    574			const struct nilfs_bmap_store *store)
    575{
    576	memcpy(bmap->b_u.u_data, store->data, sizeof(store->data));
    577	bmap->b_last_allocated_key = store->last_allocated_key;
    578	bmap->b_last_allocated_ptr = store->last_allocated_ptr;
    579	bmap->b_state = store->state;
    580}