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/fcntl.h>
  40#include <linux/time.h>
  41#include <linux/stat.h>
  42#include <linux/string.h>
  43#include <linux/smp_lock.h>
  44#include <linux/buffer_head.h>
  45#include <linux/blkdev.h>
  46#include <linux/sched.h>
  47
  48#include "ufs_fs.h"
  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_sync_block(ind_ubh);
 248        ubh_brelse (ind_ubh);
 249        
 250        UFSD("EXIT: ino %lu\n", inode->i_ino);
 251        
 252        return retry;
 253}
 254
 255static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p)
 256{
 257        struct super_block * sb;
 258        struct ufs_sb_private_info * uspi;
 259        struct ufs_buffer_head *dind_bh;
 260        u64 i, tmp, dindirect_block;
 261        void *dind;
 262        int retry = 0;
 263        
 264        UFSD("ENTER: ino %lu\n", inode->i_ino);
 265        
 266        sb = inode->i_sb;
 267        uspi = UFS_SB(sb)->s_uspi;
 268
 269        dindirect_block = (DIRECT_BLOCK > offset) 
 270                ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0;
 271        retry = 0;
 272        
 273        tmp = ufs_data_ptr_to_cpu(sb, p);
 274        if (!tmp)
 275                return 0;
 276        dind_bh = ubh_bread(sb, tmp, uspi->s_bsize);
 277        if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 278                ubh_brelse (dind_bh);
 279                return 1;
 280        }
 281        if (!dind_bh) {
 282                ufs_data_ptr_clear(uspi, p);
 283                return 0;
 284        }
 285
 286        for (i = dindirect_block ; i < uspi->s_apb ; i++) {
 287                dind = ubh_get_data_ptr(uspi, dind_bh, i);
 288                tmp = ufs_data_ptr_to_cpu(sb, dind);
 289                if (!tmp)
 290                        continue;
 291                retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind);
 292                ubh_mark_buffer_dirty(dind_bh);
 293        }
 294
 295        for (i = 0; i < uspi->s_apb; i++)
 296                if (!ufs_is_data_ptr_zero(uspi,
 297                                          ubh_get_data_ptr(uspi, dind_bh, i)))
 298                        break;
 299        if (i >= uspi->s_apb) {
 300                tmp = ufs_data_ptr_to_cpu(sb, p);
 301                ufs_data_ptr_clear(uspi, p);
 302
 303                ufs_free_blocks(inode, tmp, uspi->s_fpb);
 304                mark_inode_dirty(inode);
 305                ubh_bforget(dind_bh);
 306                dind_bh = NULL;
 307        }
 308        if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh))
 309                ubh_sync_block(dind_bh);
 310        ubh_brelse (dind_bh);
 311        
 312        UFSD("EXIT: ino %lu\n", inode->i_ino);
 313        
 314        return retry;
 315}
 316
 317static int ufs_trunc_tindirect(struct inode *inode)
 318{
 319        struct super_block *sb = inode->i_sb;
 320        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 321        struct ufs_inode_info *ufsi = UFS_I(inode);
 322        struct ufs_buffer_head * tind_bh;
 323        u64 tindirect_block, tmp, i;
 324        void *tind, *p;
 325        int retry;
 326        
 327        UFSD("ENTER: ino %lu\n", inode->i_ino);
 328
 329        retry = 0;
 330        
 331        tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb))
 332                ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0;
 333
 334        p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK);
 335        if (!(tmp = ufs_data_ptr_to_cpu(sb, p)))
 336                return 0;
 337        tind_bh = ubh_bread (sb, tmp, uspi->s_bsize);
 338        if (tmp != ufs_data_ptr_to_cpu(sb, p)) {
 339                ubh_brelse (tind_bh);
 340                return 1;
 341        }
 342        if (!tind_bh) {
 343                ufs_data_ptr_clear(uspi, p);
 344                return 0;
 345        }
 346
 347        for (i = tindirect_block ; i < uspi->s_apb ; i++) {
 348                tind = ubh_get_data_ptr(uspi, tind_bh, i);
 349                retry |= ufs_trunc_dindirect(inode, UFS_NDADDR + 
 350                        uspi->s_apb + ((i + 1) << uspi->s_2apbshift), tind);
 351                ubh_mark_buffer_dirty(tind_bh);
 352        }
 353        for (i = 0; i < uspi->s_apb; i++)
 354                if (!ufs_is_data_ptr_zero(uspi,
 355                                          ubh_get_data_ptr(uspi, tind_bh, i)))
 356                        break;
 357        if (i >= uspi->s_apb) {
 358                tmp = ufs_data_ptr_to_cpu(sb, p);
 359                ufs_data_ptr_clear(uspi, p);
 360
 361                ufs_free_blocks(inode, tmp, uspi->s_fpb);
 362                mark_inode_dirty(inode);
 363                ubh_bforget(tind_bh);
 364                tind_bh = NULL;
 365        }
 366        if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh))
 367                ubh_sync_block(tind_bh);
 368        ubh_brelse (tind_bh);
 369        
 370        UFSD("EXIT: ino %lu\n", inode->i_ino);
 371        return retry;
 372}
 373
 374static int ufs_alloc_lastblock(struct inode *inode)
 375{
 376        int err = 0;
 377        struct super_block *sb = inode->i_sb;
 378        struct address_space *mapping = inode->i_mapping;
 379        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 380        unsigned i, end;
 381        sector_t lastfrag;
 382        struct page *lastpage;
 383        struct buffer_head *bh;
 384        u64 phys64;
 385
 386        lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;
 387
 388        if (!lastfrag)
 389                goto out;
 390
 391        lastfrag--;
 392
 393        lastpage = ufs_get_locked_page(mapping, lastfrag >>
 394                                       (PAGE_CACHE_SHIFT - inode->i_blkbits));
 395       if (IS_ERR(lastpage)) {
 396               err = -EIO;
 397               goto out;
 398       }
 399
 400       end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1);
 401       bh = page_buffers(lastpage);
 402       for (i = 0; i < end; ++i)
 403               bh = bh->b_this_page;
 404
 405
 406       err = ufs_getfrag_block(inode, lastfrag, bh, 1);
 407
 408       if (unlikely(err))
 409               goto out_unlock;
 410
 411       if (buffer_new(bh)) {
 412               clear_buffer_new(bh);
 413               unmap_underlying_metadata(bh->b_bdev,
 414                                         bh->b_blocknr);
 415               /*
 416                * we do not zeroize fragment, because of
 417                * if it maped to hole, it already contains zeroes
 418                */
 419               set_buffer_uptodate(bh);
 420               mark_buffer_dirty(bh);
 421               set_page_dirty(lastpage);
 422       }
 423
 424       if (lastfrag >= UFS_IND_FRAGMENT) {
 425               end = uspi->s_fpb - ufs_fragnum(lastfrag) - 1;
 426               phys64 = bh->b_blocknr + 1;
 427               for (i = 0; i < end; ++i) {
 428                       bh = sb_getblk(sb, i + phys64);
 429                       lock_buffer(bh);
 430                       memset(bh->b_data, 0, sb->s_blocksize);
 431                       set_buffer_uptodate(bh);
 432                       mark_buffer_dirty(bh);
 433                       unlock_buffer(bh);
 434                       sync_dirty_buffer(bh);
 435                       brelse(bh);
 436               }
 437       }
 438out_unlock:
 439       ufs_put_locked_page(lastpage);
 440out:
 441       return err;
 442}
 443
 444int ufs_truncate(struct inode *inode, loff_t old_i_size)
 445{
 446        struct ufs_inode_info *ufsi = UFS_I(inode);
 447        struct super_block *sb = inode->i_sb;
 448        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 449        int retry, err = 0;
 450        
 451        UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n",
 452             inode->i_ino, (unsigned long long)i_size_read(inode),
 453             (unsigned long long)old_i_size);
 454
 455        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 456              S_ISLNK(inode->i_mode)))
 457                return -EINVAL;
 458        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 459                return -EPERM;
 460
 461        err = ufs_alloc_lastblock(inode);
 462
 463        if (err) {
 464                i_size_write(inode, old_i_size);
 465                goto out;
 466        }
 467
 468        block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block);
 469
 470        lock_kernel();
 471        while (1) {
 472                retry = ufs_trunc_direct(inode);
 473                retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
 474                                            ufs_get_direct_data_ptr(uspi, ufsi,
 475                                                                    UFS_IND_BLOCK));
 476                retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb,
 477                                             ufs_get_direct_data_ptr(uspi, ufsi,
 478                                                                     UFS_DIND_BLOCK));
 479                retry |= ufs_trunc_tindirect (inode);
 480                if (!retry)
 481                        break;
 482                if (IS_SYNC(inode) && (inode->i_state & I_DIRTY))
 483                        ufs_sync_inode (inode);
 484                blk_run_address_space(inode->i_mapping);
 485                yield();
 486        }
 487
 488        inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
 489        ufsi->i_lastfrag = DIRECT_FRAGMENT;
 490        unlock_kernel();
 491        mark_inode_dirty(inode);
 492out:
 493        UFSD("EXIT: err %d\n", err);
 494        return err;
 495}
 496
 497int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 498{
 499        struct inode *inode = dentry->d_inode;
 500        unsigned int ia_valid = attr->ia_valid;
 501        int error;
 502
 503        error = inode_change_ok(inode, attr);
 504        if (error)
 505                return error;
 506
 507        if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
 508                loff_t old_i_size = inode->i_size;
 509
 510                /* XXX(truncate): truncate_setsize should be called last */
 511                truncate_setsize(inode, attr->ia_size);
 512
 513                error = ufs_truncate(inode, old_i_size);
 514                if (error)
 515                        return error;
 516        }
 517
 518        setattr_copy(inode, attr);
 519        mark_inode_dirty(inode);
 520        return 0;
 521}
 522
 523const struct inode_operations ufs_file_inode_operations = {
 524        .setattr = ufs_setattr,
 525};
 526