linux/fs/ufs/truncate.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/ufs/truncate.c
   3 *
   4 * Copyright (C) 1998
   5 * Daniel Pirkl <daniel.pirkl@email.cz>
   6 * Charles University, Faculty of Mathematics and Physics
   7 *
   8 *  from
   9 *
  10 *  linux/fs/ext2/truncate.c
  11 *
  12 * Copyright (C) 1992, 1993, 1994, 1995
  13 * Remy Card (card@masi.ibp.fr)
  14 * Laboratoire MASI - Institut Blaise Pascal
  15 * Universite Pierre et Marie Curie (Paris VI)
  16 *
  17 *  from
  18 *
  19 *  linux/fs/minix/truncate.c
  20 *
  21 *  Copyright (C) 1991, 1992  Linus Torvalds
  22 *
  23 *  Big-endian to little-endian byte-swapping/bitmaps by
  24 *        David S. Miller (davem@caip.rutgers.edu), 1995
  25 */
  26
  27/*
  28 * Real random numbers for secure rm added 94/02/18
  29 * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
  30 */
  31
  32/*
  33 * Adoptation to use page cache and UFS2 write support by
  34 * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007
  35 */
  36
  37#include <linux/errno.h>
  38#include <linux/fs.h>
  39#include <linux/ufs_fs.h>
  40#include <linux/fcntl.h>
  41#include <linux/time.h>
  42#include <linux/stat.h>
  43#include <linux/string.h>
  44#include <linux/smp_lock.h>
  45#include <linux/buffer_head.h>
  46#include <linux/blkdev.h>
  47#include <linux/sched.h>
  48
  49#include "ufs.h"
  50#include "swab.h"
  51#include "util.h"
  52
  53/*
  54 * Secure deletion currently doesn't work. It interacts very badly
  55 * with buffers shared with memory mappings, and for that reason
  56 * can't be done in the truncate() routines. It should instead be
  57 * done separately in "release()" before calling the truncate routines
  58 * that will release the actual file blocks.
  59 *
  60 *              Linus
  61 */
  62
  63#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
  64#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
  65
  66
  67static int ufs_trunc_direct(struct inode *inode)
  68{
  69        struct ufs_inode_info *ufsi = UFS_I(inode);
  70        struct super_block * sb;
  71        struct ufs_sb_private_info * uspi;
  72        void *p;
  73        u64 frag1, frag2, frag3, frag4, block1, block2;
  74        unsigned frag_to_free, free_count;
  75        unsigned i, tmp;
  76        int retry;
  77        
  78        UFSD("ENTER: ino %lu\n", inode->i_ino);
  79
  80        sb = inode->i_sb;
  81        uspi = UFS_SB(sb)->s_uspi;
  82        
  83        frag_to_free = 0;
  84        free_count = 0;
  85        retry = 0;
  86        
  87        frag1 = DIRECT_FRAGMENT;
  88        frag4 = min_t(u32, UFS_NDIR_FRAGMENT, ufsi->i_lastfrag);
  89        frag2 = ((frag1 & uspi->s_fpbmask) ? ((frag1 | uspi->s_fpbmask) + 1) : frag1);
  90        frag3 = frag4 & ~uspi->s_fpbmask;
  91        block1 = block2 = 0;
  92        if (frag2 > frag3) {
  93                frag2 = frag4;
  94                frag3 = frag4 = 0;
  95        } else if (frag2 < frag3) {
  96                block1 = ufs_fragstoblks (frag2);
  97                block2 = ufs_fragstoblks (frag3);
  98        }
  99
 100        UFSD("ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
 101             " frag3 %llu, frag4 %llu\n", inode->i_ino,
 102             (unsigned long long)frag1, (unsigned long long)frag2,
 103             (unsigned long long)block1, (unsigned long long)block2,
 104             (unsigned long long)frag3, (unsigned long long)frag4);
 105
 106        if (frag1 >= frag2)
 107                goto next1;             
 108
 109        /*
 110         * Free first free fragments
 111         */
 112        p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1));
 113        tmp = ufs_data_ptr_to_cpu(sb, p);
 114        if (!tmp )
 115                ufs_panic (sb, "ufs_trunc_direct", "internal error");
 116        frag2 -= frag1;
 117        frag1 = ufs_fragnum (frag1);
 118
 119        ufs_free_fragments(inode, tmp + frag1, frag2);
 120        mark_inode_dirty(inode);
 121        frag_to_free = tmp + frag1;
 122
 123next1:
 124        /*
 125         * Free whole blocks
 126         */
 127        for (i = block1 ; i < block2; i++) {
 128                p = ufs_get_direct_data_ptr(uspi, ufsi, i);
 129                tmp = ufs_data_ptr_to_cpu(sb, p);
 130                if (!tmp)
 131                        continue;
 132                ufs_data_ptr_clear(uspi, p);
 133
 134                if (free_count == 0) {
 135                        frag_to_free = tmp;
 136                        free_count = uspi->s_fpb;
 137                } else if (free_count > 0 && frag_to_free == tmp - free_count)
 138                        free_count += uspi->s_fpb;
 139                else {
 140                        ufs_free_blocks (inode, frag_to_free, free_count);
 141                        frag_to_free = tmp;
 142                        free_count = uspi->s_fpb;
 143                }
 144                mark_inode_dirty(inode);
 145        }
 146        
 147        if (free_count > 0)
 148                ufs_free_blocks (inode, frag_to_free, free_count);
 149
 150        if (frag3 >= frag4)
 151                goto next3;
 152
 153        /*
 154         * Free last free fragments
 155         */
 156        p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3));
 157        tmp = ufs_data_ptr_to_cpu(sb, p);
 158        if (!tmp )
 159                ufs_panic(sb, "ufs_truncate_direct", "internal error");
 160        frag4 = ufs_fragnum (frag4);
 161        ufs_data_ptr_clear(uspi, p);
 162
 163        ufs_free_fragments (inode, tmp, frag4);
 164        mark_inode_dirty(inode);
 165 next3:
 166
 167        UFSD("EXIT: ino %lu\n", inode->i_ino);
 168        return retry;
 169}
 170
 171
 172static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p)
 173{
 174        struct super_block * sb;
 175        struct ufs_sb_private_info * uspi;
 176        struct ufs_buffer_head * ind_ubh;
 177        void *ind;
 178        u64 tmp, indirect_block, i, frag_to_free;
 179        unsigned free_count;
 180        int retry;
 181
 182        UFSD("ENTER: ino %lu, offset %llu, p: %p\n",
 183             inode->i_ino, (unsigned long long)offset, p);
 184
 185        BUG_ON(!p);
 186                
 187        sb = inode->i_sb;
 188        uspi = UFS_SB(sb)->s_uspi;
 189
 190        frag_to_free = 0;
 191        free_count = 0;
 192        retry = 0;
 193        
 194        tmp = ufs_data_ptr_to_cpu(sb, p);
 195        if (!tmp)
 196                return 0;
 197        ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize);
 198        if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 199                ubh_brelse (ind_ubh);
 200                return 1;
 201        }
 202        if (!ind_ubh) {
 203                ufs_data_ptr_clear(uspi, p);
 204                return 0;
 205        }
 206
 207        indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0;
 208        for (i = indirect_block; i < uspi->s_apb; i++) {
 209                ind = ubh_get_data_ptr(uspi, ind_ubh, i);
 210                tmp = ufs_data_ptr_to_cpu(sb, ind);
 211                if (!tmp)
 212                        continue;
 213
 214                ufs_data_ptr_clear(uspi, ind);
 215                ubh_mark_buffer_dirty(ind_ubh);
 216                if (free_count == 0) {
 217                        frag_to_free = tmp;
 218                        free_count = uspi->s_fpb;
 219                } else if (free_count > 0 && frag_to_free == tmp - free_count)
 220                        free_count += uspi->s_fpb;
 221                else {
 222                        ufs_free_blocks (inode, frag_to_free, free_count);
 223                        frag_to_free = tmp;
 224                        free_count = uspi->s_fpb;
 225                }
 226
 227                mark_inode_dirty(inode);
 228        }
 229
 230        if (free_count > 0) {
 231                ufs_free_blocks (inode, frag_to_free, free_count);
 232        }
 233        for (i = 0; i < uspi->s_apb; i++)
 234                if (!ufs_is_data_ptr_zero(uspi,
 235                                          ubh_get_data_ptr(uspi, ind_ubh, i)))
 236                        break;
 237        if (i >= uspi->s_apb) {
 238                tmp = ufs_data_ptr_to_cpu(sb, p);
 239                ufs_data_ptr_clear(uspi, p);
 240
 241                ufs_free_blocks (inode, tmp, uspi->s_fpb);
 242                mark_inode_dirty(inode);
 243                ubh_bforget(ind_ubh);
 244                ind_ubh = NULL;
 245        }
 246        if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
 247                ubh_ll_rw_block(SWRITE, ind_ubh);
 248                ubh_wait_on_buffer (ind_ubh);
 249        }
 250        ubh_brelse (ind_ubh);
 251        
 252        UFSD("EXIT: ino %lu\n", inode->i_ino);
 253        
 254        return retry;
 255}
 256
 257static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
 258{
 259        struct super_block * sb;
 260        struct ufs_sb_private_info * uspi;
 261        struct ufs_buffer_head *dind_bh;
 262        u64 i, tmp, dindirect_block;
 263        void *dind;
 264        int retry = 0;
 265        
 266        UFSD("ENTER: ino %lu\n", inode->i_ino);
 267        
 268        sb = inode->i_sb;
 269        uspi = UFS_SB(sb)->s_uspi;
 270
 271        dindirect_block = (DIRECT_BLOCK > offset) 
 272                ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
 273        retry = 0;
 274        
 275        tmp = ufs_data_ptr_to_cpu(sb, p);
 276        if (!tmp)
 277                return 0;
 278        dind_bh = ubh_bread(sb, tmp, uspi->s_bsize);
 279        if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 280                ubh_brelse (dind_bh);
 281                return 1;
 282        }
 283        if (!dind_bh) {
 284                ufs_data_ptr_clear(uspi, p);
 285                return 0;
 286        }
 287
 288        for (i = dindirect_block ; i < uspi->s_apb ; i++) {
 289                dind = ubh_get_data_ptr(uspi, dind_bh, i);
 290                tmp = ufs_data_ptr_to_cpu(sb, dind);
 291                if (!tmp)
 292                        continue;
 293                retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
 294                ubh_mark_buffer_dirty(dind_bh);
 295        }
 296
 297        for (i = 0; i < uspi->s_apb; i++)
 298                if (!ufs_is_data_ptr_zero(uspi,
 299                                          ubh_get_data_ptr(uspi, dind_bh, i)))
 300                        break;
 301        if (i >= uspi->s_apb) {
 302                tmp = ufs_data_ptr_to_cpu(sb, p);
 303                ufs_data_ptr_clear(uspi, p);
 304
 305                ufs_free_blocks(inode, tmp, uspi->s_fpb);
 306                mark_inode_dirty(inode);
 307                ubh_bforget(dind_bh);
 308                dind_bh = NULL;
 309        }
 310        if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
 311                ubh_ll_rw_block(SWRITE, dind_bh);
 312                ubh_wait_on_buffer (dind_bh);
 313        }
 314        ubh_brelse (dind_bh);
 315        
 316        UFSD("EXIT: ino %lu\n", inode->i_ino);
 317        
 318        return retry;
 319}
 320
 321static int ufs_trunc_tindirect(struct inode *inode)
 322{
 323        struct super_block *sb = inode->i_sb;
 324        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 325        struct ufs_inode_info *ufsi = UFS_I(inode);
 326        struct ufs_buffer_head * tind_bh;
 327        u64 tindirect_block, tmp, i;
 328        void *tind, *p;
 329        int retry;
 330        
 331        UFSD("ENTER: ino %lu\n", inode->i_ino);
 332
 333        retry = 0;
 334        
 335        tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
 336                ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
 337
 338        p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK);
 339        if (!(tmp = ufs_data_ptr_to_cpu(sb, p)))
 340                return 0;
 341        tind_bh = ubh_bread (sb, tmp, uspi->s_bsize);
 342        if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 343                ubh_brelse (tind_bh);
 344                return 1;
 345        }
 346        if (!tind_bh) {
 347                ufs_data_ptr_clear(uspi, p);
 348                return 0;
 349        }
 350
 351        for (i = tindirect_block ; i < uspi->s_apb ; i++) {
 352                tind = ubh_get_data_ptr(uspi, tind_bh, i);
 353                retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + 
 354                        uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind);
 355                ubh_mark_buffer_dirty(tind_bh);
 356        }
 357        for (i = 0; i < uspi->s_apb; i++)
 358                if (!ufs_is_data_ptr_zero(uspi,
 359                                          ubh_get_data_ptr(uspi, tind_bh, i)))
 360                        break;
 361        if (i >= uspi->s_apb) {
 362                tmp = ufs_data_ptr_to_cpu(sb, p);
 363                ufs_data_ptr_clear(uspi, p);
 364
 365                ufs_free_blocks(inode, tmp, uspi->s_fpb);
 366                mark_inode_dirty(inode);
 367                ubh_bforget(tind_bh);
 368                tind_bh = NULL;
 369        }
 370        if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
 371                ubh_ll_rw_block(SWRITE, tind_bh);
 372                ubh_wait_on_buffer (tind_bh);
 373        }
 374        ubh_brelse (tind_bh);
 375        
 376        UFSD("EXIT: ino %lu\n", inode->i_ino);
 377        return retry;
 378}
 379
 380static int ufs_alloc_lastblock(struct inode *inode)
 381{
 382        int err = 0;
 383        struct super_block *sb = inode->i_sb;
 384        struct address_space *mapping = inode->i_mapping;
 385        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 386        unsigned i, end;
 387        sector_t lastfrag;
 388        struct page *lastpage;
 389        struct buffer_head *bh;
 390        u64 phys64;
 391
 392        lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;
 393
 394        if (!lastfrag)
 395                goto out;
 396
 397        lastfrag--;
 398
 399        lastpage = ufs_get_locked_page(mapping, lastfrag >>
 400                                       (PAGE_CACHE_SHIFT - inode->i_blkbits));
 401       if (IS_ERR(lastpage)) {
 402               err = -EIO;
 403               goto out;
 404       }
 405
 406       end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1);
 407       bh = page_buffers(lastpage);
 408       for (i = 0; i < end; ++i)
 409               bh = bh->b_this_page;
 410
 411
 412       err = ufs_getfrag_block(inode, lastfrag, bh, 1);
 413
 414       if (unlikely(err))
 415               goto out_unlock;
 416
 417       if (buffer_new(bh)) {
 418               clear_buffer_new(bh);
 419               unmap_underlying_metadata(bh->b_bdev,
 420                                         bh->b_blocknr);
 421               /*
 422                * we do not zeroize fragment, because of
 423                * if it maped to hole, it already contains zeroes
 424                */
 425               set_buffer_uptodate(bh);
 426               mark_buffer_dirty(bh);
 427               set_page_dirty(lastpage);
 428       }
 429
 430       if (lastfrag >= UFS_IND_FRAGMENT) {
 431               end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
 432               phys64 = bh->b_blocknr + 1;
 433               for (i = 0; i < end; ++i) {
 434                       bh = sb_getblk(sb, i + phys64);
 435                       lock_buffer(bh);
 436                       memset(bh->b_data, 0, sb->s_blocksize);
 437                       set_buffer_uptodate(bh);
 438                       mark_buffer_dirty(bh);
 439                       unlock_buffer(bh);
 440                       sync_dirty_buffer(bh);
 441                       brelse(bh);
 442               }
 443       }
 444out_unlock:
 445       ufs_put_locked_page(lastpage);
 446out:
 447       return err;
 448}
 449
 450int ufs_truncate(struct inode *inode, loff_t old_i_size)
 451{
 452        struct ufs_inode_info *ufsi = UFS_I(inode);
 453        struct super_block *sb = inode->i_sb;
 454        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 455        int retry, err = 0;
 456        
 457        UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
 458             inode->i_ino, (unsigned long long)i_size_read(inode),
 459             (unsigned long long)old_i_size);
 460
 461        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 462              S_ISLNK(inode->i_mode)))
 463                return -EINVAL;
 464        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 465                return -EPERM;
 466
 467        err = ufs_alloc_lastblock(inode);
 468
 469        if (err) {
 470                i_size_write(inode, old_i_size);
 471                goto out;
 472        }
 473
 474        block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block);
 475
 476        lock_kernel();
 477        while (1) {
 478                retry = ufs_trunc_direct(inode);
 479                retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
 480                                            ufs_get_direct_data_ptr(uspi, ufsi,
 481                                                                    UFS_IND_BLOCK));
 482                retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb,
 483                                             ufs_get_direct_data_ptr(uspi, ufsi,
 484                                                                     UFS_DIND_BLOCK));
 485                retry |= ufs_trunc_tindirect (inode);
 486                if (!retry)
 487                        break;
 488                if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
 489                        ufs_sync_inode (inode);
 490                blk_run_address_space(inode->i_mapping);
 491                yield();
 492        }
 493
 494        inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
 495        ufsi->i_lastfrag = DIRECT_FRAGMENT;
 496        unlock_kernel();
 497        mark_inode_dirty(inode);
 498out:
 499        UFSD("EXIT: err %d\n", err);
 500        return err;
 501}
 502
 503
 504/*
 505 * We don't define our `inode->i_op->truncate', and call it here,
 506 * because of:
 507 * - there is no way to know old size
 508 * - there is no way inform user about error, if it happens in `truncate'
 509 */
 510static int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 511{
 512        struct inode *inode = dentry->d_inode;
 513        unsigned int ia_valid = attr->ia_valid;
 514        int error;
 515
 516        error = inode_change_ok(inode, attr);
 517        if (error)
 518                return error;
 519
 520        if (ia_valid & ATTR_SIZE &&
 521            attr->ia_size != i_size_read(inode)) {
 522                loff_t old_i_size = inode->i_size;
 523                error = vmtruncate(inode, attr->ia_size);
 524                if (error)
 525                        return error;
 526                error = ufs_truncate(inode, old_i_size);
 527                if (error)
 528                        return error;
 529        }
 530        return inode_setattr(inode, attr);
 531}
 532
 533const struct inode_operations ufs_file_inode_operations = {
 534        .setattr = ufs_setattr,
 535};
 536