diff options
Diffstat (limited to 'fs')
53 files changed, 664 insertions, 423 deletions
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index ab5547ff29a1..38d695d66a0b 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/mount.h> | 37 | #include <linux/mount.h> |
38 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
39 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
40 | #include <linux/smp_lock.h> | ||
41 | #include <net/9p/9p.h> | 40 | #include <net/9p/9p.h> |
42 | #include <net/9p/client.h> | 41 | #include <net/9p/client.h> |
43 | 42 | ||
@@ -231,10 +230,8 @@ v9fs_umount_begin(struct super_block *sb) | |||
231 | { | 230 | { |
232 | struct v9fs_session_info *v9ses; | 231 | struct v9fs_session_info *v9ses; |
233 | 232 | ||
234 | lock_kernel(); | ||
235 | v9ses = sb->s_fs_info; | 233 | v9ses = sb->s_fs_info; |
236 | v9fs_session_cancel(v9ses); | 234 | v9fs_session_cancel(v9ses); |
237 | unlock_kernel(); | ||
238 | } | 235 | } |
239 | 236 | ||
240 | static const struct super_operations v9fs_super_ops = { | 237 | static const struct super_operations v9fs_super_ops = { |
diff --git a/fs/Kconfig b/fs/Kconfig index 525da2e8f73b..d78e950402c1 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -39,6 +39,13 @@ config FS_POSIX_ACL | |||
39 | bool | 39 | bool |
40 | default n | 40 | default n |
41 | 41 | ||
42 | source "fs/xfs/Kconfig" | ||
43 | source "fs/gfs2/Kconfig" | ||
44 | source "fs/ocfs2/Kconfig" | ||
45 | source "fs/btrfs/Kconfig" | ||
46 | |||
47 | endif # BLOCK | ||
48 | |||
42 | config FILE_LOCKING | 49 | config FILE_LOCKING |
43 | bool "Enable POSIX file locking API" if EMBEDDED | 50 | bool "Enable POSIX file locking API" if EMBEDDED |
44 | default y | 51 | default y |
@@ -47,13 +54,6 @@ config FILE_LOCKING | |||
47 | for filesystems like NFS and for the flock() system | 54 | for filesystems like NFS and for the flock() system |
48 | call. Disabling this option saves about 11k. | 55 | call. Disabling this option saves about 11k. |
49 | 56 | ||
50 | source "fs/xfs/Kconfig" | ||
51 | source "fs/gfs2/Kconfig" | ||
52 | source "fs/ocfs2/Kconfig" | ||
53 | source "fs/btrfs/Kconfig" | ||
54 | |||
55 | endif # BLOCK | ||
56 | |||
57 | source "fs/notify/Kconfig" | 57 | source "fs/notify/Kconfig" |
58 | 58 | ||
59 | source "fs/quota/Kconfig" | 59 | source "fs/quota/Kconfig" |
@@ -134,7 +134,7 @@ config TMPFS_POSIX_ACL | |||
134 | config HUGETLBFS | 134 | config HUGETLBFS |
135 | bool "HugeTLB file system support" | 135 | bool "HugeTLB file system support" |
136 | depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \ | 136 | depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \ |
137 | (S390 && 64BIT) || BROKEN | 137 | (S390 && 64BIT) || SYS_SUPPORTS_HUGETLBFS || BROKEN |
138 | help | 138 | help |
139 | hugetlbfs is a filesystem backing for HugeTLB pages, based on | 139 | hugetlbfs is a filesystem backing for HugeTLB pages, based on |
140 | ramfs. For architectures that support it, say Y here and read | 140 | ramfs. For architectures that support it, say Y here and read |
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index a6665f37f456..9cc18775b832 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h | |||
@@ -1,3 +1,6 @@ | |||
1 | #include <linux/fs.h> | ||
2 | #include <linux/adfs_fs.h> | ||
3 | |||
1 | /* Internal data structures for ADFS */ | 4 | /* Internal data structures for ADFS */ |
2 | 5 | ||
3 | #define ADFS_FREE_FRAG 0 | 6 | #define ADFS_FREE_FRAG 0 |
@@ -17,6 +20,58 @@ | |||
17 | struct buffer_head; | 20 | struct buffer_head; |
18 | 21 | ||
19 | /* | 22 | /* |
23 | * adfs file system inode data in memory | ||
24 | */ | ||
25 | struct adfs_inode_info { | ||
26 | loff_t mmu_private; | ||
27 | unsigned long parent_id; /* object id of parent */ | ||
28 | __u32 loadaddr; /* RISC OS load address */ | ||
29 | __u32 execaddr; /* RISC OS exec address */ | ||
30 | unsigned int filetype; /* RISC OS file type */ | ||
31 | unsigned int attr; /* RISC OS permissions */ | ||
32 | unsigned int stamped:1; /* RISC OS file has date/time */ | ||
33 | struct inode vfs_inode; | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Forward-declare this | ||
38 | */ | ||
39 | struct adfs_discmap; | ||
40 | struct adfs_dir_ops; | ||
41 | |||
42 | /* | ||
43 | * ADFS file system superblock data in memory | ||
44 | */ | ||
45 | struct adfs_sb_info { | ||
46 | struct adfs_discmap *s_map; /* bh list containing map */ | ||
47 | struct adfs_dir_ops *s_dir; /* directory operations */ | ||
48 | |||
49 | uid_t s_uid; /* owner uid */ | ||
50 | gid_t s_gid; /* owner gid */ | ||
51 | umode_t s_owner_mask; /* ADFS owner perm -> unix perm */ | ||
52 | umode_t s_other_mask; /* ADFS other perm -> unix perm */ | ||
53 | |||
54 | __u32 s_ids_per_zone; /* max. no ids in one zone */ | ||
55 | __u32 s_idlen; /* length of ID in map */ | ||
56 | __u32 s_map_size; /* sector size of a map */ | ||
57 | unsigned long s_size; /* total size (in blocks) of this fs */ | ||
58 | signed int s_map2blk; /* shift left by this for map->sector */ | ||
59 | unsigned int s_log2sharesize;/* log2 share size */ | ||
60 | __le32 s_version; /* disc format version */ | ||
61 | unsigned int s_namelen; /* maximum number of characters in name */ | ||
62 | }; | ||
63 | |||
64 | static inline struct adfs_sb_info *ADFS_SB(struct super_block *sb) | ||
65 | { | ||
66 | return sb->s_fs_info; | ||
67 | } | ||
68 | |||
69 | static inline struct adfs_inode_info *ADFS_I(struct inode *inode) | ||
70 | { | ||
71 | return container_of(inode, struct adfs_inode_info, vfs_inode); | ||
72 | } | ||
73 | |||
74 | /* | ||
20 | * Directory handling | 75 | * Directory handling |
21 | */ | 76 | */ |
22 | struct adfs_dir { | 77 | struct adfs_dir { |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 4d4073447d1a..23aa52f548a0 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
@@ -9,15 +9,7 @@ | |||
9 | * | 9 | * |
10 | * Common directory handling for ADFS | 10 | * Common directory handling for ADFS |
11 | */ | 11 | */ |
12 | #include <linux/errno.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/adfs_fs.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/stat.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
19 | #include <linux/buffer_head.h> /* for file_fsync() */ | ||
20 | |||
21 | #include "adfs.h" | 13 | #include "adfs.h" |
22 | 14 | ||
23 | /* | 15 | /* |
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c index 31df6adf0de6..bafc71222e25 100644 --- a/fs/adfs/dir_f.c +++ b/fs/adfs/dir_f.c | |||
@@ -9,15 +9,7 @@ | |||
9 | * | 9 | * |
10 | * E and F format directory handling | 10 | * E and F format directory handling |
11 | */ | 11 | */ |
12 | #include <linux/errno.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/adfs_fs.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/stat.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
19 | #include <linux/string.h> | ||
20 | |||
21 | #include "adfs.h" | 13 | #include "adfs.h" |
22 | #include "dir_f.h" | 14 | #include "dir_f.h" |
23 | 15 | ||
diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c index 139e0f345f18..1796bb352d05 100644 --- a/fs/adfs/dir_fplus.c +++ b/fs/adfs/dir_fplus.c | |||
@@ -7,15 +7,7 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/errno.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/adfs_fs.h> | ||
13 | #include <linux/time.h> | ||
14 | #include <linux/stat.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
17 | #include <linux/string.h> | ||
18 | |||
19 | #include "adfs.h" | 11 | #include "adfs.h" |
20 | #include "dir_fplus.h" | 12 | #include "dir_fplus.h" |
21 | 13 | ||
diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 8224d54a2afb..005ea34d1758 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c | |||
@@ -19,10 +19,6 @@ | |||
19 | * | 19 | * |
20 | * adfs regular file handling primitives | 20 | * adfs regular file handling primitives |
21 | */ | 21 | */ |
22 | #include <linux/fs.h> | ||
23 | #include <linux/buffer_head.h> /* for file_fsync() */ | ||
24 | #include <linux/adfs_fs.h> | ||
25 | |||
26 | #include "adfs.h" | 22 | #include "adfs.h" |
27 | 23 | ||
28 | const struct file_operations adfs_file_operations = { | 24 | const struct file_operations adfs_file_operations = { |
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 05b3a677201d..798cb071d132 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c | |||
@@ -7,17 +7,8 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/errno.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/adfs_fs.h> | ||
13 | #include <linux/time.h> | ||
14 | #include <linux/stat.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/smp_lock.h> | 10 | #include <linux/smp_lock.h> |
18 | #include <linux/module.h> | ||
19 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
20 | |||
21 | #include "adfs.h" | 12 | #include "adfs.h" |
22 | 13 | ||
23 | /* | 14 | /* |
@@ -395,4 +386,3 @@ int adfs_write_inode(struct inode *inode, int wait) | |||
395 | unlock_kernel(); | 386 | unlock_kernel(); |
396 | return ret; | 387 | return ret; |
397 | } | 388 | } |
398 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/adfs/map.c b/fs/adfs/map.c index 568081b93f73..d1a5932bb0f1 100644 --- a/fs/adfs/map.c +++ b/fs/adfs/map.c | |||
@@ -7,14 +7,8 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/errno.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/adfs_fs.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/buffer_head.h> | 10 | #include <linux/buffer_head.h> |
15 | |||
16 | #include <asm/unaligned.h> | 11 | #include <asm/unaligned.h> |
17 | |||
18 | #include "adfs.h" | 12 | #include "adfs.h" |
19 | 13 | ||
20 | /* | 14 | /* |
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 0ec5aaf47aa7..aad92f0a1048 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
@@ -8,26 +8,12 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/errno.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/adfs_fs.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/stat.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/init.h> | 11 | #include <linux/init.h> |
19 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
20 | #include <linux/vfs.h> | ||
21 | #include <linux/parser.h> | 13 | #include <linux/parser.h> |
22 | #include <linux/bitops.h> | ||
23 | #include <linux/mount.h> | 14 | #include <linux/mount.h> |
24 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
25 | 16 | #include <linux/statfs.h> | |
26 | #include <asm/uaccess.h> | ||
27 | #include <asm/system.h> | ||
28 | |||
29 | #include <stdarg.h> | ||
30 | |||
31 | #include "adfs.h" | 17 | #include "adfs.h" |
32 | #include "dir_f.h" | 18 | #include "dir_f.h" |
33 | #include "dir_fplus.h" | 19 | #include "dir_fplus.h" |
@@ -534,3 +520,4 @@ static void __exit exit_adfs_fs(void) | |||
534 | 520 | ||
535 | module_init(init_adfs_fs) | 521 | module_init(init_adfs_fs) |
536 | module_exit(exit_adfs_fs) | 522 | module_exit(exit_adfs_fs) |
523 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/afs/misc.c b/fs/afs/misc.c index 2d33a5f7d218..0dd4dafee10b 100644 --- a/fs/afs/misc.c +++ b/fs/afs/misc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <rxrpc/packet.h> | ||
15 | #include "internal.h" | 16 | #include "internal.h" |
16 | #include "afs_fs.h" | 17 | #include "afs_fs.h" |
17 | 18 | ||
@@ -54,6 +55,21 @@ int afs_abort_to_error(u32 abort_code) | |||
54 | case 0x2f6df24: return -ENOLCK; | 55 | case 0x2f6df24: return -ENOLCK; |
55 | case 0x2f6df26: return -ENOTEMPTY; | 56 | case 0x2f6df26: return -ENOTEMPTY; |
56 | case 0x2f6df78: return -EDQUOT; | 57 | case 0x2f6df78: return -EDQUOT; |
58 | |||
59 | case RXKADINCONSISTENCY: return -EPROTO; | ||
60 | case RXKADPACKETSHORT: return -EPROTO; | ||
61 | case RXKADLEVELFAIL: return -EKEYREJECTED; | ||
62 | case RXKADTICKETLEN: return -EKEYREJECTED; | ||
63 | case RXKADOUTOFSEQUENCE: return -EPROTO; | ||
64 | case RXKADNOAUTH: return -EKEYREJECTED; | ||
65 | case RXKADBADKEY: return -EKEYREJECTED; | ||
66 | case RXKADBADTICKET: return -EKEYREJECTED; | ||
67 | case RXKADUNKNOWNKEY: return -EKEYREJECTED; | ||
68 | case RXKADEXPIRED: return -EKEYEXPIRED; | ||
69 | case RXKADSEALEDINCON: return -EKEYREJECTED; | ||
70 | case RXKADDATALEN: return -EKEYREJECTED; | ||
71 | case RXKADILLEGALLEVEL: return -EKEYREJECTED; | ||
72 | |||
57 | default: return -EREMOTEIO; | 73 | default: return -EREMOTEIO; |
58 | } | 74 | } |
59 | } | 75 | } |
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c index ec2a7431e458..6e689208def2 100644 --- a/fs/afs/vlocation.c +++ b/fs/afs/vlocation.c | |||
@@ -65,6 +65,8 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl, | |||
65 | goto out; | 65 | goto out; |
66 | goto rotate; | 66 | goto rotate; |
67 | case -ENOMEDIUM: | 67 | case -ENOMEDIUM: |
68 | case -EKEYREJECTED: | ||
69 | case -EKEYEXPIRED: | ||
68 | goto out; | 70 | goto out; |
69 | default: | 71 | default: |
70 | ret = -EIO; | 72 | ret = -EIO; |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 9367b6297d84..615d5496fe0f 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -513,7 +513,7 @@ befs_utf2nls(struct super_block *sb, const char *in, | |||
513 | { | 513 | { |
514 | struct nls_table *nls = BEFS_SB(sb)->nls; | 514 | struct nls_table *nls = BEFS_SB(sb)->nls; |
515 | int i, o; | 515 | int i, o; |
516 | wchar_t uni; | 516 | unicode_t uni; |
517 | int unilen, utflen; | 517 | int unilen, utflen; |
518 | char *result; | 518 | char *result; |
519 | /* The utf8->nls conversion won't make the final nls string bigger | 519 | /* The utf8->nls conversion won't make the final nls string bigger |
@@ -539,16 +539,16 @@ befs_utf2nls(struct super_block *sb, const char *in, | |||
539 | for (i = o = 0; i < in_len; i += utflen, o += unilen) { | 539 | for (i = o = 0; i < in_len; i += utflen, o += unilen) { |
540 | 540 | ||
541 | /* convert from UTF-8 to Unicode */ | 541 | /* convert from UTF-8 to Unicode */ |
542 | utflen = utf8_mbtowc(&uni, &in[i], in_len - i); | 542 | utflen = utf8_to_utf32(&in[i], in_len - i, &uni); |
543 | if (utflen < 0) { | 543 | if (utflen < 0) |
544 | goto conv_err; | 544 | goto conv_err; |
545 | } | ||
546 | 545 | ||
547 | /* convert from Unicode to nls */ | 546 | /* convert from Unicode to nls */ |
547 | if (uni > MAX_WCHAR_T) | ||
548 | goto conv_err; | ||
548 | unilen = nls->uni2char(uni, &result[o], in_len - o); | 549 | unilen = nls->uni2char(uni, &result[o], in_len - o); |
549 | if (unilen < 0) { | 550 | if (unilen < 0) |
550 | goto conv_err; | 551 | goto conv_err; |
551 | } | ||
552 | } | 552 | } |
553 | result[o] = '\0'; | 553 | result[o] = '\0'; |
554 | *out_len = o; | 554 | *out_len = o; |
@@ -619,15 +619,13 @@ befs_nls2utf(struct super_block *sb, const char *in, | |||
619 | 619 | ||
620 | /* convert from nls to unicode */ | 620 | /* convert from nls to unicode */ |
621 | unilen = nls->char2uni(&in[i], in_len - i, &uni); | 621 | unilen = nls->char2uni(&in[i], in_len - i, &uni); |
622 | if (unilen < 0) { | 622 | if (unilen < 0) |
623 | goto conv_err; | 623 | goto conv_err; |
624 | } | ||
625 | 624 | ||
626 | /* convert from unicode to UTF-8 */ | 625 | /* convert from unicode to UTF-8 */ |
627 | utflen = utf8_wctomb(&result[o], uni, 3); | 626 | utflen = utf32_to_utf8(uni, &result[o], 3); |
628 | if (utflen <= 0) { | 627 | if (utflen <= 0) |
629 | goto conv_err; | 628 | goto conv_err; |
630 | } | ||
631 | } | 629 | } |
632 | 630 | ||
633 | result[o] = '\0'; | 631 | result[o] = '\0'; |
@@ -737,8 +735,6 @@ parse_options(char *options, befs_mount_options * opts) | |||
737 | static void | 735 | static void |
738 | befs_put_super(struct super_block *sb) | 736 | befs_put_super(struct super_block *sb) |
739 | { | 737 | { |
740 | lock_kernel(); | ||
741 | |||
742 | kfree(BEFS_SB(sb)->mount_opts.iocharset); | 738 | kfree(BEFS_SB(sb)->mount_opts.iocharset); |
743 | BEFS_SB(sb)->mount_opts.iocharset = NULL; | 739 | BEFS_SB(sb)->mount_opts.iocharset = NULL; |
744 | 740 | ||
@@ -749,8 +745,6 @@ befs_put_super(struct super_block *sb) | |||
749 | 745 | ||
750 | kfree(sb->s_fs_info); | 746 | kfree(sb->s_fs_info); |
751 | sb->s_fs_info = NULL; | 747 | sb->s_fs_info = NULL; |
752 | |||
753 | unlock_kernel(); | ||
754 | } | 748 | } |
755 | 749 | ||
756 | /* Allocate private field of the superblock, fill it. | 750 | /* Allocate private field of the superblock, fill it. |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 0aac371bff0b..c5ded5ff72b5 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -788,12 +788,6 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
788 | if (put_user(compat_ptr(data), &sgio->usr_ptr)) | 788 | if (put_user(compat_ptr(data), &sgio->usr_ptr)) |
789 | return -EFAULT; | 789 | return -EFAULT; |
790 | 790 | ||
791 | if (copy_in_user(&sgio->status, &sgio32->status, | ||
792 | (4 * sizeof(unsigned char)) + | ||
793 | (2 * sizeof(unsigned short)) + | ||
794 | (3 * sizeof(int)))) | ||
795 | return -EFAULT; | ||
796 | |||
797 | err = sys_ioctl(fd, cmd, (unsigned long) sgio); | 791 | err = sys_ioctl(fd, cmd, (unsigned long) sgio); |
798 | 792 | ||
799 | if (err >= 0) { | 793 | if (err >= 0) { |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 33a90120f6ad..4d74fc72c195 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
@@ -67,6 +67,8 @@ static int debugfs_u8_get(void *data, u64 *val) | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); | 69 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); |
70 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8_ro, debugfs_u8_get, NULL, "%llu\n"); | ||
71 | DEFINE_SIMPLE_ATTRIBUTE(fops_u8_wo, NULL, debugfs_u8_set, "%llu\n"); | ||
70 | 72 | ||
71 | /** | 73 | /** |
72 | * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value | 74 | * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value |
@@ -95,6 +97,13 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n"); | |||
95 | struct dentry *debugfs_create_u8(const char *name, mode_t mode, | 97 | struct dentry *debugfs_create_u8(const char *name, mode_t mode, |
96 | struct dentry *parent, u8 *value) | 98 | struct dentry *parent, u8 *value) |
97 | { | 99 | { |
100 | /* if there are no write bits set, make read only */ | ||
101 | if (!(mode & S_IWUGO)) | ||
102 | return debugfs_create_file(name, mode, parent, value, &fops_u8_ro); | ||
103 | /* if there are no read bits set, make write only */ | ||
104 | if (!(mode & S_IRUGO)) | ||
105 | return debugfs_create_file(name, mode, parent, value, &fops_u8_wo); | ||
106 | |||
98 | return debugfs_create_file(name, mode, parent, value, &fops_u8); | 107 | return debugfs_create_file(name, mode, parent, value, &fops_u8); |
99 | } | 108 | } |
100 | EXPORT_SYMBOL_GPL(debugfs_create_u8); | 109 | EXPORT_SYMBOL_GPL(debugfs_create_u8); |
@@ -110,6 +119,8 @@ static int debugfs_u16_get(void *data, u64 *val) | |||
110 | return 0; | 119 | return 0; |
111 | } | 120 | } |
112 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); | 121 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); |
122 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16_ro, debugfs_u16_get, NULL, "%llu\n"); | ||
123 | DEFINE_SIMPLE_ATTRIBUTE(fops_u16_wo, NULL, debugfs_u16_set, "%llu\n"); | ||
113 | 124 | ||
114 | /** | 125 | /** |
115 | * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value | 126 | * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value |
@@ -138,6 +149,13 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n"); | |||
138 | struct dentry *debugfs_create_u16(const char *name, mode_t mode, | 149 | struct dentry *debugfs_create_u16(const char *name, mode_t mode, |
139 | struct dentry *parent, u16 *value) | 150 | struct dentry *parent, u16 *value) |
140 | { | 151 | { |
152 | /* if there are no write bits set, make read only */ | ||
153 | if (!(mode & S_IWUGO)) | ||
154 | return debugfs_create_file(name, mode, parent, value, &fops_u16_ro); | ||
155 | /* if there are no read bits set, make write only */ | ||
156 | if (!(mode & S_IRUGO)) | ||
157 | return debugfs_create_file(name, mode, parent, value, &fops_u16_wo); | ||
158 | |||
141 | return debugfs_create_file(name, mode, parent, value, &fops_u16); | 159 | return debugfs_create_file(name, mode, parent, value, &fops_u16); |
142 | } | 160 | } |
143 | EXPORT_SYMBOL_GPL(debugfs_create_u16); | 161 | EXPORT_SYMBOL_GPL(debugfs_create_u16); |
@@ -153,6 +171,8 @@ static int debugfs_u32_get(void *data, u64 *val) | |||
153 | return 0; | 171 | return 0; |
154 | } | 172 | } |
155 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); | 173 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); |
174 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32_ro, debugfs_u32_get, NULL, "%llu\n"); | ||
175 | DEFINE_SIMPLE_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); | ||
156 | 176 | ||
157 | /** | 177 | /** |
158 | * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value | 178 | * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value |
@@ -181,6 +201,13 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n"); | |||
181 | struct dentry *debugfs_create_u32(const char *name, mode_t mode, | 201 | struct dentry *debugfs_create_u32(const char *name, mode_t mode, |
182 | struct dentry *parent, u32 *value) | 202 | struct dentry *parent, u32 *value) |
183 | { | 203 | { |
204 | /* if there are no write bits set, make read only */ | ||
205 | if (!(mode & S_IWUGO)) | ||
206 | return debugfs_create_file(name, mode, parent, value, &fops_u32_ro); | ||
207 | /* if there are no read bits set, make write only */ | ||
208 | if (!(mode & S_IRUGO)) | ||
209 | return debugfs_create_file(name, mode, parent, value, &fops_u32_wo); | ||
210 | |||
184 | return debugfs_create_file(name, mode, parent, value, &fops_u32); | 211 | return debugfs_create_file(name, mode, parent, value, &fops_u32); |
185 | } | 212 | } |
186 | EXPORT_SYMBOL_GPL(debugfs_create_u32); | 213 | EXPORT_SYMBOL_GPL(debugfs_create_u32); |
@@ -197,6 +224,8 @@ static int debugfs_u64_get(void *data, u64 *val) | |||
197 | return 0; | 224 | return 0; |
198 | } | 225 | } |
199 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); | 226 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); |
227 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64_ro, debugfs_u64_get, NULL, "%llu\n"); | ||
228 | DEFINE_SIMPLE_ATTRIBUTE(fops_u64_wo, NULL, debugfs_u64_set, "%llu\n"); | ||
200 | 229 | ||
201 | /** | 230 | /** |
202 | * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value | 231 | * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value |
@@ -225,15 +254,28 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n"); | |||
225 | struct dentry *debugfs_create_u64(const char *name, mode_t mode, | 254 | struct dentry *debugfs_create_u64(const char *name, mode_t mode, |
226 | struct dentry *parent, u64 *value) | 255 | struct dentry *parent, u64 *value) |
227 | { | 256 | { |
257 | /* if there are no write bits set, make read only */ | ||
258 | if (!(mode & S_IWUGO)) | ||
259 | return debugfs_create_file(name, mode, parent, value, &fops_u64_ro); | ||
260 | /* if there are no read bits set, make write only */ | ||
261 | if (!(mode & S_IRUGO)) | ||
262 | return debugfs_create_file(name, mode, parent, value, &fops_u64_wo); | ||
263 | |||
228 | return debugfs_create_file(name, mode, parent, value, &fops_u64); | 264 | return debugfs_create_file(name, mode, parent, value, &fops_u64); |
229 | } | 265 | } |
230 | EXPORT_SYMBOL_GPL(debugfs_create_u64); | 266 | EXPORT_SYMBOL_GPL(debugfs_create_u64); |
231 | 267 | ||
232 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); | 268 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8, debugfs_u8_get, debugfs_u8_set, "0x%02llx\n"); |
269 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8_ro, debugfs_u8_get, NULL, "0x%02llx\n"); | ||
270 | DEFINE_SIMPLE_ATTRIBUTE(fops_x8_wo, NULL, debugfs_u8_set, "0x%02llx\n"); | ||
233 | 271 | ||
234 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); | 272 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16, debugfs_u16_get, debugfs_u16_set, "0x%04llx\n"); |
273 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16_ro, debugfs_u16_get, NULL, "0x%04llx\n"); | ||
274 | DEFINE_SIMPLE_ATTRIBUTE(fops_x16_wo, NULL, debugfs_u16_set, "0x%04llx\n"); | ||
235 | 275 | ||
236 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); | 276 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n"); |
277 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32_ro, debugfs_u32_get, NULL, "0x%08llx\n"); | ||
278 | DEFINE_SIMPLE_ATTRIBUTE(fops_x32_wo, NULL, debugfs_u32_set, "0x%08llx\n"); | ||
237 | 279 | ||
238 | /* | 280 | /* |
239 | * debugfs_create_x{8,16,32} - create a debugfs file that is used to read and write an unsigned {8,16,32}-bit value | 281 | * debugfs_create_x{8,16,32} - create a debugfs file that is used to read and write an unsigned {8,16,32}-bit value |
@@ -256,6 +298,13 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_x32, debugfs_u32_get, debugfs_u32_set, "0x%08llx\n" | |||
256 | struct dentry *debugfs_create_x8(const char *name, mode_t mode, | 298 | struct dentry *debugfs_create_x8(const char *name, mode_t mode, |
257 | struct dentry *parent, u8 *value) | 299 | struct dentry *parent, u8 *value) |
258 | { | 300 | { |
301 | /* if there are no write bits set, make read only */ | ||
302 | if (!(mode & S_IWUGO)) | ||
303 | return debugfs_create_file(name, mode, parent, value, &fops_x8_ro); | ||
304 | /* if there are no read bits set, make write only */ | ||
305 | if (!(mode & S_IRUGO)) | ||
306 | return debugfs_create_file(name, mode, parent, value, &fops_x8_wo); | ||
307 | |||
259 | return debugfs_create_file(name, mode, parent, value, &fops_x8); | 308 | return debugfs_create_file(name, mode, parent, value, &fops_x8); |
260 | } | 309 | } |
261 | EXPORT_SYMBOL_GPL(debugfs_create_x8); | 310 | EXPORT_SYMBOL_GPL(debugfs_create_x8); |
@@ -273,6 +322,13 @@ EXPORT_SYMBOL_GPL(debugfs_create_x8); | |||
273 | struct dentry *debugfs_create_x16(const char *name, mode_t mode, | 322 | struct dentry *debugfs_create_x16(const char *name, mode_t mode, |
274 | struct dentry *parent, u16 *value) | 323 | struct dentry *parent, u16 *value) |
275 | { | 324 | { |
325 | /* if there are no write bits set, make read only */ | ||
326 | if (!(mode & S_IWUGO)) | ||
327 | return debugfs_create_file(name, mode, parent, value, &fops_x16_ro); | ||
328 | /* if there are no read bits set, make write only */ | ||
329 | if (!(mode & S_IRUGO)) | ||
330 | return debugfs_create_file(name, mode, parent, value, &fops_x16_wo); | ||
331 | |||
276 | return debugfs_create_file(name, mode, parent, value, &fops_x16); | 332 | return debugfs_create_file(name, mode, parent, value, &fops_x16); |
277 | } | 333 | } |
278 | EXPORT_SYMBOL_GPL(debugfs_create_x16); | 334 | EXPORT_SYMBOL_GPL(debugfs_create_x16); |
@@ -290,6 +346,13 @@ EXPORT_SYMBOL_GPL(debugfs_create_x16); | |||
290 | struct dentry *debugfs_create_x32(const char *name, mode_t mode, | 346 | struct dentry *debugfs_create_x32(const char *name, mode_t mode, |
291 | struct dentry *parent, u32 *value) | 347 | struct dentry *parent, u32 *value) |
292 | { | 348 | { |
349 | /* if there are no write bits set, make read only */ | ||
350 | if (!(mode & S_IWUGO)) | ||
351 | return debugfs_create_file(name, mode, parent, value, &fops_x32_ro); | ||
352 | /* if there are no read bits set, make write only */ | ||
353 | if (!(mode & S_IRUGO)) | ||
354 | return debugfs_create_file(name, mode, parent, value, &fops_x32_wo); | ||
355 | |||
293 | return debugfs_create_file(name, mode, parent, value, &fops_x32); | 356 | return debugfs_create_file(name, mode, parent, value, &fops_x32); |
294 | } | 357 | } |
295 | EXPORT_SYMBOL_GPL(debugfs_create_x32); | 358 | EXPORT_SYMBOL_GPL(debugfs_create_x32); |
@@ -419,7 +482,7 @@ static const struct file_operations fops_blob = { | |||
419 | }; | 482 | }; |
420 | 483 | ||
421 | /** | 484 | /** |
422 | * debugfs_create_blob - create a debugfs file that is used to read and write a binary blob | 485 | * debugfs_create_blob - create a debugfs file that is used to read a binary blob |
423 | * @name: a pointer to a string containing the name of the file to create. | 486 | * @name: a pointer to a string containing the name of the file to create. |
424 | * @mode: the permission that the file should have | 487 | * @mode: the permission that the file should have |
425 | * @parent: a pointer to the parent dentry for this file. This should be a | 488 | * @parent: a pointer to the parent dentry for this file. This should be a |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 0662ba6de85a..d22438ef7674 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -403,6 +403,7 @@ void debugfs_remove_recursive(struct dentry *dentry) | |||
403 | } | 403 | } |
404 | child = list_entry(parent->d_subdirs.next, struct dentry, | 404 | child = list_entry(parent->d_subdirs.next, struct dentry, |
405 | d_u.d_child); | 405 | d_u.d_child); |
406 | next_sibling: | ||
406 | 407 | ||
407 | /* | 408 | /* |
408 | * If "child" isn't empty, walk down the tree and | 409 | * If "child" isn't empty, walk down the tree and |
@@ -417,6 +418,16 @@ void debugfs_remove_recursive(struct dentry *dentry) | |||
417 | __debugfs_remove(child, parent); | 418 | __debugfs_remove(child, parent); |
418 | if (parent->d_subdirs.next == &child->d_u.d_child) { | 419 | if (parent->d_subdirs.next == &child->d_u.d_child) { |
419 | /* | 420 | /* |
421 | * Try the next sibling. | ||
422 | */ | ||
423 | if (child->d_u.d_child.next != &parent->d_subdirs) { | ||
424 | child = list_entry(child->d_u.d_child.next, | ||
425 | struct dentry, | ||
426 | d_u.d_child); | ||
427 | goto next_sibling; | ||
428 | } | ||
429 | |||
430 | /* | ||
420 | * Avoid infinite loop if we fail to remove | 431 | * Avoid infinite loop if we fail to remove |
421 | * one dentry. | 432 | * one dentry. |
422 | */ | 433 | */ |
diff --git a/fs/drop_caches.c b/fs/drop_caches.c index b6a719a909f8..a2edb7913447 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c | |||
@@ -24,7 +24,7 @@ static void drop_pagecache_sb(struct super_block *sb) | |||
24 | continue; | 24 | continue; |
25 | __iget(inode); | 25 | __iget(inode); |
26 | spin_unlock(&inode_lock); | 26 | spin_unlock(&inode_lock); |
27 | __invalidate_mapping_pages(inode->i_mapping, 0, -1, true); | 27 | invalidate_mapping_pages(inode->i_mapping, 0, -1); |
28 | iput(toput_inode); | 28 | iput(toput_inode); |
29 | toput_inode = inode; | 29 | toput_inode = inode; |
30 | spin_lock(&inode_lock); | 30 | spin_lock(&inode_lock); |
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 49308a29798a..7ee6f7e3a608 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c | |||
@@ -5,12 +5,12 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/buffer_head.h> | 7 | #include <linux/buffer_head.h> |
8 | #include <linux/smp_lock.h> | ||
9 | #include "efs.h" | 8 | #include "efs.h" |
10 | 9 | ||
11 | static int efs_readdir(struct file *, void *, filldir_t); | 10 | static int efs_readdir(struct file *, void *, filldir_t); |
12 | 11 | ||
13 | const struct file_operations efs_dir_operations = { | 12 | const struct file_operations efs_dir_operations = { |
13 | .llseek = generic_file_llseek, | ||
14 | .read = generic_read_dir, | 14 | .read = generic_read_dir, |
15 | .readdir = efs_readdir, | 15 | .readdir = efs_readdir, |
16 | }; | 16 | }; |
@@ -33,8 +33,6 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { | |||
33 | if (inode->i_size & (EFS_DIRBSIZE-1)) | 33 | if (inode->i_size & (EFS_DIRBSIZE-1)) |
34 | printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); | 34 | printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n"); |
35 | 35 | ||
36 | lock_kernel(); | ||
37 | |||
38 | /* work out where this entry can be found */ | 36 | /* work out where this entry can be found */ |
39 | block = filp->f_pos >> EFS_DIRBSIZE_BITS; | 37 | block = filp->f_pos >> EFS_DIRBSIZE_BITS; |
40 | 38 | ||
@@ -107,7 +105,6 @@ static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) { | |||
107 | 105 | ||
108 | filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; | 106 | filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; |
109 | out: | 107 | out: |
110 | unlock_kernel(); | ||
111 | return 0; | 108 | return 0; |
112 | } | 109 | } |
113 | 110 | ||
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index c3fb5f9c4a44..1511bf9e5f80 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c | |||
@@ -8,7 +8,6 @@ | |||
8 | 8 | ||
9 | #include <linux/buffer_head.h> | 9 | #include <linux/buffer_head.h> |
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/smp_lock.h> | ||
12 | #include <linux/exportfs.h> | 11 | #include <linux/exportfs.h> |
13 | #include "efs.h" | 12 | #include "efs.h" |
14 | 13 | ||
@@ -63,16 +62,12 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei | |||
63 | efs_ino_t inodenum; | 62 | efs_ino_t inodenum; |
64 | struct inode * inode = NULL; | 63 | struct inode * inode = NULL; |
65 | 64 | ||
66 | lock_kernel(); | ||
67 | inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); | 65 | inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); |
68 | if (inodenum) { | 66 | if (inodenum) { |
69 | inode = efs_iget(dir->i_sb, inodenum); | 67 | inode = efs_iget(dir->i_sb, inodenum); |
70 | if (IS_ERR(inode)) { | 68 | if (IS_ERR(inode)) |
71 | unlock_kernel(); | ||
72 | return ERR_CAST(inode); | 69 | return ERR_CAST(inode); |
73 | } | ||
74 | } | 70 | } |
75 | unlock_kernel(); | ||
76 | 71 | ||
77 | return d_splice_alias(inode, dentry); | 72 | return d_splice_alias(inode, dentry); |
78 | } | 73 | } |
@@ -115,11 +110,9 @@ struct dentry *efs_get_parent(struct dentry *child) | |||
115 | struct dentry *parent = ERR_PTR(-ENOENT); | 110 | struct dentry *parent = ERR_PTR(-ENOENT); |
116 | efs_ino_t ino; | 111 | efs_ino_t ino; |
117 | 112 | ||
118 | lock_kernel(); | ||
119 | ino = efs_find_entry(child->d_inode, "..", 2); | 113 | ino = efs_find_entry(child->d_inode, "..", 2); |
120 | if (ino) | 114 | if (ino) |
121 | parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); | 115 | parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); |
122 | unlock_kernel(); | ||
123 | 116 | ||
124 | return parent; | 117 | return parent; |
125 | } | 118 | } |
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c index 41911ec83aaf..75117d0dac2b 100644 --- a/fs/efs/symlink.c +++ b/fs/efs/symlink.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/string.h> | 9 | #include <linux/string.h> |
10 | #include <linux/pagemap.h> | 10 | #include <linux/pagemap.h> |
11 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
12 | #include <linux/smp_lock.h> | ||
13 | #include "efs.h" | 12 | #include "efs.h" |
14 | 13 | ||
15 | static int efs_symlink_readpage(struct file *file, struct page *page) | 14 | static int efs_symlink_readpage(struct file *file, struct page *page) |
@@ -22,9 +21,8 @@ static int efs_symlink_readpage(struct file *file, struct page *page) | |||
22 | 21 | ||
23 | err = -ENAMETOOLONG; | 22 | err = -ENAMETOOLONG; |
24 | if (size > 2 * EFS_BLOCKSIZE) | 23 | if (size > 2 * EFS_BLOCKSIZE) |
25 | goto fail_notlocked; | 24 | goto fail; |
26 | 25 | ||
27 | lock_kernel(); | ||
28 | /* read first 512 bytes of link target */ | 26 | /* read first 512 bytes of link target */ |
29 | err = -EIO; | 27 | err = -EIO; |
30 | bh = sb_bread(inode->i_sb, efs_bmap(inode, 0)); | 28 | bh = sb_bread(inode->i_sb, efs_bmap(inode, 0)); |
@@ -40,14 +38,11 @@ static int efs_symlink_readpage(struct file *file, struct page *page) | |||
40 | brelse(bh); | 38 | brelse(bh); |
41 | } | 39 | } |
42 | link[size] = '\0'; | 40 | link[size] = '\0'; |
43 | unlock_kernel(); | ||
44 | SetPageUptodate(page); | 41 | SetPageUptodate(page); |
45 | kunmap(page); | 42 | kunmap(page); |
46 | unlock_page(page); | 43 | unlock_page(page); |
47 | return 0; | 44 | return 0; |
48 | fail: | 45 | fail: |
49 | unlock_kernel(); | ||
50 | fail_notlocked: | ||
51 | SetPageError(page); | 46 | SetPageError(page); |
52 | kunmap(page); | 47 | kunmap(page); |
53 | unlock_page(page); | 48 | unlock_page(page); |
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index d81ef2fdb08e..e0c745451715 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c | |||
@@ -129,12 +129,15 @@ fail: | |||
129 | static inline struct posix_acl * | 129 | static inline struct posix_acl * |
130 | ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl) | 130 | ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl) |
131 | { | 131 | { |
132 | struct posix_acl *acl = EXT3_ACL_NOT_CACHED; | 132 | struct posix_acl *acl = ACCESS_ONCE(*i_acl); |
133 | 133 | ||
134 | spin_lock(&inode->i_lock); | 134 | if (acl) { |
135 | if (*i_acl != EXT3_ACL_NOT_CACHED) | 135 | spin_lock(&inode->i_lock); |
136 | acl = posix_acl_dup(*i_acl); | 136 | acl = *i_acl; |
137 | spin_unlock(&inode->i_lock); | 137 | if (acl != EXT3_ACL_NOT_CACHED) |
138 | acl = posix_acl_dup(acl); | ||
139 | spin_unlock(&inode->i_lock); | ||
140 | } | ||
138 | 141 | ||
139 | return acl; | 142 | return acl; |
140 | } | 143 | } |
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 647e0d65a284..605aeed96d68 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c | |||
@@ -129,12 +129,15 @@ fail: | |||
129 | static inline struct posix_acl * | 129 | static inline struct posix_acl * |
130 | ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl) | 130 | ext4_iget_acl(struct inode *inode, struct posix_acl **i_acl) |
131 | { | 131 | { |
132 | struct posix_acl *acl = EXT4_ACL_NOT_CACHED; | 132 | struct posix_acl *acl = ACCESS_ONCE(*i_acl); |
133 | 133 | ||
134 | spin_lock(&inode->i_lock); | 134 | if (acl) { |
135 | if (*i_acl != EXT4_ACL_NOT_CACHED) | 135 | spin_lock(&inode->i_lock); |
136 | acl = posix_acl_dup(*i_acl); | 136 | acl = *i_acl; |
137 | spin_unlock(&inode->i_lock); | 137 | if (acl != EXT4_ACL_NOT_CACHED) |
138 | acl = posix_acl_dup(acl); | ||
139 | spin_unlock(&inode->i_lock); | ||
140 | } | ||
138 | 141 | ||
139 | return acl; | 142 | return acl; |
140 | } | 143 | } |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 3b8e71b412fd..38ff75a0fe22 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -22,6 +22,19 @@ | |||
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include "fat.h" | 23 | #include "fat.h" |
24 | 24 | ||
25 | /* | ||
26 | * Maximum buffer size of short name. | ||
27 | * [(MSDOS_NAME + '.') * max one char + nul] | ||
28 | * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul] | ||
29 | */ | ||
30 | #define FAT_MAX_SHORT_SIZE ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1) | ||
31 | /* | ||
32 | * Maximum buffer size of unicode chars from slots. | ||
33 | * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)] | ||
34 | */ | ||
35 | #define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1) | ||
36 | #define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t)) | ||
37 | |||
25 | static inline loff_t fat_make_i_pos(struct super_block *sb, | 38 | static inline loff_t fat_make_i_pos(struct super_block *sb, |
26 | struct buffer_head *bh, | 39 | struct buffer_head *bh, |
27 | struct msdos_dir_entry *de) | 40 | struct msdos_dir_entry *de) |
@@ -171,7 +184,8 @@ static inline int fat_uni_to_x8(struct msdos_sb_info *sbi, const wchar_t *uni, | |||
171 | unsigned char *buf, int size) | 184 | unsigned char *buf, int size) |
172 | { | 185 | { |
173 | if (sbi->options.utf8) | 186 | if (sbi->options.utf8) |
174 | return utf8_wcstombs(buf, uni, size); | 187 | return utf16s_to_utf8s(uni, FAT_MAX_UNI_CHARS, |
188 | UTF16_HOST_ENDIAN, buf, size); | ||
175 | else | 189 | else |
176 | return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate, | 190 | return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate, |
177 | sbi->nls_io); | 191 | sbi->nls_io); |
@@ -325,19 +339,6 @@ parse_long: | |||
325 | } | 339 | } |
326 | 340 | ||
327 | /* | 341 | /* |
328 | * Maximum buffer size of short name. | ||
329 | * [(MSDOS_NAME + '.') * max one char + nul] | ||
330 | * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul] | ||
331 | */ | ||
332 | #define FAT_MAX_SHORT_SIZE ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1) | ||
333 | /* | ||
334 | * Maximum buffer size of unicode chars from slots. | ||
335 | * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)] | ||
336 | */ | ||
337 | #define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1) | ||
338 | #define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t)) | ||
339 | |||
340 | /* | ||
341 | * Return values: negative -> error, 0 -> not found, positive -> found, | 342 | * Return values: negative -> error, 0 -> not found, positive -> found, |
342 | * value is the total amount of slots, including the shortname entry. | 343 | * value is the total amount of slots, including the shortname entry. |
343 | */ | 344 | */ |
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 8d6fdcfd41df..73471b7ecc8c 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c | |||
@@ -502,11 +502,11 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, | |||
502 | if (utf8) { | 502 | if (utf8) { |
503 | int name_len = strlen(name); | 503 | int name_len = strlen(name); |
504 | 504 | ||
505 | *outlen = utf8_mbstowcs((wchar_t *)outname, name, PATH_MAX); | 505 | *outlen = utf8s_to_utf16s(name, PATH_MAX, (wchar_t *) outname); |
506 | 506 | ||
507 | /* | 507 | /* |
508 | * We stripped '.'s before and set len appropriately, | 508 | * We stripped '.'s before and set len appropriately, |
509 | * but utf8_mbstowcs doesn't care about len | 509 | * but utf8s_to_utf16s doesn't care about len |
510 | */ | 510 | */ |
511 | *outlen -= (name_len - len); | 511 | *outlen -= (name_len - len); |
512 | 512 | ||
diff --git a/fs/fcntl.c b/fs/fcntl.c index 1ad703150dee..a040b764f8e3 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -198,15 +198,19 @@ static int setfl(int fd, struct file * filp, unsigned long arg) | |||
198 | } | 198 | } |
199 | 199 | ||
200 | static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, | 200 | static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, |
201 | uid_t uid, uid_t euid, int force) | 201 | int force) |
202 | { | 202 | { |
203 | write_lock_irq(&filp->f_owner.lock); | 203 | write_lock_irq(&filp->f_owner.lock); |
204 | if (force || !filp->f_owner.pid) { | 204 | if (force || !filp->f_owner.pid) { |
205 | put_pid(filp->f_owner.pid); | 205 | put_pid(filp->f_owner.pid); |
206 | filp->f_owner.pid = get_pid(pid); | 206 | filp->f_owner.pid = get_pid(pid); |
207 | filp->f_owner.pid_type = type; | 207 | filp->f_owner.pid_type = type; |
208 | filp->f_owner.uid = uid; | 208 | |
209 | filp->f_owner.euid = euid; | 209 | if (pid) { |
210 | const struct cred *cred = current_cred(); | ||
211 | filp->f_owner.uid = cred->uid; | ||
212 | filp->f_owner.euid = cred->euid; | ||
213 | } | ||
210 | } | 214 | } |
211 | write_unlock_irq(&filp->f_owner.lock); | 215 | write_unlock_irq(&filp->f_owner.lock); |
212 | } | 216 | } |
@@ -214,14 +218,13 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, | |||
214 | int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, | 218 | int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, |
215 | int force) | 219 | int force) |
216 | { | 220 | { |
217 | const struct cred *cred = current_cred(); | ||
218 | int err; | 221 | int err; |
219 | 222 | ||
220 | err = security_file_set_fowner(filp); | 223 | err = security_file_set_fowner(filp); |
221 | if (err) | 224 | if (err) |
222 | return err; | 225 | return err; |
223 | 226 | ||
224 | f_modown(filp, pid, type, cred->uid, cred->euid, force); | 227 | f_modown(filp, pid, type, force); |
225 | return 0; | 228 | return 0; |
226 | } | 229 | } |
227 | EXPORT_SYMBOL(__f_setown); | 230 | EXPORT_SYMBOL(__f_setown); |
@@ -247,7 +250,7 @@ EXPORT_SYMBOL(f_setown); | |||
247 | 250 | ||
248 | void f_delown(struct file *filp) | 251 | void f_delown(struct file *filp) |
249 | { | 252 | { |
250 | f_modown(filp, NULL, PIDTYPE_PID, 0, 0, 1); | 253 | f_modown(filp, NULL, PIDTYPE_PID, 1); |
251 | } | 254 | } |
252 | 255 | ||
253 | pid_t f_getown(struct file *filp) | 256 | pid_t f_getown(struct file *filp) |
@@ -425,14 +428,20 @@ static inline int sigio_perm(struct task_struct *p, | |||
425 | } | 428 | } |
426 | 429 | ||
427 | static void send_sigio_to_task(struct task_struct *p, | 430 | static void send_sigio_to_task(struct task_struct *p, |
428 | struct fown_struct *fown, | 431 | struct fown_struct *fown, |
429 | int fd, | 432 | int fd, |
430 | int reason) | 433 | int reason) |
431 | { | 434 | { |
432 | if (!sigio_perm(p, fown, fown->signum)) | 435 | /* |
436 | * F_SETSIG can change ->signum lockless in parallel, make | ||
437 | * sure we read it once and use the same value throughout. | ||
438 | */ | ||
439 | int signum = ACCESS_ONCE(fown->signum); | ||
440 | |||
441 | if (!sigio_perm(p, fown, signum)) | ||
433 | return; | 442 | return; |
434 | 443 | ||
435 | switch (fown->signum) { | 444 | switch (signum) { |
436 | siginfo_t si; | 445 | siginfo_t si; |
437 | default: | 446 | default: |
438 | /* Queue a rt signal with the appropriate fd as its | 447 | /* Queue a rt signal with the appropriate fd as its |
@@ -441,7 +450,7 @@ static void send_sigio_to_task(struct task_struct *p, | |||
441 | delivered even if we can't queue. Failure to | 450 | delivered even if we can't queue. Failure to |
442 | queue in this case _should_ be reported; we fall | 451 | queue in this case _should_ be reported; we fall |
443 | back to SIGIO in that case. --sct */ | 452 | back to SIGIO in that case. --sct */ |
444 | si.si_signo = fown->signum; | 453 | si.si_signo = signum; |
445 | si.si_errno = 0; | 454 | si.si_errno = 0; |
446 | si.si_code = reason; | 455 | si.si_code = reason; |
447 | /* Make sure we are called with one of the POLL_* | 456 | /* Make sure we are called with one of the POLL_* |
@@ -453,7 +462,7 @@ static void send_sigio_to_task(struct task_struct *p, | |||
453 | else | 462 | else |
454 | si.si_band = band_table[reason - POLL_IN]; | 463 | si.si_band = band_table[reason - POLL_IN]; |
455 | si.si_fd = fd; | 464 | si.si_fd = fd; |
456 | if (!group_send_sig_info(fown->signum, &si, p)) | 465 | if (!group_send_sig_info(signum, &si, p)) |
457 | break; | 466 | break; |
458 | /* fall-through: fall back on the old plain SIGIO signal */ | 467 | /* fall-through: fall back on the old plain SIGIO signal */ |
459 | case 0: | 468 | case 0: |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 40308e98c6a4..caf049146ca2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -321,7 +321,7 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
321 | 321 | ||
322 | spin_lock(&inode_lock); | 322 | spin_lock(&inode_lock); |
323 | inode->i_state &= ~I_SYNC; | 323 | inode->i_state &= ~I_SYNC; |
324 | if (!(inode->i_state & I_FREEING)) { | 324 | if (!(inode->i_state & (I_FREEING | I_CLEAR))) { |
325 | if (!(inode->i_state & I_DIRTY) && | 325 | if (!(inode->i_state & I_DIRTY) && |
326 | mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { | 326 | mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { |
327 | /* | 327 | /* |
@@ -492,7 +492,7 @@ void generic_sync_sb_inodes(struct super_block *sb, | |||
492 | break; | 492 | break; |
493 | } | 493 | } |
494 | 494 | ||
495 | if (inode->i_state & I_NEW) { | 495 | if (inode->i_state & (I_NEW | I_WILL_FREE)) { |
496 | requeue_io(inode); | 496 | requeue_io(inode); |
497 | continue; | 497 | continue; |
498 | } | 498 | } |
@@ -523,7 +523,7 @@ void generic_sync_sb_inodes(struct super_block *sb, | |||
523 | if (current_is_pdflush() && !writeback_acquire(bdi)) | 523 | if (current_is_pdflush() && !writeback_acquire(bdi)) |
524 | break; | 524 | break; |
525 | 525 | ||
526 | BUG_ON(inode->i_state & I_FREEING); | 526 | BUG_ON(inode->i_state & (I_FREEING | I_CLEAR)); |
527 | __iget(inode); | 527 | __iget(inode); |
528 | pages_skipped = wbc->pages_skipped; | 528 | pages_skipped = wbc->pages_skipped; |
529 | __writeback_single_inode(inode, wbc); | 529 | __writeback_single_inode(inode, wbc); |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index f0df55a52929..d8673ccf90b7 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/random.h> | 19 | #include <linux/random.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/exportfs.h> | 21 | #include <linux/exportfs.h> |
22 | #include <linux/smp_lock.h> | ||
23 | 22 | ||
24 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); | 23 | MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); |
25 | MODULE_DESCRIPTION("Filesystem in Userspace"); | 24 | MODULE_DESCRIPTION("Filesystem in Userspace"); |
@@ -260,9 +259,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | |||
260 | 259 | ||
261 | static void fuse_umount_begin(struct super_block *sb) | 260 | static void fuse_umount_begin(struct super_block *sb) |
262 | { | 261 | { |
263 | lock_kernel(); | ||
264 | fuse_abort_conn(get_fuse_conn_super(sb)); | 262 | fuse_abort_conn(get_fuse_conn_super(sb)); |
265 | unlock_kernel(); | ||
266 | } | 263 | } |
267 | 264 | ||
268 | static void fuse_send_destroy(struct fuse_conn *fc) | 265 | static void fuse_send_destroy(struct fuse_conn *fc) |
diff --git a/fs/ioctl.c b/fs/ioctl.c index 286f38dfc6c0..001f8d3118f2 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -70,9 +70,7 @@ static int ioctl_fibmap(struct file *filp, int __user *p) | |||
70 | res = get_user(block, p); | 70 | res = get_user(block, p); |
71 | if (res) | 71 | if (res) |
72 | return res; | 72 | return res; |
73 | lock_kernel(); | ||
74 | res = mapping->a_ops->bmap(mapping, block); | 73 | res = mapping->a_ops->bmap(mapping, block); |
75 | unlock_kernel(); | ||
76 | return put_user(res, p); | 74 | return put_user(res, p); |
77 | } | 75 | } |
78 | 76 | ||
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c index 92c14b850e9c..a048de81c093 100644 --- a/fs/isofs/joliet.c +++ b/fs/isofs/joliet.c | |||
@@ -37,37 +37,6 @@ uni16_to_x8(unsigned char *ascii, __be16 *uni, int len, struct nls_table *nls) | |||
37 | return (op - ascii); | 37 | return (op - ascii); |
38 | } | 38 | } |
39 | 39 | ||
40 | /* Convert big endian wide character string to utf8 */ | ||
41 | static int | ||
42 | wcsntombs_be(__u8 *s, const __u8 *pwcs, int inlen, int maxlen) | ||
43 | { | ||
44 | const __u8 *ip; | ||
45 | __u8 *op; | ||
46 | int size; | ||
47 | __u16 c; | ||
48 | |||
49 | op = s; | ||
50 | ip = pwcs; | ||
51 | while ((*ip || ip[1]) && (maxlen > 0) && (inlen > 0)) { | ||
52 | c = (*ip << 8) | ip[1]; | ||
53 | if (c > 0x7f) { | ||
54 | size = utf8_wctomb(op, c, maxlen); | ||
55 | if (size == -1) { | ||
56 | /* Ignore character and move on */ | ||
57 | maxlen--; | ||
58 | } else { | ||
59 | op += size; | ||
60 | maxlen -= size; | ||
61 | } | ||
62 | } else { | ||
63 | *op++ = (__u8) c; | ||
64 | } | ||
65 | ip += 2; | ||
66 | inlen--; | ||
67 | } | ||
68 | return (op - s); | ||
69 | } | ||
70 | |||
71 | int | 40 | int |
72 | get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) | 41 | get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, struct inode * inode) |
73 | { | 42 | { |
@@ -79,8 +48,9 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st | |||
79 | nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset; | 48 | nls = ISOFS_SB(inode->i_sb)->s_nls_iocharset; |
80 | 49 | ||
81 | if (utf8) { | 50 | if (utf8) { |
82 | len = wcsntombs_be(outname, de->name, | 51 | len = utf16s_to_utf8s((const wchar_t *) de->name, |
83 | de->name_len[0] >> 1, PAGE_SIZE); | 52 | de->name_len[0] >> 1, UTF16_BIG_ENDIAN, |
53 | outname, PAGE_SIZE); | ||
84 | } else { | 54 | } else { |
85 | len = uni16_to_x8(outname, (__be16 *) de->name, | 55 | len = uni16_to_x8(outname, (__be16 *) de->name, |
86 | de->name_len[0] >> 1, nls); | 56 | de->name_len[0] >> 1, nls); |
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c index bbbd5f202e37..41d6045dbeb0 100644 --- a/fs/jfs/jfs_extent.c +++ b/fs/jfs/jfs_extent.c | |||
@@ -391,6 +391,7 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp) | |||
391 | } | 391 | } |
392 | XADaddress(xp, xaddr); | 392 | XADaddress(xp, xaddr); |
393 | XADlength(xp, xlen); | 393 | XADlength(xp, xlen); |
394 | XADoffset(xp, prev); | ||
394 | /* | 395 | /* |
395 | * only preserve the abnr flag within the xad flags | 396 | * only preserve the abnr flag within the xad flags |
396 | * of the returned hint. | 397 | * of the returned hint. |
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index 3aebe322271a..6ac693faae49 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c | |||
@@ -12,13 +12,14 @@ | |||
12 | /* bitmap.c contains the code that handles the inode and block bitmaps */ | 12 | /* bitmap.c contains the code that handles the inode and block bitmaps */ |
13 | 13 | ||
14 | #include "minix.h" | 14 | #include "minix.h" |
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/buffer_head.h> | 15 | #include <linux/buffer_head.h> |
17 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
18 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
19 | 18 | ||
20 | static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; | 19 | static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 }; |
21 | 20 | ||
21 | static DEFINE_SPINLOCK(bitmap_lock); | ||
22 | |||
22 | static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits) | 23 | static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits) |
23 | { | 24 | { |
24 | unsigned i, j, sum = 0; | 25 | unsigned i, j, sum = 0; |
@@ -69,11 +70,11 @@ void minix_free_block(struct inode *inode, unsigned long block) | |||
69 | return; | 70 | return; |
70 | } | 71 | } |
71 | bh = sbi->s_zmap[zone]; | 72 | bh = sbi->s_zmap[zone]; |
72 | lock_kernel(); | 73 | spin_lock(&bitmap_lock); |
73 | if (!minix_test_and_clear_bit(bit, bh->b_data)) | 74 | if (!minix_test_and_clear_bit(bit, bh->b_data)) |
74 | printk("minix_free_block (%s:%lu): bit already cleared\n", | 75 | printk("minix_free_block (%s:%lu): bit already cleared\n", |
75 | sb->s_id, block); | 76 | sb->s_id, block); |
76 | unlock_kernel(); | 77 | spin_unlock(&bitmap_lock); |
77 | mark_buffer_dirty(bh); | 78 | mark_buffer_dirty(bh); |
78 | return; | 79 | return; |
79 | } | 80 | } |
@@ -88,18 +89,18 @@ int minix_new_block(struct inode * inode) | |||
88 | struct buffer_head *bh = sbi->s_zmap[i]; | 89 | struct buffer_head *bh = sbi->s_zmap[i]; |
89 | int j; | 90 | int j; |
90 | 91 | ||
91 | lock_kernel(); | 92 | spin_lock(&bitmap_lock); |
92 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); | 93 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); |
93 | if (j < bits_per_zone) { | 94 | if (j < bits_per_zone) { |
94 | minix_set_bit(j, bh->b_data); | 95 | minix_set_bit(j, bh->b_data); |
95 | unlock_kernel(); | 96 | spin_unlock(&bitmap_lock); |
96 | mark_buffer_dirty(bh); | 97 | mark_buffer_dirty(bh); |
97 | j += i * bits_per_zone + sbi->s_firstdatazone-1; | 98 | j += i * bits_per_zone + sbi->s_firstdatazone-1; |
98 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) | 99 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) |
99 | break; | 100 | break; |
100 | return j; | 101 | return j; |
101 | } | 102 | } |
102 | unlock_kernel(); | 103 | spin_unlock(&bitmap_lock); |
103 | } | 104 | } |
104 | return 0; | 105 | return 0; |
105 | } | 106 | } |
@@ -211,10 +212,10 @@ void minix_free_inode(struct inode * inode) | |||
211 | minix_clear_inode(inode); /* clear on-disk copy */ | 212 | minix_clear_inode(inode); /* clear on-disk copy */ |
212 | 213 | ||
213 | bh = sbi->s_imap[ino]; | 214 | bh = sbi->s_imap[ino]; |
214 | lock_kernel(); | 215 | spin_lock(&bitmap_lock); |
215 | if (!minix_test_and_clear_bit(bit, bh->b_data)) | 216 | if (!minix_test_and_clear_bit(bit, bh->b_data)) |
216 | printk("minix_free_inode: bit %lu already cleared\n", bit); | 217 | printk("minix_free_inode: bit %lu already cleared\n", bit); |
217 | unlock_kernel(); | 218 | spin_unlock(&bitmap_lock); |
218 | mark_buffer_dirty(bh); | 219 | mark_buffer_dirty(bh); |
219 | out: | 220 | out: |
220 | clear_inode(inode); /* clear in-memory copy */ | 221 | clear_inode(inode); /* clear in-memory copy */ |
@@ -237,7 +238,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) | |||
237 | j = bits_per_zone; | 238 | j = bits_per_zone; |
238 | bh = NULL; | 239 | bh = NULL; |
239 | *error = -ENOSPC; | 240 | *error = -ENOSPC; |
240 | lock_kernel(); | 241 | spin_lock(&bitmap_lock); |
241 | for (i = 0; i < sbi->s_imap_blocks; i++) { | 242 | for (i = 0; i < sbi->s_imap_blocks; i++) { |
242 | bh = sbi->s_imap[i]; | 243 | bh = sbi->s_imap[i]; |
243 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); | 244 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); |
@@ -245,17 +246,17 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) | |||
245 | break; | 246 | break; |
246 | } | 247 | } |
247 | if (!bh || j >= bits_per_zone) { | 248 | if (!bh || j >= bits_per_zone) { |
248 | unlock_kernel(); | 249 | spin_unlock(&bitmap_lock); |
249 | iput(inode); | 250 | iput(inode); |
250 | return NULL; | 251 | return NULL; |
251 | } | 252 | } |
252 | if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ | 253 | if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ |
253 | unlock_kernel(); | 254 | spin_unlock(&bitmap_lock); |
254 | printk("minix_new_inode: bit already set\n"); | 255 | printk("minix_new_inode: bit already set\n"); |
255 | iput(inode); | 256 | iput(inode); |
256 | return NULL; | 257 | return NULL; |
257 | } | 258 | } |
258 | unlock_kernel(); | 259 | spin_unlock(&bitmap_lock); |
259 | mark_buffer_dirty(bh); | 260 | mark_buffer_dirty(bh); |
260 | j += i * bits_per_zone; | 261 | j += i * bits_per_zone; |
261 | if (!j || j > sbi->s_ninodes) { | 262 | if (!j || j > sbi->s_ninodes) { |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index e5f206467e40..d407e7a0b6fe 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include "minix.h" | 11 | #include "minix.h" |
12 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
13 | #include <linux/highmem.h> | 13 | #include <linux/highmem.h> |
14 | #include <linux/smp_lock.h> | ||
15 | #include <linux/swap.h> | 14 | #include <linux/swap.h> |
16 | 15 | ||
17 | typedef struct minix_dir_entry minix_dirent; | 16 | typedef struct minix_dir_entry minix_dirent; |
@@ -20,6 +19,7 @@ typedef struct minix3_dir_entry minix3_dirent; | |||
20 | static int minix_readdir(struct file *, void *, filldir_t); | 19 | static int minix_readdir(struct file *, void *, filldir_t); |
21 | 20 | ||
22 | const struct file_operations minix_dir_operations = { | 21 | const struct file_operations minix_dir_operations = { |
22 | .llseek = generic_file_llseek, | ||
23 | .read = generic_read_dir, | 23 | .read = generic_read_dir, |
24 | .readdir = minix_readdir, | 24 | .readdir = minix_readdir, |
25 | .fsync = simple_fsync, | 25 | .fsync = simple_fsync, |
@@ -102,8 +102,6 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
102 | char *name; | 102 | char *name; |
103 | __u32 inumber; | 103 | __u32 inumber; |
104 | 104 | ||
105 | lock_kernel(); | ||
106 | |||
107 | pos = (pos + chunk_size-1) & ~(chunk_size-1); | 105 | pos = (pos + chunk_size-1) & ~(chunk_size-1); |
108 | if (pos >= inode->i_size) | 106 | if (pos >= inode->i_size) |
109 | goto done; | 107 | goto done; |
@@ -146,7 +144,6 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
146 | 144 | ||
147 | done: | 145 | done: |
148 | filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; | 146 | filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; |
149 | unlock_kernel(); | ||
150 | return 0; | 147 | return 0; |
151 | } | 148 | } |
152 | 149 | ||
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index f91a23693597..74ea82d72164 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -35,8 +35,6 @@ static void minix_put_super(struct super_block *sb) | |||
35 | int i; | 35 | int i; |
36 | struct minix_sb_info *sbi = minix_sb(sb); | 36 | struct minix_sb_info *sbi = minix_sb(sb); |
37 | 37 | ||
38 | lock_kernel(); | ||
39 | |||
40 | if (!(sb->s_flags & MS_RDONLY)) { | 38 | if (!(sb->s_flags & MS_RDONLY)) { |
41 | if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ | 39 | if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */ |
42 | sbi->s_ms->s_state = sbi->s_mount_state; | 40 | sbi->s_ms->s_state = sbi->s_mount_state; |
@@ -50,8 +48,6 @@ static void minix_put_super(struct super_block *sb) | |||
50 | kfree(sbi->s_imap); | 48 | kfree(sbi->s_imap); |
51 | sb->s_fs_info = NULL; | 49 | sb->s_fs_info = NULL; |
52 | kfree(sbi); | 50 | kfree(sbi); |
53 | |||
54 | unlock_kernel(); | ||
55 | } | 51 | } |
56 | 52 | ||
57 | static struct kmem_cache * minix_inode_cachep; | 53 | static struct kmem_cache * minix_inode_cachep; |
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c index 97645f112114..0ec6237a5970 100644 --- a/fs/ncpfs/ncplib_kernel.c +++ b/fs/ncpfs/ncplib_kernel.c | |||
@@ -1113,11 +1113,13 @@ ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen, | |||
1113 | 1113 | ||
1114 | if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { | 1114 | if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { |
1115 | int k; | 1115 | int k; |
1116 | unicode_t u; | ||
1116 | 1117 | ||
1117 | k = utf8_mbtowc(&ec, iname, iname_end - iname); | 1118 | k = utf8_to_utf32(iname, iname_end - iname, &u); |
1118 | if (k < 0) | 1119 | if (k < 0 || u > MAX_WCHAR_T) |
1119 | return -EINVAL; | 1120 | return -EINVAL; |
1120 | iname += k; | 1121 | iname += k; |
1122 | ec = u; | ||
1121 | } else { | 1123 | } else { |
1122 | if (*iname == NCP_ESC) { | 1124 | if (*iname == NCP_ESC) { |
1123 | int k; | 1125 | int k; |
@@ -1214,7 +1216,7 @@ ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen, | |||
1214 | if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { | 1216 | if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) { |
1215 | int k; | 1217 | int k; |
1216 | 1218 | ||
1217 | k = utf8_wctomb(iname, ec, iname_end - iname); | 1219 | k = utf32_to_utf8(ec, iname, iname_end - iname); |
1218 | if (k < 0) { | 1220 | if (k < 0) { |
1219 | err = -ENAMETOOLONG; | 1221 | err = -ENAMETOOLONG; |
1220 | goto quit; | 1222 | goto quit; |
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h index a2ab2529b5ca..ceda50aad73c 100644 --- a/fs/nfs/iostat.h +++ b/fs/nfs/iostat.h | |||
@@ -31,7 +31,7 @@ static inline void nfs_inc_server_stats(const struct nfs_server *server, | |||
31 | cpu = get_cpu(); | 31 | cpu = get_cpu(); |
32 | iostats = per_cpu_ptr(server->io_stats, cpu); | 32 | iostats = per_cpu_ptr(server->io_stats, cpu); |
33 | iostats->events[stat]++; | 33 | iostats->events[stat]++; |
34 | put_cpu_no_resched(); | 34 | put_cpu(); |
35 | } | 35 | } |
36 | 36 | ||
37 | static inline void nfs_inc_stats(const struct inode *inode, | 37 | static inline void nfs_inc_stats(const struct inode *inode, |
@@ -50,7 +50,7 @@ static inline void nfs_add_server_stats(const struct nfs_server *server, | |||
50 | cpu = get_cpu(); | 50 | cpu = get_cpu(); |
51 | iostats = per_cpu_ptr(server->io_stats, cpu); | 51 | iostats = per_cpu_ptr(server->io_stats, cpu); |
52 | iostats->bytes[stat] += addend; | 52 | iostats->bytes[stat] += addend; |
53 | put_cpu_no_resched(); | 53 | put_cpu(); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline void nfs_add_stats(const struct inode *inode, | 56 | static inline void nfs_add_stats(const struct inode *inode, |
@@ -71,7 +71,7 @@ static inline void nfs_add_fscache_stats(struct inode *inode, | |||
71 | cpu = get_cpu(); | 71 | cpu = get_cpu(); |
72 | iostats = per_cpu_ptr(NFS_SERVER(inode)->io_stats, cpu); | 72 | iostats = per_cpu_ptr(NFS_SERVER(inode)->io_stats, cpu); |
73 | iostats->fscache[stat] += addend; | 73 | iostats->fscache[stat] += addend; |
74 | put_cpu_no_resched(); | 74 | put_cpu(); |
75 | } | 75 | } |
76 | #endif | 76 | #endif |
77 | 77 | ||
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 9b0efdad8910..477d37d83b31 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/kmod.h> | 16 | #include <linux/kmod.h> |
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <asm/byteorder.h> | ||
18 | 19 | ||
19 | static struct nls_table default_table; | 20 | static struct nls_table default_table; |
20 | static struct nls_table *tables = &default_table; | 21 | static struct nls_table *tables = &default_table; |
@@ -43,10 +44,17 @@ static const struct utf8_table utf8_table[] = | |||
43 | {0, /* end of table */} | 44 | {0, /* end of table */} |
44 | }; | 45 | }; |
45 | 46 | ||
46 | int | 47 | #define UNICODE_MAX 0x0010ffff |
47 | utf8_mbtowc(wchar_t *p, const __u8 *s, int n) | 48 | #define PLANE_SIZE 0x00010000 |
49 | |||
50 | #define SURROGATE_MASK 0xfffff800 | ||
51 | #define SURROGATE_PAIR 0x0000d800 | ||
52 | #define SURROGATE_LOW 0x00000400 | ||
53 | #define SURROGATE_BITS 0x000003ff | ||
54 | |||
55 | int utf8_to_utf32(const u8 *s, int len, unicode_t *pu) | ||
48 | { | 56 | { |
49 | long l; | 57 | unsigned long l; |
50 | int c0, c, nc; | 58 | int c0, c, nc; |
51 | const struct utf8_table *t; | 59 | const struct utf8_table *t; |
52 | 60 | ||
@@ -57,12 +65,13 @@ utf8_mbtowc(wchar_t *p, const __u8 *s, int n) | |||
57 | nc++; | 65 | nc++; |
58 | if ((c0 & t->cmask) == t->cval) { | 66 | if ((c0 & t->cmask) == t->cval) { |
59 | l &= t->lmask; | 67 | l &= t->lmask; |
60 | if (l < t->lval) | 68 | if (l < t->lval || l > UNICODE_MAX || |
69 | (l & SURROGATE_MASK) == SURROGATE_PAIR) | ||
61 | return -1; | 70 | return -1; |
62 | *p = l; | 71 | *pu = (unicode_t) l; |
63 | return nc; | 72 | return nc; |
64 | } | 73 | } |
65 | if (n <= nc) | 74 | if (len <= nc) |
66 | return -1; | 75 | return -1; |
67 | s++; | 76 | s++; |
68 | c = (*s ^ 0x80) & 0xFF; | 77 | c = (*s ^ 0x80) & 0xFF; |
@@ -72,90 +81,133 @@ utf8_mbtowc(wchar_t *p, const __u8 *s, int n) | |||
72 | } | 81 | } |
73 | return -1; | 82 | return -1; |
74 | } | 83 | } |
84 | EXPORT_SYMBOL(utf8_to_utf32); | ||
75 | 85 | ||
76 | int | 86 | int utf32_to_utf8(unicode_t u, u8 *s, int maxlen) |
77 | utf8_mbstowcs(wchar_t *pwcs, const __u8 *s, int n) | ||
78 | { | 87 | { |
79 | __u16 *op; | 88 | unsigned long l; |
80 | const __u8 *ip; | ||
81 | int size; | ||
82 | |||
83 | op = pwcs; | ||
84 | ip = s; | ||
85 | while (*ip && n > 0) { | ||
86 | if (*ip & 0x80) { | ||
87 | size = utf8_mbtowc(op, ip, n); | ||
88 | if (size == -1) { | ||
89 | /* Ignore character and move on */ | ||
90 | ip++; | ||
91 | n--; | ||
92 | } else { | ||
93 | op++; | ||
94 | ip += size; | ||
95 | n -= size; | ||
96 | } | ||
97 | } else { | ||
98 | *op++ = *ip++; | ||
99 | n--; | ||
100 | } | ||
101 | } | ||
102 | return (op - pwcs); | ||
103 | } | ||
104 | |||
105 | int | ||
106 | utf8_wctomb(__u8 *s, wchar_t wc, int maxlen) | ||
107 | { | ||
108 | long l; | ||
109 | int c, nc; | 89 | int c, nc; |
110 | const struct utf8_table *t; | 90 | const struct utf8_table *t; |
111 | 91 | ||
112 | if (!s) | 92 | if (!s) |
113 | return 0; | 93 | return 0; |
114 | 94 | ||
115 | l = wc; | 95 | l = u; |
96 | if (l > UNICODE_MAX || (l & SURROGATE_MASK) == SURROGATE_PAIR) | ||
97 | return -1; | ||
98 | |||
116 | nc = 0; | 99 | nc = 0; |
117 | for (t = utf8_table; t->cmask && maxlen; t++, maxlen--) { | 100 | for (t = utf8_table; t->cmask && maxlen; t++, maxlen--) { |
118 | nc++; | 101 | nc++; |
119 | if (l <= t->lmask) { | 102 | if (l <= t->lmask) { |
120 | c = t->shift; | 103 | c = t->shift; |
121 | *s = t->cval | (l >> c); | 104 | *s = (u8) (t->cval | (l >> c)); |
122 | while (c > 0) { | 105 | while (c > 0) { |
123 | c -= 6; | 106 | c -= 6; |
124 | s++; | 107 | s++; |
125 | *s = 0x80 | ((l >> c) & 0x3F); | 108 | *s = (u8) (0x80 | ((l >> c) & 0x3F)); |
126 | } | 109 | } |
127 | return nc; | 110 | return nc; |
128 | } | 111 | } |
129 | } | 112 | } |
130 | return -1; | 113 | return -1; |
131 | } | 114 | } |
115 | EXPORT_SYMBOL(utf32_to_utf8); | ||
132 | 116 | ||
133 | int | 117 | int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs) |
134 | utf8_wcstombs(__u8 *s, const wchar_t *pwcs, int maxlen) | ||
135 | { | 118 | { |
136 | const __u16 *ip; | 119 | u16 *op; |
137 | __u8 *op; | ||
138 | int size; | 120 | int size; |
121 | unicode_t u; | ||
122 | |||
123 | op = pwcs; | ||
124 | while (*s && len > 0) { | ||
125 | if (*s & 0x80) { | ||
126 | size = utf8_to_utf32(s, len, &u); | ||
127 | if (size < 0) { | ||
128 | /* Ignore character and move on */ | ||
129 | size = 1; | ||
130 | } else if (u >= PLANE_SIZE) { | ||
131 | u -= PLANE_SIZE; | ||
132 | *op++ = (wchar_t) (SURROGATE_PAIR | | ||
133 | ((u >> 10) & SURROGATE_BITS)); | ||
134 | *op++ = (wchar_t) (SURROGATE_PAIR | | ||
135 | SURROGATE_LOW | | ||
136 | (u & SURROGATE_BITS)); | ||
137 | } else { | ||
138 | *op++ = (wchar_t) u; | ||
139 | } | ||
140 | s += size; | ||
141 | len -= size; | ||
142 | } else { | ||
143 | *op++ = *s++; | ||
144 | len--; | ||
145 | } | ||
146 | } | ||
147 | return op - pwcs; | ||
148 | } | ||
149 | EXPORT_SYMBOL(utf8s_to_utf16s); | ||
150 | |||
151 | static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian) | ||
152 | { | ||
153 | switch (endian) { | ||
154 | default: | ||
155 | return c; | ||
156 | case UTF16_LITTLE_ENDIAN: | ||
157 | return __le16_to_cpu(c); | ||
158 | case UTF16_BIG_ENDIAN: | ||
159 | return __be16_to_cpu(c); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | int utf16s_to_utf8s(const wchar_t *pwcs, int len, enum utf16_endian endian, | ||
164 | u8 *s, int maxlen) | ||
165 | { | ||
166 | u8 *op; | ||
167 | int size; | ||
168 | unsigned long u, v; | ||
139 | 169 | ||
140 | op = s; | 170 | op = s; |
141 | ip = pwcs; | 171 | while (len > 0 && maxlen > 0) { |
142 | while (*ip && maxlen > 0) { | 172 | u = get_utf16(*pwcs, endian); |
143 | if (*ip > 0x7f) { | 173 | if (!u) |
144 | size = utf8_wctomb(op, *ip, maxlen); | 174 | break; |
175 | pwcs++; | ||
176 | len--; | ||
177 | if (u > 0x7f) { | ||
178 | if ((u & SURROGATE_MASK) == SURROGATE_PAIR) { | ||
179 | if (u & SURROGATE_LOW) { | ||
180 | /* Ignore character and move on */ | ||
181 | continue; | ||
182 | } | ||
183 | if (len <= 0) | ||
184 | break; | ||
185 | v = get_utf16(*pwcs, endian); | ||
186 | if ((v & SURROGATE_MASK) != SURROGATE_PAIR || | ||
187 | !(v & SURROGATE_LOW)) { | ||
188 | /* Ignore character and move on */ | ||
189 | continue; | ||
190 | } | ||
191 | u = PLANE_SIZE + ((u & SURROGATE_BITS) << 10) | ||
192 | + (v & SURROGATE_BITS); | ||
193 | pwcs++; | ||
194 | len--; | ||
195 | } | ||
196 | size = utf32_to_utf8(u, op, maxlen); | ||
145 | if (size == -1) { | 197 | if (size == -1) { |
146 | /* Ignore character and move on */ | 198 | /* Ignore character and move on */ |
147 | maxlen--; | ||
148 | } else { | 199 | } else { |
149 | op += size; | 200 | op += size; |
150 | maxlen -= size; | 201 | maxlen -= size; |
151 | } | 202 | } |
152 | } else { | 203 | } else { |
153 | *op++ = (__u8) *ip; | 204 | *op++ = (u8) u; |
205 | maxlen--; | ||
154 | } | 206 | } |
155 | ip++; | ||
156 | } | 207 | } |
157 | return (op - s); | 208 | return op - s; |
158 | } | 209 | } |
210 | EXPORT_SYMBOL(utf16s_to_utf8s); | ||
159 | 211 | ||
160 | int register_nls(struct nls_table * nls) | 212 | int register_nls(struct nls_table * nls) |
161 | { | 213 | { |
@@ -467,9 +519,5 @@ EXPORT_SYMBOL(unregister_nls); | |||
467 | EXPORT_SYMBOL(unload_nls); | 519 | EXPORT_SYMBOL(unload_nls); |
468 | EXPORT_SYMBOL(load_nls); | 520 | EXPORT_SYMBOL(load_nls); |
469 | EXPORT_SYMBOL(load_nls_default); | 521 | EXPORT_SYMBOL(load_nls_default); |
470 | EXPORT_SYMBOL(utf8_mbtowc); | ||
471 | EXPORT_SYMBOL(utf8_mbstowcs); | ||
472 | EXPORT_SYMBOL(utf8_wctomb); | ||
473 | EXPORT_SYMBOL(utf8_wcstombs); | ||
474 | 522 | ||
475 | MODULE_LICENSE("Dual BSD/GPL"); | 523 | MODULE_LICENSE("Dual BSD/GPL"); |
diff --git a/fs/nls/nls_utf8.c b/fs/nls/nls_utf8.c index aa2c42fdd977..0d60a44acacd 100644 --- a/fs/nls/nls_utf8.c +++ b/fs/nls/nls_utf8.c | |||
@@ -15,7 +15,11 @@ static int uni2char(wchar_t uni, unsigned char *out, int boundlen) | |||
15 | { | 15 | { |
16 | int n; | 16 | int n; |
17 | 17 | ||
18 | if ( (n = utf8_wctomb(out, uni, boundlen)) == -1) { | 18 | if (boundlen <= 0) |
19 | return -ENAMETOOLONG; | ||
20 | |||
21 | n = utf32_to_utf8(uni, out, boundlen); | ||
22 | if (n < 0) { | ||
19 | *out = '?'; | 23 | *out = '?'; |
20 | return -EINVAL; | 24 | return -EINVAL; |
21 | } | 25 | } |
@@ -25,11 +29,14 @@ static int uni2char(wchar_t uni, unsigned char *out, int boundlen) | |||
25 | static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) | 29 | static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) |
26 | { | 30 | { |
27 | int n; | 31 | int n; |
32 | unicode_t u; | ||
28 | 33 | ||
29 | if ( (n = utf8_mbtowc(uni, rawstring, boundlen)) == -1) { | 34 | n = utf8_to_utf32(rawstring, boundlen, &u); |
35 | if (n < 0 || u > MAX_WCHAR_T) { | ||
30 | *uni = 0x003f; /* ? */ | 36 | *uni = 0x003f; /* ? */ |
31 | n = -EINVAL; | 37 | return -EINVAL; |
32 | } | 38 | } |
39 | *uni = (wchar_t) u; | ||
33 | return n; | 40 | return n; |
34 | } | 41 | } |
35 | 42 | ||
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 82c5085559c6..9938034762cc 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
28 | #include <linux/quotaops.h> | 28 | #include <linux/quotaops.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/log2.h> | ||
30 | 31 | ||
31 | #include "aops.h" | 32 | #include "aops.h" |
32 | #include "attrib.h" | 33 | #include "attrib.h" |
@@ -1570,7 +1571,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1570 | ntfs_debug("Index collation rule is 0x%x.", | 1571 | ntfs_debug("Index collation rule is 0x%x.", |
1571 | le32_to_cpu(ir->collation_rule)); | 1572 | le32_to_cpu(ir->collation_rule)); |
1572 | ni->itype.index.block_size = le32_to_cpu(ir->index_block_size); | 1573 | ni->itype.index.block_size = le32_to_cpu(ir->index_block_size); |
1573 | if (ni->itype.index.block_size & (ni->itype.index.block_size - 1)) { | 1574 | if (!is_power_of_2(ni->itype.index.block_size)) { |
1574 | ntfs_error(vi->i_sb, "Index block size (%u) is not a power of " | 1575 | ntfs_error(vi->i_sb, "Index block size (%u) is not a power of " |
1575 | "two.", ni->itype.index.block_size); | 1576 | "two.", ni->itype.index.block_size); |
1576 | goto unm_err_out; | 1577 | goto unm_err_out; |
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index d7932e95b1fd..89b02985c054 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/highmem.h> | 26 | #include <linux/highmem.h> |
27 | #include <linux/buffer_head.h> | 27 | #include <linux/buffer_head.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/log2.h> | ||
29 | 30 | ||
30 | #include "attrib.h" | 31 | #include "attrib.h" |
31 | #include "aops.h" | 32 | #include "aops.h" |
@@ -65,7 +66,7 @@ static bool ntfs_check_restart_page_header(struct inode *vi, | |||
65 | logfile_log_page_size < NTFS_BLOCK_SIZE || | 66 | logfile_log_page_size < NTFS_BLOCK_SIZE || |
66 | logfile_system_page_size & | 67 | logfile_system_page_size & |
67 | (logfile_system_page_size - 1) || | 68 | (logfile_system_page_size - 1) || |
68 | logfile_log_page_size & (logfile_log_page_size - 1)) { | 69 | !is_power_of_2(logfile_log_page_size)) { |
69 | ntfs_error(vi->i_sb, "$LogFile uses unsupported page size."); | 70 | ntfs_error(vi->i_sb, "$LogFile uses unsupported page size."); |
70 | return false; | 71 | return false; |
71 | } | 72 | } |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1539e630c47d..3ce5ae9e3d2d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1006,7 +1006,12 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf, | |||
1006 | 1006 | ||
1007 | if (!task) | 1007 | if (!task) |
1008 | return -ESRCH; | 1008 | return -ESRCH; |
1009 | oom_adjust = task->oomkilladj; | 1009 | task_lock(task); |
1010 | if (task->mm) | ||
1011 | oom_adjust = task->mm->oom_adj; | ||
1012 | else | ||
1013 | oom_adjust = OOM_DISABLE; | ||
1014 | task_unlock(task); | ||
1010 | put_task_struct(task); | 1015 | put_task_struct(task); |
1011 | 1016 | ||
1012 | len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); | 1017 | len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); |
@@ -1035,11 +1040,19 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1035 | task = get_proc_task(file->f_path.dentry->d_inode); | 1040 | task = get_proc_task(file->f_path.dentry->d_inode); |
1036 | if (!task) | 1041 | if (!task) |
1037 | return -ESRCH; | 1042 | return -ESRCH; |
1038 | if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) { | 1043 | task_lock(task); |
1044 | if (!task->mm) { | ||
1045 | task_unlock(task); | ||
1046 | put_task_struct(task); | ||
1047 | return -EINVAL; | ||
1048 | } | ||
1049 | if (oom_adjust < task->mm->oom_adj && !capable(CAP_SYS_RESOURCE)) { | ||
1050 | task_unlock(task); | ||
1039 | put_task_struct(task); | 1051 | put_task_struct(task); |
1040 | return -EACCES; | 1052 | return -EACCES; |
1041 | } | 1053 | } |
1042 | task->oomkilladj = oom_adjust; | 1054 | task->mm->oom_adj = oom_adjust; |
1055 | task_unlock(task); | ||
1043 | put_task_struct(task); | 1056 | put_task_struct(task); |
1044 | if (end - buffer == 0) | 1057 | if (end - buffer == 0) |
1045 | return -EIO; | 1058 | return -EIO; |
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index c6b0302af4c4..d5c410d47fae 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c | |||
@@ -64,10 +64,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v) | |||
64 | "Inactive(anon): %8lu kB\n" | 64 | "Inactive(anon): %8lu kB\n" |
65 | "Active(file): %8lu kB\n" | 65 | "Active(file): %8lu kB\n" |
66 | "Inactive(file): %8lu kB\n" | 66 | "Inactive(file): %8lu kB\n" |
67 | #ifdef CONFIG_UNEVICTABLE_LRU | ||
68 | "Unevictable: %8lu kB\n" | 67 | "Unevictable: %8lu kB\n" |
69 | "Mlocked: %8lu kB\n" | 68 | "Mlocked: %8lu kB\n" |
70 | #endif | ||
71 | #ifdef CONFIG_HIGHMEM | 69 | #ifdef CONFIG_HIGHMEM |
72 | "HighTotal: %8lu kB\n" | 70 | "HighTotal: %8lu kB\n" |
73 | "HighFree: %8lu kB\n" | 71 | "HighFree: %8lu kB\n" |
@@ -109,10 +107,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v) | |||
109 | K(pages[LRU_INACTIVE_ANON]), | 107 | K(pages[LRU_INACTIVE_ANON]), |
110 | K(pages[LRU_ACTIVE_FILE]), | 108 | K(pages[LRU_ACTIVE_FILE]), |
111 | K(pages[LRU_INACTIVE_FILE]), | 109 | K(pages[LRU_INACTIVE_FILE]), |
112 | #ifdef CONFIG_UNEVICTABLE_LRU | ||
113 | K(pages[LRU_UNEVICTABLE]), | 110 | K(pages[LRU_UNEVICTABLE]), |
114 | K(global_page_state(NR_MLOCK)), | 111 | K(global_page_state(NR_MLOCK)), |
115 | #endif | ||
116 | #ifdef CONFIG_HIGHMEM | 112 | #ifdef CONFIG_HIGHMEM |
117 | K(i.totalhigh), | 113 | K(i.totalhigh), |
118 | K(i.freehigh), | 114 | K(i.freehigh), |
diff --git a/fs/proc/page.c b/fs/proc/page.c index e9983837d08d..2707c6c7a20f 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c | |||
@@ -6,11 +6,13 @@ | |||
6 | #include <linux/mmzone.h> | 6 | #include <linux/mmzone.h> |
7 | #include <linux/proc_fs.h> | 7 | #include <linux/proc_fs.h> |
8 | #include <linux/seq_file.h> | 8 | #include <linux/seq_file.h> |
9 | #include <linux/hugetlb.h> | ||
9 | #include <asm/uaccess.h> | 10 | #include <asm/uaccess.h> |
10 | #include "internal.h" | 11 | #include "internal.h" |
11 | 12 | ||
12 | #define KPMSIZE sizeof(u64) | 13 | #define KPMSIZE sizeof(u64) |
13 | #define KPMMASK (KPMSIZE - 1) | 14 | #define KPMMASK (KPMSIZE - 1) |
15 | |||
14 | /* /proc/kpagecount - an array exposing page counts | 16 | /* /proc/kpagecount - an array exposing page counts |
15 | * | 17 | * |
16 | * Each entry is a u64 representing the corresponding | 18 | * Each entry is a u64 representing the corresponding |
@@ -32,20 +34,22 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf, | |||
32 | return -EINVAL; | 34 | return -EINVAL; |
33 | 35 | ||
34 | while (count > 0) { | 36 | while (count > 0) { |
35 | ppage = NULL; | ||
36 | if (pfn_valid(pfn)) | 37 | if (pfn_valid(pfn)) |
37 | ppage = pfn_to_page(pfn); | 38 | ppage = pfn_to_page(pfn); |
38 | pfn++; | 39 | else |
40 | ppage = NULL; | ||
39 | if (!ppage) | 41 | if (!ppage) |
40 | pcount = 0; | 42 | pcount = 0; |
41 | else | 43 | else |
42 | pcount = page_mapcount(ppage); | 44 | pcount = page_mapcount(ppage); |
43 | 45 | ||
44 | if (put_user(pcount, out++)) { | 46 | if (put_user(pcount, out)) { |
45 | ret = -EFAULT; | 47 | ret = -EFAULT; |
46 | break; | 48 | break; |
47 | } | 49 | } |
48 | 50 | ||
51 | pfn++; | ||
52 | out++; | ||
49 | count -= KPMSIZE; | 53 | count -= KPMSIZE; |
50 | } | 54 | } |
51 | 55 | ||
@@ -68,19 +72,122 @@ static const struct file_operations proc_kpagecount_operations = { | |||
68 | 72 | ||
69 | /* These macros are used to decouple internal flags from exported ones */ | 73 | /* These macros are used to decouple internal flags from exported ones */ |
70 | 74 | ||
71 | #define KPF_LOCKED 0 | 75 | #define KPF_LOCKED 0 |
72 | #define KPF_ERROR 1 | 76 | #define KPF_ERROR 1 |
73 | #define KPF_REFERENCED 2 | 77 | #define KPF_REFERENCED 2 |
74 | #define KPF_UPTODATE 3 | 78 | #define KPF_UPTODATE 3 |
75 | #define KPF_DIRTY 4 | 79 | #define KPF_DIRTY 4 |
76 | #define KPF_LRU 5 | 80 | #define KPF_LRU 5 |
77 | #define KPF_ACTIVE 6 | 81 | #define KPF_ACTIVE 6 |
78 | #define KPF_SLAB 7 | 82 | #define KPF_SLAB 7 |
79 | #define KPF_WRITEBACK 8 | 83 | #define KPF_WRITEBACK 8 |
80 | #define KPF_RECLAIM 9 | 84 | #define KPF_RECLAIM 9 |
81 | #define KPF_BUDDY 10 | 85 | #define KPF_BUDDY 10 |
86 | |||
87 | /* 11-20: new additions in 2.6.31 */ | ||
88 | #define KPF_MMAP 11 | ||
89 | #define KPF_ANON 12 | ||
90 | #define KPF_SWAPCACHE 13 | ||
91 | #define KPF_SWAPBACKED 14 | ||
92 | #define KPF_COMPOUND_HEAD 15 | ||
93 | #define KPF_COMPOUND_TAIL 16 | ||
94 | #define KPF_HUGE 17 | ||
95 | #define KPF_UNEVICTABLE 18 | ||
96 | #define KPF_NOPAGE 20 | ||
97 | |||
98 | /* kernel hacking assistances | ||
99 | * WARNING: subject to change, never rely on them! | ||
100 | */ | ||
101 | #define KPF_RESERVED 32 | ||
102 | #define KPF_MLOCKED 33 | ||
103 | #define KPF_MAPPEDTODISK 34 | ||
104 | #define KPF_PRIVATE 35 | ||
105 | #define KPF_PRIVATE_2 36 | ||
106 | #define KPF_OWNER_PRIVATE 37 | ||
107 | #define KPF_ARCH 38 | ||
108 | #define KPF_UNCACHED 39 | ||
109 | |||
110 | static inline u64 kpf_copy_bit(u64 kflags, int ubit, int kbit) | ||
111 | { | ||
112 | return ((kflags >> kbit) & 1) << ubit; | ||
113 | } | ||
82 | 114 | ||
83 | #define kpf_copy_bit(flags, dstpos, srcpos) (((flags >> srcpos) & 1) << dstpos) | 115 | static u64 get_uflags(struct page *page) |
116 | { | ||
117 | u64 k; | ||
118 | u64 u; | ||
119 | |||
120 | /* | ||
121 | * pseudo flag: KPF_NOPAGE | ||
122 | * it differentiates a memory hole from a page with no flags | ||
123 | */ | ||
124 | if (!page) | ||
125 | return 1 << KPF_NOPAGE; | ||
126 | |||
127 | k = page->flags; | ||
128 | u = 0; | ||
129 | |||
130 | /* | ||
131 | * pseudo flags for the well known (anonymous) memory mapped pages | ||
132 | * | ||
133 | * Note that page->_mapcount is overloaded in SLOB/SLUB/SLQB, so the | ||
134 | * simple test in page_mapped() is not enough. | ||
135 | */ | ||
136 | if (!PageSlab(page) && page_mapped(page)) | ||
137 | u |= 1 << KPF_MMAP; | ||
138 | if (PageAnon(page)) | ||
139 | u |= 1 << KPF_ANON; | ||
140 | |||
141 | /* | ||
142 | * compound pages: export both head/tail info | ||
143 | * they together define a compound page's start/end pos and order | ||
144 | */ | ||
145 | if (PageHead(page)) | ||
146 | u |= 1 << KPF_COMPOUND_HEAD; | ||
147 | if (PageTail(page)) | ||
148 | u |= 1 << KPF_COMPOUND_TAIL; | ||
149 | if (PageHuge(page)) | ||
150 | u |= 1 << KPF_HUGE; | ||
151 | |||
152 | u |= kpf_copy_bit(k, KPF_LOCKED, PG_locked); | ||
153 | |||
154 | /* | ||
155 | * Caveats on high order pages: | ||
156 | * PG_buddy will only be set on the head page; SLUB/SLQB do the same | ||
157 | * for PG_slab; SLOB won't set PG_slab at all on compound pages. | ||
158 | */ | ||
159 | u |= kpf_copy_bit(k, KPF_SLAB, PG_slab); | ||
160 | u |= kpf_copy_bit(k, KPF_BUDDY, PG_buddy); | ||
161 | |||
162 | u |= kpf_copy_bit(k, KPF_ERROR, PG_error); | ||
163 | u |= kpf_copy_bit(k, KPF_DIRTY, PG_dirty); | ||
164 | u |= kpf_copy_bit(k, KPF_UPTODATE, PG_uptodate); | ||
165 | u |= kpf_copy_bit(k, KPF_WRITEBACK, PG_writeback); | ||
166 | |||
167 | u |= kpf_copy_bit(k, KPF_LRU, PG_lru); | ||
168 | u |= kpf_copy_bit(k, KPF_REFERENCED, PG_referenced); | ||
169 | u |= kpf_copy_bit(k, KPF_ACTIVE, PG_active); | ||
170 | u |= kpf_copy_bit(k, KPF_RECLAIM, PG_reclaim); | ||
171 | |||
172 | u |= kpf_copy_bit(k, KPF_SWAPCACHE, PG_swapcache); | ||
173 | u |= kpf_copy_bit(k, KPF_SWAPBACKED, PG_swapbacked); | ||
174 | |||
175 | u |= kpf_copy_bit(k, KPF_UNEVICTABLE, PG_unevictable); | ||
176 | u |= kpf_copy_bit(k, KPF_MLOCKED, PG_mlocked); | ||
177 | |||
178 | #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR | ||
179 | u |= kpf_copy_bit(k, KPF_UNCACHED, PG_uncached); | ||
180 | #endif | ||
181 | |||
182 | u |= kpf_copy_bit(k, KPF_RESERVED, PG_reserved); | ||
183 | u |= kpf_copy_bit(k, KPF_MAPPEDTODISK, PG_mappedtodisk); | ||
184 | u |= kpf_copy_bit(k, KPF_PRIVATE, PG_private); | ||
185 | u |= kpf_copy_bit(k, KPF_PRIVATE_2, PG_private_2); | ||
186 | u |= kpf_copy_bit(k, KPF_OWNER_PRIVATE, PG_owner_priv_1); | ||
187 | u |= kpf_copy_bit(k, KPF_ARCH, PG_arch_1); | ||
188 | |||
189 | return u; | ||
190 | }; | ||
84 | 191 | ||
85 | static ssize_t kpageflags_read(struct file *file, char __user *buf, | 192 | static ssize_t kpageflags_read(struct file *file, char __user *buf, |
86 | size_t count, loff_t *ppos) | 193 | size_t count, loff_t *ppos) |
@@ -90,7 +197,6 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, | |||
90 | unsigned long src = *ppos; | 197 | unsigned long src = *ppos; |
91 | unsigned long pfn; | 198 | unsigned long pfn; |
92 | ssize_t ret = 0; | 199 | ssize_t ret = 0; |
93 | u64 kflags, uflags; | ||
94 | 200 | ||
95 | pfn = src / KPMSIZE; | 201 | pfn = src / KPMSIZE; |
96 | count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src); | 202 | count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src); |
@@ -98,32 +204,18 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, | |||
98 | return -EINVAL; | 204 | return -EINVAL; |
99 | 205 | ||
100 | while (count > 0) { | 206 | while (count > 0) { |
101 | ppage = NULL; | ||
102 | if (pfn_valid(pfn)) | 207 | if (pfn_valid(pfn)) |
103 | ppage = pfn_to_page(pfn); | 208 | ppage = pfn_to_page(pfn); |
104 | pfn++; | ||
105 | if (!ppage) | ||
106 | kflags = 0; | ||
107 | else | 209 | else |
108 | kflags = ppage->flags; | 210 | ppage = NULL; |
109 | 211 | ||
110 | uflags = kpf_copy_bit(kflags, KPF_LOCKED, PG_locked) | | 212 | if (put_user(get_uflags(ppage), out)) { |
111 | kpf_copy_bit(kflags, KPF_ERROR, PG_error) | | ||
112 | kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) | | ||
113 | kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) | | ||
114 | kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) | | ||
115 | kpf_copy_bit(kflags, KPF_LRU, PG_lru) | | ||
116 | kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) | | ||
117 | kpf_copy_bit(kflags, KPF_SLAB, PG_slab) | | ||
118 | kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) | | ||
119 | kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) | | ||
120 | kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy); | ||
121 | |||
122 | if (put_user(uflags, out++)) { | ||
123 | ret = -EFAULT; | 213 | ret = -EFAULT; |
124 | break; | 214 | break; |
125 | } | 215 | } |
126 | 216 | ||
217 | pfn++; | ||
218 | out++; | ||
127 | count -= KPMSIZE; | 219 | count -= KPMSIZE; |
128 | } | 220 | } |
129 | 221 | ||
diff --git a/fs/select.c b/fs/select.c index 0fe0e1469df3..d870237e42c7 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -168,7 +168,7 @@ static struct poll_table_entry *poll_get_entry(struct poll_wqueues *p) | |||
168 | return table->entry++; | 168 | return table->entry++; |
169 | } | 169 | } |
170 | 170 | ||
171 | static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) | 171 | static int __pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) |
172 | { | 172 | { |
173 | struct poll_wqueues *pwq = wait->private; | 173 | struct poll_wqueues *pwq = wait->private; |
174 | DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task); | 174 | DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task); |
@@ -194,6 +194,16 @@ static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) | |||
194 | return default_wake_function(&dummy_wait, mode, sync, key); | 194 | return default_wake_function(&dummy_wait, mode, sync, key); |
195 | } | 195 | } |
196 | 196 | ||
197 | static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) | ||
198 | { | ||
199 | struct poll_table_entry *entry; | ||
200 | |||
201 | entry = container_of(wait, struct poll_table_entry, wait); | ||
202 | if (key && !((unsigned long)key & entry->key)) | ||
203 | return 0; | ||
204 | return __pollwake(wait, mode, sync, key); | ||
205 | } | ||
206 | |||
197 | /* Add a new entry */ | 207 | /* Add a new entry */ |
198 | static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | 208 | static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, |
199 | poll_table *p) | 209 | poll_table *p) |
@@ -205,6 +215,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | |||
205 | get_file(filp); | 215 | get_file(filp); |
206 | entry->filp = filp; | 216 | entry->filp = filp; |
207 | entry->wait_address = wait_address; | 217 | entry->wait_address = wait_address; |
218 | entry->key = p->key; | ||
208 | init_waitqueue_func_entry(&entry->wait, pollwake); | 219 | init_waitqueue_func_entry(&entry->wait, pollwake); |
209 | entry->wait.private = pwq; | 220 | entry->wait.private = pwq; |
210 | add_wait_queue(wait_address, &entry->wait); | 221 | add_wait_queue(wait_address, &entry->wait); |
@@ -362,6 +373,18 @@ get_max: | |||
362 | #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) | 373 | #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) |
363 | #define POLLEX_SET (POLLPRI) | 374 | #define POLLEX_SET (POLLPRI) |
364 | 375 | ||
376 | static inline void wait_key_set(poll_table *wait, unsigned long in, | ||
377 | unsigned long out, unsigned long bit) | ||
378 | { | ||
379 | if (wait) { | ||
380 | wait->key = POLLEX_SET; | ||
381 | if (in & bit) | ||
382 | wait->key |= POLLIN_SET; | ||
383 | if (out & bit) | ||
384 | wait->key |= POLLOUT_SET; | ||
385 | } | ||
386 | } | ||
387 | |||
365 | int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | 388 | int do_select(int n, fd_set_bits *fds, struct timespec *end_time) |
366 | { | 389 | { |
367 | ktime_t expire, *to = NULL; | 390 | ktime_t expire, *to = NULL; |
@@ -418,20 +441,25 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) | |||
418 | if (file) { | 441 | if (file) { |
419 | f_op = file->f_op; | 442 | f_op = file->f_op; |
420 | mask = DEFAULT_POLLMASK; | 443 | mask = DEFAULT_POLLMASK; |
421 | if (f_op && f_op->poll) | 444 | if (f_op && f_op->poll) { |
422 | mask = (*f_op->poll)(file, retval ? NULL : wait); | 445 | wait_key_set(wait, in, out, bit); |
446 | mask = (*f_op->poll)(file, wait); | ||
447 | } | ||
423 | fput_light(file, fput_needed); | 448 | fput_light(file, fput_needed); |
424 | if ((mask & POLLIN_SET) && (in & bit)) { | 449 | if ((mask & POLLIN_SET) && (in & bit)) { |
425 | res_in |= bit; | 450 | res_in |= bit; |
426 | retval++; | 451 | retval++; |
452 | wait = NULL; | ||
427 | } | 453 | } |
428 | if ((mask & POLLOUT_SET) && (out & bit)) { | 454 | if ((mask & POLLOUT_SET) && (out & bit)) { |
429 | res_out |= bit; | 455 | res_out |= bit; |
430 | retval++; | 456 | retval++; |
457 | wait = NULL; | ||
431 | } | 458 | } |
432 | if ((mask & POLLEX_SET) && (ex & bit)) { | 459 | if ((mask & POLLEX_SET) && (ex & bit)) { |
433 | res_ex |= bit; | 460 | res_ex |= bit; |
434 | retval++; | 461 | retval++; |
462 | wait = NULL; | ||
435 | } | 463 | } |
436 | } | 464 | } |
437 | } | 465 | } |
@@ -685,8 +713,12 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) | |||
685 | mask = POLLNVAL; | 713 | mask = POLLNVAL; |
686 | if (file != NULL) { | 714 | if (file != NULL) { |
687 | mask = DEFAULT_POLLMASK; | 715 | mask = DEFAULT_POLLMASK; |
688 | if (file->f_op && file->f_op->poll) | 716 | if (file->f_op && file->f_op->poll) { |
717 | if (pwait) | ||
718 | pwait->key = pollfd->events | | ||
719 | POLLERR | POLLHUP; | ||
689 | mask = file->f_op->poll(file, pwait); | 720 | mask = file->f_op->poll(file, pwait); |
721 | } | ||
690 | /* Mask out unneeded events. */ | 722 | /* Mask out unneeded events. */ |
691 | mask &= pollfd->events | POLLERR | POLLHUP; | 723 | mask &= pollfd->events | POLLERR | POLLHUP; |
692 | fput_light(file, fput_needed); | 724 | fput_light(file, fput_needed); |
diff --git a/fs/super.c b/fs/super.c index 83b47416d006..d40d53a22fb5 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -545,24 +545,18 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
545 | if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) { | 545 | if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) { |
546 | if (force) | 546 | if (force) |
547 | mark_files_ro(sb); | 547 | mark_files_ro(sb); |
548 | else if (!fs_may_remount_ro(sb)) { | 548 | else if (!fs_may_remount_ro(sb)) |
549 | unlock_kernel(); | ||
550 | return -EBUSY; | 549 | return -EBUSY; |
551 | } | ||
552 | retval = vfs_dq_off(sb, 1); | 550 | retval = vfs_dq_off(sb, 1); |
553 | if (retval < 0 && retval != -ENOSYS) { | 551 | if (retval < 0 && retval != -ENOSYS) |
554 | unlock_kernel(); | ||
555 | return -EBUSY; | 552 | return -EBUSY; |
556 | } | ||
557 | } | 553 | } |
558 | remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); | 554 | remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); |
559 | 555 | ||
560 | if (sb->s_op->remount_fs) { | 556 | if (sb->s_op->remount_fs) { |
561 | retval = sb->s_op->remount_fs(sb, &flags, data); | 557 | retval = sb->s_op->remount_fs(sb, &flags, data); |
562 | if (retval) { | 558 | if (retval) |
563 | unlock_kernel(); | ||
564 | return retval; | 559 | return retval; |
565 | } | ||
566 | } | 560 | } |
567 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); | 561 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); |
568 | if (remount_rw) | 562 | if (remount_rw) |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index a3ba217fbe74..1d897ad808e0 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -192,8 +192,11 @@ static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
192 | { | 192 | { |
193 | int error = -ENOMEM; | 193 | int error = -ENOMEM; |
194 | unsigned long page = get_zeroed_page(GFP_KERNEL); | 194 | unsigned long page = get_zeroed_page(GFP_KERNEL); |
195 | if (page) | 195 | if (page) { |
196 | error = sysfs_getlink(dentry, (char *) page); | 196 | error = sysfs_getlink(dentry, (char *) page); |
197 | if (error < 0) | ||
198 | free_page((unsigned long)page); | ||
199 | } | ||
197 | nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); | 200 | nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); |
198 | return NULL; | 201 | return NULL; |
199 | } | 202 | } |
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index c7798079e644..4e50286a4cc3 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -15,13 +15,13 @@ | |||
15 | 15 | ||
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/smp_lock.h> | ||
19 | #include <linux/swap.h> | 18 | #include <linux/swap.h> |
20 | #include "sysv.h" | 19 | #include "sysv.h" |
21 | 20 | ||
22 | static int sysv_readdir(struct file *, void *, filldir_t); | 21 | static int sysv_readdir(struct file *, void *, filldir_t); |
23 | 22 | ||
24 | const struct file_operations sysv_dir_operations = { | 23 | const struct file_operations sysv_dir_operations = { |
24 | .llseek = generic_file_llseek, | ||
25 | .read = generic_read_dir, | 25 | .read = generic_read_dir, |
26 | .readdir = sysv_readdir, | 26 | .readdir = sysv_readdir, |
27 | .fsync = simple_fsync, | 27 | .fsync = simple_fsync, |
@@ -74,8 +74,6 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
74 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | 74 | unsigned long n = pos >> PAGE_CACHE_SHIFT; |
75 | unsigned long npages = dir_pages(inode); | 75 | unsigned long npages = dir_pages(inode); |
76 | 76 | ||
77 | lock_kernel(); | ||
78 | |||
79 | pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); | 77 | pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); |
80 | if (pos >= inode->i_size) | 78 | if (pos >= inode->i_size) |
81 | goto done; | 79 | goto done; |
@@ -113,7 +111,6 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
113 | 111 | ||
114 | done: | 112 | done: |
115 | filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset; | 113 | filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset; |
116 | unlock_kernel(); | ||
117 | return 0; | 114 | return 0; |
118 | } | 115 | } |
119 | 116 | ||
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 479923456a54..9824743832a7 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * the superblock. | 21 | * the superblock. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/smp_lock.h> | ||
25 | #include <linux/highuid.h> | 24 | #include <linux/highuid.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
@@ -37,7 +36,6 @@ static int sysv_sync_fs(struct super_block *sb, int wait) | |||
37 | unsigned long time = get_seconds(), old_time; | 36 | unsigned long time = get_seconds(), old_time; |
38 | 37 | ||
39 | lock_super(sb); | 38 | lock_super(sb); |
40 | lock_kernel(); | ||
41 | 39 | ||
42 | /* | 40 | /* |
43 | * If we are going to write out the super block, | 41 | * If we are going to write out the super block, |
@@ -52,7 +50,6 @@ static int sysv_sync_fs(struct super_block *sb, int wait) | |||
52 | mark_buffer_dirty(sbi->s_bh2); | 50 | mark_buffer_dirty(sbi->s_bh2); |
53 | } | 51 | } |
54 | 52 | ||
55 | unlock_kernel(); | ||
56 | unlock_super(sb); | 53 | unlock_super(sb); |
57 | 54 | ||
58 | return 0; | 55 | return 0; |
@@ -82,8 +79,6 @@ static void sysv_put_super(struct super_block *sb) | |||
82 | { | 79 | { |
83 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 80 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
84 | 81 | ||
85 | lock_kernel(); | ||
86 | |||
87 | if (sb->s_dirt) | 82 | if (sb->s_dirt) |
88 | sysv_write_super(sb); | 83 | sysv_write_super(sb); |
89 | 84 | ||
@@ -99,8 +94,6 @@ static void sysv_put_super(struct super_block *sb) | |||
99 | brelse(sbi->s_bh2); | 94 | brelse(sbi->s_bh2); |
100 | 95 | ||
101 | kfree(sbi); | 96 | kfree(sbi); |
102 | |||
103 | unlock_kernel(); | ||
104 | } | 97 | } |
105 | 98 | ||
106 | static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) | 99 | static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) |
@@ -275,7 +268,6 @@ int sysv_write_inode(struct inode *inode, int wait) | |||
275 | return -EIO; | 268 | return -EIO; |
276 | } | 269 | } |
277 | 270 | ||
278 | lock_kernel(); | ||
279 | raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode); | 271 | raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode); |
280 | raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid)); | 272 | raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid)); |
281 | raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid)); | 273 | raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid)); |
@@ -291,7 +283,6 @@ int sysv_write_inode(struct inode *inode, int wait) | |||
291 | for (block = 0; block < 10+1+1+1; block++) | 283 | for (block = 0; block < 10+1+1+1; block++) |
292 | write3byte(sbi, (u8 *)&si->i_data[block], | 284 | write3byte(sbi, (u8 *)&si->i_data[block], |
293 | &raw_inode->i_data[3*block]); | 285 | &raw_inode->i_data[3*block]); |
294 | unlock_kernel(); | ||
295 | mark_buffer_dirty(bh); | 286 | mark_buffer_dirty(bh); |
296 | if (wait) { | 287 | if (wait) { |
297 | sync_dirty_buffer(bh); | 288 | sync_dirty_buffer(bh); |
@@ -315,9 +306,7 @@ static void sysv_delete_inode(struct inode *inode) | |||
315 | truncate_inode_pages(&inode->i_data, 0); | 306 | truncate_inode_pages(&inode->i_data, 0); |
316 | inode->i_size = 0; | 307 | inode->i_size = 0; |
317 | sysv_truncate(inode); | 308 | sysv_truncate(inode); |
318 | lock_kernel(); | ||
319 | sysv_free_inode(inode); | 309 | sysv_free_inode(inode); |
320 | unlock_kernel(); | ||
321 | } | 310 | } |
322 | 311 | ||
323 | static struct kmem_cache *sysv_inode_cachep; | 312 | static struct kmem_cache *sysv_inode_cachep; |
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index af1914462f02..eaf6d891d46f 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c | |||
@@ -91,7 +91,6 @@ static int shrink_liability(struct ubifs_info *c, int nr_to_write) | |||
91 | return nr_written; | 91 | return nr_written; |
92 | } | 92 | } |
93 | 93 | ||
94 | |||
95 | /** | 94 | /** |
96 | * run_gc - run garbage collector. | 95 | * run_gc - run garbage collector. |
97 | * @c: UBIFS file-system description object | 96 | * @c: UBIFS file-system description object |
@@ -628,7 +627,7 @@ void ubifs_convert_page_budget(struct ubifs_info *c) | |||
628 | * | 627 | * |
629 | * This function releases budget corresponding to a dirty inode. It is usually | 628 | * This function releases budget corresponding to a dirty inode. It is usually |
630 | * called when after the inode has been written to the media and marked as | 629 | * called when after the inode has been written to the media and marked as |
631 | * clean. | 630 | * clean. It also causes the "no space" flags to be cleared. |
632 | */ | 631 | */ |
633 | void ubifs_release_dirty_inode_budget(struct ubifs_info *c, | 632 | void ubifs_release_dirty_inode_budget(struct ubifs_info *c, |
634 | struct ubifs_inode *ui) | 633 | struct ubifs_inode *ui) |
@@ -636,6 +635,7 @@ void ubifs_release_dirty_inode_budget(struct ubifs_info *c, | |||
636 | struct ubifs_budget_req req; | 635 | struct ubifs_budget_req req; |
637 | 636 | ||
638 | memset(&req, 0, sizeof(struct ubifs_budget_req)); | 637 | memset(&req, 0, sizeof(struct ubifs_budget_req)); |
638 | /* The "no space" flags will be cleared because dd_growth is > 0 */ | ||
639 | req.dd_growth = c->inode_budget + ALIGN(ui->data_len, 8); | 639 | req.dd_growth = c->inode_budget + ALIGN(ui->data_len, 8); |
640 | ubifs_release_budget(c, &req); | 640 | ubifs_release_budget(c, &req); |
641 | } | 641 | } |
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index f55d523c52bb..552fb0111fff 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -528,6 +528,25 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, | |||
528 | inode->i_nlink, dir->i_ino); | 528 | inode->i_nlink, dir->i_ino); |
529 | ubifs_assert(mutex_is_locked(&dir->i_mutex)); | 529 | ubifs_assert(mutex_is_locked(&dir->i_mutex)); |
530 | ubifs_assert(mutex_is_locked(&inode->i_mutex)); | 530 | ubifs_assert(mutex_is_locked(&inode->i_mutex)); |
531 | |||
532 | /* | ||
533 | * Return -ENOENT if we've raced with unlink and i_nlink is 0. Doing | ||
534 | * otherwise has the potential to corrupt the orphan inode list. | ||
535 | * | ||
536 | * Indeed, consider a scenario when 'vfs_link(dirA/fileA)' and | ||
537 | * 'vfs_unlink(dirA/fileA, dirB/fileB)' race. 'vfs_link()' does not | ||
538 | * lock 'dirA->i_mutex', so this is possible. Both of the functions | ||
539 | * lock 'fileA->i_mutex' though. Suppose 'vfs_unlink()' wins, and takes | ||
540 | * 'fileA->i_mutex' mutex first. Suppose 'fileA->i_nlink' is 1. In this | ||
541 | * case 'ubifs_unlink()' will drop the last reference, and put 'inodeA' | ||
542 | * to the list of orphans. After this, 'vfs_link()' will link | ||
543 | * 'dirB/fileB' to 'inodeA'. This is a problem because, for example, | ||
544 | * the subsequent 'vfs_unlink(dirB/fileB)' will add the same inode | ||
545 | * to the list of orphans. | ||
546 | */ | ||
547 | if (inode->i_nlink == 0) | ||
548 | return -ENOENT; | ||
549 | |||
531 | err = dbg_check_synced_i_size(inode); | 550 | err = dbg_check_synced_i_size(inode); |
532 | if (err) | 551 | if (err) |
533 | return err; | 552 | return err; |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index e8e632a1dcdf..bc5857199ec2 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
@@ -293,13 +293,14 @@ void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last) | |||
293 | * | 293 | * |
294 | * This function is called when the write-buffer timer expires. | 294 | * This function is called when the write-buffer timer expires. |
295 | */ | 295 | */ |
296 | static void wbuf_timer_callback_nolock(unsigned long data) | 296 | static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer) |
297 | { | 297 | { |
298 | struct ubifs_wbuf *wbuf = (struct ubifs_wbuf *)data; | 298 | struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer); |
299 | 299 | ||
300 | wbuf->need_sync = 1; | 300 | wbuf->need_sync = 1; |
301 | wbuf->c->need_wbuf_sync = 1; | 301 | wbuf->c->need_wbuf_sync = 1; |
302 | ubifs_wake_up_bgt(wbuf->c); | 302 | ubifs_wake_up_bgt(wbuf->c); |
303 | return HRTIMER_NORESTART; | ||
303 | } | 304 | } |
304 | 305 | ||
305 | /** | 306 | /** |
@@ -308,13 +309,12 @@ static void wbuf_timer_callback_nolock(unsigned long data) | |||
308 | */ | 309 | */ |
309 | static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) | 310 | static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) |
310 | { | 311 | { |
311 | ubifs_assert(!timer_pending(&wbuf->timer)); | 312 | ubifs_assert(!hrtimer_active(&wbuf->timer)); |
312 | 313 | ||
313 | if (!wbuf->timeout) | 314 | if (!ktime_to_ns(wbuf->softlimit)) |
314 | return; | 315 | return; |
315 | 316 | hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta, | |
316 | wbuf->timer.expires = jiffies + wbuf->timeout; | 317 | HRTIMER_MODE_REL); |
317 | add_timer(&wbuf->timer); | ||
318 | } | 318 | } |
319 | 319 | ||
320 | /** | 320 | /** |
@@ -329,7 +329,7 @@ static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf) | |||
329 | * should be canceled. | 329 | * should be canceled. |
330 | */ | 330 | */ |
331 | wbuf->need_sync = 0; | 331 | wbuf->need_sync = 0; |
332 | del_timer(&wbuf->timer); | 332 | hrtimer_cancel(&wbuf->timer); |
333 | } | 333 | } |
334 | 334 | ||
335 | /** | 335 | /** |
@@ -825,6 +825,7 @@ out: | |||
825 | int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) | 825 | int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) |
826 | { | 826 | { |
827 | size_t size; | 827 | size_t size; |
828 | ktime_t hardlimit; | ||
828 | 829 | ||
829 | wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); | 830 | wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); |
830 | if (!wbuf->buf) | 831 | if (!wbuf->buf) |
@@ -845,14 +846,21 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf) | |||
845 | wbuf->sync_callback = NULL; | 846 | wbuf->sync_callback = NULL; |
846 | mutex_init(&wbuf->io_mutex); | 847 | mutex_init(&wbuf->io_mutex); |
847 | spin_lock_init(&wbuf->lock); | 848 | spin_lock_init(&wbuf->lock); |
848 | |||
849 | wbuf->c = c; | 849 | wbuf->c = c; |
850 | init_timer(&wbuf->timer); | ||
851 | wbuf->timer.function = wbuf_timer_callback_nolock; | ||
852 | wbuf->timer.data = (unsigned long)wbuf; | ||
853 | wbuf->timeout = DEFAULT_WBUF_TIMEOUT; | ||
854 | wbuf->next_ino = 0; | 850 | wbuf->next_ino = 0; |
855 | 851 | ||
852 | hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
853 | wbuf->timer.function = wbuf_timer_callback_nolock; | ||
854 | /* | ||
855 | * Make write-buffer soft limit to be 20% of the hard limit. The | ||
856 | * write-buffer timer is allowed to expire any time between the soft | ||
857 | * and hard limits. | ||
858 | */ | ||
859 | hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0); | ||
860 | wbuf->delta = (DEFAULT_WBUF_TIMEOUT_SECS * NSEC_PER_SEC) * 2 / 10; | ||
861 | wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta); | ||
862 | hrtimer_set_expires_range_ns(&wbuf->timer, wbuf->softlimit, | ||
863 | wbuf->delta); | ||
856 | return 0; | 864 | return 0; |
857 | } | 865 | } |
858 | 866 | ||
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 10662975d2ef..805605250f12 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -343,33 +343,15 @@ int ubifs_write_rcvrd_mst_node(struct ubifs_info *c) | |||
343 | * | 343 | * |
344 | * This function returns %1 if @offs was in the last write to the LEB whose data | 344 | * This function returns %1 if @offs was in the last write to the LEB whose data |
345 | * is in @buf, otherwise %0 is returned. The determination is made by checking | 345 | * is in @buf, otherwise %0 is returned. The determination is made by checking |
346 | * for subsequent empty space starting from the next min_io_size boundary (or a | 346 | * for subsequent empty space starting from the next @c->min_io_size boundary. |
347 | * bit less than the common header size if min_io_size is one). | ||
348 | */ | 347 | */ |
349 | static int is_last_write(const struct ubifs_info *c, void *buf, int offs) | 348 | static int is_last_write(const struct ubifs_info *c, void *buf, int offs) |
350 | { | 349 | { |
351 | int empty_offs; | 350 | int empty_offs, check_len; |
352 | int check_len; | ||
353 | uint8_t *p; | 351 | uint8_t *p; |
354 | 352 | ||
355 | if (c->min_io_size == 1) { | ||
356 | check_len = c->leb_size - offs; | ||
357 | p = buf + check_len; | ||
358 | for (; check_len > 0; check_len--) | ||
359 | if (*--p != 0xff) | ||
360 | break; | ||
361 | /* | ||
362 | * 'check_len' is the size of the corruption which cannot be | ||
363 | * more than the size of 1 node if it was caused by an unclean | ||
364 | * unmount. | ||
365 | */ | ||
366 | if (check_len > UBIFS_MAX_NODE_SZ) | ||
367 | return 0; | ||
368 | return 1; | ||
369 | } | ||
370 | |||
371 | /* | 353 | /* |
372 | * Round up to the next c->min_io_size boundary i.e. 'offs' is in the | 354 | * Round up to the next @c->min_io_size boundary i.e. @offs is in the |
373 | * last wbuf written. After that should be empty space. | 355 | * last wbuf written. After that should be empty space. |
374 | */ | 356 | */ |
375 | empty_offs = ALIGN(offs + 1, c->min_io_size); | 357 | empty_offs = ALIGN(offs + 1, c->min_io_size); |
@@ -392,7 +374,7 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs) | |||
392 | * | 374 | * |
393 | * This function pads up to the next min_io_size boundary (if there is one) and | 375 | * This function pads up to the next min_io_size boundary (if there is one) and |
394 | * sets empty space to all 0xff. @buf, @offs and @len are updated to the next | 376 | * sets empty space to all 0xff. @buf, @offs and @len are updated to the next |
395 | * min_io_size boundary (if there is one). | 377 | * @c->min_io_size boundary. |
396 | */ | 378 | */ |
397 | static void clean_buf(const struct ubifs_info *c, void **buf, int lnum, | 379 | static void clean_buf(const struct ubifs_info *c, void **buf, int lnum, |
398 | int *offs, int *len) | 380 | int *offs, int *len) |
@@ -402,11 +384,6 @@ static void clean_buf(const struct ubifs_info *c, void **buf, int lnum, | |||
402 | lnum = lnum; | 384 | lnum = lnum; |
403 | dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs); | 385 | dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs); |
404 | 386 | ||
405 | if (c->min_io_size == 1) { | ||
406 | memset(*buf, 0xff, c->leb_size - *offs); | ||
407 | return; | ||
408 | } | ||
409 | |||
410 | ubifs_assert(!(*offs & 7)); | 387 | ubifs_assert(!(*offs & 7)); |
411 | empty_offs = ALIGN(*offs, c->min_io_size); | 388 | empty_offs = ALIGN(*offs, c->min_io_size); |
412 | pad_len = empty_offs - *offs; | 389 | pad_len = empty_offs - *offs; |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 3260b73abe29..79fad43f3c57 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -361,6 +361,11 @@ static void ubifs_delete_inode(struct inode *inode) | |||
361 | out: | 361 | out: |
362 | if (ui->dirty) | 362 | if (ui->dirty) |
363 | ubifs_release_dirty_inode_budget(c, ui); | 363 | ubifs_release_dirty_inode_budget(c, ui); |
364 | else { | ||
365 | /* We've deleted something - clean the "no space" flags */ | ||
366 | c->nospace = c->nospace_rp = 0; | ||
367 | smp_wmb(); | ||
368 | } | ||
364 | clear_inode(inode); | 369 | clear_inode(inode); |
365 | } | 370 | } |
366 | 371 | ||
@@ -792,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c) | |||
792 | * does not need to be synchronized by timer. | 797 | * does not need to be synchronized by timer. |
793 | */ | 798 | */ |
794 | c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; | 799 | c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM; |
795 | c->jheads[GCHD].wbuf.timeout = 0; | 800 | c->jheads[GCHD].wbuf.softlimit = ktime_set(0, 0); |
796 | 801 | ||
797 | return 0; | 802 | return 0; |
798 | } | 803 | } |
@@ -933,6 +938,27 @@ static const match_table_t tokens = { | |||
933 | }; | 938 | }; |
934 | 939 | ||
935 | /** | 940 | /** |
941 | * parse_standard_option - parse a standard mount option. | ||
942 | * @option: the option to parse | ||
943 | * | ||
944 | * Normally, standard mount options like "sync" are passed to file-systems as | ||
945 | * flags. However, when a "rootflags=" kernel boot parameter is used, they may | ||
946 | * be present in the options string. This function tries to deal with this | ||
947 | * situation and parse standard options. Returns 0 if the option was not | ||
948 | * recognized, and the corresponding integer flag if it was. | ||
949 | * | ||
950 | * UBIFS is only interested in the "sync" option, so do not check for anything | ||
951 | * else. | ||
952 | */ | ||
953 | static int parse_standard_option(const char *option) | ||
954 | { | ||
955 | ubifs_msg("parse %s", option); | ||
956 | if (!strcmp(option, "sync")) | ||
957 | return MS_SYNCHRONOUS; | ||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | /** | ||
936 | * ubifs_parse_options - parse mount parameters. | 962 | * ubifs_parse_options - parse mount parameters. |
937 | * @c: UBIFS file-system description object | 963 | * @c: UBIFS file-system description object |
938 | * @options: parameters to parse | 964 | * @options: parameters to parse |
@@ -1008,9 +1034,19 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, | |||
1008 | break; | 1034 | break; |
1009 | } | 1035 | } |
1010 | default: | 1036 | default: |
1011 | ubifs_err("unrecognized mount option \"%s\" " | 1037 | { |
1012 | "or missing value", p); | 1038 | unsigned long flag; |
1013 | return -EINVAL; | 1039 | struct super_block *sb = c->vfs_sb; |
1040 | |||
1041 | flag = parse_standard_option(p); | ||
1042 | if (!flag) { | ||
1043 | ubifs_err("unrecognized mount option \"%s\" " | ||
1044 | "or missing value", p); | ||
1045 | return -EINVAL; | ||
1046 | } | ||
1047 | sb->s_flags |= flag; | ||
1048 | break; | ||
1049 | } | ||
1014 | } | 1050 | } |
1015 | } | 1051 | } |
1016 | 1052 | ||
@@ -1180,6 +1216,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1180 | if (!ubifs_compr_present(c->default_compr)) { | 1216 | if (!ubifs_compr_present(c->default_compr)) { |
1181 | ubifs_err("'compressor \"%s\" is not compiled in", | 1217 | ubifs_err("'compressor \"%s\" is not compiled in", |
1182 | ubifs_compr_name(c->default_compr)); | 1218 | ubifs_compr_name(c->default_compr)); |
1219 | err = -ENOTSUPP; | ||
1183 | goto out_free; | 1220 | goto out_free; |
1184 | } | 1221 | } |
1185 | 1222 | ||
@@ -1656,7 +1693,7 @@ static void ubifs_remount_ro(struct ubifs_info *c) | |||
1656 | 1693 | ||
1657 | for (i = 0; i < c->jhead_cnt; i++) { | 1694 | for (i = 0; i < c->jhead_cnt; i++) { |
1658 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | 1695 | ubifs_wbuf_sync(&c->jheads[i].wbuf); |
1659 | del_timer_sync(&c->jheads[i].wbuf.timer); | 1696 | hrtimer_cancel(&c->jheads[i].wbuf.timer); |
1660 | } | 1697 | } |
1661 | 1698 | ||
1662 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); | 1699 | c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); |
@@ -1719,7 +1756,7 @@ static void ubifs_put_super(struct super_block *sb) | |||
1719 | if (c->jheads) | 1756 | if (c->jheads) |
1720 | for (i = 0; i < c->jhead_cnt; i++) { | 1757 | for (i = 0; i < c->jhead_cnt; i++) { |
1721 | ubifs_wbuf_sync(&c->jheads[i].wbuf); | 1758 | ubifs_wbuf_sync(&c->jheads[i].wbuf); |
1722 | del_timer_sync(&c->jheads[i].wbuf.timer); | 1759 | hrtimer_cancel(&c->jheads[i].wbuf.timer); |
1723 | } | 1760 | } |
1724 | 1761 | ||
1725 | /* | 1762 | /* |
@@ -1911,6 +1948,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
1911 | INIT_LIST_HEAD(&c->orph_list); | 1948 | INIT_LIST_HEAD(&c->orph_list); |
1912 | INIT_LIST_HEAD(&c->orph_new); | 1949 | INIT_LIST_HEAD(&c->orph_new); |
1913 | 1950 | ||
1951 | c->vfs_sb = sb; | ||
1914 | c->highest_inum = UBIFS_FIRST_INO; | 1952 | c->highest_inum = UBIFS_FIRST_INO; |
1915 | c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; | 1953 | c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; |
1916 | 1954 | ||
@@ -1945,13 +1983,10 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
1945 | if (err) | 1983 | if (err) |
1946 | goto out_bdi; | 1984 | goto out_bdi; |
1947 | 1985 | ||
1948 | c->vfs_sb = sb; | ||
1949 | |||
1950 | sb->s_fs_info = c; | 1986 | sb->s_fs_info = c; |
1951 | sb->s_magic = UBIFS_SUPER_MAGIC; | 1987 | sb->s_magic = UBIFS_SUPER_MAGIC; |
1952 | sb->s_blocksize = UBIFS_BLOCK_SIZE; | 1988 | sb->s_blocksize = UBIFS_BLOCK_SIZE; |
1953 | sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; | 1989 | sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; |
1954 | sb->s_dev = c->vi.cdev; | ||
1955 | sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); | 1990 | sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); |
1956 | if (c->max_inode_sz > MAX_LFS_FILESIZE) | 1991 | if (c->max_inode_sz > MAX_LFS_FILESIZE) |
1957 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; | 1992 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; |
@@ -1996,16 +2031,9 @@ out_free: | |||
1996 | static int sb_test(struct super_block *sb, void *data) | 2031 | static int sb_test(struct super_block *sb, void *data) |
1997 | { | 2032 | { |
1998 | dev_t *dev = data; | 2033 | dev_t *dev = data; |
2034 | struct ubifs_info *c = sb->s_fs_info; | ||
1999 | 2035 | ||
2000 | return sb->s_dev == *dev; | 2036 | return c->vi.cdev == *dev; |
2001 | } | ||
2002 | |||
2003 | static int sb_set(struct super_block *sb, void *data) | ||
2004 | { | ||
2005 | dev_t *dev = data; | ||
2006 | |||
2007 | sb->s_dev = *dev; | ||
2008 | return 0; | ||
2009 | } | 2037 | } |
2010 | 2038 | ||
2011 | static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | 2039 | static int ubifs_get_sb(struct file_system_type *fs_type, int flags, |
@@ -2033,7 +2061,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | |||
2033 | 2061 | ||
2034 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); | 2062 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); |
2035 | 2063 | ||
2036 | sb = sget(fs_type, &sb_test, &sb_set, &vi.cdev); | 2064 | sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev); |
2037 | if (IS_ERR(sb)) { | 2065 | if (IS_ERR(sb)) { |
2038 | err = PTR_ERR(sb); | 2066 | err = PTR_ERR(sb); |
2039 | goto out_close; | 2067 | goto out_close; |
@@ -2073,16 +2101,11 @@ out_close: | |||
2073 | return err; | 2101 | return err; |
2074 | } | 2102 | } |
2075 | 2103 | ||
2076 | static void ubifs_kill_sb(struct super_block *sb) | ||
2077 | { | ||
2078 | generic_shutdown_super(sb); | ||
2079 | } | ||
2080 | |||
2081 | static struct file_system_type ubifs_fs_type = { | 2104 | static struct file_system_type ubifs_fs_type = { |
2082 | .name = "ubifs", | 2105 | .name = "ubifs", |
2083 | .owner = THIS_MODULE, | 2106 | .owner = THIS_MODULE, |
2084 | .get_sb = ubifs_get_sb, | 2107 | .get_sb = ubifs_get_sb, |
2085 | .kill_sb = ubifs_kill_sb | 2108 | .kill_sb = kill_anon_super, |
2086 | }; | 2109 | }; |
2087 | 2110 | ||
2088 | /* | 2111 | /* |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 0a8341e14088..1bf01d820066 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -95,8 +95,8 @@ | |||
95 | */ | 95 | */ |
96 | #define BGT_NAME_PATTERN "ubifs_bgt%d_%d" | 96 | #define BGT_NAME_PATTERN "ubifs_bgt%d_%d" |
97 | 97 | ||
98 | /* Default write-buffer synchronization timeout (5 secs) */ | 98 | /* Default write-buffer synchronization timeout in seconds */ |
99 | #define DEFAULT_WBUF_TIMEOUT (5 * HZ) | 99 | #define DEFAULT_WBUF_TIMEOUT_SECS 5 |
100 | 100 | ||
101 | /* Maximum possible inode number (only 32-bit inodes are supported now) */ | 101 | /* Maximum possible inode number (only 32-bit inodes are supported now) */ |
102 | #define MAX_INUM 0xFFFFFFFF | 102 | #define MAX_INUM 0xFFFFFFFF |
@@ -650,8 +650,10 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c, | |||
650 | * @io_mutex: serializes write-buffer I/O | 650 | * @io_mutex: serializes write-buffer I/O |
651 | * @lock: serializes @buf, @lnum, @offs, @avail, @used, @next_ino and @inodes | 651 | * @lock: serializes @buf, @lnum, @offs, @avail, @used, @next_ino and @inodes |
652 | * fields | 652 | * fields |
653 | * @softlimit: soft write-buffer timeout interval | ||
654 | * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit | ||
655 | * and @softlimit + @delta) | ||
653 | * @timer: write-buffer timer | 656 | * @timer: write-buffer timer |
654 | * @timeout: timer expire interval in jiffies | ||
655 | * @need_sync: it is set if its timer expired and needs sync | 657 | * @need_sync: it is set if its timer expired and needs sync |
656 | * @next_ino: points to the next position of the following inode number | 658 | * @next_ino: points to the next position of the following inode number |
657 | * @inodes: stores the inode numbers of the nodes which are in wbuf | 659 | * @inodes: stores the inode numbers of the nodes which are in wbuf |
@@ -678,8 +680,9 @@ struct ubifs_wbuf { | |||
678 | int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad); | 680 | int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad); |
679 | struct mutex io_mutex; | 681 | struct mutex io_mutex; |
680 | spinlock_t lock; | 682 | spinlock_t lock; |
681 | struct timer_list timer; | 683 | ktime_t softlimit; |
682 | int timeout; | 684 | unsigned long long delta; |
685 | struct hrtimer timer; | ||
683 | int need_sync; | 686 | int need_sync; |
684 | int next_ino; | 687 | int next_ino; |
685 | ino_t *inodes; | 688 | ino_t *inodes; |