11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2000-2004 31da177e4SLinus Torvalds * Portions Copyright (C) Christoph Hellwig, 2001-2002 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 61da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 71da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 81da177e4SLinus Torvalds * (at your option) any later version. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 111da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 121da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 131da177e4SLinus Torvalds * the GNU General Public License for more details. 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 161da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 171da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #include <linux/fs.h> 211da177e4SLinus Torvalds #include <linux/mpage.h> 221da177e4SLinus Torvalds #include <linux/buffer_head.h> 231da177e4SLinus Torvalds #include <linux/pagemap.h> 241da177e4SLinus Torvalds #include <linux/quotaops.h> 25e2e40f2cSChristoph Hellwig #include <linux/uio.h> 26a9185b41SChristoph Hellwig #include <linux/writeback.h> 271da177e4SLinus Torvalds #include "jfs_incore.h" 281868f4aaSDave Kleikamp #include "jfs_inode.h" 291da177e4SLinus Torvalds #include "jfs_filsys.h" 301da177e4SLinus Torvalds #include "jfs_imap.h" 311da177e4SLinus Torvalds #include "jfs_extent.h" 321da177e4SLinus Torvalds #include "jfs_unicode.h" 331da177e4SLinus Torvalds #include "jfs_debug.h" 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds 36eab1df71SDavid Howells struct inode *jfs_iget(struct super_block *sb, unsigned long ino) 371da177e4SLinus Torvalds { 38eab1df71SDavid Howells struct inode *inode; 39eab1df71SDavid Howells int ret; 40eab1df71SDavid Howells 41eab1df71SDavid Howells inode = iget_locked(sb, ino); 42eab1df71SDavid Howells if (!inode) 43eab1df71SDavid Howells return ERR_PTR(-ENOMEM); 44eab1df71SDavid Howells if (!(inode->i_state & I_NEW)) 45eab1df71SDavid Howells return inode; 46eab1df71SDavid Howells 47eab1df71SDavid Howells ret = diRead(inode); 48eab1df71SDavid Howells if (ret < 0) { 49eab1df71SDavid Howells iget_failed(inode); 50eab1df71SDavid Howells return ERR_PTR(ret); 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 541da177e4SLinus Torvalds inode->i_op = &jfs_file_inode_operations; 551da177e4SLinus Torvalds inode->i_fop = &jfs_file_operations; 561da177e4SLinus Torvalds inode->i_mapping->a_ops = &jfs_aops; 571da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 581da177e4SLinus Torvalds inode->i_op = &jfs_dir_inode_operations; 591da177e4SLinus Torvalds inode->i_fop = &jfs_dir_operations; 601da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 611da177e4SLinus Torvalds if (inode->i_size >= IDATASIZE) { 621da177e4SLinus Torvalds inode->i_op = &page_symlink_inode_operations; 631da177e4SLinus Torvalds inode->i_mapping->a_ops = &jfs_aops; 64d69e83d9SDave Kleikamp } else { 65c7f2e1f0SDmitry Monakhov inode->i_op = &jfs_fast_symlink_inode_operations; 66ad476fedSAl Viro inode->i_link = JFS_IP(inode)->i_inline; 67d69e83d9SDave Kleikamp /* 68d69e83d9SDave Kleikamp * The inline data should be null-terminated, but 69d69e83d9SDave Kleikamp * don't let on-disk corruption crash the kernel 70d69e83d9SDave Kleikamp */ 71ad476fedSAl Viro inode->i_link[inode->i_size] = '\0'; 72d69e83d9SDave Kleikamp } 731da177e4SLinus Torvalds } else { 741da177e4SLinus Torvalds inode->i_op = &jfs_file_inode_operations; 751da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, inode->i_rdev); 761da177e4SLinus Torvalds } 77eab1df71SDavid Howells unlock_new_inode(inode); 78eab1df71SDavid Howells return inode; 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds /* 821da177e4SLinus Torvalds * Workhorse of both fsync & write_inode 831da177e4SLinus Torvalds */ 841da177e4SLinus Torvalds int jfs_commit_inode(struct inode *inode, int wait) 851da177e4SLinus Torvalds { 861da177e4SLinus Torvalds int rc = 0; 871da177e4SLinus Torvalds tid_t tid; 881da177e4SLinus Torvalds static int noisy = 5; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds jfs_info("In jfs_commit_inode, inode = 0x%p", inode); 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* 931da177e4SLinus Torvalds * Don't commit if inode has been committed since last being 941da177e4SLinus Torvalds * marked dirty, or if it has been deleted. 951da177e4SLinus Torvalds */ 961da177e4SLinus Torvalds if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode)) 971da177e4SLinus Torvalds return 0; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds if (isReadOnly(inode)) { 1001da177e4SLinus Torvalds /* kernel allows writes to devices on read-only 1011da177e4SLinus Torvalds * partitions and may think inode is dirty 1021da177e4SLinus Torvalds */ 1031da177e4SLinus Torvalds if (!special_file(inode->i_mode) && noisy) { 1041da177e4SLinus Torvalds jfs_err("jfs_commit_inode(0x%p) called on " 1051da177e4SLinus Torvalds "read-only volume", inode); 1061da177e4SLinus Torvalds jfs_err("Is remount racy?"); 1071da177e4SLinus Torvalds noisy--; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds return 0; 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds tid = txBegin(inode->i_sb, COMMIT_INODE); 1131de87444SIngo Molnar mutex_lock(&JFS_IP(inode)->commit_mutex); 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds /* 1161de87444SIngo Molnar * Retest inode state after taking commit_mutex 1171da177e4SLinus Torvalds */ 1181da177e4SLinus Torvalds if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode)) 1191da177e4SLinus Torvalds rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds txEnd(tid); 1221de87444SIngo Molnar mutex_unlock(&JFS_IP(inode)->commit_mutex); 1231da177e4SLinus Torvalds return rc; 1241da177e4SLinus Torvalds } 1251da177e4SLinus Torvalds 126a9185b41SChristoph Hellwig int jfs_write_inode(struct inode *inode, struct writeback_control *wbc) 1271da177e4SLinus Torvalds { 128a9185b41SChristoph Hellwig int wait = wbc->sync_mode == WB_SYNC_ALL; 129a9185b41SChristoph Hellwig 13073aaa22dSDave Kleikamp if (inode->i_nlink == 0) 1311da177e4SLinus Torvalds return 0; 1321da177e4SLinus Torvalds /* 1331da177e4SLinus Torvalds * If COMMIT_DIRTY is not set, the inode isn't really dirty. 1341da177e4SLinus Torvalds * It has been committed since the last change, but was still 1351da177e4SLinus Torvalds * on the dirty inode list. 1361da177e4SLinus Torvalds */ 1371da177e4SLinus Torvalds if (!test_cflag(COMMIT_Dirty, inode)) { 1381da177e4SLinus Torvalds /* Make sure committed changes hit the disk */ 1391da177e4SLinus Torvalds jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait); 1401da177e4SLinus Torvalds return 0; 1411da177e4SLinus Torvalds } 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds if (jfs_commit_inode(inode, wait)) { 1441da177e4SLinus Torvalds jfs_err("jfs_write_inode: jfs_commit_inode failed!"); 1451da177e4SLinus Torvalds return -EIO; 1461da177e4SLinus Torvalds } else 1471da177e4SLinus Torvalds return 0; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 15062aff86fSAl Viro void jfs_evict_inode(struct inode *inode) 1511da177e4SLinus Torvalds { 15262aff86fSAl Viro jfs_info("In jfs_evict_inode, inode = 0x%p", inode); 1531da177e4SLinus Torvalds 15462aff86fSAl Viro if (!inode->i_nlink && !is_bad_inode(inode)) { 155871a2931SChristoph Hellwig dquot_initialize(inode); 156907f4554SChristoph Hellwig 15762aff86fSAl Viro if (JFS_IP(inode)->fileset == FILESYSTEM_I) { 15891b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 159fef26658SMark Fasheh 1601da177e4SLinus Torvalds if (test_cflag(COMMIT_Freewmap, inode)) 1611868f4aaSDave Kleikamp jfs_free_zero_link(inode); 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds diFree(inode); 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds /* 1661da177e4SLinus Torvalds * Free the inode from the quota allocation. 1671da177e4SLinus Torvalds */ 168871a2931SChristoph Hellwig dquot_initialize(inode); 16963936ddaSChristoph Hellwig dquot_free_inode(inode); 170b1b5d7f9SDave Kleikamp } 17162aff86fSAl Viro } else { 17291b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data); 17362aff86fSAl Viro } 174dbd5768fSJan Kara clear_inode(inode); 17562aff86fSAl Viro dquot_drop(inode); 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds 178aa385729SChristoph Hellwig void jfs_dirty_inode(struct inode *inode, int flags) 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds static int noisy = 5; 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds if (isReadOnly(inode)) { 1831da177e4SLinus Torvalds if (!special_file(inode->i_mode) && noisy) { 1841da177e4SLinus Torvalds /* kernel allows writes to devices on read-only 1851da177e4SLinus Torvalds * partitions and may try to mark inode dirty 1861da177e4SLinus Torvalds */ 1871da177e4SLinus Torvalds jfs_err("jfs_dirty_inode called on read-only volume"); 1881da177e4SLinus Torvalds jfs_err("Is remount racy?"); 1891da177e4SLinus Torvalds noisy--; 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds return; 1921da177e4SLinus Torvalds } 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds set_cflag(COMMIT_Dirty, inode); 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 197115ff50bSDave Kleikamp int jfs_get_block(struct inode *ip, sector_t lblock, 1981da177e4SLinus Torvalds struct buffer_head *bh_result, int create) 1991da177e4SLinus Torvalds { 2001da177e4SLinus Torvalds s64 lblock64 = lblock; 2011da177e4SLinus Torvalds int rc = 0; 2021da177e4SLinus Torvalds xad_t xad; 2031da177e4SLinus Torvalds s64 xaddr; 2041da177e4SLinus Torvalds int xflag; 205115ff50bSDave Kleikamp s32 xlen = bh_result->b_size >> ip->i_blkbits; 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds /* 2081da177e4SLinus Torvalds * Take appropriate lock on inode 2091da177e4SLinus Torvalds */ 2101da177e4SLinus Torvalds if (create) 21182d5b9a7SDave Kleikamp IWRITE_LOCK(ip, RDWRLOCK_NORMAL); 2121da177e4SLinus Torvalds else 21382d5b9a7SDave Kleikamp IREAD_LOCK(ip, RDWRLOCK_NORMAL); 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && 216115ff50bSDave Kleikamp (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && 2176628465eSDave Kleikamp xaddr) { 2181da177e4SLinus Torvalds if (xflag & XAD_NOTRECORDED) { 2191da177e4SLinus Torvalds if (!create) 2201da177e4SLinus Torvalds /* 2211da177e4SLinus Torvalds * Allocated but not recorded, read treats 2221da177e4SLinus Torvalds * this as a hole 2231da177e4SLinus Torvalds */ 2241da177e4SLinus Torvalds goto unlock; 2251da177e4SLinus Torvalds #ifdef _JFS_4K 2261da177e4SLinus Torvalds XADoffset(&xad, lblock64); 2271da177e4SLinus Torvalds XADlength(&xad, xlen); 2281da177e4SLinus Torvalds XADaddress(&xad, xaddr); 2291da177e4SLinus Torvalds #else /* _JFS_4K */ 2301da177e4SLinus Torvalds /* 2311da177e4SLinus Torvalds * As long as block size = 4K, this isn't a problem. 2321da177e4SLinus Torvalds * We should mark the whole page not ABNR, but how 2331da177e4SLinus Torvalds * will we know to mark the other blocks BH_New? 2341da177e4SLinus Torvalds */ 2351da177e4SLinus Torvalds BUG(); 2361da177e4SLinus Torvalds #endif /* _JFS_4K */ 2371da177e4SLinus Torvalds rc = extRecord(ip, &xad); 2381da177e4SLinus Torvalds if (rc) 2391da177e4SLinus Torvalds goto unlock; 2401da177e4SLinus Torvalds set_buffer_new(bh_result); 2411da177e4SLinus Torvalds } 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds map_bh(bh_result, ip->i_sb, xaddr); 2441da177e4SLinus Torvalds bh_result->b_size = xlen << ip->i_blkbits; 2451da177e4SLinus Torvalds goto unlock; 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds if (!create) 2481da177e4SLinus Torvalds goto unlock; 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds /* 2511da177e4SLinus Torvalds * Allocate a new block 2521da177e4SLinus Torvalds */ 2531da177e4SLinus Torvalds #ifdef _JFS_4K 2541da177e4SLinus Torvalds if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) 2551da177e4SLinus Torvalds goto unlock; 2564d81715fSRichard Knutsson rc = extAlloc(ip, xlen, lblock64, &xad, false); 2571da177e4SLinus Torvalds if (rc) 2581da177e4SLinus Torvalds goto unlock; 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds set_buffer_new(bh_result); 2611da177e4SLinus Torvalds map_bh(bh_result, ip->i_sb, addressXAD(&xad)); 2621da177e4SLinus Torvalds bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits; 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds #else /* _JFS_4K */ 2651da177e4SLinus Torvalds /* 2661da177e4SLinus Torvalds * We need to do whatever it takes to keep all but the last buffers 2671da177e4SLinus Torvalds * in 4K pages - see jfs_write.c 2681da177e4SLinus Torvalds */ 2691da177e4SLinus Torvalds BUG(); 2701da177e4SLinus Torvalds #endif /* _JFS_4K */ 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds unlock: 2731da177e4SLinus Torvalds /* 2741da177e4SLinus Torvalds * Release lock on inode 2751da177e4SLinus Torvalds */ 2761da177e4SLinus Torvalds if (create) 2771da177e4SLinus Torvalds IWRITE_UNLOCK(ip); 2781da177e4SLinus Torvalds else 2791da177e4SLinus Torvalds IREAD_UNLOCK(ip); 2801da177e4SLinus Torvalds return rc; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds static int jfs_writepage(struct page *page, struct writeback_control *wbc) 2841da177e4SLinus Torvalds { 285d5c5f84bSNick Piggin return block_write_full_page(page, jfs_get_block, wbc); 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds static int jfs_writepages(struct address_space *mapping, 2891da177e4SLinus Torvalds struct writeback_control *wbc) 2901da177e4SLinus Torvalds { 2911da177e4SLinus Torvalds return mpage_writepages(mapping, wbc, jfs_get_block); 2921da177e4SLinus Torvalds } 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds static int jfs_readpage(struct file *file, struct page *page) 2951da177e4SLinus Torvalds { 2961da177e4SLinus Torvalds return mpage_readpage(page, jfs_get_block); 2971da177e4SLinus Torvalds } 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvalds static int jfs_readpages(struct file *file, struct address_space *mapping, 3001da177e4SLinus Torvalds struct list_head *pages, unsigned nr_pages) 3011da177e4SLinus Torvalds { 3021da177e4SLinus Torvalds return mpage_readpages(mapping, pages, nr_pages, jfs_get_block); 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds 30586dd07d6SMarco Stornelli static void jfs_write_failed(struct address_space *mapping, loff_t to) 30686dd07d6SMarco Stornelli { 30786dd07d6SMarco Stornelli struct inode *inode = mapping->host; 30886dd07d6SMarco Stornelli 30986dd07d6SMarco Stornelli if (to > inode->i_size) { 3107caef267SKirill A. Shutemov truncate_pagecache(inode, inode->i_size); 31186dd07d6SMarco Stornelli jfs_truncate(inode); 31286dd07d6SMarco Stornelli } 31386dd07d6SMarco Stornelli } 31486dd07d6SMarco Stornelli 315d5c5f84bSNick Piggin static int jfs_write_begin(struct file *file, struct address_space *mapping, 316d5c5f84bSNick Piggin loff_t pos, unsigned len, unsigned flags, 317d5c5f84bSNick Piggin struct page **pagep, void **fsdata) 3181da177e4SLinus Torvalds { 319ea0f04e5SChristoph Hellwig int ret; 320ea0f04e5SChristoph Hellwig 321ea0f04e5SChristoph Hellwig ret = nobh_write_begin(mapping, pos, len, flags, pagep, fsdata, 322d5c5f84bSNick Piggin jfs_get_block); 32386dd07d6SMarco Stornelli if (unlikely(ret)) 32486dd07d6SMarco Stornelli jfs_write_failed(mapping, pos + len); 325ea0f04e5SChristoph Hellwig 326ea0f04e5SChristoph Hellwig return ret; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds static sector_t jfs_bmap(struct address_space *mapping, sector_t block) 3301da177e4SLinus Torvalds { 3311da177e4SLinus Torvalds return generic_block_bmap(mapping, block, jfs_get_block); 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds 33422c6186eSOmar Sandoval static ssize_t jfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, 33522c6186eSOmar Sandoval loff_t offset) 3361da177e4SLinus Torvalds { 3371da177e4SLinus Torvalds struct file *file = iocb->ki_filp; 33886dd07d6SMarco Stornelli struct address_space *mapping = file->f_mapping; 3391da177e4SLinus Torvalds struct inode *inode = file->f_mapping->host; 340a6cbcd4aSAl Viro size_t count = iov_iter_count(iter); 341eafdc7d1SChristoph Hellwig ssize_t ret; 3421da177e4SLinus Torvalds 34317f8c842SOmar Sandoval ret = blockdev_direct_IO(iocb, inode, iter, offset, jfs_get_block); 344eafdc7d1SChristoph Hellwig 345eafdc7d1SChristoph Hellwig /* 346eafdc7d1SChristoph Hellwig * In case of error extending write may have instantiated a few 347eafdc7d1SChristoph Hellwig * blocks outside i_size. Trim these off again. 348eafdc7d1SChristoph Hellwig */ 3496f673763SOmar Sandoval if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) { 350eafdc7d1SChristoph Hellwig loff_t isize = i_size_read(inode); 351a6cbcd4aSAl Viro loff_t end = offset + count; 352eafdc7d1SChristoph Hellwig 353eafdc7d1SChristoph Hellwig if (end > isize) 35486dd07d6SMarco Stornelli jfs_write_failed(mapping, end); 355eafdc7d1SChristoph Hellwig } 356eafdc7d1SChristoph Hellwig 357eafdc7d1SChristoph Hellwig return ret; 3581da177e4SLinus Torvalds } 3591da177e4SLinus Torvalds 360f5e54d6eSChristoph Hellwig const struct address_space_operations jfs_aops = { 3611da177e4SLinus Torvalds .readpage = jfs_readpage, 3621da177e4SLinus Torvalds .readpages = jfs_readpages, 3631da177e4SLinus Torvalds .writepage = jfs_writepage, 3641da177e4SLinus Torvalds .writepages = jfs_writepages, 365d5c5f84bSNick Piggin .write_begin = jfs_write_begin, 36603158cd7SNick Piggin .write_end = nobh_write_end, 3671da177e4SLinus Torvalds .bmap = jfs_bmap, 3681da177e4SLinus Torvalds .direct_IO = jfs_direct_IO, 3691da177e4SLinus Torvalds }; 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds /* 3721da177e4SLinus Torvalds * Guts of jfs_truncate. Called with locks already held. Can be called 3731da177e4SLinus Torvalds * with directory for truncating directory index table. 3741da177e4SLinus Torvalds */ 3751da177e4SLinus Torvalds void jfs_truncate_nolock(struct inode *ip, loff_t length) 3761da177e4SLinus Torvalds { 3771da177e4SLinus Torvalds loff_t newsize; 3781da177e4SLinus Torvalds tid_t tid; 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds ASSERT(length >= 0); 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds if (test_cflag(COMMIT_Nolink, ip)) { 3831da177e4SLinus Torvalds xtTruncate(0, ip, length, COMMIT_WMAP); 3841da177e4SLinus Torvalds return; 3851da177e4SLinus Torvalds } 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds do { 3881da177e4SLinus Torvalds tid = txBegin(ip->i_sb, 0); 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds /* 3911de87444SIngo Molnar * The commit_mutex cannot be taken before txBegin. 3921da177e4SLinus Torvalds * txBegin may block and there is a chance the inode 3931da177e4SLinus Torvalds * could be marked dirty and need to be committed 3941da177e4SLinus Torvalds * before txBegin unblocks 3951da177e4SLinus Torvalds */ 3961de87444SIngo Molnar mutex_lock(&JFS_IP(ip)->commit_mutex); 3971da177e4SLinus Torvalds 3981da177e4SLinus Torvalds newsize = xtTruncate(tid, ip, length, 3991da177e4SLinus Torvalds COMMIT_TRUNCATE | COMMIT_PWMAP); 4001da177e4SLinus Torvalds if (newsize < 0) { 4011da177e4SLinus Torvalds txEnd(tid); 4021de87444SIngo Molnar mutex_unlock(&JFS_IP(ip)->commit_mutex); 4031da177e4SLinus Torvalds break; 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds ip->i_mtime = ip->i_ctime = CURRENT_TIME; 4071da177e4SLinus Torvalds mark_inode_dirty(ip); 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds txCommit(tid, 1, &ip, 0); 4101da177e4SLinus Torvalds txEnd(tid); 4111de87444SIngo Molnar mutex_unlock(&JFS_IP(ip)->commit_mutex); 4121da177e4SLinus Torvalds } while (newsize > length); /* Truncate isn't always atomic */ 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds void jfs_truncate(struct inode *ip) 4161da177e4SLinus Torvalds { 4171da177e4SLinus Torvalds jfs_info("jfs_truncate: size = 0x%lx", (ulong) ip->i_size); 4181da177e4SLinus Torvalds 41903158cd7SNick Piggin nobh_truncate_page(ip->i_mapping, ip->i_size, jfs_get_block); 4201da177e4SLinus Torvalds 42182d5b9a7SDave Kleikamp IWRITE_LOCK(ip, RDWRLOCK_NORMAL); 4221da177e4SLinus Torvalds jfs_truncate_nolock(ip, ip->i_size); 4231da177e4SLinus Torvalds IWRITE_UNLOCK(ip); 4241da177e4SLinus Torvalds } 425