diff options
Diffstat (limited to 'fs/jfs')
44 files changed, 33077 insertions, 0 deletions
diff --git a/fs/jfs/Makefile b/fs/jfs/Makefile new file mode 100644 index 00000000000..6f1e0e95587 --- /dev/null +++ b/fs/jfs/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the Linux JFS filesystem routines. +# + +obj-$(CONFIG_JFS_FS) += jfs.o + +jfs-y := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \ + jfs_xtree.o jfs_imap.o jfs_debug.o jfs_dmap.o \ + jfs_unicode.o jfs_dtree.o jfs_inode.o \ + jfs_extent.o symlink.o jfs_metapage.o \ + jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o resize.o xattr.o + +jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o + +EXTRA_CFLAGS += -D_JFS_4K diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c new file mode 100644 index 00000000000..8d2a9ab981d --- /dev/null +++ b/fs/jfs/acl.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) International Business Machines Corp., 2002-2004 + * Copyright (C) Andreas Gruenbacher, 2001 + * Copyright (C) Linus Torvalds, 1991, 1992 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/quotaops.h> +#include "jfs_incore.h" +#include "jfs_xattr.h" +#include "jfs_acl.h" + +static struct posix_acl *jfs_get_acl(struct inode *inode, int type) +{ + struct posix_acl *acl; + char *ea_name; + struct jfs_inode_info *ji = JFS_IP(inode); + struct posix_acl **p_acl; + int size; + char *value = NULL; + + switch(type) { + case ACL_TYPE_ACCESS: + ea_name = XATTR_NAME_ACL_ACCESS; + p_acl = &ji->i_acl; + break; + case ACL_TYPE_DEFAULT: + ea_name = XATTR_NAME_ACL_DEFAULT; + p_acl = &ji->i_default_acl; + break; + default: + return ERR_PTR(-EINVAL); + } + + if (*p_acl != JFS_ACL_NOT_CACHED) + return posix_acl_dup(*p_acl); + + size = __jfs_getxattr(inode, ea_name, NULL, 0); + + if (size > 0) { + value = kmalloc(size, GFP_KERNEL); + if (!value) + return ERR_PTR(-ENOMEM); + size = __jfs_getxattr(inode, ea_name, value, size); + } + + if (size < 0) { + if (size == -ENODATA) { + *p_acl = NULL; + acl = NULL; + } else + acl = ERR_PTR(size); + } else { + acl = posix_acl_from_xattr(value, size); + if (!IS_ERR(acl)) + *p_acl = posix_acl_dup(acl); + } + if (value) + kfree(value); + return acl; +} + +static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) +{ + char *ea_name; + struct jfs_inode_info *ji = JFS_IP(inode); + struct posix_acl **p_acl; + int rc; + int size = 0; + char *value = NULL; + + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + + switch(type) { + case ACL_TYPE_ACCESS: + ea_name = XATTR_NAME_ACL_ACCESS; + p_acl = &ji->i_acl; + break; + case ACL_TYPE_DEFAULT: + ea_name = XATTR_NAME_ACL_DEFAULT; + p_acl = &ji->i_default_acl; + if (!S_ISDIR(inode->i_mode)) + return acl ? -EACCES : 0; + break; + default: + return -EINVAL; + } + if (acl) { + size = xattr_acl_size(acl->a_count); + value = kmalloc(size, GFP_KERNEL); + if (!value) + return -ENOMEM; + rc = posix_acl_to_xattr(acl, value, size); + if (rc < 0) + goto out; + } + rc = __jfs_setxattr(inode, ea_name, value, size, 0); +out: + if (value) + kfree(value); + + if (!rc) { + if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) + posix_acl_release(*p_acl); + *p_acl = posix_acl_dup(acl); + } + return rc; +} + +static int jfs_check_acl(struct inode *inode, int mask) +{ + struct jfs_inode_info *ji = JFS_IP(inode); + + if (ji->i_acl == JFS_ACL_NOT_CACHED) { + struct posix_acl *acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR(acl)) + return PTR_ERR(acl); + posix_acl_release(acl); + } + + if (ji->i_acl) + return posix_acl_permission(inode, ji->i_acl, mask); + return -EAGAIN; +} + +int jfs_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + return generic_permission(inode, mask, jfs_check_acl); +} + +int jfs_init_acl(struct inode *inode, struct inode *dir) +{ + struct posix_acl *acl = NULL; + struct posix_acl *clone; + mode_t mode; + int rc = 0; + + if (S_ISLNK(inode->i_mode)) + return 0; + + acl = jfs_get_acl(dir, ACL_TYPE_DEFAULT); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + if (acl) { + if (S_ISDIR(inode->i_mode)) { + rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl); + if (rc) + goto cleanup; + } + clone = posix_acl_clone(acl, GFP_KERNEL); + if (!clone) { + rc = -ENOMEM; + goto cleanup; + } + mode = inode->i_mode; + rc = posix_acl_create_masq(clone, &mode); + if (rc >= 0) { + inode->i_mode = mode; + if (rc > 0) + rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); + } + posix_acl_release(clone); +cleanup: + posix_acl_release(acl); + } else + inode->i_mode &= ~current->fs->umask; + + return rc; +} + +static int jfs_acl_chmod(struct inode *inode) +{ + struct posix_acl *acl, *clone; + int rc; + + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + + acl = jfs_get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR(acl) || !acl) + return PTR_ERR(acl); + + clone = posix_acl_clone(acl, GFP_KERNEL); + posix_acl_release(acl); + if (!clone) + return -ENOMEM; + + rc = posix_acl_chmod_masq(clone, inode->i_mode); + if (!rc) + rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone); + + posix_acl_release(clone); + return rc; +} + +int jfs_setattr(struct dentry *dentry, struct iattr *iattr) +{ + struct inode *inode = dentry->d_inode; + int rc; + + rc = inode_change_ok(inode, iattr); + if (rc) + return rc; + + if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) || + (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) { + if (DQUOT_TRANSFER(inode, iattr)) + return -EDQUOT; + } + + rc = inode_setattr(inode, iattr); + + if (!rc && (iattr->ia_valid & ATTR_MODE)) + rc = jfs_acl_chmod(inode); + + return rc; +} diff --git a/fs/jfs/endian24.h b/fs/jfs/endian24.h new file mode 100644 index 00000000000..ab7cd0567c9 --- /dev/null +++ b/fs/jfs/endian24.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) International Business Machines Corp., 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _H_ENDIAN24 +#define _H_ENDIAN24 + +/* + * endian24.h: + * + * Endian conversion for 24-byte data + * + */ +#define __swab24(x) \ +({ \ + __u32 __x = (x); \ + ((__u32)( \ + ((__x & (__u32)0x000000ffUL) << 16) | \ + (__x & (__u32)0x0000ff00UL) | \ + ((__x & (__u32)0x00ff0000UL) >> 16) )); \ +}) + +#if (defined(__KERNEL__) && defined(__LITTLE_ENDIAN)) || (defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)) + #define __cpu_to_le24(x) ((__u32)(x)) + #define __le24_to_cpu(x) ((__u32)(x)) +#else + #define __cpu_to_le24(x) __swab24(x) + #define __le24_to_cpu(x) __swab24(x) +#endif + +#ifdef __KERNEL__ + #define cpu_to_le24 __cpu_to_le24 + #define le24_to_cpu __le24_to_cpu +#endif + +#endif /* !_H_ENDIAN24 */ diff --git a/fs/jfs/file.c b/fs/jfs/file.c new file mode 100644 index 00000000000..a87b06fa8ff --- /dev/null +++ b/fs/jfs/file.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) International Business Machines Corp., 2000-2002 + * Portions Copyright (c) Christoph Hellwig, 2001-2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/fs.h> +#include "jfs_incore.h" +#include "jfs_dmap.h" +#include "jfs_txnmgr.h" +#include "jfs_xattr.h" +#include "jfs_acl.h" +#include "jfs_debug.h" + + +extern int jfs_commit_inode(struct inode *, int); +extern void jfs_truncate(struct inode *); + +int jfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + struct inode *inode = dentry->d_inode; + int rc = 0; + + if (!(inode->i_state & I_DIRTY) || + (datasync && !(inode->i_state & I_DIRTY_DATASYNC))) { + /* Make sure committed changes hit the disk */ + jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1); + return rc; + } + + rc |= jfs_commit_inode(inode, 1); + + return rc ? -EIO : 0; +} + +static int jfs_open(struct inode *inode, struct file *file) +{ + int rc; + + if ((rc = generic_file_open(inode, file))) + return rc; + + /* + * We attempt to allow only one "active" file open per aggregate + * group. Otherwise, appending to files in parallel can cause + * fragmentation within the files. + * + * If the file is empty, it was probably just created and going + * to be written to. If it has a size, we'll hold off until the + * file is actually grown. + */ + if (S_ISREG(inode->i_mode) && file->f_mode & FMODE_WRITE && + (inode->i_size == 0)) { + struct jfs_inode_info *ji = JFS_IP(inode); + spin_lock_irq(&ji->ag_lock); + if (ji->active_ag == -1) { + ji->active_ag = ji->agno; + atomic_inc( + &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]); + } + spin_unlock_irq(&ji->ag_lock); + } + + return 0; +} +static int jfs_release(struct inode *inode, struct file *file) +{ + struct jfs_inode_info *ji = JFS_IP(inode); + + spin_lock_irq(&ji->ag_lock); + if (ji->active_ag != -1) { + struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; + atomic_dec(&bmap->db_active[ji->active_ag]); + ji->active_ag = -1; + } + spin_unlock_irq(&ji->ag_lock); + + return 0; +} + +struct inode_operations jfs_file_inode_operations = { + .truncate = jfs_truncate, + .setxattr = jfs_setxattr, + .getxattr = jfs_getxattr, + .listxattr = jfs_listxattr, + .removexattr = jfs_removexattr, +#ifdef CONFIG_JFS_POSIX_ACL + .setattr = jfs_setattr, + .permission = jfs_permission, +#endif +}; + +struct file_operations jfs_file_operations = { + .open = jfs_open, + .llseek = generic_file_llseek, + .write = generic_file_write, + .read = generic_file_read, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, + .mmap = generic_file_mmap, + .readv = generic_file_readv, + .writev = generic_file_writev, + .sendfile = generic_file_sendfile, + .fsync = jfs_fsync, + .release = jfs_release, +}; diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c new file mode 100644 index 00000000000..7bc906677b0 --- /dev/null +++ b/fs/jfs/inode.c @@ -0,0 +1,384 @@ +/* + * Copyright (C) International Business Machines Corp., 2000-2004 + * Portions Copyright (C) Christoph Hellwig, 2001-2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/fs.h> +#include <linux/mpage.h> +#include <linux/buffer_head.h> +#include <linux/pagemap.h> +#include <linux/quotaops.h> +#include "jfs_incore.h" +#include "jfs_filsys.h" +#include "jfs_imap.h" +#include "jfs_extent.h" +#include "jfs_unicode.h" +#include "jfs_debug.h" + + +extern struct inode_operations jfs_dir_inode_operations; +extern struct inode_operations jfs_file_inode_operations; +extern struct inode_operations jfs_symlink_inode_operations; +extern struct file_operations jfs_dir_operations; +extern struct file_operations jfs_file_operations; +struct address_space_operations jfs_aops; +extern int freeZeroLink(struct inode *); + +void jfs_read_inode(struct inode *inode) +{ + if (diRead(inode)) { + make_bad_inode(inode); + return; + } + + if (S_ISREG(inode->i_mode)) { + inode->i_op = &jfs_file_inode_operations; + inode->i_fop = &jfs_file_operations; + inode->i_mapping->a_ops = &jfs_aops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &jfs_dir_inode_operations; + inode->i_fop = &jfs_dir_operations; + } else if (S_ISLNK(inode->i_mode)) { + if (inode->i_size >= IDATASIZE) { + inode->i_op = &page_symlink_inode_operations; + inode->i_mapping->a_ops = &jfs_aops; + } else + inode->i_op = &jfs_symlink_inode_operations; + } else { + inode->i_op = &jfs_file_inode_operations; + init_special_inode(inode, inode->i_mode, inode->i_rdev); + } +} + +/* + * Workhorse of both fsync & write_inode + */ +int jfs_commit_inode(struct inode *inode, int wait) +{ + int rc = 0; + tid_t tid; + static int noisy = 5; + + jfs_info("In jfs_commit_inode, inode = 0x%p", inode); + + /* + * Don't commit if inode has been committed since last being + * marked dirty, or if it has been deleted. + */ + if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode)) + return 0; + + if (isReadOnly(inode)) { + /* kernel allows writes to devices on read-only + * partitions and may think inode is dirty + */ + if (!special_file(inode->i_mode) && noisy) { + jfs_err("jfs_commit_inode(0x%p) called on " + "read-only volume", inode); + jfs_err("Is remount racy?"); + noisy--; + } + return 0; + } + + tid = txBegin(inode->i_sb, COMMIT_INODE); + down(&JFS_IP(inode)->commit_sem); + + /* + * Retest inode state after taking commit_sem + */ + if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode)) + rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); + + txEnd(tid); + up(&JFS_IP(inode)->commit_sem); + return rc; +} + +int jfs_write_inode(struct inode *inode, int wait) +{ + if (test_cflag(COMMIT_Nolink, inode)) + return 0; + /* + * If COMMIT_DIRTY is not set, the inode isn't really dirty. + * It has been committed since the last change, but was still + * on the dirty inode list. + */ + if (!test_cflag(COMMIT_Dirty, inode)) { + /* Make sure committed changes hit the disk */ + jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait); + return 0; + } + + if (jfs_commit_inode(inode, wait)) { + jfs_err("jfs_write_inode: jfs_commit_inode failed!"); + return -EIO; + } else + return 0; +} + +void jfs_delete_inode(struct inode *inode) +{ + jfs_info("In jfs_delete_inode, inode = 0x%p", inode); + + if (test_cflag(COMMIT_Freewmap, inode)) + freeZeroLink(inode); + + diFree(inode); + + /* + * Free the inode from the quota allocation. + */ + DQUOT_INIT(inode); + DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); + + clear_inode(inode); +} + +void jfs_dirty_inode(struct inode *inode) +{ + static int noisy = 5; + + if (isReadOnly(inode)) { + if (!special_file(inode->i_mode) && noisy) { + /* kernel allows writes to devices on read-only + * partitions and may try to mark inode dirty + */ + jfs_err("jfs_dirty_inode called on read-only volume"); + jfs_err("Is remount racy?"); + noisy--; + } + return; + } + + set_cflag(COMMIT_Dirty, inode); +} + +static int +jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, + struct buffer_head *bh_result, int create) +{ + s64 lblock64 = lblock; + int rc = 0; + int take_locks; + xad_t xad; + s64 xaddr; + int xflag; + s32 xlen; + + /* + * If this is a special inode (imap, dmap) + * the lock should already be taken + */ + take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I); + + /* + * Take appropriate lock on inode + */ + if (take_locks) { + if (create) + IWRITE_LOCK(ip); + else + IREAD_LOCK(ip); + } + + if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && + (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0) + == 0) && xlen) { + if (xflag & XAD_NOTRECORDED) { + if (!create) + /* + * Allocated but not recorded, read treats + * this as a hole + */ + goto unlock; +#ifdef _JFS_4K + XADoffset(&xad, lblock64); + XADlength(&xad, xlen); + XADaddress(&xad, xaddr); +#else /* _JFS_4K */ + /* + * As long as block size = 4K, this isn't a problem. + * We should mark the whole page not ABNR, but how + * will we know to mark the other blocks BH_New? + */ + BUG(); +#endif /* _JFS_4K */ + rc = extRecord(ip, &xad); + if (rc) + goto unlock; + set_buffer_new(bh_result); + } + + map_bh(bh_result, ip->i_sb, xaddr); + bh_result->b_size = xlen << ip->i_blkbits; + goto unlock; + } + if (!create) + goto unlock; + + /* + * Allocate a new block + */ +#ifdef _JFS_4K + if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) + goto unlock; + rc = extAlloc(ip, max_blocks, lblock64, &xad, FALSE); + if (rc) + goto unlock; + + set_buffer_new(bh_result); + map_bh(bh_result, ip->i_sb, addressXAD(&xad)); + bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits; + +#else /* _JFS_4K */ + /* + * We need to do whatever it takes to keep all but the last buffers + * in 4K pages - see jfs_write.c + */ + BUG(); +#endif /* _JFS_4K */ + + unlock: + /* + * Release lock on inode + */ + if (take_locks) { + if (create) + IWRITE_UNLOCK(ip); + else + IREAD_UNLOCK(ip); + } + return rc; +} + +static int jfs_get_block(struct inode *ip, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + return jfs_get_blocks(ip, lblock, 1, bh_result, create); +} + +static int jfs_writepage(struct page *page, struct writeback_control *wbc) +{ + return nobh_writepage(page, jfs_get_block, wbc); +} + +static int jfs_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + return mpage_writepages(mapping, wbc, jfs_get_block); +} + +static int jfs_readpage(struct file *file, struct page *page) +{ + return mpage_readpage(page, jfs_get_block); +} + +static int jfs_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned nr_pages) +{ + return mpage_readpages(mapping, pages, nr_pages, jfs_get_block); +} + +static int jfs_prepare_write(struct file *file, + struct page *page, unsigned from, unsigned to) +{ + return nobh_prepare_write(page, from, to, jfs_get_block); +} + +static sector_t jfs_bmap(struct address_space *mapping, sector_t block) +{ + return generic_block_bmap(mapping, block, jfs_get_block); +} + +static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, loff_t offset, unsigned long nr_segs) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; + + return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, jfs_get_blocks, NULL); +} + +struct address_space_operations jfs_aops = { + .readpage = jfs_readpage, + .readpages = jfs_readpages, + .writepage = jfs_writepage, + .writepages = jfs_writepages, + .sync_page = block_sync_page, + .prepare_write = jfs_prepare_write, + .commit_write = nobh_commit_write, + .bmap = jfs_bmap, + .direct_IO = jfs_direct_IO, +}; + +/* + * Guts of jfs_truncate. Called with locks already held. Can be called + * with directory for truncating directory index table. + */ +void jfs_truncate_nolock(struct inode *ip, loff_t length) +{ + loff_t newsize; + tid_t tid; + + ASSERT(length >= 0); + + if (test_cflag(COMMIT_Nolink, ip)) { + xtTruncate(0, ip, length, COMMIT_WMAP); + return; + } + + do { + tid = txBegin(ip->i_sb, 0); + + /* + * The commit_sem cannot be taken before txBegin. + * txBegin may block and there is a chance the inode + * could be marked dirty and need to be committed + * before txBegin unblocks + */ + down(&JFS_IP(ip)->commit_sem); + + newsize = xtTruncate(tid, ip, length, + COMMIT_TRUNCATE | COMMIT_PWMAP); + if (newsize < 0) { + txEnd(tid); + up(&JFS_IP(ip)->commit_sem); + break; + } + + ip->i_mtime = ip->i_ctime = CURRENT_TIME; + mark_inode_dirty(ip); + + txCommit(tid, 1, &ip, 0); + txEnd(tid); + up(&JFS_IP(ip)->commit_sem); + } while (newsize > length); /* Truncate isn't always atomic */ +} + +void jfs_truncate(struct inode *ip) +{ + jfs_info("jfs_truncate: size = 0x%lx", (ulong) ip->i_size); + + nobh_truncate_page(ip->i_mapping, ip->i_size); + + IWRITE_LOCK(ip); + jfs_truncate_nolock(ip, ip->i_size); + IWRITE_UNLOCK(ip); +} diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h new file mode 100644 index 00000000000..d2ae430adec --- /dev/null +++ b/fs/jfs/jfs_acl.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) International Business Machines Corp., 2002 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _H_JFS_ACL +#define _H_JFS_ACL + +#ifdef CONFIG_JFS_POSIX_ |