xref: /linux/fs/jfs/inode.c (revision 79828b4fa835f73cdaf4bffa48696abdcbea9d02)
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