diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-13 23:52:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-13 23:52:39 -0400 |
commit | 4ae127d1b6c71f9240dd4245f240e6dd8fc98014 (patch) | |
tree | b7aa27b3e0c655f4613fe2146cb57d7f69e421f6 /fs | |
parent | 875ec4333b99144e2589e900a0bcd2c25c757b27 (diff) | |
parent | 7775c9753b94fe429dc4323360d6502c95e0dd6e (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/smc911x.c
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig.binfmt | 2 | ||||
-rw-r--r-- | fs/afs/callback.c | 2 | ||||
-rw-r--r-- | fs/afs/inode.c | 2 | ||||
-rw-r--r-- | fs/afs/super.c | 2 | ||||
-rw-r--r-- | fs/aio.c | 4 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 2 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 8 | ||||
-rw-r--r-- | fs/block_dev.c | 8 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 5 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 14 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 21 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 23 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 12 | ||||
-rw-r--r-- | fs/cifs/connect.c | 5 | ||||
-rw-r--r-- | fs/cifs/dir.c | 4 | ||||
-rw-r--r-- | fs/cifs/file.c | 7 | ||||
-rw-r--r-- | fs/cifs/inode.c | 148 | ||||
-rw-r--r-- | fs/cifs/misc.c | 3 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 77 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 2 | ||||
-rw-r--r-- | fs/ecryptfs/read_write.c | 22 | ||||
-rw-r--r-- | fs/ext3/resize.c | 3 | ||||
-rw-r--r-- | fs/ext4/balloc.c | 71 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 8 | ||||
-rw-r--r-- | fs/ext4/resize.c | 3 | ||||
-rw-r--r-- | fs/ext4/super.c | 36 | ||||
-rw-r--r-- | fs/fat/file.c | 44 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 1 | ||||
-rw-r--r-- | fs/jbd2/recovery.c | 12 | ||||
-rw-r--r-- | fs/libfs.c | 18 | ||||
-rw-r--r-- | fs/proc/array.c | 2 | ||||
-rw-r--r-- | fs/proc/base.c | 33 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 6 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 111 |
35 files changed, 453 insertions, 271 deletions
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 55e8ee1900a5..3263084eef9e 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -42,7 +42,7 @@ config BINFMT_ELF_FDPIC | |||
42 | 42 | ||
43 | config BINFMT_FLAT | 43 | config BINFMT_FLAT |
44 | bool "Kernel support for flat binaries" | 44 | bool "Kernel support for flat binaries" |
45 | depends on !MMU | 45 | depends on !MMU && (!FRV || BROKEN) |
46 | help | 46 | help |
47 | Support uClinux FLAT format binaries. | 47 | Support uClinux FLAT format binaries. |
48 | 48 | ||
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index a78d5b236bb1..587ef5123cd8 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * along with this program; if not, write to the Free Software | 8 | * along with this program; if not, write to the Free Software |
9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
10 | * | 10 | * |
11 | * Authors: David Woodhouse <dwmw2@cambridge.redhat.com> | 11 | * Authors: David Woodhouse <dwmw2@infradead.org> |
12 | * David Howells <dhowells@redhat.com> | 12 | * David Howells <dhowells@redhat.com> |
13 | * | 13 | * |
14 | */ | 14 | */ |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 08db82e1343a..bb47217f6a18 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * along with this program; if not, write to the Free Software | 8 | * along with this program; if not, write to the Free Software |
9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
10 | * | 10 | * |
11 | * Authors: David Woodhouse <dwmw2@cambridge.redhat.com> | 11 | * Authors: David Woodhouse <dwmw2@infradead.org> |
12 | * David Howells <dhowells@redhat.com> | 12 | * David Howells <dhowells@redhat.com> |
13 | * | 13 | * |
14 | */ | 14 | */ |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 4b572b801d8d..7e3faeef6818 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 10 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
11 | * | 11 | * |
12 | * Authors: David Howells <dhowells@redhat.com> | 12 | * Authors: David Howells <dhowells@redhat.com> |
13 | * David Woodhouse <dwmw2@redhat.com> | 13 | * David Woodhouse <dwmw2@infradead.org> |
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
@@ -591,10 +591,6 @@ static void use_mm(struct mm_struct *mm) | |||
591 | atomic_inc(&mm->mm_count); | 591 | atomic_inc(&mm->mm_count); |
592 | tsk->mm = mm; | 592 | tsk->mm = mm; |
593 | tsk->active_mm = mm; | 593 | tsk->active_mm = mm; |
594 | /* | ||
595 | * Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise | ||
596 | * it won't work. Update it accordingly if you change it here | ||
597 | */ | ||
598 | switch_mm(active_mm, mm, tsk); | 594 | switch_mm(active_mm, mm, tsk); |
599 | task_unlock(tsk); | 595 | task_unlock(tsk); |
600 | 596 | ||
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index ddd35d873391..d051a32e6270 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -390,7 +390,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
390 | } | 390 | } |
391 | 391 | ||
392 | /* expand the stack mapping to use up the entire allocation granule */ | 392 | /* expand the stack mapping to use up the entire allocation granule */ |
393 | fullsize = ksize((char *) current->mm->start_brk); | 393 | fullsize = kobjsize((char *) current->mm->start_brk); |
394 | if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size, | 394 | if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size, |
395 | fullsize, 0, 0))) | 395 | fullsize, 0, 0))) |
396 | stack_size = fullsize; | 396 | stack_size = fullsize; |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 3b40d45a3a16..2cb1acda3a82 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -548,7 +548,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
548 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); | 548 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
549 | /* Remap to use all availabe slack region space */ | 549 | /* Remap to use all availabe slack region space */ |
550 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { | 550 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { |
551 | reallen = ksize((void *)realdatastart); | 551 | reallen = kobjsize((void *)realdatastart); |
552 | if (reallen > len) { | 552 | if (reallen > len) { |
553 | realdatastart = do_mremap(realdatastart, len, | 553 | realdatastart = do_mremap(realdatastart, len, |
554 | reallen, MREMAP_FIXED, realdatastart); | 554 | reallen, MREMAP_FIXED, realdatastart); |
@@ -600,7 +600,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
600 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); | 600 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
601 | /* Remap to use all availabe slack region space */ | 601 | /* Remap to use all availabe slack region space */ |
602 | if (textpos && (textpos < (unsigned long) -4096)) { | 602 | if (textpos && (textpos < (unsigned long) -4096)) { |
603 | reallen = ksize((void *)textpos); | 603 | reallen = kobjsize((void *)textpos); |
604 | if (reallen > len) { | 604 | if (reallen > len) { |
605 | textpos = do_mremap(textpos, len, reallen, | 605 | textpos = do_mremap(textpos, len, reallen, |
606 | MREMAP_FIXED, textpos); | 606 | MREMAP_FIXED, textpos); |
@@ -683,7 +683,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
683 | */ | 683 | */ |
684 | current->mm->start_brk = datapos + data_len + bss_len; | 684 | current->mm->start_brk = datapos + data_len + bss_len; |
685 | current->mm->brk = (current->mm->start_brk + 3) & ~3; | 685 | current->mm->brk = (current->mm->start_brk + 3) & ~3; |
686 | current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len; | 686 | current->mm->context.end_brk = memp + kobjsize((void *) memp) - stack_len; |
687 | } | 687 | } |
688 | 688 | ||
689 | if (flags & FLAT_FLAG_KTRACE) | 689 | if (flags & FLAT_FLAG_KTRACE) |
@@ -790,7 +790,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
790 | 790 | ||
791 | /* zero the BSS, BRK and stack areas */ | 791 | /* zero the BSS, BRK and stack areas */ |
792 | memset((void*)(datapos + data_len), 0, bss_len + | 792 | memset((void*)(datapos + data_len), 0, bss_len + |
793 | (memp + ksize((void *) memp) - stack_len - /* end brk */ | 793 | (memp + kobjsize((void *) memp) - stack_len - /* end brk */ |
794 | libinfo->lib_list[id].start_brk) + /* start brk */ | 794 | libinfo->lib_list[id].start_brk) + /* start brk */ |
795 | stack_len); | 795 | stack_len); |
796 | 796 | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 7d822fae7765..470c10ceb0fb 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/kmod.h> | 12 | #include <linux/kmod.h> |
13 | #include <linux/major.h> | 13 | #include <linux/major.h> |
14 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
15 | #include <linux/device_cgroup.h> | ||
15 | #include <linux/highmem.h> | 16 | #include <linux/highmem.h> |
16 | #include <linux/blkdev.h> | 17 | #include <linux/blkdev.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
@@ -928,9 +929,14 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) | |||
928 | { | 929 | { |
929 | struct module *owner = NULL; | 930 | struct module *owner = NULL; |
930 | struct gendisk *disk; | 931 | struct gendisk *disk; |
931 | int ret = -ENXIO; | 932 | int ret; |
932 | int part; | 933 | int part; |
933 | 934 | ||
935 | ret = devcgroup_inode_permission(bdev->bd_inode, file->f_mode); | ||
936 | if (ret != 0) | ||
937 | return ret; | ||
938 | |||
939 | ret = -ENXIO; | ||
934 | file->f_mapping = bdev->bd_inode->i_mapping; | 940 | file->f_mapping = bdev->bd_inode->i_mapping; |
935 | lock_kernel(); | 941 | lock_kernel(); |
936 | disk = get_gendisk(bdev->bd_dev, &part); | 942 | disk = get_gendisk(bdev->bd_dev, &part); |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 28e3d5c5fcac..1f3465201fdf 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -2,6 +2,11 @@ Version 1.53 | |||
2 | ------------ | 2 | ------------ |
3 | DFS support added (Microsoft Distributed File System client support needed | 3 | DFS support added (Microsoft Distributed File System client support needed |
4 | for referrals which enable a hierarchical name space among servers). | 4 | for referrals which enable a hierarchical name space among servers). |
5 | Disable temporary caching of mode bits to servers which do not support | ||
6 | storing of mode (e.g. Windows servers, when client mounts without cifsacl | ||
7 | mount option) and add new "dynperm" mount option to enable temporary caching | ||
8 | of mode (enable old behavior). Fix hang on mount caused when server crashes | ||
9 | tcp session during negotiate protocol. | ||
5 | 10 | ||
6 | Version 1.52 | 11 | Version 1.52 |
7 | ------------ | 12 | ------------ |
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index cb52cbbe45ff..f58e41d3ba48 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
@@ -186,6 +186,11 @@ asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len) | |||
186 | } | 186 | } |
187 | } | 187 | } |
188 | } | 188 | } |
189 | |||
190 | /* don't trust len bigger than ctx buffer */ | ||
191 | if (*len > ctx->end - ctx->pointer) | ||
192 | return 0; | ||
193 | |||
189 | return 1; | 194 | return 1; |
190 | } | 195 | } |
191 | 196 | ||
@@ -203,6 +208,10 @@ asn1_header_decode(struct asn1_ctx *ctx, | |||
203 | if (!asn1_length_decode(ctx, &def, &len)) | 208 | if (!asn1_length_decode(ctx, &def, &len)) |
204 | return 0; | 209 | return 0; |
205 | 210 | ||
211 | /* primitive shall be definite, indefinite shall be constructed */ | ||
212 | if (*con == ASN1_PRI && !def) | ||
213 | return 0; | ||
214 | |||
206 | if (def) | 215 | if (def) |
207 | *eoc = ctx->pointer + len; | 216 | *eoc = ctx->pointer + len; |
208 | else | 217 | else |
@@ -389,6 +398,11 @@ asn1_oid_decode(struct asn1_ctx *ctx, | |||
389 | unsigned long *optr; | 398 | unsigned long *optr; |
390 | 399 | ||
391 | size = eoc - ctx->pointer + 1; | 400 | size = eoc - ctx->pointer + 1; |
401 | |||
402 | /* first subid actually encodes first two subids */ | ||
403 | if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) | ||
404 | return 0; | ||
405 | |||
392 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); | 406 | *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); |
393 | if (*oid == NULL) | 407 | if (*oid == NULL) |
394 | return 0; | 408 | return 0; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5df93fd6303f..86b4d5f405ae 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -97,9 +97,6 @@ cifs_read_super(struct super_block *sb, void *data, | |||
97 | { | 97 | { |
98 | struct inode *inode; | 98 | struct inode *inode; |
99 | struct cifs_sb_info *cifs_sb; | 99 | struct cifs_sb_info *cifs_sb; |
100 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
101 | int len; | ||
102 | #endif | ||
103 | int rc = 0; | 100 | int rc = 0; |
104 | 101 | ||
105 | /* BB should we make this contingent on mount parm? */ | 102 | /* BB should we make this contingent on mount parm? */ |
@@ -117,15 +114,17 @@ cifs_read_super(struct super_block *sb, void *data, | |||
117 | * complex operation (mount), and in case of fail | 114 | * complex operation (mount), and in case of fail |
118 | * just exit instead of doing mount and attempting | 115 | * just exit instead of doing mount and attempting |
119 | * undo it if this copy fails?*/ | 116 | * undo it if this copy fails?*/ |
120 | len = strlen(data); | 117 | if (data) { |
121 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | 118 | int len = strlen(data); |
122 | if (cifs_sb->mountdata == NULL) { | 119 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); |
123 | kfree(sb->s_fs_info); | 120 | if (cifs_sb->mountdata == NULL) { |
124 | sb->s_fs_info = NULL; | 121 | kfree(sb->s_fs_info); |
125 | return -ENOMEM; | 122 | sb->s_fs_info = NULL; |
123 | return -ENOMEM; | ||
124 | } | ||
125 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
126 | cifs_sb->mountdata[len] = '\0'; | ||
126 | } | 127 | } |
127 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
128 | cifs_sb->mountdata[len] = '\0'; | ||
129 | #endif | 128 | #endif |
130 | 129 | ||
131 | rc = cifs_mount(sb, cifs_sb, data, devname); | 130 | rc = cifs_mount(sb, cifs_sb, data, devname); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 08914053242b..9cfcf326ead3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -333,7 +333,6 @@ struct cifsFileInfo { | |||
333 | bool messageMode:1; /* for pipes: message vs byte mode */ | 333 | bool messageMode:1; /* for pipes: message vs byte mode */ |
334 | atomic_t wrtPending; /* handle in use - defer close */ | 334 | atomic_t wrtPending; /* handle in use - defer close */ |
335 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ | 335 | struct semaphore fh_sem; /* prevents reopen race after dead ses*/ |
336 | char *search_resume_name; /* BB removeme BB */ | ||
337 | struct cifs_search_info srch_inf; | 336 | struct cifs_search_info srch_inf; |
338 | }; | 337 | }; |
339 | 338 | ||
@@ -626,7 +625,7 @@ GLOBAL_EXTERN atomic_t tcpSesAllocCount; | |||
626 | GLOBAL_EXTERN atomic_t tcpSesReconnectCount; | 625 | GLOBAL_EXTERN atomic_t tcpSesReconnectCount; |
627 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; | 626 | GLOBAL_EXTERN atomic_t tconInfoReconnectCount; |
628 | 627 | ||
629 | /* Various Debug counters to remove someday (BB) */ | 628 | /* Various Debug counters */ |
630 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ | 629 | GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ |
631 | #ifdef CONFIG_CIFS_STATS2 | 630 | #ifdef CONFIG_CIFS_STATS2 |
632 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ | 631 | GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 65d58b4e6a61..0f327c224da3 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -79,6 +79,19 @@ | |||
79 | #define TRANS2_GET_DFS_REFERRAL 0x10 | 79 | #define TRANS2_GET_DFS_REFERRAL 0x10 |
80 | #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 | 80 | #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 |
81 | 81 | ||
82 | /* SMB Transact (Named Pipe) subcommand codes */ | ||
83 | #define TRANS_SET_NMPIPE_STATE 0x0001 | ||
84 | #define TRANS_RAW_READ_NMPIPE 0x0011 | ||
85 | #define TRANS_QUERY_NMPIPE_STATE 0x0021 | ||
86 | #define TRANS_QUERY_NMPIPE_INFO 0x0022 | ||
87 | #define TRANS_PEEK_NMPIPE 0x0023 | ||
88 | #define TRANS_TRANSACT_NMPIPE 0x0026 | ||
89 | #define TRANS_RAW_WRITE_NMPIPE 0x0031 | ||
90 | #define TRANS_READ_NMPIPE 0x0036 | ||
91 | #define TRANS_WRITE_NMPIPE 0x0037 | ||
92 | #define TRANS_WAIT_NMPIPE 0x0053 | ||
93 | #define TRANS_CALL_NMPIPE 0x0054 | ||
94 | |||
82 | /* NT Transact subcommand codes */ | 95 | /* NT Transact subcommand codes */ |
83 | #define NT_TRANSACT_CREATE 0x01 | 96 | #define NT_TRANSACT_CREATE 0x01 |
84 | #define NT_TRANSACT_IOCTL 0x02 | 97 | #define NT_TRANSACT_IOCTL 0x02 |
@@ -328,12 +341,13 @@ | |||
328 | #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ | 341 | #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ |
329 | #define CREATE_NO_EA_KNOWLEDGE 0x00000200 | 342 | #define CREATE_NO_EA_KNOWLEDGE 0x00000200 |
330 | #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete | 343 | #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete |
331 | open for recovery flag - should | 344 | "open for recovery" flag - should |
332 | be zero */ | 345 | be zero in any case */ |
346 | #define CREATE_OPEN_FOR_RECOVERY 0x00000400 | ||
333 | #define CREATE_RANDOM_ACCESS 0x00000800 | 347 | #define CREATE_RANDOM_ACCESS 0x00000800 |
334 | #define CREATE_DELETE_ON_CLOSE 0x00001000 | 348 | #define CREATE_DELETE_ON_CLOSE 0x00001000 |
335 | #define CREATE_OPEN_BY_ID 0x00002000 | 349 | #define CREATE_OPEN_BY_ID 0x00002000 |
336 | #define CREATE_OPEN_BACKUP_INTN 0x00004000 | 350 | #define CREATE_OPEN_BACKUP_INTENT 0x00004000 |
337 | #define CREATE_NO_COMPRESSION 0x00008000 | 351 | #define CREATE_NO_COMPRESSION 0x00008000 |
338 | #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ | 352 | #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ |
339 | #define OPEN_REPARSE_POINT 0x00200000 | 353 | #define OPEN_REPARSE_POINT 0x00200000 |
@@ -722,7 +736,6 @@ typedef struct smb_com_tconx_rsp_ext { | |||
722 | #define SMB_CSC_CACHE_AUTO_REINT 0x0004 | 736 | #define SMB_CSC_CACHE_AUTO_REINT 0x0004 |
723 | #define SMB_CSC_CACHE_VDO 0x0008 | 737 | #define SMB_CSC_CACHE_VDO 0x0008 |
724 | #define SMB_CSC_NO_CACHING 0x000C | 738 | #define SMB_CSC_NO_CACHING 0x000C |
725 | |||
726 | #define SMB_UNIQUE_FILE_NAME 0x0010 | 739 | #define SMB_UNIQUE_FILE_NAME 0x0010 |
727 | #define SMB_EXTENDED_SIGNATURES 0x0020 | 740 | #define SMB_EXTENDED_SIGNATURES 0x0020 |
728 | 741 | ||
@@ -806,7 +819,7 @@ typedef struct smb_com_findclose_req { | |||
806 | #define ICOUNT_MASK 0x00FF | 819 | #define ICOUNT_MASK 0x00FF |
807 | #define PIPE_READ_MODE 0x0100 | 820 | #define PIPE_READ_MODE 0x0100 |
808 | #define NAMED_PIPE_TYPE 0x0400 | 821 | #define NAMED_PIPE_TYPE 0x0400 |
809 | #define PIPE_END_POINT 0x0800 | 822 | #define PIPE_END_POINT 0x4000 |
810 | #define BLOCKING_NAMED_PIPE 0x8000 | 823 | #define BLOCKING_NAMED_PIPE 0x8000 |
811 | 824 | ||
812 | typedef struct smb_com_open_req { /* also handles create */ | 825 | typedef struct smb_com_open_req { /* also handles create */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 9b8b4cfdf993..4511b708f0f3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -1728,7 +1728,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1728 | { | 1728 | { |
1729 | int rc = 0; | 1729 | int rc = 0; |
1730 | LOCK_REQ *pSMB = NULL; | 1730 | LOCK_REQ *pSMB = NULL; |
1731 | LOCK_RSP *pSMBr = NULL; | 1731 | /* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ |
1732 | int bytes_returned; | 1732 | int bytes_returned; |
1733 | int timeout = 0; | 1733 | int timeout = 0; |
1734 | __u16 count; | 1734 | __u16 count; |
@@ -1739,8 +1739,6 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1739 | if (rc) | 1739 | if (rc) |
1740 | return rc; | 1740 | return rc; |
1741 | 1741 | ||
1742 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | ||
1743 | |||
1744 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1742 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1745 | timeout = CIFS_ASYNC_OP; /* no response expected */ | 1743 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1746 | pSMB->Timeout = 0; | 1744 | pSMB->Timeout = 0; |
@@ -1774,7 +1772,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1774 | 1772 | ||
1775 | if (waitFlag) { | 1773 | if (waitFlag) { |
1776 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1774 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1777 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1775 | (struct smb_hdr *) pSMB, &bytes_returned); |
1778 | cifs_small_buf_release(pSMB); | 1776 | cifs_small_buf_release(pSMB); |
1779 | } else { | 1777 | } else { |
1780 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, | 1778 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
@@ -3927,9 +3925,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
3927 | } | 3925 | } |
3928 | 3926 | ||
3929 | ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); | 3927 | ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); |
3930 | if (ref->VersionNumber != 3) { | 3928 | if (ref->VersionNumber != cpu_to_le16(3)) { |
3931 | cERROR(1, ("Referrals of V%d version are not supported," | 3929 | cERROR(1, ("Referrals of V%d version are not supported," |
3932 | "should be V3", ref->VersionNumber)); | 3930 | "should be V3", le16_to_cpu(ref->VersionNumber))); |
3933 | rc = -EINVAL; | 3931 | rc = -EINVAL; |
3934 | goto parse_DFS_referrals_exit; | 3932 | goto parse_DFS_referrals_exit; |
3935 | } | 3933 | } |
@@ -3977,7 +3975,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
3977 | if (rc) | 3975 | if (rc) |
3978 | goto parse_DFS_referrals_exit; | 3976 | goto parse_DFS_referrals_exit; |
3979 | 3977 | ||
3980 | ref += ref->Size; | 3978 | ref += le16_to_cpu(ref->Size); |
3981 | } | 3979 | } |
3982 | 3980 | ||
3983 | parse_DFS_referrals_exit: | 3981 | parse_DFS_referrals_exit: |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 023434f72c15..e8fa46c7cff2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -653,6 +653,7 @@ multi_t2_fnd: | |||
653 | spin_lock(&GlobalMid_Lock); | 653 | spin_lock(&GlobalMid_Lock); |
654 | server->tcpStatus = CifsExiting; | 654 | server->tcpStatus = CifsExiting; |
655 | spin_unlock(&GlobalMid_Lock); | 655 | spin_unlock(&GlobalMid_Lock); |
656 | wake_up_all(&server->response_q); | ||
656 | 657 | ||
657 | /* don't exit until kthread_stop is called */ | 658 | /* don't exit until kthread_stop is called */ |
658 | set_current_state(TASK_UNINTERRUPTIBLE); | 659 | set_current_state(TASK_UNINTERRUPTIBLE); |
@@ -2120,6 +2121,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2120 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 2121 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
2121 | } | 2122 | } |
2122 | 2123 | ||
2124 | if ((volume_info.cifs_acl) && (volume_info.dynperm)) | ||
2125 | cERROR(1, ("mount option dynperm ignored if cifsacl " | ||
2126 | "mount option supported")); | ||
2127 | |||
2123 | tcon = | 2128 | tcon = |
2124 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, | 2129 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, |
2125 | volume_info.username); | 2130 | volume_info.username); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f0b5b5f3dd2e..fb69c1fa85c9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -260,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
260 | buf, inode->i_sb, xid, | 260 | buf, inode->i_sb, xid, |
261 | &fileHandle); | 261 | &fileHandle); |
262 | if (newinode) { | 262 | if (newinode) { |
263 | newinode->i_mode = mode; | 263 | if (cifs_sb->mnt_cifs_flags & |
264 | CIFS_MOUNT_DYNPERM) | ||
265 | newinode->i_mode = mode; | ||
264 | if ((oplock & CIFS_CREATE_ACTION) && | 266 | if ((oplock & CIFS_CREATE_ACTION) && |
265 | (cifs_sb->mnt_cifs_flags & | 267 | (cifs_sb->mnt_cifs_flags & |
266 | CIFS_MOUNT_SET_UID)) { | 268 | CIFS_MOUNT_SET_UID)) { |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8636cec2642c..0aac824371a5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -546,7 +546,6 @@ int cifs_close(struct inode *inode, struct file *file) | |||
546 | msleep(timeout); | 546 | msleep(timeout); |
547 | timeout *= 8; | 547 | timeout *= 8; |
548 | } | 548 | } |
549 | kfree(pSMBFile->search_resume_name); | ||
550 | kfree(file->private_data); | 549 | kfree(file->private_data); |
551 | file->private_data = NULL; | 550 | file->private_data = NULL; |
552 | } else | 551 | } else |
@@ -605,12 +604,6 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
605 | else | 604 | else |
606 | cifs_buf_release(ptmp); | 605 | cifs_buf_release(ptmp); |
607 | } | 606 | } |
608 | ptmp = pCFileStruct->search_resume_name; | ||
609 | if (ptmp) { | ||
610 | cFYI(1, ("closedir free resume name")); | ||
611 | pCFileStruct->search_resume_name = NULL; | ||
612 | kfree(ptmp); | ||
613 | } | ||
614 | kfree(file->private_data); | 607 | kfree(file->private_data); |
615 | file->private_data = NULL; | 608 | file->private_data = NULL; |
616 | } | 609 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 129dbfe4dca7..722be543ceec 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -418,6 +418,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
418 | char *buf = NULL; | 418 | char *buf = NULL; |
419 | bool adjustTZ = false; | 419 | bool adjustTZ = false; |
420 | bool is_dfs_referral = false; | 420 | bool is_dfs_referral = false; |
421 | umode_t default_mode; | ||
421 | 422 | ||
422 | pTcon = cifs_sb->tcon; | 423 | pTcon = cifs_sb->tcon; |
423 | cFYI(1, ("Getting info on %s", full_path)); | 424 | cFYI(1, ("Getting info on %s", full_path)); |
@@ -530,47 +531,42 @@ int cifs_get_inode_info(struct inode **pinode, | |||
530 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | 531 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; |
531 | } | 532 | } |
532 | 533 | ||
533 | /* set default mode. will override for dirs below */ | 534 | /* get default inode mode */ |
534 | if (atomic_read(&cifsInfo->inUse) == 0) | 535 | if (attr & ATTR_DIRECTORY) |
535 | /* new inode, can safely set these fields */ | 536 | default_mode = cifs_sb->mnt_dir_mode; |
536 | inode->i_mode = cifs_sb->mnt_file_mode; | 537 | else |
537 | else /* since we set the inode type below we need to mask off | 538 | default_mode = cifs_sb->mnt_file_mode; |
538 | to avoid strange results if type changes and both | 539 | |
539 | get orred in */ | 540 | /* set permission bits */ |
540 | inode->i_mode &= ~S_IFMT; | 541 | if (atomic_read(&cifsInfo->inUse) == 0 || |
541 | /* if (attr & ATTR_REPARSE) */ | 542 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
542 | /* We no longer handle these as symlinks because we could not | 543 | inode->i_mode = default_mode; |
543 | follow them due to the absolute path with drive letter */ | 544 | else { |
544 | if (attr & ATTR_DIRECTORY) { | 545 | /* just reenable write bits if !ATTR_READONLY */ |
545 | /* override default perms since we do not do byte range locking | 546 | if ((inode->i_mode & S_IWUGO) == 0 && |
546 | on dirs */ | 547 | (attr & ATTR_READONLY) == 0) |
547 | inode->i_mode = cifs_sb->mnt_dir_mode; | 548 | inode->i_mode |= (S_IWUGO & default_mode); |
548 | inode->i_mode |= S_IFDIR; | 549 | inode->i_mode &= ~S_IFMT; |
549 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 550 | } |
550 | (cifsInfo->cifsAttrs & ATTR_SYSTEM) && | 551 | /* clear write bits if ATTR_READONLY is set */ |
551 | /* No need to le64 convert size of zero */ | 552 | if (attr & ATTR_READONLY) |
552 | (pfindData->EndOfFile == 0)) { | 553 | inode->i_mode &= ~S_IWUGO; |
553 | inode->i_mode = cifs_sb->mnt_file_mode; | 554 | |
554 | inode->i_mode |= S_IFIFO; | 555 | /* set inode type */ |
555 | /* BB Finish for SFU style symlinks and devices */ | 556 | if ((attr & ATTR_SYSTEM) && |
556 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 557 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { |
557 | (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { | 558 | /* no need to fix endianness on 0 */ |
558 | if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), | 559 | if (pfindData->EndOfFile == 0) |
559 | full_path, cifs_sb, xid)) | 560 | inode->i_mode |= S_IFIFO; |
560 | cFYI(1, ("Unrecognized sfu inode type")); | 561 | else if (decode_sfu_inode(inode, |
561 | 562 | le64_to_cpu(pfindData->EndOfFile), | |
562 | cFYI(1, ("sfu mode 0%o", inode->i_mode)); | 563 | full_path, cifs_sb, xid)) |
564 | cFYI(1, ("unknown SFU file type\n")); | ||
563 | } else { | 565 | } else { |
564 | inode->i_mode |= S_IFREG; | 566 | if (attr & ATTR_DIRECTORY) |
565 | /* treat dos attribute of read-only as read-only mode eg 555 */ | 567 | inode->i_mode |= S_IFDIR; |
566 | if (cifsInfo->cifsAttrs & ATTR_READONLY) | 568 | else |
567 | inode->i_mode &= ~(S_IWUGO); | 569 | inode->i_mode |= S_IFREG; |
568 | else if ((inode->i_mode & S_IWUGO) == 0) | ||
569 | /* the ATTR_READONLY flag may have been */ | ||
570 | /* changed on server -- set any w bits */ | ||
571 | /* allowed by mnt_file_mode */ | ||
572 | inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); | ||
573 | /* BB add code to validate if device or weird share or device type? */ | ||
574 | } | 570 | } |
575 | 571 | ||
576 | spin_lock(&inode->i_lock); | 572 | spin_lock(&inode->i_lock); |
@@ -1019,8 +1015,11 @@ mkdir_get_info: | |||
1019 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1015 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1020 | } | 1016 | } |
1021 | if (direntry->d_inode) { | 1017 | if (direntry->d_inode) { |
1022 | direntry->d_inode->i_mode = mode; | 1018 | if (cifs_sb->mnt_cifs_flags & |
1023 | direntry->d_inode->i_mode |= S_IFDIR; | 1019 | CIFS_MOUNT_DYNPERM) |
1020 | direntry->d_inode->i_mode = | ||
1021 | (mode | S_IFDIR); | ||
1022 | |||
1024 | if (cifs_sb->mnt_cifs_flags & | 1023 | if (cifs_sb->mnt_cifs_flags & |
1025 | CIFS_MOUNT_SET_UID) { | 1024 | CIFS_MOUNT_SET_UID) { |
1026 | direntry->d_inode->i_uid = | 1025 | direntry->d_inode->i_uid = |
@@ -1547,13 +1546,26 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1547 | } else | 1546 | } else |
1548 | goto cifs_setattr_exit; | 1547 | goto cifs_setattr_exit; |
1549 | } | 1548 | } |
1550 | if (attrs->ia_valid & ATTR_UID) { | 1549 | |
1551 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | 1550 | /* |
1552 | uid = attrs->ia_uid; | 1551 | * Without unix extensions we can't send ownership changes to the |
1553 | } | 1552 | * server, so silently ignore them. This is consistent with how |
1554 | if (attrs->ia_valid & ATTR_GID) { | 1553 | * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With |
1555 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | 1554 | * CIFSACL support + proper Windows to Unix idmapping, we may be |
1556 | gid = attrs->ia_gid; | 1555 | * able to support this in the future. |
1556 | */ | ||
1557 | if (!pTcon->unix_ext && | ||
1558 | !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { | ||
1559 | attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); | ||
1560 | } else { | ||
1561 | if (attrs->ia_valid & ATTR_UID) { | ||
1562 | cFYI(1, ("UID changed to %d", attrs->ia_uid)); | ||
1563 | uid = attrs->ia_uid; | ||
1564 | } | ||
1565 | if (attrs->ia_valid & ATTR_GID) { | ||
1566 | cFYI(1, ("GID changed to %d", attrs->ia_gid)); | ||
1567 | gid = attrs->ia_gid; | ||
1568 | } | ||
1557 | } | 1569 | } |
1558 | 1570 | ||
1559 | time_buf.Attributes = 0; | 1571 | time_buf.Attributes = 0; |
@@ -1563,7 +1575,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1563 | attrs->ia_valid &= ~ATTR_MODE; | 1575 | attrs->ia_valid &= ~ATTR_MODE; |
1564 | 1576 | ||
1565 | if (attrs->ia_valid & ATTR_MODE) { | 1577 | if (attrs->ia_valid & ATTR_MODE) { |
1566 | cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); | 1578 | cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); |
1567 | mode = attrs->ia_mode; | 1579 | mode = attrs->ia_mode; |
1568 | } | 1580 | } |
1569 | 1581 | ||
@@ -1578,18 +1590,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1578 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1590 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
1579 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 1591 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
1580 | rc = mode_to_acl(inode, full_path, mode); | 1592 | rc = mode_to_acl(inode, full_path, mode); |
1581 | else if ((mode & S_IWUGO) == 0) { | 1593 | else |
1582 | #else | ||
1583 | if ((mode & S_IWUGO) == 0) { | ||
1584 | #endif | 1594 | #endif |
1585 | /* not writeable */ | 1595 | if (((mode & S_IWUGO) == 0) && |
1586 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 1596 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1587 | set_dosattr = true; | 1597 | set_dosattr = true; |
1588 | time_buf.Attributes = | 1598 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | |
1589 | cpu_to_le32(cifsInode->cifsAttrs | | 1599 | ATTR_READONLY); |
1590 | ATTR_READONLY); | 1600 | /* fix up mode if we're not using dynperm */ |
1591 | } | 1601 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
1592 | } else if (cifsInode->cifsAttrs & ATTR_READONLY) { | 1602 | attrs->ia_mode = inode->i_mode & ~S_IWUGO; |
1603 | } else if ((mode & S_IWUGO) && | ||
1604 | (cifsInode->cifsAttrs & ATTR_READONLY)) { | ||
1593 | /* If file is readonly on server, we would | 1605 | /* If file is readonly on server, we would |
1594 | not be able to write to it - so if any write | 1606 | not be able to write to it - so if any write |
1595 | bit is enabled for user or group or other we | 1607 | bit is enabled for user or group or other we |
@@ -1600,6 +1612,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1600 | /* Windows ignores set to zero */ | 1612 | /* Windows ignores set to zero */ |
1601 | if (time_buf.Attributes == 0) | 1613 | if (time_buf.Attributes == 0) |
1602 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); | 1614 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); |
1615 | |||
1616 | /* reset local inode permissions to normal */ | ||
1617 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1618 | attrs->ia_mode &= ~(S_IALLUGO); | ||
1619 | if (S_ISDIR(inode->i_mode)) | ||
1620 | attrs->ia_mode |= | ||
1621 | cifs_sb->mnt_dir_mode; | ||
1622 | else | ||
1623 | attrs->ia_mode |= | ||
1624 | cifs_sb->mnt_file_mode; | ||
1625 | } | ||
1626 | } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1627 | /* ignore mode change - ATTR_READONLY hasn't changed */ | ||
1628 | attrs->ia_valid &= ~ATTR_MODE; | ||
1603 | } | 1629 | } |
1604 | } | 1630 | } |
1605 | 1631 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1d69b8014e0b..4b17f8fe3157 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -519,8 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
519 | pnotify = (struct file_notify_information *) | 519 | pnotify = (struct file_notify_information *) |
520 | ((char *)&pSMBr->hdr.Protocol + data_offset); | 520 | ((char *)&pSMBr->hdr.Protocol + data_offset); |
521 | cFYI(1, ("dnotify on %s Action: 0x%x", | 521 | cFYI(1, ("dnotify on %s Action: 0x%x", |
522 | pnotify->FileName, | 522 | pnotify->FileName, pnotify->Action)); |
523 | pnotify->Action)); /* BB removeme BB */ | ||
524 | /* cifs_dump_mem("Rcvd notify Data: ",buf, | 523 | /* cifs_dump_mem("Rcvd notify Data: ",buf, |
525 | sizeof(struct smb_hdr)+60); */ | 524 | sizeof(struct smb_hdr)+60); */ |
526 | return true; | 525 | return true; |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 713c25110197..83f306954883 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
132 | __u32 attr; | 132 | __u32 attr; |
133 | __u64 allocation_size; | 133 | __u64 allocation_size; |
134 | __u64 end_of_file; | 134 | __u64 end_of_file; |
135 | umode_t default_mode; | ||
135 | 136 | ||
136 | /* save mtime and size */ | 137 | /* save mtime and size */ |
137 | local_mtime = tmp_inode->i_mtime; | 138 | local_mtime = tmp_inode->i_mtime; |
@@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | |||
187 | if (atomic_read(&cifsInfo->inUse) == 0) { | 188 | if (atomic_read(&cifsInfo->inUse) == 0) { |
188 | tmp_inode->i_uid = cifs_sb->mnt_uid; | 189 | tmp_inode->i_uid = cifs_sb->mnt_uid; |
189 | tmp_inode->i_gid = cifs_sb->mnt_gid; | 190 | tmp_inode->i_gid = cifs_sb->mnt_gid; |
190 | /* set default mode. will override for dirs below */ | 191 | } |
191 | tmp_inode->i_mode = cifs_sb->mnt_file_mode; | 192 | |
192 | } else { | 193 | if (attr & ATTR_DIRECTORY) |
193 | /* mask off the type bits since it gets set | 194 | default_mode = cifs_sb->mnt_dir_mode; |
194 | below and we do not want to get two type | 195 | else |
195 | bits set */ | 196 | default_mode = cifs_sb->mnt_file_mode; |
197 | |||
198 | /* set initial permissions */ | ||
199 | if ((atomic_read(&cifsInfo->inUse) == 0) || | ||
200 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) | ||
201 | tmp_inode->i_mode = default_mode; | ||
202 | else { | ||
203 | /* just reenable write bits if !ATTR_READONLY */ | ||
204 | if ((tmp_inode->i_mode & S_IWUGO) == 0 && | ||
205 | (attr & ATTR_READONLY) == 0) | ||
206 | tmp_inode->i_mode |= (S_IWUGO & default_mode); | ||
207 | |||
196 | tmp_inode->i_mode &= ~S_IFMT; | 208 | tmp_inode->i_mode &= ~S_IFMT; |
197 | } | 209 | } |
198 | 210 | ||
199 | if (attr & ATTR_DIRECTORY) { | 211 | /* clear write bits if ATTR_READONLY is set */ |
200 | *pobject_type = DT_DIR; | 212 | if (attr & ATTR_READONLY) |
201 | /* override default perms since we do not lock dirs */ | 213 | tmp_inode->i_mode &= ~S_IWUGO; |
202 | if (atomic_read(&cifsInfo->inUse) == 0) | 214 | |
203 | tmp_inode->i_mode = cifs_sb->mnt_dir_mode; | 215 | /* set inode type */ |
204 | tmp_inode->i_mode |= S_IFDIR; | 216 | if ((attr & ATTR_SYSTEM) && |
205 | } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && | 217 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { |
206 | (attr & ATTR_SYSTEM)) { | ||
207 | if (end_of_file == 0) { | 218 | if (end_of_file == 0) { |
208 | *pobject_type = DT_FIFO; | ||
209 | tmp_inode->i_mode |= S_IFIFO; | 219 | tmp_inode->i_mode |= S_IFIFO; |
220 | *pobject_type = DT_FIFO; | ||
210 | } else { | 221 | } else { |
211 | /* rather than get the type here, we mark the | 222 | /* |
212 | inode as needing revalidate and get the real type | 223 | * trying to get the type can be slow, so just call |
213 | (blk vs chr vs. symlink) later ie in lookup */ | 224 | * this a regular file for now, and mark for reval |
214 | *pobject_type = DT_REG; | 225 | */ |
215 | tmp_inode->i_mode |= S_IFREG; | 226 | tmp_inode->i_mode |= S_IFREG; |
227 | *pobject_type = DT_REG; | ||
216 | cifsInfo->time = 0; | 228 | cifsInfo->time = 0; |
217 | } | 229 | } |
218 | /* we no longer mark these because we could not follow them */ | ||
219 | /* } else if (attr & ATTR_REPARSE) { | ||
220 | *pobject_type = DT_LNK; | ||
221 | tmp_inode->i_mode |= S_IFLNK; */ | ||
222 | } else { | 230 | } else { |
223 | *pobject_type = DT_REG; | 231 | if (attr & ATTR_DIRECTORY) { |
224 | tmp_inode->i_mode |= S_IFREG; | 232 | tmp_inode->i_mode |= S_IFDIR; |
225 | if (attr & ATTR_READONLY) | 233 | *pobject_type = DT_DIR; |
226 | tmp_inode->i_mode &= ~(S_IWUGO); | 234 | } else { |
227 | else if ((tmp_inode->i_mode & S_IWUGO) == 0) | 235 | tmp_inode->i_mode |= S_IFREG; |
228 | /* the ATTR_READONLY flag may have been changed on */ | 236 | *pobject_type = DT_REG; |
229 | /* server -- set any w bits allowed by mnt_file_mode */ | 237 | } |
230 | tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); | 238 | } |
231 | } /* could add code here - to validate if device or weird share type? */ | ||
232 | 239 | ||
233 | /* can not fill in nlink here as in qpathinfo version and Unx search */ | 240 | /* can not fill in nlink here as in qpathinfo version and Unx search */ |
234 | if (atomic_read(&cifsInfo->inUse) == 0) | 241 | if (atomic_read(&cifsInfo->inUse) == 0) |
@@ -675,8 +682,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
675 | cifsFile->invalidHandle = true; | 682 | cifsFile->invalidHandle = true; |
676 | CIFSFindClose(xid, pTcon, cifsFile->netfid); | 683 | CIFSFindClose(xid, pTcon, cifsFile->netfid); |
677 | } | 684 | } |
678 | kfree(cifsFile->search_resume_name); | ||
679 | cifsFile->search_resume_name = NULL; | ||
680 | if (cifsFile->srch_inf.ntwrk_buf_start) { | 685 | if (cifsFile->srch_inf.ntwrk_buf_start) { |
681 | cFYI(1, ("freeing SMB ff cache buf on search rewind")); | 686 | cFYI(1, ("freeing SMB ff cache buf on search rewind")); |
682 | if (cifsFile->srch_inf.smallBuf) | 687 | if (cifsFile->srch_inf.smallBuf) |
@@ -1043,9 +1048,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1043 | } /* else { | 1048 | } /* else { |
1044 | cifsFile->invalidHandle = true; | 1049 | cifsFile->invalidHandle = true; |
1045 | CIFSFindClose(xid, pTcon, cifsFile->netfid); | 1050 | CIFSFindClose(xid, pTcon, cifsFile->netfid); |
1046 | } | 1051 | } */ |
1047 | kfree(cifsFile->search_resume_name); | ||
1048 | cifsFile->search_resume_name = NULL; */ | ||
1049 | 1052 | ||
1050 | rc = find_cifs_entry(xid, pTcon, file, | 1053 | rc = find_cifs_entry(xid, pTcon, file, |
1051 | ¤t_entry, &num_to_fill); | 1054 | ¤t_entry, &num_to_fill); |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 951ee33a022d..c15c25745e05 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -660,8 +660,6 @@ int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, | |||
660 | int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, | 660 | int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, |
661 | struct ecryptfs_auth_tok **auth_tok, | 661 | struct ecryptfs_auth_tok **auth_tok, |
662 | char *sig); | 662 | char *sig); |
663 | int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, | ||
664 | int num_zeros); | ||
665 | int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, | 663 | int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, |
666 | loff_t offset, size_t size); | 664 | loff_t offset, size_t size); |
667 | int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, | 665 | int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode, |
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index ebf55150be56..75c2ea9fee35 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
@@ -157,20 +157,6 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset, | |||
157 | ecryptfs_page_idx, rc); | 157 | ecryptfs_page_idx, rc); |
158 | goto out; | 158 | goto out; |
159 | } | 159 | } |
160 | if (start_offset_in_page) { | ||
161 | /* Read in the page from the lower | ||
162 | * into the eCryptfs inode page cache, | ||
163 | * decrypting */ | ||
164 | rc = ecryptfs_decrypt_page(ecryptfs_page); | ||
165 | if (rc) { | ||
166 | printk(KERN_ERR "%s: Error decrypting " | ||
167 | "page; rc = [%d]\n", | ||
168 | __func__, rc); | ||
169 | ClearPageUptodate(ecryptfs_page); | ||
170 | page_cache_release(ecryptfs_page); | ||
171 | goto out; | ||
172 | } | ||
173 | } | ||
174 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | 160 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); |
175 | 161 | ||
176 | /* | 162 | /* |
@@ -349,14 +335,6 @@ int ecryptfs_read(char *data, loff_t offset, size_t size, | |||
349 | ecryptfs_page_idx, rc); | 335 | ecryptfs_page_idx, rc); |
350 | goto out; | 336 | goto out; |
351 | } | 337 | } |
352 | rc = ecryptfs_decrypt_page(ecryptfs_page); | ||
353 | if (rc) { | ||
354 | printk(KERN_ERR "%s: Error decrypting " | ||
355 | "page; rc = [%d]\n", __func__, rc); | ||
356 | ClearPageUptodate(ecryptfs_page); | ||
357 | page_cache_release(ecryptfs_page); | ||
358 | goto out; | ||
359 | } | ||
360 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | 338 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); |
361 | memcpy((data + data_offset), | 339 | memcpy((data + data_offset), |
362 | ((char *)ecryptfs_page_virt + start_offset_in_page), | 340 | ((char *)ecryptfs_page_virt + start_offset_in_page), |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 28cfd0b40527..77278e947e94 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -580,7 +580,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, | |||
580 | } | 580 | } |
581 | 581 | ||
582 | blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count; | 582 | blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count; |
583 | data = (__le32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count; | 583 | data = (__le32 *)dind->b_data + (EXT3_SB(sb)->s_gdb_count % |
584 | EXT3_ADDR_PER_BLOCK(sb)); | ||
584 | end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb); | 585 | end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb); |
585 | 586 | ||
586 | /* Get each reserved primary GDT block and verify it holds backups */ | 587 | /* Get each reserved primary GDT block and verify it holds backups */ |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 30494c5da843..9cc80b9cc8d8 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -43,6 +43,46 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, | |||
43 | 43 | ||
44 | } | 44 | } |
45 | 45 | ||
46 | static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block, | ||
47 | ext4_group_t block_group) | ||
48 | { | ||
49 | ext4_group_t actual_group; | ||
50 | ext4_get_group_no_and_offset(sb, block, &actual_group, 0); | ||
51 | if (actual_group == block_group) | ||
52 | return 1; | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int ext4_group_used_meta_blocks(struct super_block *sb, | ||
57 | ext4_group_t block_group) | ||
58 | { | ||
59 | ext4_fsblk_t tmp; | ||
60 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
61 | /* block bitmap, inode bitmap, and inode table blocks */ | ||
62 | int used_blocks = sbi->s_itb_per_group + 2; | ||
63 | |||
64 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { | ||
65 | struct ext4_group_desc *gdp; | ||
66 | struct buffer_head *bh; | ||
67 | |||
68 | gdp = ext4_get_group_desc(sb, block_group, &bh); | ||
69 | if (!ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), | ||
70 | block_group)) | ||
71 | used_blocks--; | ||
72 | |||
73 | if (!ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), | ||
74 | block_group)) | ||
75 | used_blocks--; | ||
76 | |||
77 | tmp = ext4_inode_table(sb, gdp); | ||
78 | for (; tmp < ext4_inode_table(sb, gdp) + | ||
79 | sbi->s_itb_per_group; tmp++) { | ||
80 | if (!ext4_block_in_group(sb, tmp, block_group)) | ||
81 | used_blocks -= 1; | ||
82 | } | ||
83 | } | ||
84 | return used_blocks; | ||
85 | } | ||
46 | /* Initializes an uninitialized block bitmap if given, and returns the | 86 | /* Initializes an uninitialized block bitmap if given, and returns the |
47 | * number of blocks free in the group. */ | 87 | * number of blocks free in the group. */ |
48 | unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | 88 | unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, |
@@ -105,20 +145,34 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
105 | free_blocks = group_blocks - bit_max; | 145 | free_blocks = group_blocks - bit_max; |
106 | 146 | ||
107 | if (bh) { | 147 | if (bh) { |
108 | ext4_fsblk_t start; | 148 | ext4_fsblk_t start, tmp; |
149 | int flex_bg = 0; | ||
109 | 150 | ||
110 | for (bit = 0; bit < bit_max; bit++) | 151 | for (bit = 0; bit < bit_max; bit++) |
111 | ext4_set_bit(bit, bh->b_data); | 152 | ext4_set_bit(bit, bh->b_data); |
112 | 153 | ||
113 | start = ext4_group_first_block_no(sb, block_group); | 154 | start = ext4_group_first_block_no(sb, block_group); |
114 | 155 | ||
115 | /* Set bits for block and inode bitmaps, and inode table */ | 156 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, |
116 | ext4_set_bit(ext4_block_bitmap(sb, gdp) - start, bh->b_data); | 157 | EXT4_FEATURE_INCOMPAT_FLEX_BG)) |
117 | ext4_set_bit(ext4_inode_bitmap(sb, gdp) - start, bh->b_data); | 158 | flex_bg = 1; |
118 | for (bit = (ext4_inode_table(sb, gdp) - start), | ||
119 | bit_max = bit + sbi->s_itb_per_group; bit < bit_max; bit++) | ||
120 | ext4_set_bit(bit, bh->b_data); | ||
121 | 159 | ||
160 | /* Set bits for block and inode bitmaps, and inode table */ | ||
161 | tmp = ext4_block_bitmap(sb, gdp); | ||
162 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | ||
163 | ext4_set_bit(tmp - start, bh->b_data); | ||
164 | |||
165 | tmp = ext4_inode_bitmap(sb, gdp); | ||
166 | if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) | ||
167 | ext4_set_bit(tmp - start, bh->b_data); | ||
168 | |||
169 | tmp = ext4_inode_table(sb, gdp); | ||
170 | for (; tmp < ext4_inode_table(sb, gdp) + | ||
171 | sbi->s_itb_per_group; tmp++) { | ||
172 | if (!flex_bg || | ||
173 | ext4_block_in_group(sb, tmp, block_group)) | ||
174 | ext4_set_bit(tmp - start, bh->b_data); | ||
175 | } | ||
122 | /* | 176 | /* |
123 | * Also if the number of blocks within the group is | 177 | * Also if the number of blocks within the group is |
124 | * less than the blocksize * 8 ( which is the size | 178 | * less than the blocksize * 8 ( which is the size |
@@ -126,8 +180,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
126 | */ | 180 | */ |
127 | mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data); | 181 | mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data); |
128 | } | 182 | } |
129 | 183 | return free_blocks - ext4_group_used_meta_blocks(sb, block_group); | |
130 | return free_blocks - sbi->s_itb_per_group - 2; | ||
131 | } | 184 | } |
132 | 185 | ||
133 | 186 | ||
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 873ad9b3418c..c9900aade150 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2745,8 +2745,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2745 | sbi = EXT4_SB(sb); | 2745 | sbi = EXT4_SB(sb); |
2746 | es = sbi->s_es; | 2746 | es = sbi->s_es; |
2747 | 2747 | ||
2748 | ext4_debug("using block group %lu(%d)\n", ac->ac_b_ex.fe_group, | ||
2749 | gdp->bg_free_blocks_count); | ||
2750 | 2748 | ||
2751 | err = -EIO; | 2749 | err = -EIO; |
2752 | bitmap_bh = read_block_bitmap(sb, ac->ac_b_ex.fe_group); | 2750 | bitmap_bh = read_block_bitmap(sb, ac->ac_b_ex.fe_group); |
@@ -2762,6 +2760,9 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2762 | if (!gdp) | 2760 | if (!gdp) |
2763 | goto out_err; | 2761 | goto out_err; |
2764 | 2762 | ||
2763 | ext4_debug("using block group %lu(%d)\n", ac->ac_b_ex.fe_group, | ||
2764 | gdp->bg_free_blocks_count); | ||
2765 | |||
2765 | err = ext4_journal_get_write_access(handle, gdp_bh); | 2766 | err = ext4_journal_get_write_access(handle, gdp_bh); |
2766 | if (err) | 2767 | if (err) |
2767 | goto out_err; | 2768 | goto out_err; |
@@ -3094,8 +3095,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac, | |||
3094 | static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, | 3095 | static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, |
3095 | struct ext4_prealloc_space *pa) | 3096 | struct ext4_prealloc_space *pa) |
3096 | { | 3097 | { |
3097 | unsigned len = ac->ac_o_ex.fe_len; | 3098 | unsigned int len = ac->ac_o_ex.fe_len; |
3098 | |||
3099 | ext4_get_group_no_and_offset(ac->ac_sb, pa->pa_pstart, | 3099 | ext4_get_group_no_and_offset(ac->ac_sb, pa->pa_pstart, |
3100 | &ac->ac_b_ex.fe_group, | 3100 | &ac->ac_b_ex.fe_group, |
3101 | &ac->ac_b_ex.fe_start); | 3101 | &ac->ac_b_ex.fe_start); |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 9f086a6a472b..9ecb92f68543 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -563,7 +563,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, | |||
563 | } | 563 | } |
564 | 564 | ||
565 | blk = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + EXT4_SB(sb)->s_gdb_count; | 565 | blk = EXT4_SB(sb)->s_sbh->b_blocknr + 1 + EXT4_SB(sb)->s_gdb_count; |
566 | data = (__le32 *)dind->b_data + EXT4_SB(sb)->s_gdb_count; | 566 | data = (__le32 *)dind->b_data + (EXT4_SB(sb)->s_gdb_count % |
567 | EXT4_ADDR_PER_BLOCK(sb)); | ||
567 | end = (__le32 *)dind->b_data + EXT4_ADDR_PER_BLOCK(sb); | 568 | end = (__le32 *)dind->b_data + EXT4_ADDR_PER_BLOCK(sb); |
568 | 569 | ||
569 | /* Get each reserved primary GDT block and verify it holds backups */ | 570 | /* Get each reserved primary GDT block and verify it holds backups */ |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 09d9359c8055..cb96f127c366 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -671,6 +671,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
671 | unsigned long def_mount_opts; | 671 | unsigned long def_mount_opts; |
672 | struct super_block *sb = vfs->mnt_sb; | 672 | struct super_block *sb = vfs->mnt_sb; |
673 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 673 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
674 | journal_t *journal = sbi->s_journal; | ||
674 | struct ext4_super_block *es = sbi->s_es; | 675 | struct ext4_super_block *es = sbi->s_es; |
675 | 676 | ||
676 | def_mount_opts = le32_to_cpu(es->s_default_mount_opts); | 677 | def_mount_opts = le32_to_cpu(es->s_default_mount_opts); |
@@ -729,8 +730,15 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
729 | seq_printf(seq, ",commit=%u", | 730 | seq_printf(seq, ",commit=%u", |
730 | (unsigned) (sbi->s_commit_interval / HZ)); | 731 | (unsigned) (sbi->s_commit_interval / HZ)); |
731 | } | 732 | } |
732 | if (test_opt(sb, BARRIER)) | 733 | /* |
733 | seq_puts(seq, ",barrier=1"); | 734 | * We're changing the default of barrier mount option, so |
735 | * let's always display its mount state so it's clear what its | ||
736 | * status is. | ||
737 | */ | ||
738 | seq_puts(seq, ",barrier="); | ||
739 | seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0"); | ||
740 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) | ||
741 | seq_puts(seq, ",journal_async_commit"); | ||
734 | if (test_opt(sb, NOBH)) | 742 | if (test_opt(sb, NOBH)) |
735 | seq_puts(seq, ",nobh"); | 743 | seq_puts(seq, ",nobh"); |
736 | if (!test_opt(sb, EXTENTS)) | 744 | if (!test_opt(sb, EXTENTS)) |
@@ -1907,6 +1915,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1907 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 1915 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); |
1908 | 1916 | ||
1909 | set_opt(sbi->s_mount_opt, RESERVATION); | 1917 | set_opt(sbi->s_mount_opt, RESERVATION); |
1918 | set_opt(sbi->s_mount_opt, BARRIER); | ||
1910 | 1919 | ||
1911 | /* | 1920 | /* |
1912 | * turn on extents feature by default in ext4 filesystem | 1921 | * turn on extents feature by default in ext4 filesystem |
@@ -2189,6 +2198,29 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
2189 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { | 2198 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { |
2190 | if (ext4_load_journal(sb, es, journal_devnum)) | 2199 | if (ext4_load_journal(sb, es, journal_devnum)) |
2191 | goto failed_mount3; | 2200 | goto failed_mount3; |
2201 | if (!(sb->s_flags & MS_RDONLY) && | ||
2202 | EXT4_SB(sb)->s_journal->j_failed_commit) { | ||
2203 | printk(KERN_CRIT "EXT4-fs error (device %s): " | ||
2204 | "ext4_fill_super: Journal transaction " | ||
2205 | "%u is corrupt\n", sb->s_id, | ||
2206 | EXT4_SB(sb)->s_journal->j_failed_commit); | ||
2207 | if (test_opt (sb, ERRORS_RO)) { | ||
2208 | printk (KERN_CRIT | ||
2209 | "Mounting filesystem read-only\n"); | ||
2210 | sb->s_flags |= MS_RDONLY; | ||
2211 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
2212 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
2213 | } | ||
2214 | if (test_opt(sb, ERRORS_PANIC)) { | ||
2215 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
2216 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
2217 | ext4_commit_super(sb, es, 1); | ||
2218 | printk(KERN_CRIT | ||
2219 | "EXT4-fs (device %s): mount failed\n", | ||
2220 | sb->s_id); | ||
2221 | goto failed_mount4; | ||
2222 | } | ||
2223 | } | ||
2192 | } else if (journal_inum) { | 2224 | } else if (journal_inum) { |
2193 | if (ext4_create_journal(sb, es, journal_inum)) | 2225 | if (ext4_create_journal(sb, es, journal_inum)) |
2194 | goto failed_mount3; | 2226 | goto failed_mount3; |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 27cc1164ec36..771326b8047e 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -257,26 +257,34 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
257 | } | 257 | } |
258 | EXPORT_SYMBOL_GPL(fat_getattr); | 258 | EXPORT_SYMBOL_GPL(fat_getattr); |
259 | 259 | ||
260 | static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode, | 260 | static int fat_sanitize_mode(const struct msdos_sb_info *sbi, |
261 | mode_t mode) | 261 | struct inode *inode, umode_t *mode_ptr) |
262 | { | 262 | { |
263 | mode_t mask, req = mode & ~S_IFMT; | 263 | mode_t mask, perm; |
264 | 264 | ||
265 | if (S_ISREG(mode)) | 265 | /* |
266 | * Note, the basic check is already done by a caller of | ||
267 | * (attr->ia_mode & ~MSDOS_VALID_MODE) | ||
268 | */ | ||
269 | |||
270 | if (S_ISREG(inode->i_mode)) | ||
266 | mask = sbi->options.fs_fmask; | 271 | mask = sbi->options.fs_fmask; |
267 | else | 272 | else |
268 | mask = sbi->options.fs_dmask; | 273 | mask = sbi->options.fs_dmask; |
269 | 274 | ||
275 | perm = *mode_ptr & ~(S_IFMT | mask); | ||
276 | |||
270 | /* | 277 | /* |
271 | * Of the r and x bits, all (subject to umask) must be present. Of the | 278 | * Of the r and x bits, all (subject to umask) must be present. Of the |
272 | * w bits, either all (subject to umask) or none must be present. | 279 | * w bits, either all (subject to umask) or none must be present. |
273 | */ | 280 | */ |
274 | req &= ~mask; | 281 | if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) |
275 | if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) | ||
276 | return -EPERM; | 282 | return -EPERM; |
277 | if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask))) | 283 | if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) |
278 | return -EPERM; | 284 | return -EPERM; |
279 | 285 | ||
286 | *mode_ptr &= S_IFMT | perm; | ||
287 | |||
280 | return 0; | 288 | return 0; |
281 | } | 289 | } |
282 | 290 | ||
@@ -299,7 +307,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
299 | { | 307 | { |
300 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); | 308 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); |
301 | struct inode *inode = dentry->d_inode; | 309 | struct inode *inode = dentry->d_inode; |
302 | int mask, error = 0; | 310 | int error = 0; |
303 | unsigned int ia_valid; | 311 | unsigned int ia_valid; |
304 | 312 | ||
305 | lock_kernel(); | 313 | lock_kernel(); |
@@ -332,12 +340,13 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
332 | error = 0; | 340 | error = 0; |
333 | goto out; | 341 | goto out; |
334 | } | 342 | } |
343 | |||
335 | if (((attr->ia_valid & ATTR_UID) && | 344 | if (((attr->ia_valid & ATTR_UID) && |
336 | (attr->ia_uid != sbi->options.fs_uid)) || | 345 | (attr->ia_uid != sbi->options.fs_uid)) || |
337 | ((attr->ia_valid & ATTR_GID) && | 346 | ((attr->ia_valid & ATTR_GID) && |
338 | (attr->ia_gid != sbi->options.fs_gid)) || | 347 | (attr->ia_gid != sbi->options.fs_gid)) || |
339 | ((attr->ia_valid & ATTR_MODE) && | 348 | ((attr->ia_valid & ATTR_MODE) && |
340 | fat_check_mode(sbi, inode, attr->ia_mode) < 0)) | 349 | (attr->ia_mode & ~MSDOS_VALID_MODE))) |
341 | error = -EPERM; | 350 | error = -EPERM; |
342 | 351 | ||
343 | if (error) { | 352 | if (error) { |
@@ -346,15 +355,16 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
346 | goto out; | 355 | goto out; |
347 | } | 356 | } |
348 | 357 | ||
349 | error = inode_setattr(inode, attr); | 358 | /* |
350 | if (error) | 359 | * We don't return -EPERM here. Yes, strange, but this is too |
351 | goto out; | 360 | * old behavior. |
361 | */ | ||
362 | if (attr->ia_valid & ATTR_MODE) { | ||
363 | if (fat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) | ||
364 | attr->ia_valid &= ~ATTR_MODE; | ||
365 | } | ||
352 | 366 | ||
353 | if (S_ISDIR(inode->i_mode)) | 367 | error = inode_setattr(inode, attr); |
354 | mask = sbi->options.fs_dmask; | ||
355 | else | ||
356 | mask = sbi->options.fs_fmask; | ||
357 | inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask); | ||
358 | out: | 368 | out: |
359 | unlock_kernel(); | 369 | unlock_kernel(); |
360 | return error; | 370 | return error; |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 4d99685fdce4..a2ed72f7ceee 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -168,6 +168,7 @@ static int journal_submit_commit_record(journal_t *journal, | |||
168 | spin_unlock(&journal->j_state_lock); | 168 | spin_unlock(&journal->j_state_lock); |
169 | 169 | ||
170 | /* And try again, without the barrier */ | 170 | /* And try again, without the barrier */ |
171 | lock_buffer(bh); | ||
171 | set_buffer_uptodate(bh); | 172 | set_buffer_uptodate(bh); |
172 | set_buffer_dirty(bh); | 173 | set_buffer_dirty(bh); |
173 | ret = submit_bh(WRITE, bh); | 174 | ret = submit_bh(WRITE, bh); |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 5d0405a9e7ca..058f50f65b76 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -344,6 +344,7 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh, | |||
344 | *crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data, | 344 | *crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data, |
345 | obh->b_size); | 345 | obh->b_size); |
346 | } | 346 | } |
347 | put_bh(obh); | ||
347 | } | 348 | } |
348 | return 0; | 349 | return 0; |
349 | } | 350 | } |
@@ -610,9 +611,8 @@ static int do_one_pass(journal_t *journal, | |||
610 | chksum_err = chksum_seen = 0; | 611 | chksum_err = chksum_seen = 0; |
611 | 612 | ||
612 | if (info->end_transaction) { | 613 | if (info->end_transaction) { |
613 | printk(KERN_ERR "JBD: Transaction %u " | 614 | journal->j_failed_commit = |
614 | "found to be corrupt.\n", | 615 | info->end_transaction; |
615 | next_commit_ID - 1); | ||
616 | brelse(bh); | 616 | brelse(bh); |
617 | break; | 617 | break; |
618 | } | 618 | } |
@@ -643,10 +643,8 @@ static int do_one_pass(journal_t *journal, | |||
643 | 643 | ||
644 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 644 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, |
645 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){ | 645 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){ |
646 | printk(KERN_ERR | 646 | journal->j_failed_commit = |
647 | "JBD: Transaction %u " | 647 | next_commit_ID; |
648 | "found to be corrupt.\n", | ||
649 | next_commit_ID); | ||
650 | brelse(bh); | 648 | brelse(bh); |
651 | break; | 649 | break; |
652 | } | 650 | } |
diff --git a/fs/libfs.c b/fs/libfs.c index b004dfadd891..892d41cb3382 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -528,6 +528,23 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos, | |||
528 | return count; | 528 | return count; |
529 | } | 529 | } |
530 | 530 | ||
531 | ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, | ||
532 | const void *from, size_t available) | ||
533 | { | ||
534 | loff_t pos = *ppos; | ||
535 | |||
536 | if (pos < 0) | ||
537 | return -EINVAL; | ||
538 | if (pos >= available) | ||
539 | return 0; | ||
540 | if (count > available - pos) | ||
541 | count = available - pos; | ||
542 | memcpy(to, from + pos, count); | ||
543 | *ppos = pos + count; | ||
544 | |||
545 | return count; | ||
546 | } | ||
547 | |||
531 | /* | 548 | /* |
532 | * Transaction based IO. | 549 | * Transaction based IO. |
533 | * The file expects a single write which triggers the transaction, and then | 550 | * The file expects a single write which triggers the transaction, and then |
@@ -800,6 +817,7 @@ EXPORT_SYMBOL(simple_statfs); | |||
800 | EXPORT_SYMBOL(simple_sync_file); | 817 | EXPORT_SYMBOL(simple_sync_file); |
801 | EXPORT_SYMBOL(simple_unlink); | 818 | EXPORT_SYMBOL(simple_unlink); |
802 | EXPORT_SYMBOL(simple_read_from_buffer); | 819 | EXPORT_SYMBOL(simple_read_from_buffer); |
820 | EXPORT_SYMBOL(memory_read_from_buffer); | ||
803 | EXPORT_SYMBOL(simple_transaction_get); | 821 | EXPORT_SYMBOL(simple_transaction_get); |
804 | EXPORT_SYMBOL(simple_transaction_read); | 822 | EXPORT_SYMBOL(simple_transaction_read); |
805 | EXPORT_SYMBOL(simple_transaction_release); | 823 | EXPORT_SYMBOL(simple_transaction_release); |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 9e3b8c33c24b..797d775e0354 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -288,7 +288,7 @@ static void render_cap_t(struct seq_file *m, const char *header, | |||
288 | seq_printf(m, "%s", header); | 288 | seq_printf(m, "%s", header); |
289 | CAP_FOR_EACH_U32(__capi) { | 289 | CAP_FOR_EACH_U32(__capi) { |
290 | seq_printf(m, "%08x", | 290 | seq_printf(m, "%08x", |
291 | a->cap[(_LINUX_CAPABILITY_U32S-1) - __capi]); | 291 | a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]); |
292 | } | 292 | } |
293 | seq_printf(m, "\n"); | 293 | seq_printf(m, "\n"); |
294 | } | 294 | } |
diff --git a/fs/proc/base.c b/fs/proc/base.c index c447e0743a3c..3b455371e7ff 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -127,6 +127,25 @@ struct pid_entry { | |||
127 | NULL, &proc_single_file_operations, \ | 127 | NULL, &proc_single_file_operations, \ |
128 | { .proc_show = &proc_##OTYPE } ) | 128 | { .proc_show = &proc_##OTYPE } ) |
129 | 129 | ||
130 | /* | ||
131 | * Count the number of hardlinks for the pid_entry table, excluding the . | ||
132 | * and .. links. | ||
133 | */ | ||
134 | static unsigned int pid_entry_count_dirs(const struct pid_entry *entries, | ||
135 | unsigned int n) | ||
136 | { | ||
137 | unsigned int i; | ||
138 | unsigned int count; | ||
139 | |||
140 | count = 0; | ||
141 | for (i = 0; i < n; ++i) { | ||
142 | if (S_ISDIR(entries[i].mode)) | ||
143 | ++count; | ||
144 | } | ||
145 | |||
146 | return count; | ||
147 | } | ||
148 | |||
130 | int maps_protect; | 149 | int maps_protect; |
131 | EXPORT_SYMBOL(maps_protect); | 150 | EXPORT_SYMBOL(maps_protect); |
132 | 151 | ||
@@ -2585,10 +2604,9 @@ static struct dentry *proc_pid_instantiate(struct inode *dir, | |||
2585 | inode->i_op = &proc_tgid_base_inode_operations; | 2604 | inode->i_op = &proc_tgid_base_inode_operations; |
2586 | inode->i_fop = &proc_tgid_base_operations; | 2605 | inode->i_fop = &proc_tgid_base_operations; |
2587 | inode->i_flags|=S_IMMUTABLE; | 2606 | inode->i_flags|=S_IMMUTABLE; |
2588 | inode->i_nlink = 5; | 2607 | |
2589 | #ifdef CONFIG_SECURITY | 2608 | inode->i_nlink = 2 + pid_entry_count_dirs(tgid_base_stuff, |
2590 | inode->i_nlink += 1; | 2609 | ARRAY_SIZE(tgid_base_stuff)); |
2591 | #endif | ||
2592 | 2610 | ||
2593 | dentry->d_op = &pid_dentry_operations; | 2611 | dentry->d_op = &pid_dentry_operations; |
2594 | 2612 | ||
@@ -2816,10 +2834,9 @@ static struct dentry *proc_task_instantiate(struct inode *dir, | |||
2816 | inode->i_op = &proc_tid_base_inode_operations; | 2834 | inode->i_op = &proc_tid_base_inode_operations; |
2817 | inode->i_fop = &proc_tid_base_operations; | 2835 | inode->i_fop = &proc_tid_base_operations; |
2818 | inode->i_flags|=S_IMMUTABLE; | 2836 | inode->i_flags|=S_IMMUTABLE; |
2819 | inode->i_nlink = 4; | 2837 | |
2820 | #ifdef CONFIG_SECURITY | 2838 | inode->i_nlink = 2 + pid_entry_count_dirs(tid_base_stuff, |
2821 | inode->i_nlink += 1; | 2839 | ARRAY_SIZE(tid_base_stuff)); |
2822 | #endif | ||
2823 | 2840 | ||
2824 | dentry->d_op = &pid_dentry_operations; | 2841 | dentry->d_op = &pid_dentry_operations; |
2825 | 2842 | ||
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 32dc14cd8900..7e277f2ad466 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -716,7 +716,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf, | |||
716 | pfn = src / KPMSIZE; | 716 | pfn = src / KPMSIZE; |
717 | count = min_t(size_t, count, (max_pfn * KPMSIZE) - src); | 717 | count = min_t(size_t, count, (max_pfn * KPMSIZE) - src); |
718 | if (src & KPMMASK || count & KPMMASK) | 718 | if (src & KPMMASK || count & KPMMASK) |
719 | return -EIO; | 719 | return -EINVAL; |
720 | 720 | ||
721 | while (count > 0) { | 721 | while (count > 0) { |
722 | ppage = NULL; | 722 | ppage = NULL; |
@@ -726,7 +726,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf, | |||
726 | if (!ppage) | 726 | if (!ppage) |
727 | pcount = 0; | 727 | pcount = 0; |
728 | else | 728 | else |
729 | pcount = atomic_read(&ppage->_count); | 729 | pcount = page_mapcount(ppage); |
730 | 730 | ||
731 | if (put_user(pcount, out++)) { | 731 | if (put_user(pcount, out++)) { |
732 | ret = -EFAULT; | 732 | ret = -EFAULT; |
@@ -782,7 +782,7 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf, | |||
782 | pfn = src / KPMSIZE; | 782 | pfn = src / KPMSIZE; |
783 | count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src); | 783 | count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src); |
784 | if (src & KPMMASK || count & KPMMASK) | 784 | if (src & KPMMASK || count & KPMMASK) |
785 | return -EIO; | 785 | return -EINVAL; |
786 | 786 | ||
787 | while (count > 0) { | 787 | while (count > 0) { |
788 | ppage = NULL; | 788 | ppage = NULL; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 88717c0f941b..ab8ccc9d14ff 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -315,9 +315,9 @@ struct mem_size_stats { | |||
315 | }; | 315 | }; |
316 | 316 | ||
317 | static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | 317 | static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, |
318 | void *private) | 318 | struct mm_walk *walk) |
319 | { | 319 | { |
320 | struct mem_size_stats *mss = private; | 320 | struct mem_size_stats *mss = walk->private; |
321 | struct vm_area_struct *vma = mss->vma; | 321 | struct vm_area_struct *vma = mss->vma; |
322 | pte_t *pte, ptent; | 322 | pte_t *pte, ptent; |
323 | spinlock_t *ptl; | 323 | spinlock_t *ptl; |
@@ -365,19 +365,21 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range }; | ||
369 | |||
370 | static int show_smap(struct seq_file *m, void *v) | 368 | static int show_smap(struct seq_file *m, void *v) |
371 | { | 369 | { |
372 | struct vm_area_struct *vma = v; | 370 | struct vm_area_struct *vma = v; |
373 | struct mem_size_stats mss; | 371 | struct mem_size_stats mss; |
374 | int ret; | 372 | int ret; |
373 | struct mm_walk smaps_walk = { | ||
374 | .pmd_entry = smaps_pte_range, | ||
375 | .mm = vma->vm_mm, | ||
376 | .private = &mss, | ||
377 | }; | ||
375 | 378 | ||
376 | memset(&mss, 0, sizeof mss); | 379 | memset(&mss, 0, sizeof mss); |
377 | mss.vma = vma; | 380 | mss.vma = vma; |
378 | if (vma->vm_mm && !is_vm_hugetlb_page(vma)) | 381 | if (vma->vm_mm && !is_vm_hugetlb_page(vma)) |
379 | walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end, | 382 | walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); |
380 | &smaps_walk, &mss); | ||
381 | 383 | ||
382 | ret = show_map(m, v); | 384 | ret = show_map(m, v); |
383 | if (ret) | 385 | if (ret) |
@@ -426,9 +428,9 @@ const struct file_operations proc_smaps_operations = { | |||
426 | }; | 428 | }; |
427 | 429 | ||
428 | static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, | 430 | static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, |
429 | unsigned long end, void *private) | 431 | unsigned long end, struct mm_walk *walk) |
430 | { | 432 | { |
431 | struct vm_area_struct *vma = private; | 433 | struct vm_area_struct *vma = walk->private; |
432 | pte_t *pte, ptent; | 434 | pte_t *pte, ptent; |
433 | spinlock_t *ptl; | 435 | spinlock_t *ptl; |
434 | struct page *page; | 436 | struct page *page; |
@@ -452,8 +454,6 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, | |||
452 | return 0; | 454 | return 0; |
453 | } | 455 | } |
454 | 456 | ||
455 | static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range }; | ||
456 | |||
457 | static ssize_t clear_refs_write(struct file *file, const char __user *buf, | 457 | static ssize_t clear_refs_write(struct file *file, const char __user *buf, |
458 | size_t count, loff_t *ppos) | 458 | size_t count, loff_t *ppos) |
459 | { | 459 | { |
@@ -476,11 +476,17 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, | |||
476 | return -ESRCH; | 476 | return -ESRCH; |
477 | mm = get_task_mm(task); | 477 | mm = get_task_mm(task); |
478 | if (mm) { | 478 | if (mm) { |
479 | static struct mm_walk clear_refs_walk; | ||
480 | memset(&clear_refs_walk, 0, sizeof(clear_refs_walk)); | ||
481 | clear_refs_walk.pmd_entry = clear_refs_pte_range; | ||
482 | clear_refs_walk.mm = mm; | ||
479 | down_read(&mm->mmap_sem); | 483 | down_read(&mm->mmap_sem); |
480 | for (vma = mm->mmap; vma; vma = vma->vm_next) | 484 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
485 | clear_refs_walk.private = vma; | ||
481 | if (!is_vm_hugetlb_page(vma)) | 486 | if (!is_vm_hugetlb_page(vma)) |
482 | walk_page_range(mm, vma->vm_start, vma->vm_end, | 487 | walk_page_range(vma->vm_start, vma->vm_end, |
483 | &clear_refs_walk, vma); | 488 | &clear_refs_walk); |
489 | } | ||
484 | flush_tlb_mm(mm); | 490 | flush_tlb_mm(mm); |
485 | up_read(&mm->mmap_sem); | 491 | up_read(&mm->mmap_sem); |
486 | mmput(mm); | 492 | mmput(mm); |
@@ -496,7 +502,7 @@ const struct file_operations proc_clear_refs_operations = { | |||
496 | }; | 502 | }; |
497 | 503 | ||
498 | struct pagemapread { | 504 | struct pagemapread { |
499 | char __user *out, *end; | 505 | u64 __user *out, *end; |
500 | }; | 506 | }; |
501 | 507 | ||
502 | #define PM_ENTRY_BYTES sizeof(u64) | 508 | #define PM_ENTRY_BYTES sizeof(u64) |
@@ -519,28 +525,18 @@ struct pagemapread { | |||
519 | static int add_to_pagemap(unsigned long addr, u64 pfn, | 525 | static int add_to_pagemap(unsigned long addr, u64 pfn, |
520 | struct pagemapread *pm) | 526 | struct pagemapread *pm) |
521 | { | 527 | { |
522 | /* | ||
523 | * Make sure there's room in the buffer for an | ||
524 | * entire entry. Otherwise, only copy part of | ||
525 | * the pfn. | ||
526 | */ | ||
527 | if (pm->out + PM_ENTRY_BYTES >= pm->end) { | ||
528 | if (copy_to_user(pm->out, &pfn, pm->end - pm->out)) | ||
529 | return -EFAULT; | ||
530 | pm->out = pm->end; | ||
531 | return PM_END_OF_BUFFER; | ||
532 | } | ||
533 | |||
534 | if (put_user(pfn, pm->out)) | 528 | if (put_user(pfn, pm->out)) |
535 | return -EFAULT; | 529 | return -EFAULT; |
536 | pm->out += PM_ENTRY_BYTES; | 530 | pm->out++; |
531 | if (pm->out >= pm->end) | ||
532 | return PM_END_OF_BUFFER; | ||
537 | return 0; | 533 | return 0; |
538 | } | 534 | } |
539 | 535 | ||
540 | static int pagemap_pte_hole(unsigned long start, unsigned long end, | 536 | static int pagemap_pte_hole(unsigned long start, unsigned long end, |
541 | void *private) | 537 | struct mm_walk *walk) |
542 | { | 538 | { |
543 | struct pagemapread *pm = private; | 539 | struct pagemapread *pm = walk->private; |
544 | unsigned long addr; | 540 | unsigned long addr; |
545 | int err = 0; | 541 | int err = 0; |
546 | for (addr = start; addr < end; addr += PAGE_SIZE) { | 542 | for (addr = start; addr < end; addr += PAGE_SIZE) { |
@@ -557,24 +553,45 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte) | |||
557 | return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); | 553 | return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); |
558 | } | 554 | } |
559 | 555 | ||
556 | static unsigned long pte_to_pagemap_entry(pte_t pte) | ||
557 | { | ||
558 | unsigned long pme = 0; | ||
559 | if (is_swap_pte(pte)) | ||
560 | pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte)) | ||
561 | | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; | ||
562 | else if (pte_present(pte)) | ||
563 | pme = PM_PFRAME(pte_pfn(pte)) | ||
564 | | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; | ||
565 | return pme; | ||
566 | } | ||
567 | |||
560 | static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | 568 | static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, |
561 | void *private) | 569 | struct mm_walk *walk) |
562 | { | 570 | { |
563 | struct pagemapread *pm = private; | 571 | struct vm_area_struct *vma; |
572 | struct pagemapread *pm = walk->private; | ||
564 | pte_t *pte; | 573 | pte_t *pte; |
565 | int err = 0; | 574 | int err = 0; |
566 | 575 | ||
576 | /* find the first VMA at or above 'addr' */ | ||
577 | vma = find_vma(walk->mm, addr); | ||
567 | for (; addr != end; addr += PAGE_SIZE) { | 578 | for (; addr != end; addr += PAGE_SIZE) { |
568 | u64 pfn = PM_NOT_PRESENT; | 579 | u64 pfn = PM_NOT_PRESENT; |
569 | pte = pte_offset_map(pmd, addr); | 580 | |
570 | if (is_swap_pte(*pte)) | 581 | /* check to see if we've left 'vma' behind |
571 | pfn = PM_PFRAME(swap_pte_to_pagemap_entry(*pte)) | 582 | * and need a new, higher one */ |
572 | | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; | 583 | if (vma && (addr >= vma->vm_end)) |
573 | else if (pte_present(*pte)) | 584 | vma = find_vma(walk->mm, addr); |
574 | pfn = PM_PFRAME(pte_pfn(*pte)) | 585 | |
575 | | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; | 586 | /* check that 'vma' actually covers this address, |
576 | /* unmap so we're not in atomic when we copy to userspace */ | 587 | * and that it isn't a huge page vma */ |
577 | pte_unmap(pte); | 588 | if (vma && (vma->vm_start <= addr) && |
589 | !is_vm_hugetlb_page(vma)) { | ||
590 | pte = pte_offset_map(pmd, addr); | ||
591 | pfn = pte_to_pagemap_entry(*pte); | ||
592 | /* unmap before userspace copy */ | ||
593 | pte_unmap(pte); | ||
594 | } | ||
578 | err = add_to_pagemap(addr, pfn, pm); | 595 | err = add_to_pagemap(addr, pfn, pm); |
579 | if (err) | 596 | if (err) |
580 | return err; | 597 | return err; |
@@ -634,7 +651,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
634 | 651 | ||
635 | ret = -EINVAL; | 652 | ret = -EINVAL; |
636 | /* file position must be aligned */ | 653 | /* file position must be aligned */ |
637 | if (*ppos % PM_ENTRY_BYTES) | 654 | if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) |
638 | goto out_task; | 655 | goto out_task; |
639 | 656 | ||
640 | ret = 0; | 657 | ret = 0; |
@@ -664,8 +681,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
664 | goto out_pages; | 681 | goto out_pages; |
665 | } | 682 | } |
666 | 683 | ||
667 | pm.out = buf; | 684 | pm.out = (u64 *)buf; |
668 | pm.end = buf + count; | 685 | pm.end = (u64 *)(buf + count); |
669 | 686 | ||
670 | if (!ptrace_may_attach(task)) { | 687 | if (!ptrace_may_attach(task)) { |
671 | ret = -EIO; | 688 | ret = -EIO; |
@@ -685,14 +702,14 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
685 | * user buffer is tracked in "pm", and the walk | 702 | * user buffer is tracked in "pm", and the walk |
686 | * will stop when we hit the end of the buffer. | 703 | * will stop when we hit the end of the buffer. |
687 | */ | 704 | */ |
688 | ret = walk_page_range(mm, start_vaddr, end_vaddr, | 705 | ret = walk_page_range(start_vaddr, end_vaddr, |
689 | &pagemap_walk, &pm); | 706 | &pagemap_walk); |
690 | if (ret == PM_END_OF_BUFFER) | 707 | if (ret == PM_END_OF_BUFFER) |
691 | ret = 0; | 708 | ret = 0; |
692 | /* don't need mmap_sem for these, but this looks cleaner */ | 709 | /* don't need mmap_sem for these, but this looks cleaner */ |
693 | *ppos += pm.out - buf; | 710 | *ppos += (char *)pm.out - buf; |
694 | if (!ret) | 711 | if (!ret) |
695 | ret = pm.out - buf; | 712 | ret = (char *)pm.out - buf; |
696 | } | 713 | } |
697 | 714 | ||
698 | out_pages: | 715 | out_pages: |