diff options
Diffstat (limited to 'fs')
124 files changed, 694 insertions, 678 deletions
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 3128aa9..9ac4ffe9 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -32,6 +32,7 @@ #include <linux/inet.h> #include <linux/pagemap.h> #include <linux/idr.h> +#include <linux/sched.h> #include "debug.h" #include "v9fs.h" diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 775e26e..d939604 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -33,6 +33,7 @@ #include <linux/inet.h> #include <linux/namei.h> #include <linux/idr.h> +#include <linux/sched.h> #include "debug.h" #include "v9fs.h" diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 7624821..c76cd8f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -33,6 +33,7 @@ #include <linux/inet.h> #include <linux/namei.h> #include <linux/idr.h> +#include <linux/sched.h> #include "debug.h" #include "v9fs.h" diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 8eb9263..7bdf8b3 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -36,6 +36,7 @@ #include <linux/seq_file.h> #include <linux/mount.h> #include <linux/idr.h> +#include <linux/sched.h> #include "debug.h" #include "v9fs.h" diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 74c6440..d4fc609 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -38,7 +38,7 @@ config BINFMT_ELF_FDPIC config BINFMT_FLAT tristate "Kernel support for flat binaries" - depends on !MMU || SUPERH + depends on !MMU help Support uClinux FLAT format binaries. diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 30c2965..de2ed5c 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -232,8 +232,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct adfs_inode_info *ei = (struct adfs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/affs/inode.c b/fs/affs/inode.c index c5b9d73c..4609a6c 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -9,7 +9,7 @@ * * (C) 1991 Linus Torvalds - minix filesystem */ - +#include <linux/sched.h> #include "affs.h" extern const struct inode_operations affs_symlink_inode_operations; diff --git a/fs/affs/super.c b/fs/affs/super.c index beff7d2..6d0ebc3 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -15,6 +15,7 @@ #include <linux/statfs.h> #include <linux/parser.h> #include <linux/magic.h> +#include <linux/sched.h> #include "affs.h" extern struct timezone sys_tz; @@ -87,11 +88,9 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct affs_inode_info *ei = (struct affs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - init_MUTEX(&ei->i_link_lock); - init_MUTEX(&ei->i_ext_lock); - inode_init_once(&ei->vfs_inode); - } + init_MUTEX(&ei->i_link_lock); + init_MUTEX(&ei->i_ext_lock); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/afs/callback.c b/fs/afs/callback.c index f64e40f..bacf518 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/circ_buf.h> +#include <linux/sched.h> #include "internal.h" unsigned afs_vnode_update_timeout = 10; diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 9b1311a..175a567 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c @@ -13,6 +13,7 @@ #include <linux/slab.h> #include <linux/key.h> #include <linux/ctype.h> +#include <linux/sched.h> #include <keys/rxrpc-type.h> #include "internal.h" diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 719af4f..546c595 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -16,6 +16,7 @@ #include <linux/fs.h> #include <linux/pagemap.h> #include <linux/ctype.h> +#include <linux/sched.h> #include "internal.h" static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 47f5fed..d196840 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -19,6 +19,7 @@ #include <linux/slab.h> #include <linux/fs.h> #include <linux/pagemap.h> +#include <linux/sched.h> #include "internal.h" struct afs_iget_data { diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 4953ba5..2dac3ad 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -16,6 +16,7 @@ #include <linux/skbuff.h> #include <linux/rxrpc.h> #include <linux/key.h> +#include <linux/workqueue.h> #include "afs.h" #include "afs_vl.h" diff --git a/fs/afs/main.c b/fs/afs/main.c index f1f71ff..cd21195 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c @@ -13,6 +13,7 @@ #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/completion.h> +#include <linux/sched.h> #include "internal.h" MODULE_DESCRIPTION("AFS Client File System"); diff --git a/fs/afs/proc.c b/fs/afs/proc.c index d5601f6..13df512 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> +#include <linux/sched.h> #include <asm/uaccess.h> #include "internal.h" diff --git a/fs/afs/security.c b/fs/afs/security.c index e0ea88b..566fe71 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c @@ -13,6 +13,7 @@ #include <linux/slab.h> #include <linux/fs.h> #include <linux/ctype.h> +#include <linux/sched.h> #include <keys/rxrpc-type.h> #include "internal.h" diff --git a/fs/afs/super.c b/fs/afs/super.c index 579af63..2e8496b 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -22,6 +22,7 @@ #include <linux/pagemap.h> #include <linux/parser.h> #include <linux/statfs.h> +#include <linux/sched.h> #include "internal.h" #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ @@ -47,7 +48,6 @@ struct file_system_type afs_fs_type = { static const struct super_operations afs_super_ops = { .statfs = afs_statfs, .alloc_inode = afs_alloc_inode, - .drop_inode = generic_delete_inode, .write_inode = afs_write_inode, .destroy_inode = afs_destroy_inode, .clear_inode = afs_clear_inode, @@ -452,17 +452,15 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep, { struct afs_vnode *vnode = _vnode; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - memset(vnode, 0, sizeof(*vnode)); - inode_init_once(&vnode->vfs_inode); - init_waitqueue_head(&vnode->update_waitq); - mutex_init(&vnode->permits_lock); - mutex_init(&vnode->validate_lock); - spin_lock_init(&vnode->writeback_lock); - spin_lock_init(&vnode->lock); - INIT_LIST_HEAD(&vnode->writebacks); - INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); - } + memset(vnode, 0, sizeof(*vnode)); + inode_init_once(&vnode->vfs_inode); + init_waitqueue_head(&vnode->update_waitq); + mutex_init(&vnode->permits_lock); + mutex_init(&vnode->validate_lock); + spin_lock_init(&vnode->writeback_lock); + spin_lock_init(&vnode->lock); + INIT_LIST_HEAD(&vnode->writebacks); + INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); } /* diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c index 3370cdb..09e3ad0 100644 --- a/fs/afs/vlocation.c +++ b/fs/afs/vlocation.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/sched.h> #include "internal.h" unsigned afs_vlocation_timeout = 10; /* volume location timeout in seconds */ diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c index c36c98c..232c55d 100644 --- a/fs/afs/vnode.c +++ b/fs/afs/vnode.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/fs.h> +#include <linux/sched.h> #include "internal.h" #if 0 diff --git a/fs/afs/volume.c b/fs/afs/volume.c index dd160ca..8bab0e3 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/fs.h> #include <linux/pagemap.h> +#include <linux/sched.h> #include "internal.h" static const char *afs_voltypes[] = { "R/W", "R/O", "BAK" }; diff --git a/fs/afs/write.c b/fs/afs/write.c index 28f3751..a03b92a 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -206,7 +206,6 @@ int afs_prepare_write(struct file *file, struct page *page, _leave(" = %d [prep]", ret); return ret; } - SetPageUptodate(page); } try_again: @@ -311,8 +310,8 @@ int afs_commit_write(struct file *file, struct page *page, spin_unlock(&vnode->writeback_lock); } + SetPageUptodate(page); set_page_dirty(page); - if (PageDirty(page)) _debug("dirtied"); diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index fe96108..a5c5171 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -292,10 +292,8 @@ befs_destroy_inode(struct inode *inode) static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct befs_inode_info *bi = (struct befs_inode_info *) foo; - - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&bi->vfs_inode); - } + + inode_init_once(&bi->vfs_inode); } static void diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index edc08d8..58c7bd9 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -248,8 +248,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct bfs_inode_info *bi = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&bi->vfs_inode); + inode_init_once(&bi->vfs_inode); } static int init_inodecache(void) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 72d0b41..330fd3f 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -18,7 +18,7 @@ #include <linux/module.h> #include <linux/init.h> - +#include <linux/sched.h> #include <linux/binfmts.h> #include <linux/slab.h> #include <linux/ctype.h> diff --git a/fs/block_dev.c b/fs/block_dev.c index 7428992..ea1480a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -458,17 +458,15 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag struct bdev_inode *ei = (struct bdev_inode *) foo; struct block_device *bdev = &ei->bdev; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - memset(bdev, 0, sizeof(*bdev)); - mutex_init(&bdev->bd_mutex); - sema_init(&bdev->bd_mount_sem, 1); - INIT_LIST_HEAD(&bdev->bd_inodes); - INIT_LIST_HEAD(&bdev->bd_list); + memset(bdev, 0, sizeof(*bdev)); + mutex_init(&bdev->bd_mutex); + sema_init(&bdev->bd_mount_sem, 1); + INIT_LIST_HEAD(&bdev->bd_inodes); + INIT_LIST_HEAD(&bdev->bd_list); #ifdef CONFIG_SYSFS - INIT_LIST_HEAD(&bdev->bd_holder_list); + INIT_LIST_HEAD(&bdev->bd_holder_list); #endif - inode_init_once(&ei->vfs_inode); - } + inode_init_once(&ei->vfs_inode); } static inline void __bd_forget(struct inode *inode) diff --git a/fs/buffer.c b/fs/buffer.c index aecd057..aa68206 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -981,7 +981,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, struct page *page; struct buffer_head *bh; - page = find_or_create_page(inode->i_mapping, index, GFP_NOFS); + page = find_or_create_page(inode->i_mapping, index, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); if (!page) return NULL; @@ -2100,7 +2101,7 @@ int cont_prepare_write(struct page *page, unsigned offset, PAGE_CACHE_SIZE, get_block); if (status) goto out_unmap; - zero_user_page(page, zerofrom, PAGE_CACHE_SIZE - zerofrom, + zero_user_page(new_page, zerofrom, PAGE_CACHE_SIZE - zerofrom, KM_USER0); generic_commit_write(NULL, new_page, zerofrom, PAGE_CACHE_SIZE); unlock_page(new_page); @@ -2898,8 +2899,9 @@ static void recalc_bh_state(void) struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) { - struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); + struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags); if (ret) { + INIT_LIST_HEAD(&ret->b_assoc_buffers); get_cpu_var(bh_accounting).nr++; recalc_bh_state(); put_cpu_var(bh_accounting); @@ -2918,17 +2920,6 @@ void free_buffer_head(struct buffer_head *bh) } EXPORT_SYMBOL(free_buffer_head); -static void -init_buffer_head(void *data, struct kmem_cache *cachep, unsigned long flags) -{ - if (flags & SLAB_CTOR_CONSTRUCTOR) { - struct buffer_head * bh = (struct buffer_head *)data; - - memset(bh, 0, sizeof(*bh)); - INIT_LIST_HEAD(&bh->b_assoc_buffers); - } -} - static void buffer_exit_cpu(int cpu) { int i; @@ -2955,12 +2946,8 @@ void __init buffer_init(void) { int nrpages; - bh_cachep = kmem_cache_create("buffer_head", - sizeof(struct buffer_head), 0, - (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC| - SLAB_MEM_SPREAD), - init_buffer_head, - NULL); + bh_cachep = KMEM_CACHE(buffer_head, + SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD); /* * Limit the bh occupancy to 10% of ZONE_NORMAL diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8568e10..d38c69b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -701,10 +701,8 @@ cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags) { struct cifsInodeInfo *cifsi = inode; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&cifsi->vfs_inode); - INIT_LIST_HEAD(&cifsi->lockList); - } + inode_init_once(&cifsi->vfs_inode); + INIT_LIST_HEAD(&cifsi->lockList); } static int diff --git a/fs/coda/cache.c b/fs/coda/cache.c index 5d05271..fcb88fa 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c @@ -16,6 +16,7 @@ #include <asm/uaccess.h> #include <linux/string.h> #include <linux/list.h> +#include <linux/sched.h> #include <linux/coda.h> #include <linux/coda_linux.h> diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 0aaff36..dbff1bd 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -62,8 +62,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct coda_inode_info *ei = (struct coda_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } int coda_init_inodecache(void) diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index a5b5e63..5faacdb 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -16,7 +16,7 @@ #include <asm/system.h> #include <linux/signal.h> - +#include <linux/sched.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/mm.h> diff --git a/fs/compat.c b/fs/compat.c index 7b21b0a..4db6216 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1544,9 +1544,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) { fd_set_bits fds; - char *bits; + void *bits; int size, max_fds, ret = -EINVAL; struct fdtable *fdt; + long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; if (n < 0) goto out_nofds; @@ -1564,11 +1565,14 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, * since we used fdset we need to allocate memory in units of * long-words. */ - ret = -ENOMEM; size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; + bits = stack_fds; + if (size > sizeof(stack_fds) / 6) { + bits = kmalloc(6 * size, GFP_KERNEL); + ret = -ENOMEM; + if (!bits) + goto out_nofds; + } fds.in = (unsigned long *) bits; fds.out = (unsigned long *) (bits + size); fds.ex = (unsigned long *) (bits + 2*size); @@ -1600,7 +1604,8 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, compat_set_fd_set(n, exp, fds.res_ex)) ret = -EFAULT; out: - kfree(bits); + if (bits != stack_fds) + kfree(bits); out_nofds: return ret; } @@ -2230,21 +2235,16 @@ asmlinkage long compat_sys_signalfd(int ufd, asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags, const struct compat_itimerspec __user *utmr) { - long res; struct itimerspec t; struct itimerspec __user *ut; - res = -EFAULT; if (get_compat_itimerspec(&t, utmr)) - goto err_exit; + return -EFAULT; ut = compat_alloc_user_space(sizeof(*ut)); - if (copy_to_user(ut, &t, sizeof(t)) ) - goto err_exit; + if (copy_to_user(ut, &t, sizeof(t))) + return -EFAULT; - res = sys_timerfd(ufd, clockid, flags, ut); -err_exit: - return res; + return sys_timerfd(ufd, clockid, flags, ut); } #endif /* CONFIG_TIMERFD */ - diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 65643de..6b44cdc 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1194,6 +1194,7 @@ static int vt_check(struct file *file) { struct tty_struct *tty; struct inode *inode = file->f_path.dentry->d_inode; + struct vc_data *vc; if (file->f_op->ioctl != tty_ioctl) return -EINVAL; @@ -1204,12 +1205,16 @@ static int vt_check(struct file *file) if (tty->driver->ioctl != vt_ioctl) return -EINVAL; - + + vc = (struct vc_data *)tty->driver_data; + if (!vc_cons_allocated(vc->vc_num)) /* impossible? */ + return -ENOIOCTLCMD; + /* * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or super-user. + * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. */ - if (current->signal->tty == tty || capable(CAP_SYS_ADMIN)) + if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) return 1; return 0; } @@ -1310,16 +1315,28 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct unimapdesc32 tmp; struct unimapdesc32 __user *user_ud = compat_ptr(arg); int perm = vt_check(file); - - if (perm < 0) return perm; + struct vc_data *vc; + + if (perm < 0) + return perm; if (copy_from_user(&tmp, user_ud, sizeof tmp)) return -EFAULT; + if (tmp.entries) + if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries), + tmp.entry_ct*sizeof(struct unipair))) + return -EFAULT; + vc = ((struct tty_struct *)file->private_data)->driver_data; switch (cmd) { case PIO_UNIMAP: - if (!perm) return -EPERM; - return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries)); + if (!perm) + return -EPERM; + return con_set_unimap(vc, tmp.entry_ct, + compat_ptr(tmp.entries)); case GIO_UNIMAP: - return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); + if (!perm && fg_console != vc->vc_num) + return -EPERM; + return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), + compat_ptr(tmp.entries)); } return 0; } diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index 2ec9bea..ddc003a 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -32,6 +32,7 @@ #include <linux/namei.h> #include <linux/backing-dev.h> #include <linux/capability.h> +#include <linux/sched.h> #include <linux/configfs.h> #include "configfs_internal.h" @@ -1421,7 +1421,7 @@ int vfs_quota_off(struct super_block *sb, int type) /* If quota was reenabled in the meantime, we have * nothing to do */ if (!sb_has_quota_enabled(sb, cnt)) { - mutex_lock(&toputinode[cnt]->i_mutex); + mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA); toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA); truncate_inode_pages(&toputinode[cnt]->i_data, 0); diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 9881b5c..59288d8 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -33,63 +33,6 @@ #include "ecryptfs_kernel.h" /** - * ecryptfs_llseek - * @file: File we are seeking in - * @offset: The offset to seek to - * @origin: 2 - offset from i_size; 1 - offset from f_pos - * - * Returns the position we have seeked to, or negative on error - */ -static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin) -{ - loff_t rv; - loff_t new_end_pos; - int rc; - int expanding_file = 0; - struct inode *inode = file->f_mapping->host; - - /* If our offset is past the end of our file, we're going to - * need to grow it so we have a valid length of 0's */ - new_end_pos = offset; - switch (origin) { - case 2: - new_end_pos += i_size_read(inode); - expanding_file = 1; - break; - case 1: - new_end_pos += file->f_pos; - if (new_end_pos > i_size_read(inode)) { - ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) " - "> i_size_read(inode)(=[0x%.16x])\n", - new_end_pos, i_size_read(inode)); - expanding_file = 1; - } - break; - default: - if (new_end_pos > i_size_read(inode)) { - ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) " - "> i_size_read(inode)(=[0x%.16x])\n", - new_end_pos, i_size_read(inode)); - expanding_file = 1; - } - } - ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos); - if (expanding_file) { - rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos); - if (rc) { - rv = rc; - ecryptfs_printk(KERN_ERR, "Error on attempt to " - "truncate to (higher) offset [0x%.16x];" - " rc = [%d]\n", new_end_pos, rc); - goto out; - } - } - rv = generic_file_llseek(file, offset, origin); -out: - return rv; -} - -/** * ecryptfs_read_update_atime * * generic_file_read updates the atime of upper layer inode. But, it @@ -425,7 +368,7 @@ const struct file_operations ecryptfs_dir_fops = { }; const struct file_operations ecryptfs_main_fops = { - .llseek = ecryptfs_llseek, + .llseek = generic_file_llseek, .read = do_sync_read, .aio_read = ecryptfs_read_update_atime, .write = do_sync_write, diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 8cbf3f6..606128f 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -583,8 +583,7 @@ inode_info_init_once(void *vptr, struct kmem_cache *cachep, unsigned long flags) { struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static struct ecryptfs_cache_info { diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 3baf253..a9d87c4 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ - +#include <linux/sched.h> #include "ecryptfs_kernel.h" static LIST_HEAD(ecryptfs_msg_ctx_free_list); diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 0770c4b..55cec98 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -364,25 +364,43 @@ static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) { struct inode *inode = page->mapping->host; int end_byte_in_page; - char *page_virt; if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) goto out; end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; if (to > end_byte_in_page) end_byte_in_page = to; - page_virt = kmap_atomic(page, KM_USER0); - memset((page_virt + end_byte_in_page), 0, - (PAGE_CACHE_SIZE - end_byte_in_page)); - kunmap_atomic(page_virt, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, end_byte_in_page, + PAGE_CACHE_SIZE - end_byte_in_page, KM_USER0); out: return 0; } +/** + * eCryptfs does not currently support holes. When writing after a + * seek past the end of the file, eCryptfs fills in 0's through to the + * current location. The code to fill in the 0's to all the + * intermediate pages calls ecryptfs_prepare_write_no_truncate(). + */ +static int +ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + int rc = 0; + + if (from == 0 && to == PAGE_CACHE_SIZE) + goto out; /* If we are writing a full page, it will be + up to date. */ + if (!PageUptodate(page)) + rc = ecryptfs_do_readpage(file, page, page->index); +out: + return rc; +} + static int ecryptfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { + loff_t pos; int rc = 0; if (from == 0 && to == PAGE_CACHE_SIZE) @@ -390,6 +408,16 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, up to date. */ if (!PageUptodate(page)) rc = ecryptfs_do_readpage(file, page, page->index); + pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + if (pos > i_size_read(page->mapping->host)) { + rc = ecryptfs_truncate(file->f_path.dentry, pos); + if (rc) { + printk(KERN_ERR "Error on attempt to " + "truncate to (higher) offset [%lld];" + " rc = [%d]\n", pos, rc); + goto out; + } + } out: return rc; } @@ -740,7 +768,6 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) { int rc = 0; struct page *tmp_page; - char *tmp_page_virt; tmp_page = ecryptfs_get1page(file, index); if (IS_ERR(tmp_page)) { @@ -749,18 +776,15 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) rc = PTR_ERR(tmp_page); goto out; } - rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros); - if (rc) { + if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start, + (start + num_zeros)))) { ecryptfs_printk(KERN_ERR, "Error preparing to write zero's " - "to remainder of page at index [0x%.16x]\n", + "to page at index [0x%.16x]\n", index); page_cache_release(tmp_page); goto out; } - tmp_page_virt = kmap_atomic(tmp_page, KM_USER0); - memset(((char *)tmp_page_virt + start), 0, num_zeros); - kunmap_atomic(tmp_page_virt, KM_USER0); - flush_dcache_page(tmp_page); + zero_user_page(tmp_page, start, num_zeros, KM_USER0); rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros); if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error attempting to write zero's " diff --git a/fs/efs/super.c b/fs/efs/super.c index ba7a8b9..e0a6839 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -72,8 +72,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct efs_inode_info *ei = (struct efs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/eventfd.c b/fs/eventfd.c index 480e2b3..2ce19c0 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c @@ -17,7 +17,6 @@ #include <linux/eventfd.h> struct eventfd_ctx { - spinlock_t lock; wait_queue_head_t wqh; /* * Every time that a write(2) is performed on an eventfd, the @@ -45,13 +44,13 @@ int eventfd_signal(struct file *file, int n) if (n < 0) return -EINVAL; - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&ctx->wqh.lock, flags); if (ULLONG_MAX - ctx->count < n) n = (int) (ULLONG_MAX - ctx->count); ctx->count += n; if (waitqueue_active(&ctx->wqh)) wake_up_locked(&ctx->wqh); - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return n; } @@ -70,14 +69,14 @@ static unsigned int eventfd_poll(struct file *file, poll_table *wait) poll_wait(file, &ctx->wqh, wait); - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&ctx->wqh.lock, flags); if (ctx->count > 0) events |= POLLIN; if (ctx->count == ULLONG_MAX) events |= POLLERR; if (ULLONG_MAX - 1 > ctx->count) events |= POLLOUT; - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return events; } @@ -92,7 +91,7 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, if (count < sizeof(ucnt)) return -EINVAL; - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); res = -EAGAIN; ucnt = ctx->count; if (ucnt > 0) @@ -110,9 +109,9 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, res = -ERESTARTSYS; break; } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); schedule(); - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); } __remove_wait_queue(&ctx->wqh, &wait); __set_current_state(TASK_RUNNING); @@ -122,7 +121,7 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, if (waitqueue_active(&ctx->wqh)) wake_up_locked(&ctx->wqh); } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); if (res > 0 && put_user(ucnt, (__u64 __user *) buf)) return -EFAULT; @@ -143,7 +142,7 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c return -EFAULT; if (ucnt == ULLONG_MAX) return -EINVAL; - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); res = -EAGAIN; if (ULLONG_MAX - ctx->count > ucnt) res = sizeof(ucnt); @@ -159,9 +158,9 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c res = -ERESTARTSYS; break; } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); schedule(); - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); } __remove_wait_queue(&ctx->wqh, &wait); __set_current_state(TASK_RUNNING); @@ -171,7 +170,7 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c if (waitqueue_active(&ctx->wqh)) wake_up_locked(&ctx->wqh); } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); return res; } @@ -210,7 +209,6 @@ asmlinkage long sys_eventfd(unsigned int count) return -ENOMEM; init_waitqueue_head(&ctx->wqh); - spin_lock_init(&ctx->lock); ctx->count = count; /* @@ -60,7 +60,7 @@ #endif int core_uses_pid; -char core_pattern[128] = "core"; +char core_pattern[CORENAME_MAX_SIZE] = "core"; int suid_dumpable = 0; EXPORT_SYMBOL(suid_dumpable); @@ -134,6 +134,9 @@ asmlinkage long sys_uselib(const char __user * library) if (error) goto out; + error = -EACCES; + if (nd.mnt->mnt_flags & MNT_NOEXEC) + goto exit; error = -EINVAL; if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; @@ -1264,8 +1267,6 @@ int set_binfmt(struct linux_binfmt *new) EXPORT_SYMBOL(set_binfmt); -#define CORENAME_MAX_SIZE 64 - /* format_corename will inspect the pattern parameter, and output a * name into corename, which must have space for at least * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 685a1c2..16337bf 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -160,13 +160,11 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - rwlock_init(&ei->i_meta_lock); + rwlock_init(&ei->i_meta_lock); #ifdef CONFIG_EXT2_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - inode_init_once(&ei->vfs_inode); - } + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 54d3c90..6e30629 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -466,14 +466,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext3_inode_info *ei = (struct ext3_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_orphan); + INIT_LIST_HEAD(&ei->i_orphan); #ifdef CONFIG_EXT3_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - mutex_init(&ei->truncate_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->truncate_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7191269..cb9afdd 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -517,14 +517,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_orphan); + INIT_LIST_HEAD(&ei->i_orphan); #ifdef CONFIG_EXT4DEV_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - mutex_init(&ei->truncate_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->truncate_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 1959143..3c9c8a1 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -40,8 +40,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct fat_cache *cache = (struct fat_cache *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - INIT_LIST_HEAD(&cache->cache_list); + INIT_LIST_HEAD(&cache->cache_list); } int __init fat_cache_init(void) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 2c55e8d..479722d 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -500,14 +500,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - spin_lock_init(&ei->cache_lru_lock); - ei->nr_caches = 0; - ei->cache_valid_id = FAT_CACHE_VALID + 1; - INIT_LIST_HEAD(&ei->cache_lru); - INIT_HLIST_NODE(&ei->i_fat_hash); - inode_init_once(&ei->vfs_inode); - } + spin_lock_init(&ei->cache_lru_lock); + ei->nr_caches = 0; + ei->cache_valid_id = FAT_CACHE_VALID + 1; + INIT_LIST_HEAD(&ei->cache_lru); + INIT_HLIST_NODE(&ei->i_fat_hash); + inode_init_once(&ei->vfs_inode); } static int __init fat_init_inodecache(void) @@ -12,6 +12,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/fs.h> +#include <linux/sched.h> #include <linux/pipe_fs_i.h> static void wait_for_partner(struct inode* inode, unsigned int *cnt) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8890eba..bd5a772 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -485,7 +485,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, static int fuse_create(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { - if (nd && (nd->flags & LOOKUP_CREATE)) { + if (nd && (nd->flags & LOOKUP_OPEN)) { int err = fuse_create_open(dir, entry, mode, nd); if (err != -ENOSYS) return err; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index acfad65..adf7995 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -11,6 +11,7 @@ #include <linux/pagemap.h> #include <linux/slab.h> #include <linux/kernel.h> +#include <linux/sched.h> static const struct file_operations fuse_direct_io_file_operations; @@ -609,7 +610,9 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, ssize_t res; /* Don't allow parallel writes to the same file */ mutex_lock(&inode->i_mutex); - res = fuse_direct_io(file, buf, count, ppos, 1); + res = generic_write_checks(file, ppos, &count, 0); + if (!res) + res = fuse_direct_io(file, buf, count, ppos, 1); mutex_unlock(&inode->i_mutex); return res; } diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1397018..9804c0c 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -17,6 +17,7 @@ #include <linux/parser.h> #include <linux/statfs.h> #include <linux/random.h> +#include <linux/sched.h> MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); MODULE_DESCRIPTION("Filesystem in Userspace"); @@ -453,6 +454,7 @@ static const struct super_operations fuse_super_operations = { .destroy_inode = fuse_destroy_inode, .read_inode = fuse_read_inode, .clear_inode = fuse_clear_inode, + .drop_inode = generic_delete_inode, .remount_fs = fuse_remount_fs, .put_super = fuse_put_super, .umount_begin = fuse_umount_begin, @@ -687,8 +689,7 @@ static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep, { struct inode * inode = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(inode); + inode_init_once(inode); } static int __init fuse_fs_init(void) diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index 11477ca..b3e152d 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -10,6 +10,7 @@ #ifndef __GLOCK_DOT_H__ #define __GLOCK_DOT_H__ +#include <linux/sched.h> #include "incore.h" /* Flags for lock requests; used in gfs2_holder gh_flag field. diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index e460487..787a0ed 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -27,29 +27,27 @@ static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct gfs2_inode *ip = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&ip->i_inode); - spin_lock_init(&ip->i_spin); - init_rwsem(&ip->i_rw_mutex); - memset(ip->i_cache, 0, sizeof(ip->i_cache)); - } + + inode_init_once(&ip->i_inode); + spin_lock_init(&ip->i_spin); + init_rwsem(&ip->i_rw_mutex); + memset(ip->i_cache, 0, sizeof(ip->i_cache)); } static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct gfs2_glock *gl = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_HLIST_NODE(&gl->gl_list); - spin_lock_init(&gl->gl_spin); - INIT_LIST_HEAD(&gl->gl_holders); - INIT_LIST_HEAD(&gl->gl_waiters1); - INIT_LIST_HEAD(&gl->gl_waiters3); - gl->gl_lvb = NULL; - atomic_set(&gl->gl_lvb_count, 0); - INIT_LIST_HEAD(&gl->gl_reclaim); - INIT_LIST_HEAD(&gl->gl_ail_list); - atomic_set(&gl->gl_ail_count, 0); - } + + INIT_HLIST_NODE(&gl->gl_list); + spin_lock_init(&gl->gl_spin); + INIT_LIST_HEAD(&gl->gl_holders); + INIT_LIST_HEAD(&gl->gl_waiters1); + INIT_LIST_HEAD(&gl->gl_waiters3); + gl->gl_lvb = NULL; + atomic_set(&gl->gl_lvb_count, 0); + INIT_LIST_HEAD(&gl->gl_reclaim); + INIT_LIST_HEAD(&gl->gl_ail_list); + atomic_set(&gl->gl_ail_count, 0); } /** diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index fafcba5..9a934db 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -13,6 +13,7 @@ #include <linux/pagemap.h> #include <linux/mpage.h> +#include <linux/sched.h> #include "hfs_fs.h" #include "btree.h" diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 4f1888f..92cf875 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -434,8 +434,7 @@ static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flag { struct hfs_inode_info *i = p; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&i->vfs_inode); + inode_init_once(&i->vfs_inode); } static int __init init_hfs_fs(void) diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 642012a..45dab5d 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -12,6 +12,7 @@ #include <linux/fs.h> #include <linux/pagemap.h> #include <linux/mpage.h> +#include <linux/sched.h> #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 37afbec..ebd1b38 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -470,8 +470,7 @@ static void hfsplus_init_once(void *p, struct kmem_cache *cachep, unsigned long { struct hfsplus_inode_info *i = p; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&i->vfs_inode); + inode_init_once(&i->vfs_inode); } static int __init init_hfsplus_fs(void) diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index b52b738..b6fca54 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -5,7 +5,7 @@ * * general buffer i/o */ - +#include <linux/sched.h> #include "hpfs_fn.h" void hpfs_lock_creation(struct super_block *s) diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 9953cf9..d256559 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -5,7 +5,7 @@ * * adding & removing files & directories */ - +#include <linux/sched.h> #include "hpfs_fn.h" static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 1b95f39f..29cc34a 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/statfs.h> #include <linux/magic.h> +#include <linux/sched.h> /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */ @@ -176,11 +177,9 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - mutex_init(&ei->i_mutex); - mutex_init(&ei->i_parent_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->i_mutex); + mutex_init(&ei->i_parent_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 98959b8..aa083dd 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -556,8 +556,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } const struct file_operations hugetlbfs_file_operations = { @@ -213,8 +213,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct inode * inode = (struct inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(inode); + inode_init_once(inode); } /* diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index e99f7ff..5c3eecf 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -77,8 +77,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct iso_inode_info *ei = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 45368f8..6488af4 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -47,10 +47,8 @@ static void jffs2_i_init_once(void * foo, struct kmem_cache * cachep, unsigned l { struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - init_MUTEX(&ei->sem); - inode_init_once(&ei->vfs_inode); - } + init_MUTEX(&ei->sem); + inode_init_once(&ei->vfs_inode); } static int jffs2_sync_fs(struct super_block *sb, int wait) diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 6b3acb0..43d4f69 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -184,16 +184,14 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct metapage *mp = (struct metapage *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - mp->lid = 0; - mp->lsn = 0; - mp->flag = 0; - mp->data = NULL; - mp->clsn = 0; - mp->log = NULL; - set_bit(META_free, &mp->flag); - init_waitqueue_head(&mp->wait); - } + mp->lid = 0; + mp->lsn = 0; + mp->flag = 0; + mp->data = NULL; + mp->clsn = 0; + mp->log = NULL; + set_bit(META_free, &mp->flag); + init_waitqueue_head(&mp->wait); } static inline struct metapage *alloc_metapage(gfp_t gfp_mask) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index ea9dc3e..20e4ac1 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -752,20 +752,18 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); - INIT_LIST_HEAD(&jfs_ip->anon_inode_list); - init_rwsem(&jfs_ip->rdwrlock); - mutex_init(&jfs_ip->commit_mutex); - init_rwsem(&jfs_ip->xattr_sem); - spin_lock_init(&jfs_ip->ag_lock); - jfs_ip->active_ag = -1; + memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); + INIT_LIST_HEAD(&jfs_ip->anon_inode_list); + init_rwsem(&jfs_ip->rdwrlock); + mutex_init(&jfs_ip->commit_mutex); + init_rwsem(&jfs_ip->xattr_sem); + spin_lock_init(&jfs_ip->ag_lock); + jfs_ip->active_ag = -1; #ifdef CONFIG_JFS_POSIX_ACL - jfs_ip->i_acl = JFS_ACL_NOT_CACHED; - jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; + jfs_ip->i_acl = JFS_ACL_NOT_CACHED; + jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; #endif - inode_init_once(&jfs_ip->vfs_inode); - } + inode_init_once(&jfs_ip->vfs_inode); } static int __init init_jfs_fs(void) diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index f4d45d4..d070b18 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -153,7 +153,7 @@ nlmclnt_recovery(struct nlm_host *host) if (!host->h_reclaiming++) { nlm_get_host(host); __module_get(THIS_MODULE); - if (kernel_thread(reclaimer, host, CLONE_KERNEL) < 0) + if (kernel_thread(reclaimer, host, CLONE_FS | CLONE_FILES) < 0) module_put(THIS_MODULE); } } diff --git a/fs/lockd/host.c b/fs/lockd/host.c index ad21c07..96070bf 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -221,7 +221,7 @@ nlm_bind_host(struct nlm_host *host) host->h_nextrebind - jiffies); } } else { - unsigned long increment = nlmsvc_timeout * HZ; + unsigned long increment = nlmsvc_timeout; struct rpc_timeout timeparms = { .to_initval = increment, .to_increment = increment, diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 9702956..5316e30 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -586,10 +586,6 @@ static struct rpc_version nlm_version3 = { .procs = nlm_procedures, }; -#ifdef CONFIG_LOCKD_V4 -extern struct rpc_version nlm_version4; -#endif - static struct rpc_version * nlm_versions[] = { [1] = &nlm_version1, [3] = &nlm_version3, diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index ce1efdb..846fc1d 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -123,7 +123,8 @@ static __be32 * nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; - __s64 len, start, end; + __u64 len, start; + __s64 end; if (!(p = xdr_decode_string_inplace(p, &lock->caller, &lock->len, NLM_MAXSTRLEN)) @@ -417,7 +418,8 @@ nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) if (resp->status == nlm_lck_denied) { struct file_lock *fl = &resp->lock.fl; u32 excl; - s64 start, end, len; + __u64 start, len; + __s64 end; memset(&resp->lock, 0, sizeof(resp->lock)); locks_init_lock(fl); @@ -203,9 +203,6 @@ static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags) { struct file_lock *lock = (struct file_lock *) foo; - if (!(flags & SLAB_CTOR_CONSTRUCTOR)) - return; - locks_init_lock(lock); } diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index c4a554d..99a12f1 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c @@ -15,6 +15,7 @@ #include <linux/smp_lock.h> #include <linux/buffer_head.h> #include <linux/bitops.h> +#include <linux/sched.h> static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 2f4d43a..be40446 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -73,8 +73,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct minix_inode_info *ei = (struct minix_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index addfd31..d3152f8 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -17,6 +17,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/sched.h> #include <linux/ncp_fs.h> #include "ncplib_kernel.h" diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index c29f00a..cf06eb9 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -60,10 +60,8 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - mutex_init(&ei->open_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->open_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 8843a83..c67b4bd 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -17,6 +17,7 @@ #include <linux/highuid.h> #include <linux/smp_lock.h> #include <linux/vmalloc.h> +#include <linux/sched.h> #include <linux/ncp_fs.h> diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h index db3d791..c2bb14e 100644 --- a/fs/nfs/callback.h +++ b/fs/nfs/callback.h @@ -24,7 +24,7 @@ enum nfs4_callback_opnum { }; struct cb_compound_hdr_arg { - int taglen; + unsigned int taglen; const char *tag; unsigned int callback_ident; unsigned nops; @@ -32,7 +32,7 @@ struct cb_compound_hdr_arg { struct cb_compound_hdr_res { __be32 *status; - int taglen; + unsigned int taglen; const char *tag; __be32 *nops; }; diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 50c6821..881fa49 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -12,7 +12,7 @@ #include <linux/module.h> #include <linux/init.h> - +#include <linux/sched.h> #include <linux/time.h> #include <linux/kernel.h> #include <linux/mm.h> diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 841c99a..7f37d1b 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -226,7 +226,7 @@ restart: spin_unlock(&clp->cl_lock); } -int nfs_do_expire_all_delegations(void *ptr) +static int nfs_do_expire_all_delegations(void *ptr) { struct nfs_client *clp = ptr; struct nfs_delegation *delegation; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 3df4288..c27258b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -33,6 +33,7 @@ #include <linux/pagevec.h> #include <linux/namei.h> #include <linux/mount.h> +#include <linux/sched.h> #include "nfs4_fs.h" #include "delegation.h" @@ -607,7 +608,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) return res; } -loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) +static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { mutex_lock(&filp->f_path.dentry->d_inode->i_mutex); switch (origin) { @@ -633,7 +634,7 @@ out: * All directory operations under NFS are synchronous, so fsync() * is a dummy operation. */ -int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) +static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) { dfprintk(VFS, "NFS: fsync_dir(%s/%s) datasync %d\n", dentry->d_parent->d_name.name, dentry->d_name.name, diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 345aa5c..00eee87 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -122,19 +122,25 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_ return -EINVAL; } -static void nfs_direct_dirty_pages(struct page **pages, int npages) +static void nfs_direct_dirty_pages(struct page **pages, unsigned int pgbase, size_t count) { - int i; + unsigned int npages; + unsigned int i; + + if (count == 0) + return; + pages += (pgbase >> PAGE_SHIFT); + npages = (count + (pgbase & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { struct page *page = pages[i]; if (!PageCompound(page)) - set_page_dirty_lock(page); + set_page_dirty(page); } } -static void nfs_direct_release_pages(struct page **pages, int npages) +static void nfs_direct_release_pages(struct page **pages, unsigned int npages) { - int i; + unsigned int i; for (i = 0; i < npages; i++) page_cache_release(pages[i]); } @@ -162,7 +168,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void) return dreq; } -static void nfs_direct_req_release(struct kref *kref) +static void nfs_direct_req_free(struct kref *kref) { struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); @@ -171,6 +177,11 @@ static void nfs_direct_req_release(struct kref *kref) kmem_cache_free(nfs_direct_cachep, dreq); } +static void nfs_direct_req_release(struct nfs_direct_req *dreq) +{ + kref_put(&dreq->kref, nfs_direct_req_free); +} + /* * Collects and returns the final error value/byte-count. */ @@ -190,7 +201,6 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) result = dreq->count; out: - kref_put(&dreq->kref, nfs_direct_req_release); return (ssize_t) result; } @@ -208,7 +218,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq) } complete_all(&dreq->completion); - kref_put(&dreq->kref, nfs_direct_req_release); + nfs_direct_req_release(dreq); } /* @@ -224,17 +234,18 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata) if (nfs_readpage_result(task, data) != 0) return; - nfs_direct_dirty_pages(data->pagevec, data->npages); - nfs_direct_release_pages(data->pagevec, data->npages); - spin_lock(&dreq->lock); - - if (likely(task->tk_status >= 0)) - dreq->count += data->res.count; - else + if (unlikely(task->tk_status < 0)) { dreq->error = task->tk_status; - - spin_unlock(&dreq->lock); + spin_unlock(&dreq->lock); + } else { + dreq->count += data->res.count; + spin_unlock(&dreq->lock); + nfs_direct_dirty_pages(data->pagevec, + data->args.pgbase, + data->res.count); + } + nfs_direct_release_pages(data->pagevec, data->npages); if (put_dreq(dreq)) nfs_direct_complete(dreq); @@ -279,9 +290,12 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo result = get_user_pages(current, current->mm, user_addr, data->npages, 1, 0, data->pagevec, NULL); up_read(¤t->mm->mmap_sem); - if (unlikely(result < data->npages)) { - if (result > 0) - nfs_direct_release_pages(data->pagevec, result); + if (result < 0) { + nfs_readdata_release(data); + break; + } + if ((unsigned)result < data->npages) { + nfs_direct_release_pages(data->pagevec, result); nfs_readdata_release(data); break; } @@ -359,6 +373,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size if (!result) result = nfs_direct_wait(dreq); rpc_clnt_sigunmask(clnt, &oldset); + nfs_direct_req_release(dreq); return result; } @@ -610,9 +625,12 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l result = get_user_pages(current, current->mm, user_addr, data->npages, 0, 0, data->pagevec, NULL); up_read(¤t->mm->mmap_sem); - if (unlikely(result < data->npages)) { - if (result > 0) - nfs_direct_release_pages(data->pagevec, result); + if (result < 0) { + nfs_writedata_release(data); + break; + } + if ((unsigned)result < data->npages) { + nfs_direct_release_pages(data->pagevec, result); nfs_writedata_release(data); break; } @@ -703,6 +721,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz if (!result) result = nfs_direct_wait(dreq); rpc_clnt_sigunmask(clnt, &oldset); + nfs_direct_req_release(dreq); return result; } diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5eaee6d..9eb8eb4 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -27,6 +27,7 @@ #include <linux/slab.h> #include <linux/pagemap.h> #include <linux/smp_lock.h> +#include <linux/aio.h> #include <asm/uaccess.h> #include <asm/system.h> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2a3fd95..bd9f5a8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -15,7 +15,7 @@ #include <linux/module.h> #include <linux/init.h> - +#include <linux/sched.h> #include <linux/time.h> #include <linux/kernel.h> #include <linux/mm.h> @@ -1164,21 +1164,19 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct nfs_inode *nfsi = (struct nfs_inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&nfsi->vfs_inode); - spin_lock_init(&nfsi->req_lock); - INIT_LIST_HEAD(&nfsi->dirty); - INIT_LIST_HEAD(&nfsi->commit); - INIT_LIST_HEAD(&nfsi->open_files); - INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); - INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); - INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); - atomic_set(&nfsi->data_updates, 0); - nfsi->ndirty = 0; - nfsi->ncommit = 0; - nfsi->npages = 0; - nfs4_init_once(nfsi); - } + inode_init_once(&nfsi->vfs_inode); + spin_lock_init(&nfsi->req_lock); + INIT_LIST_HEAD(&nfsi->dirty); + INIT_LIST_HEAD(&nfsi->commit); + INIT_LIST_HEAD(&nfsi->open_files); + INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); + INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); + INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); + atomic_set(&nfsi->data_updates, 0); + nfsi->ndirty = 0; + nfsi->ncommit = 0; + nfsi->npages = 0; + nfs4_init_once(nfsi); } static int __init nfs_init_inodecache(void) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d6a30e9..648e0ac 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -790,7 +790,7 @@ out: return -EACCES; } -int nfs4_recover_expired_lease(struct nfs_server *server) +static int nfs4_recover_expired_lease(struct nfs_server *server) { struct nfs_client *clp = server->nfs_client; int ret; @@ -2748,7 +2748,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) /* This is the error handling routine for processes that are allowed * to sleep. */ -int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) +static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) { struct nfs_client *clp = server->nfs_client; int ret = errorcode; diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 5fffbdf..8ed79d5 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -104,7 +104,7 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) return cred; } -struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) +static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) { struct nfs4_state_owner *sp; diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 938f371..8003c91 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -646,10 +646,10 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg) { __be32 *p; - RESERVE_SPACE(8+sizeof(arg->stateid->data)); + RESERVE_SPACE(8+NFS4_STATEID_SIZE); WRITE32(OP_CLOSE); WRITE32(arg->seqid->sequence->counter); - WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); + WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); return 0; } @@ -793,17 +793,17 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args) WRITE64(nfs4_lock_length(args->fl)); WRITE32(args->new_lock_owner); if (args->new_lock_owner){ - RESERVE_SPACE(40); + RESERVE_SPACE(4+NFS4_STATEID_SIZE+20); WRITE32(args->open_seqid->sequence->counter); - WRITEMEM(args->open_stateid->data, sizeof(args->open_stateid->data)); + WRITEMEM(args->open_stateid->data, NFS4_STATEID_SIZE); WRITE32(args->lock_seqid->sequence->counter); WRITE64(args->lock_owner.clientid); WRITE32(4); WRITE32(args->lock_owner.id); } else { - RESERVE_SPACE(20); - WRITEMEM(args->lock_stateid->data, sizeof(args->lock_stateid->data)); + RESERVE_SPACE(NFS4_STATEID_SIZE+4); + WRITEMEM(args->lock_stateid->data, NFS4_STATEID_SIZE); WRITE32(args->lock_seqid->sequence->counter); } @@ -830,11 +830,11 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *arg { __be32 *p; - RESERVE_SPACE(44); + RESERVE_SPACE(12+NFS4_STATEID_SIZE+16); WRITE32(OP_LOCKU); WRITE32(nfs4_lock_type(args->fl, 0)); WRITE32(args->seqid->sequence->counter); - WRITEMEM(args->stateid->data, sizeof(args->stateid->data)); + WRITEMEM(args->stateid->data, NFS4_STATEID_SIZE); WRITE64(args->fl->fl_start); WRITE64(nfs4_lock_length(args->fl)); @@ -966,9 +966,9 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struc { __be32 *p; - RESERVE_SPACE(4+sizeof(stateid->data)); + RESERVE_SPACE(4+NFS4_STATEID_SIZE); WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR); - WRITEMEM(stateid->data, sizeof(stateid->data)); + WRITEMEM(stateid->data, NFS4_STATEID_SIZE); encode_string(xdr, name->len, name->name); } @@ -996,9 +996,9 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con { __be32 *p; - RESERVE_SPACE(8+sizeof(arg->stateid->data)); + RESERVE_SPACE(4+NFS4_STATEID_SIZE+4); WRITE32(OP_OPEN_CONFIRM); - WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); + WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); WRITE32(arg->seqid->sequence->counter); return 0; @@ -1008,9 +1008,9 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea { __be32 *p; - RESERVE_SPACE(8+sizeof(arg->stateid->data)); + RESERVE_SPACE(4+NFS4_STATEID_SIZE+4); WRITE32(OP_OPEN_DOWNGRADE); - WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); + WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE); WRITE32(arg->seqid->sequence->counter); encode_share_access(xdr, arg->open_flags); return 0; @@ -1045,12 +1045,12 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context nfs4_stateid stateid; __be32 *p; - RESERVE_SPACE(16); + RESERVE_SPACE(NFS4_STATEID_SIZE); if (ctx->state != NULL) { nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner); - WRITEMEM(stateid.data, sizeof(stateid.data)); + WRITEMEM(stateid.data, NFS4_STATEID_SIZE); } else - WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data)); + WRITEMEM(zero_stateid.data, NFS4_STATEID_SIZE); } static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args) @@ -1079,10 +1079,10 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg int replen; __be32 *p; - RESERVE_SPACE(32+sizeof(nfs4_verifier)); + RESERVE_SPACE(12+NFS4_VERIFIER_SIZE+20); WRITE32(OP_READDIR); WRITE64(readdir->cookie); - WRITEMEM(readdir->verifier.data, sizeof(readdir->verifier.data)); + WRITEMEM(readdir->verifier.data, NFS4_VERIFIER_SIZE); WRITE32(readdir->count >> 1); /* We're not doing readdirplus */ WRITE32(readdir->count); WRITE32(2); @@ -1190,9 +1190,9 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) { __be32 *p; - RESERVE_SPACE(4+sizeof(zero_stateid.data)); + RESERVE_SPACE(4+NFS4_STATEID_SIZE); WRITE32(OP_SETATTR); - WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data)); + WRITEMEM(zero_stateid.data, NFS4_STATEID_SIZE); RESERVE_SPACE(2*4); WRITE32(1); WRITE32(FATTR4_WORD0_ACL); @@ -1220,9 +1220,9 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs * int status; __be32 *p; - RESERVE_SPACE(4+sizeof(arg->stateid.data)); + RESERVE_SPACE(4+NFS4_STATEID_SIZE); WRITE32(OP_SETATTR); - WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); + WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE); if ((status = encode_attrs(xdr, arg->iap, server))) return status; @@ -1234,9 +1234,9 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien { __be32 *p; - RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data)); + RESERVE_SPACE(4 + NFS4_VERIFIER_SIZE); WRITE32(OP_SETCLIENTID); - WRITEMEM(setclientid->sc_verifier->data, sizeof(setclientid->sc_verifier->data)); + WRITEMEM(setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE); encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name); RESERVE_SPACE(4); @@ -1253,10 +1253,10 @@ static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_c { __be32 *p; - RESERVE_SPACE(12 + sizeof(client_state->cl_confirm.data)); + RESERVE_SPACE(12 + NFS4_VERIFIER_SIZE); WRITE32(OP_SETCLIENTID_CONFIRM); WRITE64(client_state->cl_clientid); - WRITEMEM(client_state->cl_confirm.data, sizeof(client_state->cl_confirm.data)); + WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE); return 0; } @@ -1284,10 +1284,10 @@ static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *statei { __be32 *p; - RESERVE_SPACE(20); + RESERVE_SPACE(4+NFS4_STATEID_SIZE); WRITE32(OP_DELEGRETURN); - WRITEMEM(stateid->data, sizeof(stateid->data)); + WRITEMEM(stateid->data, NFS4_STATEID_SIZE); return 0; } @@ -2494,7 +2494,7 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st int i; dprintk("%s: using first %d of %d servers returned for location %d\n", __FUNCTION__, NFS4_FS_LOCATION_MAXSERVERS, m, res->nlocations); for (i = loc->nservers; i < m; i++) { - int len; + unsigned int len; char *data; status = decode_opaque_inline(xdr, &len, &data); if (unlikely(status != 0)) @@ -2642,7 +2642,7 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t return 0; } -static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid) +static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *uid) { uint32_t len; __be32 *p; @@ -2667,7 +2667,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf return 0; } -static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid) +static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *gid) { uint32_t len; __be32 *p; @@ -2897,8 +2897,8 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res) status = decode_op_hdr(xdr, OP_CLOSE); if (status) return status; - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(NFS4_STATEID_SIZE); + COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); return 0; } @@ -3186,8 +3186,8 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) status = decode_op_hdr(xdr, OP_LOCK); if (status == 0) { - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(NFS4_STATEID_SIZE); + COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); } else if (status == -NFS4ERR_DENIED) return decode_lock_denied(xdr, NULL); return status; @@ -3209,8 +3209,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) status = decode_op_hdr(xdr, OP_LOCKU); if (status == 0) { - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(NFS4_STATEID_SIZE); + COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); } return status; } @@ -3251,8 +3251,8 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) res->delegation_type = 0; return 0; } - READ_BUF(20); - COPYMEM(res->delegation.data, sizeof(res->delegation.data)); + READ_BUF(NFS4_STATEID_SIZE+4); + COPYMEM(res->delegation.data, NFS4_STATEID_SIZE); READ32(res->do_recall); switch (delegation_type) { case NFS4_OPEN_DELEGATE_READ: @@ -3275,8 +3275,8 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) status = decode_op_hdr(xdr, OP_OPEN); if (status) return status; - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(NFS4_STATEID_SIZE); + COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); decode_change_info(xdr, &res->cinfo); @@ -3302,8 +3302,8 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); if (status) return status; - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(NFS4_STATEID_SIZE); + COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); return 0; } @@ -3315,8 +3315,8 @@ static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *re status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); if (status) return status; - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(NFS4_STATEID_SIZE); + COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); return 0; } @@ -3590,9 +3590,9 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) } READ32(nfserr); if (nfserr == NFS_OK) { - READ_BUF(8 + sizeof(clp->cl_confirm.data)); + READ_BUF(8 + NFS4_VERIFIER_SIZE); READ64(clp->cl_clientid); - COPYMEM(clp->cl_confirm.data, sizeof(clp->cl_confirm.data)); + COPYMEM(clp->cl_confirm.data, NFS4_VERIFIER_SIZE); } else if (nfserr == NFSERR_CLID_INUSE) { uint32_t len; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e12054c..c5bb51a 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -11,6 +11,7 @@ #include <linux/slab.h> #include <linux/file.h> +#include <linux/sched.h> #include <linux/sunrpc/clnt.h> #include <linux/nfs3.h> #include <linux/nfs4.h> @@ -354,6 +355,26 @@ void nfs_pageio_complete(struct nfs_pageio_descriptor *desc) nfs_pageio_doio(desc); } +/** + * nfs_pageio_cond_complete - Conditional I/O completion + * @desc: pointer to io descriptor + * @index: page index + * + * It is important to ensure that processes don't try to take locks + * on non-contiguous ranges of pages as that might deadlock. This + * function should be called before attempting to wait on a locked + * nfs_page. It will complete the I/O if the page index 'index' + * is not contiguous with the existing list of pages in 'desc'. + */ +void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index) +{ + if (!list_empty(&desc->pg_list)) { + struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev); + if (index != prev->wb_index + 1) + nfs_pageio_doio(desc); + } +} + #define NFS_SCAN_MAXENTRIES 16 /** * nfs_scan_list - Scan a list for matching requests diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 9a55807..7bd7cb9 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -79,7 +79,7 @@ void nfs_readdata_release(void *data) static int nfs_return_empty_page(struct page *page) { - memclear_highpage_flush(page, 0, PAGE_CACHE_SIZE); + zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); SetPageUptodate(page); unlock_page(page); return 0; @@ -103,10 +103,10 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) pglen = PAGE_CACHE_SIZE - base; for (;;) { if (remainder <= pglen) { - memclear_highpage_flush(*pages, base, remainder); + zero_user_page(*pages, base, remainder, KM_USER0); break; } - memclear_highpage_flush(*pages, base, pglen); + zero_user_page(*pages, base, pglen, KM_USER0); pages++; remainder -= pglen; pglen = PAGE_CACHE_SIZE; @@ -130,7 +130,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, return PTR_ERR(new); } if (len < PAGE_CACHE_SIZE) - memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); + zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0); nfs_list_add_request(new, &one_request); if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) @@ -532,7 +532,7 @@ readpage_async_filler(void *data, struct page *page) return PTR_ERR(new); } if (len < PAGE_CACHE_SIZE) - memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); + zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0); nfs_pageio_add_request(desc->pgio, new); return 0; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index de92b95..af344a1 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -58,7 +58,7 @@ struct nfs_write_data *nfs_commit_alloc(void) return p; } -void nfs_commit_rcu_free(struct rcu_head *head) +static void nfs_commit_rcu_free(struct rcu_head *head) { struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu); if (p && (p->pagevec != &p->page_array[0])) @@ -168,7 +168,7 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int if (count != nfs_page_length(page)) return; if (count != PAGE_CACHE_SIZE) - memclear_highpage_flush(page, count, PAGE_CACHE_SIZE - count); + zero_user_page(page, count, PAGE_CACHE_SIZE - count, KM_USER0); SetPageUptodate(page); } @@ -273,8 +273,6 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, * request as dirty (in which case we don't care). */ spin_unlock(req_lock); - /* Prevent deadlock! */ - nfs_pageio_complete(pgio); ret = nfs_wait_on_request(req); nfs_release_request(req); if (ret != 0) @@ -321,6 +319,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc pgio = &mypgio; } + nfs_pageio_cond_complete(pgio, page->index); + err = nfs_page_async_flush(pgio, page); if (err <= 0) goto out; @@ -329,6 +329,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc if (!offset) goto out; + nfs_pageio_cond_complete(pgio, page->index); + ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); if (ctx == NULL) { err = -EBADF; @@ -922,7 +924,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i return 0; out_bad: while (!list_empty(head)) { - struct nfs_page *req = nfs_list_entry(head->next); + req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_redirty_request(req); nfs_end_page_writeback(req->wb_page); diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 32ffea0..864090e 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -38,6 +38,7 @@ #include <linux/inet.h> #include <linux/errno.h> #include <linux/delay.h> +#include <linux/sched.h> #include <linux/sunrpc/xdr.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/clnt.h> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index c7774e3..ebd03cc 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -45,7 +45,7 @@ #include <asm/uaccess.h> #include <asm/scatterlist.h> #include <linux/crypto.h> - +#include <linux/sched.h> #define NFSDDBG_FACILITY NFSDDBG_PROC diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index d7759ce..ff55950 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -9,7 +9,7 @@ */ #include <linux/module.h> - +#include <linux/sched.h> #include <linux/time.h> #include <linux/errno.h> #include <linux/nfs.h> diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 39a1669..7ed5639 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -26,6 +26,7 @@ #include <linux/swap.h> #include <linux/uio.h> #include <linux/writeback.h> +#include <linux/sched.h> #include <asm/page.h> #include <asm/uaccess.h> diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 21d834e..4566b91 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -3085,8 +3085,7 @@ static void ntfs_big_inode_init_once(void *foo, struct kmem_cache *cachep, { ntfs_inode *ni = (ntfs_inode *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(VFS_I(ni)); + inode_init_once(VFS_I(ni)); } /* diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 8e7cafb..0023b31 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -222,7 +222,10 @@ static int ocfs2_readpage(struct file *file, struct page *page) goto out; } - down_read(&OCFS2_I(inode)->ip_alloc_sem); + if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) { + ret = AOP_TRUNCATED_PAGE; + goto out_meta_unlock; + } /* * i_size might have just been updated as we grabed the meta lock. We @@ -235,10 +238,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) * XXX sys_readahead() seems to get that wrong? */ if (start >= i_size_read(inode)) { - char *addr = kmap(page); - memset(addr, 0, PAGE_SIZE); - flush_dcache_page(page); - kunmap(page); + zero_user_page(page, 0, PAGE_SIZE, KM_USER0); SetPageUptodate(page); ret = 0; goto out_alloc; @@ -258,6 +258,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) ocfs2_data_unlock(inode, 0); out_alloc: up_read(&OCFS2_I(inode)->ip_alloc_sem); +out_meta_unlock: ocfs2_meta_unlock(inode, 0); out: if (unlock) diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 5671cf9..fd8cb1b 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -262,12 +262,10 @@ static void dlmfs_init_once(void *foo, struct dlmfs_inode_private *ip = (struct dlmfs_inode_private *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - ip->ip_dlm = NULL; - ip->ip_parent = NULL; + ip->ip_dlm = NULL; + ip->ip_parent = NULL; - inode_init_once(&ip->ip_vfs_inode); - } + inode_init_once(&ip->ip_vfs_inode); } static struct inode *dlmfs_alloc_inode(struct super_block *sb) diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 9395b4f..ac6c964 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -326,6 +326,7 @@ static int ocfs2_truncate_file(struct inode *inode, (unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)new_i_size); + unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1); truncate_inode_pages(inode->i_mapping, new_i_size); fe = (struct ocfs2_dinode *) di_bh->b_data; @@ -1418,36 +1419,6 @@ out: return total ? total : ret; } -static int ocfs2_check_iovec(const struct iovec *iov, size_t *counted, - unsigned long *nr_segs) -{ - size_t ocount; /* original count */ - unsigned long seg; - - ocount = 0; - for (seg = 0; seg < *nr_segs; seg++) { - const struct iovec *iv = &iov[seg]; - - /* - * If any segment has a negative length, or the cumulative - * length ever wraps negative then return -EINVAL. - */ - ocount += iv->iov_len; - if (unlikely((ssize_t)(ocount|iv->iov_len) < 0)) - return -EINVAL; - if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len)) - continue; - if (seg == 0) - return -EFAULT; - *nr_segs = seg; - ocount -= iv->iov_len; /* This segment is no good */ - break; - } - - *counted = ocount; - return 0; -} - static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, @@ -1470,7 +1441,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, if (iocb->ki_left == 0) return 0; - ret = ocfs2_check_iovec(iov, &ocount, &nr_segs); + ret = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); if (ret) return ret; diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 4dedd97..545f789 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -471,9 +471,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, mutex_lock(&local_alloc_inode->i_mutex); - ac->ac_inode = local_alloc_inode; - ac->ac_which = OCFS2_AC_USE_LOCAL; - if (osb->local_alloc_state != OCFS2_LA_ENABLED) { status = -ENOSPC; goto bail; @@ -511,10 +508,14 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, } } + ac->ac_inode = local_alloc_inode; + ac->ac_which = OCFS2_AC_USE_LOCAL; get_bh(osb->local_alloc_bh); ac->ac_bh = osb->local_alloc_bh; status = 0; bail: + if (status < 0 && local_alloc_inode) + iput(local_alloc_inode); mlog_exit(status); return status; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 7c5e3f5..86b559c 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -937,31 +937,29 @@ static void ocfs2_inode_init_once(void *data, { struct ocfs2_inode_info *oi = data; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - oi->ip_flags = 0; - oi->ip_open_count = 0; - spin_lock_init(&oi->ip_lock); - ocfs2_extent_map_init(&oi->vfs_inode); - INIT_LIST_HEAD(&oi->ip_io_markers); - oi->ip_created_trans = 0; - oi->ip_last_trans = 0; - oi->ip_dir_start_lookup = 0; + oi->ip_flags = 0; + oi->ip_open_count = 0; + spin_lock_init(&oi->ip_lock); + ocfs2_extent_map_init(&oi->vfs_inode); + INIT_LIST_HEAD(&oi->ip_io_markers); + oi->ip_created_trans = 0; + oi->ip_last_trans = 0; + oi->ip_dir_start_lookup = 0; - init_rwsem(&oi->ip_alloc_sem); - mutex_init(&oi->ip_io_mutex); + init_rwsem(&oi->ip_alloc_sem); + mutex_init(&oi->ip_io_mutex); - oi->ip_blkno = 0ULL; - oi->ip_clusters = 0; + oi->ip_blkno = 0ULL; + oi->ip_clusters = 0; - ocfs2_lock_res_init_once(&oi->ip_rw_lockres); - ocfs2_lock_res_init_once(&oi->ip_meta_lockres); - ocfs2_lock_res_init_once(&oi->ip_data_lockres); - ocfs2_lock_res_init_once(&oi->ip_open_lockres); + ocfs2_lock_res_init_once(&oi->ip_rw_lockres); + ocfs2_lock_res_init_once(&oi->ip_meta_lockres); + ocfs2_lock_res_init_once(&oi->ip_data_lockres); + ocfs2_lock_res_init_once(&oi->ip_open_lockres); - ocfs2_metadata_cache_init(&oi->vfs_inode); + ocfs2_metadata_cache_init(&oi->vfs_inode); - inode_init_once(&oi->vfs_inode); - } + inode_init_once(&oi->vfs_inode); } static int ocfs2_initialize_mem_caches(void) diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 731a90e..e623973 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -419,8 +419,7 @@ static void op_inode_init_once(void *data, struct kmem_cache * cachep, unsigned { struct op_inode_info *oi = (struct op_inode_info *) data; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&oi->vfs_inode); + inode_init_once(&oi->vfs_inode); } static int __init init_openprom_fs(void) diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig index 7638a1c..a99acd8 100644 --- a/fs/partitions/Kconfig +++ b/fs/partitions/Kconfig @@ -166,8 +166,12 @@ config LDM_PARTITION depends on PARTITION_ADVANCED ---help--- Say Y here if you would like to use hard disks under Linux which - were partitioned using Windows 2000's or XP's Logical Disk Manager. - They are also known as "Dynamic Disks". + were partitioned using Windows 2000's/XP's or Vista's Logical Disk + Manager. They are also known as "Dynamic Disks". + + Note this driver only supports Dynamic Disks with a protective MBR + label, i.e. DOS partition table. It does not support GPT labelled + Dynamic Disks yet as can be created with Vista. Windows 2000 introduced the concept of Dynamic Disks to get around the limitations of the PC's partitioning scheme. The Logical Disk @@ -175,8 +179,8 @@ config LDM_PARTITION mirrored, striped or RAID volumes, all without the need for rebooting. - Normal partitions are now called Basic Disks under Windows 2000 and - XP. + Normal partitions are now called Basic Disks under Windows 2000, XP, + and Vista. For a fuller description read <file:Documentation/ldm.txt>. diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 1a60926..99873a2 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c @@ -2,10 +2,10 @@ * ldm - Support for Windows Logical Disk Manager (Dynamic Disks) * * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2007 Anton Altaparmakov * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> * - * Documentation is available at http://linux-ntfs.sf.net/ldm + * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/ * * 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 @@ -62,7 +62,6 @@ static void _ldm_printk (const char *level, const char *function, printk ("%s%s(): %s\n", level, function, buf); } - /** * ldm_parse_hexbyte - Convert a ASCII hex number to a byte * @src: Pointer to at least 2 characters to convert. @@ -118,7 +117,6 @@ static bool ldm_parse_guid (const u8 *src, u8 *dest) return true; } - /** * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure * @data: Raw database PRIVHEAD structure loaded from the device @@ -130,46 +128,48 @@ static bool ldm_parse_guid (const u8 *src, u8 *dest) * Return: 'true' @ph contains the PRIVHEAD data * 'false' @ph contents are undefined */ -static bool ldm_parse_privhead (const u8 *data, struct privhead *ph) +static bool ldm_parse_privhead(const u8 *data, struct privhead *ph) { - BUG_ON (!data || !ph); + bool is_vista = false; - if (MAGIC_PRIVHEAD != BE64 (data)) { - ldm_error ("Cannot find PRIVHEAD structure. LDM database is" + BUG_ON(!data || !ph); + if (MAGIC_PRIVHEAD != BE64(data)) { + ldm_error("Cannot find PRIVHEAD structure. LDM database is" " corrupt. Aborting."); return false; } - - ph->ver_major = BE16 (data + 0x000C); - ph->ver_minor = BE16 (data + 0x000E); - ph->logical_disk_start = BE64 (data + 0x011B); - ph->logical_disk_size = BE64 (data + 0x0123); - ph->config_start = BE64 (data + 0x012B); - ph->config_size = BE64 (data + 0x0133); - - if ((ph->ver_major != 2) || (ph->ver_minor != 11)) { - ldm_error ("Expected PRIVHEAD version %d.%d, got %d.%d." - " Aborting.", 2, 11, ph->ver_major, ph->ver_minor); + ph->ver_major = BE16(data + 0x000C); + ph->ver_minor = BE16(data + 0x000E); + ph->logical_disk_start = BE64(data + 0x011B); + ph->logical_disk_size = BE64(data + 0x0123); + ph->config_start = BE64(data + 0x012B); + ph->config_size = BE64(data + 0x0133); + /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */ + if (ph->ver_major == 2 && ph->ver_minor == 12) + is_vista = true; + if (!is_vista && (ph->ver_major != 2 || ph->ver_minor != 11)) { + ldm_error("Expected PRIVHEAD version 2.11 or 2.12, got %d.%d." + " Aborting.", ph->ver_major, ph->ver_minor); return false; } + ldm_debug("PRIVHEAD version %d.%d (Windows %s).", ph->ver_major, + ph->ver_minor, is_vista ? "Vista" : "2000/XP"); if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */ - /* Warn the user and continue, carefully */ - ldm_info ("Database is normally %u bytes, it claims to " + /* Warn the user and continue, carefully. */ + ldm_info("Database is normally %u bytes, it claims to " "be %llu bytes.", LDM_DB_SIZE, - (unsigned long long)ph->config_size ); + (unsigned long long)ph->config_size); } - if ((ph->logical_disk_size == 0) || - (ph->logical_disk_start + ph->logical_disk_size > ph->config_start)) { - ldm_error ("PRIVHEAD disk size doesn't match real disk size"); + if ((ph->logical_disk_size == 0) || (ph->logical_disk_start + + ph->logical_disk_size > ph->config_start)) { + ldm_error("PRIVHEAD disk size doesn't match real disk size"); return false; } - - if (!ldm_parse_guid (data + 0x0030, ph->disk_id)) { - ldm_error ("PRIVHEAD contains an invalid GUID."); + if (!ldm_parse_guid(data + 0x0030, ph->disk_id)) { + ldm_error("PRIVHEAD contains an invalid GUID."); return false; } - - ldm_debug ("Parsed PRIVHEAD successfully."); + ldm_debug("Parsed PRIVHEAD successfully."); return true; } @@ -409,7 +409,7 @@ out: * Return: 'true' @toc1 contains validated TOCBLOCK info * 'false' @toc1 contents are undefined */ -static bool ldm_validate_tocblocks (struct block_device *bdev, +static bool ldm_validate_tocblocks(struct block_device *bdev, unsigned long base, struct ldmdb *ldb) { static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4}; @@ -417,54 +417,57 @@ static bool ldm_validate_tocblocks (struct block_device *bdev, struct privhead *ph; Sector sect; u8 *data; + int i, nr_tbs; bool result = false; - int i; - BUG_ON (!bdev || !ldb); - - ph = &ldb->ph; + BUG_ON(!bdev || !ldb); + ph = &ldb->ph; tb[0] = &ldb->toc; - tb[1] = kmalloc (sizeof (*tb[1]), GFP_KERNEL); - tb[2] = kmalloc (sizeof (*tb[2]), GFP_KERNEL); - tb[3] = kmalloc (sizeof (*tb[3]), GFP_KERNEL); - if (!tb[1] || !tb[2] || !tb[3]) { - ldm_crit ("Out of memory."); - goto out; + tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL); + if (!tb[1]) { + ldm_crit("Out of memory."); + goto err; } - - for (i = 0; i < 4; i++) /* Read and parse all four toc's. */ - { - data = read_dev_sector (bdev, base + off[i], §); + tb[2] = (struct tocblock*)((u8*)tb[1] + sizeof(*tb[1])); + tb[3] = (struct tocblock*)((u8*)tb[2] + sizeof(*tb[2])); + /* + * Try to read and parse all four TOCBLOCKs. + * + * Windows Vista LDM v2.12 does not always have all four TOCBLOCKs so + * skip any that fail as long as we get at least one valid TOCBLOCK. + */ + for (nr_tbs = i = 0; i < 4; i++) { + data = read_dev_sector(bdev, base + off[i], §); if (!data) { - ldm_crit ("Disk read failed."); - goto out; + ldm_error("Disk read failed for TOCBLOCK %d.", i); + continue; } - result = ldm_parse_tocblock (data, tb[i]); - put_dev_sector (sect); - if (!result) - goto out; /* Already logged */ + if (ldm_parse_tocblock(data, tb[nr_tbs])) + nr_tbs++; + put_dev_sector(sect); } - - /* Range check the toc against a privhead. */ + if (!nr_tbs) { + ldm_crit("Failed to find a valid TOCBLOCK."); + goto err; + } + /* Range check the TOCBLOCK against a privhead. */ if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) || - ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > ph->config_size)) { - ldm_crit ("The bitmaps are out of range. Giving up."); - goto out; + ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > + ph->config_size)) { + ldm_crit("The bitmaps are out of range. Giving up."); + goto err; } - - if (!ldm_compare_tocblocks (tb[0], tb[1]) || /* Compare all tocs. */ - !ldm_compare_tocblocks (tb[0], tb[2]) || - !ldm_compare_tocblocks (tb[0], tb[3])) { - ldm_crit ("The TOCBLOCKs don't match."); - goto out; + /* Compare all loaded TOCBLOCKs. */ + for (i = 1; i < nr_tbs; i++) { + if (!ldm_compare_tocblocks(tb[0], tb[i])) { + ldm_crit("TOCBLOCKs 0 and %d do not match.", i); + goto err; + } } - - ldm_debug ("Validated TOCBLOCKs successfully."); + ldm_debug("Validated %d TOCBLOCKs successfully.", nr_tbs); result = true; -out: - kfree (tb[1]); - kfree (tb[2]); - kfree (tb[3]); +err: + kfree(tb[1]); return result; } @@ -566,7 +569,7 @@ static bool ldm_validate_partition_table (struct block_device *bdev) p = (struct partition*)(data + 0x01BE); for (i = 0; i < 4; i++, p++) - if (SYS_IND (p) == WIN2K_DYNAMIC_PARTITION) { + if (SYS_IND (p) == LDM_PARTITION) { result = true; break; } @@ -975,44 +978,68 @@ static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb) * Return: 'true' @vb contains a Partition VBLK * 'false' @vb contents are not defined */ -static bool ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb) +static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb) { int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len; struct vblk_part *part; - BUG_ON (!buffer || !vb); - - r_objid = ldm_relative (buffer, buflen, 0x18, 0); - r_name = ldm_relative (buffer, buflen, 0x18, r_objid); - r_size = ldm_relative (buffer, buflen, 0x34, r_name); - r_parent = ldm_relative (buffer, buflen, 0x34, r_size); - r_diskid = ldm_relative (buffer, buflen, 0x34, r_parent); - + BUG_ON(!buffer || !vb); + r_objid = ldm_relative(buffer, buflen, 0x18, 0); + if (r_objid < 0) { + ldm_error("r_objid %d < 0", r_objid); + return false; + } + r_name = ldm_relative(buffer, buflen, 0x18, r_objid); + if (r_name < 0) { + ldm_error("r_name %d < 0", r_name); + return false; + } + r_size = ldm_relative(buffer, buflen, 0x34, r_name); + if (r_size < 0) { + ldm_error("r_size %d < 0", r_size); + return false; + } + r_parent = ldm_relative(buffer, buflen, 0x34, r_size); + if (r_parent < 0) { + ldm_error("r_parent %d < 0", r_parent); + return false; + } + r_diskid = ldm_relative(buffer, buflen, 0x34, r_parent); + if (r_diskid < 0) { + ldm_error("r_diskid %d < 0", r_diskid); + return false; + } if (buffer[0x12] & VBLK_FLAG_PART_INDEX) { - r_index = ldm_relative (buffer, buflen, 0x34, r_diskid); + r_index = ldm_relative(buffer, buflen, 0x34, r_diskid); + if (r_index < 0) { + ldm_error("r_index %d < 0", r_index); + return false; + } len = r_index; } else { r_index = 0; len = r_diskid; } - if (len < 0) + if (len < 0) { + ldm_error("len %d < 0", len); return false; - + } len += VBLK_SIZE_PRT3; - if (len != BE32 (buffer + 0x14)) + if (len > BE32(buffer + 0x14)) { + ldm_error("len %d > BE32(buffer + 0x14) %d", len, + BE32(buffer + 0x14)); return false; - + } part = &vb->vblk.part; - part->start = BE64 (buffer + 0x24 + r_name); - part->volume_offset = BE64 (buffer + 0x2C + r_name); - part->size = ldm_get_vnum (buffer + 0x34 + r_name); - part->parent_id = ldm_get_vnum (buffer + 0x34 + r_size); - part->disk_id = ldm_get_vnum (buffer + 0x34 + r_parent); + part->start = BE64(buffer + 0x24 + r_name); + part->volume_offset = BE64(buffer + 0x2C + r_name); + part->size = ldm_get_vnum(buffer + 0x34 + r_name); + part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size); + part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent); if (vb->flags & VBLK_FLAG_PART_INDEX) part->partnum = buffer[0x35 + r_diskid]; else part->partnum = 0; - return true; } @@ -1475,4 +1502,3 @@ out: kfree (ldb); return result; } - diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h index 6e8d795..d2e6a30 100644 --- a/fs/partitions/ldm.h +++ b/fs/partitions/ldm.h @@ -2,10 +2,10 @@ * ldm - Part of the Linux-NTFS project. * * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> - * Copyright (C) 2001 Anton Altaparmakov <aia21@cantab.net> + * Copyright (c) 2001-2007 Anton Altaparmakov * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> * - * Documentation is available at http://linux-ntfs.sf.net/ldm + * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/ * * 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 @@ -93,7 +93,7 @@ struct parsed_partitions; #define OFF_VMDB 17 /* List of partitions. */ -#define WIN2K_DYNAMIC_PARTITION 0x42 /* Formerly SFS (Landis). */ +#define LDM_PARTITION 0x42 /* Formerly SFS (Landis). */ #define TOC_BITMAP1 "config" /* Names of the two defined */ #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b817190..d5ce65c 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -109,8 +109,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct proc_inode *ei = (struct proc_inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } int __init proc_init_inodecache(void) diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 75fc849..8d256eb 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -536,8 +536,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, { struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) @@ -157,7 +157,6 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t static void quota_sync_sb(struct super_block *sb, int type) { int cnt; - struct inode *discard[MAXQUOTAS]; sb->s_qcop->quota_sync(sb, type); /* This is not very clever (and fast) but currently I don't know about @@ -167,29 +166,21 @@ static void quota_sync_sb(struct super_block *sb, int type) sb->s_op->sync_fs(sb, 1); sync_blockdev(sb->s_bdev); - /* Now when everything is written we can discard the pagecache so - * that userspace sees the changes. We need i_mutex and so we could - * not do it inside dqonoff_mutex. Moreover we need to be carefull - * about races with quotaoff() (that is the reason why we have own - * reference to inode). */ + /* + * Now when everything is written we can discard the pagecache so + * that userspace sees the changes. + */ mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - discard[cnt] = NULL; if (type != -1 && cnt != type) continue; if (!sb_has_quota_enabled(sb, cnt)) continue; - discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]); + mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA); + truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0); + mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex); } mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); - for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (discard[cnt]) { - mutex_lock(&discard[cnt]->i_mutex); - truncate_inode_pages(&discard[cnt]->i_data, 0); - mutex_unlock(&discard[cnt]->i_mutex); - iput(discard[cnt]); - } - } } void sync_dquots(struct super_block *sb, int type) diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 3b481d5..9345a46 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -179,7 +179,7 @@ static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size) return ret; } - ret = vmtruncate(inode, size); + ret = vmtruncate(inode, newsize); return ret; } diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 4ace5d7..d40d22b 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -32,7 +32,7 @@ #include <linux/string.h> #include <linux/backing-dev.h> #include <linux/ramfs.h> - +#include <linux/sched.h> #include <asm/uaccess.h> #include "internal.h" diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 9c23fee..ffbfc2c 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -10,7 +10,7 @@ #include <linux/buffer_head.h> #include <asm/uaccess.h> -extern struct reiserfs_key MIN_KEY; +extern const struct reiserfs_key MIN_KEY; static int reiserfs_readdir(struct file *, void *, filldir_t); static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index c776214..b4ac911 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -511,14 +511,12 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_prealloc_list); - inode_init_once(&ei->vfs_inode); + INIT_LIST_HEAD(&ei->i_prealloc_list); + inode_init_once(&ei->vfs_inode); #ifdef CONFIG_REISERFS_FS_POSIX_ACL - ei->i_acl_access = NULL; - ei->i_acl_default = NULL; + ei->i_acl_access = NULL; + ei->i_acl_default = NULL; #endif - } } static int init_inodecache(void) diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 8042851..2284e03 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -566,12 +566,11 @@ static void romfs_destroy_inode(struct inode *inode) kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); } -static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { - struct romfs_inode_info *ei = (struct romfs_inode_info *) foo; + struct romfs_inode_info *ei = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/signalfd.c b/fs/signalfd.c index 7cfeab4..f1da892 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -11,6 +11,8 @@ * Now using anonymous inode source. * Thanks to Oleg Nesterov for useful code review and suggestions. * More comments and suggestions from Arnd Bergmann. + * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br> + * Retrieve multiple signals with one read() call */ #include <linux/file.h> @@ -206,6 +208,59 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, return err ? -EFAULT: sizeof(*uinfo); } +static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info, + int nonblock) +{ + ssize_t ret; + struct signalfd_lockctx lk; + DECLARE_WAITQUEUE(wait, current); + + if (!signalfd_lock(ctx, &lk)) + return 0; + + ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); + switch (ret) { + case 0: + if (!nonblock) + break; + ret = -EAGAIN; + default: + signalfd_unlock(&lk); + return ret; + } + + add_wait_queue(&ctx->wqh, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + ret = dequeue_signal(lk.tsk, &ctx->sigmask, info); + signalfd_unlock(&lk); + if (ret != 0) + break; + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + schedule(); + ret = signalfd_lock(ctx, &lk); + if (unlikely(!ret)) { + /* + * Let the caller read zero byte, ala socket + * recv() when the peer disconnect. This test + * must be done before doing a dequeue_signal(), + * because if the sighand has been orphaned, + * the dequeue_signal() call is going to crash + * because ->sighand will be long gone. + */ + break; + } + } + + remove_wait_queue(&ctx->wqh, &wait); + __set_current_state(TASK_RUNNING); + + return ret; +} + /* * Returns either the size of a "struct signalfd_siginfo", or zero if the * sighand we are attached to, has been orphaned. The "count" parameter @@ -215,55 +270,30 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct signalfd_ctx *ctx = file->private_data; - ssize_t res = 0; - int locked, signo; + struct signalfd_siginfo __user *siginfo; + int nonblock = file->f_flags & O_NONBLOCK; + ssize_t ret, total = 0; siginfo_t info; - struct signalfd_lockctx lk; - DECLARE_WAITQUEUE(wait, current); - if (count < sizeof(struct signalfd_siginfo)) + count /= sizeof(struct signalfd_siginfo); + if (!count) return -EINVAL; - locked = signalfd_lock(ctx, &lk); - if (!locked) - return 0; - res = -EAGAIN; - signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info); - if (signo == 0 && !(file->f_flags & O_NONBLOCK)) { - add_wait_queue(&ctx->wqh, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info); - if (signo != 0) - break; - if (signal_pending(current)) { - res = -ERESTARTSYS; - break; - } - signalfd_unlock(&lk); - schedule(); - locked = signalfd_lock(ctx, &lk); - if (unlikely(!locked)) { - /* - * Let the caller read zero byte, ala socket - * recv() when the peer disconnect. This test - * must be done before doing a dequeue_signal(), - * because if the sighand has been orphaned, - * the dequeue_signal() call is going to crash. - */ - res = 0; - break; - } - } - remove_wait_queue(&ctx->wqh, &wait); - __set_current_state(TASK_RUNNING); - } - if (likely(locked)) - signalfd_unlock(&lk); - if (likely(signo)) - res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf, - &info); - return res; + siginfo = (struct signalfd_siginfo __user *) buf; + + do { + ret = signalfd_dequeue(ctx, &info, nonblock); + if (unlikely(ret <= 0)) + break; + ret = signalfd_copyinfo(siginfo, &info); + if (ret < 0) + break; + siginfo++; + total += ret; + nonblock = 1; + } while (--count); + + return total ? total : ret; } static const struct file_operations signalfd_fops = { diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index 50136b1..48da4fa 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -13,6 +13,7 @@ #include <linux/smp_lock.h> #include <linux/ctype.h> #include <linux/net.h> +#include <linux/sched.h> #include <linux/smb_fs.h> #include <linux/smb_mount.h> diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index f161797..aea3f8a 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -17,6 +17,7 @@ #include <linux/pagemap.h> #include <linux/smp_lock.h> #include <linux/net.h> +#include <linux/aio.h> #include <asm/uaccess.h> #include <asm/system.h> diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 424a3dd..6724a6c 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -25,6 +25,7 @@ #include <linux/net.h> #include <linux/vfs.h> #include <linux/highuid.h> +#include <linux/sched.h> #include <linux/smb_fs.h> #include <linux/smbno.h> #include <linux/smb_mount.h> @@ -70,8 +71,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct smb_inode_info *ei = (struct smb_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c index c288fbe..3f54a0f 100644 --- a/fs/smbfs/request.c +++ b/fs/smbfs/request.c @@ -11,6 +11,7 @@ #include <linux/fs.h> #include <linux/slab.h> #include <linux/net.h> +#include <linux/sched.h> #include <linux/smb_fs.h> #include <linux/smbno.h> diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 4de5c6b..bdd30e7 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -13,6 +13,7 @@ #include <linux/backing-dev.h> #include <linux/capability.h> #include <linux/errno.h> +#include <linux/sched.h> #include <asm/semaphore.h> #include "sysfs.h" diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 3152d74..5644116 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -322,8 +322,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags) { struct sysv_inode_info *si = (struct sysv_inode_info *)p; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&si->vfs_inode); + inode_init_once(&si->vfs_inode); } const struct super_operations sysv_sops = { diff --git a/fs/timerfd.c b/fs/timerfd.c index e329e37..af9eca5 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -24,7 +24,6 @@ struct timerfd_ctx { struct hrtimer tmr; ktime_t tintv; - spinlock_t lock; wait_queue_head_t wqh; int expired; }; @@ -39,10 +38,10 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr); unsigned long flags; - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&ctx->wqh.lock, flags); ctx->expired = 1; wake_up_locked(&ctx->wqh); - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return HRTIMER_NORESTART; } @@ -83,10 +82,10 @@ static unsigned int timerfd_poll(struct file *file, poll_table *wait) poll_wait(file, &ctx->wqh, wait); - spin_lock_irqsave(&ctx->lock, flags); + spin_lock_irqsave(&ctx->wqh.lock, flags); if (ctx->expired) events |= POLLIN; - spin_unlock_irqrestore(&ctx->lock, flags); + spin_unlock_irqrestore(&ctx->wqh.lock, flags); return events; } @@ -101,7 +100,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, if (count < sizeof(ticks)) return -EINVAL; - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); res = -EAGAIN; if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) { __add_wait_queue(&ctx->wqh, &wait); @@ -115,9 +114,9 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, res = -ERESTARTSYS; break; } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); schedule(); - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); } __remove_wait_queue(&ctx->wqh, &wait); __set_current_state(TASK_RUNNING); @@ -139,7 +138,7 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count, } else ticks = 1; } - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); if (ticks) res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks); return res; @@ -176,7 +175,6 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags, return -ENOMEM; init_waitqueue_head(&ctx->wqh); - spin_lock_init(&ctx->lock); timerfd_setup(ctx, clockid, flags, &ktmr); @@ -202,10 +200,10 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags, * it to the new values. */ for (;;) { - spin_lock_irq(&ctx->lock); + spin_lock_irq(&ctx->wqh.lock); if (hrtimer_try_to_cancel(&ctx->tmr) >= 0) break; - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); cpu_relax(); } /* @@ -213,7 +211,7 @@ asmlinkage long sys_timerfd(int ufd, int clockid, int flags, */ timerfd_setup(ctx, clockid, flags, &ktmr); - spin_unlock_irq(&ctx->lock); + spin_unlock_irq(&ctx->wqh.lock); fput(file); } diff --git a/fs/udf/file.c b/fs/udf/file.c index 40d5047..51b5764 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -36,6 +36,7 @@ #include <linux/smp_lock.h> #include <linux/pagemap.h> #include <linux/buffer_head.h> +#include <linux/aio.h> #include "udf_i.h" #include "udf_sb.h" diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 91df492..51fe307 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -30,6 +30,7 @@ #include <linux/quotaops.h> #include <linux/smp_lock.h> #include <linux/buffer_head.h> +#include <linux/sched.h> static inline int udf_match(int len1, const char *name1, int len2, const char *name2) { diff --git a/fs/udf/super.c b/fs/udf/super.c index 9b8644a..3a743d8 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -134,10 +134,8 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct udf_inode_info *ei = (struct udf_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - ei->i_ext.i_data = NULL; - inode_init_once(&ei->vfs_inode); - } + ei->i_ext.i_data = NULL; + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index be7c48c..22ff6ed 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1237,8 +1237,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 4475588..7361861 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -701,7 +701,7 @@ xfs_is_delayed_page( else if (buffer_delay(bh)) acceptable = (type == IOMAP_DELAY); else if (buffer_dirty(bh) && buffer_mapped(bh)) - acceptable = (type == 0); + acceptable = (type == IOMAP_NEW); else break; } while ((bh = bh->b_this_page) != head); @@ -810,7 +810,7 @@ xfs_convert_page( page_dirty--; count++; } else { - type = 0; + type = IOMAP_NEW; if (buffer_mapped(bh) && all_bh && startio) { lock_buffer(bh); xfs_add_to_ioend(inode, bh, offset, @@ -968,8 +968,8 @@ xfs_page_state_convert( bh = head = page_buffers(page); offset = page_offset(page); - flags = -1; - type = IOMAP_READ; + flags = BMAPI_READ; + type = IOMAP_NEW; /* TODO: cleanup count and page_dirty */ @@ -999,14 +999,14 @@ xfs_page_state_convert( * * Third case, an unmapped buffer was found, and we are * in a path where we need to write the whole page out. - */ + */ if (buffer_unwritten(bh) || buffer_delay(bh) || ((buffer_uptodate(bh) || PageUptodate(page)) && !buffer_mapped(bh) && (unmapped || startio))) { - /* + /* * Make sure we don't use a read-only iomap */ - if (flags == BMAPI_READ) + if (flags == BMAPI_READ) iomap_valid = 0; if (buffer_unwritten(bh)) { @@ -1055,7 +1055,7 @@ xfs_page_state_convert( * That means it must already have extents allocated * underneath it. Map the extent by reading it. */ - if (!iomap_valid || type != IOMAP_READ) { + if (!iomap_valid || flags != BMAPI_READ) { flags = BMAPI_READ; size = xfs_probe_cluster(inode, page, bh, head, 1); @@ -1066,7 +1066,15 @@ xfs_page_state_convert( iomap_valid = xfs_iomap_valid(&iomap, offset); } - type = IOMAP_READ; + /* + * We set the type to IOMAP_NEW in case we are doing a + * small write at EOF that is extending the file but + * without needing an allocation. We need to update the + * file size on I/O completion in this case so it is + * the same case as having just allocated a new extent + * that we are writing into for the first time. + */ + type = IOMAP_NEW; if (!test_and_set_bit(BH_Lock, &bh->b_state)) { ASSERT(buffer_mapped(bh)); if (iomap_valid) diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 14e2cbe..bf9a9d5 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -360,8 +360,7 @@ xfs_fs_inode_init_once( kmem_zone_t *zonep, unsigned long flags) { - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); + inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); } STATIC int |