162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) International Business Machines Corp., 2000-2004 462306a36Sopenharmony_ci * Portions Copyright (C) Christoph Hellwig, 2001-2002 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/fs.h> 862306a36Sopenharmony_ci#include <linux/mpage.h> 962306a36Sopenharmony_ci#include <linux/buffer_head.h> 1062306a36Sopenharmony_ci#include <linux/pagemap.h> 1162306a36Sopenharmony_ci#include <linux/quotaops.h> 1262306a36Sopenharmony_ci#include <linux/uio.h> 1362306a36Sopenharmony_ci#include <linux/writeback.h> 1462306a36Sopenharmony_ci#include "jfs_incore.h" 1562306a36Sopenharmony_ci#include "jfs_inode.h" 1662306a36Sopenharmony_ci#include "jfs_filsys.h" 1762306a36Sopenharmony_ci#include "jfs_imap.h" 1862306a36Sopenharmony_ci#include "jfs_extent.h" 1962306a36Sopenharmony_ci#include "jfs_unicode.h" 2062306a36Sopenharmony_ci#include "jfs_debug.h" 2162306a36Sopenharmony_ci#include "jfs_dmap.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct inode *jfs_iget(struct super_block *sb, unsigned long ino) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct inode *inode; 2762306a36Sopenharmony_ci int ret; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci inode = iget_locked(sb, ino); 3062306a36Sopenharmony_ci if (!inode) 3162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 3262306a36Sopenharmony_ci if (!(inode->i_state & I_NEW)) 3362306a36Sopenharmony_ci return inode; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci ret = diRead(inode); 3662306a36Sopenharmony_ci if (ret < 0) { 3762306a36Sopenharmony_ci iget_failed(inode); 3862306a36Sopenharmony_ci return ERR_PTR(ret); 3962306a36Sopenharmony_ci } 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (S_ISREG(inode->i_mode)) { 4262306a36Sopenharmony_ci inode->i_op = &jfs_file_inode_operations; 4362306a36Sopenharmony_ci inode->i_fop = &jfs_file_operations; 4462306a36Sopenharmony_ci inode->i_mapping->a_ops = &jfs_aops; 4562306a36Sopenharmony_ci } else if (S_ISDIR(inode->i_mode)) { 4662306a36Sopenharmony_ci inode->i_op = &jfs_dir_inode_operations; 4762306a36Sopenharmony_ci inode->i_fop = &jfs_dir_operations; 4862306a36Sopenharmony_ci } else if (S_ISLNK(inode->i_mode)) { 4962306a36Sopenharmony_ci if (inode->i_size >= IDATASIZE) { 5062306a36Sopenharmony_ci inode->i_op = &page_symlink_inode_operations; 5162306a36Sopenharmony_ci inode_nohighmem(inode); 5262306a36Sopenharmony_ci inode->i_mapping->a_ops = &jfs_aops; 5362306a36Sopenharmony_ci } else { 5462306a36Sopenharmony_ci inode->i_op = &jfs_fast_symlink_inode_operations; 5562306a36Sopenharmony_ci inode->i_link = JFS_IP(inode)->i_inline; 5662306a36Sopenharmony_ci /* 5762306a36Sopenharmony_ci * The inline data should be null-terminated, but 5862306a36Sopenharmony_ci * don't let on-disk corruption crash the kernel 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci inode->i_link[inode->i_size] = '\0'; 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci } else { 6362306a36Sopenharmony_ci inode->i_op = &jfs_file_inode_operations; 6462306a36Sopenharmony_ci init_special_inode(inode, inode->i_mode, inode->i_rdev); 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci unlock_new_inode(inode); 6762306a36Sopenharmony_ci return inode; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* 7162306a36Sopenharmony_ci * Workhorse of both fsync & write_inode 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ciint jfs_commit_inode(struct inode *inode, int wait) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci int rc = 0; 7662306a36Sopenharmony_ci tid_t tid; 7762306a36Sopenharmony_ci static int noisy = 5; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci jfs_info("In jfs_commit_inode, inode = 0x%p", inode); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* 8262306a36Sopenharmony_ci * Don't commit if inode has been committed since last being 8362306a36Sopenharmony_ci * marked dirty, or if it has been deleted. 8462306a36Sopenharmony_ci */ 8562306a36Sopenharmony_ci if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode)) 8662306a36Sopenharmony_ci return 0; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci if (isReadOnly(inode)) { 8962306a36Sopenharmony_ci /* kernel allows writes to devices on read-only 9062306a36Sopenharmony_ci * partitions and may think inode is dirty 9162306a36Sopenharmony_ci */ 9262306a36Sopenharmony_ci if (!special_file(inode->i_mode) && noisy) { 9362306a36Sopenharmony_ci jfs_err("jfs_commit_inode(0x%p) called on read-only volume", 9462306a36Sopenharmony_ci inode); 9562306a36Sopenharmony_ci jfs_err("Is remount racy?"); 9662306a36Sopenharmony_ci noisy--; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci return 0; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci tid = txBegin(inode->i_sb, COMMIT_INODE); 10262306a36Sopenharmony_ci mutex_lock(&JFS_IP(inode)->commit_mutex); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* 10562306a36Sopenharmony_ci * Retest inode state after taking commit_mutex 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode)) 10862306a36Sopenharmony_ci rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci txEnd(tid); 11162306a36Sopenharmony_ci mutex_unlock(&JFS_IP(inode)->commit_mutex); 11262306a36Sopenharmony_ci return rc; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint jfs_write_inode(struct inode *inode, struct writeback_control *wbc) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci int wait = wbc->sync_mode == WB_SYNC_ALL; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (inode->i_nlink == 0) 12062306a36Sopenharmony_ci return 0; 12162306a36Sopenharmony_ci /* 12262306a36Sopenharmony_ci * If COMMIT_DIRTY is not set, the inode isn't really dirty. 12362306a36Sopenharmony_ci * It has been committed since the last change, but was still 12462306a36Sopenharmony_ci * on the dirty inode list. 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_ci if (!test_cflag(COMMIT_Dirty, inode)) { 12762306a36Sopenharmony_ci /* Make sure committed changes hit the disk */ 12862306a36Sopenharmony_ci jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait); 12962306a36Sopenharmony_ci return 0; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (jfs_commit_inode(inode, wait)) { 13362306a36Sopenharmony_ci jfs_err("jfs_write_inode: jfs_commit_inode failed!"); 13462306a36Sopenharmony_ci return -EIO; 13562306a36Sopenharmony_ci } else 13662306a36Sopenharmony_ci return 0; 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_civoid jfs_evict_inode(struct inode *inode) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct jfs_inode_info *ji = JFS_IP(inode); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci jfs_info("In jfs_evict_inode, inode = 0x%p", inode); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (!inode->i_nlink && !is_bad_inode(inode)) { 14662306a36Sopenharmony_ci dquot_initialize(inode); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (JFS_IP(inode)->fileset == FILESYSTEM_I) { 14962306a36Sopenharmony_ci struct inode *ipimap = JFS_SBI(inode->i_sb)->ipimap; 15062306a36Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if (test_cflag(COMMIT_Freewmap, inode)) 15362306a36Sopenharmony_ci jfs_free_zero_link(inode); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (ipimap && JFS_IP(ipimap)->i_imap) 15662306a36Sopenharmony_ci diFree(inode); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* 15962306a36Sopenharmony_ci * Free the inode from the quota allocation. 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci dquot_free_inode(inode); 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci } else { 16462306a36Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci clear_inode(inode); 16762306a36Sopenharmony_ci dquot_drop(inode); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci BUG_ON(!list_empty(&ji->anon_inode_list)); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci spin_lock_irq(&ji->ag_lock); 17262306a36Sopenharmony_ci if (ji->active_ag != -1) { 17362306a36Sopenharmony_ci struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; 17462306a36Sopenharmony_ci atomic_dec(&bmap->db_active[ji->active_ag]); 17562306a36Sopenharmony_ci ji->active_ag = -1; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci spin_unlock_irq(&ji->ag_lock); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_civoid jfs_dirty_inode(struct inode *inode, int flags) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci static int noisy = 5; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (isReadOnly(inode)) { 18562306a36Sopenharmony_ci if (!special_file(inode->i_mode) && noisy) { 18662306a36Sopenharmony_ci /* kernel allows writes to devices on read-only 18762306a36Sopenharmony_ci * partitions and may try to mark inode dirty 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ci jfs_err("jfs_dirty_inode called on read-only volume"); 19062306a36Sopenharmony_ci jfs_err("Is remount racy?"); 19162306a36Sopenharmony_ci noisy--; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci return; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci set_cflag(COMMIT_Dirty, inode); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciint jfs_get_block(struct inode *ip, sector_t lblock, 20062306a36Sopenharmony_ci struct buffer_head *bh_result, int create) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci s64 lblock64 = lblock; 20362306a36Sopenharmony_ci int rc = 0; 20462306a36Sopenharmony_ci xad_t xad; 20562306a36Sopenharmony_ci s64 xaddr; 20662306a36Sopenharmony_ci int xflag; 20762306a36Sopenharmony_ci s32 xlen = bh_result->b_size >> ip->i_blkbits; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci /* 21062306a36Sopenharmony_ci * Take appropriate lock on inode 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci if (create) 21362306a36Sopenharmony_ci IWRITE_LOCK(ip, RDWRLOCK_NORMAL); 21462306a36Sopenharmony_ci else 21562306a36Sopenharmony_ci IREAD_LOCK(ip, RDWRLOCK_NORMAL); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && 21862306a36Sopenharmony_ci (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && 21962306a36Sopenharmony_ci xaddr) { 22062306a36Sopenharmony_ci if (xflag & XAD_NOTRECORDED) { 22162306a36Sopenharmony_ci if (!create) 22262306a36Sopenharmony_ci /* 22362306a36Sopenharmony_ci * Allocated but not recorded, read treats 22462306a36Sopenharmony_ci * this as a hole 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci goto unlock; 22762306a36Sopenharmony_ci XADoffset(&xad, lblock64); 22862306a36Sopenharmony_ci XADlength(&xad, xlen); 22962306a36Sopenharmony_ci XADaddress(&xad, xaddr); 23062306a36Sopenharmony_ci rc = extRecord(ip, &xad); 23162306a36Sopenharmony_ci if (rc) 23262306a36Sopenharmony_ci goto unlock; 23362306a36Sopenharmony_ci set_buffer_new(bh_result); 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci map_bh(bh_result, ip->i_sb, xaddr); 23762306a36Sopenharmony_ci bh_result->b_size = xlen << ip->i_blkbits; 23862306a36Sopenharmony_ci goto unlock; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci if (!create) 24162306a36Sopenharmony_ci goto unlock; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* 24462306a36Sopenharmony_ci * Allocate a new block 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ci if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) 24762306a36Sopenharmony_ci goto unlock; 24862306a36Sopenharmony_ci rc = extAlloc(ip, xlen, lblock64, &xad, false); 24962306a36Sopenharmony_ci if (rc) 25062306a36Sopenharmony_ci goto unlock; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci set_buffer_new(bh_result); 25362306a36Sopenharmony_ci map_bh(bh_result, ip->i_sb, addressXAD(&xad)); 25462306a36Sopenharmony_ci bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci unlock: 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * Release lock on inode 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci if (create) 26162306a36Sopenharmony_ci IWRITE_UNLOCK(ip); 26262306a36Sopenharmony_ci else 26362306a36Sopenharmony_ci IREAD_UNLOCK(ip); 26462306a36Sopenharmony_ci return rc; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic int jfs_writepages(struct address_space *mapping, 26862306a36Sopenharmony_ci struct writeback_control *wbc) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci return mpage_writepages(mapping, wbc, jfs_get_block); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic int jfs_read_folio(struct file *file, struct folio *folio) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci return mpage_read_folio(folio, jfs_get_block); 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic void jfs_readahead(struct readahead_control *rac) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci mpage_readahead(rac, jfs_get_block); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic void jfs_write_failed(struct address_space *mapping, loff_t to) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci struct inode *inode = mapping->host; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (to > inode->i_size) { 28862306a36Sopenharmony_ci truncate_pagecache(inode, inode->i_size); 28962306a36Sopenharmony_ci jfs_truncate(inode); 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic int jfs_write_begin(struct file *file, struct address_space *mapping, 29462306a36Sopenharmony_ci loff_t pos, unsigned len, 29562306a36Sopenharmony_ci struct page **pagep, void **fsdata) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci int ret; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci ret = block_write_begin(mapping, pos, len, pagep, jfs_get_block); 30062306a36Sopenharmony_ci if (unlikely(ret)) 30162306a36Sopenharmony_ci jfs_write_failed(mapping, pos + len); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return ret; 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic int jfs_write_end(struct file *file, struct address_space *mapping, 30762306a36Sopenharmony_ci loff_t pos, unsigned len, unsigned copied, struct page *page, 30862306a36Sopenharmony_ci void *fsdata) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci int ret; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); 31362306a36Sopenharmony_ci if (ret < len) 31462306a36Sopenharmony_ci jfs_write_failed(mapping, pos + len); 31562306a36Sopenharmony_ci return ret; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic sector_t jfs_bmap(struct address_space *mapping, sector_t block) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci return generic_block_bmap(mapping, block, jfs_get_block); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic ssize_t jfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci struct file *file = iocb->ki_filp; 32662306a36Sopenharmony_ci struct address_space *mapping = file->f_mapping; 32762306a36Sopenharmony_ci struct inode *inode = file->f_mapping->host; 32862306a36Sopenharmony_ci size_t count = iov_iter_count(iter); 32962306a36Sopenharmony_ci ssize_t ret; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci ret = blockdev_direct_IO(iocb, inode, iter, jfs_get_block); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* 33462306a36Sopenharmony_ci * In case of error extending write may have instantiated a few 33562306a36Sopenharmony_ci * blocks outside i_size. Trim these off again. 33662306a36Sopenharmony_ci */ 33762306a36Sopenharmony_ci if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) { 33862306a36Sopenharmony_ci loff_t isize = i_size_read(inode); 33962306a36Sopenharmony_ci loff_t end = iocb->ki_pos + count; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (end > isize) 34262306a36Sopenharmony_ci jfs_write_failed(mapping, end); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci return ret; 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ciconst struct address_space_operations jfs_aops = { 34962306a36Sopenharmony_ci .dirty_folio = block_dirty_folio, 35062306a36Sopenharmony_ci .invalidate_folio = block_invalidate_folio, 35162306a36Sopenharmony_ci .read_folio = jfs_read_folio, 35262306a36Sopenharmony_ci .readahead = jfs_readahead, 35362306a36Sopenharmony_ci .writepages = jfs_writepages, 35462306a36Sopenharmony_ci .write_begin = jfs_write_begin, 35562306a36Sopenharmony_ci .write_end = jfs_write_end, 35662306a36Sopenharmony_ci .bmap = jfs_bmap, 35762306a36Sopenharmony_ci .direct_IO = jfs_direct_IO, 35862306a36Sopenharmony_ci .migrate_folio = buffer_migrate_folio, 35962306a36Sopenharmony_ci}; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/* 36262306a36Sopenharmony_ci * Guts of jfs_truncate. Called with locks already held. Can be called 36362306a36Sopenharmony_ci * with directory for truncating directory index table. 36462306a36Sopenharmony_ci */ 36562306a36Sopenharmony_civoid jfs_truncate_nolock(struct inode *ip, loff_t length) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci loff_t newsize; 36862306a36Sopenharmony_ci tid_t tid; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci ASSERT(length >= 0); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (test_cflag(COMMIT_Nolink, ip)) { 37362306a36Sopenharmony_ci xtTruncate(0, ip, length, COMMIT_WMAP); 37462306a36Sopenharmony_ci return; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci do { 37862306a36Sopenharmony_ci tid = txBegin(ip->i_sb, 0); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* 38162306a36Sopenharmony_ci * The commit_mutex cannot be taken before txBegin. 38262306a36Sopenharmony_ci * txBegin may block and there is a chance the inode 38362306a36Sopenharmony_ci * could be marked dirty and need to be committed 38462306a36Sopenharmony_ci * before txBegin unblocks 38562306a36Sopenharmony_ci */ 38662306a36Sopenharmony_ci mutex_lock(&JFS_IP(ip)->commit_mutex); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci newsize = xtTruncate(tid, ip, length, 38962306a36Sopenharmony_ci COMMIT_TRUNCATE | COMMIT_PWMAP); 39062306a36Sopenharmony_ci if (newsize < 0) { 39162306a36Sopenharmony_ci txEnd(tid); 39262306a36Sopenharmony_ci mutex_unlock(&JFS_IP(ip)->commit_mutex); 39362306a36Sopenharmony_ci break; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci ip->i_mtime = inode_set_ctime_current(ip); 39762306a36Sopenharmony_ci mark_inode_dirty(ip); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci txCommit(tid, 1, &ip, 0); 40062306a36Sopenharmony_ci txEnd(tid); 40162306a36Sopenharmony_ci mutex_unlock(&JFS_IP(ip)->commit_mutex); 40262306a36Sopenharmony_ci } while (newsize > length); /* Truncate isn't always atomic */ 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_civoid jfs_truncate(struct inode *ip) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci jfs_info("jfs_truncate: size = 0x%lx", (ulong) ip->i_size); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci block_truncate_page(ip->i_mapping, ip->i_size, jfs_get_block); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci IWRITE_LOCK(ip, RDWRLOCK_NORMAL); 41262306a36Sopenharmony_ci jfs_truncate_nolock(ip, ip->i_size); 41362306a36Sopenharmony_ci IWRITE_UNLOCK(ip); 41462306a36Sopenharmony_ci} 415