root/fs/nilfs2/dat.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. NILFS_DAT_I
  2. nilfs_dat_prepare_entry
  3. nilfs_dat_commit_entry
  4. nilfs_dat_abort_entry
  5. nilfs_dat_prepare_alloc
  6. nilfs_dat_commit_alloc
  7. nilfs_dat_abort_alloc
  8. nilfs_dat_commit_free
  9. nilfs_dat_prepare_start
  10. nilfs_dat_commit_start
  11. nilfs_dat_prepare_end
  12. nilfs_dat_commit_end
  13. nilfs_dat_abort_end
  14. nilfs_dat_prepare_update
  15. nilfs_dat_commit_update
  16. nilfs_dat_abort_update
  17. nilfs_dat_mark_dirty
  18. nilfs_dat_freev
  19. nilfs_dat_move
  20. nilfs_dat_translate
  21. nilfs_dat_get_vinfo
  22. nilfs_dat_read

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * dat.c - NILFS disk address translation.
   4  *
   5  * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation.
   6  *
   7  * Written by Koji Sato.
   8  */
   9 
  10 #include <linux/types.h>
  11 #include <linux/buffer_head.h>
  12 #include <linux/string.h>
  13 #include <linux/errno.h>
  14 #include "nilfs.h"
  15 #include "mdt.h"
  16 #include "alloc.h"
  17 #include "dat.h"
  18 
  19 
  20 #define NILFS_CNO_MIN   ((__u64)1)
  21 #define NILFS_CNO_MAX   (~(__u64)0)
  22 
  23 /**
  24  * struct nilfs_dat_info - on-memory private data of DAT file
  25  * @mi: on-memory private data of metadata file
  26  * @palloc_cache: persistent object allocator cache of DAT file
  27  * @shadow: shadow map of DAT file
  28  */
  29 struct nilfs_dat_info {
  30         struct nilfs_mdt_info mi;
  31         struct nilfs_palloc_cache palloc_cache;
  32         struct nilfs_shadow_map shadow;
  33 };
  34 
  35 static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat)
  36 {
  37         return (struct nilfs_dat_info *)NILFS_MDT(dat);
  38 }
  39 
  40 static int nilfs_dat_prepare_entry(struct inode *dat,
  41                                    struct nilfs_palloc_req *req, int create)
  42 {
  43         return nilfs_palloc_get_entry_block(dat, req->pr_entry_nr,
  44                                             create, &req->pr_entry_bh);
  45 }
  46 
  47 static void nilfs_dat_commit_entry(struct inode *dat,
  48                                    struct nilfs_palloc_req *req)
  49 {
  50         mark_buffer_dirty(req->pr_entry_bh);
  51         nilfs_mdt_mark_dirty(dat);
  52         brelse(req->pr_entry_bh);
  53 }
  54 
  55 static void nilfs_dat_abort_entry(struct inode *dat,
  56                                   struct nilfs_palloc_req *req)
  57 {
  58         brelse(req->pr_entry_bh);
  59 }
  60 
  61 int nilfs_dat_prepare_alloc(struct inode *dat, struct nilfs_palloc_req *req)
  62 {
  63         int ret;
  64 
  65         ret = nilfs_palloc_prepare_alloc_entry(dat, req);
  66         if (ret < 0)
  67                 return ret;
  68 
  69         ret = nilfs_dat_prepare_entry(dat, req, 1);
  70         if (ret < 0)
  71                 nilfs_palloc_abort_alloc_entry(dat, req);
  72 
  73         return ret;
  74 }
  75 
  76 void nilfs_dat_commit_alloc(struct inode *dat, struct nilfs_palloc_req *req)
  77 {
  78         struct nilfs_dat_entry *entry;
  79         void *kaddr;
  80 
  81         kaddr = kmap_atomic(req->pr_entry_bh->b_page);
  82         entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
  83                                              req->pr_entry_bh, kaddr);
  84         entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
  85         entry->de_end = cpu_to_le64(NILFS_CNO_MAX);
  86         entry->de_blocknr = cpu_to_le64(0);
  87         kunmap_atomic(kaddr);
  88 
  89         nilfs_palloc_commit_alloc_entry(dat, req);
  90         nilfs_dat_commit_entry(dat, req);
  91 }
  92 
  93 void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
  94 {
  95         nilfs_dat_abort_entry(dat, req);
  96         nilfs_palloc_abort_alloc_entry(dat, req);
  97 }
  98 
  99 static void nilfs_dat_commit_free(struct inode *dat,
 100                                   struct nilfs_palloc_req *req)
 101 {
 102         struct nilfs_dat_entry *entry;
 103         void *kaddr;
 104 
 105         kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 106         entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 107                                              req->pr_entry_bh, kaddr);
 108         entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
 109         entry->de_end = cpu_to_le64(NILFS_CNO_MIN);
 110         entry->de_blocknr = cpu_to_le64(0);
 111         kunmap_atomic(kaddr);
 112 
 113         nilfs_dat_commit_entry(dat, req);
 114         nilfs_palloc_commit_free_entry(dat, req);
 115 }
 116 
 117 int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req)
 118 {
 119         int ret;
 120 
 121         ret = nilfs_dat_prepare_entry(dat, req, 0);
 122         WARN_ON(ret == -ENOENT);
 123         return ret;
 124 }
 125 
 126 void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
 127                             sector_t blocknr)
 128 {
 129         struct nilfs_dat_entry *entry;
 130         void *kaddr;
 131 
 132         kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 133         entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 134                                              req->pr_entry_bh, kaddr);
 135         entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat));
 136         entry->de_blocknr = cpu_to_le64(blocknr);
 137         kunmap_atomic(kaddr);
 138 
 139         nilfs_dat_commit_entry(dat, req);
 140 }
 141 
 142 int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
 143 {
 144         struct nilfs_dat_entry *entry;
 145         sector_t blocknr;
 146         void *kaddr;
 147         int ret;
 148 
 149         ret = nilfs_dat_prepare_entry(dat, req, 0);
 150         if (ret < 0) {
 151                 WARN_ON(ret == -ENOENT);
 152                 return ret;
 153         }
 154 
 155         kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 156         entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 157                                              req->pr_entry_bh, kaddr);
 158         blocknr = le64_to_cpu(entry->de_blocknr);
 159         kunmap_atomic(kaddr);
 160 
 161         if (blocknr == 0) {
 162                 ret = nilfs_palloc_prepare_free_entry(dat, req);
 163                 if (ret < 0) {
 164                         nilfs_dat_abort_entry(dat, req);
 165                         return ret;
 166                 }
 167         }
 168 
 169         return 0;
 170 }
 171 
 172 void nilfs_dat_commit_end(struct inode *dat, struct nilfs_palloc_req *req,
 173                           int dead)
 174 {
 175         struct nilfs_dat_entry *entry;
 176         __u64 start, end;
 177         sector_t blocknr;
 178         void *kaddr;
 179 
 180         kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 181         entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 182                                              req->pr_entry_bh, kaddr);
 183         end = start = le64_to_cpu(entry->de_start);
 184         if (!dead) {
 185                 end = nilfs_mdt_cno(dat);
 186                 WARN_ON(start > end);
 187         }
 188         entry->de_end = cpu_to_le64(end);
 189         blocknr = le64_to_cpu(entry->de_blocknr);
 190         kunmap_atomic(kaddr);
 191 
 192         if (blocknr == 0)
 193                 nilfs_dat_commit_free(dat, req);
 194         else
 195                 nilfs_dat_commit_entry(dat, req);
 196 }
 197 
 198 void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req)
 199 {
 200         struct nilfs_dat_entry *entry;
 201         __u64 start;
 202         sector_t blocknr;
 203         void *kaddr;
 204 
 205         kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 206         entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 207                                              req->pr_entry_bh, kaddr);
 208         start = le64_to_cpu(entry->de_start);
 209         blocknr = le64_to_cpu(entry->de_blocknr);
 210         kunmap_atomic(kaddr);
 211 
 212         if (start == nilfs_mdt_cno(dat) && blocknr == 0)
 213                 nilfs_palloc_abort_free_entry(dat, req);
 214         nilfs_dat_abort_entry(dat, req);
 215 }
 216 
 217 int nilfs_dat_prepare_update(struct inode *dat,
 218                              struct nilfs_palloc_req *oldreq,
 219                              struct nilfs_palloc_req *newreq)
 220 {
 221         int ret;
 222 
 223         ret = nilfs_dat_prepare_end(dat, oldreq);
 224         if (!ret) {
 225                 ret = nilfs_dat_prepare_alloc(dat, newreq);
 226                 if (ret < 0)
 227                         nilfs_dat_abort_end(dat, oldreq);
 228         }
 229         return ret;
 230 }
 231 
 232 void nilfs_dat_commit_update(struct inode *dat,
 233                              struct nilfs_palloc_req *oldreq,
 234                              struct nilfs_palloc_req *newreq, int dead)
 235 {
 236         nilfs_dat_commit_end(dat, oldreq, dead);
 237         nilfs_dat_commit_alloc(dat, newreq);
 238 }
 239 
 240 void nilfs_dat_abort_update(struct inode *dat,
 241                             struct nilfs_palloc_req *oldreq,
 242                             struct nilfs_palloc_req *newreq)
 243 {
 244         nilfs_dat_abort_end(dat, oldreq);
 245         nilfs_dat_abort_alloc(dat, newreq);
 246 }
 247 
 248 /**
 249  * nilfs_dat_mark_dirty -
 250  * @dat: DAT file inode
 251  * @vblocknr: virtual block number
 252  *
 253  * Description:
 254  *
 255  * Return Value: On success, 0 is returned. On error, one of the following
 256  * negative error codes is returned.
 257  *
 258  * %-EIO - I/O error.
 259  *
 260  * %-ENOMEM - Insufficient amount of memory available.
 261  */
 262 int nilfs_dat_mark_dirty(struct inode *dat, __u64 vblocknr)
 263 {
 264         struct nilfs_palloc_req req;
 265         int ret;
 266 
 267         req.pr_entry_nr = vblocknr;
 268         ret = nilfs_dat_prepare_entry(dat, &req, 0);
 269         if (ret == 0)
 270                 nilfs_dat_commit_entry(dat, &req);
 271         return ret;
 272 }
 273 
 274 /**
 275  * nilfs_dat_freev - free virtual block numbers
 276  * @dat: DAT file inode
 277  * @vblocknrs: array of virtual block numbers
 278  * @nitems: number of virtual block numbers
 279  *
 280  * Description: nilfs_dat_freev() frees the virtual block numbers specified by
 281  * @vblocknrs and @nitems.
 282  *
 283  * Return Value: On success, 0 is returned. On error, one of the following
 284  * negative error codes is returned.
 285  *
 286  * %-EIO - I/O error.
 287  *
 288  * %-ENOMEM - Insufficient amount of memory available.
 289  *
 290  * %-ENOENT - The virtual block number have not been allocated.
 291  */
 292 int nilfs_dat_freev(struct inode *dat, __u64 *vblocknrs, size_t nitems)
 293 {
 294         return nilfs_palloc_freev(dat, vblocknrs, nitems);
 295 }
 296 
 297 /**
 298  * nilfs_dat_move - change a block number
 299  * @dat: DAT file inode
 300  * @vblocknr: virtual block number
 301  * @blocknr: block number
 302  *
 303  * Description: nilfs_dat_move() changes the block number associated with
 304  * @vblocknr to @blocknr.
 305  *
 306  * Return Value: On success, 0 is returned. On error, one of the following
 307  * negative error codes is returned.
 308  *
 309  * %-EIO - I/O error.
 310  *
 311  * %-ENOMEM - Insufficient amount of memory available.
 312  */
 313 int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
 314 {
 315         struct buffer_head *entry_bh;
 316         struct nilfs_dat_entry *entry;
 317         void *kaddr;
 318         int ret;
 319 
 320         ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
 321         if (ret < 0)
 322                 return ret;
 323 
 324         /*
 325          * The given disk block number (blocknr) is not yet written to
 326          * the device at this point.
 327          *
 328          * To prevent nilfs_dat_translate() from returning the
 329          * uncommitted block number, this makes a copy of the entry
 330          * buffer and redirects nilfs_dat_translate() to the copy.
 331          */
 332         if (!buffer_nilfs_redirected(entry_bh)) {
 333                 ret = nilfs_mdt_freeze_buffer(dat, entry_bh);
 334                 if (ret) {
 335                         brelse(entry_bh);
 336                         return ret;
 337                 }
 338         }
 339 
 340         kaddr = kmap_atomic(entry_bh->b_page);
 341         entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
 342         if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
 343                 nilfs_msg(dat->i_sb, KERN_CRIT,
 344                           "%s: invalid vblocknr = %llu, [%llu, %llu)",
 345                           __func__, (unsigned long long)vblocknr,
 346                           (unsigned long long)le64_to_cpu(entry->de_start),
 347                           (unsigned long long)le64_to_cpu(entry->de_end));
 348                 kunmap_atomic(kaddr);
 349                 brelse(entry_bh);
 350                 return -EINVAL;
 351         }
 352         WARN_ON(blocknr == 0);
 353         entry->de_blocknr = cpu_to_le64(blocknr);
 354         kunmap_atomic(kaddr);
 355 
 356         mark_buffer_dirty(entry_bh);
 357         nilfs_mdt_mark_dirty(dat);
 358 
 359         brelse(entry_bh);
 360 
 361         return 0;
 362 }
 363 
 364 /**
 365  * nilfs_dat_translate - translate a virtual block number to a block number
 366  * @dat: DAT file inode
 367  * @vblocknr: virtual block number
 368  * @blocknrp: pointer to a block number
 369  *
 370  * Description: nilfs_dat_translate() maps the virtual block number @vblocknr
 371  * to the corresponding block number.
 372  *
 373  * Return Value: On success, 0 is returned and the block number associated
 374  * with @vblocknr is stored in the place pointed by @blocknrp. On error, one
 375  * of the following negative error codes is returned.
 376  *
 377  * %-EIO - I/O error.
 378  *
 379  * %-ENOMEM - Insufficient amount of memory available.
 380  *
 381  * %-ENOENT - A block number associated with @vblocknr does not exist.
 382  */
 383 int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
 384 {
 385         struct buffer_head *entry_bh, *bh;
 386         struct nilfs_dat_entry *entry;
 387         sector_t blocknr;
 388         void *kaddr;
 389         int ret;
 390 
 391         ret = nilfs_palloc_get_entry_block(dat, vblocknr, 0, &entry_bh);
 392         if (ret < 0)
 393                 return ret;
 394 
 395         if (!nilfs_doing_gc() && buffer_nilfs_redirected(entry_bh)) {
 396                 bh = nilfs_mdt_get_frozen_buffer(dat, entry_bh);
 397                 if (bh) {
 398                         WARN_ON(!buffer_uptodate(bh));
 399                         brelse(entry_bh);
 400                         entry_bh = bh;
 401                 }
 402         }
 403 
 404         kaddr = kmap_atomic(entry_bh->b_page);
 405         entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
 406         blocknr = le64_to_cpu(entry->de_blocknr);
 407         if (blocknr == 0) {
 408                 ret = -ENOENT;
 409                 goto out;
 410         }
 411         *blocknrp = blocknr;
 412 
 413  out:
 414         kunmap_atomic(kaddr);
 415         brelse(entry_bh);
 416         return ret;
 417 }
 418 
 419 ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned int visz,
 420                             size_t nvi)
 421 {
 422         struct buffer_head *entry_bh;
 423         struct nilfs_dat_entry *entry;
 424         struct nilfs_vinfo *vinfo = buf;
 425         __u64 first, last;
 426         void *kaddr;
 427         unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
 428         int i, j, n, ret;
 429 
 430         for (i = 0; i < nvi; i += n) {
 431                 ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
 432                                                    0, &entry_bh);
 433                 if (ret < 0)
 434                         return ret;
 435                 kaddr = kmap_atomic(entry_bh->b_page);
 436                 /* last virtual block number in this block */
 437                 first = vinfo->vi_vblocknr;
 438                 do_div(first, entries_per_block);
 439                 first *= entries_per_block;
 440                 last = first + entries_per_block - 1;
 441                 for (j = i, n = 0;
 442                      j < nvi && vinfo->vi_vblocknr >= first &&
 443                              vinfo->vi_vblocknr <= last;
 444                      j++, n++, vinfo = (void *)vinfo + visz) {
 445                         entry = nilfs_palloc_block_get_entry(
 446                                 dat, vinfo->vi_vblocknr, entry_bh, kaddr);
 447                         vinfo->vi_start = le64_to_cpu(entry->de_start);
 448                         vinfo->vi_end = le64_to_cpu(entry->de_end);
 449                         vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
 450                 }
 451                 kunmap_atomic(kaddr);
 452                 brelse(entry_bh);
 453         }
 454 
 455         return nvi;
 456 }
 457 
 458 /**
 459  * nilfs_dat_read - read or get dat inode
 460  * @sb: super block instance
 461  * @entry_size: size of a dat entry
 462  * @raw_inode: on-disk dat inode
 463  * @inodep: buffer to store the inode
 464  */
 465 int nilfs_dat_read(struct super_block *sb, size_t entry_size,
 466                    struct nilfs_inode *raw_inode, struct inode **inodep)
 467 {
 468         static struct lock_class_key dat_lock_key;
 469         struct inode *dat;
 470         struct nilfs_dat_info *di;
 471         int err;
 472 
 473         if (entry_size > sb->s_blocksize) {
 474                 nilfs_msg(sb, KERN_ERR, "too large DAT entry size: %zu bytes",
 475                           entry_size);
 476                 return -EINVAL;
 477         } else if (entry_size < NILFS_MIN_DAT_ENTRY_SIZE) {
 478                 nilfs_msg(sb, KERN_ERR, "too small DAT entry size: %zu bytes",
 479                           entry_size);
 480                 return -EINVAL;
 481         }
 482 
 483         dat = nilfs_iget_locked(sb, NULL, NILFS_DAT_INO);
 484         if (unlikely(!dat))
 485                 return -ENOMEM;
 486         if (!(dat->i_state & I_NEW))
 487                 goto out;
 488 
 489         err = nilfs_mdt_init(dat, NILFS_MDT_GFP, sizeof(*di));
 490         if (err)
 491                 goto failed;
 492 
 493         err = nilfs_palloc_init_blockgroup(dat, entry_size);
 494         if (err)
 495                 goto failed;
 496 
 497         di = NILFS_DAT_I(dat);
 498         lockdep_set_class(&di->mi.mi_sem, &dat_lock_key);
 499         nilfs_palloc_setup_cache(dat, &di->palloc_cache);
 500         nilfs_mdt_setup_shadow_map(dat, &di->shadow);
 501 
 502         err = nilfs_read_inode_common(dat, raw_inode);
 503         if (err)
 504                 goto failed;
 505 
 506         unlock_new_inode(dat);
 507  out:
 508         *inodep = dat;
 509         return 0;
 510  failed:
 511         iget_failed(dat);
 512         return err;
 513 }

/* [<][>][^][v][top][bottom][index][help] */