diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-04-20 17:27:45 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-20 17:27:45 -0400 |
commit | 9707b27100a48950f1e15e08a7c5028786e47f55 (patch) | |
tree | 5745b1e7497ae1499a2e2e9e0a567996419ab34f /fs | |
parent | 8fc65162a8f25929be80c8d6321a3479e92b5aae (diff) | |
parent | 402a26f0c040077ed6f941eefac5a6971f0d5f40 (diff) |
Merge branch 'master'
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 6 | ||||
-rw-r--r-- | fs/exec.c | 2 | ||||
-rw-r--r-- | fs/ext3/resize.c | 1 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 2 | ||||
-rw-r--r-- | fs/locks.c | 9 | ||||
-rw-r--r-- | fs/nfs/dir.c | 5 | ||||
-rw-r--r-- | fs/nfs/direct.c | 8 | ||||
-rw-r--r-- | fs/nfs/file.c | 5 | ||||
-rw-r--r-- | fs/nfs/inode.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 10 | ||||
-rw-r--r-- | fs/open.c | 24 | ||||
-rw-r--r-- | fs/partitions/check.c | 5 | ||||
-rw-r--r-- | fs/proc/base.c | 21 | ||||
-rw-r--r-- | fs/splice.c | 196 |
14 files changed, 208 insertions, 91 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 2524629dc835..f9b5842c8d2d 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -842,6 +842,12 @@ config TMPFS | |||
842 | config HUGETLBFS | 842 | config HUGETLBFS |
843 | bool "HugeTLB file system support" | 843 | bool "HugeTLB file system support" |
844 | depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN | 844 | depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN |
845 | help | ||
846 | hugetlbfs is a filesystem backing for HugeTLB pages, based on | ||
847 | ramfs. For architectures that support it, say Y here and read | ||
848 | <file:Documentation/vm/hugetlbpage.txt> for details. | ||
849 | |||
850 | If unsure, say N. | ||
845 | 851 | ||
846 | config HUGETLB_PAGE | 852 | config HUGETLB_PAGE |
847 | def_bool HUGETLBFS | 853 | def_bool HUGETLBFS |
@@ -712,7 +712,7 @@ static int de_thread(struct task_struct *tsk) | |||
712 | attach_pid(current, PIDTYPE_PID, current->pid); | 712 | attach_pid(current, PIDTYPE_PID, current->pid); |
713 | attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); | 713 | attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); |
714 | attach_pid(current, PIDTYPE_SID, current->signal->session); | 714 | attach_pid(current, PIDTYPE_SID, current->signal->session); |
715 | list_add_tail(¤t->tasks, &init_task.tasks); | 715 | list_add_tail_rcu(¤t->tasks, &init_task.tasks); |
716 | 716 | ||
717 | current->group_leader = current; | 717 | current->group_leader = current; |
718 | leader->group_leader = current; | 718 | leader->group_leader = current; |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 14f5f6ea3e72..c5ffa8523968 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -767,6 +767,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) | |||
767 | if (input->group != sbi->s_groups_count) { | 767 | if (input->group != sbi->s_groups_count) { |
768 | ext3_warning(sb, __FUNCTION__, | 768 | ext3_warning(sb, __FUNCTION__, |
769 | "multiple resizers run on filesystem!"); | 769 | "multiple resizers run on filesystem!"); |
770 | unlock_super(sb); | ||
770 | err = -EBUSY; | 771 | err = -EBUSY; |
771 | goto exit_journal; | 772 | goto exit_journal; |
772 | } | 773 | } |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d2b66bad7d50..3ef739120dff 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -650,7 +650,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) | |||
650 | svc_wake_up(block->b_daemon); | 650 | svc_wake_up(block->b_daemon); |
651 | } | 651 | } |
652 | 652 | ||
653 | void nlmsvc_grant_release(void *data) | 653 | static void nlmsvc_grant_release(void *data) |
654 | { | 654 | { |
655 | struct nlm_rqst *call = data; | 655 | struct nlm_rqst *call = data; |
656 | 656 | ||
diff --git a/fs/locks.c b/fs/locks.c index dda83d6cd48b..efad798824dc 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -2230,7 +2230,12 @@ void steal_locks(fl_owner_t from) | |||
2230 | 2230 | ||
2231 | lock_kernel(); | 2231 | lock_kernel(); |
2232 | j = 0; | 2232 | j = 0; |
2233 | rcu_read_lock(); | 2233 | |
2234 | /* | ||
2235 | * We are not taking a ref to the file structures, so | ||
2236 | * we need to acquire ->file_lock. | ||
2237 | */ | ||
2238 | spin_lock(&files->file_lock); | ||
2234 | fdt = files_fdtable(files); | 2239 | fdt = files_fdtable(files); |
2235 | for (;;) { | 2240 | for (;;) { |
2236 | unsigned long set; | 2241 | unsigned long set; |
@@ -2248,7 +2253,7 @@ void steal_locks(fl_owner_t from) | |||
2248 | set >>= 1; | 2253 | set >>= 1; |
2249 | } | 2254 | } |
2250 | } | 2255 | } |
2251 | rcu_read_unlock(); | 2256 | spin_unlock(&files->file_lock); |
2252 | unlock_kernel(); | 2257 | unlock_kernel(); |
2253 | } | 2258 | } |
2254 | EXPORT_SYMBOL(steal_locks); | 2259 | EXPORT_SYMBOL(steal_locks); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a23f34894167..cae74dd4c7f5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -128,15 +128,14 @@ struct inode_operations nfs4_dir_inode_operations = { | |||
128 | static int | 128 | static int |
129 | nfs_opendir(struct inode *inode, struct file *filp) | 129 | nfs_opendir(struct inode *inode, struct file *filp) |
130 | { | 130 | { |
131 | int res = 0; | 131 | int res; |
132 | 132 | ||
133 | dfprintk(VFS, "NFS: opendir(%s/%ld)\n", | 133 | dfprintk(VFS, "NFS: opendir(%s/%ld)\n", |
134 | inode->i_sb->s_id, inode->i_ino); | 134 | inode->i_sb->s_id, inode->i_ino); |
135 | 135 | ||
136 | lock_kernel(); | 136 | lock_kernel(); |
137 | /* Call generic open code in order to cache credentials */ | 137 | /* Call generic open code in order to cache credentials */ |
138 | if (!res) | 138 | res = nfs_open(inode, filp); |
139 | res = nfs_open(inode, filp); | ||
140 | unlock_kernel(); | 139 | unlock_kernel(); |
141 | return res; | 140 | return res; |
142 | } | 141 | } |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 0f583cb16ddb..3c72b0c07283 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -112,10 +112,9 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode | |||
112 | */ | 112 | */ |
113 | ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) | 113 | ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs) |
114 | { | 114 | { |
115 | struct dentry *dentry = iocb->ki_filp->f_dentry; | ||
116 | |||
117 | dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n", | 115 | dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n", |
118 | dentry->d_name.name, (long long) pos, nr_segs); | 116 | iocb->ki_filp->f_dentry->d_name.name, |
117 | (long long) pos, nr_segs); | ||
119 | 118 | ||
120 | return -EINVAL; | 119 | return -EINVAL; |
121 | } | 120 | } |
@@ -468,7 +467,6 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { | |||
468 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | 467 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) |
469 | { | 468 | { |
470 | struct nfs_write_data *data = dreq->commit_data; | 469 | struct nfs_write_data *data = dreq->commit_data; |
471 | struct rpc_task *task = &data->task; | ||
472 | 470 | ||
473 | data->inode = dreq->inode; | 471 | data->inode = dreq->inode; |
474 | data->cred = dreq->ctx->cred; | 472 | data->cred = dreq->ctx->cred; |
@@ -489,7 +487,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
489 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ | 487 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ |
490 | dreq->commit_data = NULL; | 488 | dreq->commit_data = NULL; |
491 | 489 | ||
492 | dprintk("NFS: %5u initiated commit call\n", task->tk_pid); | 490 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
493 | 491 | ||
494 | lock_kernel(); | 492 | lock_kernel(); |
495 | rpc_execute(&data->task); | 493 | rpc_execute(&data->task); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f1df2c8d9259..fade02c15e6e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -534,10 +534,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
534 | */ | 534 | */ |
535 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | 535 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) |
536 | { | 536 | { |
537 | struct inode * inode = filp->f_mapping->host; | ||
538 | |||
539 | dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", | 537 | dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", |
540 | inode->i_sb->s_id, inode->i_ino, | 538 | filp->f_dentry->d_inode->i_sb->s_id, |
539 | filp->f_dentry->d_inode->i_ino, | ||
541 | fl->fl_type, fl->fl_flags); | 540 | fl->fl_type, fl->fl_flags); |
542 | 541 | ||
543 | /* | 542 | /* |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2f7656b911b6..d0b991a92327 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -700,12 +700,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) | |||
700 | /* | 700 | /* |
701 | * Display superblock I/O counters | 701 | * Display superblock I/O counters |
702 | */ | 702 | */ |
703 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 703 | for_each_possible_cpu(cpu) { |
704 | struct nfs_iostats *stats; | 704 | struct nfs_iostats *stats; |
705 | 705 | ||
706 | if (!cpu_possible(cpu)) | ||
707 | continue; | ||
708 | |||
709 | preempt_disable(); | 706 | preempt_disable(); |
710 | stats = per_cpu_ptr(nfss->io_stats, cpu); | 707 | stats = per_cpu_ptr(nfss->io_stats, cpu); |
711 | 708 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 47ece1dd3c67..d86c0db7b1e8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1218,7 +1218,7 @@ out: | |||
1218 | return status; | 1218 | return status; |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state) | 1221 | static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state) |
1222 | { | 1222 | { |
1223 | struct file *filp; | 1223 | struct file *filp; |
1224 | 1224 | ||
@@ -1227,8 +1227,10 @@ static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, st | |||
1227 | struct nfs_open_context *ctx; | 1227 | struct nfs_open_context *ctx; |
1228 | ctx = (struct nfs_open_context *)filp->private_data; | 1228 | ctx = (struct nfs_open_context *)filp->private_data; |
1229 | ctx->state = state; | 1229 | ctx->state = state; |
1230 | } else | 1230 | return 0; |
1231 | nfs4_close_state(state, nd->intent.open.flags); | 1231 | } |
1232 | nfs4_close_state(state, nd->intent.open.flags); | ||
1233 | return PTR_ERR(filp); | ||
1232 | } | 1234 | } |
1233 | 1235 | ||
1234 | struct dentry * | 1236 | struct dentry * |
@@ -1835,7 +1837,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
1835 | nfs_setattr_update_inode(state->inode, sattr); | 1837 | nfs_setattr_update_inode(state->inode, sattr); |
1836 | } | 1838 | } |
1837 | if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN)) | 1839 | if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN)) |
1838 | nfs4_intent_set_file(nd, dentry, state); | 1840 | status = nfs4_intent_set_file(nd, dentry, state); |
1839 | else | 1841 | else |
1840 | nfs4_close_state(state, flags); | 1842 | nfs4_close_state(state, flags); |
1841 | out: | 1843 | out: |
@@ -331,7 +331,10 @@ out: | |||
331 | 331 | ||
332 | asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length) | 332 | asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length) |
333 | { | 333 | { |
334 | return do_sys_ftruncate(fd, length, 1); | 334 | long ret = do_sys_ftruncate(fd, length, 1); |
335 | /* avoid REGPARM breakage on x86: */ | ||
336 | prevent_tail_call(ret); | ||
337 | return ret; | ||
335 | } | 338 | } |
336 | 339 | ||
337 | /* LFS versions of truncate are only needed on 32 bit machines */ | 340 | /* LFS versions of truncate are only needed on 32 bit machines */ |
@@ -343,7 +346,10 @@ asmlinkage long sys_truncate64(const char __user * path, loff_t length) | |||
343 | 346 | ||
344 | asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length) | 347 | asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length) |
345 | { | 348 | { |
346 | return do_sys_ftruncate(fd, length, 0); | 349 | long ret = do_sys_ftruncate(fd, length, 0); |
350 | /* avoid REGPARM breakage on x86: */ | ||
351 | prevent_tail_call(ret); | ||
352 | return ret; | ||
347 | } | 353 | } |
348 | #endif | 354 | #endif |
349 | 355 | ||
@@ -1093,20 +1099,30 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode) | |||
1093 | 1099 | ||
1094 | asmlinkage long sys_open(const char __user *filename, int flags, int mode) | 1100 | asmlinkage long sys_open(const char __user *filename, int flags, int mode) |
1095 | { | 1101 | { |
1102 | long ret; | ||
1103 | |||
1096 | if (force_o_largefile()) | 1104 | if (force_o_largefile()) |
1097 | flags |= O_LARGEFILE; | 1105 | flags |= O_LARGEFILE; |
1098 | 1106 | ||
1099 | return do_sys_open(AT_FDCWD, filename, flags, mode); | 1107 | ret = do_sys_open(AT_FDCWD, filename, flags, mode); |
1108 | /* avoid REGPARM breakage on x86: */ | ||
1109 | prevent_tail_call(ret); | ||
1110 | return ret; | ||
1100 | } | 1111 | } |
1101 | EXPORT_SYMBOL_GPL(sys_open); | 1112 | EXPORT_SYMBOL_GPL(sys_open); |
1102 | 1113 | ||
1103 | asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, | 1114 | asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, |
1104 | int mode) | 1115 | int mode) |
1105 | { | 1116 | { |
1117 | long ret; | ||
1118 | |||
1106 | if (force_o_largefile()) | 1119 | if (force_o_largefile()) |
1107 | flags |= O_LARGEFILE; | 1120 | flags |= O_LARGEFILE; |
1108 | 1121 | ||
1109 | return do_sys_open(dfd, filename, flags, mode); | 1122 | ret = do_sys_open(dfd, filename, flags, mode); |
1123 | /* avoid REGPARM breakage on x86: */ | ||
1124 | prevent_tail_call(ret); | ||
1125 | return ret; | ||
1110 | } | 1126 | } |
1111 | EXPORT_SYMBOL_GPL(sys_openat); | 1127 | EXPORT_SYMBOL_GPL(sys_openat); |
1112 | 1128 | ||
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f3b6af071722..45ae7dd3c650 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -372,6 +372,7 @@ static char *make_block_name(struct gendisk *disk) | |||
372 | char *name; | 372 | char *name; |
373 | static char *block_str = "block:"; | 373 | static char *block_str = "block:"; |
374 | int size; | 374 | int size; |
375 | char *s; | ||
375 | 376 | ||
376 | size = strlen(block_str) + strlen(disk->disk_name) + 1; | 377 | size = strlen(block_str) + strlen(disk->disk_name) + 1; |
377 | name = kmalloc(size, GFP_KERNEL); | 378 | name = kmalloc(size, GFP_KERNEL); |
@@ -379,6 +380,10 @@ static char *make_block_name(struct gendisk *disk) | |||
379 | return NULL; | 380 | return NULL; |
380 | strcpy(name, block_str); | 381 | strcpy(name, block_str); |
381 | strcat(name, disk->disk_name); | 382 | strcat(name, disk->disk_name); |
383 | /* ewww... some of these buggers have / in name... */ | ||
384 | s = strchr(name, '/'); | ||
385 | if (s) | ||
386 | *s = '!'; | ||
382 | return name; | 387 | return name; |
383 | } | 388 | } |
384 | 389 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index a3a3eecef689..6cc77dc3f3ff 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -297,16 +297,20 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm | |||
297 | 297 | ||
298 | files = get_files_struct(task); | 298 | files = get_files_struct(task); |
299 | if (files) { | 299 | if (files) { |
300 | rcu_read_lock(); | 300 | /* |
301 | * We are not taking a ref to the file structure, so we must | ||
302 | * hold ->file_lock. | ||
303 | */ | ||
304 | spin_lock(&files->file_lock); | ||
301 | file = fcheck_files(files, fd); | 305 | file = fcheck_files(files, fd); |
302 | if (file) { | 306 | if (file) { |
303 | *mnt = mntget(file->f_vfsmnt); | 307 | *mnt = mntget(file->f_vfsmnt); |
304 | *dentry = dget(file->f_dentry); | 308 | *dentry = dget(file->f_dentry); |
305 | rcu_read_unlock(); | 309 | spin_unlock(&files->file_lock); |
306 | put_files_struct(files); | 310 | put_files_struct(files); |
307 | return 0; | 311 | return 0; |
308 | } | 312 | } |
309 | rcu_read_unlock(); | 313 | spin_unlock(&files->file_lock); |
310 | put_files_struct(files); | 314 | put_files_struct(files); |
311 | } | 315 | } |
312 | return -ENOENT; | 316 | return -ENOENT; |
@@ -1523,7 +1527,12 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, | |||
1523 | if (!files) | 1527 | if (!files) |
1524 | goto out_unlock; | 1528 | goto out_unlock; |
1525 | inode->i_mode = S_IFLNK; | 1529 | inode->i_mode = S_IFLNK; |
1526 | rcu_read_lock(); | 1530 | |
1531 | /* | ||
1532 | * We are not taking a ref to the file structure, so we must | ||
1533 | * hold ->file_lock. | ||
1534 | */ | ||
1535 | spin_lock(&files->file_lock); | ||
1527 | file = fcheck_files(files, fd); | 1536 | file = fcheck_files(files, fd); |
1528 | if (!file) | 1537 | if (!file) |
1529 | goto out_unlock2; | 1538 | goto out_unlock2; |
@@ -1531,7 +1540,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, | |||
1531 | inode->i_mode |= S_IRUSR | S_IXUSR; | 1540 | inode->i_mode |= S_IRUSR | S_IXUSR; |
1532 | if (file->f_mode & 2) | 1541 | if (file->f_mode & 2) |
1533 | inode->i_mode |= S_IWUSR | S_IXUSR; | 1542 | inode->i_mode |= S_IWUSR | S_IXUSR; |
1534 | rcu_read_unlock(); | 1543 | spin_unlock(&files->file_lock); |
1535 | put_files_struct(files); | 1544 | put_files_struct(files); |
1536 | inode->i_op = &proc_pid_link_inode_operations; | 1545 | inode->i_op = &proc_pid_link_inode_operations; |
1537 | inode->i_size = 64; | 1546 | inode->i_size = 64; |
@@ -1541,7 +1550,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, | |||
1541 | return NULL; | 1550 | return NULL; |
1542 | 1551 | ||
1543 | out_unlock2: | 1552 | out_unlock2: |
1544 | rcu_read_unlock(); | 1553 | spin_unlock(&files->file_lock); |
1545 | put_files_struct(files); | 1554 | put_files_struct(files); |
1546 | out_unlock: | 1555 | out_unlock: |
1547 | iput(inode); | 1556 | iput(inode); |
diff --git a/fs/splice.c b/fs/splice.c index 8d57e89924a6..0559e7577a04 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -50,7 +50,8 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, | |||
50 | struct page *page = buf->page; | 50 | struct page *page = buf->page; |
51 | struct address_space *mapping = page_mapping(page); | 51 | struct address_space *mapping = page_mapping(page); |
52 | 52 | ||
53 | WARN_ON(!PageLocked(page)); | 53 | lock_page(page); |
54 | |||
54 | WARN_ON(!PageUptodate(page)); | 55 | WARN_ON(!PageUptodate(page)); |
55 | 56 | ||
56 | /* | 57 | /* |
@@ -65,8 +66,10 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, | |||
65 | if (PagePrivate(page)) | 66 | if (PagePrivate(page)) |
66 | try_to_release_page(page, mapping_gfp_mask(mapping)); | 67 | try_to_release_page(page, mapping_gfp_mask(mapping)); |
67 | 68 | ||
68 | if (!remove_mapping(mapping, page)) | 69 | if (!remove_mapping(mapping, page)) { |
70 | unlock_page(page); | ||
69 | return 1; | 71 | return 1; |
72 | } | ||
70 | 73 | ||
71 | buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU; | 74 | buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU; |
72 | return 0; | 75 | return 0; |
@@ -145,8 +148,8 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = { | |||
145 | * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). | 148 | * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). |
146 | */ | 149 | */ |
147 | static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages, | 150 | static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages, |
148 | int nr_pages, unsigned long offset, | 151 | int nr_pages, unsigned long len, |
149 | unsigned long len, unsigned int flags) | 152 | unsigned int offset, unsigned int flags) |
150 | { | 153 | { |
151 | int ret, do_wakeup, i; | 154 | int ret, do_wakeup, i; |
152 | 155 | ||
@@ -243,14 +246,16 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
243 | unsigned int flags) | 246 | unsigned int flags) |
244 | { | 247 | { |
245 | struct address_space *mapping = in->f_mapping; | 248 | struct address_space *mapping = in->f_mapping; |
246 | unsigned int offset, nr_pages; | 249 | unsigned int loff, offset, nr_pages; |
247 | struct page *pages[PIPE_BUFFERS]; | 250 | struct page *pages[PIPE_BUFFERS]; |
248 | struct page *page; | 251 | struct page *page; |
249 | pgoff_t index; | 252 | pgoff_t index, end_index; |
253 | loff_t isize; | ||
254 | size_t bytes; | ||
250 | int i, error; | 255 | int i, error; |
251 | 256 | ||
252 | index = *ppos >> PAGE_CACHE_SHIFT; | 257 | index = *ppos >> PAGE_CACHE_SHIFT; |
253 | offset = *ppos & ~PAGE_CACHE_MASK; | 258 | loff = offset = *ppos & ~PAGE_CACHE_MASK; |
254 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 259 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
255 | 260 | ||
256 | if (nr_pages > PIPE_BUFFERS) | 261 | if (nr_pages > PIPE_BUFFERS) |
@@ -268,7 +273,17 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
268 | * Now fill in the holes: | 273 | * Now fill in the holes: |
269 | */ | 274 | */ |
270 | error = 0; | 275 | error = 0; |
276 | bytes = 0; | ||
271 | for (i = 0; i < nr_pages; i++, index++) { | 277 | for (i = 0; i < nr_pages; i++, index++) { |
278 | unsigned int this_len; | ||
279 | |||
280 | if (!len) | ||
281 | break; | ||
282 | |||
283 | /* | ||
284 | * this_len is the max we'll use from this page | ||
285 | */ | ||
286 | this_len = min(len, PAGE_CACHE_SIZE - loff); | ||
272 | find_page: | 287 | find_page: |
273 | /* | 288 | /* |
274 | * lookup the page for this index | 289 | * lookup the page for this index |
@@ -276,14 +291,6 @@ find_page: | |||
276 | page = find_get_page(mapping, index); | 291 | page = find_get_page(mapping, index); |
277 | if (!page) { | 292 | if (!page) { |
278 | /* | 293 | /* |
279 | * If in nonblock mode then dont block on | ||
280 | * readpage (we've kicked readahead so there | ||
281 | * will be asynchronous progress): | ||
282 | */ | ||
283 | if (flags & SPLICE_F_NONBLOCK) | ||
284 | break; | ||
285 | |||
286 | /* | ||
287 | * page didn't exist, allocate one | 294 | * page didn't exist, allocate one |
288 | */ | 295 | */ |
289 | page = page_cache_alloc_cold(mapping); | 296 | page = page_cache_alloc_cold(mapping); |
@@ -304,6 +311,13 @@ find_page: | |||
304 | * If the page isn't uptodate, we may need to start io on it | 311 | * If the page isn't uptodate, we may need to start io on it |
305 | */ | 312 | */ |
306 | if (!PageUptodate(page)) { | 313 | if (!PageUptodate(page)) { |
314 | /* | ||
315 | * If in nonblock mode then dont block on waiting | ||
316 | * for an in-flight io page | ||
317 | */ | ||
318 | if (flags & SPLICE_F_NONBLOCK) | ||
319 | break; | ||
320 | |||
307 | lock_page(page); | 321 | lock_page(page); |
308 | 322 | ||
309 | /* | 323 | /* |
@@ -336,13 +350,43 @@ readpage: | |||
336 | goto find_page; | 350 | goto find_page; |
337 | break; | 351 | break; |
338 | } | 352 | } |
353 | |||
354 | /* | ||
355 | * i_size must be checked after ->readpage(). | ||
356 | */ | ||
357 | isize = i_size_read(mapping->host); | ||
358 | end_index = (isize - 1) >> PAGE_CACHE_SHIFT; | ||
359 | if (unlikely(!isize || index > end_index)) { | ||
360 | page_cache_release(page); | ||
361 | break; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * if this is the last page, see if we need to shrink | ||
366 | * the length and stop | ||
367 | */ | ||
368 | if (end_index == index) { | ||
369 | loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK); | ||
370 | if (bytes + loff > isize) { | ||
371 | page_cache_release(page); | ||
372 | break; | ||
373 | } | ||
374 | /* | ||
375 | * force quit after adding this page | ||
376 | */ | ||
377 | nr_pages = i; | ||
378 | this_len = min(this_len, loff); | ||
379 | } | ||
339 | } | 380 | } |
340 | fill_it: | 381 | fill_it: |
341 | pages[i] = page; | 382 | pages[i] = page; |
383 | bytes += this_len; | ||
384 | len -= this_len; | ||
385 | loff = 0; | ||
342 | } | 386 | } |
343 | 387 | ||
344 | if (i) | 388 | if (i) |
345 | return move_to_pipe(pipe, pages, i, offset, len, flags); | 389 | return move_to_pipe(pipe, pages, i, bytes, offset, flags); |
346 | 390 | ||
347 | return error; | 391 | return error; |
348 | } | 392 | } |
@@ -369,17 +413,20 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, | |||
369 | while (len) { | 413 | while (len) { |
370 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); | 414 | ret = __generic_file_splice_read(in, ppos, pipe, len, flags); |
371 | 415 | ||
372 | if (ret <= 0) | 416 | if (ret < 0) |
373 | break; | 417 | break; |
418 | else if (!ret) { | ||
419 | if (spliced) | ||
420 | break; | ||
421 | if (flags & SPLICE_F_NONBLOCK) { | ||
422 | ret = -EAGAIN; | ||
423 | break; | ||
424 | } | ||
425 | } | ||
374 | 426 | ||
375 | *ppos += ret; | 427 | *ppos += ret; |
376 | len -= ret; | 428 | len -= ret; |
377 | spliced += ret; | 429 | spliced += ret; |
378 | |||
379 | if (!(flags & SPLICE_F_NONBLOCK)) | ||
380 | continue; | ||
381 | ret = -EAGAIN; | ||
382 | break; | ||
383 | } | 430 | } |
384 | 431 | ||
385 | if (spliced) | 432 | if (spliced) |
@@ -474,14 +521,12 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, | |||
474 | if (sd->flags & SPLICE_F_MOVE) { | 521 | if (sd->flags & SPLICE_F_MOVE) { |
475 | /* | 522 | /* |
476 | * If steal succeeds, buf->page is now pruned from the vm | 523 | * If steal succeeds, buf->page is now pruned from the vm |
477 | * side (LRU and page cache) and we can reuse it. | 524 | * side (LRU and page cache) and we can reuse it. The page |
525 | * will also be looked on successful return. | ||
478 | */ | 526 | */ |
479 | if (buf->ops->steal(info, buf)) | 527 | if (buf->ops->steal(info, buf)) |
480 | goto find_page; | 528 | goto find_page; |
481 | 529 | ||
482 | /* | ||
483 | * this will also set the page locked | ||
484 | */ | ||
485 | page = buf->page; | 530 | page = buf->page; |
486 | if (add_to_page_cache(page, mapping, index, gfp_mask)) | 531 | if (add_to_page_cache(page, mapping, index, gfp_mask)) |
487 | goto find_page; | 532 | goto find_page; |
@@ -490,15 +535,27 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, | |||
490 | lru_cache_add(page); | 535 | lru_cache_add(page); |
491 | } else { | 536 | } else { |
492 | find_page: | 537 | find_page: |
493 | ret = -ENOMEM; | 538 | page = find_lock_page(mapping, index); |
494 | page = find_or_create_page(mapping, index, gfp_mask); | 539 | if (!page) { |
495 | if (!page) | 540 | ret = -ENOMEM; |
496 | goto out_nomem; | 541 | page = page_cache_alloc_cold(mapping); |
542 | if (unlikely(!page)) | ||
543 | goto out_nomem; | ||
544 | |||
545 | /* | ||
546 | * This will also lock the page | ||
547 | */ | ||
548 | ret = add_to_page_cache_lru(page, mapping, index, | ||
549 | gfp_mask); | ||
550 | if (unlikely(ret)) | ||
551 | goto out; | ||
552 | } | ||
497 | 553 | ||
498 | /* | 554 | /* |
499 | * If the page is uptodate, it is also locked. If it isn't | 555 | * We get here with the page locked. If the page is also |
500 | * uptodate, we can mark it uptodate if we are filling the | 556 | * uptodate, we don't need to do more. If it isn't, we |
501 | * full page. Otherwise we need to read it in first... | 557 | * may need to bring it in if we are not going to overwrite |
558 | * the full page. | ||
502 | */ | 559 | */ |
503 | if (!PageUptodate(page)) { | 560 | if (!PageUptodate(page)) { |
504 | if (sd->len < PAGE_CACHE_SIZE) { | 561 | if (sd->len < PAGE_CACHE_SIZE) { |
@@ -520,10 +577,8 @@ find_page: | |||
520 | ret = -EIO; | 577 | ret = -EIO; |
521 | goto out; | 578 | goto out; |
522 | } | 579 | } |
523 | } else { | 580 | } else |
524 | WARN_ON(!PageLocked(page)); | ||
525 | SetPageUptodate(page); | 581 | SetPageUptodate(page); |
526 | } | ||
527 | } | 582 | } |
528 | } | 583 | } |
529 | 584 | ||
@@ -552,10 +607,10 @@ find_page: | |||
552 | mark_page_accessed(page); | 607 | mark_page_accessed(page); |
553 | balance_dirty_pages_ratelimited(mapping); | 608 | balance_dirty_pages_ratelimited(mapping); |
554 | out: | 609 | out: |
555 | if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) { | 610 | if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) |
556 | page_cache_release(page); | 611 | page_cache_release(page); |
557 | unlock_page(page); | 612 | |
558 | } | 613 | unlock_page(page); |
559 | out_nomem: | 614 | out_nomem: |
560 | buf->ops->unmap(info, buf); | 615 | buf->ops->unmap(info, buf); |
561 | return ret; | 616 | return ret; |
@@ -687,22 +742,26 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
687 | ssize_t ret; | 742 | ssize_t ret; |
688 | 743 | ||
689 | ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 744 | ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); |
690 | 745 | if (ret > 0) { | |
691 | /* | ||
692 | * If file or inode is SYNC and we actually wrote some data, sync it. | ||
693 | */ | ||
694 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(mapping->host)) | ||
695 | && ret > 0) { | ||
696 | struct inode *inode = mapping->host; | 746 | struct inode *inode = mapping->host; |
697 | int err; | ||
698 | 747 | ||
699 | mutex_lock(&inode->i_mutex); | 748 | *ppos += ret; |
700 | err = generic_osync_inode(mapping->host, mapping, | 749 | |
701 | OSYNC_METADATA|OSYNC_DATA); | 750 | /* |
702 | mutex_unlock(&inode->i_mutex); | 751 | * If file or inode is SYNC and we actually wrote some data, |
752 | * sync it. | ||
753 | */ | ||
754 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | ||
755 | int err; | ||
756 | |||
757 | mutex_lock(&inode->i_mutex); | ||
758 | err = generic_osync_inode(inode, mapping, | ||
759 | OSYNC_METADATA|OSYNC_DATA); | ||
760 | mutex_unlock(&inode->i_mutex); | ||
703 | 761 | ||
704 | if (err) | 762 | if (err) |
705 | ret = err; | 763 | ret = err; |
764 | } | ||
706 | } | 765 | } |
707 | 766 | ||
708 | return ret; | 767 | return ret; |
@@ -904,6 +963,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
904 | { | 963 | { |
905 | struct pipe_inode_info *pipe; | 964 | struct pipe_inode_info *pipe; |
906 | loff_t offset, *off; | 965 | loff_t offset, *off; |
966 | long ret; | ||
907 | 967 | ||
908 | pipe = in->f_dentry->d_inode->i_pipe; | 968 | pipe = in->f_dentry->d_inode->i_pipe; |
909 | if (pipe) { | 969 | if (pipe) { |
@@ -918,7 +978,12 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
918 | } else | 978 | } else |
919 | off = &out->f_pos; | 979 | off = &out->f_pos; |
920 | 980 | ||
921 | return do_splice_from(pipe, out, off, len, flags); | 981 | ret = do_splice_from(pipe, out, off, len, flags); |
982 | |||
983 | if (off_out && copy_to_user(off_out, off, sizeof(loff_t))) | ||
984 | ret = -EFAULT; | ||
985 | |||
986 | return ret; | ||
922 | } | 987 | } |
923 | 988 | ||
924 | pipe = out->f_dentry->d_inode->i_pipe; | 989 | pipe = out->f_dentry->d_inode->i_pipe; |
@@ -934,7 +999,12 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
934 | } else | 999 | } else |
935 | off = &in->f_pos; | 1000 | off = &in->f_pos; |
936 | 1001 | ||
937 | return do_splice_to(in, off, pipe, len, flags); | 1002 | ret = do_splice_to(in, off, pipe, len, flags); |
1003 | |||
1004 | if (off_in && copy_to_user(off_in, off, sizeof(loff_t))) | ||
1005 | ret = -EFAULT; | ||
1006 | |||
1007 | return ret; | ||
938 | } | 1008 | } |
939 | 1009 | ||
940 | return -EINVAL; | 1010 | return -EINVAL; |
@@ -979,7 +1049,9 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
979 | size_t len, unsigned int flags) | 1049 | size_t len, unsigned int flags) |
980 | { | 1050 | { |
981 | struct pipe_buffer *ibuf, *obuf; | 1051 | struct pipe_buffer *ibuf, *obuf; |
982 | int ret = 0, do_wakeup = 0, i; | 1052 | int ret, do_wakeup, i, ipipe_first; |
1053 | |||
1054 | ret = do_wakeup = ipipe_first = 0; | ||
983 | 1055 | ||
984 | /* | 1056 | /* |
985 | * Potential ABBA deadlock, work around it by ordering lock | 1057 | * Potential ABBA deadlock, work around it by ordering lock |
@@ -987,6 +1059,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
987 | * could deadlock (one doing tee from A -> B, the other from B -> A). | 1059 | * could deadlock (one doing tee from A -> B, the other from B -> A). |
988 | */ | 1060 | */ |
989 | if (ipipe->inode < opipe->inode) { | 1061 | if (ipipe->inode < opipe->inode) { |
1062 | ipipe_first = 1; | ||
990 | mutex_lock(&ipipe->inode->i_mutex); | 1063 | mutex_lock(&ipipe->inode->i_mutex); |
991 | mutex_lock(&opipe->inode->i_mutex); | 1064 | mutex_lock(&opipe->inode->i_mutex); |
992 | } else { | 1065 | } else { |
@@ -1035,9 +1108,11 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1035 | 1108 | ||
1036 | /* | 1109 | /* |
1037 | * We have input available, but no output room. | 1110 | * We have input available, but no output room. |
1038 | * If we already copied data, return that. | 1111 | * If we already copied data, return that. If we |
1112 | * need to drop the opipe lock, it must be ordered | ||
1113 | * last to avoid deadlocks. | ||
1039 | */ | 1114 | */ |
1040 | if (flags & SPLICE_F_NONBLOCK) { | 1115 | if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) { |
1041 | if (!ret) | 1116 | if (!ret) |
1042 | ret = -EAGAIN; | 1117 | ret = -EAGAIN; |
1043 | break; | 1118 | break; |
@@ -1071,7 +1146,12 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
1071 | if (ret) | 1146 | if (ret) |
1072 | break; | 1147 | break; |
1073 | } | 1148 | } |
1074 | if (flags & SPLICE_F_NONBLOCK) { | 1149 | /* |
1150 | * pipe_wait() drops the ipipe mutex. To avoid deadlocks | ||
1151 | * with another process, we can only safely do that if | ||
1152 | * the ipipe lock is ordered last. | ||
1153 | */ | ||
1154 | if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) { | ||
1075 | if (!ret) | 1155 | if (!ret) |
1076 | ret = -EAGAIN; | 1156 | ret = -EAGAIN; |
1077 | break; | 1157 | break; |