ae98043f5f7fa (Ryusuke Konishi 2018-09-04 15:46:30 -0700 1) // SPDX-License-Identifier: GPL-2.0+
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 2) /*
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 3) * direct.c - NILFS direct block pointer.
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 4) *
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 5) * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 6) *
4b420ab4eedc7 (Ryusuke Konishi 2016-05-23 16:23:09 -0700 7) * Written by Koji Sato.
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 8) */
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 9)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 10) #include <linux/errno.h>
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 11) #include "nilfs.h"
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 12) #include "page.h"
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 13) #include "direct.h"
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 14) #include "alloc.h"
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 15) #include "dat.h"
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 16)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 17) static inline __le64 *nilfs_direct_dptrs(const struct nilfs_bmap *direct)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 18) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 19) return (__le64 *)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 20) ((struct nilfs_direct_node *)direct->b_u.u_data + 1);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 21) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 22)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 23) static inline __u64
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 24) nilfs_direct_get_ptr(const struct nilfs_bmap *direct, __u64 key)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 25) {
25b8d7ded0e45 (Ryusuke Konishi 2010-07-10 16:50:41 +0900 26) return le64_to_cpu(*(nilfs_direct_dptrs(direct) + key));
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 27) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 28)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 29) static inline void nilfs_direct_set_ptr(struct nilfs_bmap *direct,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 30) __u64 key, __u64 ptr)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 31) {
25b8d7ded0e45 (Ryusuke Konishi 2010-07-10 16:50:41 +0900 32) *(nilfs_direct_dptrs(direct) + key) = cpu_to_le64(ptr);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 33) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 34)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 35) static int nilfs_direct_lookup(const struct nilfs_bmap *direct,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 36) __u64 key, int level, __u64 *ptrp)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 37) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 38) __u64 ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 39)
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 40) if (key > NILFS_DIRECT_KEY_MAX || level != 1)
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 41) return -ENOENT;
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 42) ptr = nilfs_direct_get_ptr(direct, key);
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 43) if (ptr == NILFS_BMAP_INVALID_PTR)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 44) return -ENOENT;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 45)
364ec2d700223 (Ryusuke Konishi 2010-07-13 23:33:51 +0900 46) *ptrp = ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 47) return 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 48) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 49)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 50) static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 51) __u64 key, __u64 *ptrp,
0c6c44cb9f93f (Ryusuke Konishi 2016-05-23 16:23:39 -0700 52) unsigned int maxblocks)
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 53) {
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 54) struct inode *dat = NULL;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 55) __u64 ptr, ptr2;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 56) sector_t blocknr;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 57) int ret, cnt;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 58)
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 59) if (key > NILFS_DIRECT_KEY_MAX)
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 60) return -ENOENT;
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 61) ptr = nilfs_direct_get_ptr(direct, key);
5ee581483246e (Jiro SEKIBA 2009-12-06 15:43:56 +0900 62) if (ptr == NILFS_BMAP_INVALID_PTR)
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 63) return -ENOENT;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 64)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 65) if (NILFS_BMAP_USE_VBN(direct)) {
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 66) dat = nilfs_bmap_get_dat(direct);
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 67) ret = nilfs_dat_translate(dat, ptr, &blocknr);
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 68) if (ret < 0)
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 69) return ret;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 70) ptr = blocknr;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 71) }
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 72)
0c6c44cb9f93f (Ryusuke Konishi 2016-05-23 16:23:39 -0700 73) maxblocks = min_t(unsigned int, maxblocks,
0c6c44cb9f93f (Ryusuke Konishi 2016-05-23 16:23:39 -0700 74) NILFS_DIRECT_KEY_MAX - key + 1);
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 75) for (cnt = 1; cnt < maxblocks &&
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 76) (ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) !=
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 77) NILFS_BMAP_INVALID_PTR;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 78) cnt++) {
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 79) if (dat) {
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 80) ret = nilfs_dat_translate(dat, ptr2, &blocknr);
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 81) if (ret < 0)
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 82) return ret;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 83) ptr2 = blocknr;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 84) }
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 85) if (ptr2 != ptr + cnt)
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 86) break;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 87) }
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 88) *ptrp = ptr;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 89) return cnt;
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 90) }
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 91)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 92) static __u64
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 93) nilfs_direct_find_target_v(const struct nilfs_bmap *direct, __u64 key)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 94) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 95) __u64 ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 96)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 97) ptr = nilfs_bmap_find_target_seq(direct, key);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 98) if (ptr != NILFS_BMAP_INVALID_PTR)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 99) /* sequential access */
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 100) return ptr;
7f00184e9cb53 (Ryusuke Konishi 2016-05-23 16:23:42 -0700 101)
7f00184e9cb53 (Ryusuke Konishi 2016-05-23 16:23:42 -0700 102) /* block group */
7f00184e9cb53 (Ryusuke Konishi 2016-05-23 16:23:42 -0700 103) return nilfs_bmap_find_target_in_group(direct);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 104) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 105)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 106) static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 107) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 108) union nilfs_bmap_ptr_req req;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 109) struct inode *dat = NULL;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 110) struct buffer_head *bh;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 111) int ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 112)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 113) if (key > NILFS_DIRECT_KEY_MAX)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 114) return -ENOENT;
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 115) if (nilfs_direct_get_ptr(bmap, key) != NILFS_BMAP_INVALID_PTR)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 116) return -EEXIST;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 117)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 118) if (NILFS_BMAP_USE_VBN(bmap)) {
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 119) req.bpr_ptr = nilfs_direct_find_target_v(bmap, key);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 120) dat = nilfs_bmap_get_dat(bmap);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 121) }
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 122) ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 123) if (!ret) {
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 124) /* ptr must be a pointer to a buffer head. */
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 125) bh = (struct buffer_head *)((unsigned long)ptr);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 126) set_buffer_nilfs_volatile(bh);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 127)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 128) nilfs_bmap_commit_alloc_ptr(bmap, &req, dat);
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 129) nilfs_direct_set_ptr(bmap, key, req.bpr_ptr);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 130)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 131) if (!nilfs_bmap_dirty(bmap))
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 132) nilfs_bmap_set_dirty(bmap);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 133)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 134) if (NILFS_BMAP_USE_VBN(bmap))
dc935be2a0940 (Ryusuke Konishi 2010-07-10 22:21:54 +0900 135) nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 136)
be667377a8b8c (Ryusuke Konishi 2011-03-05 00:19:32 +0900 137) nilfs_inode_add_blocks(bmap->b_inode, 1);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 138) }
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 139) return ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 140) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 141)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 142) static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 143) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 144) union nilfs_bmap_ptr_req req;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 145) struct inode *dat;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 146) int ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 147)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 148) if (key > NILFS_DIRECT_KEY_MAX ||
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 149) nilfs_direct_get_ptr(bmap, key) == NILFS_BMAP_INVALID_PTR)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 150) return -ENOENT;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 151)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 152) dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 153) req.bpr_ptr = nilfs_direct_get_ptr(bmap, key);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 154)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 155) ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 156) if (!ret) {
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 157) nilfs_bmap_commit_end_ptr(bmap, &req, dat);
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 158) nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
be667377a8b8c (Ryusuke Konishi 2011-03-05 00:19:32 +0900 159) nilfs_inode_sub_blocks(bmap->b_inode, 1);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 160) }
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 161) return ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 162) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 163)
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 164) static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start,
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 165) __u64 *keyp)
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 166) {
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 167) __u64 key;
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 168)
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 169) for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) {
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 170) if (nilfs_direct_get_ptr(direct, key) !=
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 171) NILFS_BMAP_INVALID_PTR) {
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 172) *keyp = key;
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 173) return 0;
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 174) }
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 175) }
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 176) return -ENOENT;
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 177) }
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 178)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 179) static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 180) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 181) __u64 key, lastkey;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 182)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 183) lastkey = NILFS_DIRECT_KEY_MAX + 1;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 184) for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 185) if (nilfs_direct_get_ptr(direct, key) !=
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 186) NILFS_BMAP_INVALID_PTR)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 187) lastkey = key;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 188)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 189) if (lastkey == NILFS_DIRECT_KEY_MAX + 1)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 190) return -ENOENT;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 191)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 192) *keyp = lastkey;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 193)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 194) return 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 195) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 196)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 197) static int nilfs_direct_check_insert(const struct nilfs_bmap *bmap, __u64 key)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 198) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 199) return key > NILFS_DIRECT_KEY_MAX;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 200) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 201)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 202) static int nilfs_direct_gather_data(struct nilfs_bmap *direct,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 203) __u64 *keys, __u64 *ptrs, int nitems)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 204) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 205) __u64 key;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 206) __u64 ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 207) int n;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 208)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 209) if (nitems > NILFS_DIRECT_NBLOCKS)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 210) nitems = NILFS_DIRECT_NBLOCKS;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 211) n = 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 212) for (key = 0; key < nitems; key++) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 213) ptr = nilfs_direct_get_ptr(direct, key);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 214) if (ptr != NILFS_BMAP_INVALID_PTR) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 215) keys[n] = key;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 216) ptrs[n] = ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 217) n++;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 218) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 219) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 220) return n;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 221) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 222)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 223) int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
3033342a0b760 (Ryusuke Konishi 2009-05-24 00:09:44 +0900 224) __u64 key, __u64 *keys, __u64 *ptrs, int n)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 225) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 226) __le64 *dptrs;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 227) int ret, i, j;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 228)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 229) /* no need to allocate any resource for conversion */
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 230)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 231) /* delete */
8acfbf0939e98 (Pekka Enberg 2009-04-06 19:01:49 -0700 232) ret = bmap->b_ops->bop_delete(bmap, key);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 233) if (ret < 0)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 234) return ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 235)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 236) /* free resources */
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 237) if (bmap->b_ops->bop_clear != NULL)
8acfbf0939e98 (Pekka Enberg 2009-04-06 19:01:49 -0700 238) bmap->b_ops->bop_clear(bmap);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 239)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 240) /* convert */
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 241) dptrs = nilfs_direct_dptrs(bmap);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 242) for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 243) if ((j < n) && (i == keys[j])) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 244) dptrs[i] = (i != key) ?
25b8d7ded0e45 (Ryusuke Konishi 2010-07-10 16:50:41 +0900 245) cpu_to_le64(ptrs[j]) :
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 246) NILFS_BMAP_INVALID_PTR;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 247) j++;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 248) } else
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 249) dptrs[i] = NILFS_BMAP_INVALID_PTR;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 250) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 251)
3033342a0b760 (Ryusuke Konishi 2009-05-24 00:09:44 +0900 252) nilfs_direct_init(bmap);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 253) return 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 254) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 255)
583ada4761e18 (Ryusuke Konishi 2010-07-10 21:37:47 +0900 256) static int nilfs_direct_propagate(struct nilfs_bmap *bmap,
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 257) struct buffer_head *bh)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 258) {
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 259) struct nilfs_palloc_req oldreq, newreq;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 260) struct inode *dat;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 261) __u64 key;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 262) __u64 ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 263) int ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 264)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 265) if (!NILFS_BMAP_USE_VBN(bmap))
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 266) return 0;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 267)
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 268) dat = nilfs_bmap_get_dat(bmap);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 269) key = nilfs_bmap_data_get_key(bmap, bh);
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 270) ptr = nilfs_direct_get_ptr(bmap, key);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 271) if (!buffer_nilfs_volatile(bh)) {
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 272) oldreq.pr_entry_nr = ptr;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 273) newreq.pr_entry_nr = ptr;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 274) ret = nilfs_dat_prepare_update(dat, &oldreq, &newreq);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 275) if (ret < 0)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 276) return ret;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 277) nilfs_dat_commit_update(dat, &oldreq, &newreq,
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 278) bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 279) set_buffer_nilfs_volatile(bh);
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 280) nilfs_direct_set_ptr(bmap, key, newreq.pr_entry_nr);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 281) } else
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 282) ret = nilfs_dat_mark_dirty(dat, ptr);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 283)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 284) return ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 285) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 286)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 287) static int nilfs_direct_assign_v(struct nilfs_bmap *direct,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 288) __u64 key, __u64 ptr,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 289) struct buffer_head **bh,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 290) sector_t blocknr,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 291) union nilfs_binfo *binfo)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 292) {
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 293) struct inode *dat = nilfs_bmap_get_dat(direct);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 294) union nilfs_bmap_ptr_req req;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 295) int ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 296)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 297) req.bpr_ptr = ptr;
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 298) ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 299) if (!ret) {
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 300) nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
25b8d7ded0e45 (Ryusuke Konishi 2010-07-10 16:50:41 +0900 301) binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
25b8d7ded0e45 (Ryusuke Konishi 2010-07-10 16:50:41 +0900 302) binfo->bi_v.bi_blkoff = cpu_to_le64(key);
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 303) }
2e0c2c73923fe (Ryusuke Konishi 2009-08-15 15:34:33 +0900 304) return ret;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 305) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 306)
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 307) static int nilfs_direct_assign_p(struct nilfs_bmap *direct,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 308) __u64 key, __u64 ptr,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 309) struct buffer_head **bh,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 310) sector_t blocknr,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 311) union nilfs_binfo *binfo)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 312) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 313) nilfs_direct_set_ptr(direct, key, blocknr);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 314)
25b8d7ded0e45 (Ryusuke Konishi 2010-07-10 16:50:41 +0900 315) binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 316) binfo->bi_dat.bi_level = 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 317)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 318) return 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 319) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 320)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 321) static int nilfs_direct_assign(struct nilfs_bmap *bmap,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 322) struct buffer_head **bh,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 323) sector_t blocknr,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 324) union nilfs_binfo *binfo)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 325) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 326) __u64 key;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 327) __u64 ptr;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 328)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 329) key = nilfs_bmap_data_get_key(bmap, *bh);
1f5abe7e7dbcd (Ryusuke Konishi 2009-04-06 19:01:55 -0700 330) if (unlikely(key > NILFS_DIRECT_KEY_MAX)) {
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 331) nilfs_crit(bmap->b_inode->i_sb,
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 332) "%s (ino=%lu): invalid key: %llu",
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 333) __func__,
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 334) bmap->b_inode->i_ino, (unsigned long long)key);
1f5abe7e7dbcd (Ryusuke Konishi 2009-04-06 19:01:55 -0700 335) return -EINVAL;
1f5abe7e7dbcd (Ryusuke Konishi 2009-04-06 19:01:55 -0700 336) }
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 337) ptr = nilfs_direct_get_ptr(bmap, key);
1f5abe7e7dbcd (Ryusuke Konishi 2009-04-06 19:01:55 -0700 338) if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) {
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 339) nilfs_crit(bmap->b_inode->i_sb,
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 340) "%s (ino=%lu): invalid pointer: %llu",
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 341) __func__,
a1d0747a393a0 (Joe Perches 2020-08-11 18:35:49 -0700 342) bmap->b_inode->i_ino, (unsigned long long)ptr);
1f5abe7e7dbcd (Ryusuke Konishi 2009-04-06 19:01:55 -0700 343) return -EINVAL;
1f5abe7e7dbcd (Ryusuke Konishi 2009-04-06 19:01:55 -0700 344) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 345)
355c6b61034a5 (Ryusuke Konishi 2009-05-24 16:46:37 +0900 346) return NILFS_BMAP_USE_VBN(bmap) ?
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 347) nilfs_direct_assign_v(bmap, key, ptr, bh, blocknr, binfo) :
10ff885ba6f56 (Ryusuke Konishi 2010-07-10 18:07:04 +0900 348) nilfs_direct_assign_p(bmap, key, ptr, bh, blocknr, binfo);
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 349) }
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 350)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 351) static const struct nilfs_bmap_operations nilfs_direct_ops = {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 352) .bop_lookup = nilfs_direct_lookup,
c3a7abf06ce71 (Ryusuke Konishi 2009-05-25 02:47:14 +0900 353) .bop_lookup_contig = nilfs_direct_lookup_contig,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 354) .bop_insert = nilfs_direct_insert,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 355) .bop_delete = nilfs_direct_delete,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 356) .bop_clear = NULL,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 357)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 358) .bop_propagate = nilfs_direct_propagate,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 359)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 360) .bop_lookup_dirty_buffers = NULL,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 361)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 362) .bop_assign = nilfs_direct_assign,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 363) .bop_mark = NULL,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 364)
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 365) .bop_seek_key = nilfs_direct_seek_key,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 366) .bop_last_key = nilfs_direct_last_key,
5b20384fb32cc (Ryusuke Konishi 2015-04-16 12:46:36 -0700 367)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 368) .bop_check_insert = nilfs_direct_check_insert,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 369) .bop_check_delete = NULL,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 370) .bop_gather_data = nilfs_direct_gather_data,
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 371) };
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 372)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 373)
3033342a0b760 (Ryusuke Konishi 2009-05-24 00:09:44 +0900 374) int nilfs_direct_init(struct nilfs_bmap *bmap)
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 375) {
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 376) bmap->b_ops = &nilfs_direct_ops;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 377) return 0;
36a580eb489f5 (Koji Sato 2009-04-06 19:01:25 -0700 378) }