diff options
Diffstat (limited to 'fs')
65 files changed, 1033 insertions, 240 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 2e43d46f65d..cf12c403b8c 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1005,7 +1005,8 @@ config TMPFS_POSIX_ACL config HUGETLBFS bool "HugeTLB file system support" - depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN + depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \ + (S390 && 64BIT) || BROKEN help hugetlbfs is a filesystem backing for HugeTLB pages, based on ramfs. For architectures that support it, say Y here and read diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 936f2af39c4..831157502d5 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -75,7 +75,7 @@ extern unsigned int adfs_map_free(struct super_block *sb); /* Misc */ void __adfs_error(struct super_block *sb, const char *function, const char *fmt, ...); -#define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt) +#define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt) /* super.c */ diff --git a/fs/affs/file.c b/fs/affs/file.c index e87ede608f7..1a4f092f24e 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -539,7 +539,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize) tmp = min(bsize - boff, newsize - size); BUG_ON(boff + tmp > bsize || tmp > bsize); memset(AFFS_DATA(bh) + boff, 0, tmp); - AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp); + be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp); affs_fix_checksum(sb, bh); mark_buffer_dirty_inode(bh, inode); size += tmp; @@ -680,7 +680,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, tmp = min(bsize - boff, to - from); BUG_ON(boff + tmp > bsize || tmp > bsize); memcpy(AFFS_DATA(bh) + boff, data + from, tmp); - AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp); + be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp); affs_fix_checksum(sb, bh); mark_buffer_dirty_inode(bh, inode); written += tmp; diff --git a/fs/afs/dir.c b/fs/afs/dir.c index b58af8f18bc..dfda03d4397 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -140,7 +140,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page) if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) { printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n", - __FUNCTION__, dir->i_ino, qty, + __func__, dir->i_ino, qty, ntohs(dbuf->blocks[0].pagehdr.npages)); goto error; } @@ -159,7 +159,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page) for (tmp = 0; tmp < qty; tmp++) { if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) { printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n", - __FUNCTION__, dir->i_ino, tmp, qty, + __func__, dir->i_ino, tmp, qty, ntohs(dbuf->blocks[tmp].pagehdr.magic)); goto error; } diff --git a/fs/afs/internal.h b/fs/afs/internal.h index eec41c76de7..7102824ba84 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -757,8 +757,8 @@ void _dbprintk(const char *fmt, ...) { } -#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__) -#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__) +#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) +#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) @@ -791,8 +791,8 @@ do { \ } while (0) #else -#define _enter(FMT,...) _dbprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__) -#define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__) +#define _enter(FMT,...) _dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) +#define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) #define _debug(FMT,...) _dbprintk(" "FMT ,##__VA_ARGS__) #endif @@ -1078,9 +1078,7 @@ static void timeout_func(unsigned long data) static inline void init_timeout(struct aio_timeout *to) { - init_timer(&to->timer); - to->timer.data = (unsigned long)to; - to->timer.function = timeout_func; + setup_timer_on_stack(&to->timer, timeout_func, (unsigned long) to); to->timed_out = 0; to->p = current; } @@ -1213,6 +1211,7 @@ retry: if (timeout) clear_timeout(&to); out: + destroy_timer_on_stack(&to.timer); return i ? i : ret; } diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 2d4ae40718d..c3d352d7fa9 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -35,7 +35,7 @@ /* #define DEBUG */ #ifdef DEBUG -#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __FUNCTION__ , ##args); } while(0) +#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __func__ , ##args); } while(0) #else #define DPRINTK(fmt,args...) do {} while(0) #endif diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 71faf4d2390..70f5d3a8eed 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h @@ -42,7 +42,7 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) #define printf(format, args...) \ - printk(KERN_ERR "BFS-fs: %s(): " format, __FUNCTION__, ## args) + printk(KERN_ERR "BFS-fs: %s(): " format, __func__, ## args) /* inode.c */ extern struct inode *bfs_iget(struct super_block *sb, unsigned long ino); diff --git a/fs/buffer.c b/fs/buffer.c index 189efa4efc6..a073f3f4f01 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1101,7 +1101,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) printk(KERN_ERR "%s: requested out-of-range block %llu for " "device %s\n", - __FUNCTION__, (unsigned long long)block, + __func__, (unsigned long long)block, bdevname(bdev, b)); return -EIO; } diff --git a/fs/compat.c b/fs/compat.c index 2ce4456aad3..139dc93c092 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1634,7 +1634,7 @@ sticky: return ret; } -#ifdef TIF_RESTORE_SIGMASK +#ifdef HAVE_SET_RESTORE_SIGMASK asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, @@ -1720,7 +1720,7 @@ sticky: if (sigmask) { memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); } } else if (sigmask) sigprocmask(SIG_SETMASK, &sigsaved, NULL); @@ -1791,7 +1791,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds, if (sigmask) { memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); } ret = -ERESTARTNOHAND; } else if (sigmask) @@ -1825,7 +1825,7 @@ sticky: return ret; } -#endif /* TIF_RESTORE_SIGMASK */ +#endif /* HAVE_SET_RESTORE_SIGMASK */ #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) /* Stuff for NFS server syscalls... */ @@ -2080,7 +2080,7 @@ long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2) #ifdef CONFIG_EPOLL -#ifdef TIF_RESTORE_SIGMASK +#ifdef HAVE_SET_RESTORE_SIGMASK asmlinkage long compat_sys_epoll_pwait(int epfd, struct compat_epoll_event __user *events, int maxevents, int timeout, @@ -2117,14 +2117,14 @@ asmlinkage long compat_sys_epoll_pwait(int epfd, if (err == -EINTR) { memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); } else sigprocmask(SIG_SETMASK, &sigsaved, NULL); } return err; } -#endif /* TIF_RESTORE_SIGMASK */ +#endif /* HAVE_SET_RESTORE_SIGMASK */ #endif /* CONFIG_EPOLL */ diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index c6e72aebd16..97dba0d9234 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -1046,14 +1046,14 @@ static int vt_check(struct file *file) struct inode *inode = file->f_path.dentry->d_inode; struct vc_data *vc; - if (file->f_op->ioctl != tty_ioctl) + if (file->f_op->unlocked_ioctl != tty_ioctl) return -EINVAL; tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_ioctl")) return -EINVAL; - if (tty->driver->ioctl != vt_ioctl) + if (tty->ops->ioctl != vt_ioctl) return -EINVAL; vc = (struct vc_data *)tty->driver_data; diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 397cb503a18..2b6cb23dd14 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -115,7 +115,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp goto out; } pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", - __FUNCTION__, count, *ppos, buffer->page); + __func__, count, *ppos, buffer->page); retval = simple_read_from_buffer(buf, count, ppos, buffer->page, buffer->count); out: diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index 4c1ebff778e..b9a1d810346 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -47,7 +47,7 @@ static const struct address_space_operations configfs_aops = { static struct backing_dev_info configfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; static const struct inode_operations configfs_inode_operations ={ diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index de3b31d0a37..8421cea7d8c 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -92,7 +92,7 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) root = d_alloc_root(inode); if (!root) { - pr_debug("%s: could not get root dentry!\n",__FUNCTION__); + pr_debug("%s: could not get root dentry!\n",__func__); iput(inode); return -ENOMEM; } diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 78929ea84ff..2a731ef5f30 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -210,13 +210,13 @@ static int configfs_get_target_path(struct config_item * item, struct config_ite if (size > PATH_MAX) return -ENAMETOOLONG; - pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size); + pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size); for (s = path; depth--; s += 3) strcpy(s,"../"); fill_item_path(target, path, size); - pr_debug("%s: path = '%s'\n", __FUNCTION__, path); + pr_debug("%s: path = '%s'\n", __func__, path); return 0; } diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index f120e120787..285b64a8b06 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -17,6 +17,8 @@ #include <linux/namei.h> #include <linux/mount.h> #include <linux/tty.h> +#include <linux/mutex.h> +#include <linux/idr.h> #include <linux/devpts_fs.h> #include <linux/parser.h> #include <linux/fsnotify.h> @@ -26,6 +28,10 @@ #define DEVPTS_DEFAULT_MODE 0600 +extern int pty_limit; /* Config limit on Unix98 ptys */ +static DEFINE_IDR(allocated_ptys); +static DEFINE_MUTEX(allocated_ptys_lock); + static struct vfsmount *devpts_mnt; static struct dentry *devpts_root; @@ -171,9 +177,44 @@ static struct dentry *get_node(int num) return lookup_one_len(s, root, sprintf(s, "%d", num)); } +int devpts_new_index(void) +{ + int index; + int idr_ret; + +retry: + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + return -ENOMEM; + } + + mutex_lock(&allocated_ptys_lock); + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + mutex_unlock(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + goto retry; + return -EIO; + } + + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + mutex_unlock(&allocated_ptys_lock); + return -EIO; + } + mutex_unlock(&allocated_ptys_lock); + return index; +} + +void devpts_kill_index(int idx) +{ + mutex_lock(&allocated_ptys_lock); + idr_remove(&allocated_ptys, idx); + mutex_unlock(&allocated_ptys_lock); +} + int devpts_pty_new(struct tty_struct *tty) { - int number = tty->index; + int number = tty->index; /* tty layer puts index from devpts_new_index() in here */ struct tty_driver *driver = tty->driver; dev_t device = MKDEV(driver->major, driver->minor_start+number); struct dentry *dentry; diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index b64e55e0515..499e16759e9 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -200,7 +200,7 @@ int __init dlm_lockspace_init(void) dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj); if (!dlm_kset) { - printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__); + printk(KERN_WARNING "%s: can not create kset\n", __func__); return -ENOMEM; } return 0; diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 0d237182d72..221086fef17 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1241,7 +1241,7 @@ error_return: return error; } -#ifdef TIF_RESTORE_SIGMASK +#ifdef HAVE_SET_RESTORE_SIGMASK /* * Implement the event wait interface for the eventpoll file. It is the kernel @@ -1279,7 +1279,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, if (error == -EINTR) { memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); } else sigprocmask(SIG_SETMASK, &sigsaved, NULL); } @@ -1287,7 +1287,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, return error; } -#endif /* #ifdef TIF_RESTORE_SIGMASK */ +#endif /* HAVE_SET_RESTORE_SIGMASK */ static int __init eventpoll_init(void) { @@ -1309,4 +1309,3 @@ static int __init eventpoll_init(void) return 0; } fs_initcall(eventpoll_init); - diff --git a/fs/exec.c b/fs/exec.c index a13883903ee..9f9f931ef94 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -766,9 +766,7 @@ static int de_thread(struct task_struct *tsk) /* * Kill all other threads in the thread group. - * We must hold tasklist_lock to call zap_other_threads. */ - read_lock(&tasklist_lock); spin_lock_irq(lock); if (signal_group_exit(sig)) { /* @@ -776,21 +774,10 @@ static int de_thread(struct task_struct *tsk) * return so that the signal is processed. */ spin_unlock_irq(lock); - read_unlock(&tasklist_lock); return -EAGAIN; } - - /* - * child_reaper ignores SIGKILL, change it now. - * Reparenting needs write_lock on tasklist_lock, - * so it is safe to do it under read_lock. - */ - if (unlikely(tsk->group_leader == task_child_reaper(tsk))) - task_active_pid_ns(tsk)->child_reaper = tsk; - sig->group_exit_task = tsk; zap_other_threads(tsk); - read_unlock(&tasklist_lock); /* Account for the thread group leader hanging around: */ count = thread_group_leader(tsk) ? 1 : 2; @@ -811,7 +798,7 @@ static int de_thread(struct task_struct *tsk) if (!thread_group_leader(tsk)) { leader = tsk->group_leader; - sig->notify_count = -1; + sig->notify_count = -1; /* for exit_notify() */ for (;;) { write_lock_irq(&tasklist_lock); if (likely(leader->exit_state)) @@ -821,6 +808,8 @@ static int de_thread(struct task_struct *tsk) schedule(); } + if (unlikely(task_child_reaper(tsk) == leader)) + task_active_pid_ns(tsk)->child_reaper = tsk; /* * The only record we have of the real-time age of a * process, regardless of execs it's done, is start_time. diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 109ab5e44ec..cc91227d3bb 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -150,12 +150,12 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir) if (IS_ERR(ppd)) { err = PTR_ERR(ppd); dprintk("%s: get_parent of %ld failed, err %d\n", - __FUNCTION__, pd->d_inode->i_ino, err); + __func__, pd->d_inode->i_ino, err); dput(pd); break; } - dprintk("%s: find name of %lu in %lu\n", __FUNCTION__, + dprintk("%s: find name of %lu in %lu\n", __func__, pd->d_inode->i_ino, ppd->d_inode->i_ino); err = exportfs_get_name(mnt, ppd, nbuf, pd); if (err) { @@ -168,14 +168,14 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir) continue; break; } - dprintk("%s: found name: %s\n", __FUNCTION__, nbuf); + dprintk("%s: found name: %s\n", __func__, nbuf); mutex_lock(&ppd->d_inode->i_mutex); npd = lookup_one_len(nbuf, ppd, strlen(nbuf)); mutex_unlock(&ppd->d_inode->i_mutex); if (IS_ERR(npd)) { err = PTR_ERR(npd); dprintk("%s: lookup failed: %d\n", - __FUNCTION__, err); + __func__, err); dput(ppd); dput(pd); break; @@ -188,7 +188,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir) if (npd == pd) noprogress = 0; else - printk("%s: npd != pd\n", __FUNCTION__); + printk("%s: npd != pd\n", __func__); dput(npd); dput(ppd); if (IS_ROOT(pd)) { diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 639b3b4f86d..fda25479af2 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -242,7 +242,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) /* prevent the infinite loop of cluster chain */ if (*fclus > limit) { fat_fs_panic(sb, "%s: detected the cluster chain loop" - " (i_pos %lld)", __FUNCTION__, + " (i_pos %lld)", __func__, MSDOS_I(inode)->i_pos); nr = -EIO; goto out; @@ -253,7 +253,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) goto out; else if (nr == FAT_ENT_FREE) { fat_fs_panic(sb, "%s: invalid cluster chain" - " (i_pos %lld)", __FUNCTION__, + " (i_pos %lld)", __func__, MSDOS_I(inode)->i_pos); nr = -EIO; goto out; @@ -286,7 +286,7 @@ static int fat_bmap_cluster(struct inode *inode, int cluster) return ret; else if (ret == FAT_ENT_EOF) { fat_fs_panic(sb, "%s: request beyond EOF (i_pos %lld)", - __FUNCTION__, MSDOS_I(inode)->i_pos); + __func__, MSDOS_I(inode)->i_pos); return -EIO; } return dclus; diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index 13ab763cc51..302e95c4af7 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -546,7 +546,7 @@ int fat_free_clusters(struct inode *inode, int cluster) goto error; } else if (cluster == FAT_ENT_FREE) { fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF", - __FUNCTION__); + __func__); err = -EIO; goto error; } diff --git a/fs/fat/file.c b/fs/fat/file.c index d604bb13242..27cc1164ec3 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -208,7 +208,7 @@ static int fat_free(struct inode *inode, int skip) } else if (ret == FAT_ENT_FREE) { fat_fs_panic(sb, "%s: invalid cluster chain (i_pos %lld)", - __FUNCTION__, MSDOS_I(inode)->i_pos); + __func__, MSDOS_I(inode)->i_pos); ret = -EIO; } else if (ret > 0) { err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait); diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 105d4a271e0..4f3cab32141 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -117,7 +117,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc) parent = fuse_control_sb->s_root; inc_nlink(parent->d_inode); - sprintf(name, "%llu", (unsigned long long) fc->id); + sprintf(name, "%u", fc->dev); parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2, &simple_dir_inode_operations, &simple_dir_operations); diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index af639807524..87250b6a868 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -47,6 +47,14 @@ struct fuse_req *fuse_request_alloc(void) return req; } +struct fuse_req *fuse_request_alloc_nofs(void) +{ + struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS); + if (req) + fuse_request_init(req); + return req; +} + void fuse_request_free(struct fuse_req *req) { kmem_cache_free(fuse_req_cachep, req); @@ -291,6 +299,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) static void wait_answer_interruptible(struct fuse_conn *fc, struct fuse_req *req) + __releases(fc->lock) __acquires(fc->lock) { if (signal_pending(current)) return; @@ -307,8 +316,8 @@ static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req) kill_fasync(&fc->fasync, SIGIO, POLL_IN); } -/* Called with fc->lock held. Releases, and then reacquires it. */ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) + __releases(fc->lock) __acquires(fc->lock) { if (!fc->no_interrupt) { /* Any signal may interrupt this */ @@ -430,6 +439,17 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req) } /* + * Called under fc->lock + * + * fc->connected must have been checked previously + */ +void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req) +{ + req->isreply = 1; + request_send_nowait_locked(fc, req); +} + +/* * Lock the request. Up to the next unlock_request() there mustn't be * anything that could cause a page-fault. If the request was already * aborted bail out. @@ -968,6 +988,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head) * locked). */ static void end_io_requests(struct fuse_conn *fc) + __releases(fc->lock) __acquires(fc->lock) { while (!list_empty(&fc->io)) { struct fuse_req *req = diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c4807b3fc8a..2060bf06b90 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -132,7 +132,7 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, req->out.args[0].value = outarg; } -static u64 fuse_get_attr_version(struct fuse_conn *fc) +u64 fuse_get_attr_version(struct fuse_conn *fc) { u64 curr_version; @@ -1107,6 +1107,50 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) } /* + * Prevent concurrent writepages on inode + * + * This is done by adding a negative bias to the inode write counter + * and waiting for all pending writes to finish. + */ +void fuse_set_nowrite(struct inode *inode) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + + BUG_ON(!mutex_is_locked(&inode->i_mutex)); + + spin_lock(&fc->lock); + BUG_ON(fi->writectr < 0); + fi->writectr += FUSE_NOWRITE; + spin_unlock(&fc->lock); + wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); +} + +/* + * Allow writepages on inode + * + * Remove the bias from the writecounter and send any queued + * writepages. + */ +static void __fuse_release_nowrite(struct inode *inode) +{ + struct fuse_inode *fi = get_fuse_inode(inode); + + BUG_ON(fi->writectr != FUSE_NOWRITE); + fi->writectr = 0; + fuse_flush_writepages(inode); +} + +void fuse_release_nowrite(struct inode *inode) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + + spin_lock(&fc->lock); + __fuse_release_nowrite(inode); + spin_unlock(&fc->lock); +} + +/* * Set attributes, and at the same time refresh them. * * Truncation is slightly complicated, because the 'truncate' request @@ -1122,6 +1166,8 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, struct fuse_req *req; struct fuse_setattr_in inarg; struct fuse_attr_out outarg; + bool is_truncate = false; + loff_t oldsize; int err; if (!fuse_allow_task(fc, current)) @@ -1145,12 +1191,16 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, send_sig(SIGXFSZ, current, 0); return -EFBIG; } + is_truncate = true; } req = fuse_get_req(fc); if (IS_ERR(req)) return PTR_ERR(req); + if (is_truncate) + fuse_set_nowrite(inode); + memset(&inarg, 0, sizeof(inarg)); memset(&outarg, 0, sizeof(outarg)); iattr_to_fattr(attr, &inarg); @@ -1181,16 +1231,44 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, if (err) { if (err == -EINTR) fuse_invalidate_attr(inode); - return err; + goto error; } if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { make_bad_inode(inode); - return -EIO; + err = -EIO; + goto error; + } + + spin_lock(&fc->lock); + fuse_change_attributes_common(inode, &outarg.attr, + attr_timeout(&outarg)); + oldsize = inode->i_size; + i_size_write(inode, outarg.attr.size); + + if (is_truncate) { + /* NOTE: this may release/reacquire fc->lock */ + __fuse_release_nowrite(inode); + } + spin_unlock(&fc->lock); + + /* + * Only call invalidate_inode_pages2() after removing + * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. + */ + if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { + if (outarg.attr.size < oldsize) + fuse_truncate(inode->i_mapping, outarg.attr.size); + invalidate_inode_pages2(inode->i_mapping); } - fuse_change_attributes(inode, &outarg.attr, attr_timeout(&outarg), 0); return 0; + +error: + if (is_truncate) + fuse_release_nowrite(inode); + + return err; } static int fuse_setattr(struct dentry *entry, struct iattr *attr) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 676b0bc8a86..9ced35b0068 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -210,6 +210,49 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) return (u64) v0 + ((u64) v1 << 32); } +/* + * Check if page is under writeback + * + * This is currently done by walking the list of writepage requests + * for the inode, which can be pretty inefficient. + */ +static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_req *req; + bool found = false; + + spin_lock(&fc->lock); + list_for_each_entry(req, &fi->writepages, writepages_entry) { + pgoff_t curr_index; + + BUG_ON(req->inode != inode); + curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT; + if (curr_index == index) { + found = true; + break; + } + } + spin_unlock(&fc->lock); + + return found; +} + +/* + * Wait for page writeback to be completed. + * + * Since fuse doesn't rely on the VM writeback tracking, this has to + * use some other means. + */ +static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index) +{ + struct fuse_inode *fi = get_fuse_inode(inode); + + wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index)); + return 0; +} + static int fuse_flush(struct file *file, fl_owner_t id) { struct inode *inode = file->f_path.dentry->d_inode; @@ -245,6 +288,21 @@ static int fuse_flush(struct file *file, fl_owner_t id) return err; } +/* + * Wait for all pending writepages on the inode to finish. + * + * This is currently done by blocking further writes with FUSE_NOWRITE + * and waiting for all sent writes to complete. + * + * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage + * could conflict with truncation. + */ +static void fuse_sync_writes(struct inode *inode) +{ + fuse_set_nowrite(inode); + fuse_release_nowrite(inode); +} + int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, int isdir) { @@ -261,6 +319,17 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) return 0; + /* + * Start writeback against all dirty pages of the inode, then + * wait for all outstanding writes, before sending the FSYNC + * request. + */ + err = write_inode_now(inode, 0); + if (err) + return err; + + fuse_sync_writes(inode); + req = fuse_get_req(fc); if (IS_ERR(req)) return PTR_ERR(req); @@ -294,7 +363,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) void fuse_read_fill(struct fuse_req *req, struct file *file, struct inode *inode, loff_t pos, size_t count, int opcode) { - struct fuse_read_in *inarg = &req->misc.read_in; + struct fuse_read_in *inarg = &req->misc.read.in; struct fuse_file *ff = file->private_data; inarg->fh = ff->fh; @@ -320,7 +389,7 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, fuse_read_fill(req, file, inode, pos, count, FUSE_READ); if (owner != NULL) { - struct fuse_read_in *inarg = &req->misc.read_in; + struct fuse_read_in *inarg = &req->misc.read.in; inarg->read_flags |= FUSE_READ_LOCKOWNER; inarg->lock_owner = fuse_lock_owner_id(fc, owner); @@ -329,31 +398,66 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, return req->out.args[0].size; } +static void fuse_read_update_size(struct inode *inode, loff_t size, + u64 attr_ver) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fc->lock); + if (attr_ver == fi->attr_version && size < inode->i_size) { + fi->attr_version = ++fc->attr_version; + i_size_write(inode, size); + } + spin_unlock(&fc->lock); +} + static int fuse_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; + size_t num_read; + loff_t pos = page_offset(page); + size_t count = PAGE_CACHE_SIZE; + u64 attr_ver; int err; err = -EIO; if (is_bad_inode(inode)) goto out; + /* + * Page writeback can extend beyond the liftime of the + * page-cache page, so make sure we read a properly synced + * page. + */ + fuse_wait_on_page_writeback(inode, page->index); + req = fuse_get_req(fc); err = PTR_ERR(req); if (IS_ERR(req)) goto out; + attr_ver = fuse_get_attr_version(fc); + req->out.page_zeroing = 1; req->num_pages = 1; req->pages[0] = page; - fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE, - NULL); + num_read = fuse_send_read(req, file, inode, pos, count, NULL); err = req->out.h.error; fuse_put_request(fc, req); - if (!err) + + if (!err) { + /* + * Short read means EOF. If file size is larger, truncate it + */ + if (num_read < count) + fuse_read_update_size(inode, pos + num_read, attr_ver); + SetPageUptodate(page); + } + fuse_invalidate_attr(inode); /* atime changed */ out: unlock_page(page); @@ -363,8 +467,19 @@ static int fuse_readpage(struct file *file, struct page *page) static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) { int i; + size_t count = req->misc.read.in.size; + size_t num_read = req->out.args[0].size; + struct inode *inode = req->pages[0]->mapping->host; + + /* + * Short read means EOF. If file size is larger, truncate it + */ + if (!req->out.h.error && num_read < count) { + loff_t pos = page_offset(req->pages[0]) + num_read; + fuse_read_update_size(inode, pos, req->misc.read.attr_ver); + } - fuse_invalidate_attr(req->pages[0]->mapping->host); /* atime changed */ + fuse_invalidate_attr(inode); /* atime changed */ for (i = 0; i < req->num_pages; i++) { struct page *page = req->pages[i]; @@ -387,6 +502,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, size_t count = req->num_pages << PAGE_CACHE_SHIFT; req->out.page_zeroing = 1; fuse_read_fill(req, file, inode, pos, count, FUSE_READ); + req->misc.read.attr_ver = fuse_get_attr_version(fc); if (fc->async_read) { struct fuse_file *ff = file->private_data; req->ff = fuse_file_get(ff); @@ -411,6 +527,8 @@ static int fuse_readpages_fill(void *_data, struct page *page) struct inode *inode = data->inode; struct fuse_conn *fc = get_fuse_conn(inode); + fuse_wait_on_page_writeback(inode, page->index); + if (req->num_pages && (req->num_pages == FUSE_MAX_PAGES_PER_REQ || (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || @@ -477,11 +595,10 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, } static void fuse_write_fill(struct fuse_req *req, struct file *file, - struct inode *inode, loff_t pos, size_t count, - int writepage) + struct fuse_file *ff, struct inode *inode, + loff_t pos, size_t count, int writepage) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; struct fuse_write_in *inarg = &req->misc.write.in; struct fuse_write_out *outarg = &req->misc.write.out; @@ -490,7 +607,7 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file, inarg->offset = pos; inarg->size = count; inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; - inarg->flags = file->f_flags; + inarg->flags = file ? file->f_flags : 0; req->in.h.opcode = FUSE_WRITE; req->in.h.nodeid = get_node_id(inode); req->in.argpages = 1; @@ -511,7 +628,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, fl_owner_t owner) { struct fuse_conn *fc = get_fuse_conn(inode); - fuse_write_fill(req, file, inode, pos, count, 0); + fuse_write_fill(req, file, file->private_data, inode, pos, count, 0); if (owner != NULL) { struct fuse_write_in *inarg = &req->misc.write.in; inarg->write_flags |= FUSE_WRITE_LOCKOWNER; @@ -533,19 +650,36 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping, return 0; } +static void fuse_write_update_size(struct inode *inode, loff_t pos) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fc->lock); + fi->attr_version = ++fc->attr_version; + if (pos > inode->i_size) + i_size_write(inode, pos); + spin_unlock(&fc->lock); +} + static int fuse_buffered_write(struct file *file, struct inode *inode, loff_t pos, unsigned count, struct page *page) { int err; size_t nres; struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_inode *fi = get_fuse_inode(inode); unsigned offset = pos & (PAGE_CACHE_SIZE - 1); struct fuse_req *req; if (is_bad_inode(inode)) return -EIO; + /* + * Make sure writepages on the same page are not mixed up with + * plain writes. + */ + fuse_wait_on_page_writeback(inode, page->index); + req = fuse_get_req(fc); if (IS_ERR(req)) return PTR_ERR(req); @@ -560,12 +694,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, err = -EIO; if (!err) { pos += nres; - spin_lock(&fc->lock); - fi->attr_version = ++fc->attr_version; - if (pos > inode->i_size) - i_size_write(inode, pos); - spin_unlock(&fc->lock); - + fuse_write_update_size(inode, pos); if (count == PAGE_CACHE_SIZE) SetPageUptodate(page); } @@ -588,6 +717,198 @@ static int fuse_write_end(struct file *file, struct address_space *mapping, return res; } +static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, + size_t count) +{ + size_t res; + unsigned offset; + unsigned i; + + for (i = 0; i < req->num_pages; i++) + fuse_wait_on_page_writeback(inode, req->pages[i]->index); + + res = fuse_send_write(req, file, inode, pos, count, NULL); + + offset = req->page_offset; + count = res; + for (i = 0; i < req->num_pages; i++) { + struct page *page = req->pages[i]; + + if (!req->out.h.error && !offset && count >= PAGE_CACHE_SIZE) + SetPageUptodate(page); + + if (count > PAGE_CACHE_SIZE - offset) + count -= PAGE_CACHE_SIZE - offset; + else + count = 0; + offset = 0; + + unlock_page(page); + page_cache_release(page); + } + + return res; +} + +static ssize_t fuse_fill_write_pages(struct fuse_req *req, + struct address_space *mapping, + struct iov_iter *ii, loff_t pos) +{ + struct fuse_conn *fc = get_fuse_conn(mapping->host); + unsigned offset = pos & (PAGE_CACHE_SIZE - 1); + size_t count = 0; + int err; + + req->page_offset = offset; + + do { + size_t tmp; + struct page *page; + pgoff_t index = pos >> PAGE_CACHE_SHIFT; + size_t bytes = min_t(size_t, PAGE_CACHE_SIZE - offset, + iov_iter_count(ii)); + + bytes = min_t(size_t, bytes, fc->max_write - count); + + again: + err = -EFAULT; + if (iov_iter_fault_in_readable(ii, bytes)) + break; + + err = -ENOMEM; + page = __grab_cache_page(mapping, index); + if (!page) + break; + + pagefault_disable(); + tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes); + pagefault_enable(); + flush_dcache_page(page); + + if (!tmp) { + unlock_page(page); + page_cache_release(page); + bytes = min(bytes, iov_iter_single_seg_count(ii)); + goto again; + } + + err = 0; + req->pages[req->num_pages] = page; + req->num_pages++; + + iov_iter_advance(ii, tmp); + count += tmp; + pos += tmp; + offset += tmp; + if (offset == PAGE_CACHE_SIZE) + offset = 0; + + } while (iov_iter_count(ii) && count < fc->max_write && + req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0); + + return count > 0 ? count : err; +} + +static ssize_t fuse_perform_write(struct file *file, + struct address_space *mapping, + struct iov_iter *ii, loff_t pos) +{ + struct inode *inode = mapping->host; + struct fuse_conn *fc = get_fuse_conn(inode); + int err = 0; + ssize_t res = 0; + + if (is_bad_inode(inode)) + return -EIO; + + do { + struct fuse_req *req; + ssize_t count; + + req = fuse_get_req(fc); + if (IS_ERR(req)) { + err = PTR_ERR(req); + break; + } + + count = fuse_fill_write_pages(req, mapping, ii, pos); + if (count <= 0) { + err = count; + } else { + size_t num_written; + + num_written = fuse_send_write_pages(req, file, inode, + pos, count); + err = req->out.h.error; + if (!err) { + res += num_written; + pos += num_written; + + /* break out of the loop on short write */ + if (num_written != count) + err = -EIO; + } + } + fuse_put_request(fc, req); + } while (!err && iov_iter_count(ii)); + + if (res > 0) + fuse_write_update_size(inode, pos); + + fuse_invalidate_attr(inode); + + return res > 0 ? res : err; +} + +static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + size_t count = 0; + ssize_t written = 0; + struct inode *inode = mapping->host; + ssize_t err; + struct iov_iter i; + + WARN_ON(iocb->ki_pos != pos); + + err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ); + if (err) + return err; + + mutex_lock(&inode->i_mutex); + vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + + /* We can write back this queue in page reclaim */ + current->backing_dev_info = mapping->backing_dev_info; + + err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); + if (err) + goto out; + + if (count == 0) + goto out; + + err = remove_suid(file->f_path.dentry); + if (err) + goto out; + + file_update_time(file); + + iov_iter_init(&i, iov, nr_segs, count, 0); + written = fuse_perform_write(file, mapping, &i, pos); + if (written >= 0) + iocb->ki_pos = pos + written; + +out: + current->backing_dev_info = NULL; + mutex_unlock(&inode->i_mutex); + + return written ? written : err; +} + static void fuse_release_user_pages(struct fuse_req *req, int write) { unsigned i; @@ -645,14 +966,15 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, while (count) { size_t nres; - size_t nbytes = min(count, nmax); - int err = fuse_get_user_pages(req, buf, nbytes, !write); + size_t nbytes_limit = min(count, nmax); + size_t nbytes; + int err = fuse_get_user_pages(req, buf, nbytes_limit, !write); if (err) { res = err; break; } nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; - nbytes = min(count, nbytes); + nbytes = min(nbytes_limit, nbytes); if (write) nres = fuse_send_write(req, file, inode, pos, nbytes, current->files); @@ -683,12 +1005,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, } fuse_put_request(fc, req); if (res > 0) { - if (write) { - spin_lock(&fc->lock); - if (pos > inode->i_size) - i_size_write(inode, pos); - spin_unlock(&fc->lock); - } + if (write) + fuse_write_update_size(inode, pos); *ppos = pos; } fuse_invalidate_attr(inode); @@ -716,21 +1034,225 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, return res; } -static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) +static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) { - if ((vma->vm_flags & VM_SHARED)) { - if ((vma->vm_flags & VM_WRITE)) - return -ENODEV; - else - vma->vm_flags &= ~VM_MAYWRITE; + __free_page(req->pages[0]); + fuse_file_put(req->ff); + fuse_put_request(fc, req); +} + +static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) +{ + struct inode *inode = req->inode; + struct fuse_inode *fi = get_fuse_inode(inode); + struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info; + + list_del(&req->writepages_entry); + dec_bdi_stat(bdi, BDI_WRITEBACK); + dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP); + bdi_writeout_inc(bdi); + wake_up(&fi->page_waitq); +} + +/* Called under fc->lock, may release and reacquire it */ +static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req) +{ + struct fuse_inode *fi = get_fuse_inode(req->inode); + loff_t size = i_size_read(req->inode); + struct fuse_write_in *inarg = &req->misc.write.in; + + if (!fc->connected) + goto out_free; + + if (inarg->offset + PAGE_CACHE_SIZE <= size) { + inarg->size = PAGE_CACHE_SIZE; + } else if (inarg->offset < size) { + inarg->size = size & (PAGE_CACHE_SIZE - 1); + } else { + /* Got truncated off completely */ + goto out_free; + } + + req->in.args[1].size = inarg->size; + fi->writectr++; + request_send_background_locked(fc, req); + return; + + out_free: + fuse_writepage_finish(fc, req); + spin_unlock(&fc->lock); + fuse_writepage_free(fc, req); + spin_lock(&fc->lock); +} + +/* + * If fi->writectr is positive (no truncate or fsync going on) send + * all queued writepage requests. + * + * Called with fc->lock + */ +void fuse_flush_writepages(struct inode *inode) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_req *req; + + while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) { + req = list_entry(fi->queued_writes.next, struct fuse_req, list); + list_del_init(&req->list); + fuse_send_writepage(fc, req); + } +} + +static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req) +{ + struct inode *inode = req->inode; + struct fuse_inode *fi = get_fuse_inode(inode); + + mapping_set_error(inode->i_mapping, req->out.h.error); + spin_lock(&fc->lock); + fi->writectr--; + fuse_writepage_finish(fc, req); + spin_unlock(&fc->lock); + fuse_writepage_free(fc, req); +} + +static int fuse_writepage_locked(struct page *page) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_req *req; + struct fuse_file *ff; + struct page *tmp_page; + + set_page_writeback(page); + + req = fuse_request_alloc_nofs(); + if (!req) + goto err; + + tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); + if (!tmp_page) + goto err_free; + + spin_lock(&fc->lock); + BUG_ON(list_empty(&fi->write_files)); + ff = list_entry(fi->write_files.next, struct fuse_file, write_entry); + req->ff = fuse_file_get(ff); + spin_unlock(&fc->lock); + + fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1); + + copy_highpage(tmp_page, page); + req->num_pages = 1; + req->pages[0] = tmp_page; + req->page_offset = 0; + req->end = fuse_writepage_end; + req->inode = inode; + + inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK); + inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP); + end_page_writeback(page); + + spin_lock(&fc->lock); + list_add(&req->writepages_entry, &fi->writepages); + list_add_tail(&req->list, &fi->queued_writes); + fuse_flush_writepages(inode); + spin_unlock(&fc->lock); + + return 0; + +err_free: + fuse_request_free(req); +err: + end_page_writeback(page); + return -ENOMEM; +} + +static int fuse_writepage(struct page *page, struct writeback_control *wbc) +{ + int err; + + err = fuse_writepage_locked(page); + unlock_page(page); + + return err; +} + +static int fuse_launder_page(struct page *page) +{ + int err = 0; + if (clear_page_dirty_for_io(page)) { + struct inode *inode = page->mapping->host; + err = fuse_writepage_locked(page); + if (!err) + fuse_wait_on_page_writeback(inode, page->index); } - return generic_file_mmap(file, vma); + return err; } -static int fuse_set_page_dirty(struct page *page) +/* + * Write back dirty pages now, because there may not be any suitable + * open files later + */ +static void fuse_vma_close(struct vm_area_struct *vma) { - printk("fuse_set_page_dirty: should not happen\n"); - dump_stack(); + filemap_write_and_wait(vma->vm_file->f_mapping); +} + +/* + * Wait for writeback against this page to complete before allowing it + * to be marked dirty again, and hence written back again, possibly + * before the previous writepage completed. + * + * Block here, instead of in ->writepage(), so that the userspace fs + * can only block processes actually operating on the filesystem. + * + * Otherwise unprivileged userspace fs would be able to block + * unrelated: + * + * - page migration + * - sync(2) + * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER + */ +static int fuse_page_mkwrite(struct vm_area_struct *vma, struct page *page) +{ + /* + * Don't use page->mapping as it may become NULL from a + * concurrent truncate. + */ + struct inode *inode = vma->vm_file->f_mapping->host; + + fuse_wait_on_page_writeback(inode, page->index); + return 0; +} + +static struct vm_operations_struct fuse_file_vm_ops = { + .close = fuse_vma_close, + .fault = filemap_fault, + .page_mkwrite = fuse_page_mkwrite, +}; + +static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) { + struct inode *inode = file->f_dentry->d_inode; + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_file *ff = file->private_data; + /* + * file may be written through mmap, so chain it onto the + * inodes's write_file list + */ + spin_lock(&fc->lock); + if (list_empty(&ff->write_entry)) + list_add(&ff->write_entry, &fi->write_files); + spin_unlock(&fc->lock); + } + file_accessed(file); + vma->vm_ops = &fuse_file_vm_ops; return 0; } @@ -909,12 +1431,37 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) return err ? 0 : outarg.block; } +static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) +{ + loff_t retval; + struct inode *inode = file->f_path.dentry->d_inode; + + mutex_lock(&inode->i_mutex); + switch (origin) { + case SEEK_END: + offset += i_size_read(inode); + break; + case SEEK_CUR: + offset += file->f_pos; + } + retval = -EINVAL; + if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) { + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_version = 0; + } + retval = offset; + } + mutex_unlock(&inode->i_mutex); + return retval; +} + static const struct file_operations fuse_file_operations = { - .llseek = generic_file_llseek, + .llseek = fuse_file_llseek, .read = do_sync_read, .aio_read = fuse_file_aio_read, .write = do_sync_write, - .aio_write = generic_file_aio_write, + .aio_write = fuse_file_aio_write, .mmap = fuse_file_mmap, .open = fuse_open, .flush = fuse_flush, @@ -926,7 +1473,7 @@ static const struct file_operations fuse_file_operations = { }; static const struct file_operations fuse_direct_io_file_operations = { - .llseek = generic_file_llseek, + .llseek = fuse_file_llseek, .read = fuse_direct_read, .write = fuse_direct_write, .open = fuse_open, @@ -940,10 +1487,12 @@ static const struct file_operations fuse_direct_io_file_operations = { static const struct address_space_operations fuse_file_aops = { .readpage = fuse_readpage, + .writepage = fuse_writepage, + .launder_page = fuse_launder_page, .write_begin = fuse_write_begin, .write_end = fuse_write_end, .readpages = fuse_readpages, - .set_page_dirty = fuse_set_page_dirty, + .set_page_dirty = __set_page_dirty_nobuffers, .bmap = fuse_bmap, }; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 67aaf6ee38e..dadffa21a20 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -15,6 +15,7 @@ #include <linux/mm.h> #include <linux/backing-dev.h> #include <linux/mutex.h> +#include <linux/rwsem.h> /** Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 @@ -25,6 +26,9 @@ /** Congestion starts at 75% of maximum */ #define FUSE_CONGESTION_THRESHOLD (FUSE_MAX_BACKGROUND * 75 / 100) +/** Bias for fi->writectr, meaning new writepages must not be sent */ +#define FUSE_NOWRITE INT_MIN + /** It could be as large as PATH_MAX, but would that have any uses? */ #define FUSE_NAME_MAX 1024 @@ -73,6 +77,19 @@ struct fuse_inode { /** Files usable in writepage. Protected by fc->lock */ struct list_head write_files; + + /** Writepages pending on truncate or fsync */ + struct list_head queued_writes; + + /** Number of sent writes, a negative bias (FUSE_NOWRITE) + * means more writes are blocked */ + int writectr; + + /** Waitq for writepage completion */ + wait_queue_head_t page_waitq; + + /** List of writepage requestst (pending or sent) */ + struct list_head writepages; }; /** FUSE specific file data */ @@ -222,7 +239,10 @@ struct fuse_req { } release; struct fuse_init_in init_in; struct fuse_init_out init_out; - struct fuse_read_in read_in; + struct { + struct fuse_read_in in; + u64 attr_ver; + } read; struct { struct fuse_write_in in; struct fuse_write_out out; @@ -242,6 +262,12 @@ struct fuse_req { /** File used in the request (or NULL) */ struct fuse_file *ff; + /** Inode used in the request or NULL */ + struct inode *inode; + + /** Link on fi->writepages */ + struct list_head writepages_entry; + /** Request completion callback */ void (*end)(struct fuse_conn *, struct fuse_req *); @@ -390,8 +416,8 @@ struct fuse_conn { /** Entry on the fuse_conn_list */ struct list_head entry; - /** Unique ID */ - u64 id; + /** Device ID from super block */ + dev_t dev; /** Dentries in the control filesystem */ struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES]; @@ -438,7 +464,7 @@ extern const struct file_operations fuse_dev_operations; /** * Get a filled in inode */ -struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, +struct inode *fuse_iget(struct super_block *sb, u64 nodeid, int generation, struct fuse_attr *attr, u64 attr_valid, u64 attr_version); @@ -446,7 +472,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, * Send FORGET command */ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, - unsigned long nodeid, u64 nlookup); + u64 nodeid, u64 nlookup); /** * Initialize READ or READDIR request @@ -504,6 +530,11 @@ void fuse_init_symlink(struct inode *inode); void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, u64 attr_valid, u64 attr_version); +void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, + u64 attr_valid); + +void fuse_truncate(struct address_space *mapping, loff_t offset); + /** * Initialize the client device */ @@ -522,6 +553,8 @@ void fuse_ctl_cleanup(void); */ struct fuse_req *fuse_request_alloc(void); +struct fuse_req *fuse_request_alloc_nofs(void); + /** * Free a request */ @@ -558,6 +591,8 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); */ void request_send_background(struct fuse_conn *fc, struct fuse_req *req); +void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req); + /* Abort all requests */ void fuse_abort_conn(struct fuse_conn *fc); @@ -600,3 +635,10 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); int fuse_update_attributes(struct inode *inode, struct kstat *stat, struct file *file, bool *refreshed); + +void fuse_flush_writepages(struct inode *inode); + +void fuse_set_nowrite(struct inode *inode); +void fuse_release_nowrite(struct inode *inode); + +u64 fuse_get_attr_version(struct fuse_conn *fc); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 4df34da2284..79b61587383 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -59,7 +59,11 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->nodeid = 0; fi->nlookup = 0; fi->attr_version = 0; + fi->writectr = 0; INIT_LIST_HEAD(&fi->write_files); + INIT_LIST_HEAD(&fi->queued_writes); + INIT_LIST_HEAD(&fi->writepages); + init_waitqueue_head(&fi->page_waitq); fi->forget_req = fuse_request_alloc(); if (!fi->forget_req) { kmem_cache_free(fuse_inode_cachep, inode); @@ -73,13 +77,14 @@ static void fuse_destroy_inode(struct inode *inode) { struct fuse_inode *fi = get_fuse_inode(inode); BUG_ON(!list_empty(&fi->write_files)); + BUG_ON(!list_empty(&fi->queued_writes)); if (fi->forget_req) fuse_request_free(fi->forget_req); kmem_cache_free(fuse_inode_cachep, inode); } void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, - unsigned long nodeid, u64 nlookup) + u64 nodeid, u64 nlookup) { struct fuse_forget_in *inarg = &req->misc.forget_in; inarg->nlookup = nlookup; @@ -109,7 +114,7 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } -static void fuse_truncate(struct address_space *mapping, loff_t offset) +void fuse_truncate(struct address_space *mapping, loff_t offset) { /* See vmtruncate() */ unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); @@ -117,19 +122,12 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset) unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); } - -void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, - u64 attr_valid, u64 attr_version) +void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, + u64 attr_valid) { struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_inode *fi = get_fuse_inode(inode); - loff_t oldsize; - spin_lock(&fc->lock); - if (attr_version != 0 && fi->attr_version > attr_version) { - spin_unlock(&fc->lock); - return; - } fi->attr_version = ++fc->attr_version; fi->i_time = attr_valid; @@ -159,6 +157,22 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, fi->orig_i_mode = inode->i_mode; if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) inode->i_mode &= ~S_ISVTX; +} + +void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, + u64 attr_valid, u64 attr_version) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + loff_t oldsize; + + spin_lock(&fc->lock); + if (attr_version != 0 && fi->attr_version > attr_version) { + spin_unlock(&fc->lock); + return; + } + + fuse_change_attributes_common(inode, attr, attr_valid); oldsize = inode->i_size; i_size_write(inode, attr->size); @@ -193,7 +207,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) static int fuse_inode_eq(struct inode *inode, void *_nodeidp) { - unsigned long nodeid = *(unsigned long *) _nodeidp; + u64 nodeid = *(u64 *) _nodeidp; if (get_node_id(inode) == nodeid) return 1; else @@ -202,12 +216,12 @@ static int fuse_inode_eq(struct inode *inode, void *_nodeidp) static int fuse_inode_set(struct inode *inode, void *_nodeidp) { - unsigned long nodeid = *(unsigned long *) _nodeidp; + u64 nodeid = *(u64 *) _nodeidp; get_fuse_inode(inode)->nodeid = nodeid; return 0; } -struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, +struct inode *fuse_iget(struct super_block *sb, u64 nodeid, int generation, struct fuse_attr *attr, u64 attr_valid, u64 attr_version) { @@ -447,7 +461,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) return 0; } -static struct fuse_conn *new_conn(void) +static struct fuse_conn *new_conn(struct super_block *sb) { struct fuse_conn *fc; int err; @@ -468,19 +482,41 @@ static struct fuse_conn *new_conn(void) atomic_set(&fc->num_waiting, 0); fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; fc->bdi.unplug_io_fn = default_unplug_io_fn; + /* fuse does it's own writeback accounting */ + fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; + fc->dev = sb->s_dev; err = bdi_init(&fc->bdi); - if (err) { - kfree(fc); - fc = NULL; - goto out; - } + if (err) + goto error_kfree; + err = bdi_register_dev(&fc->bdi, fc->dev); + if (err) + goto error_bdi_destroy; + /* + * For a single fuse filesystem use max 1% of dirty + + * writeback threshold. + * + * This gives about 1M of write buffer for memory maps on a + * machine with 1G and 10% dirty_ratio, which should be more + * than enough. + * + * Privileged users can raise it by writing to + * + * /sys/class/bdi/<bdi>/max_ratio + */ + bdi_set_max_ratio(&fc->bdi, 1); fc->reqctr = 0; fc->blocked = 1; fc->attr_version = 1; get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); } -out: return fc; + +error_bdi_destroy: + bdi_destroy(&fc->bdi); +error_kfree: + mutex_destroy(&fc->inst_mutex); + kfree(fc); + return NULL; } void fuse_conn_put(struct fuse_conn *fc) @@ -548,6 +584,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); fc->minor = arg->minor; fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; + fc->max_write = min_t(unsigned, 4096, fc->max_write); fc->conn_init = 1; } fuse_put_request(fc, req); @@ -578,12 +615,6 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) request_send_background(fc, req); } -static u64 conn_id(void) -{ - static u64 ctr = 1; - return ctr++; -} - static int fuse_fill_super(struct super_block *sb, void *data, int silent) { struct fuse_conn *fc; @@ -621,14 +652,14 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (file->f_op != &fuse_dev_operations) return -EINVAL; - fc = new_conn(); + fc = new_conn(sb); if (!fc) return -ENOMEM; fc->flags = d.flags; fc->user_id = d.user_id; fc->group_id = d.group_id; - fc->max_read = d.max_read; + fc->max_read = min_t(unsigned, 4096, d.max_read); /* Used by get_root_inode() */ sb->s_fs_info = fc; @@ -659,7 +690,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) if (file->private_data) goto err_unlock; - fc->id = conn_id(); err = fuse_ctl_add_conn(fc); if (err) goto err_unlock; diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c index 8479da47049..a4ff271df9e 100644 --- a/fs/gfs2/locking/dlm/sysfs.c +++ b/fs/gfs2/locking/dlm/sysfs.c @@ -212,7 +212,7 @@ int gdlm_sysfs_init(void) { gdlm_kset = kset_create_and_add("lock_dlm", NULL, kernel_kobj); if (!gdlm_kset) { - printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__); + printk(KERN_WARNING "%s: can not create kset\n", __func__); return -ENOMEM; } return 0; diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 509c5d60bd8..7f48576289c 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h @@ -41,7 +41,7 @@ int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion, #define gfs2_assert_withdraw(sdp, assertion) \ ((likely(assertion)) ? 0 : gfs2_assert_withdraw_i((sdp), #assertion, \ - __FUNCTION__, __FILE__, __LINE__)) + __func__, __FILE__, __LINE__)) int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, @@ -49,28 +49,28 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, #define gfs2_assert_warn(sdp, assertion) \ ((likely(assertion)) ? 0 : gfs2_assert_warn_i((sdp), #assertion, \ - __FUNCTION__, __FILE__, __LINE__)) + __func__, __FILE__, __LINE__)) int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide, const char *function, char *file, unsigned int line); #define gfs2_consist(sdp) \ -gfs2_consist_i((sdp), 0, __FUNCTION__, __FILE__, __LINE__) +gfs2_consist_i((sdp), 0, __func__, __FILE__, __LINE__) int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide, const char *function, char *file, unsigned int line); #define gfs2_consist_inode(ip) \ -gfs2_consist_inode_i((ip), 0, __FUNCTION__, __FILE__, __LINE__) +gfs2_consist_inode_i((ip), 0, __func__, __FILE__, __LINE__) int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide, const char *function, char *file, unsigned int line); #define gfs2_consist_rgrpd(rgd) \ -gfs2_consist_rgrpd_i((rgd), 0, __FUNCTION__, __FILE__, __LINE__) +gfs2_consist_rgrpd_i((rgd), 0, __func__, __FILE__, __LINE__) int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, @@ -91,7 +91,7 @@ static inline int gfs2_meta_check_i(struct gfs2_sbd *sdp, } #define gfs2_meta_check(sdp, bh) \ -gfs2_meta_check_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__) +gfs2_meta_check_i((sdp), (bh), __func__, __FILE__, __LINE__) int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh, @@ -118,7 +118,7 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp, } #define gfs2_metatype_check(sdp, bh, type) \ -gfs2_metatype_check_i((sdp), (bh), (type), __FUNCTION__, __FILE__, __LINE__) +gfs2_metatype_check_i((sdp), (bh), (type), __func__, __FILE__, __LINE__) static inline void gfs2_metatype_set(struct buffer_head *bh, u16 type, u16 format) @@ -134,14 +134,14 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file, unsigned int line); #define gfs2_io_error(sdp) \ -gfs2_io_error_i((sdp), __FUNCTION__, __FILE__, __LINE__); +gfs2_io_error_i((sdp), __func__, __FILE__, __LINE__); int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh, const char *function, char *file, unsigned int line); #define gfs2_io_error_bh(sdp, bh) \ -gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__); +gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__); extern struct kmem_cache *gfs2_glock_cachep; diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c index 24cf6fc4302..f6621a78520 100644 --- a/fs/hfs/btree.c +++ b/fs/hfs/btree.c @@ -208,7 +208,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) struct hfs_bnode *node, *next_node; struct page **pagep; u32 nidx, idx; - u16 off, len; + unsigned off; + u16 off16; + u16 len; u8 *data, byte, m; int i; @@ -235,7 +237,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) node = hfs_bnode_find(tree, nidx); if (IS_ERR(node)) return node; - len = hfs_brec_lenoff(node, 2, &off); + len = hfs_brec_lenoff(node, 2, &off16); + off = off16; off += node->page_offset; pagep = node->page + (off >> PAGE_CACHE_SHIFT); @@ -280,7 +283,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) return next_node; node = next_node; - len = hfs_brec_lenoff(node, 0, &off); + len = hfs_brec_lenoff(node, 0, &off16); + off = off16; off += node->page_offset; pagep = node->page + (off >> PAGE_CACHE_SHIFT); data = kmap(*pagep); diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index b4651e128d7..36ca2e1a4fa 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -215,7 +215,7 @@ int hfs_mdb_get(struct super_block *sb) attrib &= cpu_to_be16(~HFS_SB_ATTRIB_UNMNT); attrib |= cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT); mdb->drAtrb = attrib; - mdb->drWrCnt = cpu_to_be32(be32_to_cpu(mdb->drWrCnt) + 1); + be32_add_cpu(&mdb->drWrCnt, 1); mdb->drLsMod = hfs_mtime(); mark_buffer_dirty(HFS_SB(sb)->mdb_bh); diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index bb5433608a4..e49fcee1e29 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c @@ -184,7 +184,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) struct hfs_bnode *node, *next_node; struct page **pagep; u32 nidx, idx; - u16 off, len; + unsigned off; + u16 off16; + u16 len; u8 *data, byte, m; int i; @@ -211,7 +213,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) node = hfs_bnode_find(tree, nidx); if (IS_ERR(node)) return node; - len = hfs_brec_lenoff(node, 2, &off); + len = hfs_brec_lenoff(node, 2, &off16); + off = off16; off += node->page_offset; pagep = node->page + (off >> PAGE_CACHE_SHIFT); @@ -256,7 +259,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree) return next_node; node = next_node; - len = hfs_brec_lenoff(node, 0, &off); + len = hfs_brec_lenoff(node, 0, &off16); + off = off16; off += node->page_offset; pagep = node->page + (off >> PAGE_CACHE_SHIFT); data = kmap(*pagep); diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 946466cd9f2..ce97a54518d 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) */ vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION); vhdr->modify_date = hfsp_now2mt(); - vhdr->write_count = cpu_to_be32(be32_to_cpu(vhdr->write_count) + 1); + be32_add_cpu(&vhdr->write_count, 1); vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT); vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT); mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 9783723e8ff..aeabf80f81a 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -45,7 +45,7 @@ static const struct inode_operations hugetlbfs_inode_operations; static struct backing_dev_info hugetlbfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; int sysctl_hugetlb_shm_group; diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 1ba407c64df..2f0dc5a1463 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -145,6 +145,14 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, } de = tmpde; } + /* Basic sanity check, whether name doesn't exceed dir entry */ + if (de_len < de->name_len[0] + + sizeof(struct iso_directory_record)) { + printk(KERN_NOTICE "iso9660: Corrupted directory entry" + " in block %lu of inode %lu\n", block, + inode->i_ino); + return -EIO; + } if (first_de) { isofs_normalize_block_and_offset(de, diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 344b247bc29..8299889a835 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -111,6 +111,13 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, dlen = de->name_len[0]; dpnt = de->name; + /* Basic sanity check, whether name doesn't exceed dir entry */ + if (de_len < dlen + sizeof(struct iso_directory_record)) { + printk(KERN_NOTICE "iso9660: Corrupted directory entry" + " in block %lu of inode %lu\n", block, + dir->i_ino); + return 0; + } if (sbi->s_rock && ((i = get_rock_ridge_filename(de, tmpname, dir)))) { diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 9645275023e..a113ecc3baf 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -82,28 +82,28 @@ do { \ printk(JFFS2_ERR_MSG_PREFIX \ " (%d) %s: " fmt, task_pid_nr(current), \ - __FUNCTION__ , ##__VA_ARGS__); \ + __func__ , ##__VA_ARGS__); \ } while(0) #define JFFS2_WARNING(fmt, ...) \ do { \ printk(JFFS2_WARN_MSG_PREFIX \ " (%d) %s: " fmt, task_pid_nr(current), \ - __FUNCTION__ , ##__VA_ARGS__); \ + __func__ , ##__VA_ARGS__); \ } while(0) #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_MSG_PREFIX \ " (%d) %s: " fmt, task_pid_nr(current), \ - __FUNCTION__ , ##__VA_ARGS__); \ + __func__ , ##__VA_ARGS__); \ } while(0) #define JFFS2_DEBUG(fmt, ...) \ do { \ printk(JFFS2_DBG_MSG_PREFIX \ " (%d) %s: " fmt, task_pid_nr(current), \ - __FUNCTION__ , ##__VA_ARGS__); \ + __func__ , ##__VA_ARGS__); \ } while(0) /* diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index e48665984cb..574cb7532d6 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -82,7 +82,7 @@ static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_ static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ - D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version)); + D1(dbg_xattr("%s: xid=%u, version=%u\n", __func__, xd->xid, xd->version)); if (xd->xname) { c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len); kfree(xd->xname); @@ -1252,7 +1252,7 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); if (rc) { JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n", - __FUNCTION__, rc, totlen); + __func__, rc, totlen); rc = rc ? rc : -EBADFD; goto out; } diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 40b16f23e49..5df517b81f3 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -573,7 +573,7 @@ again: /* Ensure the resulting lock will get added to granted list */ fl->fl_flags |= FL_SLEEP; if (do_vfs_lock(fl) < 0) - printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__); + printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __func__); up_read(&host->h_rwsem); fl->fl_flags = fl_flags; status = 0; diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 4d81553d294..81aca859bfd 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -752,7 +752,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) return; default: printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", - -error, __FUNCTION__); + -error, __func__); nlmsvc_insert_block(block, 10 * HZ); nlmsvc_release_block(block); return; diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 2d4358c59f6..05ff4f1d702 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -609,7 +609,7 @@ error_inode: if (corrupt < 0) { fat_fs_panic(new_dir->i_sb, "%s: Filesystem corrupted (i_pos %lld)", - __FUNCTION__, sinfo.i_pos); + __func__, sinfo.i_pos); } goto out; } diff --git a/fs/namespace.c b/fs/namespace.c index 061e5edb4d2..4fc302c2a0e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2329,10 +2329,10 @@ void __init mnt_init(void) err = sysfs_init(); if (err) printk(KERN_WARNING "%s: sysfs_init error: %d\n", - __FUNCTION__, err); + __func__, err); fs_kobj = kobject_create_and_add("fs", NULL); if (!fs_kobj) - printk(KERN_WARNING "%s: kobj create error\n", __FUNCTION__); + printk(KERN_WARNING "%s: kobj create error\n", __func__); init_rootfs(); init_mount_tree(); } diff --git a/fs/nfs/super.c b/fs/nfs/super.c index fa220dc7460..7226a506f3c 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -1575,6 +1575,11 @@ static int nfs_compare_super(struct super_block *sb, void *data) return nfs_compare_mount_options(sb, server, mntflags); } +static int nfs_bdi_register(struct nfs_server *server) +{ + return bdi_register_dev(&server->backing_dev_info, server->s_dev); +} + static int nfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { @@ -1617,6 +1622,10 @@ static int nfs_get_sb(struct file_system_type *fs_type, if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; + } else { + error = nfs_bdi_register(server); + if (error) + goto error_splat_super; } if (!s->s_root) { @@ -1664,6 +1673,7 @@ static void nfs_kill_super(struct super_block *s) { struct nfs_server *server = NFS_SB(s); + bdi_unregister(&server->backing_dev_info); kill_anon_super(s); nfs_free_server(server); } @@ -1708,6 +1718,10 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; + } else { + error = nfs_bdi_register(server); + if (error) + goto error_splat_super; } if (!s->s_root) { @@ -1984,6 +1998,10 @@ static int nfs4_get_sb(struct file_system_type *fs_type, if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; + } else { + error = nfs_bdi_register(server); + if (error) + goto error_splat_super; } if (!s->s_root) { @@ -2070,6 +2088,10 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; + } else { + error = nfs_bdi_register(server); + if (error) + goto error_splat_super; } if (!s->s_root) { @@ -2149,6 +2171,10 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; + } else { + error = nfs_bdi_register(server); + if (error) + goto error_splat_super; } if (!s->s_root) { diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 562abf3380d..0b3ffa9840c 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -104,7 +104,7 @@ xdr_writemem(__be32 *p, const void *ptr, int nbytes) } while (0) #define RESERVE_SPACE(nbytes) do { \ p = xdr_reserve_space(xdr, nbytes); \ - if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __FUNCTION__); \ + if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \ BUG_ON(!p); \ } while (0) @@ -134,7 +134,7 @@ xdr_error: \ p = xdr_inline_decode(xdr, nbytes); \ if (!p) { \ dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \ - __FUNCTION__, __LINE__); \ + __func__, __LINE__); \ return -EIO; \ } \ } while (0) diff --git a/fs/ntfs/debug.h b/fs/ntfs/debug.h index 8ac37c33d12..5e6724c1afd 100644 --- a/fs/ntfs/debug.h +++ b/fs/ntfs/debug.h @@ -45,7 +45,7 @@ static void ntfs_debug(const char *f, ...); extern void __ntfs_debug (const char *file, int line, const char *function, const char *format, ...) __attribute__ ((format (printf, 4, 5))); #define ntfs_debug(f, a...) \ - __ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a) + __ntfs_debug(__FILE__, __LINE__, __func__, f, ##a) extern void ntfs_debug_dump_runlist(const runlist_element *rl); @@ -58,10 +58,10 @@ extern void ntfs_debug_dump_runlist(const runlist_element *rl); extern void __ntfs_warning(const char *function, const struct super_block *sb, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -#define ntfs_warning(sb, f, a...) __ntfs_warning(__FUNCTION__, sb, f, ##a) +#define ntfs_warning(sb, f, a...) __ntfs_warning(__func__, sb, f, ##a) extern void __ntfs_error(const char *function, const struct super_block *sb, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -#define ntfs_error(sb, f, a...) __ntfs_error(__FUNCTION__, sb, f, ##a) +#define ntfs_error(sb, f, a...) __ntfs_error(__func__, sb, f, ##a) #endif /* _LINUX_NTFS_DEBUG_H */ diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 61a000f8524..e48aba698b7 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -327,7 +327,7 @@ clear_fields: static struct backing_dev_info dlmfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; static struct inode *dlmfs_get_root_inode(struct super_block *sb) diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index e7dd1d4e347..0fdda2e8a4c 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c @@ -41,12 +41,12 @@ #ifndef CONFIG_LDM_DEBUG #define ldm_debug(...) do {} while (0) #else -#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __FUNCTION__, f, ##a) +#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __func__, f, ##a) #endif -#define ldm_crit(f, a...) _ldm_printk (KERN_CRIT, __FUNCTION__, f, ##a) -#define ldm_error(f, a...) _ldm_printk (KERN_ERR, __FUNCTION__, f, ##a) -#define ldm_info(f, a...) _ldm_printk (KERN_INFO, __FUNCTION__, f, ##a) +#define ldm_crit(f, a...) _ldm_printk (KERN_CRIT, __func__, f, ##a) +#define ldm_error(f, a...) _ldm_printk (KERN_ERR, __func__, f, ##a) +#define ldm_info(f, a...) _ldm_printk (KERN_INFO, __func__, f, ##a) __attribute__ ((format (printf, 3, 4))) static void _ldm_printk (const char *level, const char *function, diff --git a/fs/proc/array.c b/fs/proc/array.c index 07d6c4853fe..c135cbdd912 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -425,12 +425,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, cutime = cstime = utime = stime = cputime_zero; cgtime = gtime = cputime_zero; - rcu_read_lock(); if (lock_task_sighand(task, &flags)) { struct signal_struct *sig = task->signal; if (sig->tty) { - tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns); + struct pid *pgrp = tty_get_pgrp(sig->tty); + tty_pgrp = pid_nr_ns(pgrp, ns); + put_pid(pgrp); tty_nr = new_encode_dev(tty_devnum(sig->tty)); } @@ -469,7 +470,6 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, unlock_task_sighand(task, &flags); } - rcu_read_unlock(); if (!whole || num_threads < 2) wchan = get_wchan(task); diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 48bcf20cec2..74a323d2b85 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -179,6 +179,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, "PageTables: %8lu kB\n" "NFS_Unstable: %8lu kB\n" "Bounce: %8lu kB\n" + "WritebackTmp: %8lu kB\n" "CommitLimit: %8lu kB\n" "Committed_AS: %8lu kB\n" "VmallocTotal: %8lu kB\n" @@ -210,6 +211,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, K(global_page_state(NR_PAGETABLE)), K(global_page_state(NR_UNSTABLE_NFS)), K(global_page_state(NR_BOUNCE)), + K(global_page_state(NR_WRITEBACK_TEMP)), K(allowed), K(committed), (unsigned long)VMALLOC_TOTAL >> 10, diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index ac26ccc25f4..21f490f5d65 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c @@ -192,16 +192,14 @@ void proc_tty_register_driver(struct tty_driver *driver) { struct proc_dir_entry *ent; - if ((!driver->read_proc && !driver->write_proc) || - !driver->driver_name || + if (!driver->ops->read_proc || !driver->driver_name || driver->proc_entry) return; ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver); if (!ent) return; - ent->read_proc = driver->read_proc; - ent->write_proc = driver->write_proc; + ent->read_proc = driver->ops->read_proc; ent->owner = driver->owner; ent->data = driver; diff --git a/fs/quota_v2.c b/fs/quota_v2.c index 23b647f25d0..234ada90363 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c @@ -306,7 +306,7 @@ static uint find_free_dqentry(struct dquot *dquot, int *err) printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk); goto out_buf; } - dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1); + le16_add_cpu(&dh->dqdh_entries, 1); memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk)); /* Find free structure in block */ for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++); @@ -448,7 +448,7 @@ static int free_dqentry(struct dquot *dquot, uint blk) goto out_buf; } dh = (struct v2_disk_dqdbheader *)buf; - dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1); + le16_add_cpu(&dh->dqdh_entries, -1); if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */ if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 || (ret = put_free_dqblk(sb, type, buf, blk)) < 0) { diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 8428d5b2711..b13123424e4 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -44,7 +44,7 @@ static const struct inode_operations ramfs_dir_inode_operations; static struct backing_dev_info ramfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, }; diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index da86042b3e0..e396b2fa474 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2574,11 +2574,9 @@ static int release_journal_dev(struct super_block *super, result = 0; - if (journal->j_dev_file != NULL) { - result = filp_close(journal->j_dev_file, NULL); - journal->j_dev_file = NULL; - journal->j_dev_bd = NULL; - } else if (journal->j_dev_bd != NULL) { + if (journal->j_dev_bd != NULL) { + if (journal->j_dev_bd->bd_dev != super->s_dev) + bd_release(journal->j_dev_bd); result = blkdev_put(journal->j_dev_bd); journal->j_dev_bd = NULL; } @@ -2603,7 +2601,6 @@ static int journal_init_dev(struct super_block *super, result = 0; journal->j_dev_bd = NULL; - journal->j_dev_file = NULL; jdev = SB_ONDISK_JOURNAL_DEVICE(super) ? new_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev; @@ -2620,35 +2617,34 @@ static int journal_init_dev(struct super_block *super, "cannot init journal device '%s': %i", __bdevname(jdev, b), result); return result; - } else if (jdev != super->s_dev) + } else if (jdev != super->s_dev) { + result = bd_claim(journal->j_dev_bd, journal); + if (result) { + blkdev_put(journal->j_dev_bd); + return result; + } + set_blocksize(journal->j_dev_bd, super->s_blocksize); + } + return 0; } - journal->j_dev_file = filp_open(jdev_name, 0, 0); - if (!IS_ERR(journal->j_dev_file)) { - struct inode *jdev_inode = journal->j_dev_file->f_mapping->host; - if (!S_ISBLK(jdev_inode->i_mode)) { - reiserfs_warning(super, "journal_init_dev: '%s' is " - "not a block device", jdev_name); - result = -ENOTBLK; - release_journal_dev(super, journal); - } else { - /* ok */ - journal->j_dev_bd = I_BDEV(jdev_inode); - set_blocksize(journal->j_dev_bd, super->s_blocksize); - reiserfs_info(super, - "journal_init_dev: journal device: %s\n", - bdevname(journal->j_dev_bd, b)); - } - } else { - result = PTR_ERR(journal->j_dev_file); - journal->j_dev_file = NULL; + journal->j_dev_bd = open_bdev_excl(jdev_name, 0, journal); + if (IS_ERR(journal->j_dev_bd)) { + result = PTR_ERR(journal->j_dev_bd); + journal->j_dev_bd = NULL; reiserfs_warning(super, "journal_init_dev: Cannot open '%s': %i", jdev_name, result); + return result; } - return result; + + set_blocksize(journal->j_dev_bd, super->s_blocksize); + reiserfs_info(super, + "journal_init_dev: journal device: %s\n", + bdevname(journal->j_dev_bd, b)); + return 0; } /** diff --git a/fs/select.c b/fs/select.c index 00f58c5c7e0..2c292146e24 100644 --- a/fs/select.c +++ b/fs/select.c @@ -425,7 +425,7 @@ sticky: return ret; } -#ifdef TIF_RESTORE_SIGMASK +#ifdef HAVE_SET_RESTORE_SIGMASK asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timespec __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize) @@ -498,7 +498,7 @@ sticky: if (sigmask) { memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); } } else if (sigmask) sigprocmask(SIG_SETMASK, &sigsaved, NULL); @@ -528,7 +528,7 @@ asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize); } -#endif /* TIF_RESTORE_SIGMASK */ +#endif /* HAVE_SET_RESTORE_SIGMASK */ struct poll_list { struct poll_list *next; @@ -759,7 +759,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, return ret; } -#ifdef TIF_RESTORE_SIGMASK +#ifdef HAVE_SET_RESTORE_SIGMASK asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, struct timespec __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize) @@ -805,7 +805,7 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, if (sigmask) { memcpy(¤t->saved_sigmask, &sigsaved, sizeof(sigsaved)); - set_thread_flag(TIF_RESTORE_SIGMASK); + set_restore_sigmask(); } ret = -ERESTARTNOHAND; } else if (sigmask) @@ -839,4 +839,4 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, return ret; } -#endif /* TIF_RESTORE_SIGMASK */ +#endif /* HAVE_SET_RESTORE_SIGMASK */ diff --git a/fs/smbfs/smb_debug.h b/fs/smbfs/smb_debug.h index 734972b9269..fc4b1a5dd75 100644 --- a/fs/smbfs/smb_debug.h +++ b/fs/smbfs/smb_debug.h @@ -11,14 +11,14 @@ * these are normally enabled. */ #ifdef SMBFS_PARANOIA -# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __FUNCTION__ , ## a) +# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __func__ , ## a) #else # define PARANOIA(f, a...) do { ; } while(0) #endif /* lots of debug messages */ #ifdef SMBFS_DEBUG_VERBOSE -# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __FUNCTION__ , ## a) +# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a) #else # define VERBOSE(f, a...) do { ; } while(0) #endif @@ -28,7 +28,7 @@ * too common name. */ #ifdef SMBFS_DEBUG -#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __FUNCTION__ , ## a) +#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a) #else #define DEBUG1(f, a...) do { ; } while(0) #endif diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index dbdfabbfd60..e7735f643cd 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -135,7 +135,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) goto out; } pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n", - __FUNCTION__, count, *ppos, buffer->page); + __func__, count, *ppos, buffer->page); retval = simple_read_from_buffer(buf, count, ppos, buffer->page, buffer->count); out: diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index d9262f74f94..f8b82e73b3b 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -30,7 +30,7 @@ static const struct address_space_operations sysfs_aops = { static struct backing_dev_info sysfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, + .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; static const struct inode_operations sysfs_inode_operations ={ diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 74168266cd5..14f0023984d 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -61,7 +61,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) /* instantiate and link root dentry */ root = d_alloc_root(inode); if (!root) { - pr_debug("%s: could not get root dentry!\n",__FUNCTION__); + pr_debug("%s: could not get root dentry!\n",__func__); iput(inode); return -ENOMEM; } diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index 42d51d1c05c..38ebe3f85b3 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h @@ -217,9 +217,9 @@ static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d) if (sbi->s_bytesex == BYTESEX_PDP) *(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d); else if (sbi->s_bytesex == BYTESEX_LE) - *(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d); + le32_add_cpu((__le32 *)n, d); else - *(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d); + be32_add_cpu((__be32 *)n, d); return *n; } @@ -242,9 +242,9 @@ static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n) static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d) { if (sbi->s_bytesex != BYTESEX_BE) - *(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d); + le16_add_cpu((__le16 *)n, d); else - *(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d); + be16_add_cpu((__be16 *)n, d); return *n; } diff --git a/fs/udf/super.c b/fs/udf/super.c index b564fc140fe..9fb18a340fc 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -240,7 +240,7 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count) sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map), GFP_KERNEL); if (!sbi->s_partmaps) { - udf_error(sb, __FUNCTION__, + udf_error(sb, __func__, "Unable to allocate space for %d partition maps", count); sbi->s_partitions = 0; @@ -1086,7 +1086,7 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) bitmap = vmalloc(size); /* TODO: get rid of vmalloc */ if (bitmap == NULL) { - udf_error(sb, __FUNCTION__, + udf_error(sb, __func__, "Unable to allocate space for bitmap " "and %d buffer_head pointers", nr_groups); return NULL; diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index 5b66162d074..a3522727ea5 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -986,7 +986,7 @@ error_inode: if (corrupt < 0) { fat_fs_panic(new_dir->i_sb, "%s: Filesystem corrupted (i_pos %lld)", - __FUNCTION__, sinfo.i_pos); + __func__, sinfo.i_pos); } goto out; } diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 1bc9f600365..4edc46915b5 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -75,6 +75,7 @@ #include <linux/delay.h> #include <linux/log2.h> #include <linux/spinlock.h> +#include <linux/random.h> #include <asm/page.h> #include <asm/div64.h> diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 855da040864..75845f95081 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -49,8 +49,6 @@ extern void assfail(char *expr, char *f, int l); #else /* DEBUG */ -#include <linux/random.h> - #define ASSERT(expr) \ (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) |