linux/fs/reiserfs/tail_conversion.c
<<
>>
Prefs
   1/*
   2 * Copyright 1999 Hans Reiser, see reiserfs/README for licensing and copyright details
   3 */
   4
   5#include <linux/time.h>
   6#include <linux/pagemap.h>
   7#include <linux/buffer_head.h>
   8#include "reiserfs.h"
   9
  10/* access to tail : when one is going to read tail it must make sure, that is not running.
  11 direct2indirect and indirect2direct can not run concurrently */
  12
  13/* Converts direct items to an unformatted node. Panics if file has no
  14   tail. -ENOSPC if no disk space for conversion */
  15/* path points to first direct item of the file regarless of how many of
  16   them are there */
  17int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
  18                    struct treepath *path, struct buffer_head *unbh,
  19                    loff_t tail_offset)
  20{
  21        struct super_block *sb = inode->i_sb;
  22        struct buffer_head *up_to_date_bh;
  23        struct item_head *p_le_ih = PATH_PITEM_HEAD(path);
  24        unsigned long total_tail = 0;
  25        struct cpu_key end_key; /* Key to search for the last byte of the
  26                                   converted item. */
  27        struct item_head ind_ih;        /* new indirect item to be inserted or
  28                                           key of unfm pointer to be pasted */
  29        int blk_size, retval;   /* returned value for reiserfs_insert_item and clones */
  30        unp_t unfm_ptr;         /* Handle on an unformatted node
  31                                   that will be inserted in the
  32                                   tree. */
  33
  34        BUG_ON(!th->t_trans_id);
  35
  36        REISERFS_SB(sb)->s_direct2indirect++;
  37
  38        blk_size = sb->s_blocksize;
  39
  40        /* and key to search for append or insert pointer to the new
  41           unformatted node. */
  42        copy_item_head(&ind_ih, p_le_ih);
  43        set_le_ih_k_offset(&ind_ih, tail_offset);
  44        set_le_ih_k_type(&ind_ih, TYPE_INDIRECT);
  45
  46        /* Set the key to search for the place for new unfm pointer */
  47        make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4);
  48
  49        /* FIXME: we could avoid this */
  50        if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) {
  51                reiserfs_error(sb, "PAP-14030",
  52                               "pasted or inserted byte exists in "
  53                               "the tree %K. Use fsck to repair.", &end_key);
  54                pathrelse(path);
  55                return -EIO;
  56        }
  57
  58        p_le_ih = PATH_PITEM_HEAD(path);
  59
  60        unfm_ptr = cpu_to_le32(unbh->b_blocknr);
  61
  62        if (is_statdata_le_ih(p_le_ih)) {
  63                /* Insert new indirect item. */
  64                set_ih_free_space(&ind_ih, 0);  /* delete at nearest future */
  65                put_ih_item_len(&ind_ih, UNFM_P_SIZE);
  66                PATH_LAST_POSITION(path)++;
  67                retval =
  68                    reiserfs_insert_item(th, path, &end_key, &ind_ih, inode,
  69                                         (char *)&unfm_ptr);
  70        } else {
  71                /* Paste into last indirect item of an object. */
  72                retval = reiserfs_paste_into_item(th, path, &end_key, inode,
  73                                                    (char *)&unfm_ptr,
  74                                                    UNFM_P_SIZE);
  75        }
  76        if (retval) {
  77                return retval;
  78        }
  79        // note: from here there are two keys which have matching first
  80        // three key components. They only differ by the fourth one.
  81
  82        /* Set the key to search for the direct items of the file */
  83        make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT,
  84                     4);
  85
  86        /* Move bytes from the direct items to the new unformatted node
  87           and delete them. */
  88        while (1) {
  89                int tail_size;
  90
  91                /* end_key.k_offset is set so, that we will always have found
  92                   last item of the file */
  93                if (search_for_position_by_key(sb, &end_key, path) ==
  94                    POSITION_FOUND)
  95                        reiserfs_panic(sb, "PAP-14050",
  96                                       "direct item (%K) not found", &end_key);
  97                p_le_ih = PATH_PITEM_HEAD(path);
  98                RFALSE(!is_direct_le_ih(p_le_ih),
  99                       "vs-14055: direct item expected(%K), found %h",
 100                       &end_key, p_le_ih);
 101                tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1))
 102                    + ih_item_len(p_le_ih) - 1;
 103
 104                /* we only send the unbh pointer if the buffer is not up to date.
 105                 ** this avoids overwriting good data from writepage() with old data
 106                 ** from the disk or buffer cache
 107                 ** Special case: unbh->b_page will be NULL if we are coming through
 108                 ** DIRECT_IO handler here.
 109                 */
 110                if (!unbh->b_page || buffer_uptodate(unbh)
 111                    || PageUptodate(unbh->b_page)) {
 112                        up_to_date_bh = NULL;
 113                } else {
 114                        up_to_date_bh = unbh;
 115                }
 116                retval = reiserfs_delete_item(th, path, &end_key, inode,
 117                                                up_to_date_bh);
 118
 119                total_tail += retval;
 120                if (tail_size == retval)
 121                        // done: file does not have direct items anymore
 122                        break;
 123
 124        }
 125        /* if we've copied bytes from disk into the page, we need to zero
 126         ** out the unused part of the block (it was not up to date before)
 127         */
 128        if (up_to_date_bh) {
 129                unsigned pgoff =
 130                    (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1);
 131                char *kaddr = kmap_atomic(up_to_date_bh->b_page);
 132                memset(kaddr + pgoff, 0, blk_size - total_tail);
 133                kunmap_atomic(kaddr);
 134        }
 135
 136        REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
 137
 138        return 0;
 139}
 140
 141/* stolen from fs/buffer.c */
 142void reiserfs_unmap_buffer(struct buffer_head *bh)
 143{
 144        lock_buffer(bh);
 145        if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
 146                BUG();
 147        }
 148        clear_buffer_dirty(bh);
 149        /* Remove the buffer from whatever list it belongs to. We are mostly
 150           interested in removing it from per-sb j_dirty_buffers list, to avoid
 151           BUG() on attempt to write not mapped buffer */
 152        if ((!list_empty(&bh->b_assoc_buffers) || bh->b_private) && bh->b_page) {
 153                struct inode *inode = bh->b_page->mapping->host;
 154                struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
 155                spin_lock(&j->j_dirty_buffers_lock);
 156                list_del_init(&bh->b_assoc_buffers);
 157                reiserfs_free_jh(bh);
 158                spin_unlock(&j->j_dirty_buffers_lock);
 159        }
 160        clear_buffer_mapped(bh);
 161        clear_buffer_req(bh);
 162        clear_buffer_new(bh);
 163        bh->b_bdev = NULL;
 164        unlock_buffer(bh);
 165}
 166
 167/* this first locks inode (neither reads nor sync are permitted),
 168   reads tail through page cache, insert direct item. When direct item
 169   inserted successfully inode is left locked. Return value is always
 170   what we expect from it (number of cut bytes). But when tail remains
 171   in the unformatted node, we set mode to SKIP_BALANCING and unlock
 172   inode */
 173int indirect2direct(struct reiserfs_transaction_handle *th,
 174                    struct inode *inode, struct page *page,
 175                    struct treepath *path,      /* path to the indirect item. */
 176                    const struct cpu_key *item_key,     /* Key to look for
 177                                                         * unformatted node
 178                                                         * pointer to be cut. */
 179                    loff_t n_new_file_size,     /* New file size. */
 180                    char *mode)
 181{
 182        struct super_block *sb = inode->i_sb;
 183        struct item_head s_ih;
 184        unsigned long block_size = sb->s_blocksize;
 185        char *tail;
 186        int tail_len, round_tail_len;
 187        loff_t pos, pos1;       /* position of first byte of the tail */
 188        struct cpu_key key;
 189
 190        BUG_ON(!th->t_trans_id);
 191
 192        REISERFS_SB(sb)->s_indirect2direct++;
 193
 194        *mode = M_SKIP_BALANCING;
 195
 196        /* store item head path points to. */
 197        copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
 198
 199        tail_len = (n_new_file_size & (block_size - 1));
 200        if (get_inode_sd_version(inode) == STAT_DATA_V2)
 201                round_tail_len = ROUND_UP(tail_len);
 202        else
 203                round_tail_len = tail_len;
 204
 205        pos =
 206            le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE -
 207                                         1) * sb->s_blocksize;
 208        pos1 = pos;
 209
 210        // we are protected by i_mutex. The tail can not disapper, not
 211        // append can be done either
 212        // we are in truncate or packing tail in file_release
 213
 214        tail = (char *)kmap(page);      /* this can schedule */
 215
 216        if (path_changed(&s_ih, path)) {
 217                /* re-search indirect item */
 218                if (search_for_position_by_key(sb, item_key, path)
 219                    == POSITION_NOT_FOUND)
 220                        reiserfs_panic(sb, "PAP-5520",
 221                                       "item to be converted %K does not exist",
 222                                       item_key);
 223                copy_item_head(&s_ih, PATH_PITEM_HEAD(path));
 224#ifdef CONFIG_REISERFS_CHECK
 225                pos = le_ih_k_offset(&s_ih) - 1 +
 226                    (ih_item_len(&s_ih) / UNFM_P_SIZE -
 227                     1) * sb->s_blocksize;
 228                if (pos != pos1)
 229                        reiserfs_panic(sb, "vs-5530", "tail position "
 230                                       "changed while we were reading it");
 231#endif
 232        }
 233
 234        /* Set direct item header to insert. */
 235        make_le_item_head(&s_ih, NULL, get_inode_item_key_version(inode),
 236                          pos1 + 1, TYPE_DIRECT, round_tail_len,
 237                          0xffff /*ih_free_space */ );
 238
 239        /* we want a pointer to the first byte of the tail in the page.
 240         ** the page was locked and this part of the page was up to date when
 241         ** indirect2direct was called, so we know the bytes are still valid
 242         */
 243        tail = tail + (pos & (PAGE_CACHE_SIZE - 1));
 244
 245        PATH_LAST_POSITION(path)++;
 246
 247        key = *item_key;
 248        set_cpu_key_k_type(&key, TYPE_DIRECT);
 249        key.key_length = 4;
 250        /* Insert tail as new direct item in the tree */
 251        if (reiserfs_insert_item(th, path, &key, &s_ih, inode,
 252                                 tail ? tail : NULL) < 0) {
 253                /* No disk memory. So we can not convert last unformatted node
 254                   to the direct item.  In this case we used to adjust
 255                   indirect items's ih_free_space. Now ih_free_space is not
 256                   used, it would be ideal to write zeros to corresponding
 257                   unformatted node. For now i_size is considered as guard for
 258                   going out of file size */
 259                kunmap(page);
 260                return block_size - round_tail_len;
 261        }
 262        kunmap(page);
 263
 264        /* make sure to get the i_blocks changes from reiserfs_insert_item */
 265        reiserfs_update_sd(th, inode);
 266
 267        // note: we have now the same as in above direct2indirect
 268        // conversion: there are two keys which have matching first three
 269        // key components. They only differ by the fouhth one.
 270
 271        /* We have inserted new direct item and must remove last
 272           unformatted node. */
 273        *mode = M_CUT;
 274
 275        /* we store position of first direct item in the in-core inode */
 276        /* mark_file_with_tail (inode, pos1 + 1); */
 277        REISERFS_I(inode)->i_first_direct_byte = pos1 + 1;
 278
 279        return block_size - round_tail_len;
 280}
 281
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.