diff options
Diffstat (limited to 'fs')
47 files changed, 708 insertions, 218 deletions
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 22f7ccd58d38..0f628041e3f7 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -460,8 +460,10 @@ static int __init init_v9fs(void) | |||
460 | 460 | ||
461 | ret = v9fs_mux_global_init(); | 461 | ret = v9fs_mux_global_init(); |
462 | if (!ret) | 462 | if (!ret) |
463 | ret = register_filesystem(&v9fs_fs_type); | 463 | return ret; |
464 | 464 | ret = register_filesystem(&v9fs_fs_type); | |
465 | if (!ret) | ||
466 | v9fs_mux_global_exit(); | ||
465 | return ret; | 467 | return ret; |
466 | } | 468 | } |
467 | 469 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index d311198bba43..4fd9efac29ab 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -881,6 +881,19 @@ config TMPFS | |||
881 | 881 | ||
882 | See <file:Documentation/filesystems/tmpfs.txt> for details. | 882 | See <file:Documentation/filesystems/tmpfs.txt> for details. |
883 | 883 | ||
884 | config TMPFS_POSIX_ACL | ||
885 | bool "Tmpfs POSIX Access Control Lists" | ||
886 | depends on TMPFS | ||
887 | select GENERIC_ACL | ||
888 | help | ||
889 | POSIX Access Control Lists (ACLs) support permissions for users and | ||
890 | groups beyond the owner/group/world scheme. | ||
891 | |||
892 | To learn more about Access Control Lists, visit the POSIX ACLs for | ||
893 | Linux website <http://acl.bestbits.at/>. | ||
894 | |||
895 | If you don't know what Access Control Lists are, say N. | ||
896 | |||
884 | config HUGETLBFS | 897 | config HUGETLBFS |
885 | bool "HugeTLB file system support" | 898 | bool "HugeTLB file system support" |
886 | depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN | 899 | depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN |
@@ -1940,6 +1953,10 @@ config 9P_FS | |||
1940 | 1953 | ||
1941 | If unsure, say N. | 1954 | If unsure, say N. |
1942 | 1955 | ||
1956 | config GENERIC_ACL | ||
1957 | bool | ||
1958 | select FS_POSIX_ACL | ||
1959 | |||
1943 | endmenu | 1960 | endmenu |
1944 | 1961 | ||
1945 | menu "Partition Types" | 1962 | menu "Partition Types" |
diff --git a/fs/Makefile b/fs/Makefile index 89135428a539..46b8cfe497b2 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o | |||
35 | obj-$(CONFIG_FS_MBCACHE) += mbcache.o | 35 | obj-$(CONFIG_FS_MBCACHE) += mbcache.o |
36 | obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o | 36 | obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o |
37 | obj-$(CONFIG_NFS_COMMON) += nfs_common/ | 37 | obj-$(CONFIG_NFS_COMMON) += nfs_common/ |
38 | obj-$(CONFIG_GENERIC_ACL) += generic_acl.o | ||
38 | 39 | ||
39 | obj-$(CONFIG_QUOTA) += dquot.o | 40 | obj-$(CONFIG_QUOTA) += dquot.o |
40 | obj-$(CONFIG_QFMT_V1) += quota_v1.o | 41 | obj-$(CONFIG_QFMT_V1) += quota_v1.o |
diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 101d21b6c037..86463ec9ccb4 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c | |||
@@ -775,6 +775,7 @@ static int afs_proc_cell_servers_release(struct inode *inode, | |||
775 | * first item | 775 | * first item |
776 | */ | 776 | */ |
777 | static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos) | 777 | static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos) |
778 | __acquires(m->private->sv_lock) | ||
778 | { | 779 | { |
779 | struct list_head *_p; | 780 | struct list_head *_p; |
780 | struct afs_cell *cell = m->private; | 781 | struct afs_cell *cell = m->private; |
@@ -823,6 +824,7 @@ static void *afs_proc_cell_servers_next(struct seq_file *p, void *v, | |||
823 | * clean up after reading from the cells list | 824 | * clean up after reading from the cells list |
824 | */ | 825 | */ |
825 | static void afs_proc_cell_servers_stop(struct seq_file *p, void *v) | 826 | static void afs_proc_cell_servers_stop(struct seq_file *p, void *v) |
827 | __releases(p->private->sv_lock) | ||
826 | { | 828 | { |
827 | struct afs_cell *cell = p->private; | 829 | struct afs_cell *cell = p->private; |
828 | 830 | ||
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 27e17f96cada..563ef9d7da9f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -281,9 +281,6 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
281 | 281 | ||
282 | DPRINTK("mount done status=%d", status); | 282 | DPRINTK("mount done status=%d", status); |
283 | 283 | ||
284 | if (status && dentry->d_inode) | ||
285 | return status; /* Try to get the kernel to invalidate this dentry */ | ||
286 | |||
287 | /* Turn this into a real negative dentry? */ | 284 | /* Turn this into a real negative dentry? */ |
288 | if (status == -ENOENT) { | 285 | if (status == -ENOENT) { |
289 | spin_lock(&dentry->d_lock); | 286 | spin_lock(&dentry->d_lock); |
@@ -359,7 +356,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
359 | * don't try to mount it again. | 356 | * don't try to mount it again. |
360 | */ | 357 | */ |
361 | spin_lock(&dcache_lock); | 358 | spin_lock(&dcache_lock); |
362 | if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { | 359 | if (!d_mountpoint(dentry) && __simple_empty(dentry)) { |
363 | spin_unlock(&dcache_lock); | 360 | spin_unlock(&dcache_lock); |
364 | 361 | ||
365 | status = try_to_fill_dentry(dentry, 0); | 362 | status = try_to_fill_dentry(dentry, 0); |
@@ -540,6 +537,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
540 | return ERR_PTR(-ERESTARTNOINTR); | 537 | return ERR_PTR(-ERESTARTNOINTR); |
541 | } | 538 | } |
542 | } | 539 | } |
540 | spin_lock(&dentry->d_lock); | ||
541 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | ||
542 | spin_unlock(&dentry->d_lock); | ||
543 | } | 543 | } |
544 | 544 | ||
545 | /* | 545 | /* |
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index f312103434d4..517e111bb7ef 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c | |||
@@ -278,6 +278,13 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
278 | return -ENOEXEC; | 278 | return -ENOEXEC; |
279 | } | 279 | } |
280 | 280 | ||
281 | /* | ||
282 | * Requires a mmap handler. This prevents people from using a.out | ||
283 | * as part of an exploit attack against /proc-related vulnerabilities. | ||
284 | */ | ||
285 | if (!bprm->file->f_op || !bprm->file->f_op->mmap) | ||
286 | return -ENOEXEC; | ||
287 | |||
281 | fd_offset = N_TXTOFF(ex); | 288 | fd_offset = N_TXTOFF(ex); |
282 | 289 | ||
283 | /* Check initial limits. This avoids letting people circumvent | 290 | /* Check initial limits. This avoids letting people circumvent |
@@ -476,6 +483,13 @@ static int load_aout_library(struct file *file) | |||
476 | goto out; | 483 | goto out; |
477 | } | 484 | } |
478 | 485 | ||
486 | /* | ||
487 | * Requires a mmap handler. This prevents people from using a.out | ||
488 | * as part of an exploit attack against /proc-related vulnerabilities. | ||
489 | */ | ||
490 | if (!file->f_op || !file->f_op->mmap) | ||
491 | goto out; | ||
492 | |||
479 | if (N_FLAGS(ex)) | 493 | if (N_FLAGS(ex)) |
480 | goto out; | 494 | goto out; |
481 | 495 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index dfd8cfb7fb5d..6eb48e1446ec 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1038,10 +1038,8 @@ out_free_interp: | |||
1038 | out_free_file: | 1038 | out_free_file: |
1039 | sys_close(elf_exec_fileno); | 1039 | sys_close(elf_exec_fileno); |
1040 | out_free_fh: | 1040 | out_free_fh: |
1041 | if (files) { | 1041 | if (files) |
1042 | put_files_struct(current->files); | 1042 | reset_files_struct(current, files); |
1043 | current->files = files; | ||
1044 | } | ||
1045 | out_free_ph: | 1043 | out_free_ph: |
1046 | kfree(elf_phdata); | 1044 | kfree(elf_phdata); |
1047 | goto out; | 1045 | goto out; |
@@ -1481,20 +1479,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
1481 | 1479 | ||
1482 | if (signr) { | 1480 | if (signr) { |
1483 | struct elf_thread_status *tmp; | 1481 | struct elf_thread_status *tmp; |
1484 | read_lock(&tasklist_lock); | 1482 | rcu_read_lock(); |
1485 | do_each_thread(g,p) | 1483 | do_each_thread(g,p) |
1486 | if (current->mm == p->mm && current != p) { | 1484 | if (current->mm == p->mm && current != p) { |
1487 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); | 1485 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); |
1488 | if (!tmp) { | 1486 | if (!tmp) { |
1489 | read_unlock(&tasklist_lock); | 1487 | rcu_read_unlock(); |
1490 | goto cleanup; | 1488 | goto cleanup; |
1491 | } | 1489 | } |
1492 | INIT_LIST_HEAD(&tmp->list); | ||
1493 | tmp->thread = p; | 1490 | tmp->thread = p; |
1494 | list_add(&tmp->list, &thread_list); | 1491 | list_add(&tmp->list, &thread_list); |
1495 | } | 1492 | } |
1496 | while_each_thread(g,p); | 1493 | while_each_thread(g,p); |
1497 | read_unlock(&tasklist_lock); | 1494 | rcu_read_unlock(); |
1498 | list_for_each(t, &thread_list) { | 1495 | list_for_each(t, &thread_list) { |
1499 | struct elf_thread_status *tmp; | 1496 | struct elf_thread_status *tmp; |
1500 | int sz; | 1497 | int sz; |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 2f3365829229..f86d5c9ce5eb 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -1597,20 +1597,19 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs, | |||
1597 | 1597 | ||
1598 | if (signr) { | 1598 | if (signr) { |
1599 | struct elf_thread_status *tmp; | 1599 | struct elf_thread_status *tmp; |
1600 | read_lock(&tasklist_lock); | 1600 | rcu_read_lock(); |
1601 | do_each_thread(g,p) | 1601 | do_each_thread(g,p) |
1602 | if (current->mm == p->mm && current != p) { | 1602 | if (current->mm == p->mm && current != p) { |
1603 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); | 1603 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); |
1604 | if (!tmp) { | 1604 | if (!tmp) { |
1605 | read_unlock(&tasklist_lock); | 1605 | rcu_read_unlock(); |
1606 | goto cleanup; | 1606 | goto cleanup; |
1607 | } | 1607 | } |
1608 | INIT_LIST_HEAD(&tmp->list); | ||
1609 | tmp->thread = p; | 1608 | tmp->thread = p; |
1610 | list_add(&tmp->list, &thread_list); | 1609 | list_add(&tmp->list, &thread_list); |
1611 | } | 1610 | } |
1612 | while_each_thread(g,p); | 1611 | while_each_thread(g,p); |
1613 | read_unlock(&tasklist_lock); | 1612 | rcu_read_unlock(); |
1614 | list_for_each(t, &thread_list) { | 1613 | list_for_each(t, &thread_list) { |
1615 | struct elf_thread_status *tmp; | 1614 | struct elf_thread_status *tmp; |
1616 | int sz; | 1615 | int sz; |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 66ba137f8661..1713c48fef54 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -215,10 +215,8 @@ _error: | |||
215 | bprm->interp_flags = 0; | 215 | bprm->interp_flags = 0; |
216 | bprm->interp_data = 0; | 216 | bprm->interp_data = 0; |
217 | _unshare: | 217 | _unshare: |
218 | if (files) { | 218 | if (files) |
219 | put_files_struct(current->files); | 219 | reset_files_struct(current, files); |
220 | current->files = files; | ||
221 | } | ||
222 | goto _ret; | 220 | goto _ret; |
223 | } | 221 | } |
224 | 222 | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 045f98854f14..4346468139e8 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -543,11 +543,11 @@ static struct kobject *bdev_get_holder(struct block_device *bdev) | |||
543 | return kobject_get(bdev->bd_disk->holder_dir); | 543 | return kobject_get(bdev->bd_disk->holder_dir); |
544 | } | 544 | } |
545 | 545 | ||
546 | static void add_symlink(struct kobject *from, struct kobject *to) | 546 | static int add_symlink(struct kobject *from, struct kobject *to) |
547 | { | 547 | { |
548 | if (!from || !to) | 548 | if (!from || !to) |
549 | return; | 549 | return 0; |
550 | sysfs_create_link(from, to, kobject_name(to)); | 550 | return sysfs_create_link(from, to, kobject_name(to)); |
551 | } | 551 | } |
552 | 552 | ||
553 | static void del_symlink(struct kobject *from, struct kobject *to) | 553 | static void del_symlink(struct kobject *from, struct kobject *to) |
@@ -648,30 +648,38 @@ static void free_bd_holder(struct bd_holder *bo) | |||
648 | * If there is no matching entry with @bo in @bdev->bd_holder_list, | 648 | * If there is no matching entry with @bo in @bdev->bd_holder_list, |
649 | * add @bo to the list, create symlinks. | 649 | * add @bo to the list, create symlinks. |
650 | * | 650 | * |
651 | * Returns 1 if @bo was added to the list. | 651 | * Returns 0 if symlinks are created or already there. |
652 | * Returns 0 if @bo wasn't used by any reason and should be freed. | 652 | * Returns -ve if something fails and @bo can be freed. |
653 | */ | 653 | */ |
654 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | 654 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) |
655 | { | 655 | { |
656 | struct bd_holder *tmp; | 656 | struct bd_holder *tmp; |
657 | int ret; | ||
657 | 658 | ||
658 | if (!bo) | 659 | if (!bo) |
659 | return 0; | 660 | return -EINVAL; |
660 | 661 | ||
661 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) { | 662 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) { |
662 | if (tmp->sdir == bo->sdir) { | 663 | if (tmp->sdir == bo->sdir) { |
663 | tmp->count++; | 664 | tmp->count++; |
665 | /* We've already done what we need to do here. */ | ||
666 | free_bd_holder(bo); | ||
664 | return 0; | 667 | return 0; |
665 | } | 668 | } |
666 | } | 669 | } |
667 | 670 | ||
668 | if (!bd_holder_grab_dirs(bdev, bo)) | 671 | if (!bd_holder_grab_dirs(bdev, bo)) |
669 | return 0; | 672 | return -EBUSY; |
670 | 673 | ||
671 | add_symlink(bo->sdir, bo->sdev); | 674 | ret = add_symlink(bo->sdir, bo->sdev); |
672 | add_symlink(bo->hdir, bo->hdev); | 675 | if (ret == 0) { |
673 | list_add_tail(&bo->list, &bdev->bd_holder_list); | 676 | ret = add_symlink(bo->hdir, bo->hdev); |
674 | return 1; | 677 | if (ret) |
678 | del_symlink(bo->sdir, bo->sdev); | ||
679 | } | ||
680 | if (ret == 0) | ||
681 | list_add_tail(&bo->list, &bdev->bd_holder_list); | ||
682 | return ret; | ||
675 | } | 683 | } |
676 | 684 | ||
677 | /** | 685 | /** |
@@ -741,7 +749,9 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
741 | 749 | ||
742 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); | 750 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); |
743 | res = bd_claim(bdev, holder); | 751 | res = bd_claim(bdev, holder); |
744 | if (res || !add_bd_holder(bdev, bo)) | 752 | if (res == 0) |
753 | res = add_bd_holder(bdev, bo); | ||
754 | if (res) | ||
745 | free_bd_holder(bo); | 755 | free_bd_holder(bo); |
746 | mutex_unlock(&bdev->bd_mutex); | 756 | mutex_unlock(&bdev->bd_mutex); |
747 | 757 | ||
@@ -1021,7 +1031,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | |||
1021 | rescan_partitions(bdev->bd_disk, bdev); | 1031 | rescan_partitions(bdev->bd_disk, bdev); |
1022 | } else { | 1032 | } else { |
1023 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, | 1033 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, |
1024 | BD_MUTEX_PARTITION); | 1034 | BD_MUTEX_WHOLE); |
1025 | bdev->bd_contains->bd_part_count++; | 1035 | bdev->bd_contains->bd_part_count++; |
1026 | mutex_unlock(&bdev->bd_contains->bd_mutex); | 1036 | mutex_unlock(&bdev->bd_contains->bd_mutex); |
1027 | } | 1037 | } |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 0009346d827f..1f3285affa39 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -128,13 +128,31 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, | |||
128 | 128 | ||
129 | for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) | 129 | for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) |
130 | if ((*cp)->major > major || | 130 | if ((*cp)->major > major || |
131 | ((*cp)->major == major && (*cp)->baseminor >= baseminor)) | 131 | ((*cp)->major == major && |
132 | (((*cp)->baseminor >= baseminor) || | ||
133 | ((*cp)->baseminor + (*cp)->minorct > baseminor)))) | ||
132 | break; | 134 | break; |
133 | if (*cp && (*cp)->major == major && | 135 | |
134 | (*cp)->baseminor < baseminor + minorct) { | 136 | /* Check for overlapping minor ranges. */ |
135 | ret = -EBUSY; | 137 | if (*cp && (*cp)->major == major) { |
136 | goto out; | 138 | int old_min = (*cp)->baseminor; |
139 | int old_max = (*cp)->baseminor + (*cp)->minorct - 1; | ||
140 | int new_min = baseminor; | ||
141 | int new_max = baseminor + minorct - 1; | ||
142 | |||
143 | /* New driver overlaps from the left. */ | ||
144 | if (new_max >= old_min && new_max <= old_max) { | ||
145 | ret = -EBUSY; | ||
146 | goto out; | ||
147 | } | ||
148 | |||
149 | /* New driver overlaps from the right. */ | ||
150 | if (new_min <= old_max && new_min >= old_min) { | ||
151 | ret = -EBUSY; | ||
152 | goto out; | ||
153 | } | ||
137 | } | 154 | } |
155 | |||
138 | cd->next = *cp; | 156 | cd->next = *cp; |
139 | *cp = cd; | 157 | *cp = cd; |
140 | mutex_unlock(&chrdevs_lock); | 158 | mutex_unlock(&chrdevs_lock); |
@@ -165,6 +183,15 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct) | |||
165 | return cd; | 183 | return cd; |
166 | } | 184 | } |
167 | 185 | ||
186 | /** | ||
187 | * register_chrdev_region() - register a range of device numbers | ||
188 | * @from: the first in the desired range of device numbers; must include | ||
189 | * the major number. | ||
190 | * @count: the number of consecutive device numbers required | ||
191 | * @name: the name of the device or driver. | ||
192 | * | ||
193 | * Return value is zero on success, a negative error code on failure. | ||
194 | */ | ||
168 | int register_chrdev_region(dev_t from, unsigned count, const char *name) | 195 | int register_chrdev_region(dev_t from, unsigned count, const char *name) |
169 | { | 196 | { |
170 | struct char_device_struct *cd; | 197 | struct char_device_struct *cd; |
@@ -190,6 +217,17 @@ fail: | |||
190 | return PTR_ERR(cd); | 217 | return PTR_ERR(cd); |
191 | } | 218 | } |
192 | 219 | ||
220 | /** | ||
221 | * alloc_chrdev_region() - register a range of char device numbers | ||
222 | * @dev: output parameter for first assigned number | ||
223 | * @baseminor: first of the requested range of minor numbers | ||
224 | * @count: the number of minor numbers required | ||
225 | * @name: the name of the associated device or driver | ||
226 | * | ||
227 | * Allocates a range of char device numbers. The major number will be | ||
228 | * chosen dynamically, and returned (along with the first minor number) | ||
229 | * in @dev. Returns zero or a negative error code. | ||
230 | */ | ||
193 | int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | 231 | int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, |
194 | const char *name) | 232 | const char *name) |
195 | { | 233 | { |
@@ -259,6 +297,15 @@ out2: | |||
259 | return err; | 297 | return err; |
260 | } | 298 | } |
261 | 299 | ||
300 | /** | ||
301 | * unregister_chrdev_region() - return a range of device numbers | ||
302 | * @from: the first in the range of numbers to unregister | ||
303 | * @count: the number of device numbers to unregister | ||
304 | * | ||
305 | * This function will unregister a range of @count device numbers, | ||
306 | * starting with @from. The caller should normally be the one who | ||
307 | * allocated those numbers in the first place... | ||
308 | */ | ||
262 | void unregister_chrdev_region(dev_t from, unsigned count) | 309 | void unregister_chrdev_region(dev_t from, unsigned count) |
263 | { | 310 | { |
264 | dev_t to = from + count; | 311 | dev_t to = from + count; |
@@ -396,6 +443,16 @@ static int exact_lock(dev_t dev, void *data) | |||
396 | return cdev_get(p) ? 0 : -1; | 443 | return cdev_get(p) ? 0 : -1; |
397 | } | 444 | } |
398 | 445 | ||
446 | /** | ||
447 | * cdev_add() - add a char device to the system | ||
448 | * @p: the cdev structure for the device | ||
449 | * @dev: the first device number for which this device is responsible | ||
450 | * @count: the number of consecutive minor numbers corresponding to this | ||
451 | * device | ||
452 | * | ||
453 | * cdev_add() adds the device represented by @p to the system, making it | ||
454 | * live immediately. A negative error code is returned on failure. | ||
455 | */ | ||
399 | int cdev_add(struct cdev *p, dev_t dev, unsigned count) | 456 | int cdev_add(struct cdev *p, dev_t dev, unsigned count) |
400 | { | 457 | { |
401 | p->dev = dev; | 458 | p->dev = dev; |
@@ -408,6 +465,13 @@ static void cdev_unmap(dev_t dev, unsigned count) | |||
408 | kobj_unmap(cdev_map, dev, count); | 465 | kobj_unmap(cdev_map, dev, count); |
409 | } | 466 | } |
410 | 467 | ||
468 | /** | ||
469 | * cdev_del() - remove a cdev from the system | ||
470 | * @p: the cdev structure to be removed | ||
471 | * | ||
472 | * cdev_del() removes @p from the system, possibly freeing the structure | ||
473 | * itself. | ||
474 | */ | ||
411 | void cdev_del(struct cdev *p) | 475 | void cdev_del(struct cdev *p) |
412 | { | 476 | { |
413 | cdev_unmap(p->dev, p->count); | 477 | cdev_unmap(p->dev, p->count); |
@@ -436,6 +500,11 @@ static struct kobj_type ktype_cdev_dynamic = { | |||
436 | .release = cdev_dynamic_release, | 500 | .release = cdev_dynamic_release, |
437 | }; | 501 | }; |
438 | 502 | ||
503 | /** | ||
504 | * cdev_alloc() - allocate a cdev structure | ||
505 | * | ||
506 | * Allocates and returns a cdev structure, or NULL on failure. | ||
507 | */ | ||
439 | struct cdev *cdev_alloc(void) | 508 | struct cdev *cdev_alloc(void) |
440 | { | 509 | { |
441 | struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); | 510 | struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); |
@@ -447,6 +516,14 @@ struct cdev *cdev_alloc(void) | |||
447 | return p; | 516 | return p; |
448 | } | 517 | } |
449 | 518 | ||
519 | /** | ||
520 | * cdev_init() - initialize a cdev structure | ||
521 | * @cdev: the structure to initialize | ||
522 | * @fops: the file_operations for this device | ||
523 | * | ||
524 | * Initializes @cdev, remembering @fops, making it ready to add to the | ||
525 | * system with cdev_add(). | ||
526 | */ | ||
450 | void cdev_init(struct cdev *cdev, const struct file_operations *fops) | 527 | void cdev_init(struct cdev *cdev, const struct file_operations *fops) |
451 | { | 528 | { |
452 | memset(cdev, 0, sizeof *cdev); | 529 | memset(cdev, 0, sizeof *cdev); |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index ad96b6990715..a624c3ec8189 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -543,8 +543,15 @@ static struct file_system_type cramfs_fs_type = { | |||
543 | 543 | ||
544 | static int __init init_cramfs_fs(void) | 544 | static int __init init_cramfs_fs(void) |
545 | { | 545 | { |
546 | cramfs_uncompress_init(); | 546 | int rv; |
547 | return register_filesystem(&cramfs_fs_type); | 547 | |
548 | rv = cramfs_uncompress_init(); | ||
549 | if (rv < 0) | ||
550 | return rv; | ||
551 | rv = register_filesystem(&cramfs_fs_type); | ||
552 | if (rv < 0) | ||
553 | cramfs_uncompress_exit(); | ||
554 | return rv; | ||
548 | } | 555 | } |
549 | 556 | ||
550 | static void __exit exit_cramfs_fs(void) | 557 | static void __exit exit_cramfs_fs(void) |
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index 8def89f2c438..fc3ccb74626f 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c | |||
@@ -68,11 +68,10 @@ int cramfs_uncompress_init(void) | |||
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | 70 | ||
71 | int cramfs_uncompress_exit(void) | 71 | void cramfs_uncompress_exit(void) |
72 | { | 72 | { |
73 | if (!--initialized) { | 73 | if (!--initialized) { |
74 | zlib_inflateEnd(&stream); | 74 | zlib_inflateEnd(&stream); |
75 | vfree(stream.workspace); | 75 | vfree(stream.workspace); |
76 | } | 76 | } |
77 | return 0; | ||
78 | } | 77 | } |
diff --git a/fs/dquot.c b/fs/dquot.c index 0122a279106a..9af789567e51 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -834,6 +834,9 @@ static void print_warning(struct dquot *dquot, const char warntype) | |||
834 | if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags))) | 834 | if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags))) |
835 | return; | 835 | return; |
836 | 836 | ||
837 | mutex_lock(&tty_mutex); | ||
838 | if (!current->signal->tty) | ||
839 | goto out_lock; | ||
837 | tty_write_message(current->signal->tty, dquot->dq_sb->s_id); | 840 | tty_write_message(current->signal->tty, dquot->dq_sb->s_id); |
838 | if (warntype == ISOFTWARN || warntype == BSOFTWARN) | 841 | if (warntype == ISOFTWARN || warntype == BSOFTWARN) |
839 | tty_write_message(current->signal->tty, ": warning, "); | 842 | tty_write_message(current->signal->tty, ": warning, "); |
@@ -861,6 +864,8 @@ static void print_warning(struct dquot *dquot, const char warntype) | |||
861 | break; | 864 | break; |
862 | } | 865 | } |
863 | tty_write_message(current->signal->tty, msg); | 866 | tty_write_message(current->signal->tty, msg); |
867 | out_lock: | ||
868 | mutex_unlock(&tty_mutex); | ||
864 | } | 869 | } |
865 | 870 | ||
866 | static inline void flush_warnings(struct dquot **dquots, char *warntype) | 871 | static inline void flush_warnings(struct dquot **dquots, char *warntype) |
@@ -898,8 +898,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
898 | return 0; | 898 | return 0; |
899 | 899 | ||
900 | mmap_failed: | 900 | mmap_failed: |
901 | put_files_struct(current->files); | 901 | reset_files_struct(current, files); |
902 | current->files = files; | ||
903 | out: | 902 | out: |
904 | return retval; | 903 | return retval; |
905 | } | 904 | } |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 1ee25232e6af..d50fc47169c1 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/writeback.h> | 15 | #include <linux/writeback.h> |
16 | #include <linux/blkdev.h> | ||
16 | 17 | ||
17 | int fat_generic_ioctl(struct inode *inode, struct file *filp, | 18 | int fat_generic_ioctl(struct inode *inode, struct file *filp, |
18 | unsigned int cmd, unsigned long arg) | 19 | unsigned int cmd, unsigned long arg) |
@@ -112,6 +113,16 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
112 | } | 113 | } |
113 | } | 114 | } |
114 | 115 | ||
116 | static int fat_file_release(struct inode *inode, struct file *filp) | ||
117 | { | ||
118 | if ((filp->f_mode & FMODE_WRITE) && | ||
119 | MSDOS_SB(inode->i_sb)->options.flush) { | ||
120 | fat_flush_inodes(inode->i_sb, inode, NULL); | ||
121 | blk_congestion_wait(WRITE, HZ/10); | ||
122 | } | ||
123 | return 0; | ||
124 | } | ||
125 | |||
115 | const struct file_operations fat_file_operations = { | 126 | const struct file_operations fat_file_operations = { |
116 | .llseek = generic_file_llseek, | 127 | .llseek = generic_file_llseek, |
117 | .read = do_sync_read, | 128 | .read = do_sync_read, |
@@ -121,6 +132,7 @@ const struct file_operations fat_file_operations = { | |||
121 | .aio_read = generic_file_aio_read, | 132 | .aio_read = generic_file_aio_read, |
122 | .aio_write = generic_file_aio_write, | 133 | .aio_write = generic_file_aio_write, |
123 | .mmap = generic_file_mmap, | 134 | .mmap = generic_file_mmap, |
135 | .release = fat_file_release, | ||
124 | .ioctl = fat_generic_ioctl, | 136 | .ioctl = fat_generic_ioctl, |
125 | .fsync = file_fsync, | 137 | .fsync = file_fsync, |
126 | .sendfile = generic_file_sendfile, | 138 | .sendfile = generic_file_sendfile, |
@@ -289,6 +301,7 @@ void fat_truncate(struct inode *inode) | |||
289 | lock_kernel(); | 301 | lock_kernel(); |
290 | fat_free(inode, nr_clusters); | 302 | fat_free(inode, nr_clusters); |
291 | unlock_kernel(); | 303 | unlock_kernel(); |
304 | fat_flush_inodes(inode->i_sb, inode, NULL); | ||
292 | } | 305 | } |
293 | 306 | ||
294 | struct inode_operations fat_file_inode_operations = { | 307 | struct inode_operations fat_file_inode_operations = { |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index ab96ae823753..045738032a83 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/vfs.h> | 24 | #include <linux/vfs.h> |
25 | #include <linux/parser.h> | 25 | #include <linux/parser.h> |
26 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
27 | #include <linux/writeback.h> | ||
27 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
28 | 29 | ||
29 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET | 30 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET |
@@ -853,7 +854,7 @@ enum { | |||
853 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 854 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
854 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 855 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
855 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 856 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
856 | Opt_obsolate, Opt_err, | 857 | Opt_obsolate, Opt_flush, Opt_err, |
857 | }; | 858 | }; |
858 | 859 | ||
859 | static match_table_t fat_tokens = { | 860 | static match_table_t fat_tokens = { |
@@ -885,7 +886,8 @@ static match_table_t fat_tokens = { | |||
885 | {Opt_obsolate, "cvf_format=%20s"}, | 886 | {Opt_obsolate, "cvf_format=%20s"}, |
886 | {Opt_obsolate, "cvf_options=%100s"}, | 887 | {Opt_obsolate, "cvf_options=%100s"}, |
887 | {Opt_obsolate, "posix"}, | 888 | {Opt_obsolate, "posix"}, |
888 | {Opt_err, NULL} | 889 | {Opt_flush, "flush"}, |
890 | {Opt_err, NULL}, | ||
889 | }; | 891 | }; |
890 | static match_table_t msdos_tokens = { | 892 | static match_table_t msdos_tokens = { |
891 | {Opt_nodots, "nodots"}, | 893 | {Opt_nodots, "nodots"}, |
@@ -1026,6 +1028,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
1026 | return 0; | 1028 | return 0; |
1027 | opts->codepage = option; | 1029 | opts->codepage = option; |
1028 | break; | 1030 | break; |
1031 | case Opt_flush: | ||
1032 | opts->flush = 1; | ||
1033 | break; | ||
1029 | 1034 | ||
1030 | /* msdos specific */ | 1035 | /* msdos specific */ |
1031 | case Opt_dots: | 1036 | case Opt_dots: |
@@ -1425,6 +1430,56 @@ out_fail: | |||
1425 | 1430 | ||
1426 | EXPORT_SYMBOL_GPL(fat_fill_super); | 1431 | EXPORT_SYMBOL_GPL(fat_fill_super); |
1427 | 1432 | ||
1433 | /* | ||
1434 | * helper function for fat_flush_inodes. This writes both the inode | ||
1435 | * and the file data blocks, waiting for in flight data blocks before | ||
1436 | * the start of the call. It does not wait for any io started | ||
1437 | * during the call | ||
1438 | */ | ||
1439 | static int writeback_inode(struct inode *inode) | ||
1440 | { | ||
1441 | |||
1442 | int ret; | ||
1443 | struct address_space *mapping = inode->i_mapping; | ||
1444 | struct writeback_control wbc = { | ||
1445 | .sync_mode = WB_SYNC_NONE, | ||
1446 | .nr_to_write = 0, | ||
1447 | }; | ||
1448 | /* if we used WB_SYNC_ALL, sync_inode waits for the io for the | ||
1449 | * inode to finish. So WB_SYNC_NONE is sent down to sync_inode | ||
1450 | * and filemap_fdatawrite is used for the data blocks | ||
1451 | */ | ||
1452 | ret = sync_inode(inode, &wbc); | ||
1453 | if (!ret) | ||
1454 | ret = filemap_fdatawrite(mapping); | ||
1455 | return ret; | ||
1456 | } | ||
1457 | |||
1458 | /* | ||
1459 | * write data and metadata corresponding to i1 and i2. The io is | ||
1460 | * started but we do not wait for any of it to finish. | ||
1461 | * | ||
1462 | * filemap_flush is used for the block device, so if there is a dirty | ||
1463 | * page for a block already in flight, we will not wait and start the | ||
1464 | * io over again | ||
1465 | */ | ||
1466 | int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2) | ||
1467 | { | ||
1468 | int ret = 0; | ||
1469 | if (!MSDOS_SB(sb)->options.flush) | ||
1470 | return 0; | ||
1471 | if (i1) | ||
1472 | ret = writeback_inode(i1); | ||
1473 | if (!ret && i2) | ||
1474 | ret = writeback_inode(i2); | ||
1475 | if (!ret && sb) { | ||
1476 | struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping; | ||
1477 | ret = filemap_flush(mapping); | ||
1478 | } | ||
1479 | return ret; | ||
1480 | } | ||
1481 | EXPORT_SYMBOL_GPL(fat_flush_inodes); | ||
1482 | |||
1428 | static int __init init_fat_fs(void) | 1483 | static int __init init_fat_fs(void) |
1429 | { | 1484 | { |
1430 | int err; | 1485 | int err; |
@@ -288,71 +288,63 @@ out: | |||
288 | } | 288 | } |
289 | 289 | ||
290 | /* | 290 | /* |
291 | * Expands the file descriptor table - it will allocate a new fdtable and | 291 | * Expand the file descriptor table. |
292 | * both fd array and fdset. It is expected to be called with the | 292 | * This function will allocate a new fdtable and both fd array and fdset, of |
293 | * files_lock held. | 293 | * the given size. |
294 | * Return <0 error code on error; 1 on successful completion. | ||
295 | * The files->file_lock should be held on entry, and will be held on exit. | ||
294 | */ | 296 | */ |
295 | static int expand_fdtable(struct files_struct *files, int nr) | 297 | static int expand_fdtable(struct files_struct *files, int nr) |
296 | __releases(files->file_lock) | 298 | __releases(files->file_lock) |
297 | __acquires(files->file_lock) | 299 | __acquires(files->file_lock) |
298 | { | 300 | { |
299 | int error = 0; | 301 | struct fdtable *new_fdt, *cur_fdt; |
300 | struct fdtable *fdt; | ||
301 | struct fdtable *nfdt = NULL; | ||
302 | 302 | ||
303 | spin_unlock(&files->file_lock); | 303 | spin_unlock(&files->file_lock); |
304 | nfdt = alloc_fdtable(nr); | 304 | new_fdt = alloc_fdtable(nr); |
305 | if (!nfdt) { | ||
306 | error = -ENOMEM; | ||
307 | spin_lock(&files->file_lock); | ||
308 | goto out; | ||
309 | } | ||
310 | |||
311 | spin_lock(&files->file_lock); | 305 | spin_lock(&files->file_lock); |
312 | fdt = files_fdtable(files); | 306 | if (!new_fdt) |
307 | return -ENOMEM; | ||
313 | /* | 308 | /* |
314 | * Check again since another task may have expanded the | 309 | * Check again since another task may have expanded the fd table while |
315 | * fd table while we dropped the lock | 310 | * we dropped the lock |
316 | */ | 311 | */ |
317 | if (nr >= fdt->max_fds || nr >= fdt->max_fdset) { | 312 | cur_fdt = files_fdtable(files); |
318 | copy_fdtable(nfdt, fdt); | 313 | if (nr >= cur_fdt->max_fds || nr >= cur_fdt->max_fdset) { |
314 | /* Continue as planned */ | ||
315 | copy_fdtable(new_fdt, cur_fdt); | ||
316 | rcu_assign_pointer(files->fdt, new_fdt); | ||
317 | free_fdtable(cur_fdt); | ||
319 | } else { | 318 | } else { |
320 | /* Somebody expanded while we dropped file_lock */ | 319 | /* Somebody else expanded, so undo our attempt */ |
321 | spin_unlock(&files->file_lock); | 320 | __free_fdtable(new_fdt); |
322 | __free_fdtable(nfdt); | ||
323 | spin_lock(&files->file_lock); | ||
324 | goto out; | ||
325 | } | 321 | } |
326 | rcu_assign_pointer(files->fdt, nfdt); | 322 | return 1; |
327 | free_fdtable(fdt); | ||
328 | out: | ||
329 | return error; | ||
330 | } | 323 | } |
331 | 324 | ||
332 | /* | 325 | /* |
333 | * Expand files. | 326 | * Expand files. |
334 | * Return <0 on error; 0 nothing done; 1 files expanded, we may have blocked. | 327 | * This function will expand the file structures, if the requested size exceeds |
335 | * Should be called with the files->file_lock spinlock held for write. | 328 | * the current capacity and there is room for expansion. |
329 | * Return <0 error code on error; 0 when nothing done; 1 when files were | ||
330 | * expanded and execution may have blocked. | ||
331 | * The files->file_lock should be held on entry, and will be held on exit. | ||
336 | */ | 332 | */ |
337 | int expand_files(struct files_struct *files, int nr) | 333 | int expand_files(struct files_struct *files, int nr) |
338 | { | 334 | { |
339 | int err, expand = 0; | ||
340 | struct fdtable *fdt; | 335 | struct fdtable *fdt; |
341 | 336 | ||
342 | fdt = files_fdtable(files); | 337 | fdt = files_fdtable(files); |
343 | if (nr >= fdt->max_fdset || nr >= fdt->max_fds) { | 338 | /* Do we need to expand? */ |
344 | if (fdt->max_fdset >= NR_OPEN || | 339 | if (nr < fdt->max_fdset && nr < fdt->max_fds) |
345 | fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) { | 340 | return 0; |
346 | err = -EMFILE; | 341 | /* Can we expand? */ |
347 | goto out; | 342 | if (fdt->max_fdset >= NR_OPEN || fdt->max_fds >= NR_OPEN || |
348 | } | 343 | nr >= NR_OPEN) |
349 | expand = 1; | 344 | return -EMFILE; |
350 | if ((err = expand_fdtable(files, nr))) | 345 | |
351 | goto out; | 346 | /* All good, so we try */ |
352 | } | 347 | return expand_fdtable(files, nr); |
353 | err = expand; | ||
354 | out: | ||
355 | return err; | ||
356 | } | 348 | } |
357 | 349 | ||
358 | static void __devinit fdtable_defer_list_init(int cpu) | 350 | static void __devinit fdtable_defer_list_init(int cpu) |
diff --git a/fs/filesystems.c b/fs/filesystems.c index 9f1072836c8e..e3fa77c6ed56 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
@@ -69,8 +69,6 @@ int register_filesystem(struct file_system_type * fs) | |||
69 | int res = 0; | 69 | int res = 0; |
70 | struct file_system_type ** p; | 70 | struct file_system_type ** p; |
71 | 71 | ||
72 | if (!fs) | ||
73 | return -EINVAL; | ||
74 | if (fs->next) | 72 | if (fs->next) |
75 | return -EBUSY; | 73 | return -EBUSY; |
76 | INIT_LIST_HEAD(&fs->fs_supers); | 74 | INIT_LIST_HEAD(&fs->fs_supers); |
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index b74b791fc23b..ac28b0835ffc 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -260,12 +260,17 @@ static struct file_system_type vxfs_fs_type = { | |||
260 | static int __init | 260 | static int __init |
261 | vxfs_init(void) | 261 | vxfs_init(void) |
262 | { | 262 | { |
263 | int rv; | ||
264 | |||
263 | vxfs_inode_cachep = kmem_cache_create("vxfs_inode", | 265 | vxfs_inode_cachep = kmem_cache_create("vxfs_inode", |
264 | sizeof(struct vxfs_inode_info), 0, | 266 | sizeof(struct vxfs_inode_info), 0, |
265 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL, NULL); | 267 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL, NULL); |
266 | if (vxfs_inode_cachep) | 268 | if (!vxfs_inode_cachep) |
267 | return register_filesystem(&vxfs_fs_type); | 269 | return -ENOMEM; |
268 | return -ENOMEM; | 270 | rv = register_filesystem(&vxfs_fs_type); |
271 | if (rv < 0) | ||
272 | kmem_cache_destroy(vxfs_inode_cachep); | ||
273 | return rv; | ||
269 | } | 274 | } |
270 | 275 | ||
271 | static void __exit | 276 | static void __exit |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 1e2006caf158..4fc557c40cc0 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -212,6 +212,7 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) | |||
212 | * Called with fc->lock, unlocks it | 212 | * Called with fc->lock, unlocks it |
213 | */ | 213 | */ |
214 | static void request_end(struct fuse_conn *fc, struct fuse_req *req) | 214 | static void request_end(struct fuse_conn *fc, struct fuse_req *req) |
215 | __releases(fc->lock) | ||
215 | { | 216 | { |
216 | void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; | 217 | void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; |
217 | req->end = NULL; | 218 | req->end = NULL; |
@@ -640,6 +641,7 @@ static void request_wait(struct fuse_conn *fc) | |||
640 | */ | 641 | */ |
641 | static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req, | 642 | static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req, |
642 | const struct iovec *iov, unsigned long nr_segs) | 643 | const struct iovec *iov, unsigned long nr_segs) |
644 | __releases(fc->lock) | ||
643 | { | 645 | { |
644 | struct fuse_copy_state cs; | 646 | struct fuse_copy_state cs; |
645 | struct fuse_in_header ih; | 647 | struct fuse_in_header ih; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 409ce6a7cca4..f85b2a282f13 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -776,7 +776,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
776 | if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) | 776 | if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) |
777 | return -EACCES; | 777 | return -EACCES; |
778 | 778 | ||
779 | if (nd && (nd->flags & LOOKUP_ACCESS)) | 779 | if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) |
780 | return fuse_access(inode, mask); | 780 | return fuse_access(inode, mask); |
781 | return 0; | 781 | return 0; |
782 | } | 782 | } |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index cb7cadb0b790..7d0a9aee01f2 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -251,6 +251,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
251 | memset(&outarg, 0, sizeof(outarg)); | 251 | memset(&outarg, 0, sizeof(outarg)); |
252 | req->in.numargs = 0; | 252 | req->in.numargs = 0; |
253 | req->in.h.opcode = FUSE_STATFS; | 253 | req->in.h.opcode = FUSE_STATFS; |
254 | req->in.h.nodeid = get_node_id(dentry->d_inode); | ||
254 | req->out.numargs = 1; | 255 | req->out.numargs = 1; |
255 | req->out.args[0].size = | 256 | req->out.args[0].size = |
256 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); | 257 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); |
diff --git a/fs/generic_acl.c b/fs/generic_acl.c new file mode 100644 index 000000000000..9ccb78947171 --- /dev/null +++ b/fs/generic_acl.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * fs/generic_acl.c | ||
3 | * | ||
4 | * (C) 2005 Andreas Gruenbacher <agruen@suse.de> | ||
5 | * | ||
6 | * This file is released under the GPL. | ||
7 | */ | ||
8 | |||
9 | #include <linux/sched.h> | ||
10 | #include <linux/fs.h> | ||
11 | #include <linux/generic_acl.h> | ||
12 | |||
13 | /** | ||
14 | * generic_acl_list - Generic xattr_handler->list() operation | ||
15 | * @ops: Filesystem specific getacl and setacl callbacks | ||
16 | */ | ||
17 | size_t | ||
18 | generic_acl_list(struct inode *inode, struct generic_acl_operations *ops, | ||
19 | int type, char *list, size_t list_size) | ||
20 | { | ||
21 | struct posix_acl *acl; | ||
22 | const char *name; | ||
23 | size_t size; | ||
24 | |||
25 | acl = ops->getacl(inode, type); | ||
26 | if (!acl) | ||
27 | return 0; | ||
28 | posix_acl_release(acl); | ||
29 | |||
30 | switch(type) { | ||
31 | case ACL_TYPE_ACCESS: | ||
32 | name = POSIX_ACL_XATTR_ACCESS; | ||
33 | break; | ||
34 | |||
35 | case ACL_TYPE_DEFAULT: | ||
36 | name = POSIX_ACL_XATTR_DEFAULT; | ||
37 | break; | ||
38 | |||
39 | default: | ||
40 | return 0; | ||
41 | } | ||
42 | size = strlen(name) + 1; | ||
43 | if (list && size <= list_size) | ||
44 | memcpy(list, name, size); | ||
45 | return size; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * generic_acl_get - Generic xattr_handler->get() operation | ||
50 | * @ops: Filesystem specific getacl and setacl callbacks | ||
51 | */ | ||
52 | int | ||
53 | generic_acl_get(struct inode *inode, struct generic_acl_operations *ops, | ||
54 | int type, void *buffer, size_t size) | ||
55 | { | ||
56 | struct posix_acl *acl; | ||
57 | int error; | ||
58 | |||
59 | acl = ops->getacl(inode, type); | ||
60 | if (!acl) | ||
61 | return -ENODATA; | ||
62 | error = posix_acl_to_xattr(acl, buffer, size); | ||
63 | posix_acl_release(acl); | ||
64 | |||
65 | return error; | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * generic_acl_set - Generic xattr_handler->set() operation | ||
70 | * @ops: Filesystem specific getacl and setacl callbacks | ||
71 | */ | ||
72 | int | ||
73 | generic_acl_set(struct inode *inode, struct generic_acl_operations *ops, | ||
74 | int type, const void *value, size_t size) | ||
75 | { | ||
76 | struct posix_acl *acl = NULL; | ||
77 | int error; | ||
78 | |||
79 | if (S_ISLNK(inode->i_mode)) | ||
80 | return -EOPNOTSUPP; | ||
81 | if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER)) | ||
82 | return -EPERM; | ||
83 | if (value) { | ||
84 | acl = posix_acl_from_xattr(value, size); | ||
85 | if (IS_ERR(acl)) | ||
86 | return PTR_ERR(acl); | ||
87 | } | ||
88 | if (acl) { | ||
89 | mode_t mode; | ||
90 | |||
91 | error = posix_acl_valid(acl); | ||
92 | if (error) | ||
93 | goto failed; | ||
94 | switch(type) { | ||
95 | case ACL_TYPE_ACCESS: | ||
96 | mode = inode->i_mode; | ||
97 | error = posix_acl_equiv_mode(acl, &mode); | ||
98 | if (error < 0) | ||
99 | goto failed; | ||
100 | inode->i_mode = mode; | ||
101 | if (error == 0) { | ||
102 | posix_acl_release(acl); | ||
103 | acl = NULL; | ||
104 | } | ||
105 | break; | ||
106 | |||
107 | case ACL_TYPE_DEFAULT: | ||
108 | if (!S_ISDIR(inode->i_mode)) { | ||
109 | error = -EINVAL; | ||
110 | goto failed; | ||
111 | } | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | ops->setacl(inode, type, acl); | ||
116 | error = 0; | ||
117 | failed: | ||
118 | posix_acl_release(acl); | ||
119 | return error; | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * generic_acl_init - Take care of acl inheritance at @inode create time | ||
124 | * @ops: Filesystem specific getacl and setacl callbacks | ||
125 | * | ||
126 | * Files created inside a directory with a default ACL inherit the | ||
127 | * directory's default ACL. | ||
128 | */ | ||
129 | int | ||
130 | generic_acl_init(struct inode *inode, struct inode *dir, | ||
131 | struct generic_acl_operations *ops) | ||
132 | { | ||
133 | struct posix_acl *acl = NULL; | ||
134 | mode_t mode = inode->i_mode; | ||
135 | int error; | ||
136 | |||
137 | inode->i_mode = mode & ~current->fs->umask; | ||
138 | if (!S_ISLNK(inode->i_mode)) | ||
139 | acl = ops->getacl(dir, ACL_TYPE_DEFAULT); | ||
140 | if (acl) { | ||
141 | struct posix_acl *clone; | ||
142 | |||
143 | if (S_ISDIR(inode->i_mode)) { | ||
144 | clone = posix_acl_clone(acl, GFP_KERNEL); | ||
145 | error = -ENOMEM; | ||
146 | if (!clone) | ||
147 | goto cleanup; | ||
148 | ops->setacl(inode, ACL_TYPE_DEFAULT, clone); | ||
149 | posix_acl_release(clone); | ||
150 | } | ||
151 | clone = posix_acl_clone(acl, GFP_KERNEL); | ||
152 | error = -ENOMEM; | ||
153 | if (!clone) | ||
154 | goto cleanup; | ||
155 | error = posix_acl_create_masq(clone, &mode); | ||
156 | if (error >= 0) { | ||
157 | inode->i_mode = mode; | ||
158 | if (error > 0) | ||
159 | ops->setacl(inode, ACL_TYPE_ACCESS, clone); | ||
160 | } | ||
161 | posix_acl_release(clone); | ||
162 | } | ||
163 | error = 0; | ||
164 | |||
165 | cleanup: | ||
166 | posix_acl_release(acl); | ||
167 | return error; | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * generic_acl_chmod - change the access acl of @inode upon chmod() | ||
172 | * @ops: FIlesystem specific getacl and setacl callbacks | ||
173 | * | ||
174 | * A chmod also changes the permissions of the owner, group/mask, and | ||
175 | * other ACL entries. | ||
176 | */ | ||
177 | int | ||
178 | generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops) | ||
179 | { | ||
180 | struct posix_acl *acl, *clone; | ||
181 | int error = 0; | ||
182 | |||
183 | if (S_ISLNK(inode->i_mode)) | ||
184 | return -EOPNOTSUPP; | ||
185 | acl = ops->getacl(inode, ACL_TYPE_ACCESS); | ||
186 | if (acl) { | ||
187 | clone = posix_acl_clone(acl, GFP_KERNEL); | ||
188 | posix_acl_release(acl); | ||
189 | if (!clone) | ||
190 | return -ENOMEM; | ||
191 | error = posix_acl_chmod_masq(clone, inode->i_mode); | ||
192 | if (!error) | ||
193 | ops->setacl(inode, ACL_TYPE_ACCESS, clone); | ||
194 | posix_acl_release(clone); | ||
195 | } | ||
196 | return error; | ||
197 | } | ||
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index e025a31b4c64..f5b8f329aca6 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -229,7 +229,7 @@ static void hugetlbfs_delete_inode(struct inode *inode) | |||
229 | clear_inode(inode); | 229 | clear_inode(inode); |
230 | } | 230 | } |
231 | 231 | ||
232 | static void hugetlbfs_forget_inode(struct inode *inode) | 232 | static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock) |
233 | { | 233 | { |
234 | struct super_block *sb = inode->i_sb; | 234 | struct super_block *sb = inode->i_sb; |
235 | 235 | ||
diff --git a/fs/inode.c b/fs/inode.c index f5c04dd9ae8a..abf77471e6c4 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -133,7 +133,6 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
133 | inode->i_bdev = NULL; | 133 | inode->i_bdev = NULL; |
134 | inode->i_cdev = NULL; | 134 | inode->i_cdev = NULL; |
135 | inode->i_rdev = 0; | 135 | inode->i_rdev = 0; |
136 | inode->i_security = NULL; | ||
137 | inode->dirtied_when = 0; | 136 | inode->dirtied_when = 0; |
138 | if (security_inode_alloc(inode)) { | 137 | if (security_inode_alloc(inode)) { |
139 | if (inode->i_sb->s_op->destroy_inode) | 138 | if (inode->i_sb->s_op->destroy_inode) |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 4527692f432b..c34b862cdbf2 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -960,30 +960,30 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
960 | goto abort; | 960 | goto abort; |
961 | } | 961 | } |
962 | 962 | ||
963 | if (nextblk) { | 963 | /* On the last section, nextblk == 0, section size is likely to |
964 | while (b_off >= (offset + sect_size)) { | 964 | * exceed sect_size by a partial block, and access beyond the |
965 | struct inode *ninode; | 965 | * end of the file will reach beyond the section size, too. |
966 | 966 | */ | |
967 | offset += sect_size; | 967 | while (nextblk && (b_off >= (offset + sect_size))) { |
968 | if (nextblk == 0) | 968 | struct inode *ninode; |
969 | goto abort; | 969 | |
970 | ninode = isofs_iget(inode->i_sb, nextblk, nextoff); | 970 | offset += sect_size; |
971 | if (!ninode) | 971 | ninode = isofs_iget(inode->i_sb, nextblk, nextoff); |
972 | goto abort; | 972 | if (!ninode) |
973 | firstext = ISOFS_I(ninode)->i_first_extent; | 973 | goto abort; |
974 | sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode); | 974 | firstext = ISOFS_I(ninode)->i_first_extent; |
975 | nextblk = ISOFS_I(ninode)->i_next_section_block; | 975 | sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode); |
976 | nextoff = ISOFS_I(ninode)->i_next_section_offset; | 976 | nextblk = ISOFS_I(ninode)->i_next_section_block; |
977 | iput(ninode); | 977 | nextoff = ISOFS_I(ninode)->i_next_section_offset; |
978 | 978 | iput(ninode); | |
979 | if (++section > 100) { | 979 | |
980 | printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); | 980 | if (++section > 100) { |
981 | printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " | 981 | printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); |
982 | "nextblk=%lu nextoff=%lu\n", | 982 | printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " |
983 | iblock, firstext, (unsigned) sect_size, | 983 | "nextblk=%lu nextoff=%lu\n", |
984 | nextblk, nextoff); | 984 | iblock, firstext, (unsigned) sect_size, |
985 | goto abort; | 985 | nextblk, nextoff); |
986 | } | 986 | goto abort; |
987 | } | 987 | } |
988 | } | 988 | } |
989 | 989 | ||
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 2fc66c3e6681..7af6099c911c 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -715,18 +715,8 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
715 | if (!journal) | 715 | if (!journal) |
716 | return NULL; | 716 | return NULL; |
717 | 717 | ||
718 | journal->j_dev = bdev; | ||
719 | journal->j_fs_dev = fs_dev; | ||
720 | journal->j_blk_offset = start; | ||
721 | journal->j_maxlen = len; | ||
722 | journal->j_blocksize = blocksize; | ||
723 | |||
724 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | ||
725 | J_ASSERT(bh != NULL); | ||
726 | journal->j_sb_buffer = bh; | ||
727 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | ||
728 | |||
729 | /* journal descriptor can store up to n blocks -bzzz */ | 718 | /* journal descriptor can store up to n blocks -bzzz */ |
719 | journal->j_blocksize = blocksize; | ||
730 | n = journal->j_blocksize / sizeof(journal_block_tag_t); | 720 | n = journal->j_blocksize / sizeof(journal_block_tag_t); |
731 | journal->j_wbufsize = n; | 721 | journal->j_wbufsize = n; |
732 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); | 722 | journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); |
@@ -736,6 +726,15 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
736 | kfree(journal); | 726 | kfree(journal); |
737 | journal = NULL; | 727 | journal = NULL; |
738 | } | 728 | } |
729 | journal->j_dev = bdev; | ||
730 | journal->j_fs_dev = fs_dev; | ||
731 | journal->j_blk_offset = start; | ||
732 | journal->j_maxlen = len; | ||
733 | |||
734 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | ||
735 | J_ASSERT(bh != NULL); | ||
736 | journal->j_sb_buffer = bh; | ||
737 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | ||
739 | 738 | ||
740 | return journal; | 739 | return journal; |
741 | } | 740 | } |
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 445eed6ce5dc..11563fe2a52b 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c | |||
@@ -46,7 +46,7 @@ static int scan_revoke_records(journal_t *, struct buffer_head *, | |||
46 | #ifdef __KERNEL__ | 46 | #ifdef __KERNEL__ |
47 | 47 | ||
48 | /* Release readahead buffers after use */ | 48 | /* Release readahead buffers after use */ |
49 | void journal_brelse_array(struct buffer_head *b[], int n) | 49 | static void journal_brelse_array(struct buffer_head *b[], int n) |
50 | { | 50 | { |
51 | while (--n >= 0) | 51 | while (--n >= 0) |
52 | brelse (b[n]); | 52 | brelse (b[n]); |
diff --git a/fs/libfs.c b/fs/libfs.c index 8db5afb7b0a7..3793aaa14577 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -317,17 +317,9 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
317 | 317 | ||
318 | int simple_readpage(struct file *file, struct page *page) | 318 | int simple_readpage(struct file *file, struct page *page) |
319 | { | 319 | { |
320 | void *kaddr; | 320 | clear_highpage(page); |
321 | |||
322 | if (PageUptodate(page)) | ||
323 | goto out; | ||
324 | |||
325 | kaddr = kmap_atomic(page, KM_USER0); | ||
326 | memset(kaddr, 0, PAGE_CACHE_SIZE); | ||
327 | kunmap_atomic(kaddr, KM_USER0); | ||
328 | flush_dcache_page(page); | 321 | flush_dcache_page(page); |
329 | SetPageUptodate(page); | 322 | SetPageUptodate(page); |
330 | out: | ||
331 | unlock_page(page); | 323 | unlock_page(page); |
332 | return 0; | 324 | return 0; |
333 | } | 325 | } |
diff --git a/fs/mbcache.c b/fs/mbcache.c index e4fde1ab22cd..0ff71256e65b 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
@@ -160,6 +160,7 @@ __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask) | |||
160 | 160 | ||
161 | static void | 161 | static void |
162 | __mb_cache_entry_release_unlock(struct mb_cache_entry *ce) | 162 | __mb_cache_entry_release_unlock(struct mb_cache_entry *ce) |
163 | __releases(mb_cache_spinlock) | ||
163 | { | 164 | { |
164 | /* Wake up all processes queuing for this cache entry. */ | 165 | /* Wake up all processes queuing for this cache entry. */ |
165 | if (ce->e_queued) | 166 | if (ce->e_queued) |
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 9e44158a7540..d220165d4918 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
@@ -280,7 +280,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, | |||
280 | struct nameidata *nd) | 280 | struct nameidata *nd) |
281 | { | 281 | { |
282 | struct super_block *sb = dir->i_sb; | 282 | struct super_block *sb = dir->i_sb; |
283 | struct inode *inode; | 283 | struct inode *inode = NULL; |
284 | struct fat_slot_info sinfo; | 284 | struct fat_slot_info sinfo; |
285 | struct timespec ts; | 285 | struct timespec ts; |
286 | unsigned char msdos_name[MSDOS_NAME]; | 286 | unsigned char msdos_name[MSDOS_NAME]; |
@@ -316,6 +316,8 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, | |||
316 | d_instantiate(dentry, inode); | 316 | d_instantiate(dentry, inode); |
317 | out: | 317 | out: |
318 | unlock_kernel(); | 318 | unlock_kernel(); |
319 | if (!err) | ||
320 | err = fat_flush_inodes(sb, dir, inode); | ||
319 | return err; | 321 | return err; |
320 | } | 322 | } |
321 | 323 | ||
@@ -348,6 +350,8 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) | |||
348 | fat_detach(inode); | 350 | fat_detach(inode); |
349 | out: | 351 | out: |
350 | unlock_kernel(); | 352 | unlock_kernel(); |
353 | if (!err) | ||
354 | err = fat_flush_inodes(inode->i_sb, dir, inode); | ||
351 | 355 | ||
352 | return err; | 356 | return err; |
353 | } | 357 | } |
@@ -401,6 +405,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
401 | d_instantiate(dentry, inode); | 405 | d_instantiate(dentry, inode); |
402 | 406 | ||
403 | unlock_kernel(); | 407 | unlock_kernel(); |
408 | fat_flush_inodes(sb, dir, inode); | ||
404 | return 0; | 409 | return 0; |
405 | 410 | ||
406 | out_free: | 411 | out_free: |
@@ -430,6 +435,8 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry) | |||
430 | fat_detach(inode); | 435 | fat_detach(inode); |
431 | out: | 436 | out: |
432 | unlock_kernel(); | 437 | unlock_kernel(); |
438 | if (!err) | ||
439 | err = fat_flush_inodes(inode->i_sb, dir, inode); | ||
433 | 440 | ||
434 | return err; | 441 | return err; |
435 | } | 442 | } |
@@ -635,6 +642,8 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
635 | new_dir, new_msdos_name, new_dentry, is_hid); | 642 | new_dir, new_msdos_name, new_dentry, is_hid); |
636 | out: | 643 | out: |
637 | unlock_kernel(); | 644 | unlock_kernel(); |
645 | if (!err) | ||
646 | err = fat_flush_inodes(old_dir->i_sb, old_dir, new_dir); | ||
638 | return err; | 647 | return err; |
639 | } | 648 | } |
640 | 649 | ||
diff --git a/fs/namei.c b/fs/namei.c index 808e4ea2bb94..2892e68d3a86 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -518,18 +518,20 @@ static int __emul_lookup_dentry(const char *, struct nameidata *); | |||
518 | static __always_inline int | 518 | static __always_inline int |
519 | walk_init_root(const char *name, struct nameidata *nd) | 519 | walk_init_root(const char *name, struct nameidata *nd) |
520 | { | 520 | { |
521 | read_lock(¤t->fs->lock); | 521 | struct fs_struct *fs = current->fs; |
522 | if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { | 522 | |
523 | nd->mnt = mntget(current->fs->altrootmnt); | 523 | read_lock(&fs->lock); |
524 | nd->dentry = dget(current->fs->altroot); | 524 | if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { |
525 | read_unlock(¤t->fs->lock); | 525 | nd->mnt = mntget(fs->altrootmnt); |
526 | nd->dentry = dget(fs->altroot); | ||
527 | read_unlock(&fs->lock); | ||
526 | if (__emul_lookup_dentry(name,nd)) | 528 | if (__emul_lookup_dentry(name,nd)) |
527 | return 0; | 529 | return 0; |
528 | read_lock(¤t->fs->lock); | 530 | read_lock(&fs->lock); |
529 | } | 531 | } |
530 | nd->mnt = mntget(current->fs->rootmnt); | 532 | nd->mnt = mntget(fs->rootmnt); |
531 | nd->dentry = dget(current->fs->root); | 533 | nd->dentry = dget(fs->root); |
532 | read_unlock(¤t->fs->lock); | 534 | read_unlock(&fs->lock); |
533 | return 1; | 535 | return 1; |
534 | } | 536 | } |
535 | 537 | ||
@@ -724,17 +726,19 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) | |||
724 | 726 | ||
725 | static __always_inline void follow_dotdot(struct nameidata *nd) | 727 | static __always_inline void follow_dotdot(struct nameidata *nd) |
726 | { | 728 | { |
729 | struct fs_struct *fs = current->fs; | ||
730 | |||
727 | while(1) { | 731 | while(1) { |
728 | struct vfsmount *parent; | 732 | struct vfsmount *parent; |
729 | struct dentry *old = nd->dentry; | 733 | struct dentry *old = nd->dentry; |
730 | 734 | ||
731 | read_lock(¤t->fs->lock); | 735 | read_lock(&fs->lock); |
732 | if (nd->dentry == current->fs->root && | 736 | if (nd->dentry == fs->root && |
733 | nd->mnt == current->fs->rootmnt) { | 737 | nd->mnt == fs->rootmnt) { |
734 | read_unlock(¤t->fs->lock); | 738 | read_unlock(&fs->lock); |
735 | break; | 739 | break; |
736 | } | 740 | } |
737 | read_unlock(¤t->fs->lock); | 741 | read_unlock(&fs->lock); |
738 | spin_lock(&dcache_lock); | 742 | spin_lock(&dcache_lock); |
739 | if (nd->dentry != nd->mnt->mnt_root) { | 743 | if (nd->dentry != nd->mnt->mnt_root) { |
740 | nd->dentry = dget(nd->dentry->d_parent); | 744 | nd->dentry = dget(nd->dentry->d_parent); |
@@ -1042,15 +1046,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) | |||
1042 | struct vfsmount *old_mnt = nd->mnt; | 1046 | struct vfsmount *old_mnt = nd->mnt; |
1043 | struct qstr last = nd->last; | 1047 | struct qstr last = nd->last; |
1044 | int last_type = nd->last_type; | 1048 | int last_type = nd->last_type; |
1049 | struct fs_struct *fs = current->fs; | ||
1050 | |||
1045 | /* | 1051 | /* |
1046 | * NAME was not found in alternate root or it's a directory. Try to find | 1052 | * NAME was not found in alternate root or it's a directory. |
1047 | * it in the normal root: | 1053 | * Try to find it in the normal root: |
1048 | */ | 1054 | */ |
1049 | nd->last_type = LAST_ROOT; | 1055 | nd->last_type = LAST_ROOT; |
1050 | read_lock(¤t->fs->lock); | 1056 | read_lock(&fs->lock); |
1051 | nd->mnt = mntget(current->fs->rootmnt); | 1057 | nd->mnt = mntget(fs->rootmnt); |
1052 | nd->dentry = dget(current->fs->root); | 1058 | nd->dentry = dget(fs->root); |
1053 | read_unlock(¤t->fs->lock); | 1059 | read_unlock(&fs->lock); |
1054 | if (path_walk(name, nd) == 0) { | 1060 | if (path_walk(name, nd) == 0) { |
1055 | if (nd->dentry->d_inode) { | 1061 | if (nd->dentry->d_inode) { |
1056 | dput(old_dentry); | 1062 | dput(old_dentry); |
@@ -1074,6 +1080,7 @@ void set_fs_altroot(void) | |||
1074 | struct vfsmount *mnt = NULL, *oldmnt; | 1080 | struct vfsmount *mnt = NULL, *oldmnt; |
1075 | struct dentry *dentry = NULL, *olddentry; | 1081 | struct dentry *dentry = NULL, *olddentry; |
1076 | int err; | 1082 | int err; |
1083 | struct fs_struct *fs = current->fs; | ||
1077 | 1084 | ||
1078 | if (!emul) | 1085 | if (!emul) |
1079 | goto set_it; | 1086 | goto set_it; |
@@ -1083,12 +1090,12 @@ void set_fs_altroot(void) | |||
1083 | dentry = nd.dentry; | 1090 | dentry = nd.dentry; |
1084 | } | 1091 | } |
1085 | set_it: | 1092 | set_it: |
1086 | write_lock(¤t->fs->lock); | 1093 | write_lock(&fs->lock); |
1087 | oldmnt = current->fs->altrootmnt; | 1094 | oldmnt = fs->altrootmnt; |
1088 | olddentry = current->fs->altroot; | 1095 | olddentry = fs->altroot; |
1089 | current->fs->altrootmnt = mnt; | 1096 | fs->altrootmnt = mnt; |
1090 | current->fs->altroot = dentry; | 1097 | fs->altroot = dentry; |
1091 | write_unlock(¤t->fs->lock); | 1098 | write_unlock(&fs->lock); |
1092 | if (olddentry) { | 1099 | if (olddentry) { |
1093 | dput(olddentry); | 1100 | dput(olddentry); |
1094 | mntput(oldmnt); | 1101 | mntput(oldmnt); |
@@ -1102,29 +1109,30 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1102 | int retval = 0; | 1109 | int retval = 0; |
1103 | int fput_needed; | 1110 | int fput_needed; |
1104 | struct file *file; | 1111 | struct file *file; |
1112 | struct fs_struct *fs = current->fs; | ||
1105 | 1113 | ||
1106 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ | 1114 | nd->last_type = LAST_ROOT; /* if there are only slashes... */ |
1107 | nd->flags = flags; | 1115 | nd->flags = flags; |
1108 | nd->depth = 0; | 1116 | nd->depth = 0; |
1109 | 1117 | ||
1110 | if (*name=='/') { | 1118 | if (*name=='/') { |
1111 | read_lock(¤t->fs->lock); | 1119 | read_lock(&fs->lock); |
1112 | if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { | 1120 | if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { |
1113 | nd->mnt = mntget(current->fs->altrootmnt); | 1121 | nd->mnt = mntget(fs->altrootmnt); |
1114 | nd->dentry = dget(current->fs->altroot); | 1122 | nd->dentry = dget(fs->altroot); |
1115 | read_unlock(¤t->fs->lock); | 1123 | read_unlock(&fs->lock); |
1116 | if (__emul_lookup_dentry(name,nd)) | 1124 | if (__emul_lookup_dentry(name,nd)) |
1117 | goto out; /* found in altroot */ | 1125 | goto out; /* found in altroot */ |
1118 | read_lock(¤t->fs->lock); | 1126 | read_lock(&fs->lock); |
1119 | } | 1127 | } |
1120 | nd->mnt = mntget(current->fs->rootmnt); | 1128 | nd->mnt = mntget(fs->rootmnt); |
1121 | nd->dentry = dget(current->fs->root); | 1129 | nd->dentry = dget(fs->root); |
1122 | read_unlock(¤t->fs->lock); | 1130 | read_unlock(&fs->lock); |
1123 | } else if (dfd == AT_FDCWD) { | 1131 | } else if (dfd == AT_FDCWD) { |
1124 | read_lock(¤t->fs->lock); | 1132 | read_lock(&fs->lock); |
1125 | nd->mnt = mntget(current->fs->pwdmnt); | 1133 | nd->mnt = mntget(fs->pwdmnt); |
1126 | nd->dentry = dget(current->fs->pwd); | 1134 | nd->dentry = dget(fs->pwd); |
1127 | read_unlock(¤t->fs->lock); | 1135 | read_unlock(&fs->lock); |
1128 | } else { | 1136 | } else { |
1129 | struct dentry *dentry; | 1137 | struct dentry *dentry; |
1130 | 1138 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 36d180858136..6ede3a539ed8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/kernel.h> | ||
16 | #include <linux/quotaops.h> | 17 | #include <linux/quotaops.h> |
17 | #include <linux/acct.h> | 18 | #include <linux/acct.h> |
18 | #include <linux/capability.h> | 19 | #include <linux/capability.h> |
@@ -1813,6 +1814,7 @@ void __init mnt_init(unsigned long mempages) | |||
1813 | struct list_head *d; | 1814 | struct list_head *d; |
1814 | unsigned int nr_hash; | 1815 | unsigned int nr_hash; |
1815 | int i; | 1816 | int i; |
1817 | int err; | ||
1816 | 1818 | ||
1817 | init_rwsem(&namespace_sem); | 1819 | init_rwsem(&namespace_sem); |
1818 | 1820 | ||
@@ -1853,8 +1855,14 @@ void __init mnt_init(unsigned long mempages) | |||
1853 | d++; | 1855 | d++; |
1854 | i--; | 1856 | i--; |
1855 | } while (i); | 1857 | } while (i); |
1856 | sysfs_init(); | 1858 | err = sysfs_init(); |
1857 | subsystem_register(&fs_subsys); | 1859 | if (err) |
1860 | printk(KERN_WARNING "%s: sysfs_init error: %d\n", | ||
1861 | __FUNCTION__, err); | ||
1862 | err = subsystem_register(&fs_subsys); | ||
1863 | if (err) | ||
1864 | printk(KERN_WARNING "%s: subsystem_register error: %d\n", | ||
1865 | __FUNCTION__, err); | ||
1858 | init_rootfs(); | 1866 | init_rootfs(); |
1859 | init_mount_tree(); | 1867 | init_mount_tree(); |
1860 | } | 1868 | } |
@@ -546,7 +546,8 @@ asmlinkage long sys_chdir(const char __user * filename) | |||
546 | struct nameidata nd; | 546 | struct nameidata nd; |
547 | int error; | 547 | int error; |
548 | 548 | ||
549 | error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); | 549 | error = __user_walk(filename, |
550 | LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); | ||
550 | if (error) | 551 | if (error) |
551 | goto out; | 552 | goto out; |
552 | 553 | ||
@@ -1172,6 +1173,7 @@ asmlinkage long sys_close(unsigned int fd) | |||
1172 | struct file * filp; | 1173 | struct file * filp; |
1173 | struct files_struct *files = current->files; | 1174 | struct files_struct *files = current->files; |
1174 | struct fdtable *fdt; | 1175 | struct fdtable *fdt; |
1176 | int retval; | ||
1175 | 1177 | ||
1176 | spin_lock(&files->file_lock); | 1178 | spin_lock(&files->file_lock); |
1177 | fdt = files_fdtable(files); | 1179 | fdt = files_fdtable(files); |
@@ -1184,7 +1186,16 @@ asmlinkage long sys_close(unsigned int fd) | |||
1184 | FD_CLR(fd, fdt->close_on_exec); | 1186 | FD_CLR(fd, fdt->close_on_exec); |
1185 | __put_unused_fd(files, fd); | 1187 | __put_unused_fd(files, fd); |
1186 | spin_unlock(&files->file_lock); | 1188 | spin_unlock(&files->file_lock); |
1187 | return filp_close(filp, files); | 1189 | retval = filp_close(filp, files); |
1190 | |||
1191 | /* can't restart close syscall because file table entry was cleared */ | ||
1192 | if (unlikely(retval == -ERESTARTSYS || | ||
1193 | retval == -ERESTARTNOINTR || | ||
1194 | retval == -ERESTARTNOHAND || | ||
1195 | retval == -ERESTART_RESTARTBLOCK)) | ||
1196 | retval = -EINTR; | ||
1197 | |||
1198 | return retval; | ||
1188 | 1199 | ||
1189 | out_unlock: | 1200 | out_unlock: |
1190 | spin_unlock(&files->file_lock); | 1201 | spin_unlock(&files->file_lock); |
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 8f12587c3129..4f8df71e49d3 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c | |||
@@ -58,6 +58,31 @@ msdos_magic_present(unsigned char *p) | |||
58 | return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2); | 58 | return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2); |
59 | } | 59 | } |
60 | 60 | ||
61 | /* Value is EBCDIC 'IBMA' */ | ||
62 | #define AIX_LABEL_MAGIC1 0xC9 | ||
63 | #define AIX_LABEL_MAGIC2 0xC2 | ||
64 | #define AIX_LABEL_MAGIC3 0xD4 | ||
65 | #define AIX_LABEL_MAGIC4 0xC1 | ||
66 | static int aix_magic_present(unsigned char *p, struct block_device *bdev) | ||
67 | { | ||
68 | Sector sect; | ||
69 | unsigned char *d; | ||
70 | int ret = 0; | ||
71 | |||
72 | if (p[0] != AIX_LABEL_MAGIC1 && | ||
73 | p[1] != AIX_LABEL_MAGIC2 && | ||
74 | p[2] != AIX_LABEL_MAGIC3 && | ||
75 | p[3] != AIX_LABEL_MAGIC4) | ||
76 | return 0; | ||
77 | d = read_dev_sector(bdev, 7, §); | ||
78 | if (d) { | ||
79 | if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M') | ||
80 | ret = 1; | ||
81 | put_dev_sector(sect); | ||
82 | }; | ||
83 | return ret; | ||
84 | } | ||
85 | |||
61 | /* | 86 | /* |
62 | * Create devices for each logical partition in an extended partition. | 87 | * Create devices for each logical partition in an extended partition. |
63 | * The logical partitions form a linked list, with each entry being | 88 | * The logical partitions form a linked list, with each entry being |
@@ -393,6 +418,12 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) | |||
393 | return 0; | 418 | return 0; |
394 | } | 419 | } |
395 | 420 | ||
421 | if (aix_magic_present(data, bdev)) { | ||
422 | put_dev_sector(sect); | ||
423 | printk( " [AIX]"); | ||
424 | return 0; | ||
425 | } | ||
426 | |||
396 | /* | 427 | /* |
397 | * Now that the 55aa signature is present, this is probably | 428 | * Now that the 55aa signature is present, this is probably |
398 | * either the boot sector of a FAT filesystem or a DOS-type | 429 | * either the boot sector of a FAT filesystem or a DOS-type |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 0b615d62a159..c0e554971df0 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -347,6 +347,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
347 | sigemptyset(&sigign); | 347 | sigemptyset(&sigign); |
348 | sigemptyset(&sigcatch); | 348 | sigemptyset(&sigcatch); |
349 | cutime = cstime = utime = stime = cputime_zero; | 349 | cutime = cstime = utime = stime = cputime_zero; |
350 | |||
351 | mutex_lock(&tty_mutex); | ||
350 | read_lock(&tasklist_lock); | 352 | read_lock(&tasklist_lock); |
351 | if (task->sighand) { | 353 | if (task->sighand) { |
352 | spin_lock_irq(&task->sighand->siglock); | 354 | spin_lock_irq(&task->sighand->siglock); |
@@ -388,6 +390,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
388 | } | 390 | } |
389 | ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; | 391 | ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0; |
390 | read_unlock(&tasklist_lock); | 392 | read_unlock(&tasklist_lock); |
393 | mutex_unlock(&tty_mutex); | ||
391 | 394 | ||
392 | if (!whole || num_threads<2) | 395 | if (!whole || num_threads<2) |
393 | wchan = get_wchan(task); | 396 | wchan = get_wchan(task); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index fe8d55fb17cc..89c20d9d50bf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -797,7 +797,7 @@ out_no_task: | |||
797 | static ssize_t mem_write(struct file * file, const char * buf, | 797 | static ssize_t mem_write(struct file * file, const char * buf, |
798 | size_t count, loff_t *ppos) | 798 | size_t count, loff_t *ppos) |
799 | { | 799 | { |
800 | int copied = 0; | 800 | int copied; |
801 | char *page; | 801 | char *page; |
802 | struct task_struct *task = get_proc_task(file->f_dentry->d_inode); | 802 | struct task_struct *task = get_proc_task(file->f_dentry->d_inode); |
803 | unsigned long dst = *ppos; | 803 | unsigned long dst = *ppos; |
@@ -814,6 +814,7 @@ static ssize_t mem_write(struct file * file, const char * buf, | |||
814 | if (!page) | 814 | if (!page) |
815 | goto out; | 815 | goto out; |
816 | 816 | ||
817 | copied = 0; | ||
817 | while (count > 0) { | 818 | while (count > 0) { |
818 | int this_len, retval; | 819 | int this_len, retval; |
819 | 820 | ||
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index 3ceff3857272..1294eda4acae 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -100,7 +100,7 @@ static int notesize(struct memelfnote *en) | |||
100 | int sz; | 100 | int sz; |
101 | 101 | ||
102 | sz = sizeof(struct elf_note); | 102 | sz = sizeof(struct elf_note); |
103 | sz += roundup(strlen(en->name), 4); | 103 | sz += roundup((strlen(en->name) + 1), 4); |
104 | sz += roundup(en->datasz, 4); | 104 | sz += roundup(en->datasz, 4); |
105 | 105 | ||
106 | return sz; | 106 | return sz; |
@@ -116,7 +116,7 @@ static char *storenote(struct memelfnote *men, char *bufp) | |||
116 | 116 | ||
117 | #define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0) | 117 | #define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0) |
118 | 118 | ||
119 | en.n_namesz = strlen(men->name); | 119 | en.n_namesz = strlen(men->name) + 1; |
120 | en.n_descsz = men->datasz; | 120 | en.n_descsz = men->datasz; |
121 | en.n_type = men->type; | 121 | en.n_type = men->type; |
122 | 122 | ||
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile index 3a59309f3ca9..0eb7ac080484 100644 --- a/fs/reiserfs/Makefile +++ b/fs/reiserfs/Makefile | |||
@@ -28,7 +28,7 @@ endif | |||
28 | # will work around it. If any other architecture displays this behavior, | 28 | # will work around it. If any other architecture displays this behavior, |
29 | # add it here. | 29 | # add it here. |
30 | ifeq ($(CONFIG_PPC32),y) | 30 | ifeq ($(CONFIG_PPC32),y) |
31 | EXTRA_CFLAGS := -O1 | 31 | EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1) |
32 | endif | 32 | endif |
33 | 33 | ||
34 | TAGS: | 34 | TAGS: |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 1627edd50810..1cfbe857ba27 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
@@ -130,7 +130,7 @@ static int reiserfs_sync_file(struct file *p_s_filp, | |||
130 | reiserfs_write_lock(p_s_inode->i_sb); | 130 | reiserfs_write_lock(p_s_inode->i_sb); |
131 | barrier_done = reiserfs_commit_for_inode(p_s_inode); | 131 | barrier_done = reiserfs_commit_for_inode(p_s_inode); |
132 | reiserfs_write_unlock(p_s_inode->i_sb); | 132 | reiserfs_write_unlock(p_s_inode->i_sb); |
133 | if (barrier_done != 1) | 133 | if (barrier_done != 1 && reiserfs_barrier_flush(p_s_inode->i_sb)) |
134 | blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL); | 134 | blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL); |
135 | if (barrier_done < 0) | 135 | if (barrier_done < 0) |
136 | return barrier_done; | 136 | return barrier_done; |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 8810fda0da46..7e5a2f5ebeb0 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -1127,9 +1127,9 @@ static void init_inode(struct inode *inode, struct path *path) | |||
1127 | REISERFS_I(inode)->i_prealloc_count = 0; | 1127 | REISERFS_I(inode)->i_prealloc_count = 0; |
1128 | REISERFS_I(inode)->i_trans_id = 0; | 1128 | REISERFS_I(inode)->i_trans_id = 0; |
1129 | REISERFS_I(inode)->i_jl = NULL; | 1129 | REISERFS_I(inode)->i_jl = NULL; |
1130 | REISERFS_I(inode)->i_acl_access = NULL; | 1130 | reiserfs_init_acl_access(inode); |
1131 | REISERFS_I(inode)->i_acl_default = NULL; | 1131 | reiserfs_init_acl_default(inode); |
1132 | init_rwsem(&REISERFS_I(inode)->xattr_sem); | 1132 | reiserfs_init_xattr_rwsem(inode); |
1133 | 1133 | ||
1134 | if (stat_data_v1(ih)) { | 1134 | if (stat_data_v1(ih)) { |
1135 | struct stat_data_v1 *sd = | 1135 | struct stat_data_v1 *sd = |
@@ -1834,9 +1834,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1834 | REISERFS_I(inode)->i_attrs = | 1834 | REISERFS_I(inode)->i_attrs = |
1835 | REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; | 1835 | REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; |
1836 | sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); | 1836 | sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); |
1837 | REISERFS_I(inode)->i_acl_access = NULL; | 1837 | reiserfs_init_acl_access(inode); |
1838 | REISERFS_I(inode)->i_acl_default = NULL; | 1838 | reiserfs_init_acl_default(inode); |
1839 | init_rwsem(&REISERFS_I(inode)->xattr_sem); | 1839 | reiserfs_init_xattr_rwsem(inode); |
1840 | 1840 | ||
1841 | if (old_format_only(sb)) | 1841 | if (old_format_only(sb)) |
1842 | make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET, | 1842 | make_le_item_head(&ih, NULL, KEY_FORMAT_3_5, SD_OFFSET, |
@@ -1974,11 +1974,13 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, | |||
1974 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking | 1974 | * iput doesn't deadlock in reiserfs_delete_xattrs. The locking |
1975 | * code really needs to be reworked, but this will take care of it | 1975 | * code really needs to be reworked, but this will take care of it |
1976 | * for now. -jeffm */ | 1976 | * for now. -jeffm */ |
1977 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
1977 | if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) { | 1978 | if (REISERFS_I(dir)->i_acl_default && !IS_ERR(REISERFS_I(dir)->i_acl_default)) { |
1978 | reiserfs_write_unlock_xattrs(dir->i_sb); | 1979 | reiserfs_write_unlock_xattrs(dir->i_sb); |
1979 | iput(inode); | 1980 | iput(inode); |
1980 | reiserfs_write_lock_xattrs(dir->i_sb); | 1981 | reiserfs_write_lock_xattrs(dir->i_sb); |
1981 | } else | 1982 | } else |
1983 | #endif | ||
1982 | iput(inode); | 1984 | iput(inode); |
1983 | return err; | 1985 | return err; |
1984 | } | 1986 | } |
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 9b3672d69367..e6b5ccf23f15 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -1186,6 +1186,21 @@ static struct reiserfs_journal_list *find_newer_jl_for_cn(struct | |||
1186 | return NULL; | 1186 | return NULL; |
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | static int newer_jl_done(struct reiserfs_journal_cnode *cn) | ||
1190 | { | ||
1191 | struct super_block *sb = cn->sb; | ||
1192 | b_blocknr_t blocknr = cn->blocknr; | ||
1193 | |||
1194 | cn = cn->hprev; | ||
1195 | while (cn) { | ||
1196 | if (cn->sb == sb && cn->blocknr == blocknr && cn->jlist && | ||
1197 | atomic_read(&cn->jlist->j_commit_left) != 0) | ||
1198 | return 0; | ||
1199 | cn = cn->hprev; | ||
1200 | } | ||
1201 | return 1; | ||
1202 | } | ||
1203 | |||
1189 | static void remove_journal_hash(struct super_block *, | 1204 | static void remove_journal_hash(struct super_block *, |
1190 | struct reiserfs_journal_cnode **, | 1205 | struct reiserfs_journal_cnode **, |
1191 | struct reiserfs_journal_list *, unsigned long, | 1206 | struct reiserfs_journal_list *, unsigned long, |
@@ -1604,6 +1619,31 @@ static int flush_journal_list(struct super_block *s, | |||
1604 | return err; | 1619 | return err; |
1605 | } | 1620 | } |
1606 | 1621 | ||
1622 | static int test_transaction(struct super_block *s, | ||
1623 | struct reiserfs_journal_list *jl) | ||
1624 | { | ||
1625 | struct reiserfs_journal_cnode *cn; | ||
1626 | |||
1627 | if (jl->j_len == 0 || atomic_read(&jl->j_nonzerolen) == 0) | ||
1628 | return 1; | ||
1629 | |||
1630 | cn = jl->j_realblock; | ||
1631 | while (cn) { | ||
1632 | /* if the blocknr == 0, this has been cleared from the hash, | ||
1633 | ** skip it | ||
1634 | */ | ||
1635 | if (cn->blocknr == 0) { | ||
1636 | goto next; | ||
1637 | } | ||
1638 | if (cn->bh && !newer_jl_done(cn)) | ||
1639 | return 0; | ||
1640 | next: | ||
1641 | cn = cn->next; | ||
1642 | cond_resched(); | ||
1643 | } | ||
1644 | return 0; | ||
1645 | } | ||
1646 | |||
1607 | static int write_one_transaction(struct super_block *s, | 1647 | static int write_one_transaction(struct super_block *s, |
1608 | struct reiserfs_journal_list *jl, | 1648 | struct reiserfs_journal_list *jl, |
1609 | struct buffer_chunk *chunk) | 1649 | struct buffer_chunk *chunk) |
@@ -3433,16 +3473,6 @@ static void flush_async_commits(void *p) | |||
3433 | flush_commit_list(p_s_sb, jl, 1); | 3473 | flush_commit_list(p_s_sb, jl, 1); |
3434 | } | 3474 | } |
3435 | unlock_kernel(); | 3475 | unlock_kernel(); |
3436 | /* | ||
3437 | * this is a little racey, but there's no harm in missing | ||
3438 | * the filemap_fdata_write | ||
3439 | */ | ||
3440 | if (!atomic_read(&journal->j_async_throttle) | ||
3441 | && !reiserfs_is_journal_aborted(journal)) { | ||
3442 | atomic_inc(&journal->j_async_throttle); | ||
3443 | filemap_fdatawrite(p_s_sb->s_bdev->bd_inode->i_mapping); | ||
3444 | atomic_dec(&journal->j_async_throttle); | ||
3445 | } | ||
3446 | } | 3476 | } |
3447 | 3477 | ||
3448 | /* | 3478 | /* |
@@ -3844,7 +3874,9 @@ static void flush_old_journal_lists(struct super_block *s) | |||
3844 | entry = journal->j_journal_list.next; | 3874 | entry = journal->j_journal_list.next; |
3845 | jl = JOURNAL_LIST_ENTRY(entry); | 3875 | jl = JOURNAL_LIST_ENTRY(entry); |
3846 | /* this check should always be run, to send old lists to disk */ | 3876 | /* this check should always be run, to send old lists to disk */ |
3847 | if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4))) { | 3877 | if (jl->j_timestamp < (now - (JOURNAL_MAX_TRANS_AGE * 4)) && |
3878 | atomic_read(&jl->j_commit_left) == 0 && | ||
3879 | test_transaction(s, jl)) { | ||
3848 | flush_used_journal_lists(s, jl); | 3880 | flush_used_journal_lists(s, jl); |
3849 | } else { | 3881 | } else { |
3850 | break; | 3882 | break; |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index b40d4d64d598..80fc3b32802f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -510,8 +510,10 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) | |||
510 | SLAB_CTOR_CONSTRUCTOR) { | 510 | SLAB_CTOR_CONSTRUCTOR) { |
511 | INIT_LIST_HEAD(&ei->i_prealloc_list); | 511 | INIT_LIST_HEAD(&ei->i_prealloc_list); |
512 | inode_init_once(&ei->vfs_inode); | 512 | inode_init_once(&ei->vfs_inode); |
513 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
513 | ei->i_acl_access = NULL; | 514 | ei->i_acl_access = NULL; |
514 | ei->i_acl_default = NULL; | 515 | ei->i_acl_default = NULL; |
516 | #endif | ||
515 | } | 517 | } |
516 | } | 518 | } |
517 | 519 | ||
@@ -560,6 +562,7 @@ static void reiserfs_dirty_inode(struct inode *inode) | |||
560 | reiserfs_write_unlock(inode->i_sb); | 562 | reiserfs_write_unlock(inode->i_sb); |
561 | } | 563 | } |
562 | 564 | ||
565 | #ifdef CONFIG_REISERFS_FS_POSIX_ACL | ||
563 | static void reiserfs_clear_inode(struct inode *inode) | 566 | static void reiserfs_clear_inode(struct inode *inode) |
564 | { | 567 | { |
565 | struct posix_acl *acl; | 568 | struct posix_acl *acl; |
@@ -574,6 +577,9 @@ static void reiserfs_clear_inode(struct inode *inode) | |||
574 | posix_acl_release(acl); | 577 | posix_acl_release(acl); |
575 | REISERFS_I(inode)->i_acl_default = NULL; | 578 | REISERFS_I(inode)->i_acl_default = NULL; |
576 | } | 579 | } |
580 | #else | ||
581 | #define reiserfs_clear_inode NULL | ||
582 | #endif | ||
577 | 583 | ||
578 | #ifdef CONFIG_QUOTA | 584 | #ifdef CONFIG_QUOTA |
579 | static ssize_t reiserfs_quota_write(struct super_block *, int, const char *, | 585 | static ssize_t reiserfs_quota_write(struct super_block *, int, const char *, |
diff --git a/fs/select.c b/fs/select.c index 33b72ba0f86f..dcbc1112b7ec 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -658,8 +658,6 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
658 | unsigned int i; | 658 | unsigned int i; |
659 | struct poll_list *head; | 659 | struct poll_list *head; |
660 | struct poll_list *walk; | 660 | struct poll_list *walk; |
661 | struct fdtable *fdt; | ||
662 | int max_fdset; | ||
663 | /* Allocate small arguments on the stack to save memory and be | 661 | /* Allocate small arguments on the stack to save memory and be |
664 | faster - use long to make sure the buffer is aligned properly | 662 | faster - use long to make sure the buffer is aligned properly |
665 | on 64 bit archs to avoid unaligned access */ | 663 | on 64 bit archs to avoid unaligned access */ |
@@ -667,11 +665,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
667 | struct poll_list *stack_pp = NULL; | 665 | struct poll_list *stack_pp = NULL; |
668 | 666 | ||
669 | /* Do a sanity check on nfds ... */ | 667 | /* Do a sanity check on nfds ... */ |
670 | rcu_read_lock(); | 668 | if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
671 | fdt = files_fdtable(current->files); | ||
672 | max_fdset = fdt->max_fdset; | ||
673 | rcu_read_unlock(); | ||
674 | if (nfds > max_fdset && nfds > OPEN_MAX) | ||
675 | return -EINVAL; | 669 | return -EINVAL; |
676 | 670 | ||
677 | poll_initwait(&table); | 671 | poll_initwait(&table); |
diff --git a/fs/super.c b/fs/super.c index 5c4c94d5495e..6987824d0dce 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(deactivate_super); | |||
199 | * success, 0 if we had failed (superblock contents was already dead or | 199 | * success, 0 if we had failed (superblock contents was already dead or |
200 | * dying when grab_super() had been called). | 200 | * dying when grab_super() had been called). |
201 | */ | 201 | */ |
202 | static int grab_super(struct super_block *s) | 202 | static int grab_super(struct super_block *s) __releases(sb_lock) |
203 | { | 203 | { |
204 | s->s_count++; | 204 | s->s_count++; |
205 | spin_unlock(&sb_lock); | 205 | spin_unlock(&sb_lock); |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 5dd356cbbda6..1d3b5d2070e5 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1621,6 +1621,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1621 | goto error_out; | 1621 | goto error_out; |
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | if (UDF_SB_PARTFLAGS(sb, UDF_SB_PARTITION(sb)) & UDF_PART_FLAG_READ_ONLY) | ||
1625 | printk("UDF-fs: Partition marked readonly; forcing readonly mount\n"); | ||
1626 | sb->s_flags |= MS_RDONLY; | ||
1627 | |||
1624 | if ( udf_find_fileset(sb, &fileset, &rootdir) ) | 1628 | if ( udf_find_fileset(sb, &fileset, &rootdir) ) |
1625 | { | 1629 | { |
1626 | printk("UDF-fs: No fileset found\n"); | 1630 | printk("UDF-fs: No fileset found\n"); |