0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/errno.h>
0011 #include "nilfs.h"
0012 #include "page.h"
0013 #include "direct.h"
0014 #include "alloc.h"
0015 #include "dat.h"
0016
0017 static inline __le64 *nilfs_direct_dptrs(const struct nilfs_bmap *direct)
0018 {
0019 return (__le64 *)
0020 ((struct nilfs_direct_node *)direct->b_u.u_data + 1);
0021 }
0022
0023 static inline __u64
0024 nilfs_direct_get_ptr(const struct nilfs_bmap *direct, __u64 key)
0025 {
0026 return le64_to_cpu(*(nilfs_direct_dptrs(direct) + key));
0027 }
0028
0029 static inline void nilfs_direct_set_ptr(struct nilfs_bmap *direct,
0030 __u64 key, __u64 ptr)
0031 {
0032 *(nilfs_direct_dptrs(direct) + key) = cpu_to_le64(ptr);
0033 }
0034
0035 static int nilfs_direct_lookup(const struct nilfs_bmap *direct,
0036 __u64 key, int level, __u64 *ptrp)
0037 {
0038 __u64 ptr;
0039
0040 if (key > NILFS_DIRECT_KEY_MAX || level != 1)
0041 return -ENOENT;
0042 ptr = nilfs_direct_get_ptr(direct, key);
0043 if (ptr == NILFS_BMAP_INVALID_PTR)
0044 return -ENOENT;
0045
0046 *ptrp = ptr;
0047 return 0;
0048 }
0049
0050 static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
0051 __u64 key, __u64 *ptrp,
0052 unsigned int maxblocks)
0053 {
0054 struct inode *dat = NULL;
0055 __u64 ptr, ptr2;
0056 sector_t blocknr;
0057 int ret, cnt;
0058
0059 if (key > NILFS_DIRECT_KEY_MAX)
0060 return -ENOENT;
0061 ptr = nilfs_direct_get_ptr(direct, key);
0062 if (ptr == NILFS_BMAP_INVALID_PTR)
0063 return -ENOENT;
0064
0065 if (NILFS_BMAP_USE_VBN(direct)) {
0066 dat = nilfs_bmap_get_dat(direct);
0067 ret = nilfs_dat_translate(dat, ptr, &blocknr);
0068 if (ret < 0)
0069 return ret;
0070 ptr = blocknr;
0071 }
0072
0073 maxblocks = min_t(unsigned int, maxblocks,
0074 NILFS_DIRECT_KEY_MAX - key + 1);
0075 for (cnt = 1; cnt < maxblocks &&
0076 (ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) !=
0077 NILFS_BMAP_INVALID_PTR;
0078 cnt++) {
0079 if (dat) {
0080 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
0081 if (ret < 0)
0082 return ret;
0083 ptr2 = blocknr;
0084 }
0085 if (ptr2 != ptr + cnt)
0086 break;
0087 }
0088 *ptrp = ptr;
0089 return cnt;
0090 }
0091
0092 static __u64
0093 nilfs_direct_find_target_v(const struct nilfs_bmap *direct, __u64 key)
0094 {
0095 __u64 ptr;
0096
0097 ptr = nilfs_bmap_find_target_seq(direct, key);
0098 if (ptr != NILFS_BMAP_INVALID_PTR)
0099
0100 return ptr;
0101
0102
0103 return nilfs_bmap_find_target_in_group(direct);
0104 }
0105
0106 static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
0107 {
0108 union nilfs_bmap_ptr_req req;
0109 struct inode *dat = NULL;
0110 struct buffer_head *bh;
0111 int ret;
0112
0113 if (key > NILFS_DIRECT_KEY_MAX)
0114 return -ENOENT;
0115 if (nilfs_direct_get_ptr(bmap, key) != NILFS_BMAP_INVALID_PTR)
0116 return -EEXIST;
0117
0118 if (NILFS_BMAP_USE_VBN(bmap)) {
0119 req.bpr_ptr = nilfs_direct_find_target_v(bmap, key);
0120 dat = nilfs_bmap_get_dat(bmap);
0121 }
0122 ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat);
0123 if (!ret) {
0124
0125 bh = (struct buffer_head *)((unsigned long)ptr);
0126 set_buffer_nilfs_volatile(bh);
0127
0128 nilfs_bmap_commit_alloc_ptr(bmap, &req, dat);
0129 nilfs_direct_set_ptr(bmap, key, req.bpr_ptr);
0130
0131 if (!nilfs_bmap_dirty(bmap))
0132 nilfs_bmap_set_dirty(bmap);
0133
0134 if (NILFS_BMAP_USE_VBN(bmap))
0135 nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
0136
0137 nilfs_inode_add_blocks(bmap->b_inode, 1);
0138 }
0139 return ret;
0140 }
0141
0142 static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
0143 {
0144 union nilfs_bmap_ptr_req req;
0145 struct inode *dat;
0146 int ret;
0147
0148 if (key > NILFS_DIRECT_KEY_MAX ||
0149 nilfs_direct_get_ptr(bmap, key) == NILFS_BMAP_INVALID_PTR)
0150 return -ENOENT;
0151
0152 dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL;
0153 req.bpr_ptr = nilfs_direct_get_ptr(bmap, key);
0154
0155 ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat);
0156 if (!ret) {
0157 nilfs_bmap_commit_end_ptr(bmap, &req, dat);
0158 nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
0159 nilfs_inode_sub_blocks(bmap->b_inode, 1);
0160 }
0161 return ret;
0162 }
0163
0164 static int nilfs_direct_seek_key(const struct nilfs_bmap *direct, __u64 start,
0165 __u64 *keyp)
0166 {
0167 __u64 key;
0168
0169 for (key = start; key <= NILFS_DIRECT_KEY_MAX; key++) {
0170 if (nilfs_direct_get_ptr(direct, key) !=
0171 NILFS_BMAP_INVALID_PTR) {
0172 *keyp = key;
0173 return 0;
0174 }
0175 }
0176 return -ENOENT;
0177 }
0178
0179 static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp)
0180 {
0181 __u64 key, lastkey;
0182
0183 lastkey = NILFS_DIRECT_KEY_MAX + 1;
0184 for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++)
0185 if (nilfs_direct_get_ptr(direct, key) !=
0186 NILFS_BMAP_INVALID_PTR)
0187 lastkey = key;
0188
0189 if (lastkey == NILFS_DIRECT_KEY_MAX + 1)
0190 return -ENOENT;
0191
0192 *keyp = lastkey;
0193
0194 return 0;
0195 }
0196
0197 static int nilfs_direct_check_insert(const struct nilfs_bmap *bmap, __u64 key)
0198 {
0199 return key > NILFS_DIRECT_KEY_MAX;
0200 }
0201
0202 static int nilfs_direct_gather_data(struct nilfs_bmap *direct,
0203 __u64 *keys, __u64 *ptrs, int nitems)
0204 {
0205 __u64 key;
0206 __u64 ptr;
0207 int n;
0208
0209 if (nitems > NILFS_DIRECT_NBLOCKS)
0210 nitems = NILFS_DIRECT_NBLOCKS;
0211 n = 0;
0212 for (key = 0; key < nitems; key++) {
0213 ptr = nilfs_direct_get_ptr(direct, key);
0214 if (ptr != NILFS_BMAP_INVALID_PTR) {
0215 keys[n] = key;
0216 ptrs[n] = ptr;
0217 n++;
0218 }
0219 }
0220 return n;
0221 }
0222
0223 int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
0224 __u64 key, __u64 *keys, __u64 *ptrs, int n)
0225 {
0226 __le64 *dptrs;
0227 int ret, i, j;
0228
0229
0230
0231
0232 ret = bmap->b_ops->bop_delete(bmap, key);
0233 if (ret < 0)
0234 return ret;
0235
0236
0237 if (bmap->b_ops->bop_clear != NULL)
0238 bmap->b_ops->bop_clear(bmap);
0239
0240
0241 dptrs = nilfs_direct_dptrs(bmap);
0242 for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) {
0243 if ((j < n) && (i == keys[j])) {
0244 dptrs[i] = (i != key) ?
0245 cpu_to_le64(ptrs[j]) :
0246 NILFS_BMAP_INVALID_PTR;
0247 j++;
0248 } else
0249 dptrs[i] = NILFS_BMAP_INVALID_PTR;
0250 }
0251
0252 nilfs_direct_init(bmap);
0253 return 0;
0254 }
0255
0256 static int nilfs_direct_propagate(struct nilfs_bmap *bmap,
0257 struct buffer_head *bh)
0258 {
0259 struct nilfs_palloc_req oldreq, newreq;
0260 struct inode *dat;
0261 __u64 key;
0262 __u64 ptr;
0263 int ret;
0264
0265 if (!NILFS_BMAP_USE_VBN(bmap))
0266 return 0;
0267
0268 dat = nilfs_bmap_get_dat(bmap);
0269 key = nilfs_bmap_data_get_key(bmap, bh);
0270 ptr = nilfs_direct_get_ptr(bmap, key);
0271 if (!buffer_nilfs_volatile(bh)) {
0272 oldreq.pr_entry_nr = ptr;
0273 newreq.pr_entry_nr = ptr;
0274 ret = nilfs_dat_prepare_update(dat, &oldreq, &newreq);
0275 if (ret < 0)
0276 return ret;
0277 nilfs_dat_commit_update(dat, &oldreq, &newreq,
0278 bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
0279 set_buffer_nilfs_volatile(bh);
0280 nilfs_direct_set_ptr(bmap, key, newreq.pr_entry_nr);
0281 } else
0282 ret = nilfs_dat_mark_dirty(dat, ptr);
0283
0284 return ret;
0285 }
0286
0287 static int nilfs_direct_assign_v(struct nilfs_bmap *direct,
0288 __u64 key, __u64 ptr,
0289 struct buffer_head **bh,
0290 sector_t blocknr,
0291 union nilfs_binfo *binfo)
0292 {
0293 struct inode *dat = nilfs_bmap_get_dat(direct);
0294 union nilfs_bmap_ptr_req req;
0295 int ret;
0296
0297 req.bpr_ptr = ptr;
0298 ret = nilfs_dat_prepare_start(dat, &req.bpr_req);
0299 if (!ret) {
0300 nilfs_dat_commit_start(dat, &req.bpr_req, blocknr);
0301 binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr);
0302 binfo->bi_v.bi_blkoff = cpu_to_le64(key);
0303 }
0304 return ret;
0305 }
0306
0307 static int nilfs_direct_assign_p(struct nilfs_bmap *direct,
0308 __u64 key, __u64 ptr,
0309 struct buffer_head **bh,
0310 sector_t blocknr,
0311 union nilfs_binfo *binfo)
0312 {
0313 nilfs_direct_set_ptr(direct, key, blocknr);
0314
0315 binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
0316 binfo->bi_dat.bi_level = 0;
0317
0318 return 0;
0319 }
0320
0321 static int nilfs_direct_assign(struct nilfs_bmap *bmap,
0322 struct buffer_head **bh,
0323 sector_t blocknr,
0324 union nilfs_binfo *binfo)
0325 {
0326 __u64 key;
0327 __u64 ptr;
0328
0329 key = nilfs_bmap_data_get_key(bmap, *bh);
0330 if (unlikely(key > NILFS_DIRECT_KEY_MAX)) {
0331 nilfs_crit(bmap->b_inode->i_sb,
0332 "%s (ino=%lu): invalid key: %llu",
0333 __func__,
0334 bmap->b_inode->i_ino, (unsigned long long)key);
0335 return -EINVAL;
0336 }
0337 ptr = nilfs_direct_get_ptr(bmap, key);
0338 if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) {
0339 nilfs_crit(bmap->b_inode->i_sb,
0340 "%s (ino=%lu): invalid pointer: %llu",
0341 __func__,
0342 bmap->b_inode->i_ino, (unsigned long long)ptr);
0343 return -EINVAL;
0344 }
0345
0346 return NILFS_BMAP_USE_VBN(bmap) ?
0347 nilfs_direct_assign_v(bmap, key, ptr, bh, blocknr, binfo) :
0348 nilfs_direct_assign_p(bmap, key, ptr, bh, blocknr, binfo);
0349 }
0350
0351 static const struct nilfs_bmap_operations nilfs_direct_ops = {
0352 .bop_lookup = nilfs_direct_lookup,
0353 .bop_lookup_contig = nilfs_direct_lookup_contig,
0354 .bop_insert = nilfs_direct_insert,
0355 .bop_delete = nilfs_direct_delete,
0356 .bop_clear = NULL,
0357
0358 .bop_propagate = nilfs_direct_propagate,
0359
0360 .bop_lookup_dirty_buffers = NULL,
0361
0362 .bop_assign = nilfs_direct_assign,
0363 .bop_mark = NULL,
0364
0365 .bop_seek_key = nilfs_direct_seek_key,
0366 .bop_last_key = nilfs_direct_last_key,
0367
0368 .bop_check_insert = nilfs_direct_check_insert,
0369 .bop_check_delete = NULL,
0370 .bop_gather_data = nilfs_direct_gather_data,
0371 };
0372
0373
0374 int nilfs_direct_init(struct nilfs_bmap *bmap)
0375 {
0376 bmap->b_ops = &nilfs_direct_ops;
0377 return 0;
0378 }