diff options
148 files changed, 1495 insertions, 1618 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index d449e632e6a0..8e2da1e06e3b 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
| @@ -61,6 +61,7 @@ ata *); | |||
| 61 | ssize_t (*listxattr) (struct dentry *, char *, size_t); | 61 | ssize_t (*listxattr) (struct dentry *, char *, size_t); |
| 62 | int (*removexattr) (struct dentry *, const char *); | 62 | int (*removexattr) (struct dentry *, const char *); |
| 63 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); | 63 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); |
| 64 | void (*update_time)(struct inode *, struct timespec *, int); | ||
| 64 | 65 | ||
| 65 | locking rules: | 66 | locking rules: |
| 66 | all may block | 67 | all may block |
| @@ -87,6 +88,8 @@ getxattr: no | |||
| 87 | listxattr: no | 88 | listxattr: no |
| 88 | removexattr: yes | 89 | removexattr: yes |
| 89 | fiemap: no | 90 | fiemap: no |
| 91 | update_time: no | ||
| 92 | |||
| 90 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on | 93 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on |
| 91 | victim. | 94 | victim. |
| 92 | cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. | 95 | cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index ef19f91a0f12..efd23f481704 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -363,6 +363,7 @@ struct inode_operations { | |||
| 363 | ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); | 363 | ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); |
| 364 | ssize_t (*listxattr) (struct dentry *, char *, size_t); | 364 | ssize_t (*listxattr) (struct dentry *, char *, size_t); |
| 365 | int (*removexattr) (struct dentry *, const char *); | 365 | int (*removexattr) (struct dentry *, const char *); |
| 366 | void (*update_time)(struct inode *, struct timespec *, int); | ||
| 366 | }; | 367 | }; |
| 367 | 368 | ||
| 368 | Again, all methods are called without any locks being held, unless | 369 | Again, all methods are called without any locks being held, unless |
| @@ -471,6 +472,9 @@ otherwise noted. | |||
| 471 | removexattr: called by the VFS to remove an extended attribute from | 472 | removexattr: called by the VFS to remove an extended attribute from |
| 472 | a file. This method is called by removexattr(2) system call. | 473 | a file. This method is called by removexattr(2) system call. |
| 473 | 474 | ||
| 475 | update_time: called by the VFS to update a specific time or the i_version of | ||
| 476 | an inode. If this is not defined the VFS will update the inode itself | ||
| 477 | and call mark_inode_dirty_sync. | ||
| 474 | 478 | ||
| 475 | The Address Space Object | 479 | The Address Space Object |
| 476 | ======================== | 480 | ======================== |
diff --git a/arch/alpha/include/asm/posix_types.h b/arch/alpha/include/asm/posix_types.h index 24779fc95994..5a8a48320efe 100644 --- a/arch/alpha/include/asm/posix_types.h +++ b/arch/alpha/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned int __kernel_ino_t; | 10 | typedef unsigned int __kernel_ino_t; |
| 11 | #define __kernel_ino_t __kernel_ino_t | 11 | #define __kernel_ino_t __kernel_ino_t |
| 12 | 12 | ||
| 13 | typedef unsigned int __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ | 13 | typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ |
| 17 | 14 | ||
| 18 | #include <asm-generic/posix_types.h> | 15 | #include <asm-generic/posix_types.h> |
diff --git a/arch/arm/include/asm/posix_types.h b/arch/arm/include/asm/posix_types.h index efdf99045d87..d2de9cbbcd9b 100644 --- a/arch/arm/include/asm/posix_types.h +++ b/arch/arm/include/asm/posix_types.h | |||
| @@ -22,9 +22,6 @@ | |||
| 22 | typedef unsigned short __kernel_mode_t; | 22 | typedef unsigned short __kernel_mode_t; |
| 23 | #define __kernel_mode_t __kernel_mode_t | 23 | #define __kernel_mode_t __kernel_mode_t |
| 24 | 24 | ||
| 25 | typedef unsigned short __kernel_nlink_t; | ||
| 26 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 27 | |||
| 28 | typedef unsigned short __kernel_ipc_pid_t; | 25 | typedef unsigned short __kernel_ipc_pid_t; |
| 29 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 26 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 30 | 27 | ||
diff --git a/arch/avr32/include/asm/posix_types.h b/arch/avr32/include/asm/posix_types.h index 74667bfc88cc..9ba9e749b3f3 100644 --- a/arch/avr32/include/asm/posix_types.h +++ b/arch/avr32/include/asm/posix_types.h | |||
| @@ -17,9 +17,6 @@ | |||
| 17 | typedef unsigned short __kernel_mode_t; | 17 | typedef unsigned short __kernel_mode_t; |
| 18 | #define __kernel_mode_t __kernel_mode_t | 18 | #define __kernel_mode_t __kernel_mode_t |
| 19 | 19 | ||
| 20 | typedef unsigned short __kernel_nlink_t; | ||
| 21 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 22 | |||
| 23 | typedef unsigned short __kernel_ipc_pid_t; | 20 | typedef unsigned short __kernel_ipc_pid_t; |
| 24 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 21 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 25 | 22 | ||
diff --git a/arch/blackfin/include/asm/posix_types.h b/arch/blackfin/include/asm/posix_types.h index 41bc1875c4d7..1bd3436db6a7 100644 --- a/arch/blackfin/include/asm/posix_types.h +++ b/arch/blackfin/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned int __kernel_ipc_pid_t; | 13 | typedef unsigned int __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/arch/cris/include/asm/posix_types.h b/arch/cris/include/asm/posix_types.h index 234891c74e2b..ce4e51793151 100644 --- a/arch/cris/include/asm/posix_types.h +++ b/arch/cris/include/asm/posix_types.h | |||
| @@ -15,9 +15,6 @@ | |||
| 15 | typedef unsigned short __kernel_mode_t; | 15 | typedef unsigned short __kernel_mode_t; |
| 16 | #define __kernel_mode_t __kernel_mode_t | 16 | #define __kernel_mode_t __kernel_mode_t |
| 17 | 17 | ||
| 18 | typedef unsigned short __kernel_nlink_t; | ||
| 19 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 20 | |||
| 21 | typedef unsigned short __kernel_ipc_pid_t; | 18 | typedef unsigned short __kernel_ipc_pid_t; |
| 22 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 19 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 23 | 20 | ||
diff --git a/arch/frv/include/asm/posix_types.h b/arch/frv/include/asm/posix_types.h index 3f34cb45fbb3..fe512af74a5a 100644 --- a/arch/frv/include/asm/posix_types.h +++ b/arch/frv/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned short __kernel_ipc_pid_t; | 13 | typedef unsigned short __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/arch/h8300/include/asm/posix_types.h b/arch/h8300/include/asm/posix_types.h index bc4c34efb1ad..91e62ba4c7b0 100644 --- a/arch/h8300/include/asm/posix_types.h +++ b/arch/h8300/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned short __kernel_ipc_pid_t; | 13 | typedef unsigned short __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/arch/ia64/include/asm/posix_types.h b/arch/ia64/include/asm/posix_types.h index 7323ab9467eb..99ee1d6510cf 100644 --- a/arch/ia64/include/asm/posix_types.h +++ b/arch/ia64/include/asm/posix_types.h | |||
| @@ -1,9 +1,6 @@ | |||
| 1 | #ifndef _ASM_IA64_POSIX_TYPES_H | 1 | #ifndef _ASM_IA64_POSIX_TYPES_H |
| 2 | #define _ASM_IA64_POSIX_TYPES_H | 2 | #define _ASM_IA64_POSIX_TYPES_H |
| 3 | 3 | ||
| 4 | typedef unsigned int __kernel_nlink_t; | ||
| 5 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 6 | |||
| 7 | typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ | 4 | typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ |
| 8 | 5 | ||
| 9 | #include <asm-generic/posix_types.h> | 6 | #include <asm-generic/posix_types.h> |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index f00ba025375d..d7f558c1e711 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
| @@ -604,12 +604,6 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) | |||
| 604 | spin_unlock(&(x)->ctx_lock); | 604 | spin_unlock(&(x)->ctx_lock); |
| 605 | } | 605 | } |
| 606 | 606 | ||
| 607 | static inline unsigned long | ||
| 608 | pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec) | ||
| 609 | { | ||
| 610 | return get_unmapped_area(file, addr, len, pgoff, flags); | ||
| 611 | } | ||
| 612 | |||
| 613 | /* forward declaration */ | 607 | /* forward declaration */ |
| 614 | static const struct dentry_operations pfmfs_dentry_operations; | 608 | static const struct dentry_operations pfmfs_dentry_operations; |
| 615 | 609 | ||
| @@ -2333,8 +2327,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t | |||
| 2333 | down_write(&task->mm->mmap_sem); | 2327 | down_write(&task->mm->mmap_sem); |
| 2334 | 2328 | ||
| 2335 | /* find some free area in address space, must have mmap sem held */ | 2329 | /* find some free area in address space, must have mmap sem held */ |
| 2336 | vma->vm_start = pfm_get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS, 0); | 2330 | vma->vm_start = get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS); |
| 2337 | if (vma->vm_start == 0UL) { | 2331 | if (IS_ERR_VALUE(vma->vm_start)) { |
| 2338 | DPRINT(("Cannot find unmapped area for size %ld\n", size)); | 2332 | DPRINT(("Cannot find unmapped area for size %ld\n", size)); |
| 2339 | up_write(&task->mm->mmap_sem); | 2333 | up_write(&task->mm->mmap_sem); |
| 2340 | goto error; | 2334 | goto error; |
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 609d50056a6c..d9439ef2f661 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c | |||
| @@ -171,22 +171,9 @@ asmlinkage unsigned long | |||
| 171 | ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, | 171 | ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, |
| 172 | unsigned long new_addr) | 172 | unsigned long new_addr) |
| 173 | { | 173 | { |
| 174 | extern unsigned long do_mremap (unsigned long addr, | 174 | addr = sys_mremap(addr, old_len, new_len, flags, new_addr); |
| 175 | unsigned long old_len, | 175 | if (!IS_ERR((void *) addr)) |
| 176 | unsigned long new_len, | 176 | force_successful_syscall_return(); |
| 177 | unsigned long flags, | ||
| 178 | unsigned long new_addr); | ||
| 179 | |||
| 180 | down_write(¤t->mm->mmap_sem); | ||
| 181 | { | ||
| 182 | addr = do_mremap(addr, old_len, new_len, flags, new_addr); | ||
| 183 | } | ||
| 184 | up_write(¤t->mm->mmap_sem); | ||
| 185 | |||
| 186 | if (IS_ERR((void *) addr)) | ||
| 187 | return addr; | ||
| 188 | |||
| 189 | force_successful_syscall_return(); | ||
| 190 | return addr; | 177 | return addr; |
| 191 | } | 178 | } |
| 192 | 179 | ||
diff --git a/arch/m32r/include/asm/posix_types.h b/arch/m32r/include/asm/posix_types.h index 0195850e1f88..236de26a409b 100644 --- a/arch/m32r/include/asm/posix_types.h +++ b/arch/m32r/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned short __kernel_ipc_pid_t; | 13 | typedef unsigned short __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/arch/m68k/include/asm/posix_types.h b/arch/m68k/include/asm/posix_types.h index 6373093be72b..cf4dbf70fdc7 100644 --- a/arch/m68k/include/asm/posix_types.h +++ b/arch/m68k/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned short __kernel_ipc_pid_t; | 13 | typedef unsigned short __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/arch/mips/include/asm/posix_types.h b/arch/mips/include/asm/posix_types.h index e0308dcca135..fa03ec3fbf89 100644 --- a/arch/mips/include/asm/posix_types.h +++ b/arch/mips/include/asm/posix_types.h | |||
| @@ -17,11 +17,6 @@ | |||
| 17 | * assume GCC is being used. | 17 | * assume GCC is being used. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #if (_MIPS_SZLONG == 64) | ||
| 21 | typedef unsigned int __kernel_nlink_t; | ||
| 22 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 23 | #endif | ||
| 24 | |||
| 25 | typedef long __kernel_daddr_t; | 20 | typedef long __kernel_daddr_t; |
| 26 | #define __kernel_daddr_t __kernel_daddr_t | 21 | #define __kernel_daddr_t __kernel_daddr_t |
| 27 | 22 | ||
diff --git a/arch/mips/include/asm/stat.h b/arch/mips/include/asm/stat.h index 6e00f751ab6d..fe9a4c3ec5a1 100644 --- a/arch/mips/include/asm/stat.h +++ b/arch/mips/include/asm/stat.h | |||
| @@ -20,7 +20,7 @@ struct stat { | |||
| 20 | long st_pad1[3]; /* Reserved for network id */ | 20 | long st_pad1[3]; /* Reserved for network id */ |
| 21 | ino_t st_ino; | 21 | ino_t st_ino; |
| 22 | mode_t st_mode; | 22 | mode_t st_mode; |
| 23 | nlink_t st_nlink; | 23 | __u32 st_nlink; |
| 24 | uid_t st_uid; | 24 | uid_t st_uid; |
| 25 | gid_t st_gid; | 25 | gid_t st_gid; |
| 26 | unsigned st_rdev; | 26 | unsigned st_rdev; |
| @@ -55,7 +55,7 @@ struct stat64 { | |||
| 55 | unsigned long long st_ino; | 55 | unsigned long long st_ino; |
| 56 | 56 | ||
| 57 | mode_t st_mode; | 57 | mode_t st_mode; |
| 58 | nlink_t st_nlink; | 58 | __u32 st_nlink; |
| 59 | 59 | ||
| 60 | uid_t st_uid; | 60 | uid_t st_uid; |
| 61 | gid_t st_gid; | 61 | gid_t st_gid; |
| @@ -96,7 +96,7 @@ struct stat { | |||
| 96 | unsigned long st_ino; | 96 | unsigned long st_ino; |
| 97 | 97 | ||
| 98 | mode_t st_mode; | 98 | mode_t st_mode; |
| 99 | nlink_t st_nlink; | 99 | __u32 st_nlink; |
| 100 | 100 | ||
| 101 | uid_t st_uid; | 101 | uid_t st_uid; |
| 102 | gid_t st_gid; | 102 | gid_t st_gid; |
diff --git a/arch/mn10300/include/asm/posix_types.h b/arch/mn10300/include/asm/posix_types.h index ab506181ec31..d31eeea480cf 100644 --- a/arch/mn10300/include/asm/posix_types.h +++ b/arch/mn10300/include/asm/posix_types.h | |||
| @@ -20,9 +20,6 @@ | |||
| 20 | typedef unsigned short __kernel_mode_t; | 20 | typedef unsigned short __kernel_mode_t; |
| 21 | #define __kernel_mode_t __kernel_mode_t | 21 | #define __kernel_mode_t __kernel_mode_t |
| 22 | 22 | ||
| 23 | typedef unsigned short __kernel_nlink_t; | ||
| 24 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 25 | |||
| 26 | typedef unsigned short __kernel_ipc_pid_t; | 23 | typedef unsigned short __kernel_ipc_pid_t; |
| 27 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 24 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 28 | 25 | ||
diff --git a/arch/parisc/include/asm/posix_types.h b/arch/parisc/include/asm/posix_types.h index 5212b0357daf..b9344256f76b 100644 --- a/arch/parisc/include/asm/posix_types.h +++ b/arch/parisc/include/asm/posix_types.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned short __kernel_ipc_pid_t; | 13 | typedef unsigned short __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/arch/parisc/include/asm/stat.h b/arch/parisc/include/asm/stat.h index 9d5fbbc5c31f..d76fbda5d62c 100644 --- a/arch/parisc/include/asm/stat.h +++ b/arch/parisc/include/asm/stat.h | |||
| @@ -7,7 +7,7 @@ struct stat { | |||
| 7 | unsigned int st_dev; /* dev_t is 32 bits on parisc */ | 7 | unsigned int st_dev; /* dev_t is 32 bits on parisc */ |
| 8 | ino_t st_ino; /* 32 bits */ | 8 | ino_t st_ino; /* 32 bits */ |
| 9 | mode_t st_mode; /* 16 bits */ | 9 | mode_t st_mode; /* 16 bits */ |
| 10 | nlink_t st_nlink; /* 16 bits */ | 10 | unsigned short st_nlink; /* 16 bits */ |
| 11 | unsigned short st_reserved1; /* old st_uid */ | 11 | unsigned short st_reserved1; /* old st_uid */ |
| 12 | unsigned short st_reserved2; /* old st_gid */ | 12 | unsigned short st_reserved2; /* old st_gid */ |
| 13 | unsigned int st_rdev; | 13 | unsigned int st_rdev; |
| @@ -42,7 +42,7 @@ struct hpux_stat64 { | |||
| 42 | unsigned int st_dev; /* dev_t is 32 bits on parisc */ | 42 | unsigned int st_dev; /* dev_t is 32 bits on parisc */ |
| 43 | ino_t st_ino; /* 32 bits */ | 43 | ino_t st_ino; /* 32 bits */ |
| 44 | mode_t st_mode; /* 16 bits */ | 44 | mode_t st_mode; /* 16 bits */ |
| 45 | nlink_t st_nlink; /* 16 bits */ | 45 | unsigned short st_nlink; /* 16 bits */ |
| 46 | unsigned short st_reserved1; /* old st_uid */ | 46 | unsigned short st_reserved1; /* old st_uid */ |
| 47 | unsigned short st_reserved2; /* old st_gid */ | 47 | unsigned short st_reserved2; /* old st_gid */ |
| 48 | unsigned int st_rdev; | 48 | unsigned int st_rdev; |
diff --git a/arch/powerpc/include/asm/posix_types.h b/arch/powerpc/include/asm/posix_types.h index f1393252bbda..2958c5b97b2d 100644 --- a/arch/powerpc/include/asm/posix_types.h +++ b/arch/powerpc/include/asm/posix_types.h | |||
| @@ -16,9 +16,6 @@ typedef int __kernel_ssize_t; | |||
| 16 | typedef long __kernel_ptrdiff_t; | 16 | typedef long __kernel_ptrdiff_t; |
| 17 | #define __kernel_size_t __kernel_size_t | 17 | #define __kernel_size_t __kernel_size_t |
| 18 | 18 | ||
| 19 | typedef unsigned short __kernel_nlink_t; | ||
| 20 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 21 | |||
| 22 | typedef short __kernel_ipc_pid_t; | 19 | typedef short __kernel_ipc_pid_t; |
| 23 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 20 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 24 | #endif | 21 | #endif |
diff --git a/arch/powerpc/include/asm/stat.h b/arch/powerpc/include/asm/stat.h index e4edc510b530..10cfb558e0fd 100644 --- a/arch/powerpc/include/asm/stat.h +++ b/arch/powerpc/include/asm/stat.h | |||
| @@ -30,11 +30,11 @@ struct stat { | |||
| 30 | unsigned long st_dev; | 30 | unsigned long st_dev; |
| 31 | ino_t st_ino; | 31 | ino_t st_ino; |
| 32 | #ifdef __powerpc64__ | 32 | #ifdef __powerpc64__ |
| 33 | nlink_t st_nlink; | 33 | unsigned short st_nlink; |
| 34 | mode_t st_mode; | 34 | mode_t st_mode; |
| 35 | #else | 35 | #else |
| 36 | mode_t st_mode; | 36 | mode_t st_mode; |
| 37 | nlink_t st_nlink; | 37 | unsigned short st_nlink; |
| 38 | #endif | 38 | #endif |
| 39 | uid_t st_uid; | 39 | uid_t st_uid; |
| 40 | gid_t st_gid; | 40 | gid_t st_gid; |
diff --git a/arch/s390/include/asm/posix_types.h b/arch/s390/include/asm/posix_types.h index edf8527ff08d..7be104c0f192 100644 --- a/arch/s390/include/asm/posix_types.h +++ b/arch/s390/include/asm/posix_types.h | |||
| @@ -24,7 +24,6 @@ typedef unsigned short __kernel_old_dev_t; | |||
| 24 | 24 | ||
| 25 | typedef unsigned long __kernel_ino_t; | 25 | typedef unsigned long __kernel_ino_t; |
| 26 | typedef unsigned short __kernel_mode_t; | 26 | typedef unsigned short __kernel_mode_t; |
| 27 | typedef unsigned short __kernel_nlink_t; | ||
| 28 | typedef unsigned short __kernel_ipc_pid_t; | 27 | typedef unsigned short __kernel_ipc_pid_t; |
| 29 | typedef unsigned short __kernel_uid_t; | 28 | typedef unsigned short __kernel_uid_t; |
| 30 | typedef unsigned short __kernel_gid_t; | 29 | typedef unsigned short __kernel_gid_t; |
| @@ -35,7 +34,6 @@ typedef int __kernel_ptrdiff_t; | |||
| 35 | 34 | ||
| 36 | typedef unsigned int __kernel_ino_t; | 35 | typedef unsigned int __kernel_ino_t; |
| 37 | typedef unsigned int __kernel_mode_t; | 36 | typedef unsigned int __kernel_mode_t; |
| 38 | typedef unsigned int __kernel_nlink_t; | ||
| 39 | typedef int __kernel_ipc_pid_t; | 37 | typedef int __kernel_ipc_pid_t; |
| 40 | typedef unsigned int __kernel_uid_t; | 38 | typedef unsigned int __kernel_uid_t; |
| 41 | typedef unsigned int __kernel_gid_t; | 39 | typedef unsigned int __kernel_gid_t; |
| @@ -47,7 +45,6 @@ typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ | |||
| 47 | 45 | ||
| 48 | #define __kernel_ino_t __kernel_ino_t | 46 | #define __kernel_ino_t __kernel_ino_t |
| 49 | #define __kernel_mode_t __kernel_mode_t | 47 | #define __kernel_mode_t __kernel_mode_t |
| 50 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 51 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 48 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 52 | #define __kernel_uid_t __kernel_uid_t | 49 | #define __kernel_uid_t __kernel_uid_t |
| 53 | #define __kernel_gid_t __kernel_gid_t | 50 | #define __kernel_gid_t __kernel_gid_t |
diff --git a/arch/sh/include/asm/posix_types_32.h b/arch/sh/include/asm/posix_types_32.h index abda58467ece..ba0bdc423b07 100644 --- a/arch/sh/include/asm/posix_types_32.h +++ b/arch/sh/include/asm/posix_types_32.h | |||
| @@ -3,8 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | typedef unsigned short __kernel_mode_t; | 4 | typedef unsigned short __kernel_mode_t; |
| 5 | #define __kernel_mode_t __kernel_mode_t | 5 | #define __kernel_mode_t __kernel_mode_t |
| 6 | typedef unsigned short __kernel_nlink_t; | ||
| 7 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 8 | typedef unsigned short __kernel_ipc_pid_t; | 6 | typedef unsigned short __kernel_ipc_pid_t; |
| 9 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 7 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 10 | typedef unsigned short __kernel_uid_t; | 8 | typedef unsigned short __kernel_uid_t; |
diff --git a/arch/sh/include/asm/posix_types_64.h b/arch/sh/include/asm/posix_types_64.h index fcda07b4a616..244f7e950e17 100644 --- a/arch/sh/include/asm/posix_types_64.h +++ b/arch/sh/include/asm/posix_types_64.h | |||
| @@ -3,8 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | typedef unsigned short __kernel_mode_t; | 4 | typedef unsigned short __kernel_mode_t; |
| 5 | #define __kernel_mode_t __kernel_mode_t | 5 | #define __kernel_mode_t __kernel_mode_t |
| 6 | typedef unsigned short __kernel_nlink_t; | ||
| 7 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 8 | typedef unsigned short __kernel_ipc_pid_t; | 6 | typedef unsigned short __kernel_ipc_pid_t; |
| 9 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 7 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 10 | typedef unsigned short __kernel_uid_t; | 8 | typedef unsigned short __kernel_uid_t; |
diff --git a/arch/sparc/include/asm/posix_types.h b/arch/sparc/include/asm/posix_types.h index 3070f25ae90a..156220ed99eb 100644 --- a/arch/sparc/include/asm/posix_types.h +++ b/arch/sparc/include/asm/posix_types.h | |||
| @@ -9,8 +9,6 @@ | |||
| 9 | 9 | ||
| 10 | #if defined(__sparc__) && defined(__arch64__) | 10 | #if defined(__sparc__) && defined(__arch64__) |
| 11 | /* sparc 64 bit */ | 11 | /* sparc 64 bit */ |
| 12 | typedef unsigned int __kernel_nlink_t; | ||
| 13 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 14 | 12 | ||
| 15 | typedef unsigned short __kernel_old_uid_t; | 13 | typedef unsigned short __kernel_old_uid_t; |
| 16 | typedef unsigned short __kernel_old_gid_t; | 14 | typedef unsigned short __kernel_old_gid_t; |
| @@ -38,9 +36,6 @@ typedef unsigned short __kernel_gid_t; | |||
| 38 | typedef unsigned short __kernel_mode_t; | 36 | typedef unsigned short __kernel_mode_t; |
| 39 | #define __kernel_mode_t __kernel_mode_t | 37 | #define __kernel_mode_t __kernel_mode_t |
| 40 | 38 | ||
| 41 | typedef short __kernel_nlink_t; | ||
| 42 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 43 | |||
| 44 | typedef long __kernel_daddr_t; | 39 | typedef long __kernel_daddr_t; |
| 45 | #define __kernel_daddr_t __kernel_daddr_t | 40 | #define __kernel_daddr_t __kernel_daddr_t |
| 46 | 41 | ||
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 3ee51f189a55..275f74fd6f6a 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
| @@ -580,16 +580,9 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, | |||
| 580 | unsigned long, new_len, unsigned long, flags, | 580 | unsigned long, new_len, unsigned long, flags, |
| 581 | unsigned long, new_addr) | 581 | unsigned long, new_addr) |
| 582 | { | 582 | { |
| 583 | unsigned long ret = -EINVAL; | ||
| 584 | |||
| 585 | if (test_thread_flag(TIF_32BIT)) | 583 | if (test_thread_flag(TIF_32BIT)) |
| 586 | goto out; | 584 | return -EINVAL; |
| 587 | 585 | return sys_mremap(addr, old_len, new_len, flags, new_addr); | |
| 588 | down_write(¤t->mm->mmap_sem); | ||
| 589 | ret = do_mremap(addr, old_len, new_len, flags, new_addr); | ||
| 590 | up_write(¤t->mm->mmap_sem); | ||
| 591 | out: | ||
| 592 | return ret; | ||
| 593 | } | 586 | } |
| 594 | 587 | ||
| 595 | /* we come to here via sys_nis_syscall so it can setup the regs argument */ | 588 | /* we come to here via sys_nis_syscall so it can setup the regs argument */ |
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 69adc08d36a5..6e74450ff0a1 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h | |||
| @@ -44,7 +44,6 @@ typedef __kernel_uid32_t __compat_gid32_t; | |||
| 44 | typedef __kernel_mode_t compat_mode_t; | 44 | typedef __kernel_mode_t compat_mode_t; |
| 45 | typedef __kernel_dev_t compat_dev_t; | 45 | typedef __kernel_dev_t compat_dev_t; |
| 46 | typedef __kernel_loff_t compat_loff_t; | 46 | typedef __kernel_loff_t compat_loff_t; |
| 47 | typedef __kernel_nlink_t compat_nlink_t; | ||
| 48 | typedef __kernel_ipc_pid_t compat_ipc_pid_t; | 47 | typedef __kernel_ipc_pid_t compat_ipc_pid_t; |
| 49 | typedef __kernel_daddr_t compat_daddr_t; | 48 | typedef __kernel_daddr_t compat_daddr_t; |
| 50 | typedef __kernel_fsid_t compat_fsid_t; | 49 | typedef __kernel_fsid_t compat_fsid_t; |
diff --git a/arch/x86/include/asm/posix_types_32.h b/arch/x86/include/asm/posix_types_32.h index 99f262e04b91..8e525059e7d8 100644 --- a/arch/x86/include/asm/posix_types_32.h +++ b/arch/x86/include/asm/posix_types_32.h | |||
| @@ -10,9 +10,6 @@ | |||
| 10 | typedef unsigned short __kernel_mode_t; | 10 | typedef unsigned short __kernel_mode_t; |
| 11 | #define __kernel_mode_t __kernel_mode_t | 11 | #define __kernel_mode_t __kernel_mode_t |
| 12 | 12 | ||
| 13 | typedef unsigned short __kernel_nlink_t; | ||
| 14 | #define __kernel_nlink_t __kernel_nlink_t | ||
| 15 | |||
| 16 | typedef unsigned short __kernel_ipc_pid_t; | 13 | typedef unsigned short __kernel_ipc_pid_t; |
| 17 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t | 14 | #define __kernel_ipc_pid_t __kernel_ipc_pid_t |
| 18 | 15 | ||
diff --git a/drivers/base/soc.c b/drivers/base/soc.c index ba29b2e73d48..72b5e7280d14 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c | |||
| @@ -42,7 +42,7 @@ struct device *soc_device_to_device(struct soc_device *soc_dev) | |||
| 42 | return &soc_dev->dev; | 42 | return &soc_dev->dev; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static mode_t soc_attribute_mode(struct kobject *kobj, | 45 | static umode_t soc_attribute_mode(struct kobject *kobj, |
| 46 | struct attribute *attr, | 46 | struct attribute *attr, |
| 47 | int index) | 47 | int index) |
| 48 | { | 48 | { |
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index f920fb5e42b6..fa9439159ebd 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c | |||
| @@ -130,11 +130,10 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) | |||
| 130 | return -EINVAL; | 130 | return -EINVAL; |
| 131 | 131 | ||
| 132 | /* This is all entirely broken */ | 132 | /* This is all entirely broken */ |
| 133 | down_write(¤t->mm->mmap_sem); | ||
| 134 | old_fops = file_priv->filp->f_op; | 133 | old_fops = file_priv->filp->f_op; |
| 135 | file_priv->filp->f_op = &i810_buffer_fops; | 134 | file_priv->filp->f_op = &i810_buffer_fops; |
| 136 | dev_priv->mmap_buffer = buf; | 135 | dev_priv->mmap_buffer = buf; |
| 137 | buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total, | 136 | buf_priv->virtual = (void *)vm_mmap(file_priv->filp, 0, buf->total, |
| 138 | PROT_READ | PROT_WRITE, | 137 | PROT_READ | PROT_WRITE, |
| 139 | MAP_SHARED, buf->bus_address); | 138 | MAP_SHARED, buf->bus_address); |
| 140 | dev_priv->mmap_buffer = NULL; | 139 | dev_priv->mmap_buffer = NULL; |
| @@ -145,7 +144,6 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) | |||
| 145 | retcode = PTR_ERR(buf_priv->virtual); | 144 | retcode = PTR_ERR(buf_priv->virtual); |
| 146 | buf_priv->virtual = NULL; | 145 | buf_priv->virtual = NULL; |
| 147 | } | 146 | } |
| 148 | up_write(¤t->mm->mmap_sem); | ||
| 149 | 147 | ||
| 150 | return retcode; | 148 | return retcode; |
| 151 | } | 149 | } |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index a1e6c990cd41..e3dd2a1e2bfc 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
| @@ -68,24 +68,6 @@ static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) | |||
| 68 | return current_fsgid(); | 68 | return current_fsgid(); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /** | ||
| 72 | * v9fs_dentry_from_dir_inode - helper function to get the dentry from | ||
| 73 | * dir inode. | ||
| 74 | * | ||
| 75 | */ | ||
| 76 | |||
| 77 | static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) | ||
| 78 | { | ||
| 79 | struct dentry *dentry; | ||
| 80 | |||
| 81 | spin_lock(&inode->i_lock); | ||
| 82 | /* Directory should have only one entry. */ | ||
| 83 | BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); | ||
| 84 | dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); | ||
| 85 | spin_unlock(&inode->i_lock); | ||
| 86 | return dentry; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int v9fs_test_inode_dotl(struct inode *inode, void *data) | 71 | static int v9fs_test_inode_dotl(struct inode *inode, void *data) |
| 90 | { | 72 | { |
| 91 | struct v9fs_inode *v9inode = V9FS_I(inode); | 73 | struct v9fs_inode *v9inode = V9FS_I(inode); |
| @@ -415,7 +397,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, | |||
| 415 | if (dir->i_mode & S_ISGID) | 397 | if (dir->i_mode & S_ISGID) |
| 416 | omode |= S_ISGID; | 398 | omode |= S_ISGID; |
| 417 | 399 | ||
| 418 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | 400 | dir_dentry = dentry->d_parent; |
| 419 | dfid = v9fs_fid_lookup(dir_dentry); | 401 | dfid = v9fs_fid_lookup(dir_dentry); |
| 420 | if (IS_ERR(dfid)) { | 402 | if (IS_ERR(dfid)) { |
| 421 | err = PTR_ERR(dfid); | 403 | err = PTR_ERR(dfid); |
| @@ -793,7 +775,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, | |||
| 793 | dir->i_ino, old_dentry->d_name.name, dentry->d_name.name); | 775 | dir->i_ino, old_dentry->d_name.name, dentry->d_name.name); |
| 794 | 776 | ||
| 795 | v9ses = v9fs_inode2v9ses(dir); | 777 | v9ses = v9fs_inode2v9ses(dir); |
| 796 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | 778 | dir_dentry = dentry->d_parent; |
| 797 | dfid = v9fs_fid_lookup(dir_dentry); | 779 | dfid = v9fs_fid_lookup(dir_dentry); |
| 798 | if (IS_ERR(dfid)) | 780 | if (IS_ERR(dfid)) |
| 799 | return PTR_ERR(dfid); | 781 | return PTR_ERR(dfid); |
| @@ -858,7 +840,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
| 858 | return -EINVAL; | 840 | return -EINVAL; |
| 859 | 841 | ||
| 860 | v9ses = v9fs_inode2v9ses(dir); | 842 | v9ses = v9fs_inode2v9ses(dir); |
| 861 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | 843 | dir_dentry = dentry->d_parent; |
| 862 | dfid = v9fs_fid_lookup(dir_dentry); | 844 | dfid = v9fs_fid_lookup(dir_dentry); |
| 863 | if (IS_ERR(dfid)) { | 845 | if (IS_ERR(dfid)) { |
| 864 | err = PTR_ERR(dfid); | 846 | err = PTR_ERR(dfid); |
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 45a0ce45d7b4..1fceb320d2f2 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
| @@ -18,14 +18,6 @@ | |||
| 18 | #define AFFS_GET_HASHENTRY(data,hashkey) be32_to_cpu(((struct dir_front *)data)->hashtable[hashkey]) | 18 | #define AFFS_GET_HASHENTRY(data,hashkey) be32_to_cpu(((struct dir_front *)data)->hashtable[hashkey]) |
| 19 | #define AFFS_BLOCK(sb, bh, blk) (AFFS_HEAD(bh)->table[AFFS_SB(sb)->s_hashsize-1-(blk)]) | 19 | #define AFFS_BLOCK(sb, bh, blk) (AFFS_HEAD(bh)->table[AFFS_SB(sb)->s_hashsize-1-(blk)]) |
| 20 | 20 | ||
| 21 | #ifdef __LITTLE_ENDIAN | ||
| 22 | #define BO_EXBITS 0x18UL | ||
| 23 | #elif defined(__BIG_ENDIAN) | ||
| 24 | #define BO_EXBITS 0x00UL | ||
| 25 | #else | ||
| 26 | #error Endianness must be known for affs to work. | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #define AFFS_HEAD(bh) ((struct affs_head *)(bh)->b_data) | 21 | #define AFFS_HEAD(bh) ((struct affs_head *)(bh)->b_data) |
| 30 | #define AFFS_TAIL(sb, bh) ((struct affs_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_tail))) | 22 | #define AFFS_TAIL(sb, bh) ((struct affs_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_tail))) |
| 31 | #define AFFS_ROOT_HEAD(bh) ((struct affs_root_head *)(bh)->b_data) | 23 | #define AFFS_ROOT_HEAD(bh) ((struct affs_root_head *)(bh)->b_data) |
| @@ -134,9 +134,9 @@ static int aio_setup_ring(struct kioctx *ctx) | |||
| 134 | info->mmap_size = nr_pages * PAGE_SIZE; | 134 | info->mmap_size = nr_pages * PAGE_SIZE; |
| 135 | dprintk("attempting mmap of %lu bytes\n", info->mmap_size); | 135 | dprintk("attempting mmap of %lu bytes\n", info->mmap_size); |
| 136 | down_write(&ctx->mm->mmap_sem); | 136 | down_write(&ctx->mm->mmap_sem); |
| 137 | info->mmap_base = do_mmap(NULL, 0, info->mmap_size, | 137 | info->mmap_base = do_mmap_pgoff(NULL, 0, info->mmap_size, |
| 138 | PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, | 138 | PROT_READ|PROT_WRITE, |
| 139 | 0); | 139 | MAP_ANONYMOUS|MAP_PRIVATE, 0); |
| 140 | if (IS_ERR((void *)info->mmap_base)) { | 140 | if (IS_ERR((void *)info->mmap_base)) { |
| 141 | up_write(&ctx->mm->mmap_sem); | 141 | up_write(&ctx->mm->mmap_sem); |
| 142 | info->mmap_size = 0; | 142 | info->mmap_size = 0; |
| @@ -176,6 +176,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr) | |||
| 176 | return -EPERM; | 176 | return -EPERM; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) { | ||
| 180 | if (attr->ia_size != inode->i_size) | ||
| 181 | inode_inc_iversion(inode); | ||
| 182 | } | ||
| 183 | |||
| 179 | if ((ia_valid & ATTR_MODE)) { | 184 | if ((ia_valid & ATTR_MODE)) { |
| 180 | umode_t amode = attr->ia_mode; | 185 | umode_t amode = attr->ia_mode; |
| 181 | /* Flag setting protected by i_mutex */ | 186 | /* Flag setting protected by i_mutex */ |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e658dd134b95..1b52956afe33 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -329,7 +329,6 @@ static unsigned long elf_map(struct file *filep, unsigned long addr, | |||
| 329 | if (!size) | 329 | if (!size) |
| 330 | return addr; | 330 | return addr; |
| 331 | 331 | ||
| 332 | down_write(¤t->mm->mmap_sem); | ||
| 333 | /* | 332 | /* |
| 334 | * total_size is the size of the ELF (interpreter) image. | 333 | * total_size is the size of the ELF (interpreter) image. |
| 335 | * The _first_ mmap needs to know the full size, otherwise | 334 | * The _first_ mmap needs to know the full size, otherwise |
| @@ -340,13 +339,12 @@ static unsigned long elf_map(struct file *filep, unsigned long addr, | |||
| 340 | */ | 339 | */ |
| 341 | if (total_size) { | 340 | if (total_size) { |
| 342 | total_size = ELF_PAGEALIGN(total_size); | 341 | total_size = ELF_PAGEALIGN(total_size); |
| 343 | map_addr = do_mmap(filep, addr, total_size, prot, type, off); | 342 | map_addr = vm_mmap(filep, addr, total_size, prot, type, off); |
| 344 | if (!BAD_ADDR(map_addr)) | 343 | if (!BAD_ADDR(map_addr)) |
| 345 | do_munmap(current->mm, map_addr+size, total_size-size); | 344 | vm_munmap(map_addr+size, total_size-size); |
| 346 | } else | 345 | } else |
| 347 | map_addr = do_mmap(filep, addr, size, prot, type, off); | 346 | map_addr = vm_mmap(filep, addr, size, prot, type, off); |
| 348 | 347 | ||
| 349 | up_write(¤t->mm->mmap_sem); | ||
| 350 | return(map_addr); | 348 | return(map_addr); |
| 351 | } | 349 | } |
| 352 | 350 | ||
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 6b2daf99fab8..178cb70acc26 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
| @@ -562,7 +562,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 562 | realdatastart = (unsigned long) -ENOMEM; | 562 | realdatastart = (unsigned long) -ENOMEM; |
| 563 | printk("Unable to allocate RAM for process data, errno %d\n", | 563 | printk("Unable to allocate RAM for process data, errno %d\n", |
| 564 | (int)-realdatastart); | 564 | (int)-realdatastart); |
| 565 | do_munmap(current->mm, textpos, text_len); | 565 | vm_munmap(textpos, text_len); |
| 566 | ret = realdatastart; | 566 | ret = realdatastart; |
| 567 | goto err; | 567 | goto err; |
| 568 | } | 568 | } |
| @@ -586,8 +586,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 586 | } | 586 | } |
| 587 | if (IS_ERR_VALUE(result)) { | 587 | if (IS_ERR_VALUE(result)) { |
| 588 | printk("Unable to read data+bss, errno %d\n", (int)-result); | 588 | printk("Unable to read data+bss, errno %d\n", (int)-result); |
| 589 | do_munmap(current->mm, textpos, text_len); | 589 | vm_munmap(textpos, text_len); |
| 590 | do_munmap(current->mm, realdatastart, len); | 590 | vm_munmap(realdatastart, len); |
| 591 | ret = result; | 591 | ret = result; |
| 592 | goto err; | 592 | goto err; |
| 593 | } | 593 | } |
| @@ -654,7 +654,7 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
| 654 | } | 654 | } |
| 655 | if (IS_ERR_VALUE(result)) { | 655 | if (IS_ERR_VALUE(result)) { |
| 656 | printk("Unable to read code+data+bss, errno %d\n",(int)-result); | 656 | printk("Unable to read code+data+bss, errno %d\n",(int)-result); |
| 657 | do_munmap(current->mm, textpos, text_len + data_len + extra + | 657 | vm_munmap(textpos, text_len + data_len + extra + |
| 658 | MAX_SHARED_LIBS * sizeof(unsigned long)); | 658 | MAX_SHARED_LIBS * sizeof(unsigned long)); |
| 659 | ret = result; | 659 | ret = result; |
| 660 | goto err; | 660 | goto err; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 0151ca1ac657..0236d03c6732 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -2974,7 +2974,6 @@ int btrfs_readpage(struct file *file, struct page *page); | |||
| 2974 | void btrfs_evict_inode(struct inode *inode); | 2974 | void btrfs_evict_inode(struct inode *inode); |
| 2975 | int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); | 2975 | int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); |
| 2976 | int btrfs_dirty_inode(struct inode *inode); | 2976 | int btrfs_dirty_inode(struct inode *inode); |
| 2977 | int btrfs_update_time(struct file *file); | ||
| 2978 | struct inode *btrfs_alloc_inode(struct super_block *sb); | 2977 | struct inode *btrfs_alloc_inode(struct super_block *sb); |
| 2979 | void btrfs_destroy_inode(struct inode *inode); | 2978 | void btrfs_destroy_inode(struct inode *inode); |
| 2980 | int btrfs_drop_inode(struct inode *inode); | 2979 | int btrfs_drop_inode(struct inode *inode); |
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index e887ee62b6d4..614f34a899c2 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c | |||
| @@ -13,15 +13,14 @@ | |||
| 13 | parent_root_objectid) / 4) | 13 | parent_root_objectid) / 4) |
| 14 | #define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 4) | 14 | #define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 4) |
| 15 | 15 | ||
| 16 | static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | 16 | static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len, |
| 17 | int connectable) | 17 | struct inode *parent) |
| 18 | { | 18 | { |
| 19 | struct btrfs_fid *fid = (struct btrfs_fid *)fh; | 19 | struct btrfs_fid *fid = (struct btrfs_fid *)fh; |
| 20 | struct inode *inode = dentry->d_inode; | ||
| 21 | int len = *max_len; | 20 | int len = *max_len; |
| 22 | int type; | 21 | int type; |
| 23 | 22 | ||
| 24 | if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) { | 23 | if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) { |
| 25 | *max_len = BTRFS_FID_SIZE_CONNECTABLE; | 24 | *max_len = BTRFS_FID_SIZE_CONNECTABLE; |
| 26 | return 255; | 25 | return 255; |
| 27 | } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) { | 26 | } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) { |
| @@ -36,19 +35,13 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | |||
| 36 | fid->root_objectid = BTRFS_I(inode)->root->objectid; | 35 | fid->root_objectid = BTRFS_I(inode)->root->objectid; |
| 37 | fid->gen = inode->i_generation; | 36 | fid->gen = inode->i_generation; |
| 38 | 37 | ||
| 39 | if (connectable && !S_ISDIR(inode->i_mode)) { | 38 | if (parent) { |
| 40 | struct inode *parent; | ||
| 41 | u64 parent_root_id; | 39 | u64 parent_root_id; |
| 42 | 40 | ||
| 43 | spin_lock(&dentry->d_lock); | ||
| 44 | |||
| 45 | parent = dentry->d_parent->d_inode; | ||
| 46 | fid->parent_objectid = BTRFS_I(parent)->location.objectid; | 41 | fid->parent_objectid = BTRFS_I(parent)->location.objectid; |
| 47 | fid->parent_gen = parent->i_generation; | 42 | fid->parent_gen = parent->i_generation; |
| 48 | parent_root_id = BTRFS_I(parent)->root->objectid; | 43 | parent_root_id = BTRFS_I(parent)->root->objectid; |
| 49 | 44 | ||
| 50 | spin_unlock(&dentry->d_lock); | ||
| 51 | |||
| 52 | if (parent_root_id != fid->root_objectid) { | 45 | if (parent_root_id != fid->root_objectid) { |
| 53 | fid->parent_root_objectid = parent_root_id; | 46 | fid->parent_root_objectid = parent_root_id; |
| 54 | len = BTRFS_FID_SIZE_CONNECTABLE_ROOT; | 47 | len = BTRFS_FID_SIZE_CONNECTABLE_ROOT; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 876cddd6b2f0..70dc8ca73e25 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1433,7 +1433,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1433 | goto out; | 1433 | goto out; |
| 1434 | } | 1434 | } |
| 1435 | 1435 | ||
| 1436 | err = btrfs_update_time(file); | 1436 | err = file_update_time(file); |
| 1437 | if (err) { | 1437 | if (err) { |
| 1438 | mutex_unlock(&inode->i_mutex); | 1438 | mutex_unlock(&inode->i_mutex); |
| 1439 | goto out; | 1439 | goto out; |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 19a0d85b451c..81296c57405a 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -77,7 +77,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root, | |||
| 77 | return ERR_PTR(-ENOENT); | 77 | return ERR_PTR(-ENOENT); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | inode->i_mapping->flags &= ~__GFP_FS; | 80 | mapping_set_gfp_mask(inode->i_mapping, |
| 81 | mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); | ||
| 81 | 82 | ||
| 82 | return inode; | 83 | return inode; |
| 83 | } | 84 | } |
| @@ -367,7 +368,7 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode, | |||
| 367 | 368 | ||
| 368 | static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation) | 369 | static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation) |
| 369 | { | 370 | { |
| 370 | u64 *val; | 371 | __le64 *val; |
| 371 | 372 | ||
| 372 | io_ctl_map_page(io_ctl, 1); | 373 | io_ctl_map_page(io_ctl, 1); |
| 373 | 374 | ||
| @@ -390,7 +391,7 @@ static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation) | |||
| 390 | 391 | ||
| 391 | static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation) | 392 | static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation) |
| 392 | { | 393 | { |
| 393 | u64 *gen; | 394 | __le64 *gen; |
| 394 | 395 | ||
| 395 | /* | 396 | /* |
| 396 | * Skip the crc area. If we don't check crcs then we just have a 64bit | 397 | * Skip the crc area. If we don't check crcs then we just have a 64bit |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e9991adc0960..f6ab6f5e635a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -4475,46 +4475,18 @@ int btrfs_dirty_inode(struct inode *inode) | |||
| 4475 | * This is a copy of file_update_time. We need this so we can return error on | 4475 | * This is a copy of file_update_time. We need this so we can return error on |
| 4476 | * ENOSPC for updating the inode in the case of file write and mmap writes. | 4476 | * ENOSPC for updating the inode in the case of file write and mmap writes. |
| 4477 | */ | 4477 | */ |
| 4478 | int btrfs_update_time(struct file *file) | 4478 | static int btrfs_update_time(struct inode *inode, struct timespec *now, |
| 4479 | int flags) | ||
| 4479 | { | 4480 | { |
| 4480 | struct inode *inode = file->f_path.dentry->d_inode; | 4481 | if (flags & S_VERSION) |
| 4481 | struct timespec now; | ||
| 4482 | int ret; | ||
| 4483 | enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; | ||
| 4484 | |||
| 4485 | /* First try to exhaust all avenues to not sync */ | ||
| 4486 | if (IS_NOCMTIME(inode)) | ||
| 4487 | return 0; | ||
| 4488 | |||
| 4489 | now = current_fs_time(inode->i_sb); | ||
| 4490 | if (!timespec_equal(&inode->i_mtime, &now)) | ||
| 4491 | sync_it = S_MTIME; | ||
| 4492 | |||
| 4493 | if (!timespec_equal(&inode->i_ctime, &now)) | ||
| 4494 | sync_it |= S_CTIME; | ||
| 4495 | |||
| 4496 | if (IS_I_VERSION(inode)) | ||
| 4497 | sync_it |= S_VERSION; | ||
| 4498 | |||
| 4499 | if (!sync_it) | ||
| 4500 | return 0; | ||
| 4501 | |||
| 4502 | /* Finally allowed to write? Takes lock. */ | ||
| 4503 | if (mnt_want_write_file(file)) | ||
| 4504 | return 0; | ||
| 4505 | |||
| 4506 | /* Only change inode inside the lock region */ | ||
| 4507 | if (sync_it & S_VERSION) | ||
| 4508 | inode_inc_iversion(inode); | 4482 | inode_inc_iversion(inode); |
| 4509 | if (sync_it & S_CTIME) | 4483 | if (flags & S_CTIME) |
| 4510 | inode->i_ctime = now; | 4484 | inode->i_ctime = *now; |
| 4511 | if (sync_it & S_MTIME) | 4485 | if (flags & S_MTIME) |
| 4512 | inode->i_mtime = now; | 4486 | inode->i_mtime = *now; |
| 4513 | ret = btrfs_dirty_inode(inode); | 4487 | if (flags & S_ATIME) |
| 4514 | if (!ret) | 4488 | inode->i_atime = *now; |
| 4515 | mark_inode_dirty_sync(inode); | 4489 | return btrfs_dirty_inode(inode); |
| 4516 | mnt_drop_write(file->f_path.mnt); | ||
| 4517 | return ret; | ||
| 4518 | } | 4490 | } |
| 4519 | 4491 | ||
| 4520 | /* | 4492 | /* |
| @@ -6565,7 +6537,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 6565 | 6537 | ||
| 6566 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); | 6538 | ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); |
| 6567 | if (!ret) { | 6539 | if (!ret) { |
| 6568 | ret = btrfs_update_time(vma->vm_file); | 6540 | ret = file_update_time(vma->vm_file); |
| 6569 | reserved = 1; | 6541 | reserved = 1; |
| 6570 | } | 6542 | } |
| 6571 | if (ret) { | 6543 | if (ret) { |
| @@ -7635,6 +7607,7 @@ static const struct inode_operations btrfs_file_inode_operations = { | |||
| 7635 | .permission = btrfs_permission, | 7607 | .permission = btrfs_permission, |
| 7636 | .fiemap = btrfs_fiemap, | 7608 | .fiemap = btrfs_fiemap, |
| 7637 | .get_acl = btrfs_get_acl, | 7609 | .get_acl = btrfs_get_acl, |
| 7610 | .update_time = btrfs_update_time, | ||
| 7638 | }; | 7611 | }; |
| 7639 | static const struct inode_operations btrfs_special_inode_operations = { | 7612 | static const struct inode_operations btrfs_special_inode_operations = { |
| 7640 | .getattr = btrfs_getattr, | 7613 | .getattr = btrfs_getattr, |
| @@ -7645,6 +7618,7 @@ static const struct inode_operations btrfs_special_inode_operations = { | |||
| 7645 | .listxattr = btrfs_listxattr, | 7618 | .listxattr = btrfs_listxattr, |
| 7646 | .removexattr = btrfs_removexattr, | 7619 | .removexattr = btrfs_removexattr, |
| 7647 | .get_acl = btrfs_get_acl, | 7620 | .get_acl = btrfs_get_acl, |
| 7621 | .update_time = btrfs_update_time, | ||
| 7648 | }; | 7622 | }; |
| 7649 | static const struct inode_operations btrfs_symlink_inode_operations = { | 7623 | static const struct inode_operations btrfs_symlink_inode_operations = { |
| 7650 | .readlink = generic_readlink, | 7624 | .readlink = generic_readlink, |
| @@ -7658,6 +7632,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { | |||
| 7658 | .listxattr = btrfs_listxattr, | 7632 | .listxattr = btrfs_listxattr, |
| 7659 | .removexattr = btrfs_removexattr, | 7633 | .removexattr = btrfs_removexattr, |
| 7660 | .get_acl = btrfs_get_acl, | 7634 | .get_acl = btrfs_get_acl, |
| 7635 | .update_time = btrfs_update_time, | ||
| 7661 | }; | 7636 | }; |
| 7662 | 7637 | ||
| 7663 | const struct dentry_operations btrfs_dentry_operations = { | 7638 | const struct dentry_operations btrfs_dentry_operations = { |
diff --git a/fs/buffer.c b/fs/buffer.c index ad5938ca357c..838a9cf246bd 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -3152,7 +3152,7 @@ SYSCALL_DEFINE2(bdflush, int, func, long, data) | |||
| 3152 | /* | 3152 | /* |
| 3153 | * Buffer-head allocation | 3153 | * Buffer-head allocation |
| 3154 | */ | 3154 | */ |
| 3155 | static struct kmem_cache *bh_cachep; | 3155 | static struct kmem_cache *bh_cachep __read_mostly; |
| 3156 | 3156 | ||
| 3157 | /* | 3157 | /* |
| 3158 | * Once the number of bh's in the machine exceeds this level, we start | 3158 | * Once the number of bh's in the machine exceeds this level, we start |
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index fbb2a643ef10..8e1b60e557b6 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c | |||
| @@ -40,38 +40,49 @@ struct ceph_nfs_confh { | |||
| 40 | u32 parent_name_hash; | 40 | u32 parent_name_hash; |
| 41 | } __attribute__ ((packed)); | 41 | } __attribute__ ((packed)); |
| 42 | 42 | ||
| 43 | static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, | 43 | /* |
| 44 | int connectable) | 44 | * The presence of @parent_inode here tells us whether NFS wants a |
| 45 | * connectable file handle. However, we want to make a connectionable | ||
| 46 | * file handle unconditionally so that the MDS gets as much of a hint | ||
| 47 | * as possible. That means we only use @parent_dentry to indicate | ||
| 48 | * whether nfsd wants a connectable fh, and whether we should indicate | ||
| 49 | * failure from a too-small @max_len. | ||
| 50 | */ | ||
| 51 | static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, | ||
| 52 | struct inode *parent_inode) | ||
| 45 | { | 53 | { |
| 46 | int type; | 54 | int type; |
| 47 | struct ceph_nfs_fh *fh = (void *)rawfh; | 55 | struct ceph_nfs_fh *fh = (void *)rawfh; |
| 48 | struct ceph_nfs_confh *cfh = (void *)rawfh; | 56 | struct ceph_nfs_confh *cfh = (void *)rawfh; |
| 49 | struct dentry *parent; | ||
| 50 | struct inode *inode = dentry->d_inode; | ||
| 51 | int connected_handle_length = sizeof(*cfh)/4; | 57 | int connected_handle_length = sizeof(*cfh)/4; |
| 52 | int handle_length = sizeof(*fh)/4; | 58 | int handle_length = sizeof(*fh)/4; |
| 59 | struct dentry *dentry = d_find_alias(inode); | ||
| 60 | struct dentry *parent; | ||
| 53 | 61 | ||
| 54 | /* don't re-export snaps */ | 62 | /* don't re-export snaps */ |
| 55 | if (ceph_snap(inode) != CEPH_NOSNAP) | 63 | if (ceph_snap(inode) != CEPH_NOSNAP) |
| 56 | return -EINVAL; | 64 | return -EINVAL; |
| 57 | 65 | ||
| 58 | spin_lock(&dentry->d_lock); | 66 | /* if we found an alias, generate a connectable fh */ |
| 59 | parent = dentry->d_parent; | 67 | if (*max_len >= connected_handle_length && dentry) { |
| 60 | if (*max_len >= connected_handle_length) { | ||
| 61 | dout("encode_fh %p connectable\n", dentry); | 68 | dout("encode_fh %p connectable\n", dentry); |
| 62 | cfh->ino = ceph_ino(dentry->d_inode); | 69 | spin_lock(&dentry->d_lock); |
| 70 | parent = dentry->d_parent; | ||
| 71 | cfh->ino = ceph_ino(inode); | ||
| 63 | cfh->parent_ino = ceph_ino(parent->d_inode); | 72 | cfh->parent_ino = ceph_ino(parent->d_inode); |
| 64 | cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode, | 73 | cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode, |
| 65 | dentry); | 74 | dentry); |
| 66 | *max_len = connected_handle_length; | 75 | *max_len = connected_handle_length; |
| 67 | type = 2; | 76 | type = 2; |
| 77 | spin_unlock(&dentry->d_lock); | ||
| 68 | } else if (*max_len >= handle_length) { | 78 | } else if (*max_len >= handle_length) { |
| 69 | if (connectable) { | 79 | if (parent_inode) { |
| 80 | /* nfsd wants connectable */ | ||
| 70 | *max_len = connected_handle_length; | 81 | *max_len = connected_handle_length; |
| 71 | type = 255; | 82 | type = 255; |
| 72 | } else { | 83 | } else { |
| 73 | dout("encode_fh %p\n", dentry); | 84 | dout("encode_fh %p\n", dentry); |
| 74 | fh->ino = ceph_ino(dentry->d_inode); | 85 | fh->ino = ceph_ino(inode); |
| 75 | *max_len = handle_length; | 86 | *max_len = handle_length; |
| 76 | type = 1; | 87 | type = 1; |
| 77 | } | 88 | } |
| @@ -79,7 +90,6 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, | |||
| 79 | *max_len = handle_length; | 90 | *max_len = handle_length; |
| 80 | type = 255; | 91 | type = 255; |
| 81 | } | 92 | } |
| 82 | spin_unlock(&dentry->d_lock); | ||
| 83 | return type; | 93 | return type; |
| 84 | } | 94 | } |
| 85 | 95 | ||
diff --git a/fs/compat.c b/fs/compat.c index 6556a9ce8a28..3004d2bad13f 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -871,12 +871,12 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd, | |||
| 871 | { | 871 | { |
| 872 | int error; | 872 | int error; |
| 873 | struct file *file; | 873 | struct file *file; |
| 874 | int fput_needed; | ||
| 874 | struct compat_readdir_callback buf; | 875 | struct compat_readdir_callback buf; |
| 875 | 876 | ||
| 876 | error = -EBADF; | 877 | file = fget_light(fd, &fput_needed); |
| 877 | file = fget(fd); | ||
| 878 | if (!file) | 878 | if (!file) |
| 879 | goto out; | 879 | return -EBADF; |
| 880 | 880 | ||
| 881 | buf.result = 0; | 881 | buf.result = 0; |
| 882 | buf.dirent = dirent; | 882 | buf.dirent = dirent; |
| @@ -885,8 +885,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd, | |||
| 885 | if (buf.result) | 885 | if (buf.result) |
| 886 | error = buf.result; | 886 | error = buf.result; |
| 887 | 887 | ||
| 888 | fput(file); | 888 | fput_light(file, fput_needed); |
| 889 | out: | ||
| 890 | return error; | 889 | return error; |
| 891 | } | 890 | } |
| 892 | 891 | ||
| @@ -953,16 +952,15 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
| 953 | struct file * file; | 952 | struct file * file; |
| 954 | struct compat_linux_dirent __user * lastdirent; | 953 | struct compat_linux_dirent __user * lastdirent; |
| 955 | struct compat_getdents_callback buf; | 954 | struct compat_getdents_callback buf; |
| 955 | int fput_needed; | ||
| 956 | int error; | 956 | int error; |
| 957 | 957 | ||
| 958 | error = -EFAULT; | ||
| 959 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 958 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
| 960 | goto out; | 959 | return -EFAULT; |
| 961 | 960 | ||
| 962 | error = -EBADF; | 961 | file = fget_light(fd, &fput_needed); |
| 963 | file = fget(fd); | ||
| 964 | if (!file) | 962 | if (!file) |
| 965 | goto out; | 963 | return -EBADF; |
| 966 | 964 | ||
| 967 | buf.current_dir = dirent; | 965 | buf.current_dir = dirent; |
| 968 | buf.previous = NULL; | 966 | buf.previous = NULL; |
| @@ -979,8 +977,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd, | |||
| 979 | else | 977 | else |
| 980 | error = count - buf.count; | 978 | error = count - buf.count; |
| 981 | } | 979 | } |
| 982 | fput(file); | 980 | fput_light(file, fput_needed); |
| 983 | out: | ||
| 984 | return error; | 981 | return error; |
| 985 | } | 982 | } |
| 986 | 983 | ||
| @@ -1041,16 +1038,15 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
| 1041 | struct file * file; | 1038 | struct file * file; |
| 1042 | struct linux_dirent64 __user * lastdirent; | 1039 | struct linux_dirent64 __user * lastdirent; |
| 1043 | struct compat_getdents_callback64 buf; | 1040 | struct compat_getdents_callback64 buf; |
| 1041 | int fput_needed; | ||
| 1044 | int error; | 1042 | int error; |
| 1045 | 1043 | ||
| 1046 | error = -EFAULT; | ||
| 1047 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 1044 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
| 1048 | goto out; | 1045 | return -EFAULT; |
| 1049 | 1046 | ||
| 1050 | error = -EBADF; | 1047 | file = fget_light(fd, &fput_needed); |
| 1051 | file = fget(fd); | ||
| 1052 | if (!file) | 1048 | if (!file) |
| 1053 | goto out; | 1049 | return -EBADF; |
| 1054 | 1050 | ||
| 1055 | buf.current_dir = dirent; | 1051 | buf.current_dir = dirent; |
| 1056 | buf.previous = NULL; | 1052 | buf.previous = NULL; |
| @@ -1068,8 +1064,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd, | |||
| 1068 | else | 1064 | else |
| 1069 | error = count - buf.count; | 1065 | error = count - buf.count; |
| 1070 | } | 1066 | } |
| 1071 | fput(file); | 1067 | fput_light(file, fput_needed); |
| 1072 | out: | ||
| 1073 | return error; | 1068 | return error; |
| 1074 | } | 1069 | } |
| 1075 | #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ | 1070 | #endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */ |
diff --git a/fs/dcache.c b/fs/dcache.c index 4435d8b32904..85c9e2bff8e6 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -683,8 +683,6 @@ EXPORT_SYMBOL(dget_parent); | |||
| 683 | /** | 683 | /** |
| 684 | * d_find_alias - grab a hashed alias of inode | 684 | * d_find_alias - grab a hashed alias of inode |
| 685 | * @inode: inode in question | 685 | * @inode: inode in question |
| 686 | * @want_discon: flag, used by d_splice_alias, to request | ||
| 687 | * that only a DISCONNECTED alias be returned. | ||
| 688 | * | 686 | * |
| 689 | * If inode has a hashed alias, or is a directory and has any alias, | 687 | * If inode has a hashed alias, or is a directory and has any alias, |
| 690 | * acquire the reference to alias and return it. Otherwise return NULL. | 688 | * acquire the reference to alias and return it. Otherwise return NULL. |
| @@ -693,10 +691,9 @@ EXPORT_SYMBOL(dget_parent); | |||
| 693 | * of a filesystem. | 691 | * of a filesystem. |
| 694 | * | 692 | * |
| 695 | * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer | 693 | * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer |
| 696 | * any other hashed alias over that one unless @want_discon is set, | 694 | * any other hashed alias over that. |
| 697 | * in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias. | ||
| 698 | */ | 695 | */ |
| 699 | static struct dentry *__d_find_alias(struct inode *inode, int want_discon) | 696 | static struct dentry *__d_find_alias(struct inode *inode) |
| 700 | { | 697 | { |
| 701 | struct dentry *alias, *discon_alias; | 698 | struct dentry *alias, *discon_alias; |
| 702 | 699 | ||
| @@ -708,7 +705,7 @@ again: | |||
| 708 | if (IS_ROOT(alias) && | 705 | if (IS_ROOT(alias) && |
| 709 | (alias->d_flags & DCACHE_DISCONNECTED)) { | 706 | (alias->d_flags & DCACHE_DISCONNECTED)) { |
| 710 | discon_alias = alias; | 707 | discon_alias = alias; |
| 711 | } else if (!want_discon) { | 708 | } else { |
| 712 | __dget_dlock(alias); | 709 | __dget_dlock(alias); |
| 713 | spin_unlock(&alias->d_lock); | 710 | spin_unlock(&alias->d_lock); |
| 714 | return alias; | 711 | return alias; |
| @@ -739,7 +736,7 @@ struct dentry *d_find_alias(struct inode *inode) | |||
| 739 | 736 | ||
| 740 | if (!list_empty(&inode->i_dentry)) { | 737 | if (!list_empty(&inode->i_dentry)) { |
| 741 | spin_lock(&inode->i_lock); | 738 | spin_lock(&inode->i_lock); |
| 742 | de = __d_find_alias(inode, 0); | 739 | de = __d_find_alias(inode); |
| 743 | spin_unlock(&inode->i_lock); | 740 | spin_unlock(&inode->i_lock); |
| 744 | } | 741 | } |
| 745 | return de; | 742 | return de; |
| @@ -1650,9 +1647,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
| 1650 | 1647 | ||
| 1651 | if (inode && S_ISDIR(inode->i_mode)) { | 1648 | if (inode && S_ISDIR(inode->i_mode)) { |
| 1652 | spin_lock(&inode->i_lock); | 1649 | spin_lock(&inode->i_lock); |
| 1653 | new = __d_find_alias(inode, 1); | 1650 | new = __d_find_any_alias(inode); |
| 1654 | if (new) { | 1651 | if (new) { |
| 1655 | BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); | ||
| 1656 | spin_unlock(&inode->i_lock); | 1652 | spin_unlock(&inode->i_lock); |
| 1657 | security_d_instantiate(new, inode); | 1653 | security_d_instantiate(new, inode); |
| 1658 | d_move(new, dentry); | 1654 | d_move(new, dentry); |
| @@ -2482,7 +2478,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
| 2482 | struct dentry *alias; | 2478 | struct dentry *alias; |
| 2483 | 2479 | ||
| 2484 | /* Does an aliased dentry already exist? */ | 2480 | /* Does an aliased dentry already exist? */ |
| 2485 | alias = __d_find_alias(inode, 0); | 2481 | alias = __d_find_alias(inode); |
| 2486 | if (alias) { | 2482 | if (alias) { |
| 2487 | actual = alias; | 2483 | actual = alias; |
| 2488 | write_seqlock(&rename_lock); | 2484 | write_seqlock(&rename_lock); |
| @@ -2575,7 +2571,7 @@ static int prepend_path(const struct path *path, | |||
| 2575 | bool slash = false; | 2571 | bool slash = false; |
| 2576 | int error = 0; | 2572 | int error = 0; |
| 2577 | 2573 | ||
| 2578 | br_read_lock(vfsmount_lock); | 2574 | br_read_lock(&vfsmount_lock); |
| 2579 | while (dentry != root->dentry || vfsmnt != root->mnt) { | 2575 | while (dentry != root->dentry || vfsmnt != root->mnt) { |
| 2580 | struct dentry * parent; | 2576 | struct dentry * parent; |
| 2581 | 2577 | ||
| @@ -2606,7 +2602,7 @@ static int prepend_path(const struct path *path, | |||
| 2606 | error = prepend(buffer, buflen, "/", 1); | 2602 | error = prepend(buffer, buflen, "/", 1); |
| 2607 | 2603 | ||
| 2608 | out: | 2604 | out: |
| 2609 | br_read_unlock(vfsmount_lock); | 2605 | br_read_unlock(&vfsmount_lock); |
| 2610 | return error; | 2606 | return error; |
| 2611 | 2607 | ||
| 2612 | global_root: | 2608 | global_root: |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index ab35b113003b..a07441a0a878 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
| @@ -660,11 +660,10 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, | |||
| 660 | { | 660 | { |
| 661 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | 661 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); |
| 662 | char *lower_buf; | 662 | char *lower_buf; |
| 663 | size_t lower_bufsiz = PATH_MAX; | ||
| 664 | mm_segment_t old_fs; | 663 | mm_segment_t old_fs; |
| 665 | int rc; | 664 | int rc; |
| 666 | 665 | ||
| 667 | lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); | 666 | lower_buf = kmalloc(PATH_MAX, GFP_KERNEL); |
| 668 | if (!lower_buf) { | 667 | if (!lower_buf) { |
| 669 | rc = -ENOMEM; | 668 | rc = -ENOMEM; |
| 670 | goto out; | 669 | goto out; |
| @@ -673,58 +672,29 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf, | |||
| 673 | set_fs(get_ds()); | 672 | set_fs(get_ds()); |
| 674 | rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, | 673 | rc = lower_dentry->d_inode->i_op->readlink(lower_dentry, |
| 675 | (char __user *)lower_buf, | 674 | (char __user *)lower_buf, |
| 676 | lower_bufsiz); | 675 | PATH_MAX); |
| 677 | set_fs(old_fs); | 676 | set_fs(old_fs); |
| 678 | if (rc < 0) | 677 | if (rc < 0) |
| 679 | goto out; | 678 | goto out; |
| 680 | lower_bufsiz = rc; | ||
| 681 | rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry, | 679 | rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry, |
| 682 | lower_buf, lower_bufsiz); | 680 | lower_buf, rc); |
| 683 | out: | 681 | out: |
| 684 | kfree(lower_buf); | 682 | kfree(lower_buf); |
| 685 | return rc; | 683 | return rc; |
| 686 | } | 684 | } |
| 687 | 685 | ||
| 688 | static int | 686 | static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) |
| 689 | ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | ||
| 690 | { | 687 | { |
| 691 | char *kbuf; | 688 | char *buf; |
| 692 | size_t kbufsiz, copied; | 689 | size_t len = PATH_MAX; |
| 693 | int rc; | 690 | int rc; |
| 694 | 691 | ||
| 695 | rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz); | 692 | rc = ecryptfs_readlink_lower(dentry, &buf, &len); |
| 696 | if (rc) | 693 | if (rc) |
| 697 | goto out; | 694 | goto out; |
| 698 | copied = min_t(size_t, bufsiz, kbufsiz); | ||
| 699 | rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied; | ||
| 700 | kfree(kbuf); | ||
| 701 | fsstack_copy_attr_atime(dentry->d_inode, | 695 | fsstack_copy_attr_atime(dentry->d_inode, |
| 702 | ecryptfs_dentry_to_lower(dentry)->d_inode); | 696 | ecryptfs_dentry_to_lower(dentry)->d_inode); |
| 703 | out: | 697 | buf[len] = '\0'; |
| 704 | return rc; | ||
| 705 | } | ||
| 706 | |||
| 707 | static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
| 708 | { | ||
| 709 | char *buf; | ||
| 710 | int len = PAGE_SIZE, rc; | ||
| 711 | mm_segment_t old_fs; | ||
| 712 | |||
| 713 | /* Released in ecryptfs_put_link(); only release here on error */ | ||
| 714 | buf = kmalloc(len, GFP_KERNEL); | ||
| 715 | if (!buf) { | ||
| 716 | buf = ERR_PTR(-ENOMEM); | ||
| 717 | goto out; | ||
| 718 | } | ||
| 719 | old_fs = get_fs(); | ||
| 720 | set_fs(get_ds()); | ||
| 721 | rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len); | ||
| 722 | set_fs(old_fs); | ||
| 723 | if (rc < 0) { | ||
| 724 | kfree(buf); | ||
| 725 | buf = ERR_PTR(rc); | ||
| 726 | } else | ||
| 727 | buf[rc] = '\0'; | ||
| 728 | out: | 698 | out: |
| 729 | nd_set_link(nd, buf); | 699 | nd_set_link(nd, buf); |
| 730 | return NULL; | 700 | return NULL; |
| @@ -1153,7 +1123,7 @@ out: | |||
| 1153 | } | 1123 | } |
| 1154 | 1124 | ||
| 1155 | const struct inode_operations ecryptfs_symlink_iops = { | 1125 | const struct inode_operations ecryptfs_symlink_iops = { |
| 1156 | .readlink = ecryptfs_readlink, | 1126 | .readlink = generic_readlink, |
| 1157 | .follow_link = ecryptfs_follow_link, | 1127 | .follow_link = ecryptfs_follow_link, |
| 1158 | .put_link = ecryptfs_put_link, | 1128 | .put_link = ecryptfs_put_link, |
| 1159 | .permission = ecryptfs_permission, | 1129 | .permission = ecryptfs_permission, |
| @@ -280,10 +280,6 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
| 280 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 280 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
| 281 | INIT_LIST_HEAD(&vma->anon_vma_chain); | 281 | INIT_LIST_HEAD(&vma->anon_vma_chain); |
| 282 | 282 | ||
| 283 | err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); | ||
| 284 | if (err) | ||
| 285 | goto err; | ||
| 286 | |||
| 287 | err = insert_vm_struct(mm, vma); | 283 | err = insert_vm_struct(mm, vma); |
| 288 | if (err) | 284 | if (err) |
| 289 | goto err; | 285 | goto err; |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b05acb796135..b0201ca6e9c6 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
| @@ -304,24 +304,23 @@ out: | |||
| 304 | 304 | ||
| 305 | /** | 305 | /** |
| 306 | * export_encode_fh - default export_operations->encode_fh function | 306 | * export_encode_fh - default export_operations->encode_fh function |
| 307 | * @dentry: the dentry to encode | 307 | * @inode: the object to encode |
| 308 | * @fh: where to store the file handle fragment | 308 | * @fh: where to store the file handle fragment |
| 309 | * @max_len: maximum length to store there | 309 | * @max_len: maximum length to store there |
| 310 | * @connectable: whether to store parent information | 310 | * @parent: parent directory inode, if wanted |
| 311 | * | 311 | * |
| 312 | * This default encode_fh function assumes that the 32 inode number | 312 | * This default encode_fh function assumes that the 32 inode number |
| 313 | * is suitable for locating an inode, and that the generation number | 313 | * is suitable for locating an inode, and that the generation number |
| 314 | * can be used to check that it is still valid. It places them in the | 314 | * can be used to check that it is still valid. It places them in the |
| 315 | * filehandle fragment where export_decode_fh expects to find them. | 315 | * filehandle fragment where export_decode_fh expects to find them. |
| 316 | */ | 316 | */ |
| 317 | static int export_encode_fh(struct dentry *dentry, struct fid *fid, | 317 | static int export_encode_fh(struct inode *inode, struct fid *fid, |
| 318 | int *max_len, int connectable) | 318 | int *max_len, struct inode *parent) |
| 319 | { | 319 | { |
| 320 | struct inode * inode = dentry->d_inode; | ||
| 321 | int len = *max_len; | 320 | int len = *max_len; |
| 322 | int type = FILEID_INO32_GEN; | 321 | int type = FILEID_INO32_GEN; |
| 323 | 322 | ||
| 324 | if (connectable && (len < 4)) { | 323 | if (parent && (len < 4)) { |
| 325 | *max_len = 4; | 324 | *max_len = 4; |
| 326 | return 255; | 325 | return 255; |
| 327 | } else if (len < 2) { | 326 | } else if (len < 2) { |
| @@ -332,14 +331,9 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid, | |||
| 332 | len = 2; | 331 | len = 2; |
| 333 | fid->i32.ino = inode->i_ino; | 332 | fid->i32.ino = inode->i_ino; |
| 334 | fid->i32.gen = inode->i_generation; | 333 | fid->i32.gen = inode->i_generation; |
| 335 | if (connectable && !S_ISDIR(inode->i_mode)) { | 334 | if (parent) { |
| 336 | struct inode *parent; | ||
| 337 | |||
| 338 | spin_lock(&dentry->d_lock); | ||
| 339 | parent = dentry->d_parent->d_inode; | ||
| 340 | fid->i32.parent_ino = parent->i_ino; | 335 | fid->i32.parent_ino = parent->i_ino; |
| 341 | fid->i32.parent_gen = parent->i_generation; | 336 | fid->i32.parent_gen = parent->i_generation; |
| 342 | spin_unlock(&dentry->d_lock); | ||
| 343 | len = 4; | 337 | len = 4; |
| 344 | type = FILEID_INO32_GEN_PARENT; | 338 | type = FILEID_INO32_GEN_PARENT; |
| 345 | } | 339 | } |
| @@ -352,11 +346,22 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, | |||
| 352 | { | 346 | { |
| 353 | const struct export_operations *nop = dentry->d_sb->s_export_op; | 347 | const struct export_operations *nop = dentry->d_sb->s_export_op; |
| 354 | int error; | 348 | int error; |
| 349 | struct dentry *p = NULL; | ||
| 350 | struct inode *inode = dentry->d_inode, *parent = NULL; | ||
| 355 | 351 | ||
| 352 | if (connectable && !S_ISDIR(inode->i_mode)) { | ||
| 353 | p = dget_parent(dentry); | ||
| 354 | /* | ||
| 355 | * note that while p might've ceased to be our parent already, | ||
| 356 | * it's still pinned by and still positive. | ||
| 357 | */ | ||
| 358 | parent = p->d_inode; | ||
| 359 | } | ||
| 356 | if (nop->encode_fh) | 360 | if (nop->encode_fh) |
| 357 | error = nop->encode_fh(dentry, fid->raw, max_len, connectable); | 361 | error = nop->encode_fh(inode, fid->raw, max_len, parent); |
| 358 | else | 362 | else |
| 359 | error = export_encode_fh(dentry, fid, max_len, connectable); | 363 | error = export_encode_fh(inode, fid, max_len, parent); |
| 364 | dput(p); | ||
| 360 | 365 | ||
| 361 | return error; | 366 | return error; |
| 362 | } | 367 | } |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c2973ea5df9a..a3d81ebf6d86 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -735,10 +735,9 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb, | |||
| 735 | } | 735 | } |
| 736 | 736 | ||
| 737 | static int | 737 | static int |
| 738 | fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) | 738 | fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, struct inode *parent) |
| 739 | { | 739 | { |
| 740 | int len = *lenp; | 740 | int len = *lenp; |
| 741 | struct inode *inode = de->d_inode; | ||
| 742 | u32 ipos_h, ipos_m, ipos_l; | 741 | u32 ipos_h, ipos_m, ipos_l; |
| 743 | 742 | ||
| 744 | if (len < 5) { | 743 | if (len < 5) { |
| @@ -754,9 +753,9 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable) | |||
| 754 | fh[1] = inode->i_generation; | 753 | fh[1] = inode->i_generation; |
| 755 | fh[2] = ipos_h; | 754 | fh[2] = ipos_h; |
| 756 | fh[3] = ipos_m | MSDOS_I(inode)->i_logstart; | 755 | fh[3] = ipos_m | MSDOS_I(inode)->i_logstart; |
| 757 | spin_lock(&de->d_lock); | 756 | fh[4] = ipos_l; |
| 758 | fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart; | 757 | if (parent) |
| 759 | spin_unlock(&de->d_lock); | 758 | fh[4] |= MSDOS_I(parent)->i_logstart; |
| 760 | return 3; | 759 | return 3; |
| 761 | } | 760 | } |
| 762 | 761 | ||
diff --git a/fs/fcntl.c b/fs/fcntl.c index d078b75572a7..81b70e665bf0 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
| @@ -442,28 +442,24 @@ static int check_fcntl_cmd(unsigned cmd) | |||
| 442 | SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) | 442 | SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) |
| 443 | { | 443 | { |
| 444 | struct file *filp; | 444 | struct file *filp; |
| 445 | int fput_needed; | ||
| 445 | long err = -EBADF; | 446 | long err = -EBADF; |
| 446 | 447 | ||
| 447 | filp = fget_raw(fd); | 448 | filp = fget_raw_light(fd, &fput_needed); |
| 448 | if (!filp) | 449 | if (!filp) |
| 449 | goto out; | 450 | goto out; |
| 450 | 451 | ||
| 451 | if (unlikely(filp->f_mode & FMODE_PATH)) { | 452 | if (unlikely(filp->f_mode & FMODE_PATH)) { |
| 452 | if (!check_fcntl_cmd(cmd)) { | 453 | if (!check_fcntl_cmd(cmd)) |
| 453 | fput(filp); | 454 | goto out1; |
| 454 | goto out; | ||
| 455 | } | ||
| 456 | } | 455 | } |
| 457 | 456 | ||
| 458 | err = security_file_fcntl(filp, cmd, arg); | 457 | err = security_file_fcntl(filp, cmd, arg); |
| 459 | if (err) { | 458 | if (!err) |
| 460 | fput(filp); | 459 | err = do_fcntl(fd, cmd, arg, filp); |
| 461 | return err; | ||
| 462 | } | ||
| 463 | 460 | ||
| 464 | err = do_fcntl(fd, cmd, arg, filp); | 461 | out1: |
| 465 | 462 | fput_light(filp, fput_needed); | |
| 466 | fput(filp); | ||
| 467 | out: | 463 | out: |
| 468 | return err; | 464 | return err; |
| 469 | } | 465 | } |
| @@ -473,26 +469,21 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
| 473 | unsigned long, arg) | 469 | unsigned long, arg) |
| 474 | { | 470 | { |
| 475 | struct file * filp; | 471 | struct file * filp; |
| 476 | long err; | 472 | long err = -EBADF; |
| 473 | int fput_needed; | ||
| 477 | 474 | ||
| 478 | err = -EBADF; | 475 | filp = fget_raw_light(fd, &fput_needed); |
| 479 | filp = fget_raw(fd); | ||
| 480 | if (!filp) | 476 | if (!filp) |
| 481 | goto out; | 477 | goto out; |
| 482 | 478 | ||
| 483 | if (unlikely(filp->f_mode & FMODE_PATH)) { | 479 | if (unlikely(filp->f_mode & FMODE_PATH)) { |
| 484 | if (!check_fcntl_cmd(cmd)) { | 480 | if (!check_fcntl_cmd(cmd)) |
| 485 | fput(filp); | 481 | goto out1; |
| 486 | goto out; | ||
| 487 | } | ||
| 488 | } | 482 | } |
| 489 | 483 | ||
| 490 | err = security_file_fcntl(filp, cmd, arg); | 484 | err = security_file_fcntl(filp, cmd, arg); |
| 491 | if (err) { | 485 | if (err) |
| 492 | fput(filp); | 486 | goto out1; |
| 493 | return err; | ||
| 494 | } | ||
| 495 | err = -EBADF; | ||
| 496 | 487 | ||
| 497 | switch (cmd) { | 488 | switch (cmd) { |
| 498 | case F_GETLK64: | 489 | case F_GETLK64: |
| @@ -507,7 +498,8 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
| 507 | err = do_fcntl(fd, cmd, arg, filp); | 498 | err = do_fcntl(fd, cmd, arg, filp); |
| 508 | break; | 499 | break; |
| 509 | } | 500 | } |
| 510 | fput(filp); | 501 | out1: |
| 502 | fput_light(filp, fput_needed); | ||
| 511 | out: | 503 | out: |
| 512 | return err; | 504 | return err; |
| 513 | } | 505 | } |
diff --git a/fs/file_table.c b/fs/file_table.c index 70f2a0fd6aec..a305d9e2d1b2 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -34,7 +34,6 @@ struct files_stat_struct files_stat = { | |||
| 34 | .max_files = NR_FILE | 34 | .max_files = NR_FILE |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | DECLARE_LGLOCK(files_lglock); | ||
| 38 | DEFINE_LGLOCK(files_lglock); | 37 | DEFINE_LGLOCK(files_lglock); |
| 39 | 38 | ||
| 40 | /* SLAB cache for file structures */ | 39 | /* SLAB cache for file structures */ |
| @@ -421,9 +420,9 @@ static inline void __file_sb_list_add(struct file *file, struct super_block *sb) | |||
| 421 | */ | 420 | */ |
| 422 | void file_sb_list_add(struct file *file, struct super_block *sb) | 421 | void file_sb_list_add(struct file *file, struct super_block *sb) |
| 423 | { | 422 | { |
| 424 | lg_local_lock(files_lglock); | 423 | lg_local_lock(&files_lglock); |
| 425 | __file_sb_list_add(file, sb); | 424 | __file_sb_list_add(file, sb); |
| 426 | lg_local_unlock(files_lglock); | 425 | lg_local_unlock(&files_lglock); |
| 427 | } | 426 | } |
| 428 | 427 | ||
| 429 | /** | 428 | /** |
| @@ -436,9 +435,9 @@ void file_sb_list_add(struct file *file, struct super_block *sb) | |||
| 436 | void file_sb_list_del(struct file *file) | 435 | void file_sb_list_del(struct file *file) |
| 437 | { | 436 | { |
| 438 | if (!list_empty(&file->f_u.fu_list)) { | 437 | if (!list_empty(&file->f_u.fu_list)) { |
| 439 | lg_local_lock_cpu(files_lglock, file_list_cpu(file)); | 438 | lg_local_lock_cpu(&files_lglock, file_list_cpu(file)); |
| 440 | list_del_init(&file->f_u.fu_list); | 439 | list_del_init(&file->f_u.fu_list); |
| 441 | lg_local_unlock_cpu(files_lglock, file_list_cpu(file)); | 440 | lg_local_unlock_cpu(&files_lglock, file_list_cpu(file)); |
| 442 | } | 441 | } |
| 443 | } | 442 | } |
| 444 | 443 | ||
| @@ -485,7 +484,7 @@ void mark_files_ro(struct super_block *sb) | |||
| 485 | struct file *f; | 484 | struct file *f; |
| 486 | 485 | ||
| 487 | retry: | 486 | retry: |
| 488 | lg_global_lock(files_lglock); | 487 | lg_global_lock(&files_lglock); |
| 489 | do_file_list_for_each_entry(sb, f) { | 488 | do_file_list_for_each_entry(sb, f) { |
| 490 | struct vfsmount *mnt; | 489 | struct vfsmount *mnt; |
| 491 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) | 490 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) |
| @@ -502,12 +501,12 @@ retry: | |||
| 502 | file_release_write(f); | 501 | file_release_write(f); |
| 503 | mnt = mntget(f->f_path.mnt); | 502 | mnt = mntget(f->f_path.mnt); |
| 504 | /* This can sleep, so we can't hold the spinlock. */ | 503 | /* This can sleep, so we can't hold the spinlock. */ |
| 505 | lg_global_unlock(files_lglock); | 504 | lg_global_unlock(&files_lglock); |
| 506 | mnt_drop_write(mnt); | 505 | mnt_drop_write(mnt); |
| 507 | mntput(mnt); | 506 | mntput(mnt); |
| 508 | goto retry; | 507 | goto retry; |
| 509 | } while_file_list_for_each_entry; | 508 | } while_file_list_for_each_entry; |
| 510 | lg_global_unlock(files_lglock); | 509 | lg_global_unlock(&files_lglock); |
| 511 | } | 510 | } |
| 512 | 511 | ||
| 513 | void __init files_init(unsigned long mempages) | 512 | void __init files_init(unsigned long mempages) |
| @@ -525,6 +524,6 @@ void __init files_init(unsigned long mempages) | |||
| 525 | n = (mempages * (PAGE_SIZE / 1024)) / 10; | 524 | n = (mempages * (PAGE_SIZE / 1024)) / 10; |
| 526 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); | 525 | files_stat.max_files = max_t(unsigned long, n, NR_FILE); |
| 527 | files_defer_init(); | 526 | files_defer_init(); |
| 528 | lg_lock_init(files_lglock); | 527 | lg_lock_init(&files_lglock, "files_lglock"); |
| 529 | percpu_counter_init(&nr_files, 0); | 528 | percpu_counter_init(&nr_files, 0); |
| 530 | } | 529 | } |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 504e61b7fd75..9562109d3a87 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -962,7 +962,9 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 962 | if (err) | 962 | if (err) |
| 963 | goto out; | 963 | goto out; |
| 964 | 964 | ||
| 965 | file_update_time(file); | 965 | err = file_update_time(file); |
| 966 | if (err) | ||
| 967 | goto out; | ||
| 966 | 968 | ||
| 967 | if (file->f_flags & O_DIRECT) { | 969 | if (file->f_flags & O_DIRECT) { |
| 968 | written = generic_file_direct_write(iocb, iov, &nr_segs, | 970 | written = generic_file_direct_write(iocb, iov, &nr_segs, |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 56f6dcf30768..42678a33b7bb 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -627,12 +627,10 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, | |||
| 627 | return ERR_PTR(err); | 627 | return ERR_PTR(err); |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | 630 | static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len, |
| 631 | int connectable) | 631 | struct inode *parent) |
| 632 | { | 632 | { |
| 633 | struct inode *inode = dentry->d_inode; | 633 | int len = parent ? 6 : 3; |
| 634 | bool encode_parent = connectable && !S_ISDIR(inode->i_mode); | ||
| 635 | int len = encode_parent ? 6 : 3; | ||
| 636 | u64 nodeid; | 634 | u64 nodeid; |
| 637 | u32 generation; | 635 | u32 generation; |
| 638 | 636 | ||
| @@ -648,14 +646,9 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | |||
| 648 | fh[1] = (u32)(nodeid & 0xffffffff); | 646 | fh[1] = (u32)(nodeid & 0xffffffff); |
| 649 | fh[2] = generation; | 647 | fh[2] = generation; |
| 650 | 648 | ||
| 651 | if (encode_parent) { | 649 | if (parent) { |
| 652 | struct inode *parent; | ||
| 653 | |||
| 654 | spin_lock(&dentry->d_lock); | ||
| 655 | parent = dentry->d_parent->d_inode; | ||
| 656 | nodeid = get_fuse_inode(parent)->nodeid; | 650 | nodeid = get_fuse_inode(parent)->nodeid; |
| 657 | generation = parent->i_generation; | 651 | generation = parent->i_generation; |
| 658 | spin_unlock(&dentry->d_lock); | ||
| 659 | 652 | ||
| 660 | fh[3] = (u32)(nodeid >> 32); | 653 | fh[3] = (u32)(nodeid >> 32); |
| 661 | fh[4] = (u32)(nodeid & 0xffffffff); | 654 | fh[4] = (u32)(nodeid & 0xffffffff); |
| @@ -663,7 +656,7 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len, | |||
| 663 | } | 656 | } |
| 664 | 657 | ||
| 665 | *max_len = len; | 658 | *max_len = len; |
| 666 | return encode_parent ? 0x82 : 0x81; | 659 | return parent ? 0x82 : 0x81; |
| 667 | } | 660 | } |
| 668 | 661 | ||
| 669 | static struct dentry *fuse_fh_to_dentry(struct super_block *sb, | 662 | static struct dentry *fuse_fh_to_dentry(struct super_block *sb, |
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index 70ba891654f8..e8ed6d4a6181 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c | |||
| @@ -28,15 +28,14 @@ | |||
| 28 | #define GFS2_LARGE_FH_SIZE 8 | 28 | #define GFS2_LARGE_FH_SIZE 8 |
| 29 | #define GFS2_OLD_FH_SIZE 10 | 29 | #define GFS2_OLD_FH_SIZE 10 |
| 30 | 30 | ||
| 31 | static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | 31 | static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len, |
| 32 | int connectable) | 32 | struct inode *parent) |
| 33 | { | 33 | { |
| 34 | __be32 *fh = (__force __be32 *)p; | 34 | __be32 *fh = (__force __be32 *)p; |
| 35 | struct inode *inode = dentry->d_inode; | ||
| 36 | struct super_block *sb = inode->i_sb; | 35 | struct super_block *sb = inode->i_sb; |
| 37 | struct gfs2_inode *ip = GFS2_I(inode); | 36 | struct gfs2_inode *ip = GFS2_I(inode); |
| 38 | 37 | ||
| 39 | if (connectable && (*len < GFS2_LARGE_FH_SIZE)) { | 38 | if (parent && (*len < GFS2_LARGE_FH_SIZE)) { |
| 40 | *len = GFS2_LARGE_FH_SIZE; | 39 | *len = GFS2_LARGE_FH_SIZE; |
| 41 | return 255; | 40 | return 255; |
| 42 | } else if (*len < GFS2_SMALL_FH_SIZE) { | 41 | } else if (*len < GFS2_SMALL_FH_SIZE) { |
| @@ -50,14 +49,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | |||
| 50 | fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF); | 49 | fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF); |
| 51 | *len = GFS2_SMALL_FH_SIZE; | 50 | *len = GFS2_SMALL_FH_SIZE; |
| 52 | 51 | ||
| 53 | if (!connectable || inode == sb->s_root->d_inode) | 52 | if (!parent || inode == sb->s_root->d_inode) |
| 54 | return *len; | 53 | return *len; |
| 55 | 54 | ||
| 56 | spin_lock(&dentry->d_lock); | 55 | ip = GFS2_I(parent); |
| 57 | inode = dentry->d_parent->d_inode; | ||
| 58 | ip = GFS2_I(inode); | ||
| 59 | igrab(inode); | ||
| 60 | spin_unlock(&dentry->d_lock); | ||
| 61 | 56 | ||
| 62 | fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32); | 57 | fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32); |
| 63 | fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF); | 58 | fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF); |
| @@ -65,8 +60,6 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, | |||
| 65 | fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF); | 60 | fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF); |
| 66 | *len = GFS2_LARGE_FH_SIZE; | 61 | *len = GFS2_LARGE_FH_SIZE; |
| 67 | 62 | ||
| 68 | iput(inode); | ||
| 69 | |||
| 70 | return *len; | 63 | return *len; |
| 71 | } | 64 | } |
| 72 | 65 | ||
diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index 7a5eb2c718c8..cdb84a838068 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c | |||
| @@ -16,9 +16,9 @@ | |||
| 16 | static int chk_if_allocated(struct super_block *s, secno sec, char *msg) | 16 | static int chk_if_allocated(struct super_block *s, secno sec, char *msg) |
| 17 | { | 17 | { |
| 18 | struct quad_buffer_head qbh; | 18 | struct quad_buffer_head qbh; |
| 19 | u32 *bmp; | 19 | __le32 *bmp; |
| 20 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail; | 20 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail; |
| 21 | if ((cpu_to_le32(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) { | 21 | if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) { |
| 22 | hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec); | 22 | hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec); |
| 23 | goto fail1; | 23 | goto fail1; |
| 24 | } | 24 | } |
| @@ -62,7 +62,7 @@ int hpfs_chk_sectors(struct super_block *s, secno start, int len, char *msg) | |||
| 62 | static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigned forward) | 62 | static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigned forward) |
| 63 | { | 63 | { |
| 64 | struct quad_buffer_head qbh; | 64 | struct quad_buffer_head qbh; |
| 65 | unsigned *bmp; | 65 | __le32 *bmp; |
| 66 | unsigned bs = near & ~0x3fff; | 66 | unsigned bs = near & ~0x3fff; |
| 67 | unsigned nr = (near & 0x3fff) & ~(n - 1); | 67 | unsigned nr = (near & 0x3fff) & ~(n - 1); |
| 68 | /*unsigned mnr;*/ | 68 | /*unsigned mnr;*/ |
| @@ -236,7 +236,7 @@ static secno alloc_in_dirband(struct super_block *s, secno near) | |||
| 236 | int hpfs_alloc_if_possible(struct super_block *s, secno sec) | 236 | int hpfs_alloc_if_possible(struct super_block *s, secno sec) |
| 237 | { | 237 | { |
| 238 | struct quad_buffer_head qbh; | 238 | struct quad_buffer_head qbh; |
| 239 | u32 *bmp; | 239 | __le32 *bmp; |
| 240 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end; | 240 | if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end; |
| 241 | if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) { | 241 | if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) { |
| 242 | bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f))); | 242 | bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f))); |
| @@ -254,7 +254,7 @@ int hpfs_alloc_if_possible(struct super_block *s, secno sec) | |||
| 254 | void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) | 254 | void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n) |
| 255 | { | 255 | { |
| 256 | struct quad_buffer_head qbh; | 256 | struct quad_buffer_head qbh; |
| 257 | u32 *bmp; | 257 | __le32 *bmp; |
| 258 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 258 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
| 259 | /*printk("2 - ");*/ | 259 | /*printk("2 - ");*/ |
| 260 | if (!n) return; | 260 | if (!n) return; |
| @@ -299,7 +299,7 @@ int hpfs_check_free_dnodes(struct super_block *s, int n) | |||
| 299 | int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14; | 299 | int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14; |
| 300 | int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff; | 300 | int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff; |
| 301 | int i, j; | 301 | int i, j; |
| 302 | u32 *bmp; | 302 | __le32 *bmp; |
| 303 | struct quad_buffer_head qbh; | 303 | struct quad_buffer_head qbh; |
| 304 | if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) { | 304 | if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) { |
| 305 | for (j = 0; j < 512; j++) { | 305 | for (j = 0; j < 512; j++) { |
| @@ -351,7 +351,7 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno) | |||
| 351 | hpfs_free_sectors(s, dno, 4); | 351 | hpfs_free_sectors(s, dno, 4); |
| 352 | } else { | 352 | } else { |
| 353 | struct quad_buffer_head qbh; | 353 | struct quad_buffer_head qbh; |
| 354 | u32 *bmp; | 354 | __le32 *bmp; |
| 355 | unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4; | 355 | unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4; |
| 356 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { | 356 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { |
| 357 | return; | 357 | return; |
diff --git a/fs/hpfs/anode.c b/fs/hpfs/anode.c index 08b503e8ed29..4bae4a4a60b1 100644 --- a/fs/hpfs/anode.c +++ b/fs/hpfs/anode.c | |||
| @@ -20,7 +20,7 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode, | |||
| 20 | int c1, c2 = 0; | 20 | int c1, c2 = 0; |
| 21 | go_down: | 21 | go_down: |
| 22 | if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1; | 22 | if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1; |
| 23 | if (btree->internal) { | 23 | if (bp_internal(btree)) { |
| 24 | for (i = 0; i < btree->n_used_nodes; i++) | 24 | for (i = 0; i < btree->n_used_nodes; i++) |
| 25 | if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) { | 25 | if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) { |
| 26 | a = le32_to_cpu(btree->u.internal[i].down); | 26 | a = le32_to_cpu(btree->u.internal[i].down); |
| @@ -82,7 +82,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
| 82 | brelse(bh); | 82 | brelse(bh); |
| 83 | return -1; | 83 | return -1; |
| 84 | } | 84 | } |
| 85 | if (btree->internal) { | 85 | if (bp_internal(btree)) { |
| 86 | a = le32_to_cpu(btree->u.internal[n].down); | 86 | a = le32_to_cpu(btree->u.internal[n].down); |
| 87 | btree->u.internal[n].file_secno = cpu_to_le32(-1); | 87 | btree->u.internal[n].file_secno = cpu_to_le32(-1); |
| 88 | mark_buffer_dirty(bh); | 88 | mark_buffer_dirty(bh); |
| @@ -129,12 +129,12 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
| 129 | } | 129 | } |
| 130 | if (a == node && fnod) { | 130 | if (a == node && fnod) { |
| 131 | anode->up = cpu_to_le32(node); | 131 | anode->up = cpu_to_le32(node); |
| 132 | anode->btree.fnode_parent = 1; | 132 | anode->btree.flags |= BP_fnode_parent; |
| 133 | anode->btree.n_used_nodes = btree->n_used_nodes; | 133 | anode->btree.n_used_nodes = btree->n_used_nodes; |
| 134 | anode->btree.first_free = btree->first_free; | 134 | anode->btree.first_free = btree->first_free; |
| 135 | anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes; | 135 | anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes; |
| 136 | memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12); | 136 | memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12); |
| 137 | btree->internal = 1; | 137 | btree->flags |= BP_internal; |
| 138 | btree->n_free_nodes = 11; | 138 | btree->n_free_nodes = 11; |
| 139 | btree->n_used_nodes = 1; | 139 | btree->n_used_nodes = 1; |
| 140 | btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree); | 140 | btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree); |
| @@ -184,7 +184,10 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
| 184 | hpfs_free_sectors(s, ra, 1); | 184 | hpfs_free_sectors(s, ra, 1); |
| 185 | if ((anode = hpfs_map_anode(s, na, &bh))) { | 185 | if ((anode = hpfs_map_anode(s, na, &bh))) { |
| 186 | anode->up = cpu_to_le32(up); | 186 | anode->up = cpu_to_le32(up); |
| 187 | anode->btree.fnode_parent = up == node && fnod; | 187 | if (up == node && fnod) |
| 188 | anode->btree.flags |= BP_fnode_parent; | ||
| 189 | else | ||
| 190 | anode->btree.flags &= ~BP_fnode_parent; | ||
| 188 | mark_buffer_dirty(bh); | 191 | mark_buffer_dirty(bh); |
| 189 | brelse(bh); | 192 | brelse(bh); |
| 190 | } | 193 | } |
| @@ -198,7 +201,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
| 198 | if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) { | 201 | if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) { |
| 199 | anode = new_anode; | 202 | anode = new_anode; |
| 200 | /*anode->up = cpu_to_le32(up != -1 ? up : ra);*/ | 203 | /*anode->up = cpu_to_le32(up != -1 ? up : ra);*/ |
| 201 | anode->btree.internal = 1; | 204 | anode->btree.flags |= BP_internal; |
| 202 | anode->btree.n_used_nodes = 1; | 205 | anode->btree.n_used_nodes = 1; |
| 203 | anode->btree.n_free_nodes = 59; | 206 | anode->btree.n_free_nodes = 59; |
| 204 | anode->btree.first_free = cpu_to_le16(16); | 207 | anode->btree.first_free = cpu_to_le16(16); |
| @@ -215,7 +218,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
| 215 | } | 218 | } |
| 216 | if ((anode = hpfs_map_anode(s, na, &bh))) { | 219 | if ((anode = hpfs_map_anode(s, na, &bh))) { |
| 217 | anode->up = cpu_to_le32(node); | 220 | anode->up = cpu_to_le32(node); |
| 218 | if (fnod) anode->btree.fnode_parent = 1; | 221 | if (fnod) |
| 222 | anode->btree.flags |= BP_fnode_parent; | ||
| 219 | mark_buffer_dirty(bh); | 223 | mark_buffer_dirty(bh); |
| 220 | brelse(bh); | 224 | brelse(bh); |
| 221 | } | 225 | } |
| @@ -234,18 +238,19 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi | |||
| 234 | } | 238 | } |
| 235 | ranode->up = cpu_to_le32(node); | 239 | ranode->up = cpu_to_le32(node); |
| 236 | memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free)); | 240 | memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free)); |
| 237 | if (fnod) ranode->btree.fnode_parent = 1; | 241 | if (fnod) |
| 238 | ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes; | 242 | ranode->btree.flags |= BP_fnode_parent; |
| 239 | if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) { | 243 | ranode->btree.n_free_nodes = (bp_internal(&ranode->btree) ? 60 : 40) - ranode->btree.n_used_nodes; |
| 244 | if (bp_internal(&ranode->btree)) for (n = 0; n < ranode->btree.n_used_nodes; n++) { | ||
| 240 | struct anode *unode; | 245 | struct anode *unode; |
| 241 | if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) { | 246 | if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) { |
| 242 | unode->up = cpu_to_le32(ra); | 247 | unode->up = cpu_to_le32(ra); |
| 243 | unode->btree.fnode_parent = 0; | 248 | unode->btree.flags &= ~BP_fnode_parent; |
| 244 | mark_buffer_dirty(bh1); | 249 | mark_buffer_dirty(bh1); |
| 245 | brelse(bh1); | 250 | brelse(bh1); |
| 246 | } | 251 | } |
| 247 | } | 252 | } |
| 248 | btree->internal = 1; | 253 | btree->flags |= BP_internal; |
| 249 | btree->n_free_nodes = fnod ? 10 : 58; | 254 | btree->n_free_nodes = fnod ? 10 : 58; |
| 250 | btree->n_used_nodes = 2; | 255 | btree->n_used_nodes = 2; |
| 251 | btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree); | 256 | btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree); |
| @@ -278,7 +283,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree) | |||
| 278 | int d1, d2; | 283 | int d1, d2; |
| 279 | go_down: | 284 | go_down: |
| 280 | d2 = 0; | 285 | d2 = 0; |
| 281 | while (btree1->internal) { | 286 | while (bp_internal(btree1)) { |
| 282 | ano = le32_to_cpu(btree1->u.internal[pos].down); | 287 | ano = le32_to_cpu(btree1->u.internal[pos].down); |
| 283 | if (level) brelse(bh); | 288 | if (level) brelse(bh); |
| 284 | if (hpfs_sb(s)->sb_chk) | 289 | if (hpfs_sb(s)->sb_chk) |
| @@ -412,13 +417,13 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs) | |||
| 412 | btree->n_free_nodes = 8; | 417 | btree->n_free_nodes = 8; |
| 413 | btree->n_used_nodes = 0; | 418 | btree->n_used_nodes = 0; |
| 414 | btree->first_free = cpu_to_le16(8); | 419 | btree->first_free = cpu_to_le16(8); |
| 415 | btree->internal = 0; | 420 | btree->flags &= ~BP_internal; |
| 416 | mark_buffer_dirty(bh); | 421 | mark_buffer_dirty(bh); |
| 417 | } else hpfs_free_sectors(s, f, 1); | 422 | } else hpfs_free_sectors(s, f, 1); |
| 418 | brelse(bh); | 423 | brelse(bh); |
| 419 | return; | 424 | return; |
| 420 | } | 425 | } |
| 421 | while (btree->internal) { | 426 | while (bp_internal(btree)) { |
| 422 | nodes = btree->n_used_nodes + btree->n_free_nodes; | 427 | nodes = btree->n_used_nodes + btree->n_free_nodes; |
| 423 | for (i = 0; i < btree->n_used_nodes; i++) | 428 | for (i = 0; i < btree->n_used_nodes; i++) |
| 424 | if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f; | 429 | if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f; |
| @@ -479,13 +484,13 @@ void hpfs_remove_fnode(struct super_block *s, fnode_secno fno) | |||
| 479 | struct extended_attribute *ea; | 484 | struct extended_attribute *ea; |
| 480 | struct extended_attribute *ea_end; | 485 | struct extended_attribute *ea_end; |
| 481 | if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return; | 486 | if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return; |
| 482 | if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree); | 487 | if (!fnode_is_dir(fnode)) hpfs_remove_btree(s, &fnode->btree); |
| 483 | else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno)); | 488 | else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno)); |
| 484 | ea_end = fnode_end_ea(fnode); | 489 | ea_end = fnode_end_ea(fnode); |
| 485 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) | 490 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) |
| 486 | if (ea->indirect) | 491 | if (ea_indirect(ea)) |
| 487 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); | 492 | hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea)); |
| 488 | hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l)); | 493 | hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l)); |
| 489 | brelse(bh); | 494 | brelse(bh); |
| 490 | hpfs_free_sectors(s, fno, 1); | 495 | hpfs_free_sectors(s, fno, 1); |
| 491 | } | 496 | } |
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 2fa0089a02a8..b8472f803f4e 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
| @@ -87,7 +87,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 87 | ret = -EIOERROR; | 87 | ret = -EIOERROR; |
| 88 | goto out; | 88 | goto out; |
| 89 | } | 89 | } |
| 90 | if (!fno->dirflag) { | 90 | if (!fnode_is_dir(fno)) { |
| 91 | e = 1; | 91 | e = 1; |
| 92 | hpfs_error(inode->i_sb, "not a directory, fnode %08lx", | 92 | hpfs_error(inode->i_sb, "not a directory, fnode %08lx", |
| 93 | (unsigned long)inode->i_ino); | 93 | (unsigned long)inode->i_ino); |
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c index 1e0e2ac30fd3..3228c524ebe5 100644 --- a/fs/hpfs/dnode.c +++ b/fs/hpfs/dnode.c | |||
| @@ -153,7 +153,7 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno | |||
| 153 | } | 153 | } |
| 154 | de->length = cpu_to_le16(36); | 154 | de->length = cpu_to_le16(36); |
| 155 | de->down = 1; | 155 | de->down = 1; |
| 156 | *(dnode_secno *)((char *)de + 32) = cpu_to_le32(ptr); | 156 | *(__le32 *)((char *)de + 32) = cpu_to_le32(ptr); |
| 157 | } | 157 | } |
| 158 | } | 158 | } |
| 159 | 159 | ||
| @@ -177,7 +177,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, | |||
| 177 | memmove((char *)de + d_size, de, (char *)de_end - (char *)de); | 177 | memmove((char *)de + d_size, de, (char *)de_end - (char *)de); |
| 178 | memset(de, 0, d_size); | 178 | memset(de, 0, d_size); |
| 179 | if (down_ptr) { | 179 | if (down_ptr) { |
| 180 | *(dnode_secno *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr); | 180 | *(__le32 *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr); |
| 181 | de->down = 1; | 181 | de->down = 1; |
| 182 | } | 182 | } |
| 183 | de->length = cpu_to_le16(d_size); | 183 | de->length = cpu_to_le16(d_size); |
| @@ -656,7 +656,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
| 656 | del->down = 0; | 656 | del->down = 0; |
| 657 | d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4); | 657 | d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4); |
| 658 | } else if (down) | 658 | } else if (down) |
| 659 | *(dnode_secno *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down); | 659 | *(__le32 *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down); |
| 660 | } else goto endm; | 660 | } else goto endm; |
| 661 | if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) { | 661 | if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) { |
| 662 | printk("HPFS: out of memory for dtree balancing\n"); | 662 | printk("HPFS: out of memory for dtree balancing\n"); |
| @@ -672,7 +672,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno) | |||
| 672 | de_prev->down = 1; | 672 | de_prev->down = 1; |
| 673 | dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4); | 673 | dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4); |
| 674 | } | 674 | } |
| 675 | *(dnode_secno *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown); | 675 | *(__le32 *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown); |
| 676 | hpfs_mark_4buffers_dirty(&qbh); | 676 | hpfs_mark_4buffers_dirty(&qbh); |
| 677 | hpfs_brelse4(&qbh); | 677 | hpfs_brelse4(&qbh); |
| 678 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4); | 678 | for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4); |
| @@ -1015,7 +1015,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno, | |||
| 1015 | kfree(name2); | 1015 | kfree(name2); |
| 1016 | return NULL; | 1016 | return NULL; |
| 1017 | } | 1017 | } |
| 1018 | if (!upf->dirflag) { | 1018 | if (!fnode_is_dir(upf)) { |
| 1019 | brelse(bh); | 1019 | brelse(bh); |
| 1020 | hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up)); | 1020 | hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up)); |
| 1021 | kfree(name2); | 1021 | kfree(name2); |
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c index d8b84d113c89..bcaafcd2666a 100644 --- a/fs/hpfs/ea.c +++ b/fs/hpfs/ea.c | |||
| @@ -23,15 +23,15 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len) | |||
| 23 | return; | 23 | return; |
| 24 | } | 24 | } |
| 25 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; | 25 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; |
| 26 | if (ea->indirect) { | 26 | if (ea_indirect(ea)) { |
| 27 | if (ea_valuelen(ea) != 8) { | 27 | if (ea_valuelen(ea) != 8) { |
| 28 | hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x", | 28 | hpfs_error(s, "ea_indirect(ea) set while ea->valuelen!=8, %s %08x, pos %08x", |
| 29 | ano ? "anode" : "sectors", a, pos); | 29 | ano ? "anode" : "sectors", a, pos); |
| 30 | return; | 30 | return; |
| 31 | } | 31 | } |
| 32 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4)) | 32 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4)) |
| 33 | return; | 33 | return; |
| 34 | hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea)); | 34 | hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea)); |
| 35 | } | 35 | } |
| 36 | pos += ea->namelen + ea_valuelen(ea) + 5; | 36 | pos += ea->namelen + ea_valuelen(ea) + 5; |
| 37 | } | 37 | } |
| @@ -81,7 +81,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
| 81 | struct extended_attribute *ea_end = fnode_end_ea(fnode); | 81 | struct extended_attribute *ea_end = fnode_end_ea(fnode); |
| 82 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) | 82 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) |
| 83 | if (!strcmp(ea->name, key)) { | 83 | if (!strcmp(ea->name, key)) { |
| 84 | if (ea->indirect) | 84 | if (ea_indirect(ea)) |
| 85 | goto indirect; | 85 | goto indirect; |
| 86 | if (ea_valuelen(ea) >= size) | 86 | if (ea_valuelen(ea) >= size) |
| 87 | return -EINVAL; | 87 | return -EINVAL; |
| @@ -91,7 +91,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
| 91 | } | 91 | } |
| 92 | a = le32_to_cpu(fnode->ea_secno); | 92 | a = le32_to_cpu(fnode->ea_secno); |
| 93 | len = le32_to_cpu(fnode->ea_size_l); | 93 | len = le32_to_cpu(fnode->ea_size_l); |
| 94 | ano = fnode->ea_anode; | 94 | ano = fnode_in_anode(fnode); |
| 95 | pos = 0; | 95 | pos = 0; |
| 96 | while (pos < len) { | 96 | while (pos < len) { |
| 97 | ea = (struct extended_attribute *)ex; | 97 | ea = (struct extended_attribute *)ex; |
| @@ -101,10 +101,10 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
| 101 | return -EIO; | 101 | return -EIO; |
| 102 | } | 102 | } |
| 103 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO; | 103 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO; |
| 104 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) | 104 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4)) |
| 105 | return -EIO; | 105 | return -EIO; |
| 106 | if (!strcmp(ea->name, key)) { | 106 | if (!strcmp(ea->name, key)) { |
| 107 | if (ea->indirect) | 107 | if (ea_indirect(ea)) |
| 108 | goto indirect; | 108 | goto indirect; |
| 109 | if (ea_valuelen(ea) >= size) | 109 | if (ea_valuelen(ea) >= size) |
| 110 | return -EINVAL; | 110 | return -EINVAL; |
| @@ -119,7 +119,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key, | |||
| 119 | indirect: | 119 | indirect: |
| 120 | if (ea_len(ea) >= size) | 120 | if (ea_len(ea) >= size) |
| 121 | return -EINVAL; | 121 | return -EINVAL; |
| 122 | if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf)) | 122 | if (hpfs_ea_read(s, ea_sec(ea), ea_in_anode(ea), 0, ea_len(ea), buf)) |
| 123 | return -EIO; | 123 | return -EIO; |
| 124 | buf[ea_len(ea)] = 0; | 124 | buf[ea_len(ea)] = 0; |
| 125 | return 0; | 125 | return 0; |
| @@ -136,8 +136,8 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
| 136 | struct extended_attribute *ea_end = fnode_end_ea(fnode); | 136 | struct extended_attribute *ea_end = fnode_end_ea(fnode); |
| 137 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) | 137 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) |
| 138 | if (!strcmp(ea->name, key)) { | 138 | if (!strcmp(ea->name, key)) { |
| 139 | if (ea->indirect) | 139 | if (ea_indirect(ea)) |
| 140 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); | 140 | return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); |
| 141 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { | 141 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { |
| 142 | printk("HPFS: out of memory for EA\n"); | 142 | printk("HPFS: out of memory for EA\n"); |
| 143 | return NULL; | 143 | return NULL; |
| @@ -148,7 +148,7 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
| 148 | } | 148 | } |
| 149 | a = le32_to_cpu(fnode->ea_secno); | 149 | a = le32_to_cpu(fnode->ea_secno); |
| 150 | len = le32_to_cpu(fnode->ea_size_l); | 150 | len = le32_to_cpu(fnode->ea_size_l); |
| 151 | ano = fnode->ea_anode; | 151 | ano = fnode_in_anode(fnode); |
| 152 | pos = 0; | 152 | pos = 0; |
| 153 | while (pos < len) { | 153 | while (pos < len) { |
| 154 | char ex[4 + 255 + 1 + 8]; | 154 | char ex[4 + 255 + 1 + 8]; |
| @@ -159,11 +159,11 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si | |||
| 159 | return NULL; | 159 | return NULL; |
| 160 | } | 160 | } |
| 161 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL; | 161 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL; |
| 162 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) | 162 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4)) |
| 163 | return NULL; | 163 | return NULL; |
| 164 | if (!strcmp(ea->name, key)) { | 164 | if (!strcmp(ea->name, key)) { |
| 165 | if (ea->indirect) | 165 | if (ea_indirect(ea)) |
| 166 | return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea)); | 166 | return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea)); |
| 167 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { | 167 | if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) { |
| 168 | printk("HPFS: out of memory for EA\n"); | 168 | printk("HPFS: out of memory for EA\n"); |
| 169 | return NULL; | 169 | return NULL; |
| @@ -199,9 +199,9 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 199 | struct extended_attribute *ea_end = fnode_end_ea(fnode); | 199 | struct extended_attribute *ea_end = fnode_end_ea(fnode); |
| 200 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) | 200 | for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea)) |
| 201 | if (!strcmp(ea->name, key)) { | 201 | if (!strcmp(ea->name, key)) { |
| 202 | if (ea->indirect) { | 202 | if (ea_indirect(ea)) { |
| 203 | if (ea_len(ea) == size) | 203 | if (ea_len(ea) == size) |
| 204 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); | 204 | set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size); |
| 205 | } else if (ea_valuelen(ea) == size) { | 205 | } else if (ea_valuelen(ea) == size) { |
| 206 | memcpy(ea_data(ea), data, size); | 206 | memcpy(ea_data(ea), data, size); |
| 207 | } | 207 | } |
| @@ -209,7 +209,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 209 | } | 209 | } |
| 210 | a = le32_to_cpu(fnode->ea_secno); | 210 | a = le32_to_cpu(fnode->ea_secno); |
| 211 | len = le32_to_cpu(fnode->ea_size_l); | 211 | len = le32_to_cpu(fnode->ea_size_l); |
| 212 | ano = fnode->ea_anode; | 212 | ano = fnode_in_anode(fnode); |
| 213 | pos = 0; | 213 | pos = 0; |
| 214 | while (pos < len) { | 214 | while (pos < len) { |
| 215 | char ex[4 + 255 + 1 + 8]; | 215 | char ex[4 + 255 + 1 + 8]; |
| @@ -220,12 +220,12 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 220 | return; | 220 | return; |
| 221 | } | 221 | } |
| 222 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; | 222 | if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return; |
| 223 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4)) | 223 | if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4)) |
| 224 | return; | 224 | return; |
| 225 | if (!strcmp(ea->name, key)) { | 225 | if (!strcmp(ea->name, key)) { |
| 226 | if (ea->indirect) { | 226 | if (ea_indirect(ea)) { |
| 227 | if (ea_len(ea) == size) | 227 | if (ea_len(ea) == size) |
| 228 | set_indirect_ea(s, ea->anode, ea_sec(ea), data, size); | 228 | set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size); |
| 229 | } | 229 | } |
| 230 | else { | 230 | else { |
| 231 | if (ea_valuelen(ea) == size) | 231 | if (ea_valuelen(ea) == size) |
| @@ -246,7 +246,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 246 | if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) { | 246 | if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) { |
| 247 | hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x", | 247 | hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x", |
| 248 | (unsigned long)inode->i_ino, | 248 | (unsigned long)inode->i_ino, |
| 249 | le32_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); | 249 | le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); |
| 250 | return; | 250 | return; |
| 251 | } | 251 | } |
| 252 | if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) && | 252 | if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) && |
| @@ -276,7 +276,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 276 | fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s)); | 276 | fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s)); |
| 277 | fnode->ea_size_s = cpu_to_le16(0); | 277 | fnode->ea_size_s = cpu_to_le16(0); |
| 278 | fnode->ea_secno = cpu_to_le32(n); | 278 | fnode->ea_secno = cpu_to_le32(n); |
| 279 | fnode->ea_anode = cpu_to_le32(0); | 279 | fnode->flags &= ~FNODE_anode; |
| 280 | mark_buffer_dirty(bh); | 280 | mark_buffer_dirty(bh); |
| 281 | brelse(bh); | 281 | brelse(bh); |
| 282 | } | 282 | } |
| @@ -288,9 +288,9 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 288 | secno q = hpfs_alloc_sector(s, fno, 1, 0); | 288 | secno q = hpfs_alloc_sector(s, fno, 1, 0); |
| 289 | if (!q) goto bail; | 289 | if (!q) goto bail; |
| 290 | fnode->ea_secno = cpu_to_le32(q); | 290 | fnode->ea_secno = cpu_to_le32(q); |
| 291 | fnode->ea_anode = 0; | 291 | fnode->flags &= ~FNODE_anode; |
| 292 | len++; | 292 | len++; |
| 293 | } else if (!fnode->ea_anode) { | 293 | } else if (!fnode_in_anode(fnode)) { |
| 294 | if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) { | 294 | if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) { |
| 295 | len++; | 295 | len++; |
| 296 | } else { | 296 | } else { |
| @@ -310,7 +310,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 310 | anode->u.external[0].length = cpu_to_le32(len); | 310 | anode->u.external[0].length = cpu_to_le32(len); |
| 311 | mark_buffer_dirty(bh); | 311 | mark_buffer_dirty(bh); |
| 312 | brelse(bh); | 312 | brelse(bh); |
| 313 | fnode->ea_anode = 1; | 313 | fnode->flags |= FNODE_anode; |
| 314 | fnode->ea_secno = cpu_to_le32(a_s);*/ | 314 | fnode->ea_secno = cpu_to_le32(a_s);*/ |
| 315 | secno new_sec; | 315 | secno new_sec; |
| 316 | int i; | 316 | int i; |
| @@ -338,7 +338,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 338 | len = (pos + 511) >> 9; | 338 | len = (pos + 511) >> 9; |
| 339 | } | 339 | } |
| 340 | } | 340 | } |
| 341 | if (fnode->ea_anode) { | 341 | if (fnode_in_anode(fnode)) { |
| 342 | if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno), | 342 | if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno), |
| 343 | 0, len) != -1) { | 343 | 0, len) != -1) { |
| 344 | len++; | 344 | len++; |
| @@ -351,16 +351,16 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key, | |||
| 351 | h[1] = strlen(key); | 351 | h[1] = strlen(key); |
| 352 | h[2] = size & 0xff; | 352 | h[2] = size & 0xff; |
| 353 | h[3] = size >> 8; | 353 | h[3] = size >> 8; |
| 354 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail; | 354 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail; |
| 355 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail; | 355 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail; |
| 356 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail; | 356 | if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail; |
| 357 | fnode->ea_size_l = cpu_to_le32(pos); | 357 | fnode->ea_size_l = cpu_to_le32(pos); |
| 358 | ret: | 358 | ret: |
| 359 | hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size; | 359 | hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size; |
| 360 | return; | 360 | return; |
| 361 | bail: | 361 | bail: |
| 362 | if (le32_to_cpu(fnode->ea_secno)) | 362 | if (le32_to_cpu(fnode->ea_secno)) |
| 363 | if (fnode->ea_anode) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9); | 363 | if (fnode_in_anode(fnode)) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9); |
| 364 | else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9)); | 364 | else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9)); |
| 365 | else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0); | 365 | else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0); |
| 366 | } | 366 | } |
diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h index 8b0650aae328..cce025aff1b1 100644 --- a/fs/hpfs/hpfs.h +++ b/fs/hpfs/hpfs.h | |||
| @@ -51,11 +51,11 @@ struct hpfs_boot_block | |||
| 51 | u8 n_rootdir_entries[2]; | 51 | u8 n_rootdir_entries[2]; |
| 52 | u8 n_sectors_s[2]; | 52 | u8 n_sectors_s[2]; |
| 53 | u8 media_byte; | 53 | u8 media_byte; |
| 54 | u16 sectors_per_fat; | 54 | __le16 sectors_per_fat; |
| 55 | u16 sectors_per_track; | 55 | __le16 sectors_per_track; |
| 56 | u16 heads_per_cyl; | 56 | __le16 heads_per_cyl; |
| 57 | u32 n_hidden_sectors; | 57 | __le32 n_hidden_sectors; |
| 58 | u32 n_sectors_l; /* size of partition */ | 58 | __le32 n_sectors_l; /* size of partition */ |
| 59 | u8 drive_number; | 59 | u8 drive_number; |
| 60 | u8 mbz; | 60 | u8 mbz; |
| 61 | u8 sig_28h; /* 28h */ | 61 | u8 sig_28h; /* 28h */ |
| @@ -63,7 +63,7 @@ struct hpfs_boot_block | |||
| 63 | u8 vol_label[11]; | 63 | u8 vol_label[11]; |
| 64 | u8 sig_hpfs[8]; /* "HPFS " */ | 64 | u8 sig_hpfs[8]; /* "HPFS " */ |
| 65 | u8 pad[448]; | 65 | u8 pad[448]; |
| 66 | u16 magic; /* aa55 */ | 66 | __le16 magic; /* aa55 */ |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | 69 | ||
| @@ -75,28 +75,28 @@ struct hpfs_boot_block | |||
| 75 | 75 | ||
| 76 | struct hpfs_super_block | 76 | struct hpfs_super_block |
| 77 | { | 77 | { |
| 78 | u32 magic; /* f995 e849 */ | 78 | __le32 magic; /* f995 e849 */ |
| 79 | u32 magic1; /* fa53 e9c5, more magic? */ | 79 | __le32 magic1; /* fa53 e9c5, more magic? */ |
| 80 | u8 version; /* version of a filesystem usually 2 */ | 80 | u8 version; /* version of a filesystem usually 2 */ |
| 81 | u8 funcversion; /* functional version - oldest version | 81 | u8 funcversion; /* functional version - oldest version |
| 82 | of filesystem that can understand | 82 | of filesystem that can understand |
| 83 | this disk */ | 83 | this disk */ |
| 84 | u16 zero; /* 0 */ | 84 | __le16 zero; /* 0 */ |
| 85 | fnode_secno root; /* fnode of root directory */ | 85 | __le32 root; /* fnode of root directory */ |
| 86 | secno n_sectors; /* size of filesystem */ | 86 | __le32 n_sectors; /* size of filesystem */ |
| 87 | u32 n_badblocks; /* number of bad blocks */ | 87 | __le32 n_badblocks; /* number of bad blocks */ |
| 88 | secno bitmaps; /* pointers to free space bit maps */ | 88 | __le32 bitmaps; /* pointers to free space bit maps */ |
| 89 | u32 zero1; /* 0 */ | 89 | __le32 zero1; /* 0 */ |
| 90 | secno badblocks; /* bad block list */ | 90 | __le32 badblocks; /* bad block list */ |
| 91 | u32 zero3; /* 0 */ | 91 | __le32 zero3; /* 0 */ |
| 92 | time32_t last_chkdsk; /* date last checked, 0 if never */ | 92 | __le32 last_chkdsk; /* date last checked, 0 if never */ |
| 93 | time32_t last_optimize; /* date last optimized, 0 if never */ | 93 | __le32 last_optimize; /* date last optimized, 0 if never */ |
| 94 | secno n_dir_band; /* number of sectors in dir band */ | 94 | __le32 n_dir_band; /* number of sectors in dir band */ |
| 95 | secno dir_band_start; /* first sector in dir band */ | 95 | __le32 dir_band_start; /* first sector in dir band */ |
| 96 | secno dir_band_end; /* last sector in dir band */ | 96 | __le32 dir_band_end; /* last sector in dir band */ |
| 97 | secno dir_band_bitmap; /* free space map, 1 dnode per bit */ | 97 | __le32 dir_band_bitmap; /* free space map, 1 dnode per bit */ |
| 98 | u8 volume_name[32]; /* not used */ | 98 | u8 volume_name[32]; /* not used */ |
| 99 | secno user_id_table; /* 8 preallocated sectors - user id */ | 99 | __le32 user_id_table; /* 8 preallocated sectors - user id */ |
| 100 | u32 zero6[103]; /* 0 */ | 100 | u32 zero6[103]; /* 0 */ |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| @@ -109,8 +109,8 @@ struct hpfs_super_block | |||
| 109 | 109 | ||
| 110 | struct hpfs_spare_block | 110 | struct hpfs_spare_block |
| 111 | { | 111 | { |
| 112 | u32 magic; /* f991 1849 */ | 112 | __le32 magic; /* f991 1849 */ |
| 113 | u32 magic1; /* fa52 29c5, more magic? */ | 113 | __le32 magic1; /* fa52 29c5, more magic? */ |
| 114 | 114 | ||
| 115 | #ifdef __LITTLE_ENDIAN | 115 | #ifdef __LITTLE_ENDIAN |
| 116 | u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */ | 116 | u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */ |
| @@ -153,21 +153,21 @@ struct hpfs_spare_block | |||
| 153 | u8 mm_contlgulty; | 153 | u8 mm_contlgulty; |
| 154 | u8 unused; | 154 | u8 unused; |
| 155 | 155 | ||
| 156 | secno hotfix_map; /* info about remapped bad sectors */ | 156 | __le32 hotfix_map; /* info about remapped bad sectors */ |
| 157 | u32 n_spares_used; /* number of hotfixes */ | 157 | __le32 n_spares_used; /* number of hotfixes */ |
| 158 | u32 n_spares; /* number of spares in hotfix map */ | 158 | __le32 n_spares; /* number of spares in hotfix map */ |
| 159 | u32 n_dnode_spares_free; /* spare dnodes unused */ | 159 | __le32 n_dnode_spares_free; /* spare dnodes unused */ |
| 160 | u32 n_dnode_spares; /* length of spare_dnodes[] list, | 160 | __le32 n_dnode_spares; /* length of spare_dnodes[] list, |
| 161 | follows in this block*/ | 161 | follows in this block*/ |
| 162 | secno code_page_dir; /* code page directory block */ | 162 | __le32 code_page_dir; /* code page directory block */ |
| 163 | u32 n_code_pages; /* number of code pages */ | 163 | __le32 n_code_pages; /* number of code pages */ |
| 164 | u32 super_crc; /* on HPFS386 and LAN Server this is | 164 | __le32 super_crc; /* on HPFS386 and LAN Server this is |
| 165 | checksum of superblock, on normal | 165 | checksum of superblock, on normal |
| 166 | OS/2 unused */ | 166 | OS/2 unused */ |
| 167 | u32 spare_crc; /* on HPFS386 checksum of spareblock */ | 167 | __le32 spare_crc; /* on HPFS386 checksum of spareblock */ |
| 168 | u32 zero1[15]; /* unused */ | 168 | __le32 zero1[15]; /* unused */ |
| 169 | dnode_secno spare_dnodes[100]; /* emergency free dnode list */ | 169 | __le32 spare_dnodes[100]; /* emergency free dnode list */ |
| 170 | u32 zero2[1]; /* room for more? */ | 170 | __le32 zero2[1]; /* room for more? */ |
| 171 | }; | 171 | }; |
| 172 | 172 | ||
| 173 | /* The bad block list is 4 sectors long. The first word must be zero, | 173 | /* The bad block list is 4 sectors long. The first word must be zero, |
| @@ -202,18 +202,18 @@ struct hpfs_spare_block | |||
| 202 | 202 | ||
| 203 | struct code_page_directory | 203 | struct code_page_directory |
| 204 | { | 204 | { |
| 205 | u32 magic; /* 4945 21f7 */ | 205 | __le32 magic; /* 4945 21f7 */ |
| 206 | u32 n_code_pages; /* number of pointers following */ | 206 | __le32 n_code_pages; /* number of pointers following */ |
| 207 | u32 zero1[2]; | 207 | __le32 zero1[2]; |
| 208 | struct { | 208 | struct { |
| 209 | u16 ix; /* index */ | 209 | __le16 ix; /* index */ |
| 210 | u16 code_page_number; /* code page number */ | 210 | __le16 code_page_number; /* code page number */ |
| 211 | u32 bounds; /* matches corresponding word | 211 | __le32 bounds; /* matches corresponding word |
| 212 | in data block */ | 212 | in data block */ |
| 213 | secno code_page_data; /* sector number of a code_page_data | 213 | __le32 code_page_data; /* sector number of a code_page_data |
| 214 | containing c.p. array */ | 214 | containing c.p. array */ |
| 215 | u16 index; /* index in c.p. array in that sector*/ | 215 | __le16 index; /* index in c.p. array in that sector*/ |
| 216 | u16 unknown; /* some unknown value; usually 0; | 216 | __le16 unknown; /* some unknown value; usually 0; |
| 217 | 2 in Japanese version */ | 217 | 2 in Japanese version */ |
| 218 | } array[31]; /* unknown length */ | 218 | } array[31]; /* unknown length */ |
| 219 | }; | 219 | }; |
| @@ -224,19 +224,19 @@ struct code_page_directory | |||
| 224 | 224 | ||
| 225 | struct code_page_data | 225 | struct code_page_data |
| 226 | { | 226 | { |
| 227 | u32 magic; /* 8945 21f7 */ | 227 | __le32 magic; /* 8945 21f7 */ |
| 228 | u32 n_used; /* # elements used in c_p_data[] */ | 228 | __le32 n_used; /* # elements used in c_p_data[] */ |
| 229 | u32 bounds[3]; /* looks a bit like | 229 | __le32 bounds[3]; /* looks a bit like |
| 230 | (beg1,end1), (beg2,end2) | 230 | (beg1,end1), (beg2,end2) |
| 231 | one byte each */ | 231 | one byte each */ |
| 232 | u16 offs[3]; /* offsets from start of sector | 232 | __le16 offs[3]; /* offsets from start of sector |
| 233 | to start of c_p_data[ix] */ | 233 | to start of c_p_data[ix] */ |
| 234 | struct { | 234 | struct { |
| 235 | u16 ix; /* index */ | 235 | __le16 ix; /* index */ |
| 236 | u16 code_page_number; /* code page number */ | 236 | __le16 code_page_number; /* code page number */ |
| 237 | u16 unknown; /* the same as in cp directory */ | 237 | __le16 unknown; /* the same as in cp directory */ |
| 238 | u8 map[128]; /* upcase table for chars 80..ff */ | 238 | u8 map[128]; /* upcase table for chars 80..ff */ |
| 239 | u16 zero2; | 239 | __le16 zero2; |
| 240 | } code_page[3]; | 240 | } code_page[3]; |
| 241 | u8 incognita[78]; | 241 | u8 incognita[78]; |
| 242 | }; | 242 | }; |
| @@ -278,8 +278,8 @@ struct code_page_data | |||
| 278 | #define DNODE_MAGIC 0x77e40aae | 278 | #define DNODE_MAGIC 0x77e40aae |
| 279 | 279 | ||
| 280 | struct dnode { | 280 | struct dnode { |
| 281 | u32 magic; /* 77e4 0aae */ | 281 | __le32 magic; /* 77e4 0aae */ |
| 282 | u32 first_free; /* offset from start of dnode to | 282 | __le32 first_free; /* offset from start of dnode to |
| 283 | first free dir entry */ | 283 | first free dir entry */ |
| 284 | #ifdef __LITTLE_ENDIAN | 284 | #ifdef __LITTLE_ENDIAN |
| 285 | u8 root_dnode: 1; /* Is it root dnode? */ | 285 | u8 root_dnode: 1; /* Is it root dnode? */ |
| @@ -293,14 +293,14 @@ struct dnode { | |||
| 293 | u8 root_dnode: 1; /* Is it root dnode? */ | 293 | u8 root_dnode: 1; /* Is it root dnode? */ |
| 294 | #endif | 294 | #endif |
| 295 | u8 increment_me2[3]; | 295 | u8 increment_me2[3]; |
| 296 | secno up; /* (root dnode) directory's fnode | 296 | __le32 up; /* (root dnode) directory's fnode |
| 297 | (nonroot) parent dnode */ | 297 | (nonroot) parent dnode */ |
| 298 | dnode_secno self; /* pointer to this dnode */ | 298 | __le32 self; /* pointer to this dnode */ |
| 299 | u8 dirent[2028]; /* one or more dirents */ | 299 | u8 dirent[2028]; /* one or more dirents */ |
| 300 | }; | 300 | }; |
| 301 | 301 | ||
| 302 | struct hpfs_dirent { | 302 | struct hpfs_dirent { |
| 303 | u16 length; /* offset to next dirent */ | 303 | __le16 length; /* offset to next dirent */ |
| 304 | 304 | ||
| 305 | #ifdef __LITTLE_ENDIAN | 305 | #ifdef __LITTLE_ENDIAN |
| 306 | u8 first: 1; /* set on phony ^A^A (".") entry */ | 306 | u8 first: 1; /* set on phony ^A^A (".") entry */ |
| @@ -346,12 +346,12 @@ struct hpfs_dirent { | |||
| 346 | u8 read_only: 1; /* dos attrib */ | 346 | u8 read_only: 1; /* dos attrib */ |
| 347 | #endif | 347 | #endif |
| 348 | 348 | ||
| 349 | fnode_secno fnode; /* fnode giving allocation info */ | 349 | __le32 fnode; /* fnode giving allocation info */ |
| 350 | time32_t write_date; /* mtime */ | 350 | __le32 write_date; /* mtime */ |
| 351 | u32 file_size; /* file length, bytes */ | 351 | __le32 file_size; /* file length, bytes */ |
| 352 | time32_t read_date; /* atime */ | 352 | __le32 read_date; /* atime */ |
| 353 | time32_t creation_date; /* ctime */ | 353 | __le32 creation_date; /* ctime */ |
| 354 | u32 ea_size; /* total EA length, bytes */ | 354 | __le32 ea_size; /* total EA length, bytes */ |
| 355 | u8 no_of_acls; /* number of ACL's (low 3 bits) */ | 355 | u8 no_of_acls; /* number of ACL's (low 3 bits) */ |
| 356 | u8 ix; /* code page index (of filename), see | 356 | u8 ix; /* code page index (of filename), see |
| 357 | struct code_page_data */ | 357 | struct code_page_data */ |
| @@ -375,50 +375,36 @@ struct hpfs_dirent { | |||
| 375 | 375 | ||
| 376 | struct bplus_leaf_node | 376 | struct bplus_leaf_node |
| 377 | { | 377 | { |
| 378 | u32 file_secno; /* first file sector in extent */ | 378 | __le32 file_secno; /* first file sector in extent */ |
| 379 | u32 length; /* length, sectors */ | 379 | __le32 length; /* length, sectors */ |
| 380 | secno disk_secno; /* first corresponding disk sector */ | 380 | __le32 disk_secno; /* first corresponding disk sector */ |
| 381 | }; | 381 | }; |
| 382 | 382 | ||
| 383 | struct bplus_internal_node | 383 | struct bplus_internal_node |
| 384 | { | 384 | { |
| 385 | u32 file_secno; /* subtree maps sectors < this */ | 385 | __le32 file_secno; /* subtree maps sectors < this */ |
| 386 | anode_secno down; /* pointer to subtree */ | 386 | __le32 down; /* pointer to subtree */ |
| 387 | }; | 387 | }; |
| 388 | 388 | ||
| 389 | enum { | ||
| 390 | BP_hbff = 1, | ||
| 391 | BP_fnode_parent = 0x20, | ||
| 392 | BP_binary_search = 0x40, | ||
| 393 | BP_internal = 0x80 | ||
| 394 | }; | ||
| 389 | struct bplus_header | 395 | struct bplus_header |
| 390 | { | 396 | { |
| 391 | #ifdef __LITTLE_ENDIAN | 397 | u8 flags; /* bit 0 - high bit of first free entry offset |
| 392 | u8 hbff: 1; /* high bit of first free entry offset */ | 398 | bit 5 - we're pointed to by an fnode, |
| 393 | u8 flag1234: 4; | ||
| 394 | u8 fnode_parent: 1; /* ? we're pointed to by an fnode, | ||
| 395 | the data btree or some ea or the | ||
| 396 | main ea bootage pointer ea_secno */ | ||
| 397 | /* also can get set in fnodes, which | ||
| 398 | may be a chkdsk glitch or may mean | ||
| 399 | this bit is irrelevant in fnodes, | ||
| 400 | or this interpretation is all wet */ | ||
| 401 | u8 binary_search: 1; /* suggest binary search (unused) */ | ||
| 402 | u8 internal: 1; /* 1 -> (internal) tree of anodes | ||
| 403 | 0 -> (leaf) list of extents */ | ||
| 404 | #else | ||
| 405 | u8 internal: 1; /* 1 -> (internal) tree of anodes | ||
| 406 | 0 -> (leaf) list of extents */ | ||
| 407 | u8 binary_search: 1; /* suggest binary search (unused) */ | ||
| 408 | u8 fnode_parent: 1; /* ? we're pointed to by an fnode, | ||
| 409 | the data btree or some ea or the | 399 | the data btree or some ea or the |
| 410 | main ea bootage pointer ea_secno */ | 400 | main ea bootage pointer ea_secno |
| 411 | /* also can get set in fnodes, which | 401 | bit 6 - suggest binary search (unused) |
| 412 | may be a chkdsk glitch or may mean | 402 | bit 7 - 1 -> (internal) tree of anodes |
| 413 | this bit is irrelevant in fnodes, | 403 | 0 -> (leaf) list of extents */ |
| 414 | or this interpretation is all wet */ | ||
| 415 | u8 flag1234: 4; | ||
| 416 | u8 hbff: 1; /* high bit of first free entry offset */ | ||
| 417 | #endif | ||
| 418 | u8 fill[3]; | 404 | u8 fill[3]; |
| 419 | u8 n_free_nodes; /* free nodes in following array */ | 405 | u8 n_free_nodes; /* free nodes in following array */ |
| 420 | u8 n_used_nodes; /* used nodes in following array */ | 406 | u8 n_used_nodes; /* used nodes in following array */ |
| 421 | u16 first_free; /* offset from start of header to | 407 | __le16 first_free; /* offset from start of header to |
| 422 | first free node in array */ | 408 | first free node in array */ |
| 423 | union { | 409 | union { |
| 424 | struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving | 410 | struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving |
| @@ -428,6 +414,16 @@ struct bplus_header | |||
| 428 | } u; | 414 | } u; |
| 429 | }; | 415 | }; |
| 430 | 416 | ||
| 417 | static inline bool bp_internal(struct bplus_header *bp) | ||
| 418 | { | ||
| 419 | return bp->flags & BP_internal; | ||
| 420 | } | ||
| 421 | |||
| 422 | static inline bool bp_fnode_parent(struct bplus_header *bp) | ||
| 423 | { | ||
| 424 | return bp->flags & BP_fnode_parent; | ||
| 425 | } | ||
| 426 | |||
| 431 | /* fnode: root of allocation b+ tree, and EA's */ | 427 | /* fnode: root of allocation b+ tree, and EA's */ |
| 432 | 428 | ||
| 433 | /* Every file and every directory has one fnode, pointed to by the directory | 429 | /* Every file and every directory has one fnode, pointed to by the directory |
| @@ -436,62 +432,56 @@ struct bplus_header | |||
| 436 | 432 | ||
| 437 | #define FNODE_MAGIC 0xf7e40aae | 433 | #define FNODE_MAGIC 0xf7e40aae |
| 438 | 434 | ||
| 435 | enum {FNODE_anode = cpu_to_le16(2), FNODE_dir = cpu_to_le16(256)}; | ||
| 439 | struct fnode | 436 | struct fnode |
| 440 | { | 437 | { |
| 441 | u32 magic; /* f7e4 0aae */ | 438 | __le32 magic; /* f7e4 0aae */ |
| 442 | u32 zero1[2]; /* read history */ | 439 | __le32 zero1[2]; /* read history */ |
| 443 | u8 len, name[15]; /* true length, truncated name */ | 440 | u8 len, name[15]; /* true length, truncated name */ |
| 444 | fnode_secno up; /* pointer to file's directory fnode */ | 441 | __le32 up; /* pointer to file's directory fnode */ |
| 445 | secno acl_size_l; | 442 | __le32 acl_size_l; |
| 446 | secno acl_secno; | 443 | __le32 acl_secno; |
| 447 | u16 acl_size_s; | 444 | __le16 acl_size_s; |
| 448 | u8 acl_anode; | 445 | u8 acl_anode; |
| 449 | u8 zero2; /* history bit count */ | 446 | u8 zero2; /* history bit count */ |
| 450 | u32 ea_size_l; /* length of disk-resident ea's */ | 447 | __le32 ea_size_l; /* length of disk-resident ea's */ |
| 451 | secno ea_secno; /* first sector of disk-resident ea's*/ | 448 | __le32 ea_secno; /* first sector of disk-resident ea's*/ |
| 452 | u16 ea_size_s; /* length of fnode-resident ea's */ | 449 | __le16 ea_size_s; /* length of fnode-resident ea's */ |
| 453 | |||
| 454 | #ifdef __LITTLE_ENDIAN | ||
| 455 | u8 flag0: 1; | ||
| 456 | u8 ea_anode: 1; /* 1 -> ea_secno is an anode */ | ||
| 457 | u8 flag234567: 6; | ||
| 458 | #else | ||
| 459 | u8 flag234567: 6; | ||
| 460 | u8 ea_anode: 1; /* 1 -> ea_secno is an anode */ | ||
| 461 | u8 flag0: 1; | ||
| 462 | #endif | ||
| 463 | 450 | ||
| 464 | #ifdef __LITTLE_ENDIAN | 451 | __le16 flags; /* bit 1 set -> ea_secno is an anode */ |
| 465 | u8 dirflag: 1; /* 1 -> directory. first & only extent | 452 | /* bit 8 set -> directory. first & only extent |
| 466 | points to dnode. */ | ||
| 467 | u8 flag9012345: 7; | ||
| 468 | #else | ||
| 469 | u8 flag9012345: 7; | ||
| 470 | u8 dirflag: 1; /* 1 -> directory. first & only extent | ||
| 471 | points to dnode. */ | 453 | points to dnode. */ |
| 472 | #endif | ||
| 473 | |||
| 474 | struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */ | 454 | struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */ |
| 475 | union { | 455 | union { |
| 476 | struct bplus_leaf_node external[8]; | 456 | struct bplus_leaf_node external[8]; |
| 477 | struct bplus_internal_node internal[12]; | 457 | struct bplus_internal_node internal[12]; |
| 478 | } u; | 458 | } u; |
| 479 | 459 | ||
| 480 | u32 file_size; /* file length, bytes */ | 460 | __le32 file_size; /* file length, bytes */ |
| 481 | u32 n_needea; /* number of EA's with NEEDEA set */ | 461 | __le32 n_needea; /* number of EA's with NEEDEA set */ |
| 482 | u8 user_id[16]; /* unused */ | 462 | u8 user_id[16]; /* unused */ |
| 483 | u16 ea_offs; /* offset from start of fnode | 463 | __le16 ea_offs; /* offset from start of fnode |
| 484 | to first fnode-resident ea */ | 464 | to first fnode-resident ea */ |
| 485 | u8 dasd_limit_treshhold; | 465 | u8 dasd_limit_treshhold; |
| 486 | u8 dasd_limit_delta; | 466 | u8 dasd_limit_delta; |
| 487 | u32 dasd_limit; | 467 | __le32 dasd_limit; |
| 488 | u32 dasd_usage; | 468 | __le32 dasd_usage; |
| 489 | u8 ea[316]; /* zero or more EA's, packed together | 469 | u8 ea[316]; /* zero or more EA's, packed together |
| 490 | with no alignment padding. | 470 | with no alignment padding. |
| 491 | (Do not use this name, get here | 471 | (Do not use this name, get here |
| 492 | via fnode + ea_offs. I think.) */ | 472 | via fnode + ea_offs. I think.) */ |
| 493 | }; | 473 | }; |
| 494 | 474 | ||
| 475 | static inline bool fnode_in_anode(struct fnode *p) | ||
| 476 | { | ||
| 477 | return (p->flags & FNODE_anode) != 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | static inline bool fnode_is_dir(struct fnode *p) | ||
| 481 | { | ||
| 482 | return (p->flags & FNODE_dir) != 0; | ||
| 483 | } | ||
| 484 | |||
| 495 | 485 | ||
| 496 | /* anode: 99.44% pure allocation tree */ | 486 | /* anode: 99.44% pure allocation tree */ |
| 497 | 487 | ||
| @@ -499,9 +489,9 @@ struct fnode | |||
| 499 | 489 | ||
| 500 | struct anode | 490 | struct anode |
| 501 | { | 491 | { |
| 502 | u32 magic; /* 37e4 0aae */ | 492 | __le32 magic; /* 37e4 0aae */ |
| 503 | anode_secno self; /* pointer to this anode */ | 493 | __le32 self; /* pointer to this anode */ |
| 504 | secno up; /* parent anode or fnode */ | 494 | __le32 up; /* parent anode or fnode */ |
| 505 | 495 | ||
| 506 | struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */ | 496 | struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */ |
| 507 | union { | 497 | union { |
| @@ -509,7 +499,7 @@ struct anode | |||
| 509 | struct bplus_internal_node internal[60]; | 499 | struct bplus_internal_node internal[60]; |
| 510 | } u; | 500 | } u; |
| 511 | 501 | ||
| 512 | u32 fill[3]; /* unused */ | 502 | __le32 fill[3]; /* unused */ |
| 513 | }; | 503 | }; |
| 514 | 504 | ||
| 515 | 505 | ||
| @@ -528,32 +518,23 @@ struct anode | |||
| 528 | run, or in multiple runs. Flags in the fnode tell whether the EA list | 518 | run, or in multiple runs. Flags in the fnode tell whether the EA list |
| 529 | is immediate, in a single run, or in multiple runs. */ | 519 | is immediate, in a single run, or in multiple runs. */ |
| 530 | 520 | ||
| 521 | enum {EA_indirect = 1, EA_anode = 2, EA_needea = 128 }; | ||
| 531 | struct extended_attribute | 522 | struct extended_attribute |
| 532 | { | 523 | { |
| 533 | #ifdef __LITTLE_ENDIAN | 524 | u8 flags; /* bit 0 set -> value gives sector number |
| 534 | u8 indirect: 1; /* 1 -> value gives sector number | ||
| 535 | where real value starts */ | 525 | where real value starts */ |
| 536 | u8 anode: 1; /* 1 -> sector is an anode | 526 | /* bit 1 set -> sector is an anode |
| 537 | that points to fragmented value */ | 527 | that points to fragmented value */ |
| 538 | u8 flag23456: 5; | 528 | /* bit 7 set -> required ea */ |
| 539 | u8 needea: 1; /* required ea */ | ||
| 540 | #else | ||
| 541 | u8 needea: 1; /* required ea */ | ||
| 542 | u8 flag23456: 5; | ||
| 543 | u8 anode: 1; /* 1 -> sector is an anode | ||
| 544 | that points to fragmented value */ | ||
| 545 | u8 indirect: 1; /* 1 -> value gives sector number | ||
| 546 | where real value starts */ | ||
| 547 | #endif | ||
| 548 | u8 namelen; /* length of name, bytes */ | 529 | u8 namelen; /* length of name, bytes */ |
| 549 | u8 valuelen_lo; /* length of value, bytes */ | 530 | u8 valuelen_lo; /* length of value, bytes */ |
| 550 | u8 valuelen_hi; /* length of value, bytes */ | 531 | u8 valuelen_hi; /* length of value, bytes */ |
| 551 | u8 name[0]; | 532 | u8 name[]; |
| 552 | /* | 533 | /* |
| 553 | u8 name[namelen]; ascii attrib name | 534 | u8 name[namelen]; ascii attrib name |
| 554 | u8 nul; terminating '\0', not counted | 535 | u8 nul; terminating '\0', not counted |
| 555 | u8 value[valuelen]; value, arbitrary | 536 | u8 value[valuelen]; value, arbitrary |
| 556 | if this.indirect, valuelen is 8 and the value is | 537 | if this.flags & 1, valuelen is 8 and the value is |
| 557 | u32 length; real length of value, bytes | 538 | u32 length; real length of value, bytes |
| 558 | secno secno; sector address where it starts | 539 | secno secno; sector address where it starts |
| 559 | if this.anode, the above sector number is the root of an anode tree | 540 | if this.anode, the above sector number is the root of an anode tree |
| @@ -561,6 +542,16 @@ struct extended_attribute | |||
| 561 | */ | 542 | */ |
| 562 | }; | 543 | }; |
| 563 | 544 | ||
| 545 | static inline bool ea_indirect(struct extended_attribute *ea) | ||
| 546 | { | ||
| 547 | return ea->flags & EA_indirect; | ||
| 548 | } | ||
| 549 | |||
| 550 | static inline bool ea_in_anode(struct extended_attribute *ea) | ||
| 551 | { | ||
| 552 | return ea->flags & EA_anode; | ||
| 553 | } | ||
| 554 | |||
| 564 | /* | 555 | /* |
| 565 | Local Variables: | 556 | Local Variables: |
| 566 | comment-column: 40 | 557 | comment-column: 40 |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 6d2d5008fa43..c07ef1f1ced6 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
| @@ -75,7 +75,7 @@ struct hpfs_sb_info { | |||
| 75 | unsigned char *sb_cp_table; /* code page tables: */ | 75 | unsigned char *sb_cp_table; /* code page tables: */ |
| 76 | /* 128 bytes uppercasing table & */ | 76 | /* 128 bytes uppercasing table & */ |
| 77 | /* 128 bytes lowercasing table */ | 77 | /* 128 bytes lowercasing table */ |
| 78 | unsigned *sb_bmp_dir; /* main bitmap directory */ | 78 | __le32 *sb_bmp_dir; /* main bitmap directory */ |
| 79 | unsigned sb_c_bitmap; /* current bitmap */ | 79 | unsigned sb_c_bitmap; /* current bitmap */ |
| 80 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ | 80 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ |
| 81 | int sb_timeshift; | 81 | int sb_timeshift; |
| @@ -93,7 +93,7 @@ struct quad_buffer_head { | |||
| 93 | static inline dnode_secno de_down_pointer (struct hpfs_dirent *de) | 93 | static inline dnode_secno de_down_pointer (struct hpfs_dirent *de) |
| 94 | { | 94 | { |
| 95 | CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n")); | 95 | CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n")); |
| 96 | return le32_to_cpu(*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4)); | 96 | return le32_to_cpu(*(__le32 *) ((void *) de + le16_to_cpu(de->length) - 4)); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | /* The first dir entry in a dnode */ | 99 | /* The first dir entry in a dnode */ |
| @@ -141,12 +141,12 @@ static inline struct extended_attribute *next_ea(struct extended_attribute *ea) | |||
| 141 | 141 | ||
| 142 | static inline secno ea_sec(struct extended_attribute *ea) | 142 | static inline secno ea_sec(struct extended_attribute *ea) |
| 143 | { | 143 | { |
| 144 | return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen))); | 144 | return le32_to_cpu(get_unaligned((__le32 *)((char *)ea + 9 + ea->namelen))); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | static inline secno ea_len(struct extended_attribute *ea) | 147 | static inline secno ea_len(struct extended_attribute *ea) |
| 148 | { | 148 | { |
| 149 | return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen))); | 149 | return le32_to_cpu(get_unaligned((__le32 *)((char *)ea + 5 + ea->namelen))); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static inline char *ea_data(struct extended_attribute *ea) | 152 | static inline char *ea_data(struct extended_attribute *ea) |
| @@ -171,7 +171,7 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src) | |||
| 171 | dst->not_8x3 = n; | 171 | dst->not_8x3 = n; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | static inline unsigned tstbits(u32 *bmp, unsigned b, unsigned n) | 174 | static inline unsigned tstbits(__le32 *bmp, unsigned b, unsigned n) |
| 175 | { | 175 | { |
| 176 | int i; | 176 | int i; |
| 177 | if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n; | 177 | if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n; |
| @@ -268,10 +268,10 @@ void hpfs_evict_inode(struct inode *); | |||
| 268 | 268 | ||
| 269 | /* map.c */ | 269 | /* map.c */ |
| 270 | 270 | ||
| 271 | unsigned *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *); | 271 | __le32 *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *); |
| 272 | unsigned *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *); | 272 | __le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *); |
| 273 | unsigned char *hpfs_load_code_page(struct super_block *, secno); | 273 | unsigned char *hpfs_load_code_page(struct super_block *, secno); |
| 274 | secno *hpfs_load_bitmap_directory(struct super_block *, secno bmp); | 274 | __le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp); |
| 275 | struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **); | 275 | struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **); |
| 276 | struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **); | 276 | struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **); |
| 277 | struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *); | 277 | struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *); |
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index b43066cbdc6a..ed671e0ea784 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c | |||
| @@ -110,7 +110,7 @@ void hpfs_read_inode(struct inode *i) | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | if (fnode->dirflag) { | 113 | if (fnode_is_dir(fnode)) { |
| 114 | int n_dnodes, n_subdirs; | 114 | int n_dnodes, n_subdirs; |
| 115 | i->i_mode |= S_IFDIR; | 115 | i->i_mode |= S_IFDIR; |
| 116 | i->i_op = &hpfs_dir_iops; | 116 | i->i_op = &hpfs_dir_iops; |
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index a790821366a7..4acb19d78359 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c | |||
| @@ -8,12 +8,12 @@ | |||
| 8 | 8 | ||
| 9 | #include "hpfs_fn.h" | 9 | #include "hpfs_fn.h" |
| 10 | 10 | ||
| 11 | unsigned *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh) | 11 | __le32 *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh) |
| 12 | { | 12 | { |
| 13 | return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0); | 13 | return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, | 16 | __le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, |
| 17 | struct quad_buffer_head *qbh, char *id) | 17 | struct quad_buffer_head *qbh, char *id) |
| 18 | { | 18 | { |
| 19 | secno sec; | 19 | secno sec; |
| @@ -89,18 +89,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) | |||
| 89 | return cp_table; | 89 | return cp_table; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | secno *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) | 92 | __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) |
| 93 | { | 93 | { |
| 94 | struct buffer_head *bh; | 94 | struct buffer_head *bh; |
| 95 | int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21; | 95 | int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21; |
| 96 | int i; | 96 | int i; |
| 97 | secno *b; | 97 | __le32 *b; |
| 98 | if (!(b = kmalloc(n * 512, GFP_KERNEL))) { | 98 | if (!(b = kmalloc(n * 512, GFP_KERNEL))) { |
| 99 | printk("HPFS: can't allocate memory for bitmap directory\n"); | 99 | printk("HPFS: can't allocate memory for bitmap directory\n"); |
| 100 | return NULL; | 100 | return NULL; |
| 101 | } | 101 | } |
| 102 | for (i=0;i<n;i++) { | 102 | for (i=0;i<n;i++) { |
| 103 | secno *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1); | 103 | __le32 *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1); |
| 104 | if (!d) { | 104 | if (!d) { |
| 105 | kfree(b); | 105 | kfree(b); |
| 106 | return NULL; | 106 | return NULL; |
| @@ -130,16 +130,16 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea | |||
| 130 | (unsigned long)ino); | 130 | (unsigned long)ino); |
| 131 | goto bail; | 131 | goto bail; |
| 132 | } | 132 | } |
| 133 | if (!fnode->dirflag) { | 133 | if (!fnode_is_dir(fnode)) { |
| 134 | if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes != | 134 | if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes != |
| 135 | (fnode->btree.internal ? 12 : 8)) { | 135 | (bp_internal(&fnode->btree) ? 12 : 8)) { |
| 136 | hpfs_error(s, | 136 | hpfs_error(s, |
| 137 | "bad number of nodes in fnode %08lx", | 137 | "bad number of nodes in fnode %08lx", |
| 138 | (unsigned long)ino); | 138 | (unsigned long)ino); |
| 139 | goto bail; | 139 | goto bail; |
| 140 | } | 140 | } |
| 141 | if (le16_to_cpu(fnode->btree.first_free) != | 141 | if (le16_to_cpu(fnode->btree.first_free) != |
| 142 | 8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { | 142 | 8 + fnode->btree.n_used_nodes * (bp_internal(&fnode->btree) ? 8 : 12)) { |
| 143 | hpfs_error(s, | 143 | hpfs_error(s, |
| 144 | "bad first_free pointer in fnode %08lx", | 144 | "bad first_free pointer in fnode %08lx", |
| 145 | (unsigned long)ino); | 145 | (unsigned long)ino); |
| @@ -187,12 +187,12 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff | |||
| 187 | goto bail; | 187 | goto bail; |
| 188 | } | 188 | } |
| 189 | if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != | 189 | if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != |
| 190 | (anode->btree.internal ? 60 : 40)) { | 190 | (bp_internal(&anode->btree) ? 60 : 40)) { |
| 191 | hpfs_error(s, "bad number of nodes in anode %08x", ano); | 191 | hpfs_error(s, "bad number of nodes in anode %08x", ano); |
| 192 | goto bail; | 192 | goto bail; |
| 193 | } | 193 | } |
| 194 | if (le16_to_cpu(anode->btree.first_free) != | 194 | if (le16_to_cpu(anode->btree.first_free) != |
| 195 | 8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { | 195 | 8 + anode->btree.n_used_nodes * (bp_internal(&anode->btree) ? 8 : 12)) { |
| 196 | hpfs_error(s, "bad first_free pointer in anode %08x", ano); | 196 | hpfs_error(s, "bad first_free pointer in anode %08x", ano); |
| 197 | goto bail; | 197 | goto bail; |
| 198 | } | 198 | } |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 30dd7b10b507..9083ef8af58c 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
| @@ -70,7 +70,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 70 | fnode->len = len; | 70 | fnode->len = len; |
| 71 | memcpy(fnode->name, name, len > 15 ? 15 : len); | 71 | memcpy(fnode->name, name, len > 15 ? 15 : len); |
| 72 | fnode->up = cpu_to_le32(dir->i_ino); | 72 | fnode->up = cpu_to_le32(dir->i_ino); |
| 73 | fnode->dirflag = 1; | 73 | fnode->flags |= FNODE_dir; |
| 74 | fnode->btree.n_free_nodes = 7; | 74 | fnode->btree.n_free_nodes = 7; |
| 75 | fnode->btree.n_used_nodes = 1; | 75 | fnode->btree.n_used_nodes = 1; |
| 76 | fnode->btree.first_free = cpu_to_le16(0x14); | 76 | fnode->btree.first_free = cpu_to_le16(0x14); |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 54f6eccb79d9..706a12c083ea 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
| @@ -572,7 +572,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
| 572 | mark_buffer_dirty(bh2); | 572 | mark_buffer_dirty(bh2); |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | if (le32_to_cpu(spareblock->hotfixes_used) || le32_to_cpu(spareblock->n_spares_used)) { | 575 | if (spareblock->hotfixes_used || spareblock->n_spares_used) { |
| 576 | if (errs >= 2) { | 576 | if (errs >= 2) { |
| 577 | printk("HPFS: Hotfixes not supported here, try chkdsk\n"); | 577 | printk("HPFS: Hotfixes not supported here, try chkdsk\n"); |
| 578 | mark_dirty(s, 0); | 578 | mark_dirty(s, 0); |
| @@ -645,7 +645,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
| 645 | root->i_mtime.tv_nsec = 0; | 645 | root->i_mtime.tv_nsec = 0; |
| 646 | root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date)); | 646 | root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date)); |
| 647 | root->i_ctime.tv_nsec = 0; | 647 | root->i_ctime.tv_nsec = 0; |
| 648 | hpfs_i(root)->i_ea_size = le16_to_cpu(de->ea_size); | 648 | hpfs_i(root)->i_ea_size = le32_to_cpu(de->ea_size); |
| 649 | hpfs_i(root)->i_parent_dir = root->i_ino; | 649 | hpfs_i(root)->i_parent_dir = root->i_ino; |
| 650 | if (root->i_size == -1) | 650 | if (root->i_size == -1) |
| 651 | root->i_size = 2048; | 651 | root->i_size = 2048; |
diff --git a/fs/inode.c b/fs/inode.c index c474c1d7062b..c99163b1b310 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1487,10 +1487,30 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, | |||
| 1487 | return 0; | 1487 | return 0; |
| 1488 | } | 1488 | } |
| 1489 | 1489 | ||
| 1490 | /* | ||
| 1491 | * This does the actual work of updating an inodes time or version. Must have | ||
| 1492 | * had called mnt_want_write() before calling this. | ||
| 1493 | */ | ||
| 1494 | static int update_time(struct inode *inode, struct timespec *time, int flags) | ||
| 1495 | { | ||
| 1496 | if (inode->i_op->update_time) | ||
| 1497 | return inode->i_op->update_time(inode, time, flags); | ||
| 1498 | |||
| 1499 | if (flags & S_ATIME) | ||
| 1500 | inode->i_atime = *time; | ||
| 1501 | if (flags & S_VERSION) | ||
| 1502 | inode_inc_iversion(inode); | ||
| 1503 | if (flags & S_CTIME) | ||
| 1504 | inode->i_ctime = *time; | ||
| 1505 | if (flags & S_MTIME) | ||
| 1506 | inode->i_mtime = *time; | ||
| 1507 | mark_inode_dirty_sync(inode); | ||
| 1508 | return 0; | ||
| 1509 | } | ||
| 1510 | |||
| 1490 | /** | 1511 | /** |
| 1491 | * touch_atime - update the access time | 1512 | * touch_atime - update the access time |
| 1492 | * @mnt: mount the inode is accessed on | 1513 | * @path: the &struct path to update |
| 1493 | * @dentry: dentry accessed | ||
| 1494 | * | 1514 | * |
| 1495 | * Update the accessed time on an inode and mark it for writeback. | 1515 | * Update the accessed time on an inode and mark it for writeback. |
| 1496 | * This function automatically handles read only file systems and media, | 1516 | * This function automatically handles read only file systems and media, |
| @@ -1525,12 +1545,83 @@ void touch_atime(struct path *path) | |||
| 1525 | if (mnt_want_write(mnt)) | 1545 | if (mnt_want_write(mnt)) |
| 1526 | return; | 1546 | return; |
| 1527 | 1547 | ||
| 1528 | inode->i_atime = now; | 1548 | /* |
| 1529 | mark_inode_dirty_sync(inode); | 1549 | * File systems can error out when updating inodes if they need to |
| 1550 | * allocate new space to modify an inode (such is the case for | ||
| 1551 | * Btrfs), but since we touch atime while walking down the path we | ||
| 1552 | * really don't care if we failed to update the atime of the file, | ||
| 1553 | * so just ignore the return value. | ||
| 1554 | */ | ||
| 1555 | update_time(inode, &now, S_ATIME); | ||
| 1530 | mnt_drop_write(mnt); | 1556 | mnt_drop_write(mnt); |
| 1531 | } | 1557 | } |
| 1532 | EXPORT_SYMBOL(touch_atime); | 1558 | EXPORT_SYMBOL(touch_atime); |
| 1533 | 1559 | ||
| 1560 | /* | ||
| 1561 | * The logic we want is | ||
| 1562 | * | ||
| 1563 | * if suid or (sgid and xgrp) | ||
| 1564 | * remove privs | ||
| 1565 | */ | ||
| 1566 | int should_remove_suid(struct dentry *dentry) | ||
| 1567 | { | ||
| 1568 | umode_t mode = dentry->d_inode->i_mode; | ||
| 1569 | int kill = 0; | ||
| 1570 | |||
| 1571 | /* suid always must be killed */ | ||
| 1572 | if (unlikely(mode & S_ISUID)) | ||
| 1573 | kill = ATTR_KILL_SUID; | ||
| 1574 | |||
| 1575 | /* | ||
| 1576 | * sgid without any exec bits is just a mandatory locking mark; leave | ||
| 1577 | * it alone. If some exec bits are set, it's a real sgid; kill it. | ||
| 1578 | */ | ||
| 1579 | if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) | ||
| 1580 | kill |= ATTR_KILL_SGID; | ||
| 1581 | |||
| 1582 | if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode))) | ||
| 1583 | return kill; | ||
| 1584 | |||
| 1585 | return 0; | ||
| 1586 | } | ||
| 1587 | EXPORT_SYMBOL(should_remove_suid); | ||
| 1588 | |||
| 1589 | static int __remove_suid(struct dentry *dentry, int kill) | ||
| 1590 | { | ||
| 1591 | struct iattr newattrs; | ||
| 1592 | |||
| 1593 | newattrs.ia_valid = ATTR_FORCE | kill; | ||
| 1594 | return notify_change(dentry, &newattrs); | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | int file_remove_suid(struct file *file) | ||
| 1598 | { | ||
| 1599 | struct dentry *dentry = file->f_path.dentry; | ||
| 1600 | struct inode *inode = dentry->d_inode; | ||
| 1601 | int killsuid; | ||
| 1602 | int killpriv; | ||
| 1603 | int error = 0; | ||
| 1604 | |||
| 1605 | /* Fast path for nothing security related */ | ||
| 1606 | if (IS_NOSEC(inode)) | ||
| 1607 | return 0; | ||
| 1608 | |||
| 1609 | killsuid = should_remove_suid(dentry); | ||
| 1610 | killpriv = security_inode_need_killpriv(dentry); | ||
| 1611 | |||
| 1612 | if (killpriv < 0) | ||
| 1613 | return killpriv; | ||
| 1614 | if (killpriv) | ||
| 1615 | error = security_inode_killpriv(dentry); | ||
| 1616 | if (!error && killsuid) | ||
| 1617 | error = __remove_suid(dentry, killsuid); | ||
| 1618 | if (!error && (inode->i_sb->s_flags & MS_NOSEC)) | ||
| 1619 | inode->i_flags |= S_NOSEC; | ||
| 1620 | |||
| 1621 | return error; | ||
| 1622 | } | ||
| 1623 | EXPORT_SYMBOL(file_remove_suid); | ||
| 1624 | |||
| 1534 | /** | 1625 | /** |
| 1535 | * file_update_time - update mtime and ctime time | 1626 | * file_update_time - update mtime and ctime time |
| 1536 | * @file: file accessed | 1627 | * @file: file accessed |
| @@ -1540,18 +1631,20 @@ EXPORT_SYMBOL(touch_atime); | |||
| 1540 | * usage in the file write path of filesystems, and filesystems may | 1631 | * usage in the file write path of filesystems, and filesystems may |
| 1541 | * choose to explicitly ignore update via this function with the | 1632 | * choose to explicitly ignore update via this function with the |
| 1542 | * S_NOCMTIME inode flag, e.g. for network filesystem where these | 1633 | * S_NOCMTIME inode flag, e.g. for network filesystem where these |
| 1543 | * timestamps are handled by the server. | 1634 | * timestamps are handled by the server. This can return an error for |
| 1635 | * file systems who need to allocate space in order to update an inode. | ||
| 1544 | */ | 1636 | */ |
| 1545 | 1637 | ||
| 1546 | void file_update_time(struct file *file) | 1638 | int file_update_time(struct file *file) |
| 1547 | { | 1639 | { |
| 1548 | struct inode *inode = file->f_path.dentry->d_inode; | 1640 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1549 | struct timespec now; | 1641 | struct timespec now; |
| 1550 | enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; | 1642 | int sync_it = 0; |
| 1643 | int ret; | ||
| 1551 | 1644 | ||
| 1552 | /* First try to exhaust all avenues to not sync */ | 1645 | /* First try to exhaust all avenues to not sync */ |
| 1553 | if (IS_NOCMTIME(inode)) | 1646 | if (IS_NOCMTIME(inode)) |
| 1554 | return; | 1647 | return 0; |
| 1555 | 1648 | ||
| 1556 | now = current_fs_time(inode->i_sb); | 1649 | now = current_fs_time(inode->i_sb); |
| 1557 | if (!timespec_equal(&inode->i_mtime, &now)) | 1650 | if (!timespec_equal(&inode->i_mtime, &now)) |
| @@ -1564,21 +1657,16 @@ void file_update_time(struct file *file) | |||
| 1564 | sync_it |= S_VERSION; | 1657 | sync_it |= S_VERSION; |
| 1565 | 1658 | ||
| 1566 | if (!sync_it) | 1659 | if (!sync_it) |
| 1567 | return; | 1660 | return 0; |
| 1568 | 1661 | ||
| 1569 | /* Finally allowed to write? Takes lock. */ | 1662 | /* Finally allowed to write? Takes lock. */ |
| 1570 | if (mnt_want_write_file(file)) | 1663 | if (mnt_want_write_file(file)) |
| 1571 | return; | 1664 | return 0; |
| 1572 | 1665 | ||
| 1573 | /* Only change inode inside the lock region */ | 1666 | ret = update_time(inode, &now, sync_it); |
| 1574 | if (sync_it & S_VERSION) | ||
| 1575 | inode_inc_iversion(inode); | ||
| 1576 | if (sync_it & S_CTIME) | ||
| 1577 | inode->i_ctime = now; | ||
| 1578 | if (sync_it & S_MTIME) | ||
| 1579 | inode->i_mtime = now; | ||
| 1580 | mark_inode_dirty_sync(inode); | ||
| 1581 | mnt_drop_write_file(file); | 1667 | mnt_drop_write_file(file); |
| 1668 | |||
| 1669 | return ret; | ||
| 1582 | } | 1670 | } |
| 1583 | EXPORT_SYMBOL(file_update_time); | 1671 | EXPORT_SYMBOL(file_update_time); |
| 1584 | 1672 | ||
diff --git a/fs/internal.h b/fs/internal.h index 9962c59ba280..18bc216ea09d 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
| @@ -56,7 +56,7 @@ extern int sb_prepare_remount_readonly(struct super_block *); | |||
| 56 | 56 | ||
| 57 | extern void __init mnt_init(void); | 57 | extern void __init mnt_init(void); |
| 58 | 58 | ||
| 59 | DECLARE_BRLOCK(vfsmount_lock); | 59 | extern struct lglock vfsmount_lock; |
| 60 | 60 | ||
| 61 | 61 | ||
| 62 | /* | 62 | /* |
| @@ -100,6 +100,7 @@ extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, | |||
| 100 | 100 | ||
| 101 | extern long do_handle_open(int mountdirfd, | 101 | extern long do_handle_open(int mountdirfd, |
| 102 | struct file_handle __user *ufh, int open_flag); | 102 | struct file_handle __user *ufh, int open_flag); |
| 103 | extern int open_check_o_direct(struct file *f); | ||
| 103 | 104 | ||
| 104 | /* | 105 | /* |
| 105 | * inode.c | 106 | * inode.c |
diff --git a/fs/isofs/export.c b/fs/isofs/export.c index dd4687ff30d0..aa4356d09eee 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c | |||
| @@ -107,12 +107,11 @@ static struct dentry *isofs_export_get_parent(struct dentry *child) | |||
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static int | 109 | static int |
| 110 | isofs_export_encode_fh(struct dentry *dentry, | 110 | isofs_export_encode_fh(struct inode *inode, |
| 111 | __u32 *fh32, | 111 | __u32 *fh32, |
| 112 | int *max_len, | 112 | int *max_len, |
| 113 | int connectable) | 113 | struct inode *parent) |
| 114 | { | 114 | { |
| 115 | struct inode * inode = dentry->d_inode; | ||
| 116 | struct iso_inode_info * ei = ISOFS_I(inode); | 115 | struct iso_inode_info * ei = ISOFS_I(inode); |
| 117 | int len = *max_len; | 116 | int len = *max_len; |
| 118 | int type = 1; | 117 | int type = 1; |
| @@ -124,7 +123,7 @@ isofs_export_encode_fh(struct dentry *dentry, | |||
| 124 | * offset of the inode and the upper 16 bits of fh32[1] to | 123 | * offset of the inode and the upper 16 bits of fh32[1] to |
| 125 | * hold the offset of the parent. | 124 | * hold the offset of the parent. |
| 126 | */ | 125 | */ |
| 127 | if (connectable && (len < 5)) { | 126 | if (parent && (len < 5)) { |
| 128 | *max_len = 5; | 127 | *max_len = 5; |
| 129 | return 255; | 128 | return 255; |
| 130 | } else if (len < 3) { | 129 | } else if (len < 3) { |
| @@ -136,16 +135,12 @@ isofs_export_encode_fh(struct dentry *dentry, | |||
| 136 | fh32[0] = ei->i_iget5_block; | 135 | fh32[0] = ei->i_iget5_block; |
| 137 | fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */ | 136 | fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */ |
| 138 | fh32[2] = inode->i_generation; | 137 | fh32[2] = inode->i_generation; |
| 139 | if (connectable && !S_ISDIR(inode->i_mode)) { | 138 | if (parent) { |
| 140 | struct inode *parent; | ||
| 141 | struct iso_inode_info *eparent; | 139 | struct iso_inode_info *eparent; |
| 142 | spin_lock(&dentry->d_lock); | ||
| 143 | parent = dentry->d_parent->d_inode; | ||
| 144 | eparent = ISOFS_I(parent); | 140 | eparent = ISOFS_I(parent); |
| 145 | fh32[3] = eparent->i_iget5_block; | 141 | fh32[3] = eparent->i_iget5_block; |
| 146 | fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */ | 142 | fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */ |
| 147 | fh32[4] = parent->i_generation; | 143 | fh32[4] = parent->i_generation; |
| 148 | spin_unlock(&dentry->d_lock); | ||
| 149 | len = 5; | 144 | len = 5; |
| 150 | type = 2; | 145 | type = 2; |
| 151 | } | 146 | } |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 55a0c1dceadf..44dca1f041c5 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
| @@ -126,6 +126,10 @@ struct jffs2_sb_info { | |||
| 126 | struct jffs2_inodirty *wbuf_inodes; | 126 | struct jffs2_inodirty *wbuf_inodes; |
| 127 | struct rw_semaphore wbuf_sem; /* Protects the write buffer */ | 127 | struct rw_semaphore wbuf_sem; /* Protects the write buffer */ |
| 128 | 128 | ||
| 129 | struct delayed_work wbuf_dwork; /* write-buffer write-out work */ | ||
| 130 | int wbuf_queued; /* non-zero delayed work is queued */ | ||
| 131 | spinlock_t wbuf_dwork_lock; /* protects wbuf_dwork and and wbuf_queued */ | ||
| 132 | |||
| 129 | unsigned char *oobbuf; | 133 | unsigned char *oobbuf; |
| 130 | int oobavail; /* How many bytes are available for JFFS2 in OOB */ | 134 | int oobavail; /* How many bytes are available for JFFS2 in OOB */ |
| 131 | #endif | 135 | #endif |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 1cd3aec9d9ae..bcd983d7e7f9 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
| @@ -95,6 +95,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
| 95 | #define jffs2_ubivol(c) (0) | 95 | #define jffs2_ubivol(c) (0) |
| 96 | #define jffs2_ubivol_setup(c) (0) | 96 | #define jffs2_ubivol_setup(c) (0) |
| 97 | #define jffs2_ubivol_cleanup(c) do {} while (0) | 97 | #define jffs2_ubivol_cleanup(c) do {} while (0) |
| 98 | #define jffs2_dirty_trigger(c) do {} while (0) | ||
| 98 | 99 | ||
| 99 | #else /* NAND and/or ECC'd NOR support present */ | 100 | #else /* NAND and/or ECC'd NOR support present */ |
| 100 | 101 | ||
| @@ -135,14 +136,10 @@ void jffs2_ubivol_cleanup(struct jffs2_sb_info *c); | |||
| 135 | #define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE)) | 136 | #define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE)) |
| 136 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c); | 137 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c); |
| 137 | void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); | 138 | void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); |
| 139 | void jffs2_dirty_trigger(struct jffs2_sb_info *c); | ||
| 138 | 140 | ||
| 139 | #endif /* WRITEBUFFER */ | 141 | #endif /* WRITEBUFFER */ |
| 140 | 142 | ||
| 141 | static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c) | ||
| 142 | { | ||
| 143 | OFNI_BS_2SFFJ(c)->s_dirt = 1; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* background.c */ | 143 | /* background.c */ |
| 147 | int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); | 144 | int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); |
| 148 | void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); | 145 | void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index f9916f312bd8..bc586f204228 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
| @@ -63,21 +63,6 @@ static void jffs2_i_init_once(void *foo) | |||
| 63 | inode_init_once(&f->vfs_inode); | 63 | inode_init_once(&f->vfs_inode); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | static void jffs2_write_super(struct super_block *sb) | ||
| 67 | { | ||
| 68 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | ||
| 69 | |||
| 70 | lock_super(sb); | ||
| 71 | sb->s_dirt = 0; | ||
| 72 | |||
| 73 | if (!(sb->s_flags & MS_RDONLY)) { | ||
| 74 | jffs2_dbg(1, "%s()\n", __func__); | ||
| 75 | jffs2_flush_wbuf_gc(c, 0); | ||
| 76 | } | ||
| 77 | |||
| 78 | unlock_super(sb); | ||
| 79 | } | ||
| 80 | |||
| 81 | static const char *jffs2_compr_name(unsigned int compr) | 66 | static const char *jffs2_compr_name(unsigned int compr) |
| 82 | { | 67 | { |
| 83 | switch (compr) { | 68 | switch (compr) { |
| @@ -113,8 +98,6 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) | |||
| 113 | { | 98 | { |
| 114 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 99 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
| 115 | 100 | ||
| 116 | jffs2_write_super(sb); | ||
| 117 | |||
| 118 | mutex_lock(&c->alloc_sem); | 101 | mutex_lock(&c->alloc_sem); |
| 119 | jffs2_flush_wbuf_pad(c); | 102 | jffs2_flush_wbuf_pad(c); |
| 120 | mutex_unlock(&c->alloc_sem); | 103 | mutex_unlock(&c->alloc_sem); |
| @@ -251,7 +234,6 @@ static const struct super_operations jffs2_super_operations = | |||
| 251 | .alloc_inode = jffs2_alloc_inode, | 234 | .alloc_inode = jffs2_alloc_inode, |
| 252 | .destroy_inode =jffs2_destroy_inode, | 235 | .destroy_inode =jffs2_destroy_inode, |
| 253 | .put_super = jffs2_put_super, | 236 | .put_super = jffs2_put_super, |
| 254 | .write_super = jffs2_write_super, | ||
| 255 | .statfs = jffs2_statfs, | 237 | .statfs = jffs2_statfs, |
| 256 | .remount_fs = jffs2_remount_fs, | 238 | .remount_fs = jffs2_remount_fs, |
| 257 | .evict_inode = jffs2_evict_inode, | 239 | .evict_inode = jffs2_evict_inode, |
| @@ -319,9 +301,6 @@ static void jffs2_put_super (struct super_block *sb) | |||
| 319 | 301 | ||
| 320 | jffs2_dbg(2, "%s()\n", __func__); | 302 | jffs2_dbg(2, "%s()\n", __func__); |
| 321 | 303 | ||
| 322 | if (sb->s_dirt) | ||
| 323 | jffs2_write_super(sb); | ||
| 324 | |||
| 325 | mutex_lock(&c->alloc_sem); | 304 | mutex_lock(&c->alloc_sem); |
| 326 | jffs2_flush_wbuf_pad(c); | 305 | jffs2_flush_wbuf_pad(c); |
| 327 | mutex_unlock(&c->alloc_sem); | 306 | mutex_unlock(&c->alloc_sem); |
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 74d9be19df3f..6f4529d3697f 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/mtd/nand.h> | 20 | #include <linux/mtd/nand.h> |
| 21 | #include <linux/jiffies.h> | 21 | #include <linux/jiffies.h> |
| 22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
| 23 | #include <linux/writeback.h> | ||
| 23 | 24 | ||
| 24 | #include "nodelist.h" | 25 | #include "nodelist.h" |
| 25 | 26 | ||
| @@ -85,7 +86,7 @@ static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino) | |||
| 85 | { | 86 | { |
| 86 | struct jffs2_inodirty *new; | 87 | struct jffs2_inodirty *new; |
| 87 | 88 | ||
| 88 | /* Mark the superblock dirty so that kupdated will flush... */ | 89 | /* Schedule delayed write-buffer write-out */ |
| 89 | jffs2_dirty_trigger(c); | 90 | jffs2_dirty_trigger(c); |
| 90 | 91 | ||
| 91 | if (jffs2_wbuf_pending_for_ino(c, ino)) | 92 | if (jffs2_wbuf_pending_for_ino(c, ino)) |
| @@ -1148,6 +1149,47 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * | |||
| 1148 | return 1; | 1149 | return 1; |
| 1149 | } | 1150 | } |
| 1150 | 1151 | ||
| 1152 | static struct jffs2_sb_info *work_to_sb(struct work_struct *work) | ||
| 1153 | { | ||
| 1154 | struct delayed_work *dwork; | ||
| 1155 | |||
| 1156 | dwork = container_of(work, struct delayed_work, work); | ||
| 1157 | return container_of(dwork, struct jffs2_sb_info, wbuf_dwork); | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | static void delayed_wbuf_sync(struct work_struct *work) | ||
| 1161 | { | ||
| 1162 | struct jffs2_sb_info *c = work_to_sb(work); | ||
| 1163 | struct super_block *sb = OFNI_BS_2SFFJ(c); | ||
| 1164 | |||
| 1165 | spin_lock(&c->wbuf_dwork_lock); | ||
| 1166 | c->wbuf_queued = 0; | ||
| 1167 | spin_unlock(&c->wbuf_dwork_lock); | ||
| 1168 | |||
| 1169 | if (!(sb->s_flags & MS_RDONLY)) { | ||
| 1170 | jffs2_dbg(1, "%s()\n", __func__); | ||
| 1171 | jffs2_flush_wbuf_gc(c, 0); | ||
| 1172 | } | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | void jffs2_dirty_trigger(struct jffs2_sb_info *c) | ||
| 1176 | { | ||
| 1177 | struct super_block *sb = OFNI_BS_2SFFJ(c); | ||
| 1178 | unsigned long delay; | ||
| 1179 | |||
| 1180 | if (sb->s_flags & MS_RDONLY) | ||
| 1181 | return; | ||
| 1182 | |||
| 1183 | spin_lock(&c->wbuf_dwork_lock); | ||
| 1184 | if (!c->wbuf_queued) { | ||
| 1185 | jffs2_dbg(1, "%s()\n", __func__); | ||
| 1186 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
| 1187 | queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay); | ||
| 1188 | c->wbuf_queued = 1; | ||
| 1189 | } | ||
| 1190 | spin_unlock(&c->wbuf_dwork_lock); | ||
| 1191 | } | ||
| 1192 | |||
| 1151 | int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | 1193 | int jffs2_nand_flash_setup(struct jffs2_sb_info *c) |
| 1152 | { | 1194 | { |
| 1153 | struct nand_ecclayout *oinfo = c->mtd->ecclayout; | 1195 | struct nand_ecclayout *oinfo = c->mtd->ecclayout; |
| @@ -1169,6 +1211,8 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | |||
| 1169 | 1211 | ||
| 1170 | /* Initialise write buffer */ | 1212 | /* Initialise write buffer */ |
| 1171 | init_rwsem(&c->wbuf_sem); | 1213 | init_rwsem(&c->wbuf_sem); |
| 1214 | spin_lock_init(&c->wbuf_dwork_lock); | ||
| 1215 | INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); | ||
| 1172 | c->wbuf_pagesize = c->mtd->writesize; | 1216 | c->wbuf_pagesize = c->mtd->writesize; |
| 1173 | c->wbuf_ofs = 0xFFFFFFFF; | 1217 | c->wbuf_ofs = 0xFFFFFFFF; |
| 1174 | 1218 | ||
| @@ -1207,8 +1251,8 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { | |||
| 1207 | 1251 | ||
| 1208 | /* Initialize write buffer */ | 1252 | /* Initialize write buffer */ |
| 1209 | init_rwsem(&c->wbuf_sem); | 1253 | init_rwsem(&c->wbuf_sem); |
| 1210 | 1254 | spin_lock_init(&c->wbuf_dwork_lock); | |
| 1211 | 1255 | INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); | |
| 1212 | c->wbuf_pagesize = c->mtd->erasesize; | 1256 | c->wbuf_pagesize = c->mtd->erasesize; |
| 1213 | 1257 | ||
| 1214 | /* Find a suitable c->sector_size | 1258 | /* Find a suitable c->sector_size |
| @@ -1267,6 +1311,9 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { | |||
| 1267 | 1311 | ||
| 1268 | /* Initialize write buffer */ | 1312 | /* Initialize write buffer */ |
| 1269 | init_rwsem(&c->wbuf_sem); | 1313 | init_rwsem(&c->wbuf_sem); |
| 1314 | spin_lock_init(&c->wbuf_dwork_lock); | ||
| 1315 | INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); | ||
| 1316 | |||
| 1270 | c->wbuf_pagesize = c->mtd->writesize; | 1317 | c->wbuf_pagesize = c->mtd->writesize; |
| 1271 | c->wbuf_ofs = 0xFFFFFFFF; | 1318 | c->wbuf_ofs = 0xFFFFFFFF; |
| 1272 | 1319 | ||
| @@ -1299,6 +1346,8 @@ int jffs2_ubivol_setup(struct jffs2_sb_info *c) { | |||
| 1299 | return 0; | 1346 | return 0; |
| 1300 | 1347 | ||
| 1301 | init_rwsem(&c->wbuf_sem); | 1348 | init_rwsem(&c->wbuf_sem); |
| 1349 | spin_lock_init(&c->wbuf_dwork_lock); | ||
| 1350 | INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync); | ||
| 1302 | 1351 | ||
| 1303 | c->wbuf_pagesize = c->mtd->writesize; | 1352 | c->wbuf_pagesize = c->mtd->writesize; |
| 1304 | c->wbuf_ofs = 0xFFFFFFFF; | 1353 | c->wbuf_ofs = 0xFFFFFFFF; |
diff --git a/fs/locks.c b/fs/locks.c index 4f441e46cef4..814c51d0de47 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -1636,12 +1636,13 @@ EXPORT_SYMBOL(flock_lock_file_wait); | |||
| 1636 | SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) | 1636 | SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) |
| 1637 | { | 1637 | { |
| 1638 | struct file *filp; | 1638 | struct file *filp; |
| 1639 | int fput_needed; | ||
| 1639 | struct file_lock *lock; | 1640 | struct file_lock *lock; |
| 1640 | int can_sleep, unlock; | 1641 | int can_sleep, unlock; |
| 1641 | int error; | 1642 | int error; |
| 1642 | 1643 | ||
| 1643 | error = -EBADF; | 1644 | error = -EBADF; |
| 1644 | filp = fget(fd); | 1645 | filp = fget_light(fd, &fput_needed); |
| 1645 | if (!filp) | 1646 | if (!filp) |
| 1646 | goto out; | 1647 | goto out; |
| 1647 | 1648 | ||
| @@ -1674,7 +1675,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd) | |||
| 1674 | locks_free_lock(lock); | 1675 | locks_free_lock(lock); |
| 1675 | 1676 | ||
| 1676 | out_putf: | 1677 | out_putf: |
| 1677 | fput(filp); | 1678 | fput_light(filp, fput_needed); |
| 1678 | out: | 1679 | out: |
| 1679 | return error; | 1680 | return error; |
| 1680 | } | 1681 | } |
diff --git a/fs/namei.c b/fs/namei.c index c651f02c9fec..7d694194024a 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -449,7 +449,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) | |||
| 449 | mntget(nd->path.mnt); | 449 | mntget(nd->path.mnt); |
| 450 | 450 | ||
| 451 | rcu_read_unlock(); | 451 | rcu_read_unlock(); |
| 452 | br_read_unlock(vfsmount_lock); | 452 | br_read_unlock(&vfsmount_lock); |
| 453 | nd->flags &= ~LOOKUP_RCU; | 453 | nd->flags &= ~LOOKUP_RCU; |
| 454 | return 0; | 454 | return 0; |
| 455 | 455 | ||
| @@ -507,14 +507,14 @@ static int complete_walk(struct nameidata *nd) | |||
| 507 | if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) { | 507 | if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) { |
| 508 | spin_unlock(&dentry->d_lock); | 508 | spin_unlock(&dentry->d_lock); |
| 509 | rcu_read_unlock(); | 509 | rcu_read_unlock(); |
| 510 | br_read_unlock(vfsmount_lock); | 510 | br_read_unlock(&vfsmount_lock); |
| 511 | return -ECHILD; | 511 | return -ECHILD; |
| 512 | } | 512 | } |
| 513 | BUG_ON(nd->inode != dentry->d_inode); | 513 | BUG_ON(nd->inode != dentry->d_inode); |
| 514 | spin_unlock(&dentry->d_lock); | 514 | spin_unlock(&dentry->d_lock); |
| 515 | mntget(nd->path.mnt); | 515 | mntget(nd->path.mnt); |
| 516 | rcu_read_unlock(); | 516 | rcu_read_unlock(); |
| 517 | br_read_unlock(vfsmount_lock); | 517 | br_read_unlock(&vfsmount_lock); |
| 518 | } | 518 | } |
| 519 | 519 | ||
| 520 | if (likely(!(nd->flags & LOOKUP_JUMPED))) | 520 | if (likely(!(nd->flags & LOOKUP_JUMPED))) |
| @@ -681,15 +681,15 @@ int follow_up(struct path *path) | |||
| 681 | struct mount *parent; | 681 | struct mount *parent; |
| 682 | struct dentry *mountpoint; | 682 | struct dentry *mountpoint; |
| 683 | 683 | ||
| 684 | br_read_lock(vfsmount_lock); | 684 | br_read_lock(&vfsmount_lock); |
| 685 | parent = mnt->mnt_parent; | 685 | parent = mnt->mnt_parent; |
| 686 | if (&parent->mnt == path->mnt) { | 686 | if (&parent->mnt == path->mnt) { |
| 687 | br_read_unlock(vfsmount_lock); | 687 | br_read_unlock(&vfsmount_lock); |
| 688 | return 0; | 688 | return 0; |
| 689 | } | 689 | } |
| 690 | mntget(&parent->mnt); | 690 | mntget(&parent->mnt); |
| 691 | mountpoint = dget(mnt->mnt_mountpoint); | 691 | mountpoint = dget(mnt->mnt_mountpoint); |
| 692 | br_read_unlock(vfsmount_lock); | 692 | br_read_unlock(&vfsmount_lock); |
| 693 | dput(path->dentry); | 693 | dput(path->dentry); |
| 694 | path->dentry = mountpoint; | 694 | path->dentry = mountpoint; |
| 695 | mntput(path->mnt); | 695 | mntput(path->mnt); |
| @@ -947,7 +947,7 @@ failed: | |||
| 947 | if (!(nd->flags & LOOKUP_ROOT)) | 947 | if (!(nd->flags & LOOKUP_ROOT)) |
| 948 | nd->root.mnt = NULL; | 948 | nd->root.mnt = NULL; |
| 949 | rcu_read_unlock(); | 949 | rcu_read_unlock(); |
| 950 | br_read_unlock(vfsmount_lock); | 950 | br_read_unlock(&vfsmount_lock); |
| 951 | return -ECHILD; | 951 | return -ECHILD; |
| 952 | } | 952 | } |
| 953 | 953 | ||
| @@ -1125,8 +1125,8 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
| 1125 | * small and for now I'd prefer to have fast path as straight as possible. | 1125 | * small and for now I'd prefer to have fast path as straight as possible. |
| 1126 | * It _is_ time-critical. | 1126 | * It _is_ time-critical. |
| 1127 | */ | 1127 | */ |
| 1128 | static int do_lookup(struct nameidata *nd, struct qstr *name, | 1128 | static int lookup_fast(struct nameidata *nd, struct qstr *name, |
| 1129 | struct path *path, struct inode **inode) | 1129 | struct path *path, struct inode **inode) |
| 1130 | { | 1130 | { |
| 1131 | struct vfsmount *mnt = nd->path.mnt; | 1131 | struct vfsmount *mnt = nd->path.mnt; |
| 1132 | struct dentry *dentry, *parent = nd->path.dentry; | 1132 | struct dentry *dentry, *parent = nd->path.dentry; |
| @@ -1208,7 +1208,7 @@ unlazy: | |||
| 1208 | goto need_lookup; | 1208 | goto need_lookup; |
| 1209 | } | 1209 | } |
| 1210 | } | 1210 | } |
| 1211 | done: | 1211 | |
| 1212 | path->mnt = mnt; | 1212 | path->mnt = mnt; |
| 1213 | path->dentry = dentry; | 1213 | path->dentry = dentry; |
| 1214 | err = follow_managed(path, nd->flags); | 1214 | err = follow_managed(path, nd->flags); |
| @@ -1222,6 +1222,17 @@ done: | |||
| 1222 | return 0; | 1222 | return 0; |
| 1223 | 1223 | ||
| 1224 | need_lookup: | 1224 | need_lookup: |
| 1225 | return 1; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | /* Fast lookup failed, do it the slow way */ | ||
| 1229 | static int lookup_slow(struct nameidata *nd, struct qstr *name, | ||
| 1230 | struct path *path) | ||
| 1231 | { | ||
| 1232 | struct dentry *dentry, *parent; | ||
| 1233 | int err; | ||
| 1234 | |||
| 1235 | parent = nd->path.dentry; | ||
| 1225 | BUG_ON(nd->inode != parent->d_inode); | 1236 | BUG_ON(nd->inode != parent->d_inode); |
| 1226 | 1237 | ||
| 1227 | mutex_lock(&parent->d_inode->i_mutex); | 1238 | mutex_lock(&parent->d_inode->i_mutex); |
| @@ -1229,7 +1240,16 @@ need_lookup: | |||
| 1229 | mutex_unlock(&parent->d_inode->i_mutex); | 1240 | mutex_unlock(&parent->d_inode->i_mutex); |
| 1230 | if (IS_ERR(dentry)) | 1241 | if (IS_ERR(dentry)) |
| 1231 | return PTR_ERR(dentry); | 1242 | return PTR_ERR(dentry); |
| 1232 | goto done; | 1243 | path->mnt = nd->path.mnt; |
| 1244 | path->dentry = dentry; | ||
| 1245 | err = follow_managed(path, nd->flags); | ||
| 1246 | if (unlikely(err < 0)) { | ||
| 1247 | path_put_conditional(path, nd); | ||
| 1248 | return err; | ||
| 1249 | } | ||
| 1250 | if (err) | ||
| 1251 | nd->flags |= LOOKUP_JUMPED; | ||
| 1252 | return 0; | ||
| 1233 | } | 1253 | } |
| 1234 | 1254 | ||
| 1235 | static inline int may_lookup(struct nameidata *nd) | 1255 | static inline int may_lookup(struct nameidata *nd) |
| @@ -1265,7 +1285,7 @@ static void terminate_walk(struct nameidata *nd) | |||
| 1265 | if (!(nd->flags & LOOKUP_ROOT)) | 1285 | if (!(nd->flags & LOOKUP_ROOT)) |
| 1266 | nd->root.mnt = NULL; | 1286 | nd->root.mnt = NULL; |
| 1267 | rcu_read_unlock(); | 1287 | rcu_read_unlock(); |
| 1268 | br_read_unlock(vfsmount_lock); | 1288 | br_read_unlock(&vfsmount_lock); |
| 1269 | } | 1289 | } |
| 1270 | } | 1290 | } |
| 1271 | 1291 | ||
| @@ -1301,21 +1321,26 @@ static inline int walk_component(struct nameidata *nd, struct path *path, | |||
| 1301 | */ | 1321 | */ |
| 1302 | if (unlikely(type != LAST_NORM)) | 1322 | if (unlikely(type != LAST_NORM)) |
| 1303 | return handle_dots(nd, type); | 1323 | return handle_dots(nd, type); |
| 1304 | err = do_lookup(nd, name, path, &inode); | 1324 | err = lookup_fast(nd, name, path, &inode); |
| 1305 | if (unlikely(err)) { | 1325 | if (unlikely(err)) { |
| 1306 | terminate_walk(nd); | 1326 | if (err < 0) |
| 1307 | return err; | 1327 | goto out_err; |
| 1308 | } | 1328 | |
| 1309 | if (!inode) { | 1329 | err = lookup_slow(nd, name, path); |
| 1310 | path_to_nameidata(path, nd); | 1330 | if (err < 0) |
| 1311 | terminate_walk(nd); | 1331 | goto out_err; |
| 1312 | return -ENOENT; | 1332 | |
| 1333 | inode = path->dentry->d_inode; | ||
| 1313 | } | 1334 | } |
| 1335 | err = -ENOENT; | ||
| 1336 | if (!inode) | ||
| 1337 | goto out_path_put; | ||
| 1338 | |||
| 1314 | if (should_follow_link(inode, follow)) { | 1339 | if (should_follow_link(inode, follow)) { |
| 1315 | if (nd->flags & LOOKUP_RCU) { | 1340 | if (nd->flags & LOOKUP_RCU) { |
| 1316 | if (unlikely(unlazy_walk(nd, path->dentry))) { | 1341 | if (unlikely(unlazy_walk(nd, path->dentry))) { |
| 1317 | terminate_walk(nd); | 1342 | err = -ECHILD; |
| 1318 | return -ECHILD; | 1343 | goto out_err; |
| 1319 | } | 1344 | } |
| 1320 | } | 1345 | } |
| 1321 | BUG_ON(inode != path->dentry->d_inode); | 1346 | BUG_ON(inode != path->dentry->d_inode); |
| @@ -1324,6 +1349,12 @@ static inline int walk_component(struct nameidata *nd, struct path *path, | |||
| 1324 | path_to_nameidata(path, nd); | 1349 | path_to_nameidata(path, nd); |
| 1325 | nd->inode = inode; | 1350 | nd->inode = inode; |
| 1326 | return 0; | 1351 | return 0; |
| 1352 | |||
| 1353 | out_path_put: | ||
| 1354 | path_to_nameidata(path, nd); | ||
| 1355 | out_err: | ||
| 1356 | terminate_walk(nd); | ||
| 1357 | return err; | ||
| 1327 | } | 1358 | } |
| 1328 | 1359 | ||
| 1329 | /* | 1360 | /* |
| @@ -1620,7 +1651,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
| 1620 | nd->path = nd->root; | 1651 | nd->path = nd->root; |
| 1621 | nd->inode = inode; | 1652 | nd->inode = inode; |
| 1622 | if (flags & LOOKUP_RCU) { | 1653 | if (flags & LOOKUP_RCU) { |
| 1623 | br_read_lock(vfsmount_lock); | 1654 | br_read_lock(&vfsmount_lock); |
| 1624 | rcu_read_lock(); | 1655 | rcu_read_lock(); |
| 1625 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1656 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
| 1626 | } else { | 1657 | } else { |
| @@ -1633,7 +1664,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
| 1633 | 1664 | ||
| 1634 | if (*name=='/') { | 1665 | if (*name=='/') { |
| 1635 | if (flags & LOOKUP_RCU) { | 1666 | if (flags & LOOKUP_RCU) { |
| 1636 | br_read_lock(vfsmount_lock); | 1667 | br_read_lock(&vfsmount_lock); |
| 1637 | rcu_read_lock(); | 1668 | rcu_read_lock(); |
| 1638 | set_root_rcu(nd); | 1669 | set_root_rcu(nd); |
| 1639 | } else { | 1670 | } else { |
| @@ -1646,7 +1677,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
| 1646 | struct fs_struct *fs = current->fs; | 1677 | struct fs_struct *fs = current->fs; |
| 1647 | unsigned seq; | 1678 | unsigned seq; |
| 1648 | 1679 | ||
| 1649 | br_read_lock(vfsmount_lock); | 1680 | br_read_lock(&vfsmount_lock); |
| 1650 | rcu_read_lock(); | 1681 | rcu_read_lock(); |
| 1651 | 1682 | ||
| 1652 | do { | 1683 | do { |
| @@ -1682,7 +1713,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
| 1682 | if (fput_needed) | 1713 | if (fput_needed) |
| 1683 | *fp = file; | 1714 | *fp = file; |
| 1684 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1715 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
| 1685 | br_read_lock(vfsmount_lock); | 1716 | br_read_lock(&vfsmount_lock); |
| 1686 | rcu_read_lock(); | 1717 | rcu_read_lock(); |
| 1687 | } else { | 1718 | } else { |
| 1688 | path_get(&file->f_path); | 1719 | path_get(&file->f_path); |
| @@ -2169,6 +2200,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
| 2169 | int want_write = 0; | 2200 | int want_write = 0; |
| 2170 | int acc_mode = op->acc_mode; | 2201 | int acc_mode = op->acc_mode; |
| 2171 | struct file *filp; | 2202 | struct file *filp; |
| 2203 | struct inode *inode; | ||
| 2204 | int symlink_ok = 0; | ||
| 2205 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; | ||
| 2206 | bool retried = false; | ||
| 2172 | int error; | 2207 | int error; |
| 2173 | 2208 | ||
| 2174 | nd->flags &= ~LOOKUP_PARENT; | 2209 | nd->flags &= ~LOOKUP_PARENT; |
| @@ -2200,30 +2235,23 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
| 2200 | } | 2235 | } |
| 2201 | 2236 | ||
| 2202 | if (!(open_flag & O_CREAT)) { | 2237 | if (!(open_flag & O_CREAT)) { |
| 2203 | int symlink_ok = 0; | ||
| 2204 | if (nd->last.name[nd->last.len]) | 2238 | if (nd->last.name[nd->last.len]) |
| 2205 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | 2239 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; |
| 2206 | if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) | 2240 | if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) |
| 2207 | symlink_ok = 1; | 2241 | symlink_ok = 1; |
| 2208 | /* we _can_ be in RCU mode here */ | 2242 | /* we _can_ be in RCU mode here */ |
| 2209 | error = walk_component(nd, path, &nd->last, LAST_NORM, | 2243 | error = lookup_fast(nd, &nd->last, path, &inode); |
| 2210 | !symlink_ok); | 2244 | if (unlikely(error)) { |
| 2211 | if (error < 0) | 2245 | if (error < 0) |
| 2212 | return ERR_PTR(error); | 2246 | goto exit; |
| 2213 | if (error) /* symlink */ | ||
| 2214 | return NULL; | ||
| 2215 | /* sayonara */ | ||
| 2216 | error = complete_walk(nd); | ||
| 2217 | if (error) | ||
| 2218 | return ERR_PTR(error); | ||
| 2219 | 2247 | ||
| 2220 | error = -ENOTDIR; | 2248 | error = lookup_slow(nd, &nd->last, path); |
| 2221 | if (nd->flags & LOOKUP_DIRECTORY) { | 2249 | if (error < 0) |
| 2222 | if (!nd->inode->i_op->lookup) | ||
| 2223 | goto exit; | 2250 | goto exit; |
| 2251 | |||
| 2252 | inode = path->dentry->d_inode; | ||
| 2224 | } | 2253 | } |
| 2225 | audit_inode(pathname, nd->path.dentry); | 2254 | goto finish_lookup; |
| 2226 | goto ok; | ||
| 2227 | } | 2255 | } |
| 2228 | 2256 | ||
| 2229 | /* create side of things */ | 2257 | /* create side of things */ |
| @@ -2241,6 +2269,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
| 2241 | if (nd->last.name[nd->last.len]) | 2269 | if (nd->last.name[nd->last.len]) |
| 2242 | goto exit; | 2270 | goto exit; |
| 2243 | 2271 | ||
| 2272 | retry_lookup: | ||
| 2244 | mutex_lock(&dir->d_inode->i_mutex); | 2273 | mutex_lock(&dir->d_inode->i_mutex); |
| 2245 | 2274 | ||
| 2246 | dentry = lookup_hash(nd); | 2275 | dentry = lookup_hash(nd); |
| @@ -2302,22 +2331,49 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
| 2302 | if (error) | 2331 | if (error) |
| 2303 | nd->flags |= LOOKUP_JUMPED; | 2332 | nd->flags |= LOOKUP_JUMPED; |
| 2304 | 2333 | ||
| 2334 | BUG_ON(nd->flags & LOOKUP_RCU); | ||
| 2335 | inode = path->dentry->d_inode; | ||
| 2336 | finish_lookup: | ||
| 2337 | /* we _can_ be in RCU mode here */ | ||
| 2305 | error = -ENOENT; | 2338 | error = -ENOENT; |
| 2306 | if (!path->dentry->d_inode) | 2339 | if (!inode) { |
| 2307 | goto exit_dput; | 2340 | path_to_nameidata(path, nd); |
| 2341 | goto exit; | ||
| 2342 | } | ||
| 2308 | 2343 | ||
| 2309 | if (path->dentry->d_inode->i_op->follow_link) | 2344 | if (should_follow_link(inode, !symlink_ok)) { |
| 2345 | if (nd->flags & LOOKUP_RCU) { | ||
| 2346 | if (unlikely(unlazy_walk(nd, path->dentry))) { | ||
| 2347 | error = -ECHILD; | ||
| 2348 | goto exit; | ||
| 2349 | } | ||
| 2350 | } | ||
| 2351 | BUG_ON(inode != path->dentry->d_inode); | ||
| 2310 | return NULL; | 2352 | return NULL; |
| 2353 | } | ||
| 2311 | 2354 | ||
| 2312 | path_to_nameidata(path, nd); | 2355 | if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) { |
| 2313 | nd->inode = path->dentry->d_inode; | 2356 | path_to_nameidata(path, nd); |
| 2357 | } else { | ||
| 2358 | save_parent.dentry = nd->path.dentry; | ||
| 2359 | save_parent.mnt = mntget(path->mnt); | ||
| 2360 | nd->path.dentry = path->dentry; | ||
| 2361 | |||
| 2362 | } | ||
| 2363 | nd->inode = inode; | ||
| 2314 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ | 2364 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ |
| 2315 | error = complete_walk(nd); | 2365 | error = complete_walk(nd); |
| 2316 | if (error) | 2366 | if (error) { |
| 2367 | path_put(&save_parent); | ||
| 2317 | return ERR_PTR(error); | 2368 | return ERR_PTR(error); |
| 2369 | } | ||
| 2318 | error = -EISDIR; | 2370 | error = -EISDIR; |
| 2319 | if (S_ISDIR(nd->inode->i_mode)) | 2371 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) |
| 2372 | goto exit; | ||
| 2373 | error = -ENOTDIR; | ||
| 2374 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) | ||
| 2320 | goto exit; | 2375 | goto exit; |
| 2376 | audit_inode(pathname, nd->path.dentry); | ||
| 2321 | ok: | 2377 | ok: |
| 2322 | if (!S_ISREG(nd->inode->i_mode)) | 2378 | if (!S_ISREG(nd->inode->i_mode)) |
| 2323 | will_truncate = 0; | 2379 | will_truncate = 0; |
| @@ -2333,6 +2389,20 @@ common: | |||
| 2333 | if (error) | 2389 | if (error) |
| 2334 | goto exit; | 2390 | goto exit; |
| 2335 | filp = nameidata_to_filp(nd); | 2391 | filp = nameidata_to_filp(nd); |
| 2392 | if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) { | ||
| 2393 | BUG_ON(save_parent.dentry != dir); | ||
| 2394 | path_put(&nd->path); | ||
| 2395 | nd->path = save_parent; | ||
| 2396 | nd->inode = dir->d_inode; | ||
| 2397 | save_parent.mnt = NULL; | ||
| 2398 | save_parent.dentry = NULL; | ||
| 2399 | if (want_write) { | ||
| 2400 | mnt_drop_write(nd->path.mnt); | ||
| 2401 | want_write = 0; | ||
| 2402 | } | ||
| 2403 | retried = true; | ||
| 2404 | goto retry_lookup; | ||
| 2405 | } | ||
| 2336 | if (!IS_ERR(filp)) { | 2406 | if (!IS_ERR(filp)) { |
| 2337 | error = ima_file_check(filp, op->acc_mode); | 2407 | error = ima_file_check(filp, op->acc_mode); |
| 2338 | if (error) { | 2408 | if (error) { |
| @@ -2352,7 +2422,8 @@ common: | |||
| 2352 | out: | 2422 | out: |
| 2353 | if (want_write) | 2423 | if (want_write) |
| 2354 | mnt_drop_write(nd->path.mnt); | 2424 | mnt_drop_write(nd->path.mnt); |
| 2355 | path_put(&nd->path); | 2425 | path_put(&save_parent); |
| 2426 | terminate_walk(nd); | ||
| 2356 | return filp; | 2427 | return filp; |
| 2357 | 2428 | ||
| 2358 | exit_mutex_unlock: | 2429 | exit_mutex_unlock: |
| @@ -2415,6 +2486,12 @@ out: | |||
| 2415 | if (base) | 2486 | if (base) |
| 2416 | fput(base); | 2487 | fput(base); |
| 2417 | release_open_intent(nd); | 2488 | release_open_intent(nd); |
| 2489 | if (filp == ERR_PTR(-EOPENSTALE)) { | ||
| 2490 | if (flags & LOOKUP_RCU) | ||
| 2491 | filp = ERR_PTR(-ECHILD); | ||
| 2492 | else | ||
| 2493 | filp = ERR_PTR(-ESTALE); | ||
| 2494 | } | ||
| 2418 | return filp; | 2495 | return filp; |
| 2419 | 2496 | ||
| 2420 | out_filp: | 2497 | out_filp: |
diff --git a/fs/namespace.c b/fs/namespace.c index e6081996c9a2..1e4a5fe3d7b7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -397,7 +397,7 @@ static int mnt_make_readonly(struct mount *mnt) | |||
| 397 | { | 397 | { |
| 398 | int ret = 0; | 398 | int ret = 0; |
| 399 | 399 | ||
| 400 | br_write_lock(vfsmount_lock); | 400 | br_write_lock(&vfsmount_lock); |
| 401 | mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; | 401 | mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; |
| 402 | /* | 402 | /* |
| 403 | * After storing MNT_WRITE_HOLD, we'll read the counters. This store | 403 | * After storing MNT_WRITE_HOLD, we'll read the counters. This store |
| @@ -431,15 +431,15 @@ static int mnt_make_readonly(struct mount *mnt) | |||
| 431 | */ | 431 | */ |
| 432 | smp_wmb(); | 432 | smp_wmb(); |
| 433 | mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; | 433 | mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; |
| 434 | br_write_unlock(vfsmount_lock); | 434 | br_write_unlock(&vfsmount_lock); |
| 435 | return ret; | 435 | return ret; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | static void __mnt_unmake_readonly(struct mount *mnt) | 438 | static void __mnt_unmake_readonly(struct mount *mnt) |
| 439 | { | 439 | { |
| 440 | br_write_lock(vfsmount_lock); | 440 | br_write_lock(&vfsmount_lock); |
| 441 | mnt->mnt.mnt_flags &= ~MNT_READONLY; | 441 | mnt->mnt.mnt_flags &= ~MNT_READONLY; |
| 442 | br_write_unlock(vfsmount_lock); | 442 | br_write_unlock(&vfsmount_lock); |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | int sb_prepare_remount_readonly(struct super_block *sb) | 445 | int sb_prepare_remount_readonly(struct super_block *sb) |
| @@ -451,7 +451,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) | |||
| 451 | if (atomic_long_read(&sb->s_remove_count)) | 451 | if (atomic_long_read(&sb->s_remove_count)) |
| 452 | return -EBUSY; | 452 | return -EBUSY; |
| 453 | 453 | ||
| 454 | br_write_lock(vfsmount_lock); | 454 | br_write_lock(&vfsmount_lock); |
| 455 | list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { | 455 | list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) { |
| 456 | if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { | 456 | if (!(mnt->mnt.mnt_flags & MNT_READONLY)) { |
| 457 | mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; | 457 | mnt->mnt.mnt_flags |= MNT_WRITE_HOLD; |
| @@ -473,7 +473,7 @@ int sb_prepare_remount_readonly(struct super_block *sb) | |||
| 473 | if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD) | 473 | if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD) |
| 474 | mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; | 474 | mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD; |
| 475 | } | 475 | } |
| 476 | br_write_unlock(vfsmount_lock); | 476 | br_write_unlock(&vfsmount_lock); |
| 477 | 477 | ||
| 478 | return err; | 478 | return err; |
| 479 | } | 479 | } |
| @@ -522,14 +522,14 @@ struct vfsmount *lookup_mnt(struct path *path) | |||
| 522 | { | 522 | { |
| 523 | struct mount *child_mnt; | 523 | struct mount *child_mnt; |
| 524 | 524 | ||
| 525 | br_read_lock(vfsmount_lock); | 525 | br_read_lock(&vfsmount_lock); |
| 526 | child_mnt = __lookup_mnt(path->mnt, path->dentry, 1); | 526 | child_mnt = __lookup_mnt(path->mnt, path->dentry, 1); |
| 527 | if (child_mnt) { | 527 | if (child_mnt) { |
| 528 | mnt_add_count(child_mnt, 1); | 528 | mnt_add_count(child_mnt, 1); |
| 529 | br_read_unlock(vfsmount_lock); | 529 | br_read_unlock(&vfsmount_lock); |
| 530 | return &child_mnt->mnt; | 530 | return &child_mnt->mnt; |
| 531 | } else { | 531 | } else { |
| 532 | br_read_unlock(vfsmount_lock); | 532 | br_read_unlock(&vfsmount_lock); |
| 533 | return NULL; | 533 | return NULL; |
| 534 | } | 534 | } |
| 535 | } | 535 | } |
| @@ -714,9 +714,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
| 714 | mnt->mnt.mnt_sb = root->d_sb; | 714 | mnt->mnt.mnt_sb = root->d_sb; |
| 715 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | 715 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 716 | mnt->mnt_parent = mnt; | 716 | mnt->mnt_parent = mnt; |
| 717 | br_write_lock(vfsmount_lock); | 717 | br_write_lock(&vfsmount_lock); |
| 718 | list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts); | 718 | list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts); |
| 719 | br_write_unlock(vfsmount_lock); | 719 | br_write_unlock(&vfsmount_lock); |
| 720 | return &mnt->mnt; | 720 | return &mnt->mnt; |
| 721 | } | 721 | } |
| 722 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 722 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |
| @@ -745,9 +745,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
| 745 | mnt->mnt.mnt_root = dget(root); | 745 | mnt->mnt.mnt_root = dget(root); |
| 746 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | 746 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 747 | mnt->mnt_parent = mnt; | 747 | mnt->mnt_parent = mnt; |
| 748 | br_write_lock(vfsmount_lock); | 748 | br_write_lock(&vfsmount_lock); |
| 749 | list_add_tail(&mnt->mnt_instance, &sb->s_mounts); | 749 | list_add_tail(&mnt->mnt_instance, &sb->s_mounts); |
| 750 | br_write_unlock(vfsmount_lock); | 750 | br_write_unlock(&vfsmount_lock); |
| 751 | 751 | ||
| 752 | if (flag & CL_SLAVE) { | 752 | if (flag & CL_SLAVE) { |
| 753 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); | 753 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); |
| @@ -803,35 +803,36 @@ static void mntput_no_expire(struct mount *mnt) | |||
| 803 | { | 803 | { |
| 804 | put_again: | 804 | put_again: |
| 805 | #ifdef CONFIG_SMP | 805 | #ifdef CONFIG_SMP |
| 806 | br_read_lock(vfsmount_lock); | 806 | br_read_lock(&vfsmount_lock); |
| 807 | if (likely(atomic_read(&mnt->mnt_longterm))) { | 807 | if (likely(atomic_read(&mnt->mnt_longterm))) { |
| 808 | mnt_add_count(mnt, -1); | 808 | mnt_add_count(mnt, -1); |
| 809 | br_read_unlock(vfsmount_lock); | 809 | br_read_unlock(&vfsmount_lock); |
| 810 | return; | 810 | return; |
| 811 | } | 811 | } |
| 812 | br_read_unlock(vfsmount_lock); | 812 | br_read_unlock(&vfsmount_lock); |
| 813 | 813 | ||
| 814 | br_write_lock(vfsmount_lock); | 814 | br_write_lock(&vfsmount_lock); |
| 815 | mnt_add_count(mnt, -1); | 815 | mnt_add_count(mnt, -1); |
| 816 | if (mnt_get_count(mnt)) { | 816 | if (mnt_get_count(mnt)) { |
| 817 | br_write_unlock(vfsmount_lock); | 817 | br_write_unlock(&vfsmount_lock); |
| 818 | return; | 818 | return; |
| 819 | } | 819 | } |
| 820 | #else | 820 | #else |
| 821 | mnt_add_count(mnt, -1); | 821 | mnt_add_count(mnt, -1); |
| 822 | if (likely(mnt_get_count(mnt))) | 822 | if (likely(mnt_get_count(mnt))) |
| 823 | return; | 823 | return; |
| 824 | br_write_lock(vfsmount_lock); | 824 | br_write_lock(&vfsmount_lock); |
| 825 | #endif | 825 | #endif |
| 826 | if (unlikely(mnt->mnt_pinned)) { | 826 | if (unlikely(mnt->mnt_pinned)) { |
| 827 | mnt_add_count(mnt, mnt->mnt_pinned + 1); | 827 | mnt_add_count(mnt, mnt->mnt_pinned + 1); |
| 828 | mnt->mnt_pinned = 0; | 828 | mnt->mnt_pinned = 0; |
| 829 | br_write_unlock(vfsmount_lock); | 829 | br_write_unlock(&vfsmount_lock); |
| 830 | acct_auto_close_mnt(&mnt->mnt); | 830 | acct_auto_close_mnt(&mnt->mnt); |
| 831 | goto put_again; | 831 | goto put_again; |
| 832 | } | 832 | } |
| 833 | |||
| 833 | list_del(&mnt->mnt_instance); | 834 | list_del(&mnt->mnt_instance); |
| 834 | br_write_unlock(vfsmount_lock); | 835 | br_write_unlock(&vfsmount_lock); |
| 835 | mntfree(mnt); | 836 | mntfree(mnt); |
| 836 | } | 837 | } |
| 837 | 838 | ||
| @@ -857,21 +858,21 @@ EXPORT_SYMBOL(mntget); | |||
| 857 | 858 | ||
| 858 | void mnt_pin(struct vfsmount *mnt) | 859 | void mnt_pin(struct vfsmount *mnt) |
| 859 | { | 860 | { |
| 860 | br_write_lock(vfsmount_lock); | 861 | br_write_lock(&vfsmount_lock); |
| 861 | real_mount(mnt)->mnt_pinned++; | 862 | real_mount(mnt)->mnt_pinned++; |
| 862 | br_write_unlock(vfsmount_lock); | 863 | br_write_unlock(&vfsmount_lock); |
| 863 | } | 864 | } |
| 864 | EXPORT_SYMBOL(mnt_pin); | 865 | EXPORT_SYMBOL(mnt_pin); |
| 865 | 866 | ||
| 866 | void mnt_unpin(struct vfsmount *m) | 867 | void mnt_unpin(struct vfsmount *m) |
| 867 | { | 868 | { |
| 868 | struct mount *mnt = real_mount(m); | 869 | struct mount *mnt = real_mount(m); |
| 869 | br_write_lock(vfsmount_lock); | 870 | br_write_lock(&vfsmount_lock); |
| 870 | if (mnt->mnt_pinned) { | 871 | if (mnt->mnt_pinned) { |
| 871 | mnt_add_count(mnt, 1); | 872 | mnt_add_count(mnt, 1); |
| 872 | mnt->mnt_pinned--; | 873 | mnt->mnt_pinned--; |
| 873 | } | 874 | } |
| 874 | br_write_unlock(vfsmount_lock); | 875 | br_write_unlock(&vfsmount_lock); |
| 875 | } | 876 | } |
| 876 | EXPORT_SYMBOL(mnt_unpin); | 877 | EXPORT_SYMBOL(mnt_unpin); |
| 877 | 878 | ||
| @@ -988,12 +989,12 @@ int may_umount_tree(struct vfsmount *m) | |||
| 988 | BUG_ON(!m); | 989 | BUG_ON(!m); |
| 989 | 990 | ||
| 990 | /* write lock needed for mnt_get_count */ | 991 | /* write lock needed for mnt_get_count */ |
| 991 | br_write_lock(vfsmount_lock); | 992 | br_write_lock(&vfsmount_lock); |
| 992 | for (p = mnt; p; p = next_mnt(p, mnt)) { | 993 | for (p = mnt; p; p = next_mnt(p, mnt)) { |
| 993 | actual_refs += mnt_get_count(p); | 994 | actual_refs += mnt_get_count(p); |
| 994 | minimum_refs += 2; | 995 | minimum_refs += 2; |
| 995 | } | 996 | } |
| 996 | br_write_unlock(vfsmount_lock); | 997 | br_write_unlock(&vfsmount_lock); |
| 997 | 998 | ||
| 998 | if (actual_refs > minimum_refs) | 999 | if (actual_refs > minimum_refs) |
| 999 | return 0; | 1000 | return 0; |
| @@ -1020,10 +1021,10 @@ int may_umount(struct vfsmount *mnt) | |||
| 1020 | { | 1021 | { |
| 1021 | int ret = 1; | 1022 | int ret = 1; |
| 1022 | down_read(&namespace_sem); | 1023 | down_read(&namespace_sem); |
| 1023 | br_write_lock(vfsmount_lock); | 1024 | br_write_lock(&vfsmount_lock); |
| 1024 | if (propagate_mount_busy(real_mount(mnt), 2)) | 1025 | if (propagate_mount_busy(real_mount(mnt), 2)) |
| 1025 | ret = 0; | 1026 | ret = 0; |
| 1026 | br_write_unlock(vfsmount_lock); | 1027 | br_write_unlock(&vfsmount_lock); |
| 1027 | up_read(&namespace_sem); | 1028 | up_read(&namespace_sem); |
| 1028 | return ret; | 1029 | return ret; |
| 1029 | } | 1030 | } |
| @@ -1040,13 +1041,13 @@ void release_mounts(struct list_head *head) | |||
| 1040 | struct dentry *dentry; | 1041 | struct dentry *dentry; |
| 1041 | struct mount *m; | 1042 | struct mount *m; |
| 1042 | 1043 | ||
| 1043 | br_write_lock(vfsmount_lock); | 1044 | br_write_lock(&vfsmount_lock); |
| 1044 | dentry = mnt->mnt_mountpoint; | 1045 | dentry = mnt->mnt_mountpoint; |
| 1045 | m = mnt->mnt_parent; | 1046 | m = mnt->mnt_parent; |
| 1046 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | 1047 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; |
| 1047 | mnt->mnt_parent = mnt; | 1048 | mnt->mnt_parent = mnt; |
| 1048 | m->mnt_ghosts--; | 1049 | m->mnt_ghosts--; |
| 1049 | br_write_unlock(vfsmount_lock); | 1050 | br_write_unlock(&vfsmount_lock); |
| 1050 | dput(dentry); | 1051 | dput(dentry); |
| 1051 | mntput(&m->mnt); | 1052 | mntput(&m->mnt); |
| 1052 | } | 1053 | } |
| @@ -1073,8 +1074,9 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) | |||
| 1073 | list_del_init(&p->mnt_expire); | 1074 | list_del_init(&p->mnt_expire); |
| 1074 | list_del_init(&p->mnt_list); | 1075 | list_del_init(&p->mnt_list); |
| 1075 | __touch_mnt_namespace(p->mnt_ns); | 1076 | __touch_mnt_namespace(p->mnt_ns); |
| 1077 | if (p->mnt_ns) | ||
| 1078 | __mnt_make_shortterm(p); | ||
| 1076 | p->mnt_ns = NULL; | 1079 | p->mnt_ns = NULL; |
| 1077 | __mnt_make_shortterm(p); | ||
| 1078 | list_del_init(&p->mnt_child); | 1080 | list_del_init(&p->mnt_child); |
| 1079 | if (mnt_has_parent(p)) { | 1081 | if (mnt_has_parent(p)) { |
| 1080 | p->mnt_parent->mnt_ghosts++; | 1082 | p->mnt_parent->mnt_ghosts++; |
| @@ -1112,12 +1114,12 @@ static int do_umount(struct mount *mnt, int flags) | |||
| 1112 | * probably don't strictly need the lock here if we examined | 1114 | * probably don't strictly need the lock here if we examined |
| 1113 | * all race cases, but it's a slowpath. | 1115 | * all race cases, but it's a slowpath. |
| 1114 | */ | 1116 | */ |
| 1115 | br_write_lock(vfsmount_lock); | 1117 | br_write_lock(&vfsmount_lock); |
| 1116 | if (mnt_get_count(mnt) != 2) { | 1118 | if (mnt_get_count(mnt) != 2) { |
| 1117 | br_write_unlock(vfsmount_lock); | 1119 | br_write_unlock(&vfsmount_lock); |
| 1118 | return -EBUSY; | 1120 | return -EBUSY; |
| 1119 | } | 1121 | } |
| 1120 | br_write_unlock(vfsmount_lock); | 1122 | br_write_unlock(&vfsmount_lock); |
| 1121 | 1123 | ||
| 1122 | if (!xchg(&mnt->mnt_expiry_mark, 1)) | 1124 | if (!xchg(&mnt->mnt_expiry_mark, 1)) |
| 1123 | return -EAGAIN; | 1125 | return -EAGAIN; |
| @@ -1159,7 +1161,7 @@ static int do_umount(struct mount *mnt, int flags) | |||
| 1159 | } | 1161 | } |
| 1160 | 1162 | ||
| 1161 | down_write(&namespace_sem); | 1163 | down_write(&namespace_sem); |
| 1162 | br_write_lock(vfsmount_lock); | 1164 | br_write_lock(&vfsmount_lock); |
| 1163 | event++; | 1165 | event++; |
| 1164 | 1166 | ||
| 1165 | if (!(flags & MNT_DETACH)) | 1167 | if (!(flags & MNT_DETACH)) |
| @@ -1171,7 +1173,7 @@ static int do_umount(struct mount *mnt, int flags) | |||
| 1171 | umount_tree(mnt, 1, &umount_list); | 1173 | umount_tree(mnt, 1, &umount_list); |
| 1172 | retval = 0; | 1174 | retval = 0; |
| 1173 | } | 1175 | } |
| 1174 | br_write_unlock(vfsmount_lock); | 1176 | br_write_unlock(&vfsmount_lock); |
| 1175 | up_write(&namespace_sem); | 1177 | up_write(&namespace_sem); |
| 1176 | release_mounts(&umount_list); | 1178 | release_mounts(&umount_list); |
| 1177 | return retval; | 1179 | return retval; |
| @@ -1286,19 +1288,19 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, | |||
| 1286 | q = clone_mnt(p, p->mnt.mnt_root, flag); | 1288 | q = clone_mnt(p, p->mnt.mnt_root, flag); |
| 1287 | if (!q) | 1289 | if (!q) |
| 1288 | goto Enomem; | 1290 | goto Enomem; |
| 1289 | br_write_lock(vfsmount_lock); | 1291 | br_write_lock(&vfsmount_lock); |
| 1290 | list_add_tail(&q->mnt_list, &res->mnt_list); | 1292 | list_add_tail(&q->mnt_list, &res->mnt_list); |
| 1291 | attach_mnt(q, &path); | 1293 | attach_mnt(q, &path); |
| 1292 | br_write_unlock(vfsmount_lock); | 1294 | br_write_unlock(&vfsmount_lock); |
| 1293 | } | 1295 | } |
| 1294 | } | 1296 | } |
| 1295 | return res; | 1297 | return res; |
| 1296 | Enomem: | 1298 | Enomem: |
| 1297 | if (res) { | 1299 | if (res) { |
| 1298 | LIST_HEAD(umount_list); | 1300 | LIST_HEAD(umount_list); |
| 1299 | br_write_lock(vfsmount_lock); | 1301 | br_write_lock(&vfsmount_lock); |
| 1300 | umount_tree(res, 0, &umount_list); | 1302 | umount_tree(res, 0, &umount_list); |
| 1301 | br_write_unlock(vfsmount_lock); | 1303 | br_write_unlock(&vfsmount_lock); |
| 1302 | release_mounts(&umount_list); | 1304 | release_mounts(&umount_list); |
| 1303 | } | 1305 | } |
| 1304 | return NULL; | 1306 | return NULL; |
| @@ -1318,9 +1320,9 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
| 1318 | { | 1320 | { |
| 1319 | LIST_HEAD(umount_list); | 1321 | LIST_HEAD(umount_list); |
| 1320 | down_write(&namespace_sem); | 1322 | down_write(&namespace_sem); |
| 1321 | br_write_lock(vfsmount_lock); | 1323 | br_write_lock(&vfsmount_lock); |
| 1322 | umount_tree(real_mount(mnt), 0, &umount_list); | 1324 | umount_tree(real_mount(mnt), 0, &umount_list); |
| 1323 | br_write_unlock(vfsmount_lock); | 1325 | br_write_unlock(&vfsmount_lock); |
| 1324 | up_write(&namespace_sem); | 1326 | up_write(&namespace_sem); |
| 1325 | release_mounts(&umount_list); | 1327 | release_mounts(&umount_list); |
| 1326 | } | 1328 | } |
| @@ -1448,7 +1450,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1448 | if (err) | 1450 | if (err) |
| 1449 | goto out_cleanup_ids; | 1451 | goto out_cleanup_ids; |
| 1450 | 1452 | ||
| 1451 | br_write_lock(vfsmount_lock); | 1453 | br_write_lock(&vfsmount_lock); |
| 1452 | 1454 | ||
| 1453 | if (IS_MNT_SHARED(dest_mnt)) { | 1455 | if (IS_MNT_SHARED(dest_mnt)) { |
| 1454 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) | 1456 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) |
| @@ -1467,7 +1469,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, | |||
| 1467 | list_del_init(&child->mnt_hash); | 1469 | list_del_init(&child->mnt_hash); |
| 1468 | commit_tree(child); | 1470 | commit_tree(child); |
| 1469 | } | 1471 | } |
| 1470 | br_write_unlock(vfsmount_lock); | 1472 | br_write_unlock(&vfsmount_lock); |
| 1471 | 1473 | ||
| 1472 | return 0; | 1474 | return 0; |
| 1473 | 1475 | ||
| @@ -1565,10 +1567,10 @@ static int do_change_type(struct path *path, int flag) | |||
| 1565 | goto out_unlock; | 1567 | goto out_unlock; |
| 1566 | } | 1568 | } |
| 1567 | 1569 | ||
| 1568 | br_write_lock(vfsmount_lock); | 1570 | br_write_lock(&vfsmount_lock); |
| 1569 | for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) | 1571 | for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) |
| 1570 | change_mnt_propagation(m, type); | 1572 | change_mnt_propagation(m, type); |
| 1571 | br_write_unlock(vfsmount_lock); | 1573 | br_write_unlock(&vfsmount_lock); |
| 1572 | 1574 | ||
| 1573 | out_unlock: | 1575 | out_unlock: |
| 1574 | up_write(&namespace_sem); | 1576 | up_write(&namespace_sem); |
| @@ -1617,9 +1619,9 @@ static int do_loopback(struct path *path, char *old_name, | |||
| 1617 | 1619 | ||
| 1618 | err = graft_tree(mnt, path); | 1620 | err = graft_tree(mnt, path); |
| 1619 | if (err) { | 1621 | if (err) { |
| 1620 | br_write_lock(vfsmount_lock); | 1622 | br_write_lock(&vfsmount_lock); |
| 1621 | umount_tree(mnt, 0, &umount_list); | 1623 | umount_tree(mnt, 0, &umount_list); |
| 1622 | br_write_unlock(vfsmount_lock); | 1624 | br_write_unlock(&vfsmount_lock); |
| 1623 | } | 1625 | } |
| 1624 | out2: | 1626 | out2: |
| 1625 | unlock_mount(path); | 1627 | unlock_mount(path); |
| @@ -1677,16 +1679,16 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
| 1677 | else | 1679 | else |
| 1678 | err = do_remount_sb(sb, flags, data, 0); | 1680 | err = do_remount_sb(sb, flags, data, 0); |
| 1679 | if (!err) { | 1681 | if (!err) { |
| 1680 | br_write_lock(vfsmount_lock); | 1682 | br_write_lock(&vfsmount_lock); |
| 1681 | mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; | 1683 | mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; |
| 1682 | mnt->mnt.mnt_flags = mnt_flags; | 1684 | mnt->mnt.mnt_flags = mnt_flags; |
| 1683 | br_write_unlock(vfsmount_lock); | 1685 | br_write_unlock(&vfsmount_lock); |
| 1684 | } | 1686 | } |
| 1685 | up_write(&sb->s_umount); | 1687 | up_write(&sb->s_umount); |
| 1686 | if (!err) { | 1688 | if (!err) { |
| 1687 | br_write_lock(vfsmount_lock); | 1689 | br_write_lock(&vfsmount_lock); |
| 1688 | touch_mnt_namespace(mnt->mnt_ns); | 1690 | touch_mnt_namespace(mnt->mnt_ns); |
| 1689 | br_write_unlock(vfsmount_lock); | 1691 | br_write_unlock(&vfsmount_lock); |
| 1690 | } | 1692 | } |
| 1691 | return err; | 1693 | return err; |
| 1692 | } | 1694 | } |
| @@ -1893,9 +1895,9 @@ fail: | |||
| 1893 | /* remove m from any expiration list it may be on */ | 1895 | /* remove m from any expiration list it may be on */ |
| 1894 | if (!list_empty(&mnt->mnt_expire)) { | 1896 | if (!list_empty(&mnt->mnt_expire)) { |
| 1895 | down_write(&namespace_sem); | 1897 | down_write(&namespace_sem); |
| 1896 | br_write_lock(vfsmount_lock); | 1898 | br_write_lock(&vfsmount_lock); |
| 1897 | list_del_init(&mnt->mnt_expire); | 1899 | list_del_init(&mnt->mnt_expire); |
| 1898 | br_write_unlock(vfsmount_lock); | 1900 | br_write_unlock(&vfsmount_lock); |
| 1899 | up_write(&namespace_sem); | 1901 | up_write(&namespace_sem); |
| 1900 | } | 1902 | } |
| 1901 | mntput(m); | 1903 | mntput(m); |
| @@ -1911,11 +1913,11 @@ fail: | |||
| 1911 | void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list) | 1913 | void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list) |
| 1912 | { | 1914 | { |
| 1913 | down_write(&namespace_sem); | 1915 | down_write(&namespace_sem); |
| 1914 | br_write_lock(vfsmount_lock); | 1916 | br_write_lock(&vfsmount_lock); |
| 1915 | 1917 | ||
| 1916 | list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list); | 1918 | list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list); |
| 1917 | 1919 | ||
| 1918 | br_write_unlock(vfsmount_lock); | 1920 | br_write_unlock(&vfsmount_lock); |
| 1919 | up_write(&namespace_sem); | 1921 | up_write(&namespace_sem); |
| 1920 | } | 1922 | } |
| 1921 | EXPORT_SYMBOL(mnt_set_expiry); | 1923 | EXPORT_SYMBOL(mnt_set_expiry); |
| @@ -1935,7 +1937,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
| 1935 | return; | 1937 | return; |
| 1936 | 1938 | ||
| 1937 | down_write(&namespace_sem); | 1939 | down_write(&namespace_sem); |
| 1938 | br_write_lock(vfsmount_lock); | 1940 | br_write_lock(&vfsmount_lock); |
| 1939 | 1941 | ||
| 1940 | /* extract from the expiration list every vfsmount that matches the | 1942 | /* extract from the expiration list every vfsmount that matches the |
| 1941 | * following criteria: | 1943 | * following criteria: |
| @@ -1954,7 +1956,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) | |||
| 1954 | touch_mnt_namespace(mnt->mnt_ns); | 1956 | touch_mnt_namespace(mnt->mnt_ns); |
| 1955 | umount_tree(mnt, 1, &umounts); | 1957 | umount_tree(mnt, 1, &umounts); |
| 1956 | } | 1958 | } |
| 1957 | br_write_unlock(vfsmount_lock); | 1959 | br_write_unlock(&vfsmount_lock); |
| 1958 | up_write(&namespace_sem); | 1960 | up_write(&namespace_sem); |
| 1959 | 1961 | ||
| 1960 | release_mounts(&umounts); | 1962 | release_mounts(&umounts); |
| @@ -2218,9 +2220,9 @@ void mnt_make_shortterm(struct vfsmount *m) | |||
| 2218 | struct mount *mnt = real_mount(m); | 2220 | struct mount *mnt = real_mount(m); |
| 2219 | if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) | 2221 | if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) |
| 2220 | return; | 2222 | return; |
| 2221 | br_write_lock(vfsmount_lock); | 2223 | br_write_lock(&vfsmount_lock); |
| 2222 | atomic_dec(&mnt->mnt_longterm); | 2224 | atomic_dec(&mnt->mnt_longterm); |
| 2223 | br_write_unlock(vfsmount_lock); | 2225 | br_write_unlock(&vfsmount_lock); |
| 2224 | #endif | 2226 | #endif |
| 2225 | } | 2227 | } |
| 2226 | 2228 | ||
| @@ -2250,9 +2252,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
| 2250 | return ERR_PTR(-ENOMEM); | 2252 | return ERR_PTR(-ENOMEM); |
| 2251 | } | 2253 | } |
| 2252 | new_ns->root = new; | 2254 | new_ns->root = new; |
| 2253 | br_write_lock(vfsmount_lock); | 2255 | br_write_lock(&vfsmount_lock); |
| 2254 | list_add_tail(&new_ns->list, &new->mnt_list); | 2256 | list_add_tail(&new_ns->list, &new->mnt_list); |
| 2255 | br_write_unlock(vfsmount_lock); | 2257 | br_write_unlock(&vfsmount_lock); |
| 2256 | 2258 | ||
| 2257 | /* | 2259 | /* |
| 2258 | * Second pass: switch the tsk->fs->* elements and mark new vfsmounts | 2260 | * Second pass: switch the tsk->fs->* elements and mark new vfsmounts |
| @@ -2416,9 +2418,9 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry, | |||
| 2416 | int path_is_under(struct path *path1, struct path *path2) | 2418 | int path_is_under(struct path *path1, struct path *path2) |
| 2417 | { | 2419 | { |
| 2418 | int res; | 2420 | int res; |
| 2419 | br_read_lock(vfsmount_lock); | 2421 | br_read_lock(&vfsmount_lock); |
| 2420 | res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2); | 2422 | res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2); |
| 2421 | br_read_unlock(vfsmount_lock); | 2423 | br_read_unlock(&vfsmount_lock); |
| 2422 | return res; | 2424 | return res; |
| 2423 | } | 2425 | } |
| 2424 | EXPORT_SYMBOL(path_is_under); | 2426 | EXPORT_SYMBOL(path_is_under); |
| @@ -2505,7 +2507,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
| 2505 | /* make sure we can reach put_old from new_root */ | 2507 | /* make sure we can reach put_old from new_root */ |
| 2506 | if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new)) | 2508 | if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new)) |
| 2507 | goto out4; | 2509 | goto out4; |
| 2508 | br_write_lock(vfsmount_lock); | 2510 | br_write_lock(&vfsmount_lock); |
| 2509 | detach_mnt(new_mnt, &parent_path); | 2511 | detach_mnt(new_mnt, &parent_path); |
| 2510 | detach_mnt(root_mnt, &root_parent); | 2512 | detach_mnt(root_mnt, &root_parent); |
| 2511 | /* mount old root on put_old */ | 2513 | /* mount old root on put_old */ |
| @@ -2513,7 +2515,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
| 2513 | /* mount new_root on / */ | 2515 | /* mount new_root on / */ |
| 2514 | attach_mnt(new_mnt, &root_parent); | 2516 | attach_mnt(new_mnt, &root_parent); |
| 2515 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2517 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
| 2516 | br_write_unlock(vfsmount_lock); | 2518 | br_write_unlock(&vfsmount_lock); |
| 2517 | chroot_fs_refs(&root, &new); | 2519 | chroot_fs_refs(&root, &new); |
| 2518 | error = 0; | 2520 | error = 0; |
| 2519 | out4: | 2521 | out4: |
| @@ -2576,7 +2578,7 @@ void __init mnt_init(void) | |||
| 2576 | for (u = 0; u < HASH_SIZE; u++) | 2578 | for (u = 0; u < HASH_SIZE; u++) |
| 2577 | INIT_LIST_HEAD(&mount_hashtable[u]); | 2579 | INIT_LIST_HEAD(&mount_hashtable[u]); |
| 2578 | 2580 | ||
| 2579 | br_lock_init(vfsmount_lock); | 2581 | br_lock_init(&vfsmount_lock); |
| 2580 | 2582 | ||
| 2581 | err = sysfs_init(); | 2583 | err = sysfs_init(); |
| 2582 | if (err) | 2584 | if (err) |
| @@ -2596,9 +2598,9 @@ void put_mnt_ns(struct mnt_namespace *ns) | |||
| 2596 | if (!atomic_dec_and_test(&ns->count)) | 2598 | if (!atomic_dec_and_test(&ns->count)) |
| 2597 | return; | 2599 | return; |
| 2598 | down_write(&namespace_sem); | 2600 | down_write(&namespace_sem); |
| 2599 | br_write_lock(vfsmount_lock); | 2601 | br_write_lock(&vfsmount_lock); |
| 2600 | umount_tree(ns->root, 0, &umount_list); | 2602 | umount_tree(ns->root, 0, &umount_list); |
| 2601 | br_write_unlock(vfsmount_lock); | 2603 | br_write_unlock(&vfsmount_lock); |
| 2602 | up_write(&namespace_sem); | 2604 | up_write(&namespace_sem); |
| 2603 | release_mounts(&umount_list); | 2605 | release_mounts(&umount_list); |
| 2604 | kfree(ns); | 2606 | kfree(ns); |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 3ff5fcc1528f..122e260247f5 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
| @@ -221,6 +221,10 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
| 221 | 221 | ||
| 222 | already_written = 0; | 222 | already_written = 0; |
| 223 | 223 | ||
| 224 | errno = file_update_time(file); | ||
| 225 | if (errno) | ||
| 226 | goto outrel; | ||
| 227 | |||
| 224 | bouncebuffer = vmalloc(bufsize); | 228 | bouncebuffer = vmalloc(bufsize); |
| 225 | if (!bouncebuffer) { | 229 | if (!bouncebuffer) { |
| 226 | errno = -EIO; /* -ENOMEM */ | 230 | errno = -EIO; /* -ENOMEM */ |
| @@ -252,8 +256,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
| 252 | } | 256 | } |
| 253 | vfree(bouncebuffer); | 257 | vfree(bouncebuffer); |
| 254 | 258 | ||
| 255 | file_update_time(file); | ||
| 256 | |||
| 257 | *ppos = pos; | 259 | *ppos = pos; |
| 258 | 260 | ||
| 259 | if (pos > i_size_read(inode)) { | 261 | if (pos > i_size_read(inode)) { |
diff --git a/fs/ncpfs/ncp_fs_sb.h b/fs/ncpfs/ncp_fs_sb.h index 4af803f13516..54cc0cdb3dcb 100644 --- a/fs/ncpfs/ncp_fs_sb.h +++ b/fs/ncpfs/ncp_fs_sb.h | |||
| @@ -23,17 +23,17 @@ struct ncp_mount_data_kernel { | |||
| 23 | unsigned long flags; /* NCP_MOUNT_* flags */ | 23 | unsigned long flags; /* NCP_MOUNT_* flags */ |
| 24 | unsigned int int_flags; /* internal flags */ | 24 | unsigned int int_flags; /* internal flags */ |
| 25 | #define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001 | 25 | #define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001 |
| 26 | __kernel_uid32_t mounted_uid; /* Who may umount() this filesystem? */ | 26 | uid_t mounted_uid; /* Who may umount() this filesystem? */ |
| 27 | struct pid *wdog_pid; /* Who cares for our watchdog packets? */ | 27 | struct pid *wdog_pid; /* Who cares for our watchdog packets? */ |
| 28 | unsigned int ncp_fd; /* The socket to the ncp port */ | 28 | unsigned int ncp_fd; /* The socket to the ncp port */ |
| 29 | unsigned int time_out; /* How long should I wait after | 29 | unsigned int time_out; /* How long should I wait after |
| 30 | sending a NCP request? */ | 30 | sending a NCP request? */ |
| 31 | unsigned int retry_count; /* And how often should I retry? */ | 31 | unsigned int retry_count; /* And how often should I retry? */ |
| 32 | unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; | 32 | unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; |
| 33 | __kernel_uid32_t uid; | 33 | uid_t uid; |
| 34 | __kernel_gid32_t gid; | 34 | gid_t gid; |
| 35 | __kernel_mode_t file_mode; | 35 | umode_t file_mode; |
| 36 | __kernel_mode_t dir_mode; | 36 | umode_t dir_mode; |
| 37 | int info_fd; | 37 | int info_fd; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 0989a2099688..f430057ff3b3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1354,10 +1354,10 @@ out: | |||
| 1354 | } | 1354 | } |
| 1355 | 1355 | ||
| 1356 | #ifdef CONFIG_NFS_V4 | 1356 | #ifdef CONFIG_NFS_V4 |
| 1357 | static int nfs_open_revalidate(struct dentry *, struct nameidata *); | 1357 | static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *); |
| 1358 | 1358 | ||
| 1359 | const struct dentry_operations nfs4_dentry_operations = { | 1359 | const struct dentry_operations nfs4_dentry_operations = { |
| 1360 | .d_revalidate = nfs_open_revalidate, | 1360 | .d_revalidate = nfs4_lookup_revalidate, |
| 1361 | .d_delete = nfs_dentry_delete, | 1361 | .d_delete = nfs_dentry_delete, |
| 1362 | .d_iput = nfs_dentry_iput, | 1362 | .d_iput = nfs_dentry_iput, |
| 1363 | .d_automount = nfs_d_automount, | 1363 | .d_automount = nfs_d_automount, |
| @@ -1519,13 +1519,11 @@ no_open: | |||
| 1519 | return nfs_lookup(dir, dentry, nd); | 1519 | return nfs_lookup(dir, dentry, nd); |
| 1520 | } | 1520 | } |
| 1521 | 1521 | ||
| 1522 | static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | 1522 | static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 1523 | { | 1523 | { |
| 1524 | struct dentry *parent = NULL; | 1524 | struct dentry *parent = NULL; |
| 1525 | struct inode *inode; | 1525 | struct inode *inode; |
| 1526 | struct inode *dir; | 1526 | struct inode *dir; |
| 1527 | struct nfs_open_context *ctx; | ||
| 1528 | struct iattr attr; | ||
| 1529 | int openflags, ret = 0; | 1527 | int openflags, ret = 0; |
| 1530 | 1528 | ||
| 1531 | if (nd->flags & LOOKUP_RCU) | 1529 | if (nd->flags & LOOKUP_RCU) |
| @@ -1554,57 +1552,13 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 1554 | /* We cannot do exclusive creation on a positive dentry */ | 1552 | /* We cannot do exclusive creation on a positive dentry */ |
| 1555 | if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) | 1553 | if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) |
| 1556 | goto no_open_dput; | 1554 | goto no_open_dput; |
| 1557 | /* We can't create new files here */ | ||
| 1558 | openflags &= ~(O_CREAT|O_EXCL); | ||
| 1559 | |||
| 1560 | ctx = create_nfs_open_context(dentry, openflags); | ||
| 1561 | ret = PTR_ERR(ctx); | ||
| 1562 | if (IS_ERR(ctx)) | ||
| 1563 | goto out; | ||
| 1564 | 1555 | ||
| 1565 | attr.ia_valid = ATTR_OPEN; | 1556 | /* Let f_op->open() actually open (and revalidate) the file */ |
| 1566 | if (openflags & O_TRUNC) { | 1557 | ret = 1; |
| 1567 | attr.ia_valid |= ATTR_SIZE; | ||
| 1568 | attr.ia_size = 0; | ||
| 1569 | nfs_wb_all(inode); | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | /* | ||
| 1573 | * Note: we're not holding inode->i_mutex and so may be racing with | ||
| 1574 | * operations that change the directory. We therefore save the | ||
| 1575 | * change attribute *before* we do the RPC call. | ||
| 1576 | */ | ||
| 1577 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); | ||
| 1578 | if (IS_ERR(inode)) { | ||
| 1579 | ret = PTR_ERR(inode); | ||
| 1580 | switch (ret) { | ||
| 1581 | case -EPERM: | ||
| 1582 | case -EACCES: | ||
| 1583 | case -EDQUOT: | ||
| 1584 | case -ENOSPC: | ||
| 1585 | case -EROFS: | ||
| 1586 | goto out_put_ctx; | ||
| 1587 | default: | ||
| 1588 | goto out_drop; | ||
| 1589 | } | ||
| 1590 | } | ||
| 1591 | iput(inode); | ||
| 1592 | if (inode != dentry->d_inode) | ||
| 1593 | goto out_drop; | ||
| 1594 | 1558 | ||
| 1595 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 1596 | ret = nfs_intent_set_file(nd, ctx); | ||
| 1597 | if (ret >= 0) | ||
| 1598 | ret = 1; | ||
| 1599 | out: | 1559 | out: |
| 1600 | dput(parent); | 1560 | dput(parent); |
| 1601 | return ret; | 1561 | return ret; |
| 1602 | out_drop: | ||
| 1603 | d_drop(dentry); | ||
| 1604 | ret = 0; | ||
| 1605 | out_put_ctx: | ||
| 1606 | put_nfs_open_context(ctx); | ||
| 1607 | goto out; | ||
| 1608 | 1562 | ||
| 1609 | no_open_dput: | 1563 | no_open_dput: |
| 1610 | dput(parent); | 1564 | dput(parent); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 56311ca5f9f8..a6708e6b438d 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -879,12 +879,81 @@ const struct file_operations nfs_file_operations = { | |||
| 879 | static int | 879 | static int |
| 880 | nfs4_file_open(struct inode *inode, struct file *filp) | 880 | nfs4_file_open(struct inode *inode, struct file *filp) |
| 881 | { | 881 | { |
| 882 | struct nfs_open_context *ctx; | ||
| 883 | struct dentry *dentry = filp->f_path.dentry; | ||
| 884 | struct dentry *parent = NULL; | ||
| 885 | struct inode *dir; | ||
| 886 | unsigned openflags = filp->f_flags; | ||
| 887 | struct iattr attr; | ||
| 888 | int err; | ||
| 889 | |||
| 890 | BUG_ON(inode != dentry->d_inode); | ||
| 882 | /* | 891 | /* |
| 883 | * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to | 892 | * If no cached dentry exists or if it's negative, NFSv4 handled the |
| 884 | * this point, then something is very wrong | 893 | * opens in ->lookup() or ->create(). |
| 894 | * | ||
| 895 | * We only get this far for a cached positive dentry. We skipped | ||
| 896 | * revalidation, so handle it here by dropping the dentry and returning | ||
| 897 | * -EOPENSTALE. The VFS will retry the lookup/create/open. | ||
| 885 | */ | 898 | */ |
| 886 | dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp); | 899 | |
| 887 | return -ENOTDIR; | 900 | dprintk("NFS: open file(%s/%s)\n", |
| 901 | dentry->d_parent->d_name.name, | ||
| 902 | dentry->d_name.name); | ||
| 903 | |||
| 904 | if ((openflags & O_ACCMODE) == 3) | ||
| 905 | openflags--; | ||
| 906 | |||
| 907 | /* We can't create new files here */ | ||
| 908 | openflags &= ~(O_CREAT|O_EXCL); | ||
| 909 | |||
| 910 | parent = dget_parent(dentry); | ||
| 911 | dir = parent->d_inode; | ||
| 912 | |||
| 913 | ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode); | ||
| 914 | err = PTR_ERR(ctx); | ||
| 915 | if (IS_ERR(ctx)) | ||
| 916 | goto out; | ||
| 917 | |||
| 918 | attr.ia_valid = ATTR_OPEN; | ||
| 919 | if (openflags & O_TRUNC) { | ||
| 920 | attr.ia_valid |= ATTR_SIZE; | ||
| 921 | attr.ia_size = 0; | ||
| 922 | nfs_wb_all(inode); | ||
| 923 | } | ||
| 924 | |||
| 925 | inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr); | ||
| 926 | if (IS_ERR(inode)) { | ||
| 927 | err = PTR_ERR(inode); | ||
| 928 | switch (err) { | ||
| 929 | case -EPERM: | ||
| 930 | case -EACCES: | ||
| 931 | case -EDQUOT: | ||
| 932 | case -ENOSPC: | ||
| 933 | case -EROFS: | ||
| 934 | goto out_put_ctx; | ||
| 935 | default: | ||
| 936 | goto out_drop; | ||
| 937 | } | ||
| 938 | } | ||
| 939 | iput(inode); | ||
| 940 | if (inode != dentry->d_inode) | ||
| 941 | goto out_drop; | ||
| 942 | |||
| 943 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
| 944 | nfs_file_set_open_context(filp, ctx); | ||
| 945 | err = 0; | ||
| 946 | |||
| 947 | out_put_ctx: | ||
| 948 | put_nfs_open_context(ctx); | ||
| 949 | out: | ||
| 950 | dput(parent); | ||
| 951 | return err; | ||
| 952 | |||
| 953 | out_drop: | ||
| 954 | d_drop(dentry); | ||
| 955 | err = -EOPENSTALE; | ||
| 956 | goto out_put_ctx; | ||
| 888 | } | 957 | } |
| 889 | 958 | ||
| 890 | const struct file_operations nfs4_file_operations = { | 959 | const struct file_operations nfs4_file_operations = { |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 0bb2c2010b95..b72847988b78 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
| @@ -508,31 +508,29 @@ static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh, | |||
| 508 | return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen); | 508 | return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen); |
| 509 | } | 509 | } |
| 510 | 510 | ||
| 511 | static int nilfs_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp, | 511 | static int nilfs_encode_fh(struct inode *inode, __u32 *fh, int *lenp, |
| 512 | int connectable) | 512 | struct inode *parent) |
| 513 | { | 513 | { |
| 514 | struct nilfs_fid *fid = (struct nilfs_fid *)fh; | 514 | struct nilfs_fid *fid = (struct nilfs_fid *)fh; |
| 515 | struct inode *inode = dentry->d_inode; | ||
| 516 | struct nilfs_root *root = NILFS_I(inode)->i_root; | 515 | struct nilfs_root *root = NILFS_I(inode)->i_root; |
| 517 | int type; | 516 | int type; |
| 518 | 517 | ||
| 519 | if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE || | 518 | if (parent && *lenp < NILFS_FID_SIZE_CONNECTABLE) { |
| 520 | (connectable && *lenp < NILFS_FID_SIZE_CONNECTABLE)) | 519 | *lenp = NILFS_FID_SIZE_CONNECTABLE; |
| 520 | return 255; | ||
| 521 | } | ||
| 522 | if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE) { | ||
| 523 | *lenp = NILFS_FID_SIZE_NON_CONNECTABLE; | ||
| 521 | return 255; | 524 | return 255; |
| 525 | } | ||
| 522 | 526 | ||
| 523 | fid->cno = root->cno; | 527 | fid->cno = root->cno; |
| 524 | fid->ino = inode->i_ino; | 528 | fid->ino = inode->i_ino; |
| 525 | fid->gen = inode->i_generation; | 529 | fid->gen = inode->i_generation; |
| 526 | 530 | ||
| 527 | if (connectable && !S_ISDIR(inode->i_mode)) { | 531 | if (parent) { |
| 528 | struct inode *parent; | ||
| 529 | |||
| 530 | spin_lock(&dentry->d_lock); | ||
| 531 | parent = dentry->d_parent->d_inode; | ||
| 532 | fid->parent_ino = parent->i_ino; | 532 | fid->parent_ino = parent->i_ino; |
| 533 | fid->parent_gen = parent->i_generation; | 533 | fid->parent_gen = parent->i_generation; |
| 534 | spin_unlock(&dentry->d_lock); | ||
| 535 | |||
| 536 | type = FILEID_NILFS_WITH_PARENT; | 534 | type = FILEID_NILFS_WITH_PARENT; |
| 537 | *lenp = NILFS_FID_SIZE_CONNECTABLE; | 535 | *lenp = NILFS_FID_SIZE_CONNECTABLE; |
| 538 | } else { | 536 | } else { |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index ccb14d3fc0de..b39c5c161adb 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
| @@ -123,7 +123,7 @@ int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) | |||
| 123 | } | 123 | } |
| 124 | EXPORT_SYMBOL_GPL(__fsnotify_parent); | 124 | EXPORT_SYMBOL_GPL(__fsnotify_parent); |
| 125 | 125 | ||
| 126 | static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, | 126 | static int send_to_group(struct inode *to_tell, |
| 127 | struct fsnotify_mark *inode_mark, | 127 | struct fsnotify_mark *inode_mark, |
| 128 | struct fsnotify_mark *vfsmount_mark, | 128 | struct fsnotify_mark *vfsmount_mark, |
| 129 | __u32 mask, void *data, | 129 | __u32 mask, void *data, |
| @@ -168,10 +168,10 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, | |||
| 168 | vfsmount_test_mask &= ~inode_mark->ignored_mask; | 168 | vfsmount_test_mask &= ~inode_mark->ignored_mask; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x inode_mark=%p" | 171 | pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" |
| 172 | " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" | 172 | " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" |
| 173 | " data=%p data_is=%d cookie=%d event=%p\n", | 173 | " data=%p data_is=%d cookie=%d event=%p\n", |
| 174 | __func__, group, to_tell, mnt, mask, inode_mark, | 174 | __func__, group, to_tell, mask, inode_mark, |
| 175 | inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, | 175 | inode_test_mask, vfsmount_mark, vfsmount_test_mask, data, |
| 176 | data_is, cookie, *event); | 176 | data_is, cookie, *event); |
| 177 | 177 | ||
| @@ -258,16 +258,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, | |||
| 258 | 258 | ||
| 259 | if (inode_group > vfsmount_group) { | 259 | if (inode_group > vfsmount_group) { |
| 260 | /* handle inode */ | 260 | /* handle inode */ |
| 261 | ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, | 261 | ret = send_to_group(to_tell, inode_mark, NULL, mask, data, |
| 262 | data_is, cookie, file_name, &event); | 262 | data_is, cookie, file_name, &event); |
| 263 | /* we didn't use the vfsmount_mark */ | 263 | /* we didn't use the vfsmount_mark */ |
| 264 | vfsmount_group = NULL; | 264 | vfsmount_group = NULL; |
| 265 | } else if (vfsmount_group > inode_group) { | 265 | } else if (vfsmount_group > inode_group) { |
| 266 | ret = send_to_group(to_tell, &mnt->mnt, NULL, vfsmount_mark, mask, data, | 266 | ret = send_to_group(to_tell, NULL, vfsmount_mark, mask, data, |
| 267 | data_is, cookie, file_name, &event); | 267 | data_is, cookie, file_name, &event); |
| 268 | inode_group = NULL; | 268 | inode_group = NULL; |
| 269 | } else { | 269 | } else { |
| 270 | ret = send_to_group(to_tell, &mnt->mnt, inode_mark, vfsmount_mark, | 270 | ret = send_to_group(to_tell, inode_mark, vfsmount_mark, |
| 271 | mask, data, data_is, cookie, file_name, | 271 | mask, data, data_is, cookie, file_name, |
| 272 | &event); | 272 | &event); |
| 273 | } | 273 | } |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 8639169221c7..7389d2d5e51d 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
| @@ -2096,7 +2096,9 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb, | |||
| 2096 | err = file_remove_suid(file); | 2096 | err = file_remove_suid(file); |
| 2097 | if (err) | 2097 | if (err) |
| 2098 | goto out; | 2098 | goto out; |
| 2099 | file_update_time(file); | 2099 | err = file_update_time(file); |
| 2100 | if (err) | ||
| 2101 | goto out; | ||
| 2100 | written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos, | 2102 | written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos, |
| 2101 | count); | 2103 | count); |
| 2102 | out: | 2104 | out: |
diff --git a/fs/ocfs2/blockcheck.c b/fs/ocfs2/blockcheck.c index c7ee03c22226..0725e6054650 100644 --- a/fs/ocfs2/blockcheck.c +++ b/fs/ocfs2/blockcheck.c | |||
| @@ -422,45 +422,46 @@ int ocfs2_block_check_validate(void *data, size_t blocksize, | |||
| 422 | struct ocfs2_blockcheck_stats *stats) | 422 | struct ocfs2_blockcheck_stats *stats) |
| 423 | { | 423 | { |
| 424 | int rc = 0; | 424 | int rc = 0; |
| 425 | struct ocfs2_block_check check; | 425 | u32 bc_crc32e; |
| 426 | u16 bc_ecc; | ||
| 426 | u32 crc, ecc; | 427 | u32 crc, ecc; |
| 427 | 428 | ||
| 428 | ocfs2_blockcheck_inc_check(stats); | 429 | ocfs2_blockcheck_inc_check(stats); |
| 429 | 430 | ||
| 430 | check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); | 431 | bc_crc32e = le32_to_cpu(bc->bc_crc32e); |
| 431 | check.bc_ecc = le16_to_cpu(bc->bc_ecc); | 432 | bc_ecc = le16_to_cpu(bc->bc_ecc); |
| 432 | 433 | ||
| 433 | memset(bc, 0, sizeof(struct ocfs2_block_check)); | 434 | memset(bc, 0, sizeof(struct ocfs2_block_check)); |
| 434 | 435 | ||
| 435 | /* Fast path - if the crc32 validates, we're good to go */ | 436 | /* Fast path - if the crc32 validates, we're good to go */ |
| 436 | crc = crc32_le(~0, data, blocksize); | 437 | crc = crc32_le(~0, data, blocksize); |
| 437 | if (crc == check.bc_crc32e) | 438 | if (crc == bc_crc32e) |
| 438 | goto out; | 439 | goto out; |
| 439 | 440 | ||
| 440 | ocfs2_blockcheck_inc_failure(stats); | 441 | ocfs2_blockcheck_inc_failure(stats); |
| 441 | mlog(ML_ERROR, | 442 | mlog(ML_ERROR, |
| 442 | "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n", | 443 | "CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n", |
| 443 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 444 | (unsigned int)bc_crc32e, (unsigned int)crc); |
| 444 | 445 | ||
| 445 | /* Ok, try ECC fixups */ | 446 | /* Ok, try ECC fixups */ |
| 446 | ecc = ocfs2_hamming_encode_block(data, blocksize); | 447 | ecc = ocfs2_hamming_encode_block(data, blocksize); |
| 447 | ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc); | 448 | ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc); |
| 448 | 449 | ||
| 449 | /* And check the crc32 again */ | 450 | /* And check the crc32 again */ |
| 450 | crc = crc32_le(~0, data, blocksize); | 451 | crc = crc32_le(~0, data, blocksize); |
| 451 | if (crc == check.bc_crc32e) { | 452 | if (crc == bc_crc32e) { |
| 452 | ocfs2_blockcheck_inc_recover(stats); | 453 | ocfs2_blockcheck_inc_recover(stats); |
| 453 | goto out; | 454 | goto out; |
| 454 | } | 455 | } |
| 455 | 456 | ||
| 456 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n", | 457 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n", |
| 457 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 458 | (unsigned int)bc_crc32e, (unsigned int)crc); |
| 458 | 459 | ||
| 459 | rc = -EIO; | 460 | rc = -EIO; |
| 460 | 461 | ||
| 461 | out: | 462 | out: |
| 462 | bc->bc_crc32e = cpu_to_le32(check.bc_crc32e); | 463 | bc->bc_crc32e = cpu_to_le32(bc_crc32e); |
| 463 | bc->bc_ecc = cpu_to_le16(check.bc_ecc); | 464 | bc->bc_ecc = cpu_to_le16(bc_ecc); |
| 464 | 465 | ||
| 465 | return rc; | 466 | return rc; |
| 466 | } | 467 | } |
| @@ -528,7 +529,8 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 528 | struct ocfs2_blockcheck_stats *stats) | 529 | struct ocfs2_blockcheck_stats *stats) |
| 529 | { | 530 | { |
| 530 | int i, rc = 0; | 531 | int i, rc = 0; |
| 531 | struct ocfs2_block_check check; | 532 | u32 bc_crc32e; |
| 533 | u16 bc_ecc; | ||
| 532 | u32 crc, ecc, fix; | 534 | u32 crc, ecc, fix; |
| 533 | 535 | ||
| 534 | BUG_ON(nr < 0); | 536 | BUG_ON(nr < 0); |
| @@ -538,21 +540,21 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 538 | 540 | ||
| 539 | ocfs2_blockcheck_inc_check(stats); | 541 | ocfs2_blockcheck_inc_check(stats); |
| 540 | 542 | ||
| 541 | check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); | 543 | bc_crc32e = le32_to_cpu(bc->bc_crc32e); |
| 542 | check.bc_ecc = le16_to_cpu(bc->bc_ecc); | 544 | bc_ecc = le16_to_cpu(bc->bc_ecc); |
| 543 | 545 | ||
| 544 | memset(bc, 0, sizeof(struct ocfs2_block_check)); | 546 | memset(bc, 0, sizeof(struct ocfs2_block_check)); |
| 545 | 547 | ||
| 546 | /* Fast path - if the crc32 validates, we're good to go */ | 548 | /* Fast path - if the crc32 validates, we're good to go */ |
| 547 | for (i = 0, crc = ~0; i < nr; i++) | 549 | for (i = 0, crc = ~0; i < nr; i++) |
| 548 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); | 550 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); |
| 549 | if (crc == check.bc_crc32e) | 551 | if (crc == bc_crc32e) |
| 550 | goto out; | 552 | goto out; |
| 551 | 553 | ||
| 552 | ocfs2_blockcheck_inc_failure(stats); | 554 | ocfs2_blockcheck_inc_failure(stats); |
| 553 | mlog(ML_ERROR, | 555 | mlog(ML_ERROR, |
| 554 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", | 556 | "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", |
| 555 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 557 | (unsigned int)bc_crc32e, (unsigned int)crc); |
| 556 | 558 | ||
| 557 | /* Ok, try ECC fixups */ | 559 | /* Ok, try ECC fixups */ |
| 558 | for (i = 0, ecc = 0; i < nr; i++) { | 560 | for (i = 0, ecc = 0; i < nr; i++) { |
| @@ -565,7 +567,7 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 565 | bhs[i]->b_size * 8, | 567 | bhs[i]->b_size * 8, |
| 566 | bhs[i]->b_size * 8 * i); | 568 | bhs[i]->b_size * 8 * i); |
| 567 | } | 569 | } |
| 568 | fix = ecc ^ check.bc_ecc; | 570 | fix = ecc ^ bc_ecc; |
| 569 | for (i = 0; i < nr; i++) { | 571 | for (i = 0; i < nr; i++) { |
| 570 | /* | 572 | /* |
| 571 | * Try the fix against each buffer. It will only affect | 573 | * Try the fix against each buffer. It will only affect |
| @@ -578,19 +580,19 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, | |||
| 578 | /* And check the crc32 again */ | 580 | /* And check the crc32 again */ |
| 579 | for (i = 0, crc = ~0; i < nr; i++) | 581 | for (i = 0, crc = ~0; i < nr; i++) |
| 580 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); | 582 | crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); |
| 581 | if (crc == check.bc_crc32e) { | 583 | if (crc == bc_crc32e) { |
| 582 | ocfs2_blockcheck_inc_recover(stats); | 584 | ocfs2_blockcheck_inc_recover(stats); |
| 583 | goto out; | 585 | goto out; |
| 584 | } | 586 | } |
| 585 | 587 | ||
| 586 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", | 588 | mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", |
| 587 | (unsigned int)check.bc_crc32e, (unsigned int)crc); | 589 | (unsigned int)bc_crc32e, (unsigned int)crc); |
| 588 | 590 | ||
| 589 | rc = -EIO; | 591 | rc = -EIO; |
| 590 | 592 | ||
| 591 | out: | 593 | out: |
| 592 | bc->bc_crc32e = cpu_to_le32(check.bc_crc32e); | 594 | bc->bc_crc32e = cpu_to_le32(bc_crc32e); |
| 593 | bc->bc_ecc = cpu_to_le16(check.bc_ecc); | 595 | bc->bc_ecc = cpu_to_le16(bc_ecc); |
| 594 | 596 | ||
| 595 | return rc; | 597 | return rc; |
| 596 | } | 598 | } |
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c index 3a3ed4bb794b..fbec0be62326 100644 --- a/fs/ocfs2/dlm/dlmast.c +++ b/fs/ocfs2/dlm/dlmast.c | |||
| @@ -293,7 +293,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data, | |||
| 293 | struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf; | 293 | struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf; |
| 294 | char *name; | 294 | char *name; |
| 295 | struct list_head *iter, *head=NULL; | 295 | struct list_head *iter, *head=NULL; |
| 296 | u64 cookie; | 296 | __be64 cookie; |
| 297 | u32 flags; | 297 | u32 flags; |
| 298 | u8 node; | 298 | u8 node; |
| 299 | 299 | ||
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index a5952ceecba5..de854cca12a2 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h | |||
| @@ -679,7 +679,7 @@ struct dlm_query_join_packet { | |||
| 679 | }; | 679 | }; |
| 680 | 680 | ||
| 681 | union dlm_query_join_response { | 681 | union dlm_query_join_response { |
| 682 | u32 intval; | 682 | __be32 intval; |
| 683 | struct dlm_query_join_packet packet; | 683 | struct dlm_query_join_packet packet; |
| 684 | }; | 684 | }; |
| 685 | 685 | ||
| @@ -755,8 +755,8 @@ struct dlm_query_region { | |||
| 755 | struct dlm_node_info { | 755 | struct dlm_node_info { |
| 756 | u8 ni_nodenum; | 756 | u8 ni_nodenum; |
| 757 | u8 pad1; | 757 | u8 pad1; |
| 758 | u16 ni_ipv4_port; | 758 | __be16 ni_ipv4_port; |
| 759 | u32 ni_ipv4_address; | 759 | __be32 ni_ipv4_address; |
| 760 | }; | 760 | }; |
| 761 | 761 | ||
| 762 | struct dlm_query_nodeinfo { | 762 | struct dlm_query_nodeinfo { |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 92f2ead0fab6..9e89d70df337 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
| @@ -818,7 +818,7 @@ static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet, | |||
| 818 | union dlm_query_join_response response; | 818 | union dlm_query_join_response response; |
| 819 | 819 | ||
| 820 | response.packet = *packet; | 820 | response.packet = *packet; |
| 821 | *wire = cpu_to_be32(response.intval); | 821 | *wire = be32_to_cpu(response.intval); |
| 822 | } | 822 | } |
| 823 | 823 | ||
| 824 | static void dlm_query_join_wire_to_packet(u32 wire, | 824 | static void dlm_query_join_wire_to_packet(u32 wire, |
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 745db42528d5..322216a5f0dd 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c | |||
| @@ -177,21 +177,23 @@ bail: | |||
| 177 | return parent; | 177 | return parent; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, | 180 | static int ocfs2_encode_fh(struct inode *inode, u32 *fh_in, int *max_len, |
| 181 | int connectable) | 181 | struct inode *parent) |
| 182 | { | 182 | { |
| 183 | struct inode *inode = dentry->d_inode; | ||
| 184 | int len = *max_len; | 183 | int len = *max_len; |
| 185 | int type = 1; | 184 | int type = 1; |
| 186 | u64 blkno; | 185 | u64 blkno; |
| 187 | u32 generation; | 186 | u32 generation; |
| 188 | __le32 *fh = (__force __le32 *) fh_in; | 187 | __le32 *fh = (__force __le32 *) fh_in; |
| 189 | 188 | ||
| 189 | #ifdef TRACE_HOOKS_ARE_NOT_BRAINDEAD_IN_YOUR_OPINION | ||
| 190 | #error "You go ahead and fix that mess, then. Somehow" | ||
| 190 | trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len, | 191 | trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len, |
| 191 | dentry->d_name.name, | 192 | dentry->d_name.name, |
| 192 | fh, len, connectable); | 193 | fh, len, connectable); |
| 194 | #endif | ||
| 193 | 195 | ||
| 194 | if (connectable && (len < 6)) { | 196 | if (parent && (len < 6)) { |
| 195 | *max_len = 6; | 197 | *max_len = 6; |
| 196 | type = 255; | 198 | type = 255; |
| 197 | goto bail; | 199 | goto bail; |
| @@ -211,12 +213,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, | |||
| 211 | fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff)); | 213 | fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff)); |
| 212 | fh[2] = cpu_to_le32(generation); | 214 | fh[2] = cpu_to_le32(generation); |
| 213 | 215 | ||
| 214 | if (connectable && !S_ISDIR(inode->i_mode)) { | 216 | if (parent) { |
| 215 | struct inode *parent; | ||
| 216 | |||
| 217 | spin_lock(&dentry->d_lock); | ||
| 218 | |||
| 219 | parent = dentry->d_parent->d_inode; | ||
| 220 | blkno = OCFS2_I(parent)->ip_blkno; | 217 | blkno = OCFS2_I(parent)->ip_blkno; |
| 221 | generation = parent->i_generation; | 218 | generation = parent->i_generation; |
| 222 | 219 | ||
| @@ -224,8 +221,6 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, | |||
| 224 | fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff)); | 221 | fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff)); |
| 225 | fh[5] = cpu_to_le32(generation); | 222 | fh[5] = cpu_to_le32(generation); |
| 226 | 223 | ||
| 227 | spin_unlock(&dentry->d_lock); | ||
| 228 | |||
| 229 | len = 6; | 224 | len = 6; |
| 230 | type = 2; | 225 | type = 2; |
| 231 | 226 | ||
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 735514ca400f..d89e08a81eda 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
| @@ -273,11 +273,13 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
| 273 | inode->i_gid = le32_to_cpu(fe->i_gid); | 273 | inode->i_gid = le32_to_cpu(fe->i_gid); |
| 274 | 274 | ||
| 275 | /* Fast symlinks will have i_size but no allocated clusters. */ | 275 | /* Fast symlinks will have i_size but no allocated clusters. */ |
| 276 | if (S_ISLNK(inode->i_mode) && !fe->i_clusters) | 276 | if (S_ISLNK(inode->i_mode) && !fe->i_clusters) { |
| 277 | inode->i_blocks = 0; | 277 | inode->i_blocks = 0; |
| 278 | else | 278 | inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops; |
| 279 | } else { | ||
| 279 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 280 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
| 280 | inode->i_mapping->a_ops = &ocfs2_aops; | 281 | inode->i_mapping->a_ops = &ocfs2_aops; |
| 282 | } | ||
| 281 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); | 283 | inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); |
| 282 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); | 284 | inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); |
| 283 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); | 285 | inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); |
| @@ -331,10 +333,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, | |||
| 331 | OCFS2_I(inode)->ip_dir_lock_gen = 1; | 333 | OCFS2_I(inode)->ip_dir_lock_gen = 1; |
| 332 | break; | 334 | break; |
| 333 | case S_IFLNK: | 335 | case S_IFLNK: |
| 334 | if (ocfs2_inode_is_fast_symlink(inode)) | 336 | inode->i_op = &ocfs2_symlink_inode_operations; |
| 335 | inode->i_op = &ocfs2_fast_symlink_inode_operations; | ||
| 336 | else | ||
| 337 | inode->i_op = &ocfs2_symlink_inode_operations; | ||
| 338 | i_size_write(inode, le64_to_cpu(fe->i_size)); | 337 | i_size_write(inode, le64_to_cpu(fe->i_size)); |
| 339 | break; | 338 | break; |
| 340 | default: | 339 | default: |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index a1a1bfd652c9..d96f7f81d8dd 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
| @@ -864,7 +864,7 @@ int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info, | |||
| 864 | if (status) | 864 | if (status) |
| 865 | break; | 865 | break; |
| 866 | 866 | ||
| 867 | reqp = (struct ocfs2_info_request *)(unsigned long)req_addr; | 867 | reqp = (struct ocfs2_info_request __user *)(unsigned long)req_addr; |
| 868 | if (!reqp) { | 868 | if (!reqp) { |
| 869 | status = -EINVAL; | 869 | status = -EINVAL; |
| 870 | goto bail; | 870 | goto bail; |
| @@ -888,9 +888,11 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 888 | struct ocfs2_space_resv sr; | 888 | struct ocfs2_space_resv sr; |
| 889 | struct ocfs2_new_group_input input; | 889 | struct ocfs2_new_group_input input; |
| 890 | struct reflink_arguments args; | 890 | struct reflink_arguments args; |
| 891 | const char *old_path, *new_path; | 891 | const char __user *old_path; |
| 892 | const char __user *new_path; | ||
| 892 | bool preserve; | 893 | bool preserve; |
| 893 | struct ocfs2_info info; | 894 | struct ocfs2_info info; |
| 895 | void __user *argp = (void __user *)arg; | ||
| 894 | 896 | ||
| 895 | switch (cmd) { | 897 | switch (cmd) { |
| 896 | case OCFS2_IOC_GETFLAGS: | 898 | case OCFS2_IOC_GETFLAGS: |
| @@ -937,17 +939,15 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 937 | 939 | ||
| 938 | return ocfs2_group_add(inode, &input); | 940 | return ocfs2_group_add(inode, &input); |
| 939 | case OCFS2_IOC_REFLINK: | 941 | case OCFS2_IOC_REFLINK: |
| 940 | if (copy_from_user(&args, (struct reflink_arguments *)arg, | 942 | if (copy_from_user(&args, argp, sizeof(args))) |
| 941 | sizeof(args))) | ||
| 942 | return -EFAULT; | 943 | return -EFAULT; |
| 943 | old_path = (const char *)(unsigned long)args.old_path; | 944 | old_path = (const char __user *)(unsigned long)args.old_path; |
| 944 | new_path = (const char *)(unsigned long)args.new_path; | 945 | new_path = (const char __user *)(unsigned long)args.new_path; |
| 945 | preserve = (args.preserve != 0); | 946 | preserve = (args.preserve != 0); |
| 946 | 947 | ||
| 947 | return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve); | 948 | return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve); |
| 948 | case OCFS2_IOC_INFO: | 949 | case OCFS2_IOC_INFO: |
| 949 | if (copy_from_user(&info, (struct ocfs2_info __user *)arg, | 950 | if (copy_from_user(&info, argp, sizeof(struct ocfs2_info))) |
| 950 | sizeof(struct ocfs2_info))) | ||
| 951 | return -EFAULT; | 951 | return -EFAULT; |
| 952 | 952 | ||
| 953 | return ocfs2_info_handle(inode, &info, 0); | 953 | return ocfs2_info_handle(inode, &info, 0); |
| @@ -960,22 +960,20 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 960 | if (!capable(CAP_SYS_ADMIN)) | 960 | if (!capable(CAP_SYS_ADMIN)) |
| 961 | return -EPERM; | 961 | return -EPERM; |
| 962 | 962 | ||
| 963 | if (copy_from_user(&range, (struct fstrim_range *)arg, | 963 | if (copy_from_user(&range, argp, sizeof(range))) |
| 964 | sizeof(range))) | ||
| 965 | return -EFAULT; | 964 | return -EFAULT; |
| 966 | 965 | ||
| 967 | ret = ocfs2_trim_fs(sb, &range); | 966 | ret = ocfs2_trim_fs(sb, &range); |
| 968 | if (ret < 0) | 967 | if (ret < 0) |
| 969 | return ret; | 968 | return ret; |
| 970 | 969 | ||
| 971 | if (copy_to_user((struct fstrim_range *)arg, &range, | 970 | if (copy_to_user(argp, &range, sizeof(range))) |
| 972 | sizeof(range))) | ||
| 973 | return -EFAULT; | 971 | return -EFAULT; |
| 974 | 972 | ||
| 975 | return 0; | 973 | return 0; |
| 976 | } | 974 | } |
| 977 | case OCFS2_IOC_MOVE_EXT: | 975 | case OCFS2_IOC_MOVE_EXT: |
| 978 | return ocfs2_ioctl_move_extents(filp, (void __user *)arg); | 976 | return ocfs2_ioctl_move_extents(filp, argp); |
| 979 | default: | 977 | default: |
| 980 | return -ENOTTY; | 978 | return -ENOTTY; |
| 981 | } | 979 | } |
| @@ -988,6 +986,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
| 988 | struct reflink_arguments args; | 986 | struct reflink_arguments args; |
| 989 | struct inode *inode = file->f_path.dentry->d_inode; | 987 | struct inode *inode = file->f_path.dentry->d_inode; |
| 990 | struct ocfs2_info info; | 988 | struct ocfs2_info info; |
| 989 | void __user *argp = (void __user *)arg; | ||
| 991 | 990 | ||
| 992 | switch (cmd) { | 991 | switch (cmd) { |
| 993 | case OCFS2_IOC32_GETFLAGS: | 992 | case OCFS2_IOC32_GETFLAGS: |
| @@ -1006,16 +1005,14 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
| 1006 | case FITRIM: | 1005 | case FITRIM: |
| 1007 | break; | 1006 | break; |
| 1008 | case OCFS2_IOC_REFLINK: | 1007 | case OCFS2_IOC_REFLINK: |
| 1009 | if (copy_from_user(&args, (struct reflink_arguments *)arg, | 1008 | if (copy_from_user(&args, argp, sizeof(args))) |
| 1010 | sizeof(args))) | ||
| 1011 | return -EFAULT; | 1009 | return -EFAULT; |
| 1012 | preserve = (args.preserve != 0); | 1010 | preserve = (args.preserve != 0); |
| 1013 | 1011 | ||
| 1014 | return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path), | 1012 | return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path), |
| 1015 | compat_ptr(args.new_path), preserve); | 1013 | compat_ptr(args.new_path), preserve); |
| 1016 | case OCFS2_IOC_INFO: | 1014 | case OCFS2_IOC_INFO: |
| 1017 | if (copy_from_user(&info, (struct ocfs2_info __user *)arg, | 1015 | if (copy_from_user(&info, argp, sizeof(struct ocfs2_info))) |
| 1018 | sizeof(struct ocfs2_info))) | ||
| 1019 | return -EFAULT; | 1016 | return -EFAULT; |
| 1020 | 1017 | ||
| 1021 | return ocfs2_info_handle(inode, &info, 1); | 1018 | return ocfs2_info_handle(inode, &info, 1); |
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index b1e3fce72ea4..6083432f667e 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
| @@ -1082,8 +1082,7 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp) | |||
| 1082 | context->file = filp; | 1082 | context->file = filp; |
| 1083 | 1083 | ||
| 1084 | if (argp) { | 1084 | if (argp) { |
| 1085 | if (copy_from_user(&range, (struct ocfs2_move_extents *)argp, | 1085 | if (copy_from_user(&range, argp, sizeof(range))) { |
| 1086 | sizeof(range))) { | ||
| 1087 | status = -EFAULT; | 1086 | status = -EFAULT; |
| 1088 | goto out; | 1087 | goto out; |
| 1089 | } | 1088 | } |
| @@ -1138,8 +1137,7 @@ out: | |||
| 1138 | * length and new_offset even if failure happens somewhere. | 1137 | * length and new_offset even if failure happens somewhere. |
| 1139 | */ | 1138 | */ |
| 1140 | if (argp) { | 1139 | if (argp) { |
| 1141 | if (copy_to_user((struct ocfs2_move_extents *)argp, &range, | 1140 | if (copy_to_user(argp, &range, sizeof(range))) |
| 1142 | sizeof(range))) | ||
| 1143 | status = -EFAULT; | 1141 | status = -EFAULT; |
| 1144 | } | 1142 | } |
| 1145 | 1143 | ||
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index a9856e3eaaf0..9f39c640cddf 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -1724,15 +1724,16 @@ static int ocfs2_symlink(struct inode *dir, | |||
| 1724 | fe = (struct ocfs2_dinode *) new_fe_bh->b_data; | 1724 | fe = (struct ocfs2_dinode *) new_fe_bh->b_data; |
| 1725 | inode->i_rdev = 0; | 1725 | inode->i_rdev = 0; |
| 1726 | newsize = l - 1; | 1726 | newsize = l - 1; |
| 1727 | inode->i_op = &ocfs2_symlink_inode_operations; | ||
| 1727 | if (l > ocfs2_fast_symlink_chars(sb)) { | 1728 | if (l > ocfs2_fast_symlink_chars(sb)) { |
| 1728 | u32 offset = 0; | 1729 | u32 offset = 0; |
| 1729 | 1730 | ||
| 1730 | inode->i_op = &ocfs2_symlink_inode_operations; | ||
| 1731 | status = dquot_alloc_space_nodirty(inode, | 1731 | status = dquot_alloc_space_nodirty(inode, |
| 1732 | ocfs2_clusters_to_bytes(osb->sb, 1)); | 1732 | ocfs2_clusters_to_bytes(osb->sb, 1)); |
| 1733 | if (status) | 1733 | if (status) |
| 1734 | goto bail; | 1734 | goto bail; |
| 1735 | did_quota = 1; | 1735 | did_quota = 1; |
| 1736 | inode->i_mapping->a_ops = &ocfs2_aops; | ||
| 1736 | status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, | 1737 | status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0, |
| 1737 | new_fe_bh, | 1738 | new_fe_bh, |
| 1738 | handle, data_ac, NULL, | 1739 | handle, data_ac, NULL, |
| @@ -1750,7 +1751,7 @@ static int ocfs2_symlink(struct inode *dir, | |||
| 1750 | i_size_write(inode, newsize); | 1751 | i_size_write(inode, newsize); |
| 1751 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 1752 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
| 1752 | } else { | 1753 | } else { |
| 1753 | inode->i_op = &ocfs2_fast_symlink_inode_operations; | 1754 | inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops; |
| 1754 | memcpy((char *) fe->id2.i_symlink, symname, l); | 1755 | memcpy((char *) fe->id2.i_symlink, symname, l); |
| 1755 | i_size_write(inode, newsize); | 1756 | i_size_write(inode, newsize); |
| 1756 | inode->i_blocks = 0; | 1757 | inode->i_blocks = 0; |
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 5d22872e2bb3..f1fbb4b552ad 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c | |||
| @@ -54,101 +54,40 @@ | |||
| 54 | #include "buffer_head_io.h" | 54 | #include "buffer_head_io.h" |
| 55 | 55 | ||
| 56 | 56 | ||
| 57 | static char *ocfs2_fast_symlink_getlink(struct inode *inode, | 57 | static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page) |
| 58 | struct buffer_head **bh) | ||
| 59 | { | 58 | { |
| 60 | int status; | 59 | struct inode *inode = page->mapping->host; |
| 61 | char *link = NULL; | 60 | struct buffer_head *bh; |
| 61 | int status = ocfs2_read_inode_block(inode, &bh); | ||
| 62 | struct ocfs2_dinode *fe; | 62 | struct ocfs2_dinode *fe; |
| 63 | const char *link; | ||
| 64 | void *kaddr; | ||
| 65 | size_t len; | ||
| 63 | 66 | ||
| 64 | status = ocfs2_read_inode_block(inode, bh); | ||
| 65 | if (status < 0) { | 67 | if (status < 0) { |
| 66 | mlog_errno(status); | 68 | mlog_errno(status); |
| 67 | link = ERR_PTR(status); | 69 | return status; |
| 68 | goto bail; | ||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | fe = (struct ocfs2_dinode *) (*bh)->b_data; | 72 | fe = (struct ocfs2_dinode *) bh->b_data; |
| 72 | link = (char *) fe->id2.i_symlink; | 73 | link = (char *) fe->id2.i_symlink; |
| 73 | bail: | 74 | /* will be less than a page size */ |
| 74 | 75 | len = strnlen(link, ocfs2_fast_symlink_chars(inode->i_sb)); | |
| 75 | return link; | 76 | kaddr = kmap_atomic(page); |
| 76 | } | 77 | memcpy(kaddr, link, len + 1); |
| 77 | 78 | kunmap_atomic(kaddr); | |
| 78 | static int ocfs2_readlink(struct dentry *dentry, | 79 | SetPageUptodate(page); |
| 79 | char __user *buffer, | 80 | unlock_page(page); |
| 80 | int buflen) | ||
| 81 | { | ||
| 82 | int ret; | ||
| 83 | char *link; | ||
| 84 | struct buffer_head *bh = NULL; | ||
| 85 | struct inode *inode = dentry->d_inode; | ||
| 86 | |||
| 87 | link = ocfs2_fast_symlink_getlink(inode, &bh); | ||
| 88 | if (IS_ERR(link)) { | ||
| 89 | ret = PTR_ERR(link); | ||
| 90 | goto out; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* | ||
| 94 | * Without vfsmount we can't update atime now, | ||
| 95 | * but we will update atime here ultimately. | ||
| 96 | */ | ||
| 97 | ret = vfs_readlink(dentry, buffer, buflen, link); | ||
| 98 | |||
| 99 | brelse(bh); | 81 | brelse(bh); |
| 100 | out: | 82 | return 0; |
| 101 | if (ret < 0) | ||
| 102 | mlog_errno(ret); | ||
| 103 | return ret; | ||
| 104 | } | 83 | } |
| 105 | 84 | ||
| 106 | static void *ocfs2_fast_follow_link(struct dentry *dentry, | 85 | const struct address_space_operations ocfs2_fast_symlink_aops = { |
| 107 | struct nameidata *nd) | 86 | .readpage = ocfs2_fast_symlink_readpage, |
| 108 | { | 87 | }; |
| 109 | int status = 0; | ||
| 110 | int len; | ||
| 111 | char *target, *link = ERR_PTR(-ENOMEM); | ||
| 112 | struct inode *inode = dentry->d_inode; | ||
| 113 | struct buffer_head *bh = NULL; | ||
| 114 | |||
| 115 | BUG_ON(!ocfs2_inode_is_fast_symlink(inode)); | ||
| 116 | target = ocfs2_fast_symlink_getlink(inode, &bh); | ||
| 117 | if (IS_ERR(target)) { | ||
| 118 | status = PTR_ERR(target); | ||
| 119 | mlog_errno(status); | ||
| 120 | goto bail; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Fast symlinks can't be large */ | ||
| 124 | len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb)); | ||
| 125 | link = kzalloc(len + 1, GFP_NOFS); | ||
| 126 | if (!link) { | ||
| 127 | status = -ENOMEM; | ||
| 128 | mlog_errno(status); | ||
| 129 | goto bail; | ||
| 130 | } | ||
| 131 | |||
| 132 | memcpy(link, target, len); | ||
| 133 | |||
| 134 | bail: | ||
| 135 | nd_set_link(nd, status ? ERR_PTR(status) : link); | ||
| 136 | brelse(bh); | ||
| 137 | |||
| 138 | if (status) | ||
| 139 | mlog_errno(status); | ||
| 140 | return NULL; | ||
| 141 | } | ||
| 142 | |||
| 143 | static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) | ||
| 144 | { | ||
| 145 | char *link = nd_get_link(nd); | ||
| 146 | if (!IS_ERR(link)) | ||
| 147 | kfree(link); | ||
| 148 | } | ||
| 149 | 88 | ||
| 150 | const struct inode_operations ocfs2_symlink_inode_operations = { | 89 | const struct inode_operations ocfs2_symlink_inode_operations = { |
| 151 | .readlink = page_readlink, | 90 | .readlink = generic_readlink, |
| 152 | .follow_link = page_follow_link_light, | 91 | .follow_link = page_follow_link_light, |
| 153 | .put_link = page_put_link, | 92 | .put_link = page_put_link, |
| 154 | .getattr = ocfs2_getattr, | 93 | .getattr = ocfs2_getattr, |
| @@ -159,15 +98,3 @@ const struct inode_operations ocfs2_symlink_inode_operations = { | |||
| 159 | .removexattr = generic_removexattr, | 98 | .removexattr = generic_removexattr, |
| 160 | .fiemap = ocfs2_fiemap, | 99 | .fiemap = ocfs2_fiemap, |
| 161 | }; | 100 | }; |
| 162 | const struct inode_operations ocfs2_fast_symlink_inode_operations = { | ||
| 163 | .readlink = ocfs2_readlink, | ||
| 164 | .follow_link = ocfs2_fast_follow_link, | ||
| 165 | .put_link = ocfs2_fast_put_link, | ||
| 166 | .getattr = ocfs2_getattr, | ||
| 167 | .setattr = ocfs2_setattr, | ||
| 168 | .setxattr = generic_setxattr, | ||
| 169 | .getxattr = generic_getxattr, | ||
| 170 | .listxattr = ocfs2_listxattr, | ||
| 171 | .removexattr = generic_removexattr, | ||
| 172 | .fiemap = ocfs2_fiemap, | ||
| 173 | }; | ||
diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h index 65a6c9c6ad51..71ee4245e919 100644 --- a/fs/ocfs2/symlink.h +++ b/fs/ocfs2/symlink.h | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #define OCFS2_SYMLINK_H | 27 | #define OCFS2_SYMLINK_H |
| 28 | 28 | ||
| 29 | extern const struct inode_operations ocfs2_symlink_inode_operations; | 29 | extern const struct inode_operations ocfs2_symlink_inode_operations; |
| 30 | extern const struct inode_operations ocfs2_fast_symlink_inode_operations; | 30 | extern const struct address_space_operations ocfs2_fast_symlink_aops; |
| 31 | 31 | ||
| 32 | /* | 32 | /* |
| 33 | * Test whether an inode is a fast symlink. | 33 | * Test whether an inode is a fast symlink. |
| @@ -654,10 +654,23 @@ static inline int __get_file_write_access(struct inode *inode, | |||
| 654 | return error; | 654 | return error; |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 657 | int open_check_o_direct(struct file *f) |
| 658 | struct file *f, | 658 | { |
| 659 | int (*open)(struct inode *, struct file *), | 659 | /* NB: we're sure to have correct a_ops only after f_op->open */ |
| 660 | const struct cred *cred) | 660 | if (f->f_flags & O_DIRECT) { |
| 661 | if (!f->f_mapping->a_ops || | ||
| 662 | ((!f->f_mapping->a_ops->direct_IO) && | ||
| 663 | (!f->f_mapping->a_ops->get_xip_mem))) { | ||
| 664 | return -EINVAL; | ||
| 665 | } | ||
| 666 | } | ||
| 667 | return 0; | ||
| 668 | } | ||
| 669 | |||
| 670 | static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt, | ||
| 671 | struct file *f, | ||
| 672 | int (*open)(struct inode *, struct file *), | ||
| 673 | const struct cred *cred) | ||
| 661 | { | 674 | { |
| 662 | static const struct file_operations empty_fops = {}; | 675 | static const struct file_operations empty_fops = {}; |
| 663 | struct inode *inode; | 676 | struct inode *inode; |
| @@ -713,16 +726,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
| 713 | 726 | ||
| 714 | file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); | 727 | file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); |
| 715 | 728 | ||
| 716 | /* NB: we're sure to have correct a_ops only after f_op->open */ | ||
| 717 | if (f->f_flags & O_DIRECT) { | ||
| 718 | if (!f->f_mapping->a_ops || | ||
| 719 | ((!f->f_mapping->a_ops->direct_IO) && | ||
| 720 | (!f->f_mapping->a_ops->get_xip_mem))) { | ||
| 721 | fput(f); | ||
| 722 | f = ERR_PTR(-EINVAL); | ||
| 723 | } | ||
| 724 | } | ||
| 725 | |||
| 726 | return f; | 729 | return f; |
| 727 | 730 | ||
| 728 | cleanup_all: | 731 | cleanup_all: |
| @@ -744,12 +747,29 @@ cleanup_all: | |||
| 744 | f->f_path.dentry = NULL; | 747 | f->f_path.dentry = NULL; |
| 745 | f->f_path.mnt = NULL; | 748 | f->f_path.mnt = NULL; |
| 746 | cleanup_file: | 749 | cleanup_file: |
| 747 | put_filp(f); | ||
| 748 | dput(dentry); | 750 | dput(dentry); |
| 749 | mntput(mnt); | 751 | mntput(mnt); |
| 750 | return ERR_PTR(error); | 752 | return ERR_PTR(error); |
| 751 | } | 753 | } |
| 752 | 754 | ||
| 755 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | ||
| 756 | struct file *f, | ||
| 757 | int (*open)(struct inode *, struct file *), | ||
| 758 | const struct cred *cred) | ||
| 759 | { | ||
| 760 | struct file *res = do_dentry_open(dentry, mnt, f, open, cred); | ||
| 761 | if (!IS_ERR(res)) { | ||
| 762 | int error = open_check_o_direct(f); | ||
| 763 | if (error) { | ||
| 764 | fput(res); | ||
| 765 | res = ERR_PTR(error); | ||
| 766 | } | ||
| 767 | } else { | ||
| 768 | put_filp(f); | ||
| 769 | } | ||
| 770 | return res; | ||
| 771 | } | ||
| 772 | |||
| 753 | /** | 773 | /** |
| 754 | * lookup_instantiate_filp - instantiates the open intent filp | 774 | * lookup_instantiate_filp - instantiates the open intent filp |
| 755 | * @nd: pointer to nameidata | 775 | * @nd: pointer to nameidata |
| @@ -804,13 +824,31 @@ struct file *nameidata_to_filp(struct nameidata *nd) | |||
| 804 | 824 | ||
| 805 | /* Pick up the filp from the open intent */ | 825 | /* Pick up the filp from the open intent */ |
| 806 | filp = nd->intent.open.file; | 826 | filp = nd->intent.open.file; |
| 807 | nd->intent.open.file = NULL; | ||
| 808 | 827 | ||
| 809 | /* Has the filesystem initialised the file for us? */ | 828 | /* Has the filesystem initialised the file for us? */ |
| 810 | if (filp->f_path.dentry == NULL) { | 829 | if (filp->f_path.dentry != NULL) { |
| 830 | nd->intent.open.file = NULL; | ||
| 831 | } else { | ||
| 832 | struct file *res; | ||
| 833 | |||
| 811 | path_get(&nd->path); | 834 | path_get(&nd->path); |
| 812 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, | 835 | res = do_dentry_open(nd->path.dentry, nd->path.mnt, |
| 813 | NULL, cred); | 836 | filp, NULL, cred); |
| 837 | if (!IS_ERR(res)) { | ||
| 838 | int error; | ||
| 839 | |||
| 840 | nd->intent.open.file = NULL; | ||
| 841 | BUG_ON(res != filp); | ||
| 842 | |||
| 843 | error = open_check_o_direct(filp); | ||
| 844 | if (error) { | ||
| 845 | fput(filp); | ||
| 846 | filp = ERR_PTR(error); | ||
| 847 | } | ||
| 848 | } else { | ||
| 849 | /* Allow nd->intent.open.file to be recycled */ | ||
| 850 | filp = res; | ||
| 851 | } | ||
| 814 | } | 852 | } |
| 815 | return filp; | 853 | return filp; |
| 816 | } | 854 | } |
| @@ -654,8 +654,11 @@ out: | |||
| 654 | wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM); | 654 | wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM); |
| 655 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); | 655 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
| 656 | } | 656 | } |
| 657 | if (ret > 0) | 657 | if (ret > 0) { |
| 658 | file_update_time(filp); | 658 | int err = file_update_time(filp); |
| 659 | if (err) | ||
| 660 | ret = err; | ||
| 661 | } | ||
| 659 | return ret; | 662 | return ret; |
| 660 | } | 663 | } |
| 661 | 664 | ||
diff --git a/fs/pnode.c b/fs/pnode.c index ab5fa9e1a79a..bed378db0758 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
| @@ -257,12 +257,12 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry, | |||
| 257 | prev_src_mnt = child; | 257 | prev_src_mnt = child; |
| 258 | } | 258 | } |
| 259 | out: | 259 | out: |
| 260 | br_write_lock(vfsmount_lock); | 260 | br_write_lock(&vfsmount_lock); |
| 261 | while (!list_empty(&tmp_list)) { | 261 | while (!list_empty(&tmp_list)) { |
| 262 | child = list_first_entry(&tmp_list, struct mount, mnt_hash); | 262 | child = list_first_entry(&tmp_list, struct mount, mnt_hash); |
| 263 | umount_tree(child, 0, &umount_list); | 263 | umount_tree(child, 0, &umount_list); |
| 264 | } | 264 | } |
| 265 | br_write_unlock(vfsmount_lock); | 265 | br_write_unlock(&vfsmount_lock); |
| 266 | release_mounts(&umount_list); | 266 | release_mounts(&umount_list); |
| 267 | return ret; | 267 | return ret; |
| 268 | } | 268 | } |
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 12412852d88a..5e289a7cbad1 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c | |||
| @@ -23,12 +23,12 @@ static unsigned mounts_poll(struct file *file, poll_table *wait) | |||
| 23 | 23 | ||
| 24 | poll_wait(file, &p->ns->poll, wait); | 24 | poll_wait(file, &p->ns->poll, wait); |
| 25 | 25 | ||
| 26 | br_read_lock(vfsmount_lock); | 26 | br_read_lock(&vfsmount_lock); |
| 27 | if (p->m.poll_event != ns->event) { | 27 | if (p->m.poll_event != ns->event) { |
| 28 | p->m.poll_event = ns->event; | 28 | p->m.poll_event = ns->event; |
| 29 | res |= POLLERR | POLLPRI; | 29 | res |= POLLERR | POLLPRI; |
| 30 | } | 30 | } |
| 31 | br_read_unlock(vfsmount_lock); | 31 | br_read_unlock(&vfsmount_lock); |
| 32 | 32 | ||
| 33 | return res; | 33 | return res; |
| 34 | } | 34 | } |
diff --git a/fs/readdir.c b/fs/readdir.c index cc0a8227cddf..39e3370d79cf 100644 --- a/fs/readdir.c +++ b/fs/readdir.c | |||
| @@ -108,11 +108,11 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd, | |||
| 108 | int error; | 108 | int error; |
| 109 | struct file * file; | 109 | struct file * file; |
| 110 | struct readdir_callback buf; | 110 | struct readdir_callback buf; |
| 111 | int fput_needed; | ||
| 111 | 112 | ||
| 112 | error = -EBADF; | 113 | file = fget_light(fd, &fput_needed); |
| 113 | file = fget(fd); | ||
| 114 | if (!file) | 114 | if (!file) |
| 115 | goto out; | 115 | return -EBADF; |
| 116 | 116 | ||
| 117 | buf.result = 0; | 117 | buf.result = 0; |
| 118 | buf.dirent = dirent; | 118 | buf.dirent = dirent; |
| @@ -121,8 +121,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd, | |||
| 121 | if (buf.result) | 121 | if (buf.result) |
| 122 | error = buf.result; | 122 | error = buf.result; |
| 123 | 123 | ||
| 124 | fput(file); | 124 | fput_light(file, fput_needed); |
| 125 | out: | ||
| 126 | return error; | 125 | return error; |
| 127 | } | 126 | } |
| 128 | 127 | ||
| @@ -195,16 +194,15 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, | |||
| 195 | struct file * file; | 194 | struct file * file; |
| 196 | struct linux_dirent __user * lastdirent; | 195 | struct linux_dirent __user * lastdirent; |
| 197 | struct getdents_callback buf; | 196 | struct getdents_callback buf; |
| 197 | int fput_needed; | ||
| 198 | int error; | 198 | int error; |
| 199 | 199 | ||
| 200 | error = -EFAULT; | ||
| 201 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 200 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
| 202 | goto out; | 201 | return -EFAULT; |
| 203 | 202 | ||
| 204 | error = -EBADF; | 203 | file = fget_light(fd, &fput_needed); |
| 205 | file = fget(fd); | ||
| 206 | if (!file) | 204 | if (!file) |
| 207 | goto out; | 205 | return -EBADF; |
| 208 | 206 | ||
| 209 | buf.current_dir = dirent; | 207 | buf.current_dir = dirent; |
| 210 | buf.previous = NULL; | 208 | buf.previous = NULL; |
| @@ -221,8 +219,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd, | |||
| 221 | else | 219 | else |
| 222 | error = count - buf.count; | 220 | error = count - buf.count; |
| 223 | } | 221 | } |
| 224 | fput(file); | 222 | fput_light(file, fput_needed); |
| 225 | out: | ||
| 226 | return error; | 223 | return error; |
| 227 | } | 224 | } |
| 228 | 225 | ||
| @@ -278,16 +275,15 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd, | |||
| 278 | struct file * file; | 275 | struct file * file; |
| 279 | struct linux_dirent64 __user * lastdirent; | 276 | struct linux_dirent64 __user * lastdirent; |
| 280 | struct getdents_callback64 buf; | 277 | struct getdents_callback64 buf; |
| 278 | int fput_needed; | ||
| 281 | int error; | 279 | int error; |
| 282 | 280 | ||
| 283 | error = -EFAULT; | ||
| 284 | if (!access_ok(VERIFY_WRITE, dirent, count)) | 281 | if (!access_ok(VERIFY_WRITE, dirent, count)) |
| 285 | goto out; | 282 | return -EFAULT; |
| 286 | 283 | ||
| 287 | error = -EBADF; | 284 | file = fget_light(fd, &fput_needed); |
| 288 | file = fget(fd); | ||
| 289 | if (!file) | 285 | if (!file) |
| 290 | goto out; | 286 | return -EBADF; |
| 291 | 287 | ||
| 292 | buf.current_dir = dirent; | 288 | buf.current_dir = dirent; |
| 293 | buf.previous = NULL; | 289 | buf.previous = NULL; |
| @@ -305,7 +301,6 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd, | |||
| 305 | else | 301 | else |
| 306 | error = count - buf.count; | 302 | error = count - buf.count; |
| 307 | } | 303 | } |
| 308 | fput(file); | 304 | fput_light(file, fput_needed); |
| 309 | out: | ||
| 310 | return error; | 305 | return error; |
| 311 | } | 306 | } |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 59d06871a850..a6d4268fb6c1 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -1592,13 +1592,12 @@ struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, | |||
| 1592 | (fh_type == 6) ? fid->raw[5] : 0); | 1592 | (fh_type == 6) ? fid->raw[5] : 0); |
| 1593 | } | 1593 | } |
| 1594 | 1594 | ||
| 1595 | int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, | 1595 | int reiserfs_encode_fh(struct inode *inode, __u32 * data, int *lenp, |
| 1596 | int need_parent) | 1596 | struct inode *parent) |
| 1597 | { | 1597 | { |
| 1598 | struct inode *inode = dentry->d_inode; | ||
| 1599 | int maxlen = *lenp; | 1598 | int maxlen = *lenp; |
| 1600 | 1599 | ||
| 1601 | if (need_parent && (maxlen < 5)) { | 1600 | if (parent && (maxlen < 5)) { |
| 1602 | *lenp = 5; | 1601 | *lenp = 5; |
| 1603 | return 255; | 1602 | return 255; |
| 1604 | } else if (maxlen < 3) { | 1603 | } else if (maxlen < 3) { |
| @@ -1610,20 +1609,15 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, | |||
| 1610 | data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); | 1609 | data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); |
| 1611 | data[2] = inode->i_generation; | 1610 | data[2] = inode->i_generation; |
| 1612 | *lenp = 3; | 1611 | *lenp = 3; |
| 1613 | /* no room for directory info? return what we've stored so far */ | 1612 | if (parent) { |
| 1614 | if (maxlen < 5 || !need_parent) | 1613 | data[3] = parent->i_ino; |
| 1615 | return 3; | 1614 | data[4] = le32_to_cpu(INODE_PKEY(parent)->k_dir_id); |
| 1616 | 1615 | *lenp = 5; | |
| 1617 | spin_lock(&dentry->d_lock); | 1616 | if (maxlen >= 6) { |
| 1618 | inode = dentry->d_parent->d_inode; | 1617 | data[5] = parent->i_generation; |
| 1619 | data[3] = inode->i_ino; | 1618 | *lenp = 6; |
| 1620 | data[4] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id); | 1619 | } |
| 1621 | *lenp = 5; | 1620 | } |
| 1622 | if (maxlen >= 6) { | ||
| 1623 | data[5] = inode->i_generation; | ||
| 1624 | *lenp = 6; | ||
| 1625 | } | ||
| 1626 | spin_unlock(&dentry->d_lock); | ||
| 1627 | return *lenp; | 1621 | return *lenp; |
| 1628 | } | 1622 | } |
| 1629 | 1623 | ||
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index b1a08573fe14..afcadcc03e8a 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
| @@ -1923,6 +1923,8 @@ static int do_journal_release(struct reiserfs_transaction_handle *th, | |||
| 1923 | * the workqueue job (flush_async_commit) needs this lock | 1923 | * the workqueue job (flush_async_commit) needs this lock |
| 1924 | */ | 1924 | */ |
| 1925 | reiserfs_write_unlock(sb); | 1925 | reiserfs_write_unlock(sb); |
| 1926 | |||
| 1927 | cancel_delayed_work_sync(&REISERFS_SB(sb)->old_work); | ||
| 1926 | flush_workqueue(commit_wq); | 1928 | flush_workqueue(commit_wq); |
| 1927 | 1929 | ||
| 1928 | if (!reiserfs_mounted_fs_count) { | 1930 | if (!reiserfs_mounted_fs_count) { |
| @@ -3231,8 +3233,6 @@ int journal_mark_dirty(struct reiserfs_transaction_handle *th, | |||
| 3231 | th->t_trans_id, journal->j_trans_id); | 3233 | th->t_trans_id, journal->j_trans_id); |
| 3232 | } | 3234 | } |
| 3233 | 3235 | ||
| 3234 | sb->s_dirt = 1; | ||
| 3235 | |||
| 3236 | prepared = test_clear_buffer_journal_prepared(bh); | 3236 | prepared = test_clear_buffer_journal_prepared(bh); |
| 3237 | clear_buffer_journal_restore_dirty(bh); | 3237 | clear_buffer_journal_restore_dirty(bh); |
| 3238 | /* already in this transaction, we are done */ | 3238 | /* already in this transaction, we are done */ |
| @@ -3316,6 +3316,7 @@ int journal_mark_dirty(struct reiserfs_transaction_handle *th, | |||
| 3316 | journal->j_first = cn; | 3316 | journal->j_first = cn; |
| 3317 | journal->j_last = cn; | 3317 | journal->j_last = cn; |
| 3318 | } | 3318 | } |
| 3319 | reiserfs_schedule_old_flush(sb); | ||
| 3319 | return 0; | 3320 | return 0; |
| 3320 | } | 3321 | } |
| 3321 | 3322 | ||
| @@ -3492,7 +3493,7 @@ static void flush_async_commits(struct work_struct *work) | |||
| 3492 | ** flushes any old transactions to disk | 3493 | ** flushes any old transactions to disk |
| 3493 | ** ends the current transaction if it is too old | 3494 | ** ends the current transaction if it is too old |
| 3494 | */ | 3495 | */ |
| 3495 | int reiserfs_flush_old_commits(struct super_block *sb) | 3496 | void reiserfs_flush_old_commits(struct super_block *sb) |
| 3496 | { | 3497 | { |
| 3497 | time_t now; | 3498 | time_t now; |
| 3498 | struct reiserfs_transaction_handle th; | 3499 | struct reiserfs_transaction_handle th; |
| @@ -3502,9 +3503,8 @@ int reiserfs_flush_old_commits(struct super_block *sb) | |||
| 3502 | /* safety check so we don't flush while we are replaying the log during | 3503 | /* safety check so we don't flush while we are replaying the log during |
| 3503 | * mount | 3504 | * mount |
| 3504 | */ | 3505 | */ |
| 3505 | if (list_empty(&journal->j_journal_list)) { | 3506 | if (list_empty(&journal->j_journal_list)) |
| 3506 | return 0; | 3507 | return; |
| 3507 | } | ||
| 3508 | 3508 | ||
| 3509 | /* check the current transaction. If there are no writers, and it is | 3509 | /* check the current transaction. If there are no writers, and it is |
| 3510 | * too old, finish it, and force the commit blocks to disk | 3510 | * too old, finish it, and force the commit blocks to disk |
| @@ -3526,7 +3526,6 @@ int reiserfs_flush_old_commits(struct super_block *sb) | |||
| 3526 | do_journal_end(&th, sb, 1, COMMIT_NOW | WAIT); | 3526 | do_journal_end(&th, sb, 1, COMMIT_NOW | WAIT); |
| 3527 | } | 3527 | } |
| 3528 | } | 3528 | } |
| 3529 | return sb->s_dirt; | ||
| 3530 | } | 3529 | } |
| 3531 | 3530 | ||
| 3532 | /* | 3531 | /* |
| @@ -3955,7 +3954,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 3955 | ** it tells us if we should continue with the journal_end, or just return | 3954 | ** it tells us if we should continue with the journal_end, or just return |
| 3956 | */ | 3955 | */ |
| 3957 | if (!check_journal_end(th, sb, nblocks, flags)) { | 3956 | if (!check_journal_end(th, sb, nblocks, flags)) { |
| 3958 | sb->s_dirt = 1; | 3957 | reiserfs_schedule_old_flush(sb); |
| 3959 | wake_queued_writers(sb); | 3958 | wake_queued_writers(sb); |
| 3960 | reiserfs_async_progress_wait(sb); | 3959 | reiserfs_async_progress_wait(sb); |
| 3961 | goto out; | 3960 | goto out; |
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h index a59d27126338..33215f57ea06 100644 --- a/fs/reiserfs/reiserfs.h +++ b/fs/reiserfs/reiserfs.h | |||
| @@ -480,6 +480,11 @@ struct reiserfs_sb_info { | |||
| 480 | struct dentry *priv_root; /* root of /.reiserfs_priv */ | 480 | struct dentry *priv_root; /* root of /.reiserfs_priv */ |
| 481 | struct dentry *xattr_root; /* root of /.reiserfs_priv/xattrs */ | 481 | struct dentry *xattr_root; /* root of /.reiserfs_priv/xattrs */ |
| 482 | int j_errno; | 482 | int j_errno; |
| 483 | |||
| 484 | int work_queued; /* non-zero delayed work is queued */ | ||
| 485 | struct delayed_work old_work; /* old transactions flush delayed work */ | ||
| 486 | spinlock_t old_work_lock; /* protects old_work and work_queued */ | ||
| 487 | |||
| 483 | #ifdef CONFIG_QUOTA | 488 | #ifdef CONFIG_QUOTA |
| 484 | char *s_qf_names[MAXQUOTAS]; | 489 | char *s_qf_names[MAXQUOTAS]; |
| 485 | int s_jquota_fmt; | 490 | int s_jquota_fmt; |
| @@ -2452,7 +2457,7 @@ struct reiserfs_transaction_handle *reiserfs_persistent_transaction(struct | |||
| 2452 | int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *); | 2457 | int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *); |
| 2453 | int reiserfs_commit_page(struct inode *inode, struct page *page, | 2458 | int reiserfs_commit_page(struct inode *inode, struct page *page, |
| 2454 | unsigned from, unsigned to); | 2459 | unsigned from, unsigned to); |
| 2455 | int reiserfs_flush_old_commits(struct super_block *); | 2460 | void reiserfs_flush_old_commits(struct super_block *); |
| 2456 | int reiserfs_commit_for_inode(struct inode *); | 2461 | int reiserfs_commit_for_inode(struct inode *); |
| 2457 | int reiserfs_inode_needs_commit(struct inode *); | 2462 | int reiserfs_inode_needs_commit(struct inode *); |
| 2458 | void reiserfs_update_inode_transaction(struct inode *); | 2463 | void reiserfs_update_inode_transaction(struct inode *); |
| @@ -2487,6 +2492,7 @@ void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...); | |||
| 2487 | int reiserfs_allocate_list_bitmaps(struct super_block *s, | 2492 | int reiserfs_allocate_list_bitmaps(struct super_block *s, |
| 2488 | struct reiserfs_list_bitmap *, unsigned int); | 2493 | struct reiserfs_list_bitmap *, unsigned int); |
| 2489 | 2494 | ||
| 2495 | void reiserfs_schedule_old_flush(struct super_block *s); | ||
| 2490 | void add_save_link(struct reiserfs_transaction_handle *th, | 2496 | void add_save_link(struct reiserfs_transaction_handle *th, |
| 2491 | struct inode *inode, int truncate); | 2497 | struct inode *inode, int truncate); |
| 2492 | int remove_save_link(struct inode *inode, int truncate); | 2498 | int remove_save_link(struct inode *inode, int truncate); |
| @@ -2611,8 +2617,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | |||
| 2611 | int fh_len, int fh_type); | 2617 | int fh_len, int fh_type); |
| 2612 | struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, | 2618 | struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, |
| 2613 | int fh_len, int fh_type); | 2619 | int fh_len, int fh_type); |
| 2614 | int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, | 2620 | int reiserfs_encode_fh(struct inode *inode, __u32 * data, int *lenp, |
| 2615 | int connectable); | 2621 | struct inode *parent); |
| 2616 | 2622 | ||
| 2617 | int reiserfs_truncate_file(struct inode *, int update_timestamps); | 2623 | int reiserfs_truncate_file(struct inode *, int update_timestamps); |
| 2618 | void make_cpu_key(struct cpu_key *cpu_key, struct inode *inode, loff_t offset, | 2624 | void make_cpu_key(struct cpu_key *cpu_key, struct inode *inode, loff_t offset, |
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 9a17f63c3fd7..3ce02cff5e90 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c | |||
| @@ -200,7 +200,6 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
| 200 | (bmap_nr_new - bmap_nr))); | 200 | (bmap_nr_new - bmap_nr))); |
| 201 | PUT_SB_BLOCK_COUNT(s, block_count_new); | 201 | PUT_SB_BLOCK_COUNT(s, block_count_new); |
| 202 | PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new); | 202 | PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new); |
| 203 | s->s_dirt = 1; | ||
| 204 | 203 | ||
| 205 | journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); | 204 | journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); |
| 206 | 205 | ||
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index c07b7d709447..651ce767b55d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -72,20 +72,58 @@ static int reiserfs_sync_fs(struct super_block *s, int wait) | |||
| 72 | if (!journal_begin(&th, s, 1)) | 72 | if (!journal_begin(&th, s, 1)) |
| 73 | if (!journal_end_sync(&th, s, 1)) | 73 | if (!journal_end_sync(&th, s, 1)) |
| 74 | reiserfs_flush_old_commits(s); | 74 | reiserfs_flush_old_commits(s); |
| 75 | s->s_dirt = 0; /* Even if it's not true. | ||
| 76 | * We'll loop forever in sync_supers otherwise */ | ||
| 77 | reiserfs_write_unlock(s); | 75 | reiserfs_write_unlock(s); |
| 78 | return 0; | 76 | return 0; |
| 79 | } | 77 | } |
| 80 | 78 | ||
| 81 | static void reiserfs_write_super(struct super_block *s) | 79 | static void flush_old_commits(struct work_struct *work) |
| 82 | { | 80 | { |
| 81 | struct reiserfs_sb_info *sbi; | ||
| 82 | struct super_block *s; | ||
| 83 | |||
| 84 | sbi = container_of(work, struct reiserfs_sb_info, old_work.work); | ||
| 85 | s = sbi->s_journal->j_work_sb; | ||
| 86 | |||
| 87 | spin_lock(&sbi->old_work_lock); | ||
| 88 | sbi->work_queued = 0; | ||
| 89 | spin_unlock(&sbi->old_work_lock); | ||
| 90 | |||
| 83 | reiserfs_sync_fs(s, 1); | 91 | reiserfs_sync_fs(s, 1); |
| 84 | } | 92 | } |
| 85 | 93 | ||
| 94 | void reiserfs_schedule_old_flush(struct super_block *s) | ||
| 95 | { | ||
| 96 | struct reiserfs_sb_info *sbi = REISERFS_SB(s); | ||
| 97 | unsigned long delay; | ||
| 98 | |||
| 99 | if (s->s_flags & MS_RDONLY) | ||
| 100 | return; | ||
| 101 | |||
| 102 | spin_lock(&sbi->old_work_lock); | ||
| 103 | if (!sbi->work_queued) { | ||
| 104 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
| 105 | queue_delayed_work(system_long_wq, &sbi->old_work, delay); | ||
| 106 | sbi->work_queued = 1; | ||
| 107 | } | ||
| 108 | spin_unlock(&sbi->old_work_lock); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void cancel_old_flush(struct super_block *s) | ||
| 112 | { | ||
| 113 | struct reiserfs_sb_info *sbi = REISERFS_SB(s); | ||
| 114 | |||
| 115 | cancel_delayed_work_sync(&REISERFS_SB(s)->old_work); | ||
| 116 | spin_lock(&sbi->old_work_lock); | ||
| 117 | sbi->work_queued = 0; | ||
| 118 | spin_unlock(&sbi->old_work_lock); | ||
| 119 | } | ||
| 120 | |||
| 86 | static int reiserfs_freeze(struct super_block *s) | 121 | static int reiserfs_freeze(struct super_block *s) |
| 87 | { | 122 | { |
| 88 | struct reiserfs_transaction_handle th; | 123 | struct reiserfs_transaction_handle th; |
| 124 | |||
| 125 | cancel_old_flush(s); | ||
| 126 | |||
| 89 | reiserfs_write_lock(s); | 127 | reiserfs_write_lock(s); |
| 90 | if (!(s->s_flags & MS_RDONLY)) { | 128 | if (!(s->s_flags & MS_RDONLY)) { |
| 91 | int err = journal_begin(&th, s, 1); | 129 | int err = journal_begin(&th, s, 1); |
| @@ -99,7 +137,6 @@ static int reiserfs_freeze(struct super_block *s) | |||
| 99 | journal_end_sync(&th, s, 1); | 137 | journal_end_sync(&th, s, 1); |
| 100 | } | 138 | } |
| 101 | } | 139 | } |
| 102 | s->s_dirt = 0; | ||
| 103 | reiserfs_write_unlock(s); | 140 | reiserfs_write_unlock(s); |
| 104 | return 0; | 141 | return 0; |
| 105 | } | 142 | } |
| @@ -483,9 +520,6 @@ static void reiserfs_put_super(struct super_block *s) | |||
| 483 | 520 | ||
| 484 | reiserfs_write_lock(s); | 521 | reiserfs_write_lock(s); |
| 485 | 522 | ||
| 486 | if (s->s_dirt) | ||
| 487 | reiserfs_write_super(s); | ||
| 488 | |||
| 489 | /* change file system state to current state if it was mounted with read-write permissions */ | 523 | /* change file system state to current state if it was mounted with read-write permissions */ |
| 490 | if (!(s->s_flags & MS_RDONLY)) { | 524 | if (!(s->s_flags & MS_RDONLY)) { |
| 491 | if (!journal_begin(&th, s, 10)) { | 525 | if (!journal_begin(&th, s, 10)) { |
| @@ -692,7 +726,6 @@ static const struct super_operations reiserfs_sops = { | |||
| 692 | .dirty_inode = reiserfs_dirty_inode, | 726 | .dirty_inode = reiserfs_dirty_inode, |
| 693 | .evict_inode = reiserfs_evict_inode, | 727 | .evict_inode = reiserfs_evict_inode, |
| 694 | .put_super = reiserfs_put_super, | 728 | .put_super = reiserfs_put_super, |
| 695 | .write_super = reiserfs_write_super, | ||
| 696 | .sync_fs = reiserfs_sync_fs, | 729 | .sync_fs = reiserfs_sync_fs, |
| 697 | .freeze_fs = reiserfs_freeze, | 730 | .freeze_fs = reiserfs_freeze, |
| 698 | .unfreeze_fs = reiserfs_unfreeze, | 731 | .unfreeze_fs = reiserfs_unfreeze, |
| @@ -1400,7 +1433,6 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
| 1400 | err = journal_end(&th, s, 10); | 1433 | err = journal_end(&th, s, 10); |
| 1401 | if (err) | 1434 | if (err) |
| 1402 | goto out_err; | 1435 | goto out_err; |
| 1403 | s->s_dirt = 0; | ||
| 1404 | 1436 | ||
| 1405 | if (!(*mount_flags & MS_RDONLY)) { | 1437 | if (!(*mount_flags & MS_RDONLY)) { |
| 1406 | dquot_resume(s, -1); | 1438 | dquot_resume(s, -1); |
| @@ -1730,19 +1762,21 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1730 | return -ENOMEM; | 1762 | return -ENOMEM; |
| 1731 | s->s_fs_info = sbi; | 1763 | s->s_fs_info = sbi; |
| 1732 | /* Set default values for options: non-aggressive tails, RO on errors */ | 1764 | /* Set default values for options: non-aggressive tails, RO on errors */ |
| 1733 | REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL); | 1765 | sbi->s_mount_opt |= (1 << REISERFS_SMALLTAIL); |
| 1734 | REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_ERROR_RO); | 1766 | sbi->s_mount_opt |= (1 << REISERFS_ERROR_RO); |
| 1735 | REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_BARRIER_FLUSH); | 1767 | sbi->s_mount_opt |= (1 << REISERFS_BARRIER_FLUSH); |
| 1736 | /* no preallocation minimum, be smart in | 1768 | /* no preallocation minimum, be smart in |
| 1737 | reiserfs_file_write instead */ | 1769 | reiserfs_file_write instead */ |
| 1738 | REISERFS_SB(s)->s_alloc_options.preallocmin = 0; | 1770 | sbi->s_alloc_options.preallocmin = 0; |
| 1739 | /* Preallocate by 16 blocks (17-1) at once */ | 1771 | /* Preallocate by 16 blocks (17-1) at once */ |
| 1740 | REISERFS_SB(s)->s_alloc_options.preallocsize = 17; | 1772 | sbi->s_alloc_options.preallocsize = 17; |
| 1741 | /* setup default block allocator options */ | 1773 | /* setup default block allocator options */ |
| 1742 | reiserfs_init_alloc_options(s); | 1774 | reiserfs_init_alloc_options(s); |
| 1743 | 1775 | ||
| 1744 | mutex_init(&REISERFS_SB(s)->lock); | 1776 | spin_lock_init(&sbi->old_work_lock); |
| 1745 | REISERFS_SB(s)->lock_depth = -1; | 1777 | INIT_DELAYED_WORK(&sbi->old_work, flush_old_commits); |
| 1778 | mutex_init(&sbi->lock); | ||
| 1779 | sbi->lock_depth = -1; | ||
| 1746 | 1780 | ||
| 1747 | jdev_name = NULL; | 1781 | jdev_name = NULL; |
| 1748 | if (reiserfs_parse_options | 1782 | if (reiserfs_parse_options |
| @@ -1751,8 +1785,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1751 | goto error_unlocked; | 1785 | goto error_unlocked; |
| 1752 | } | 1786 | } |
| 1753 | if (jdev_name && jdev_name[0]) { | 1787 | if (jdev_name && jdev_name[0]) { |
| 1754 | REISERFS_SB(s)->s_jdev = kstrdup(jdev_name, GFP_KERNEL); | 1788 | sbi->s_jdev = kstrdup(jdev_name, GFP_KERNEL); |
| 1755 | if (!REISERFS_SB(s)->s_jdev) { | 1789 | if (!sbi->s_jdev) { |
| 1756 | SWARN(silent, s, "", "Cannot allocate memory for " | 1790 | SWARN(silent, s, "", "Cannot allocate memory for " |
| 1757 | "journal device name"); | 1791 | "journal device name"); |
| 1758 | goto error; | 1792 | goto error; |
| @@ -1810,7 +1844,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1810 | /* make data=ordered the default */ | 1844 | /* make data=ordered the default */ |
| 1811 | if (!reiserfs_data_log(s) && !reiserfs_data_ordered(s) && | 1845 | if (!reiserfs_data_log(s) && !reiserfs_data_ordered(s) && |
| 1812 | !reiserfs_data_writeback(s)) { | 1846 | !reiserfs_data_writeback(s)) { |
| 1813 | REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED); | 1847 | sbi->s_mount_opt |= (1 << REISERFS_DATA_ORDERED); |
| 1814 | } | 1848 | } |
| 1815 | 1849 | ||
| 1816 | if (reiserfs_data_log(s)) { | 1850 | if (reiserfs_data_log(s)) { |
| @@ -2003,6 +2037,8 @@ error_unlocked: | |||
| 2003 | reiserfs_write_unlock(s); | 2037 | reiserfs_write_unlock(s); |
| 2004 | } | 2038 | } |
| 2005 | 2039 | ||
| 2040 | cancel_delayed_work_sync(&REISERFS_SB(s)->old_work); | ||
| 2041 | |||
| 2006 | reiserfs_free_bitmap_cache(s); | 2042 | reiserfs_free_bitmap_cache(s); |
| 2007 | if (SB_BUFFER_WITH_SB(s)) | 2043 | if (SB_BUFFER_WITH_SB(s)) |
| 2008 | brelse(SB_BUFFER_WITH_SB(s)); | 2044 | brelse(SB_BUFFER_WITH_SB(s)); |
diff --git a/fs/signalfd.c b/fs/signalfd.c index 7ae2a574cb25..9f35a37173de 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
| @@ -269,12 +269,13 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, | |||
| 269 | if (ufd < 0) | 269 | if (ufd < 0) |
| 270 | kfree(ctx); | 270 | kfree(ctx); |
| 271 | } else { | 271 | } else { |
| 272 | struct file *file = fget(ufd); | 272 | int fput_needed; |
| 273 | struct file *file = fget_light(ufd, &fput_needed); | ||
| 273 | if (!file) | 274 | if (!file) |
| 274 | return -EBADF; | 275 | return -EBADF; |
| 275 | ctx = file->private_data; | 276 | ctx = file->private_data; |
| 276 | if (file->f_op != &signalfd_fops) { | 277 | if (file->f_op != &signalfd_fops) { |
| 277 | fput(file); | 278 | fput_light(file, fput_needed); |
| 278 | return -EINVAL; | 279 | return -EINVAL; |
| 279 | } | 280 | } |
| 280 | spin_lock_irq(¤t->sighand->siglock); | 281 | spin_lock_irq(¤t->sighand->siglock); |
| @@ -282,7 +283,7 @@ SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask, | |||
| 282 | spin_unlock_irq(¤t->sighand->siglock); | 283 | spin_unlock_irq(¤t->sighand->siglock); |
| 283 | 284 | ||
| 284 | wake_up(¤t->sighand->signalfd_wqh); | 285 | wake_up(¤t->sighand->signalfd_wqh); |
| 285 | fput(file); | 286 | fput_light(file, fput_needed); |
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | return ufd; | 289 | return ufd; |
diff --git a/fs/splice.c b/fs/splice.c index 406ef2b792c2..c9f1318a3b82 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -1003,8 +1003,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
| 1003 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); | 1003 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); |
| 1004 | ret = file_remove_suid(out); | 1004 | ret = file_remove_suid(out); |
| 1005 | if (!ret) { | 1005 | if (!ret) { |
| 1006 | file_update_time(out); | 1006 | ret = file_update_time(out); |
| 1007 | ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file); | 1007 | if (!ret) |
| 1008 | ret = splice_from_pipe_feed(pipe, &sd, | ||
| 1009 | pipe_to_file); | ||
| 1008 | } | 1010 | } |
| 1009 | mutex_unlock(&inode->i_mutex); | 1011 | mutex_unlock(&inode->i_mutex); |
| 1010 | } while (ret > 0); | 1012 | } while (ret > 0); |
diff --git a/fs/statfs.c b/fs/statfs.c index 43e6b6fe4e85..95ad5c0e586c 100644 --- a/fs/statfs.c +++ b/fs/statfs.c | |||
| @@ -87,11 +87,12 @@ int user_statfs(const char __user *pathname, struct kstatfs *st) | |||
| 87 | 87 | ||
| 88 | int fd_statfs(int fd, struct kstatfs *st) | 88 | int fd_statfs(int fd, struct kstatfs *st) |
| 89 | { | 89 | { |
| 90 | struct file *file = fget(fd); | 90 | int fput_needed; |
| 91 | struct file *file = fget_light(fd, &fput_needed); | ||
| 91 | int error = -EBADF; | 92 | int error = -EBADF; |
| 92 | if (file) { | 93 | if (file) { |
| 93 | error = vfs_statfs(&file->f_path, st); | 94 | error = vfs_statfs(&file->f_path, st); |
| 94 | fput(file); | 95 | fput_light(file, fput_needed); |
| 95 | } | 96 | } |
| 96 | return error; | 97 | return error; |
| 97 | } | 98 | } |
| @@ -188,11 +188,12 @@ static int do_fsync(unsigned int fd, int datasync) | |||
| 188 | { | 188 | { |
| 189 | struct file *file; | 189 | struct file *file; |
| 190 | int ret = -EBADF; | 190 | int ret = -EBADF; |
| 191 | int fput_needed; | ||
| 191 | 192 | ||
| 192 | file = fget(fd); | 193 | file = fget_light(fd, &fput_needed); |
| 193 | if (file) { | 194 | if (file) { |
| 194 | ret = vfs_fsync(file, datasync); | 195 | ret = vfs_fsync(file, datasync); |
| 195 | fput(file); | 196 | fput_light(file, fput_needed); |
| 196 | } | 197 | } |
| 197 | return ret; | 198 | return ret; |
| 198 | } | 199 | } |
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 62a2727f4ecf..a6d42efc76d2 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
| @@ -1127,16 +1127,7 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 1127 | struct ubifs_inode *ui = ubifs_inode(inode); | 1127 | struct ubifs_inode *ui = ubifs_inode(inode); |
| 1128 | 1128 | ||
| 1129 | mutex_lock(&ui->ui_mutex); | 1129 | mutex_lock(&ui->ui_mutex); |
| 1130 | stat->dev = inode->i_sb->s_dev; | 1130 | generic_fillattr(inode, stat); |
| 1131 | stat->ino = inode->i_ino; | ||
| 1132 | stat->mode = inode->i_mode; | ||
| 1133 | stat->nlink = inode->i_nlink; | ||
| 1134 | stat->uid = inode->i_uid; | ||
| 1135 | stat->gid = inode->i_gid; | ||
| 1136 | stat->rdev = inode->i_rdev; | ||
| 1137 | stat->atime = inode->i_atime; | ||
| 1138 | stat->mtime = inode->i_mtime; | ||
| 1139 | stat->ctime = inode->i_ctime; | ||
| 1140 | stat->blksize = UBIFS_BLOCK_SIZE; | 1131 | stat->blksize = UBIFS_BLOCK_SIZE; |
| 1141 | stat->size = ui->ui_size; | 1132 | stat->size = ui->ui_size; |
| 1142 | 1133 | ||
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index a165c66e3eef..18024178ac4c 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
| @@ -1260,16 +1260,15 @@ static struct dentry *udf_fh_to_parent(struct super_block *sb, | |||
| 1260 | fid->udf.parent_partref, | 1260 | fid->udf.parent_partref, |
| 1261 | fid->udf.parent_generation); | 1261 | fid->udf.parent_generation); |
| 1262 | } | 1262 | } |
| 1263 | static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, | 1263 | static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp, |
| 1264 | int connectable) | 1264 | struct inode *parent) |
| 1265 | { | 1265 | { |
| 1266 | int len = *lenp; | 1266 | int len = *lenp; |
| 1267 | struct inode *inode = de->d_inode; | ||
| 1268 | struct kernel_lb_addr location = UDF_I(inode)->i_location; | 1267 | struct kernel_lb_addr location = UDF_I(inode)->i_location; |
| 1269 | struct fid *fid = (struct fid *)fh; | 1268 | struct fid *fid = (struct fid *)fh; |
| 1270 | int type = FILEID_UDF_WITHOUT_PARENT; | 1269 | int type = FILEID_UDF_WITHOUT_PARENT; |
| 1271 | 1270 | ||
| 1272 | if (connectable && (len < 5)) { | 1271 | if (parent && (len < 5)) { |
| 1273 | *lenp = 5; | 1272 | *lenp = 5; |
| 1274 | return 255; | 1273 | return 255; |
| 1275 | } else if (len < 3) { | 1274 | } else if (len < 3) { |
| @@ -1282,14 +1281,11 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, | |||
| 1282 | fid->udf.partref = location.partitionReferenceNum; | 1281 | fid->udf.partref = location.partitionReferenceNum; |
| 1283 | fid->udf.generation = inode->i_generation; | 1282 | fid->udf.generation = inode->i_generation; |
| 1284 | 1283 | ||
| 1285 | if (connectable && !S_ISDIR(inode->i_mode)) { | 1284 | if (parent) { |
| 1286 | spin_lock(&de->d_lock); | 1285 | location = UDF_I(parent)->i_location; |
| 1287 | inode = de->d_parent->d_inode; | ||
| 1288 | location = UDF_I(inode)->i_location; | ||
| 1289 | fid->udf.parent_block = location.logicalBlockNum; | 1286 | fid->udf.parent_block = location.logicalBlockNum; |
| 1290 | fid->udf.parent_partref = location.partitionReferenceNum; | 1287 | fid->udf.parent_partref = location.partitionReferenceNum; |
| 1291 | fid->udf.parent_generation = inode->i_generation; | 1288 | fid->udf.parent_generation = inode->i_generation; |
| 1292 | spin_unlock(&de->d_lock); | ||
| 1293 | *lenp = 5; | 1289 | *lenp = 5; |
| 1294 | type = FILEID_UDF_WITH_PARENT; | 1290 | type = FILEID_UDF_WITH_PARENT; |
| 1295 | } | 1291 | } |
diff --git a/fs/utimes.c b/fs/utimes.c index ba653f3dc1bc..fa4dbe451e27 100644 --- a/fs/utimes.c +++ b/fs/utimes.c | |||
| @@ -140,18 +140,19 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times, | |||
| 140 | goto out; | 140 | goto out; |
| 141 | 141 | ||
| 142 | if (filename == NULL && dfd != AT_FDCWD) { | 142 | if (filename == NULL && dfd != AT_FDCWD) { |
| 143 | int fput_needed; | ||
| 143 | struct file *file; | 144 | struct file *file; |
| 144 | 145 | ||
| 145 | if (flags & AT_SYMLINK_NOFOLLOW) | 146 | if (flags & AT_SYMLINK_NOFOLLOW) |
| 146 | goto out; | 147 | goto out; |
| 147 | 148 | ||
| 148 | file = fget(dfd); | 149 | file = fget_light(dfd, &fput_needed); |
| 149 | error = -EBADF; | 150 | error = -EBADF; |
| 150 | if (!file) | 151 | if (!file) |
| 151 | goto out; | 152 | goto out; |
| 152 | 153 | ||
| 153 | error = utimes_common(&file->f_path, times); | 154 | error = utimes_common(&file->f_path, times); |
| 154 | fput(file); | 155 | fput_light(file, fput_needed); |
| 155 | } else { | 156 | } else { |
| 156 | struct path path; | 157 | struct path path; |
| 157 | int lookup_flags = 0; | 158 | int lookup_flags = 0; |
diff --git a/fs/xattr.c b/fs/xattr.c index 3c8c1cc333c7..1d7ac3790458 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
| @@ -399,11 +399,12 @@ SYSCALL_DEFINE5(lsetxattr, const char __user *, pathname, | |||
| 399 | SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, | 399 | SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, |
| 400 | const void __user *,value, size_t, size, int, flags) | 400 | const void __user *,value, size_t, size, int, flags) |
| 401 | { | 401 | { |
| 402 | int fput_needed; | ||
| 402 | struct file *f; | 403 | struct file *f; |
| 403 | struct dentry *dentry; | 404 | struct dentry *dentry; |
| 404 | int error = -EBADF; | 405 | int error = -EBADF; |
| 405 | 406 | ||
| 406 | f = fget(fd); | 407 | f = fget_light(fd, &fput_needed); |
| 407 | if (!f) | 408 | if (!f) |
| 408 | return error; | 409 | return error; |
| 409 | dentry = f->f_path.dentry; | 410 | dentry = f->f_path.dentry; |
| @@ -413,7 +414,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, | |||
| 413 | error = setxattr(dentry, name, value, size, flags); | 414 | error = setxattr(dentry, name, value, size, flags); |
| 414 | mnt_drop_write_file(f); | 415 | mnt_drop_write_file(f); |
| 415 | } | 416 | } |
| 416 | fput(f); | 417 | fput_light(f, fput_needed); |
| 417 | return error; | 418 | return error; |
| 418 | } | 419 | } |
| 419 | 420 | ||
| @@ -486,15 +487,16 @@ SYSCALL_DEFINE4(lgetxattr, const char __user *, pathname, | |||
| 486 | SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, | 487 | SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, |
| 487 | void __user *, value, size_t, size) | 488 | void __user *, value, size_t, size) |
| 488 | { | 489 | { |
| 490 | int fput_needed; | ||
| 489 | struct file *f; | 491 | struct file *f; |
| 490 | ssize_t error = -EBADF; | 492 | ssize_t error = -EBADF; |
| 491 | 493 | ||
| 492 | f = fget(fd); | 494 | f = fget_light(fd, &fput_needed); |
| 493 | if (!f) | 495 | if (!f) |
| 494 | return error; | 496 | return error; |
| 495 | audit_inode(NULL, f->f_path.dentry); | 497 | audit_inode(NULL, f->f_path.dentry); |
| 496 | error = getxattr(f->f_path.dentry, name, value, size); | 498 | error = getxattr(f->f_path.dentry, name, value, size); |
| 497 | fput(f); | 499 | fput_light(f, fput_needed); |
| 498 | return error; | 500 | return error; |
| 499 | } | 501 | } |
| 500 | 502 | ||
| @@ -566,15 +568,16 @@ SYSCALL_DEFINE3(llistxattr, const char __user *, pathname, char __user *, list, | |||
| 566 | 568 | ||
| 567 | SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) | 569 | SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) |
| 568 | { | 570 | { |
| 571 | int fput_needed; | ||
| 569 | struct file *f; | 572 | struct file *f; |
| 570 | ssize_t error = -EBADF; | 573 | ssize_t error = -EBADF; |
| 571 | 574 | ||
| 572 | f = fget(fd); | 575 | f = fget_light(fd, &fput_needed); |
| 573 | if (!f) | 576 | if (!f) |
| 574 | return error; | 577 | return error; |
| 575 | audit_inode(NULL, f->f_path.dentry); | 578 | audit_inode(NULL, f->f_path.dentry); |
| 576 | error = listxattr(f->f_path.dentry, list, size); | 579 | error = listxattr(f->f_path.dentry, list, size); |
| 577 | fput(f); | 580 | fput_light(f, fput_needed); |
| 578 | return error; | 581 | return error; |
| 579 | } | 582 | } |
| 580 | 583 | ||
| @@ -634,11 +637,12 @@ SYSCALL_DEFINE2(lremovexattr, const char __user *, pathname, | |||
| 634 | 637 | ||
| 635 | SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) | 638 | SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) |
| 636 | { | 639 | { |
| 640 | int fput_needed; | ||
| 637 | struct file *f; | 641 | struct file *f; |
| 638 | struct dentry *dentry; | 642 | struct dentry *dentry; |
| 639 | int error = -EBADF; | 643 | int error = -EBADF; |
| 640 | 644 | ||
| 641 | f = fget(fd); | 645 | f = fget_light(fd, &fput_needed); |
| 642 | if (!f) | 646 | if (!f) |
| 643 | return error; | 647 | return error; |
| 644 | dentry = f->f_path.dentry; | 648 | dentry = f->f_path.dentry; |
| @@ -648,7 +652,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) | |||
| 648 | error = removexattr(dentry, name); | 652 | error = removexattr(dentry, name); |
| 649 | mnt_drop_write_file(f); | 653 | mnt_drop_write_file(f); |
| 650 | } | 654 | } |
| 651 | fput(f); | 655 | fput_light(f, fput_needed); |
| 652 | return error; | 656 | return error; |
| 653 | } | 657 | } |
| 654 | 658 | ||
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c index a907de565db3..4a7286c1dc80 100644 --- a/fs/xfs/kmem.c +++ b/fs/xfs/kmem.c | |||
| @@ -46,7 +46,7 @@ kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize) | |||
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | void * | 48 | void * |
| 49 | kmem_alloc(size_t size, unsigned int __nocast flags) | 49 | kmem_alloc(size_t size, xfs_km_flags_t flags) |
| 50 | { | 50 | { |
| 51 | int retries = 0; | 51 | int retries = 0; |
| 52 | gfp_t lflags = kmem_flags_convert(flags); | 52 | gfp_t lflags = kmem_flags_convert(flags); |
| @@ -65,7 +65,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags) | |||
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | void * | 67 | void * |
| 68 | kmem_zalloc(size_t size, unsigned int __nocast flags) | 68 | kmem_zalloc(size_t size, xfs_km_flags_t flags) |
| 69 | { | 69 | { |
| 70 | void *ptr; | 70 | void *ptr; |
| 71 | 71 | ||
| @@ -87,7 +87,7 @@ kmem_free(const void *ptr) | |||
| 87 | 87 | ||
| 88 | void * | 88 | void * |
| 89 | kmem_realloc(const void *ptr, size_t newsize, size_t oldsize, | 89 | kmem_realloc(const void *ptr, size_t newsize, size_t oldsize, |
| 90 | unsigned int __nocast flags) | 90 | xfs_km_flags_t flags) |
| 91 | { | 91 | { |
| 92 | void *new; | 92 | void *new; |
| 93 | 93 | ||
| @@ -102,7 +102,7 @@ kmem_realloc(const void *ptr, size_t newsize, size_t oldsize, | |||
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void * | 104 | void * |
| 105 | kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) | 105 | kmem_zone_alloc(kmem_zone_t *zone, xfs_km_flags_t flags) |
| 106 | { | 106 | { |
| 107 | int retries = 0; | 107 | int retries = 0; |
| 108 | gfp_t lflags = kmem_flags_convert(flags); | 108 | gfp_t lflags = kmem_flags_convert(flags); |
| @@ -121,7 +121,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | void * | 123 | void * |
| 124 | kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags) | 124 | kmem_zone_zalloc(kmem_zone_t *zone, xfs_km_flags_t flags) |
| 125 | { | 125 | { |
| 126 | void *ptr; | 126 | void *ptr; |
| 127 | 127 | ||
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index ab7c53fe346e..b2f2620f9a87 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h | |||
| @@ -27,10 +27,11 @@ | |||
| 27 | * General memory allocation interfaces | 27 | * General memory allocation interfaces |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #define KM_SLEEP 0x0001u | 30 | typedef unsigned __bitwise xfs_km_flags_t; |
| 31 | #define KM_NOSLEEP 0x0002u | 31 | #define KM_SLEEP ((__force xfs_km_flags_t)0x0001u) |
| 32 | #define KM_NOFS 0x0004u | 32 | #define KM_NOSLEEP ((__force xfs_km_flags_t)0x0002u) |
| 33 | #define KM_MAYFAIL 0x0008u | 33 | #define KM_NOFS ((__force xfs_km_flags_t)0x0004u) |
| 34 | #define KM_MAYFAIL ((__force xfs_km_flags_t)0x0008u) | ||
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * We use a special process flag to avoid recursive callbacks into | 37 | * We use a special process flag to avoid recursive callbacks into |
| @@ -38,7 +39,7 @@ | |||
| 38 | * warnings, so we explicitly skip any generic ones (silly of us). | 39 | * warnings, so we explicitly skip any generic ones (silly of us). |
| 39 | */ | 40 | */ |
| 40 | static inline gfp_t | 41 | static inline gfp_t |
| 41 | kmem_flags_convert(unsigned int __nocast flags) | 42 | kmem_flags_convert(xfs_km_flags_t flags) |
| 42 | { | 43 | { |
| 43 | gfp_t lflags; | 44 | gfp_t lflags; |
| 44 | 45 | ||
| @@ -54,9 +55,9 @@ kmem_flags_convert(unsigned int __nocast flags) | |||
| 54 | return lflags; | 55 | return lflags; |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | extern void *kmem_alloc(size_t, unsigned int __nocast); | 58 | extern void *kmem_alloc(size_t, xfs_km_flags_t); |
| 58 | extern void *kmem_zalloc(size_t, unsigned int __nocast); | 59 | extern void *kmem_zalloc(size_t, xfs_km_flags_t); |
| 59 | extern void *kmem_realloc(const void *, size_t, size_t, unsigned int __nocast); | 60 | extern void *kmem_realloc(const void *, size_t, size_t, xfs_km_flags_t); |
| 60 | extern void kmem_free(const void *); | 61 | extern void kmem_free(const void *); |
| 61 | 62 | ||
| 62 | static inline void *kmem_zalloc_large(size_t size) | 63 | static inline void *kmem_zalloc_large(size_t size) |
| @@ -107,7 +108,7 @@ kmem_zone_destroy(kmem_zone_t *zone) | |||
| 107 | kmem_cache_destroy(zone); | 108 | kmem_cache_destroy(zone); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); | 111 | extern void *kmem_zone_alloc(kmem_zone_t *, xfs_km_flags_t); |
| 111 | extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); | 112 | extern void *kmem_zone_zalloc(kmem_zone_t *, xfs_km_flags_t); |
| 112 | 113 | ||
| 113 | #endif /* __XFS_SUPPORT_KMEM_H__ */ | 114 | #endif /* __XFS_SUPPORT_KMEM_H__ */ |
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 2d25d19c4ea1..42679223a0fd 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c | |||
| @@ -52,19 +52,18 @@ static int xfs_fileid_length(int fileid_type) | |||
| 52 | 52 | ||
| 53 | STATIC int | 53 | STATIC int |
| 54 | xfs_fs_encode_fh( | 54 | xfs_fs_encode_fh( |
| 55 | struct dentry *dentry, | 55 | struct inode *inode, |
| 56 | __u32 *fh, | 56 | __u32 *fh, |
| 57 | int *max_len, | 57 | int *max_len, |
| 58 | int connectable) | 58 | struct inode *parent) |
| 59 | { | 59 | { |
| 60 | struct fid *fid = (struct fid *)fh; | 60 | struct fid *fid = (struct fid *)fh; |
| 61 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; | 61 | struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; |
| 62 | struct inode *inode = dentry->d_inode; | ||
| 63 | int fileid_type; | 62 | int fileid_type; |
| 64 | int len; | 63 | int len; |
| 65 | 64 | ||
| 66 | /* Directories don't need their parent encoded, they have ".." */ | 65 | /* Directories don't need their parent encoded, they have ".." */ |
| 67 | if (S_ISDIR(inode->i_mode) || !connectable) | 66 | if (!parent) |
| 68 | fileid_type = FILEID_INO32_GEN; | 67 | fileid_type = FILEID_INO32_GEN; |
| 69 | else | 68 | else |
| 70 | fileid_type = FILEID_INO32_GEN_PARENT; | 69 | fileid_type = FILEID_INO32_GEN_PARENT; |
| @@ -96,20 +95,16 @@ xfs_fs_encode_fh( | |||
| 96 | 95 | ||
| 97 | switch (fileid_type) { | 96 | switch (fileid_type) { |
| 98 | case FILEID_INO32_GEN_PARENT: | 97 | case FILEID_INO32_GEN_PARENT: |
| 99 | spin_lock(&dentry->d_lock); | 98 | fid->i32.parent_ino = XFS_I(parent)->i_ino; |
| 100 | fid->i32.parent_ino = XFS_I(dentry->d_parent->d_inode)->i_ino; | 99 | fid->i32.parent_gen = parent->i_generation; |
| 101 | fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; | ||
| 102 | spin_unlock(&dentry->d_lock); | ||
| 103 | /*FALLTHRU*/ | 100 | /*FALLTHRU*/ |
| 104 | case FILEID_INO32_GEN: | 101 | case FILEID_INO32_GEN: |
| 105 | fid->i32.ino = XFS_I(inode)->i_ino; | 102 | fid->i32.ino = XFS_I(inode)->i_ino; |
| 106 | fid->i32.gen = inode->i_generation; | 103 | fid->i32.gen = inode->i_generation; |
| 107 | break; | 104 | break; |
| 108 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: | 105 | case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: |
| 109 | spin_lock(&dentry->d_lock); | 106 | fid64->parent_ino = XFS_I(parent)->i_ino; |
| 110 | fid64->parent_ino = XFS_I(dentry->d_parent->d_inode)->i_ino; | 107 | fid64->parent_gen = parent->i_generation; |
| 111 | fid64->parent_gen = dentry->d_parent->d_inode->i_generation; | ||
| 112 | spin_unlock(&dentry->d_lock); | ||
| 113 | /*FALLTHRU*/ | 108 | /*FALLTHRU*/ |
| 114 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: | 109 | case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: |
| 115 | fid64->ino = XFS_I(inode)->i_ino; | 110 | fid64->ino = XFS_I(inode)->i_ino; |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 8d214b87f6bb..9f7ec15a6522 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -586,8 +586,11 @@ restart: | |||
| 586 | * lock above. Eventually we should look into a way to avoid | 586 | * lock above. Eventually we should look into a way to avoid |
| 587 | * the pointless lock roundtrip. | 587 | * the pointless lock roundtrip. |
| 588 | */ | 588 | */ |
| 589 | if (likely(!(file->f_mode & FMODE_NOCMTIME))) | 589 | if (likely(!(file->f_mode & FMODE_NOCMTIME))) { |
| 590 | file_update_time(file); | 590 | error = file_update_time(file); |
| 591 | if (error) | ||
| 592 | return error; | ||
| 593 | } | ||
| 591 | 594 | ||
| 592 | /* | 595 | /* |
| 593 | * If we're writing the file then make sure to clear the setuid and | 596 | * If we're writing the file then make sure to clear the setuid and |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 6b965bf450e4..f30d9807dc48 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -3152,7 +3152,7 @@ xlog_ticket_alloc( | |||
| 3152 | int cnt, | 3152 | int cnt, |
| 3153 | char client, | 3153 | char client, |
| 3154 | bool permanent, | 3154 | bool permanent, |
| 3155 | int alloc_flags) | 3155 | xfs_km_flags_t alloc_flags) |
| 3156 | { | 3156 | { |
| 3157 | struct xlog_ticket *tic; | 3157 | struct xlog_ticket *tic; |
| 3158 | uint num_headers; | 3158 | uint num_headers; |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 735ff1ee53da..5bc33261f5be 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
| @@ -555,7 +555,7 @@ extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int); | |||
| 555 | extern kmem_zone_t *xfs_log_ticket_zone; | 555 | extern kmem_zone_t *xfs_log_ticket_zone; |
| 556 | struct xlog_ticket *xlog_ticket_alloc(struct log *log, int unit_bytes, | 556 | struct xlog_ticket *xlog_ticket_alloc(struct log *log, int unit_bytes, |
| 557 | int count, char client, bool permanent, | 557 | int count, char client, bool permanent, |
| 558 | int alloc_flags); | 558 | xfs_km_flags_t alloc_flags); |
| 559 | 559 | ||
| 560 | 560 | ||
| 561 | static inline void | 561 | static inline void |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index cdf896fcbfa4..fdf324508c5e 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
| @@ -584,7 +584,7 @@ xfs_trans_t * | |||
| 584 | _xfs_trans_alloc( | 584 | _xfs_trans_alloc( |
| 585 | xfs_mount_t *mp, | 585 | xfs_mount_t *mp, |
| 586 | uint type, | 586 | uint type, |
| 587 | uint memflags) | 587 | xfs_km_flags_t memflags) |
| 588 | { | 588 | { |
| 589 | xfs_trans_t *tp; | 589 | xfs_trans_t *tp; |
| 590 | 590 | ||
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 7ab99e1898c8..7c37b533aa8e 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
| @@ -443,7 +443,7 @@ typedef struct xfs_trans { | |||
| 443 | * XFS transaction mechanism exported interfaces. | 443 | * XFS transaction mechanism exported interfaces. |
| 444 | */ | 444 | */ |
| 445 | xfs_trans_t *xfs_trans_alloc(struct xfs_mount *, uint); | 445 | xfs_trans_t *xfs_trans_alloc(struct xfs_mount *, uint); |
| 446 | xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint, uint); | 446 | xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint, xfs_km_flags_t); |
| 447 | xfs_trans_t *xfs_trans_dup(xfs_trans_t *); | 447 | xfs_trans_t *xfs_trans_dup(xfs_trans_t *); |
| 448 | int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, | 448 | int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint, |
| 449 | uint, uint); | 449 | uint, uint); |
diff --git a/include/asm-generic/posix_types.h b/include/asm-generic/posix_types.h index 91d44bd4dde3..fe74fccf18db 100644 --- a/include/asm-generic/posix_types.h +++ b/include/asm-generic/posix_types.h | |||
| @@ -23,10 +23,6 @@ typedef __kernel_ulong_t __kernel_ino_t; | |||
| 23 | typedef unsigned int __kernel_mode_t; | 23 | typedef unsigned int __kernel_mode_t; |
| 24 | #endif | 24 | #endif |
| 25 | 25 | ||
| 26 | #ifndef __kernel_nlink_t | ||
| 27 | typedef __kernel_ulong_t __kernel_nlink_t; | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #ifndef __kernel_pid_t | 26 | #ifndef __kernel_pid_t |
| 31 | typedef int __kernel_pid_t; | 27 | typedef int __kernel_pid_t; |
| 32 | #endif | 28 | #endif |
diff --git a/include/linux/errno.h b/include/linux/errno.h index 2d09bfa5c262..e0de516374da 100644 --- a/include/linux/errno.h +++ b/include/linux/errno.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #define ENOIOCTLCMD 515 /* No ioctl command */ | 17 | #define ENOIOCTLCMD 515 /* No ioctl command */ |
| 18 | #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ | 18 | #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ |
| 19 | #define EPROBE_DEFER 517 /* Driver requests probe retry */ | 19 | #define EPROBE_DEFER 517 /* Driver requests probe retry */ |
| 20 | #define EOPENSTALE 518 /* open found a stale dentry */ | ||
| 20 | 21 | ||
| 21 | /* Defined for the NFSv3 protocol */ | 22 | /* Defined for the NFSv3 protocol */ |
| 22 | #define EBADHANDLE 521 /* Illegal NFS file handle */ | 23 | #define EBADHANDLE 521 /* Illegal NFS file handle */ |
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 3a4cef5322dc..12291a7ee275 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h | |||
| @@ -165,8 +165,8 @@ struct fid { | |||
| 165 | */ | 165 | */ |
| 166 | 166 | ||
| 167 | struct export_operations { | 167 | struct export_operations { |
| 168 | int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, | 168 | int (*encode_fh)(struct inode *inode, __u32 *fh, int *max_len, |
| 169 | int connectable); | 169 | struct inode *parent); |
| 170 | struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid, | 170 | struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid, |
| 171 | int fh_len, int fh_type); | 171 | int fh_len, int fh_type); |
| 172 | struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid, | 172 | struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid, |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 40887afaaca7..51978ed43e97 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1692,6 +1692,7 @@ struct inode_operations { | |||
| 1692 | int (*removexattr) (struct dentry *, const char *); | 1692 | int (*removexattr) (struct dentry *, const char *); |
| 1693 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, | 1693 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, |
| 1694 | u64 len); | 1694 | u64 len); |
| 1695 | int (*update_time)(struct inode *, struct timespec *, int); | ||
| 1695 | } ____cacheline_aligned; | 1696 | } ____cacheline_aligned; |
| 1696 | 1697 | ||
| 1697 | struct seq_file; | 1698 | struct seq_file; |
| @@ -1850,6 +1851,13 @@ static inline void inode_inc_iversion(struct inode *inode) | |||
| 1850 | spin_unlock(&inode->i_lock); | 1851 | spin_unlock(&inode->i_lock); |
| 1851 | } | 1852 | } |
| 1852 | 1853 | ||
| 1854 | enum file_time_flags { | ||
| 1855 | S_ATIME = 1, | ||
| 1856 | S_MTIME = 2, | ||
| 1857 | S_CTIME = 4, | ||
| 1858 | S_VERSION = 8, | ||
| 1859 | }; | ||
| 1860 | |||
| 1853 | extern void touch_atime(struct path *); | 1861 | extern void touch_atime(struct path *); |
| 1854 | static inline void file_accessed(struct file *file) | 1862 | static inline void file_accessed(struct file *file) |
| 1855 | { | 1863 | { |
| @@ -2583,7 +2591,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *); | |||
| 2583 | extern int inode_newsize_ok(const struct inode *, loff_t offset); | 2591 | extern int inode_newsize_ok(const struct inode *, loff_t offset); |
| 2584 | extern void setattr_copy(struct inode *inode, const struct iattr *attr); | 2592 | extern void setattr_copy(struct inode *inode, const struct iattr *attr); |
| 2585 | 2593 | ||
| 2586 | extern void file_update_time(struct file *file); | 2594 | extern int file_update_time(struct file *file); |
| 2587 | 2595 | ||
| 2588 | extern int generic_show_options(struct seq_file *m, struct dentry *root); | 2596 | extern int generic_show_options(struct seq_file *m, struct dentry *root); |
| 2589 | extern void save_mount_options(struct super_block *sb, char *options); | 2597 | extern void save_mount_options(struct super_block *sb, char *options); |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 91d0e0a34ef3..63d966d5c2ea 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
| @@ -60,7 +60,7 @@ | |||
| 60 | #define FS_EVENTS_POSS_ON_CHILD (FS_ACCESS | FS_MODIFY | FS_ATTRIB |\ | 60 | #define FS_EVENTS_POSS_ON_CHILD (FS_ACCESS | FS_MODIFY | FS_ATTRIB |\ |
| 61 | FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN |\ | 61 | FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | FS_OPEN |\ |
| 62 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\ | 62 | FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\ |
| 63 | FS_DELETE) | 63 | FS_DELETE | FS_OPEN_PERM | FS_ACCESS_PERM) |
| 64 | 64 | ||
| 65 | #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) | 65 | #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) |
| 66 | 66 | ||
diff --git a/include/linux/lglock.h b/include/linux/lglock.h index 87f402ccec55..f01e5f6d1f07 100644 --- a/include/linux/lglock.h +++ b/include/linux/lglock.h | |||
| @@ -23,28 +23,17 @@ | |||
| 23 | #include <linux/lockdep.h> | 23 | #include <linux/lockdep.h> |
| 24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
| 25 | #include <linux/cpu.h> | 25 | #include <linux/cpu.h> |
| 26 | #include <linux/notifier.h> | ||
| 26 | 27 | ||
| 27 | /* can make br locks by using local lock for read side, global lock for write */ | 28 | /* can make br locks by using local lock for read side, global lock for write */ |
| 28 | #define br_lock_init(name) name##_lock_init() | 29 | #define br_lock_init(name) lg_lock_init(name, #name) |
| 29 | #define br_read_lock(name) name##_local_lock() | 30 | #define br_read_lock(name) lg_local_lock(name) |
| 30 | #define br_read_unlock(name) name##_local_unlock() | 31 | #define br_read_unlock(name) lg_local_unlock(name) |
| 31 | #define br_write_lock(name) name##_global_lock_online() | 32 | #define br_write_lock(name) lg_global_lock(name) |
| 32 | #define br_write_unlock(name) name##_global_unlock_online() | 33 | #define br_write_unlock(name) lg_global_unlock(name) |
| 33 | 34 | ||
| 34 | #define DECLARE_BRLOCK(name) DECLARE_LGLOCK(name) | ||
| 35 | #define DEFINE_BRLOCK(name) DEFINE_LGLOCK(name) | 35 | #define DEFINE_BRLOCK(name) DEFINE_LGLOCK(name) |
| 36 | 36 | ||
| 37 | |||
| 38 | #define lg_lock_init(name) name##_lock_init() | ||
| 39 | #define lg_local_lock(name) name##_local_lock() | ||
| 40 | #define lg_local_unlock(name) name##_local_unlock() | ||
| 41 | #define lg_local_lock_cpu(name, cpu) name##_local_lock_cpu(cpu) | ||
| 42 | #define lg_local_unlock_cpu(name, cpu) name##_local_unlock_cpu(cpu) | ||
| 43 | #define lg_global_lock(name) name##_global_lock() | ||
| 44 | #define lg_global_unlock(name) name##_global_unlock() | ||
| 45 | #define lg_global_lock_online(name) name##_global_lock_online() | ||
| 46 | #define lg_global_unlock_online(name) name##_global_unlock_online() | ||
| 47 | |||
| 48 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 37 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 49 | #define LOCKDEP_INIT_MAP lockdep_init_map | 38 | #define LOCKDEP_INIT_MAP lockdep_init_map |
| 50 | 39 | ||
| @@ -59,142 +48,26 @@ | |||
| 59 | #define DEFINE_LGLOCK_LOCKDEP(name) | 48 | #define DEFINE_LGLOCK_LOCKDEP(name) |
| 60 | #endif | 49 | #endif |
| 61 | 50 | ||
| 62 | 51 | struct lglock { | |
| 63 | #define DECLARE_LGLOCK(name) \ | 52 | arch_spinlock_t __percpu *lock; |
| 64 | extern void name##_lock_init(void); \ | 53 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 65 | extern void name##_local_lock(void); \ | 54 | struct lock_class_key lock_key; |
| 66 | extern void name##_local_unlock(void); \ | 55 | struct lockdep_map lock_dep_map; |
| 67 | extern void name##_local_lock_cpu(int cpu); \ | 56 | #endif |
| 68 | extern void name##_local_unlock_cpu(int cpu); \ | 57 | }; |
| 69 | extern void name##_global_lock(void); \ | ||
| 70 | extern void name##_global_unlock(void); \ | ||
| 71 | extern void name##_global_lock_online(void); \ | ||
| 72 | extern void name##_global_unlock_online(void); \ | ||
| 73 | 58 | ||
| 74 | #define DEFINE_LGLOCK(name) \ | 59 | #define DEFINE_LGLOCK(name) \ |
| 75 | \ | 60 | DEFINE_LGLOCK_LOCKDEP(name); \ |
| 76 | DEFINE_SPINLOCK(name##_cpu_lock); \ | 61 | DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) \ |
| 77 | cpumask_t name##_cpus __read_mostly; \ | 62 | = __ARCH_SPIN_LOCK_UNLOCKED; \ |
| 78 | DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \ | 63 | struct lglock name = { .lock = &name ## _lock } |
| 79 | DEFINE_LGLOCK_LOCKDEP(name); \ | 64 | |
| 80 | \ | 65 | void lg_lock_init(struct lglock *lg, char *name); |
| 81 | static int \ | 66 | void lg_local_lock(struct lglock *lg); |
| 82 | name##_lg_cpu_callback(struct notifier_block *nb, \ | 67 | void lg_local_unlock(struct lglock *lg); |
| 83 | unsigned long action, void *hcpu) \ | 68 | void lg_local_lock_cpu(struct lglock *lg, int cpu); |
| 84 | { \ | 69 | void lg_local_unlock_cpu(struct lglock *lg, int cpu); |
| 85 | switch (action & ~CPU_TASKS_FROZEN) { \ | 70 | void lg_global_lock(struct lglock *lg); |
| 86 | case CPU_UP_PREPARE: \ | 71 | void lg_global_unlock(struct lglock *lg); |
| 87 | spin_lock(&name##_cpu_lock); \ | 72 | |
| 88 | cpu_set((unsigned long)hcpu, name##_cpus); \ | ||
| 89 | spin_unlock(&name##_cpu_lock); \ | ||
| 90 | break; \ | ||
| 91 | case CPU_UP_CANCELED: case CPU_DEAD: \ | ||
| 92 | spin_lock(&name##_cpu_lock); \ | ||
| 93 | cpu_clear((unsigned long)hcpu, name##_cpus); \ | ||
| 94 | spin_unlock(&name##_cpu_lock); \ | ||
| 95 | } \ | ||
| 96 | return NOTIFY_OK; \ | ||
| 97 | } \ | ||
| 98 | static struct notifier_block name##_lg_cpu_notifier = { \ | ||
| 99 | .notifier_call = name##_lg_cpu_callback, \ | ||
| 100 | }; \ | ||
| 101 | void name##_lock_init(void) { \ | ||
| 102 | int i; \ | ||
| 103 | LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \ | ||
| 104 | for_each_possible_cpu(i) { \ | ||
| 105 | arch_spinlock_t *lock; \ | ||
| 106 | lock = &per_cpu(name##_lock, i); \ | ||
| 107 | *lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \ | ||
| 108 | } \ | ||
| 109 | register_hotcpu_notifier(&name##_lg_cpu_notifier); \ | ||
| 110 | get_online_cpus(); \ | ||
| 111 | for_each_online_cpu(i) \ | ||
| 112 | cpu_set(i, name##_cpus); \ | ||
| 113 | put_online_cpus(); \ | ||
| 114 | } \ | ||
| 115 | EXPORT_SYMBOL(name##_lock_init); \ | ||
| 116 | \ | ||
| 117 | void name##_local_lock(void) { \ | ||
| 118 | arch_spinlock_t *lock; \ | ||
| 119 | preempt_disable(); \ | ||
| 120 | rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \ | ||
| 121 | lock = &__get_cpu_var(name##_lock); \ | ||
| 122 | arch_spin_lock(lock); \ | ||
| 123 | } \ | ||
| 124 | EXPORT_SYMBOL(name##_local_lock); \ | ||
| 125 | \ | ||
| 126 | void name##_local_unlock(void) { \ | ||
| 127 | arch_spinlock_t *lock; \ | ||
| 128 | rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \ | ||
| 129 | lock = &__get_cpu_var(name##_lock); \ | ||
| 130 | arch_spin_unlock(lock); \ | ||
| 131 | preempt_enable(); \ | ||
| 132 | } \ | ||
| 133 | EXPORT_SYMBOL(name##_local_unlock); \ | ||
| 134 | \ | ||
| 135 | void name##_local_lock_cpu(int cpu) { \ | ||
| 136 | arch_spinlock_t *lock; \ | ||
| 137 | preempt_disable(); \ | ||
| 138 | rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_); \ | ||
| 139 | lock = &per_cpu(name##_lock, cpu); \ | ||
| 140 | arch_spin_lock(lock); \ | ||
| 141 | } \ | ||
| 142 | EXPORT_SYMBOL(name##_local_lock_cpu); \ | ||
| 143 | \ | ||
| 144 | void name##_local_unlock_cpu(int cpu) { \ | ||
| 145 | arch_spinlock_t *lock; \ | ||
| 146 | rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_); \ | ||
| 147 | lock = &per_cpu(name##_lock, cpu); \ | ||
| 148 | arch_spin_unlock(lock); \ | ||
| 149 | preempt_enable(); \ | ||
| 150 | } \ | ||
| 151 | EXPORT_SYMBOL(name##_local_unlock_cpu); \ | ||
| 152 | \ | ||
| 153 | void name##_global_lock_online(void) { \ | ||
| 154 | int i; \ | ||
| 155 | spin_lock(&name##_cpu_lock); \ | ||
| 156 | rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \ | ||
| 157 | for_each_cpu(i, &name##_cpus) { \ | ||
| 158 | arch_spinlock_t *lock; \ | ||
| 159 | lock = &per_cpu(name##_lock, i); \ | ||
| 160 | arch_spin_lock(lock); \ | ||
| 161 | } \ | ||
| 162 | } \ | ||
| 163 | EXPORT_SYMBOL(name##_global_lock_online); \ | ||
| 164 | \ | ||
| 165 | void name##_global_unlock_online(void) { \ | ||
| 166 | int i; \ | ||
| 167 | rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \ | ||
| 168 | for_each_cpu(i, &name##_cpus) { \ | ||
| 169 | arch_spinlock_t *lock; \ | ||
| 170 | lock = &per_cpu(name##_lock, i); \ | ||
| 171 | arch_spin_unlock(lock); \ | ||
| 172 | } \ | ||
| 173 | spin_unlock(&name##_cpu_lock); \ | ||
| 174 | } \ | ||
| 175 | EXPORT_SYMBOL(name##_global_unlock_online); \ | ||
| 176 | \ | ||
| 177 | void name##_global_lock(void) { \ | ||
| 178 | int i; \ | ||
| 179 | preempt_disable(); \ | ||
| 180 | rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \ | ||
| 181 | for_each_possible_cpu(i) { \ | ||
| 182 | arch_spinlock_t *lock; \ | ||
| 183 | lock = &per_cpu(name##_lock, i); \ | ||
| 184 | arch_spin_lock(lock); \ | ||
| 185 | } \ | ||
| 186 | } \ | ||
| 187 | EXPORT_SYMBOL(name##_global_lock); \ | ||
| 188 | \ | ||
| 189 | void name##_global_unlock(void) { \ | ||
| 190 | int i; \ | ||
| 191 | rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \ | ||
| 192 | for_each_possible_cpu(i) { \ | ||
| 193 | arch_spinlock_t *lock; \ | ||
| 194 | lock = &per_cpu(name##_lock, i); \ | ||
| 195 | arch_spin_unlock(lock); \ | ||
| 196 | } \ | ||
| 197 | preempt_enable(); \ | ||
| 198 | } \ | ||
| 199 | EXPORT_SYMBOL(name##_global_unlock); | ||
| 200 | #endif | 73 | #endif |
diff --git a/include/linux/mm.h b/include/linux/mm.h index ce26716238c3..b36d08ce5c57 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -1392,7 +1392,7 @@ extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned lo | |||
| 1392 | extern unsigned long mmap_region(struct file *file, unsigned long addr, | 1392 | extern unsigned long mmap_region(struct file *file, unsigned long addr, |
| 1393 | unsigned long len, unsigned long flags, | 1393 | unsigned long len, unsigned long flags, |
| 1394 | vm_flags_t vm_flags, unsigned long pgoff); | 1394 | vm_flags_t vm_flags, unsigned long pgoff); |
| 1395 | extern unsigned long do_mmap(struct file *, unsigned long, | 1395 | extern unsigned long do_mmap_pgoff(struct file *, unsigned long, |
| 1396 | unsigned long, unsigned long, | 1396 | unsigned long, unsigned long, |
| 1397 | unsigned long, unsigned long); | 1397 | unsigned long, unsigned long); |
| 1398 | extern int do_munmap(struct mm_struct *, unsigned long, size_t); | 1398 | extern int do_munmap(struct mm_struct *, unsigned long, size_t); |
diff --git a/include/linux/security.h b/include/linux/security.h index ab0e091ce5fa..4e5a73cdbbef 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -86,9 +86,9 @@ extern int cap_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 86 | extern int cap_inode_removexattr(struct dentry *dentry, const char *name); | 86 | extern int cap_inode_removexattr(struct dentry *dentry, const char *name); |
| 87 | extern int cap_inode_need_killpriv(struct dentry *dentry); | 87 | extern int cap_inode_need_killpriv(struct dentry *dentry); |
| 88 | extern int cap_inode_killpriv(struct dentry *dentry); | 88 | extern int cap_inode_killpriv(struct dentry *dentry); |
| 89 | extern int cap_file_mmap(struct file *file, unsigned long reqprot, | 89 | extern int cap_mmap_addr(unsigned long addr); |
| 90 | unsigned long prot, unsigned long flags, | 90 | extern int cap_mmap_file(struct file *file, unsigned long reqprot, |
| 91 | unsigned long addr, unsigned long addr_only); | 91 | unsigned long prot, unsigned long flags); |
| 92 | extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags); | 92 | extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags); |
| 93 | extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 93 | extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
| 94 | unsigned long arg4, unsigned long arg5); | 94 | unsigned long arg4, unsigned long arg5); |
| @@ -586,15 +586,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
| 586 | * simple integer value. When @arg represents a user space pointer, it | 586 | * simple integer value. When @arg represents a user space pointer, it |
| 587 | * should never be used by the security module. | 587 | * should never be used by the security module. |
| 588 | * Return 0 if permission is granted. | 588 | * Return 0 if permission is granted. |
| 589 | * @file_mmap : | 589 | * @mmap_addr : |
| 590 | * Check permissions for a mmap operation at @addr. | ||
| 591 | * @addr contains virtual address that will be used for the operation. | ||
| 592 | * Return 0 if permission is granted. | ||
| 593 | * @mmap_file : | ||
| 590 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | 594 | * Check permissions for a mmap operation. The @file may be NULL, e.g. |
| 591 | * if mapping anonymous memory. | 595 | * if mapping anonymous memory. |
| 592 | * @file contains the file structure for file to map (may be NULL). | 596 | * @file contains the file structure for file to map (may be NULL). |
| 593 | * @reqprot contains the protection requested by the application. | 597 | * @reqprot contains the protection requested by the application. |
| 594 | * @prot contains the protection that will be applied by the kernel. | 598 | * @prot contains the protection that will be applied by the kernel. |
| 595 | * @flags contains the operational flags. | 599 | * @flags contains the operational flags. |
| 596 | * @addr contains virtual address that will be used for the operation. | ||
| 597 | * @addr_only contains a boolean: 0 if file-backed VMA, otherwise 1. | ||
| 598 | * Return 0 if permission is granted. | 600 | * Return 0 if permission is granted. |
| 599 | * @file_mprotect: | 601 | * @file_mprotect: |
| 600 | * Check permissions before changing memory access permissions. | 602 | * Check permissions before changing memory access permissions. |
| @@ -1481,10 +1483,10 @@ struct security_operations { | |||
| 1481 | void (*file_free_security) (struct file *file); | 1483 | void (*file_free_security) (struct file *file); |
| 1482 | int (*file_ioctl) (struct file *file, unsigned int cmd, | 1484 | int (*file_ioctl) (struct file *file, unsigned int cmd, |
| 1483 | unsigned long arg); | 1485 | unsigned long arg); |
| 1484 | int (*file_mmap) (struct file *file, | 1486 | int (*mmap_addr) (unsigned long addr); |
| 1487 | int (*mmap_file) (struct file *file, | ||
| 1485 | unsigned long reqprot, unsigned long prot, | 1488 | unsigned long reqprot, unsigned long prot, |
| 1486 | unsigned long flags, unsigned long addr, | 1489 | unsigned long flags); |
| 1487 | unsigned long addr_only); | ||
| 1488 | int (*file_mprotect) (struct vm_area_struct *vma, | 1490 | int (*file_mprotect) (struct vm_area_struct *vma, |
| 1489 | unsigned long reqprot, | 1491 | unsigned long reqprot, |
| 1490 | unsigned long prot); | 1492 | unsigned long prot); |
| @@ -1743,9 +1745,9 @@ int security_file_permission(struct file *file, int mask); | |||
| 1743 | int security_file_alloc(struct file *file); | 1745 | int security_file_alloc(struct file *file); |
| 1744 | void security_file_free(struct file *file); | 1746 | void security_file_free(struct file *file); |
| 1745 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 1747 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
| 1746 | int security_file_mmap(struct file *file, unsigned long reqprot, | 1748 | int security_mmap_file(struct file *file, unsigned long prot, |
| 1747 | unsigned long prot, unsigned long flags, | 1749 | unsigned long flags); |
| 1748 | unsigned long addr, unsigned long addr_only); | 1750 | int security_mmap_addr(unsigned long addr); |
| 1749 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 1751 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
| 1750 | unsigned long prot); | 1752 | unsigned long prot); |
| 1751 | int security_file_lock(struct file *file, unsigned int cmd); | 1753 | int security_file_lock(struct file *file, unsigned int cmd); |
| @@ -2181,13 +2183,15 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd, | |||
| 2181 | return 0; | 2183 | return 0; |
| 2182 | } | 2184 | } |
| 2183 | 2185 | ||
| 2184 | static inline int security_file_mmap(struct file *file, unsigned long reqprot, | 2186 | static inline int security_mmap_file(struct file *file, unsigned long prot, |
| 2185 | unsigned long prot, | 2187 | unsigned long flags) |
| 2186 | unsigned long flags, | 2188 | { |
| 2187 | unsigned long addr, | 2189 | return 0; |
| 2188 | unsigned long addr_only) | 2190 | } |
| 2191 | |||
| 2192 | static inline int security_mmap_addr(unsigned long addr) | ||
| 2189 | { | 2193 | { |
| 2190 | return cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | 2194 | return cap_mmap_addr(addr); |
| 2191 | } | 2195 | } |
| 2192 | 2196 | ||
| 2193 | static inline int security_file_mprotect(struct vm_area_struct *vma, | 2197 | static inline int security_file_mprotect(struct vm_area_struct *vma, |
diff --git a/include/linux/types.h b/include/linux/types.h index 7f480db60231..9c1bd539ea70 100644 --- a/include/linux/types.h +++ b/include/linux/types.h | |||
| @@ -25,7 +25,7 @@ typedef __kernel_dev_t dev_t; | |||
| 25 | typedef __kernel_ino_t ino_t; | 25 | typedef __kernel_ino_t ino_t; |
| 26 | typedef __kernel_mode_t mode_t; | 26 | typedef __kernel_mode_t mode_t; |
| 27 | typedef unsigned short umode_t; | 27 | typedef unsigned short umode_t; |
| 28 | typedef __kernel_nlink_t nlink_t; | 28 | typedef __u32 nlink_t; |
| 29 | typedef __kernel_off_t off_t; | 29 | typedef __kernel_off_t off_t; |
| 30 | typedef __kernel_pid_t pid_t; | 30 | typedef __kernel_pid_t pid_t; |
| 31 | typedef __kernel_daddr_t daddr_t; | 31 | typedef __kernel_daddr_t daddr_t; |
| @@ -1036,6 +1036,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
| 1036 | sfd->file = shp->shm_file; | 1036 | sfd->file = shp->shm_file; |
| 1037 | sfd->vm_ops = NULL; | 1037 | sfd->vm_ops = NULL; |
| 1038 | 1038 | ||
| 1039 | err = security_mmap_file(file, prot, flags); | ||
| 1040 | if (err) | ||
| 1041 | goto out_fput; | ||
| 1042 | |||
| 1039 | down_write(¤t->mm->mmap_sem); | 1043 | down_write(¤t->mm->mmap_sem); |
| 1040 | if (addr && !(shmflg & SHM_REMAP)) { | 1044 | if (addr && !(shmflg & SHM_REMAP)) { |
| 1041 | err = -EINVAL; | 1045 | err = -EINVAL; |
| @@ -1050,7 +1054,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
| 1050 | goto invalid; | 1054 | goto invalid; |
| 1051 | } | 1055 | } |
| 1052 | 1056 | ||
| 1053 | user_addr = do_mmap (file, addr, size, prot, flags, 0); | 1057 | user_addr = do_mmap_pgoff(file, addr, size, prot, flags, 0); |
| 1054 | *raddr = user_addr; | 1058 | *raddr = user_addr; |
| 1055 | err = 0; | 1059 | err = 0; |
| 1056 | if (IS_ERR_VALUE(user_addr)) | 1060 | if (IS_ERR_VALUE(user_addr)) |
| @@ -1058,6 +1062,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
| 1058 | invalid: | 1062 | invalid: |
| 1059 | up_write(¤t->mm->mmap_sem); | 1063 | up_write(¤t->mm->mmap_sem); |
| 1060 | 1064 | ||
| 1065 | out_fput: | ||
| 1061 | fput(file); | 1066 | fput(file); |
| 1062 | 1067 | ||
| 1063 | out_nattch: | 1068 | out_nattch: |
diff --git a/kernel/Makefile b/kernel/Makefile index 6f3d0ae044b2..c0cc67ad764c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o printk.o \ | |||
| 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
| 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
| 12 | notifier.o ksysfs.o cred.o \ | 12 | notifier.o ksysfs.o cred.o \ |
| 13 | async.o range.o groups.o | 13 | async.o range.o groups.o lglock.o |
| 14 | 14 | ||
| 15 | ifdef CONFIG_FUNCTION_TRACER | 15 | ifdef CONFIG_FUNCTION_TRACER |
| 16 | # Do not trace debug files and internal ftrace files | 16 | # Do not trace debug files and internal ftrace files |
diff --git a/kernel/lglock.c b/kernel/lglock.c new file mode 100644 index 000000000000..6535a667a5a7 --- /dev/null +++ b/kernel/lglock.c | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | /* See include/linux/lglock.h for description */ | ||
| 2 | #include <linux/module.h> | ||
| 3 | #include <linux/lglock.h> | ||
| 4 | #include <linux/cpu.h> | ||
| 5 | #include <linux/string.h> | ||
| 6 | |||
| 7 | /* | ||
| 8 | * Note there is no uninit, so lglocks cannot be defined in | ||
| 9 | * modules (but it's fine to use them from there) | ||
| 10 | * Could be added though, just undo lg_lock_init | ||
| 11 | */ | ||
| 12 | |||
| 13 | void lg_lock_init(struct lglock *lg, char *name) | ||
| 14 | { | ||
| 15 | LOCKDEP_INIT_MAP(&lg->lock_dep_map, name, &lg->lock_key, 0); | ||
| 16 | } | ||
| 17 | EXPORT_SYMBOL(lg_lock_init); | ||
| 18 | |||
| 19 | void lg_local_lock(struct lglock *lg) | ||
| 20 | { | ||
| 21 | arch_spinlock_t *lock; | ||
| 22 | |||
| 23 | preempt_disable(); | ||
| 24 | rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_); | ||
| 25 | lock = this_cpu_ptr(lg->lock); | ||
| 26 | arch_spin_lock(lock); | ||
| 27 | } | ||
| 28 | EXPORT_SYMBOL(lg_local_lock); | ||
| 29 | |||
| 30 | void lg_local_unlock(struct lglock *lg) | ||
| 31 | { | ||
| 32 | arch_spinlock_t *lock; | ||
| 33 | |||
| 34 | rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); | ||
| 35 | lock = this_cpu_ptr(lg->lock); | ||
| 36 | arch_spin_unlock(lock); | ||
| 37 | preempt_enable(); | ||
| 38 | } | ||
| 39 | EXPORT_SYMBOL(lg_local_unlock); | ||
| 40 | |||
| 41 | void lg_local_lock_cpu(struct lglock *lg, int cpu) | ||
| 42 | { | ||
| 43 | arch_spinlock_t *lock; | ||
| 44 | |||
| 45 | preempt_disable(); | ||
| 46 | rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_); | ||
| 47 | lock = per_cpu_ptr(lg->lock, cpu); | ||
| 48 | arch_spin_lock(lock); | ||
| 49 | } | ||
| 50 | EXPORT_SYMBOL(lg_local_lock_cpu); | ||
| 51 | |||
| 52 | void lg_local_unlock_cpu(struct lglock *lg, int cpu) | ||
| 53 | { | ||
| 54 | arch_spinlock_t *lock; | ||
| 55 | |||
| 56 | rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); | ||
| 57 | lock = per_cpu_ptr(lg->lock, cpu); | ||
| 58 | arch_spin_unlock(lock); | ||
| 59 | preempt_enable(); | ||
| 60 | } | ||
| 61 | EXPORT_SYMBOL(lg_local_unlock_cpu); | ||
| 62 | |||
| 63 | void lg_global_lock(struct lglock *lg) | ||
| 64 | { | ||
| 65 | int i; | ||
| 66 | |||
| 67 | preempt_disable(); | ||
| 68 | rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_); | ||
| 69 | for_each_possible_cpu(i) { | ||
| 70 | arch_spinlock_t *lock; | ||
| 71 | lock = per_cpu_ptr(lg->lock, i); | ||
| 72 | arch_spin_lock(lock); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | EXPORT_SYMBOL(lg_global_lock); | ||
| 76 | |||
| 77 | void lg_global_unlock(struct lglock *lg) | ||
| 78 | { | ||
| 79 | int i; | ||
| 80 | |||
| 81 | rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); | ||
| 82 | for_each_possible_cpu(i) { | ||
| 83 | arch_spinlock_t *lock; | ||
| 84 | lock = per_cpu_ptr(lg->lock, i); | ||
| 85 | arch_spin_unlock(lock); | ||
| 86 | } | ||
| 87 | preempt_enable(); | ||
| 88 | } | ||
| 89 | EXPORT_SYMBOL(lg_global_unlock); | ||
diff --git a/mm/cleancache.c b/mm/cleancache.c index 5646c740f613..32e6f4136fa2 100644 --- a/mm/cleancache.c +++ b/mm/cleancache.c | |||
| @@ -80,7 +80,7 @@ EXPORT_SYMBOL(__cleancache_init_shared_fs); | |||
| 80 | static int cleancache_get_key(struct inode *inode, | 80 | static int cleancache_get_key(struct inode *inode, |
| 81 | struct cleancache_filekey *key) | 81 | struct cleancache_filekey *key) |
| 82 | { | 82 | { |
| 83 | int (*fhfn)(struct dentry *, __u32 *fh, int *, int); | 83 | int (*fhfn)(struct inode *, __u32 *fh, int *, struct inode *); |
| 84 | int len = 0, maxlen = CLEANCACHE_KEY_MAX; | 84 | int len = 0, maxlen = CLEANCACHE_KEY_MAX; |
| 85 | struct super_block *sb = inode->i_sb; | 85 | struct super_block *sb = inode->i_sb; |
| 86 | 86 | ||
| @@ -88,9 +88,7 @@ static int cleancache_get_key(struct inode *inode, | |||
| 88 | if (sb->s_export_op != NULL) { | 88 | if (sb->s_export_op != NULL) { |
| 89 | fhfn = sb->s_export_op->encode_fh; | 89 | fhfn = sb->s_export_op->encode_fh; |
| 90 | if (fhfn) { | 90 | if (fhfn) { |
| 91 | struct dentry d; | 91 | len = (*fhfn)(inode, &key->u.fh[0], &maxlen, NULL); |
| 92 | d.d_inode = inode; | ||
| 93 | len = (*fhfn)(&d, &key->u.fh[0], &maxlen, 0); | ||
| 94 | if (len <= 0 || len == 255) | 92 | if (len <= 0 || len == 255) |
| 95 | return -1; | 93 | return -1; |
| 96 | if (maxlen > CLEANCACHE_KEY_MAX) | 94 | if (maxlen > CLEANCACHE_KEY_MAX) |
diff --git a/mm/filemap.c b/mm/filemap.c index 64b48f934b89..a4a5260b0279 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -1899,71 +1899,6 @@ struct page *read_cache_page(struct address_space *mapping, | |||
| 1899 | } | 1899 | } |
| 1900 | EXPORT_SYMBOL(read_cache_page); | 1900 | EXPORT_SYMBOL(read_cache_page); |
| 1901 | 1901 | ||
| 1902 | /* | ||
| 1903 | * The logic we want is | ||
| 1904 | * | ||
| 1905 | * if suid or (sgid and xgrp) | ||
| 1906 | * remove privs | ||
| 1907 | */ | ||
| 1908 | int should_remove_suid(struct dentry *dentry) | ||
| 1909 | { | ||
| 1910 | umode_t mode = dentry->d_inode->i_mode; | ||
| 1911 | int kill = 0; | ||
| 1912 | |||
| 1913 | /* suid always must be killed */ | ||
| 1914 | if (unlikely(mode & S_ISUID)) | ||
| 1915 | kill = ATTR_KILL_SUID; | ||
| 1916 | |||
| 1917 | /* | ||
| 1918 | * sgid without any exec bits is just a mandatory locking mark; leave | ||
| 1919 | * it alone. If some exec bits are set, it's a real sgid; kill it. | ||
| 1920 | */ | ||
| 1921 | if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) | ||
| 1922 | kill |= ATTR_KILL_SGID; | ||
| 1923 | |||
| 1924 | if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode))) | ||
| 1925 | return kill; | ||
| 1926 | |||
| 1927 | return 0; | ||
| 1928 | } | ||
| 1929 | EXPORT_SYMBOL(should_remove_suid); | ||
| 1930 | |||
| 1931 | static int __remove_suid(struct dentry *dentry, int kill) | ||
| 1932 | { | ||
| 1933 | struct iattr newattrs; | ||
| 1934 | |||
| 1935 | newattrs.ia_valid = ATTR_FORCE | kill; | ||
| 1936 | return notify_change(dentry, &newattrs); | ||
| 1937 | } | ||
| 1938 | |||
| 1939 | int file_remove_suid(struct file *file) | ||
| 1940 | { | ||
| 1941 | struct dentry *dentry = file->f_path.dentry; | ||
| 1942 | struct inode *inode = dentry->d_inode; | ||
| 1943 | int killsuid; | ||
| 1944 | int killpriv; | ||
| 1945 | int error = 0; | ||
| 1946 | |||
| 1947 | /* Fast path for nothing security related */ | ||
| 1948 | if (IS_NOSEC(inode)) | ||
| 1949 | return 0; | ||
| 1950 | |||
| 1951 | killsuid = should_remove_suid(dentry); | ||
| 1952 | killpriv = security_inode_need_killpriv(dentry); | ||
| 1953 | |||
| 1954 | if (killpriv < 0) | ||
| 1955 | return killpriv; | ||
| 1956 | if (killpriv) | ||
| 1957 | error = security_inode_killpriv(dentry); | ||
| 1958 | if (!error && killsuid) | ||
| 1959 | error = __remove_suid(dentry, killsuid); | ||
| 1960 | if (!error && (inode->i_sb->s_flags & MS_NOSEC)) | ||
| 1961 | inode->i_flags |= S_NOSEC; | ||
| 1962 | |||
| 1963 | return error; | ||
| 1964 | } | ||
| 1965 | EXPORT_SYMBOL(file_remove_suid); | ||
| 1966 | |||
| 1967 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, | 1902 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, |
| 1968 | const struct iovec *iov, size_t base, size_t bytes) | 1903 | const struct iovec *iov, size_t base, size_t bytes) |
| 1969 | { | 1904 | { |
| @@ -2489,7 +2424,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 2489 | if (err) | 2424 | if (err) |
| 2490 | goto out; | 2425 | goto out; |
| 2491 | 2426 | ||
| 2492 | file_update_time(file); | 2427 | err = file_update_time(file); |
| 2428 | if (err) | ||
| 2429 | goto out; | ||
| 2493 | 2430 | ||
| 2494 | /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ | 2431 | /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ |
| 2495 | if (unlikely(file->f_flags & O_DIRECT)) { | 2432 | if (unlikely(file->f_flags & O_DIRECT)) { |
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index a4eb31132229..213ca1f53409 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
| @@ -426,7 +426,9 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, | |||
| 426 | if (ret) | 426 | if (ret) |
| 427 | goto out_backing; | 427 | goto out_backing; |
| 428 | 428 | ||
| 429 | file_update_time(filp); | 429 | ret = file_update_time(filp); |
| 430 | if (ret) | ||
| 431 | goto out_backing; | ||
| 430 | 432 | ||
| 431 | ret = __xip_file_write (filp, buf, count, pos, ppos); | 433 | ret = __xip_file_write (filp, buf, count, pos, ppos); |
| 432 | 434 | ||
diff --git a/mm/internal.h b/mm/internal.h index 4194ab9dc19b..5cbb78190041 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
| @@ -350,3 +350,7 @@ extern u64 hwpoison_filter_flags_mask; | |||
| 350 | extern u64 hwpoison_filter_flags_value; | 350 | extern u64 hwpoison_filter_flags_value; |
| 351 | extern u64 hwpoison_filter_memcg; | 351 | extern u64 hwpoison_filter_memcg; |
| 352 | extern u32 hwpoison_filter_enable; | 352 | extern u32 hwpoison_filter_enable; |
| 353 | |||
| 354 | extern unsigned long vm_mmap_pgoff(struct file *, unsigned long, | ||
| 355 | unsigned long, unsigned long, | ||
| 356 | unsigned long, unsigned long); | ||
| @@ -971,15 +971,13 @@ static inline unsigned long round_hint_to_min(unsigned long hint) | |||
| 971 | * The caller must hold down_write(¤t->mm->mmap_sem). | 971 | * The caller must hold down_write(¤t->mm->mmap_sem). |
| 972 | */ | 972 | */ |
| 973 | 973 | ||
| 974 | static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | 974 | unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, |
| 975 | unsigned long len, unsigned long prot, | 975 | unsigned long len, unsigned long prot, |
| 976 | unsigned long flags, unsigned long pgoff) | 976 | unsigned long flags, unsigned long pgoff) |
| 977 | { | 977 | { |
| 978 | struct mm_struct * mm = current->mm; | 978 | struct mm_struct * mm = current->mm; |
| 979 | struct inode *inode; | 979 | struct inode *inode; |
| 980 | vm_flags_t vm_flags; | 980 | vm_flags_t vm_flags; |
| 981 | int error; | ||
| 982 | unsigned long reqprot = prot; | ||
| 983 | 981 | ||
| 984 | /* | 982 | /* |
| 985 | * Does the application expect PROT_READ to imply PROT_EXEC? | 983 | * Does the application expect PROT_READ to imply PROT_EXEC? |
| @@ -1101,39 +1099,9 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | |||
| 1101 | } | 1099 | } |
| 1102 | } | 1100 | } |
| 1103 | 1101 | ||
| 1104 | error = security_file_mmap(file, reqprot, prot, flags, addr, 0); | ||
| 1105 | if (error) | ||
| 1106 | return error; | ||
| 1107 | |||
| 1108 | return mmap_region(file, addr, len, flags, vm_flags, pgoff); | 1102 | return mmap_region(file, addr, len, flags, vm_flags, pgoff); |
| 1109 | } | 1103 | } |
| 1110 | 1104 | ||
| 1111 | unsigned long do_mmap(struct file *file, unsigned long addr, | ||
| 1112 | unsigned long len, unsigned long prot, | ||
| 1113 | unsigned long flag, unsigned long offset) | ||
| 1114 | { | ||
| 1115 | if (unlikely(offset + PAGE_ALIGN(len) < offset)) | ||
| 1116 | return -EINVAL; | ||
| 1117 | if (unlikely(offset & ~PAGE_MASK)) | ||
| 1118 | return -EINVAL; | ||
| 1119 | return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | ||
| 1120 | } | ||
| 1121 | EXPORT_SYMBOL(do_mmap); | ||
| 1122 | |||
| 1123 | unsigned long vm_mmap(struct file *file, unsigned long addr, | ||
| 1124 | unsigned long len, unsigned long prot, | ||
| 1125 | unsigned long flag, unsigned long offset) | ||
| 1126 | { | ||
| 1127 | unsigned long ret; | ||
| 1128 | struct mm_struct *mm = current->mm; | ||
| 1129 | |||
| 1130 | down_write(&mm->mmap_sem); | ||
| 1131 | ret = do_mmap(file, addr, len, prot, flag, offset); | ||
| 1132 | up_write(&mm->mmap_sem); | ||
| 1133 | return ret; | ||
| 1134 | } | ||
| 1135 | EXPORT_SYMBOL(vm_mmap); | ||
| 1136 | |||
| 1137 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | 1105 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, |
| 1138 | unsigned long, prot, unsigned long, flags, | 1106 | unsigned long, prot, unsigned long, flags, |
| 1139 | unsigned long, fd, unsigned long, pgoff) | 1107 | unsigned long, fd, unsigned long, pgoff) |
| @@ -1165,10 +1133,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | |||
| 1165 | 1133 | ||
| 1166 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | 1134 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); |
| 1167 | 1135 | ||
| 1168 | down_write(¤t->mm->mmap_sem); | 1136 | retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); |
| 1169 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 1170 | up_write(¤t->mm->mmap_sem); | ||
| 1171 | |||
| 1172 | if (file) | 1137 | if (file) |
| 1173 | fput(file); | 1138 | fput(file); |
| 1174 | out: | 1139 | out: |
| @@ -1629,7 +1594,9 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, | |||
| 1629 | if (addr & ~PAGE_MASK) | 1594 | if (addr & ~PAGE_MASK) |
| 1630 | return -EINVAL; | 1595 | return -EINVAL; |
| 1631 | 1596 | ||
| 1632 | return arch_rebalance_pgtables(addr, len); | 1597 | addr = arch_rebalance_pgtables(addr, len); |
| 1598 | error = security_mmap_addr(addr); | ||
| 1599 | return error ? error : addr; | ||
| 1633 | } | 1600 | } |
| 1634 | 1601 | ||
| 1635 | EXPORT_SYMBOL(get_unmapped_area); | 1602 | EXPORT_SYMBOL(get_unmapped_area); |
| @@ -1819,7 +1786,7 @@ int expand_downwards(struct vm_area_struct *vma, | |||
| 1819 | return -ENOMEM; | 1786 | return -ENOMEM; |
| 1820 | 1787 | ||
| 1821 | address &= PAGE_MASK; | 1788 | address &= PAGE_MASK; |
| 1822 | error = security_file_mmap(NULL, 0, 0, 0, address, 1); | 1789 | error = security_mmap_addr(address); |
| 1823 | if (error) | 1790 | if (error) |
| 1824 | return error; | 1791 | return error; |
| 1825 | 1792 | ||
| @@ -2159,7 +2126,6 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) | |||
| 2159 | 2126 | ||
| 2160 | return 0; | 2127 | return 0; |
| 2161 | } | 2128 | } |
| 2162 | EXPORT_SYMBOL(do_munmap); | ||
| 2163 | 2129 | ||
| 2164 | int vm_munmap(unsigned long start, size_t len) | 2130 | int vm_munmap(unsigned long start, size_t len) |
| 2165 | { | 2131 | { |
| @@ -2207,10 +2173,6 @@ static unsigned long do_brk(unsigned long addr, unsigned long len) | |||
| 2207 | if (!len) | 2173 | if (!len) |
| 2208 | return addr; | 2174 | return addr; |
| 2209 | 2175 | ||
| 2210 | error = security_file_mmap(NULL, 0, 0, 0, addr, 1); | ||
| 2211 | if (error) | ||
| 2212 | return error; | ||
| 2213 | |||
| 2214 | flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; | 2176 | flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; |
| 2215 | 2177 | ||
| 2216 | error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); | 2178 | error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); |
| @@ -2563,10 +2525,6 @@ int install_special_mapping(struct mm_struct *mm, | |||
| 2563 | vma->vm_ops = &special_mapping_vmops; | 2525 | vma->vm_ops = &special_mapping_vmops; |
| 2564 | vma->vm_private_data = pages; | 2526 | vma->vm_private_data = pages; |
| 2565 | 2527 | ||
| 2566 | ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); | ||
| 2567 | if (ret) | ||
| 2568 | goto out; | ||
| 2569 | |||
| 2570 | ret = insert_vm_struct(mm, vma); | 2528 | ret = insert_vm_struct(mm, vma); |
| 2571 | if (ret) | 2529 | if (ret) |
| 2572 | goto out; | 2530 | goto out; |
diff --git a/mm/mremap.c b/mm/mremap.c index db8d983b5a7d..21fed202ddad 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
| @@ -371,10 +371,6 @@ static unsigned long mremap_to(unsigned long addr, | |||
| 371 | if ((addr <= new_addr) && (addr+old_len) > new_addr) | 371 | if ((addr <= new_addr) && (addr+old_len) > new_addr) |
| 372 | goto out; | 372 | goto out; |
| 373 | 373 | ||
| 374 | ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); | ||
| 375 | if (ret) | ||
| 376 | goto out; | ||
| 377 | |||
| 378 | ret = do_munmap(mm, new_addr, new_len); | 374 | ret = do_munmap(mm, new_addr, new_len); |
| 379 | if (ret) | 375 | if (ret) |
| 380 | goto out; | 376 | goto out; |
| @@ -432,15 +428,17 @@ static int vma_expandable(struct vm_area_struct *vma, unsigned long delta) | |||
| 432 | * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise | 428 | * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise |
| 433 | * This option implies MREMAP_MAYMOVE. | 429 | * This option implies MREMAP_MAYMOVE. |
| 434 | */ | 430 | */ |
| 435 | unsigned long do_mremap(unsigned long addr, | 431 | SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, |
| 436 | unsigned long old_len, unsigned long new_len, | 432 | unsigned long, new_len, unsigned long, flags, |
| 437 | unsigned long flags, unsigned long new_addr) | 433 | unsigned long, new_addr) |
| 438 | { | 434 | { |
| 439 | struct mm_struct *mm = current->mm; | 435 | struct mm_struct *mm = current->mm; |
| 440 | struct vm_area_struct *vma; | 436 | struct vm_area_struct *vma; |
| 441 | unsigned long ret = -EINVAL; | 437 | unsigned long ret = -EINVAL; |
| 442 | unsigned long charged = 0; | 438 | unsigned long charged = 0; |
| 443 | 439 | ||
| 440 | down_write(¤t->mm->mmap_sem); | ||
| 441 | |||
| 444 | if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) | 442 | if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) |
| 445 | goto out; | 443 | goto out; |
| 446 | 444 | ||
| @@ -530,25 +528,11 @@ unsigned long do_mremap(unsigned long addr, | |||
| 530 | goto out; | 528 | goto out; |
| 531 | } | 529 | } |
| 532 | 530 | ||
| 533 | ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); | ||
| 534 | if (ret) | ||
| 535 | goto out; | ||
| 536 | ret = move_vma(vma, addr, old_len, new_len, new_addr); | 531 | ret = move_vma(vma, addr, old_len, new_len, new_addr); |
| 537 | } | 532 | } |
| 538 | out: | 533 | out: |
| 539 | if (ret & ~PAGE_MASK) | 534 | if (ret & ~PAGE_MASK) |
| 540 | vm_unacct_memory(charged); | 535 | vm_unacct_memory(charged); |
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, | ||
| 545 | unsigned long, new_len, unsigned long, flags, | ||
| 546 | unsigned long, new_addr) | ||
| 547 | { | ||
| 548 | unsigned long ret; | ||
| 549 | |||
| 550 | down_write(¤t->mm->mmap_sem); | ||
| 551 | ret = do_mremap(addr, old_len, new_len, flags, new_addr); | ||
| 552 | up_write(¤t->mm->mmap_sem); | 536 | up_write(¤t->mm->mmap_sem); |
| 553 | return ret; | 537 | return ret; |
| 554 | } | 538 | } |
diff --git a/mm/nommu.c b/mm/nommu.c index bb8f4f004a82..c4acfbc09972 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -889,7 +889,6 @@ static int validate_mmap_request(struct file *file, | |||
| 889 | unsigned long *_capabilities) | 889 | unsigned long *_capabilities) |
| 890 | { | 890 | { |
| 891 | unsigned long capabilities, rlen; | 891 | unsigned long capabilities, rlen; |
| 892 | unsigned long reqprot = prot; | ||
| 893 | int ret; | 892 | int ret; |
| 894 | 893 | ||
| 895 | /* do the simple checks first */ | 894 | /* do the simple checks first */ |
| @@ -1047,7 +1046,7 @@ static int validate_mmap_request(struct file *file, | |||
| 1047 | } | 1046 | } |
| 1048 | 1047 | ||
| 1049 | /* allow the security API to have its say */ | 1048 | /* allow the security API to have its say */ |
| 1050 | ret = security_file_mmap(file, reqprot, prot, flags, addr, 0); | 1049 | ret = security_mmap_addr(addr); |
| 1051 | if (ret < 0) | 1050 | if (ret < 0) |
| 1052 | return ret; | 1051 | return ret; |
| 1053 | 1052 | ||
| @@ -1233,7 +1232,7 @@ enomem: | |||
| 1233 | /* | 1232 | /* |
| 1234 | * handle mapping creation for uClinux | 1233 | * handle mapping creation for uClinux |
| 1235 | */ | 1234 | */ |
| 1236 | static unsigned long do_mmap_pgoff(struct file *file, | 1235 | unsigned long do_mmap_pgoff(struct file *file, |
| 1237 | unsigned long addr, | 1236 | unsigned long addr, |
| 1238 | unsigned long len, | 1237 | unsigned long len, |
| 1239 | unsigned long prot, | 1238 | unsigned long prot, |
| @@ -1471,32 +1470,6 @@ error_getting_region: | |||
| 1471 | return -ENOMEM; | 1470 | return -ENOMEM; |
| 1472 | } | 1471 | } |
| 1473 | 1472 | ||
| 1474 | unsigned long do_mmap(struct file *file, unsigned long addr, | ||
| 1475 | unsigned long len, unsigned long prot, | ||
| 1476 | unsigned long flag, unsigned long offset) | ||
| 1477 | { | ||
| 1478 | if (unlikely(offset + PAGE_ALIGN(len) < offset)) | ||
| 1479 | return -EINVAL; | ||
| 1480 | if (unlikely(offset & ~PAGE_MASK)) | ||
| 1481 | return -EINVAL; | ||
| 1482 | return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | ||
| 1483 | } | ||
| 1484 | EXPORT_SYMBOL(do_mmap); | ||
| 1485 | |||
| 1486 | unsigned long vm_mmap(struct file *file, unsigned long addr, | ||
| 1487 | unsigned long len, unsigned long prot, | ||
| 1488 | unsigned long flag, unsigned long offset) | ||
| 1489 | { | ||
| 1490 | unsigned long ret; | ||
| 1491 | struct mm_struct *mm = current->mm; | ||
| 1492 | |||
| 1493 | down_write(&mm->mmap_sem); | ||
| 1494 | ret = do_mmap(file, addr, len, prot, flag, offset); | ||
| 1495 | up_write(&mm->mmap_sem); | ||
| 1496 | return ret; | ||
| 1497 | } | ||
| 1498 | EXPORT_SYMBOL(vm_mmap); | ||
| 1499 | |||
| 1500 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | 1473 | SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, |
| 1501 | unsigned long, prot, unsigned long, flags, | 1474 | unsigned long, prot, unsigned long, flags, |
| 1502 | unsigned long, fd, unsigned long, pgoff) | 1475 | unsigned long, fd, unsigned long, pgoff) |
| @@ -1513,9 +1486,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, | |||
| 1513 | 1486 | ||
| 1514 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | 1487 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); |
| 1515 | 1488 | ||
| 1516 | down_write(¤t->mm->mmap_sem); | 1489 | ret = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); |
| 1517 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
| 1518 | up_write(¤t->mm->mmap_sem); | ||
| 1519 | 1490 | ||
| 1520 | if (file) | 1491 | if (file) |
| 1521 | fput(file); | 1492 | fput(file); |
diff --git a/mm/shmem.c b/mm/shmem.c index d576b84d913c..585bd220a21e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -2439,11 +2439,9 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, | |||
| 2439 | return dentry; | 2439 | return dentry; |
| 2440 | } | 2440 | } |
| 2441 | 2441 | ||
| 2442 | static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, | 2442 | static int shmem_encode_fh(struct inode *inode, __u32 *fh, int *len, |
| 2443 | int connectable) | 2443 | struct inode *parent) |
| 2444 | { | 2444 | { |
| 2445 | struct inode *inode = dentry->d_inode; | ||
| 2446 | |||
| 2447 | if (*len < 3) { | 2445 | if (*len < 3) { |
| 2448 | *len = 3; | 2446 | *len = 3; |
| 2449 | return 255; | 2447 | return 255; |
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <linux/export.h> | 4 | #include <linux/export.h> |
| 5 | #include <linux/err.h> | 5 | #include <linux/err.h> |
| 6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
| 7 | #include <linux/security.h> | ||
| 7 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
| 8 | 9 | ||
| 9 | #include "internal.h" | 10 | #include "internal.h" |
| @@ -341,6 +342,35 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start, | |||
| 341 | } | 342 | } |
| 342 | EXPORT_SYMBOL_GPL(get_user_pages_fast); | 343 | EXPORT_SYMBOL_GPL(get_user_pages_fast); |
| 343 | 344 | ||
| 345 | unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, | ||
| 346 | unsigned long len, unsigned long prot, | ||
| 347 | unsigned long flag, unsigned long pgoff) | ||
| 348 | { | ||
| 349 | unsigned long ret; | ||
| 350 | struct mm_struct *mm = current->mm; | ||
| 351 | |||
| 352 | ret = security_mmap_file(file, prot, flag); | ||
| 353 | if (!ret) { | ||
| 354 | down_write(&mm->mmap_sem); | ||
| 355 | ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff); | ||
| 356 | up_write(&mm->mmap_sem); | ||
| 357 | } | ||
| 358 | return ret; | ||
| 359 | } | ||
| 360 | |||
| 361 | unsigned long vm_mmap(struct file *file, unsigned long addr, | ||
| 362 | unsigned long len, unsigned long prot, | ||
| 363 | unsigned long flag, unsigned long offset) | ||
| 364 | { | ||
| 365 | if (unlikely(offset + PAGE_ALIGN(len) < offset)) | ||
| 366 | return -EINVAL; | ||
| 367 | if (unlikely(offset & ~PAGE_MASK)) | ||
| 368 | return -EINVAL; | ||
| 369 | |||
| 370 | return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); | ||
| 371 | } | ||
| 372 | EXPORT_SYMBOL(vm_mmap); | ||
| 373 | |||
| 344 | /* Tracepoints definitions. */ | 374 | /* Tracepoints definitions. */ |
| 345 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); | 375 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); |
| 346 | EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); | 376 | EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc); |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 8522a4793374..ca8e0a57d945 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
| @@ -16,8 +16,6 @@ | |||
| 16 | #include <net/netlink.h> | 16 | #include <net/netlink.h> |
| 17 | #include <net/pkt_sched.h> | 17 | #include <net/pkt_sched.h> |
| 18 | 18 | ||
| 19 | extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ | ||
| 20 | |||
| 21 | /* | 19 | /* |
| 22 | * The ATM queuing discipline provides a framework for invoking classifiers | 20 | * The ATM queuing discipline provides a framework for invoking classifiers |
| 23 | * (aka "filters"), which in turn select classes of this queuing discipline. | 21 | * (aka "filters"), which in turn select classes of this queuing discipline. |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 032daab449b0..8ea39aabe948 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -490,17 +490,9 @@ static int common_mmap(int op, struct file *file, unsigned long prot, | |||
| 490 | return common_file_perm(op, file, mask); | 490 | return common_file_perm(op, file, mask); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | static int apparmor_file_mmap(struct file *file, unsigned long reqprot, | 493 | static int apparmor_mmap_file(struct file *file, unsigned long reqprot, |
| 494 | unsigned long prot, unsigned long flags, | 494 | unsigned long prot, unsigned long flags) |
| 495 | unsigned long addr, unsigned long addr_only) | ||
| 496 | { | 495 | { |
| 497 | int rc = 0; | ||
| 498 | |||
| 499 | /* do DAC check */ | ||
| 500 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
| 501 | if (rc || addr_only) | ||
| 502 | return rc; | ||
| 503 | |||
| 504 | return common_mmap(OP_FMMAP, file, prot, flags); | 496 | return common_mmap(OP_FMMAP, file, prot, flags); |
| 505 | } | 497 | } |
| 506 | 498 | ||
| @@ -646,7 +638,8 @@ static struct security_operations apparmor_ops = { | |||
| 646 | .file_permission = apparmor_file_permission, | 638 | .file_permission = apparmor_file_permission, |
| 647 | .file_alloc_security = apparmor_file_alloc_security, | 639 | .file_alloc_security = apparmor_file_alloc_security, |
| 648 | .file_free_security = apparmor_file_free_security, | 640 | .file_free_security = apparmor_file_free_security, |
| 649 | .file_mmap = apparmor_file_mmap, | 641 | .mmap_file = apparmor_mmap_file, |
| 642 | .mmap_addr = cap_mmap_addr, | ||
| 650 | .file_mprotect = apparmor_file_mprotect, | 643 | .file_mprotect = apparmor_file_mprotect, |
| 651 | .file_lock = apparmor_file_lock, | 644 | .file_lock = apparmor_file_lock, |
| 652 | 645 | ||
diff --git a/security/capability.c b/security/capability.c index fca889676c5e..61095df8b89a 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -949,7 +949,8 @@ void __init security_fixup_ops(struct security_operations *ops) | |||
| 949 | set_to_cap_if_null(ops, file_alloc_security); | 949 | set_to_cap_if_null(ops, file_alloc_security); |
| 950 | set_to_cap_if_null(ops, file_free_security); | 950 | set_to_cap_if_null(ops, file_free_security); |
| 951 | set_to_cap_if_null(ops, file_ioctl); | 951 | set_to_cap_if_null(ops, file_ioctl); |
| 952 | set_to_cap_if_null(ops, file_mmap); | 952 | set_to_cap_if_null(ops, mmap_addr); |
| 953 | set_to_cap_if_null(ops, mmap_file); | ||
| 953 | set_to_cap_if_null(ops, file_mprotect); | 954 | set_to_cap_if_null(ops, file_mprotect); |
| 954 | set_to_cap_if_null(ops, file_lock); | 955 | set_to_cap_if_null(ops, file_lock); |
| 955 | set_to_cap_if_null(ops, file_fcntl); | 956 | set_to_cap_if_null(ops, file_fcntl); |
diff --git a/security/commoncap.c b/security/commoncap.c index e771cb1b2d79..6dbae4650abe 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
| @@ -958,22 +958,15 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 958 | } | 958 | } |
| 959 | 959 | ||
| 960 | /* | 960 | /* |
| 961 | * cap_file_mmap - check if able to map given addr | 961 | * cap_mmap_addr - check if able to map given addr |
| 962 | * @file: unused | ||
| 963 | * @reqprot: unused | ||
| 964 | * @prot: unused | ||
| 965 | * @flags: unused | ||
| 966 | * @addr: address attempting to be mapped | 962 | * @addr: address attempting to be mapped |
| 967 | * @addr_only: unused | ||
| 968 | * | 963 | * |
| 969 | * If the process is attempting to map memory below dac_mmap_min_addr they need | 964 | * If the process is attempting to map memory below dac_mmap_min_addr they need |
| 970 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the | 965 | * CAP_SYS_RAWIO. The other parameters to this function are unused by the |
| 971 | * capability security module. Returns 0 if this mapping should be allowed | 966 | * capability security module. Returns 0 if this mapping should be allowed |
| 972 | * -EPERM if not. | 967 | * -EPERM if not. |
| 973 | */ | 968 | */ |
| 974 | int cap_file_mmap(struct file *file, unsigned long reqprot, | 969 | int cap_mmap_addr(unsigned long addr) |
| 975 | unsigned long prot, unsigned long flags, | ||
| 976 | unsigned long addr, unsigned long addr_only) | ||
| 977 | { | 970 | { |
| 978 | int ret = 0; | 971 | int ret = 0; |
| 979 | 972 | ||
| @@ -986,3 +979,9 @@ int cap_file_mmap(struct file *file, unsigned long reqprot, | |||
| 986 | } | 979 | } |
| 987 | return ret; | 980 | return ret; |
| 988 | } | 981 | } |
| 982 | |||
| 983 | int cap_mmap_file(struct file *file, unsigned long reqprot, | ||
| 984 | unsigned long prot, unsigned long flags) | ||
| 985 | { | ||
| 986 | return 0; | ||
| 987 | } | ||
diff --git a/security/security.c b/security/security.c index 5497a57fba01..3efc9b12aef4 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | #include <linux/ima.h> | 20 | #include <linux/ima.h> |
| 21 | #include <linux/evm.h> | 21 | #include <linux/evm.h> |
| 22 | #include <linux/fsnotify.h> | 22 | #include <linux/fsnotify.h> |
| 23 | #include <linux/mman.h> | ||
| 24 | #include <linux/mount.h> | ||
| 25 | #include <linux/personality.h> | ||
| 23 | #include <net/flow.h> | 26 | #include <net/flow.h> |
| 24 | 27 | ||
| 25 | #define MAX_LSM_EVM_XATTR 2 | 28 | #define MAX_LSM_EVM_XATTR 2 |
| @@ -657,18 +660,56 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 657 | return security_ops->file_ioctl(file, cmd, arg); | 660 | return security_ops->file_ioctl(file, cmd, arg); |
| 658 | } | 661 | } |
| 659 | 662 | ||
| 660 | int security_file_mmap(struct file *file, unsigned long reqprot, | 663 | static inline unsigned long mmap_prot(struct file *file, unsigned long prot) |
| 661 | unsigned long prot, unsigned long flags, | ||
| 662 | unsigned long addr, unsigned long addr_only) | ||
| 663 | { | 664 | { |
| 664 | int ret; | 665 | /* |
| 666 | * Does we have PROT_READ and does the application expect | ||
| 667 | * it to imply PROT_EXEC? If not, nothing to talk about... | ||
| 668 | */ | ||
| 669 | if ((prot & (PROT_READ | PROT_EXEC)) != PROT_READ) | ||
| 670 | return prot; | ||
| 671 | if (!(current->personality & READ_IMPLIES_EXEC)) | ||
| 672 | return prot; | ||
| 673 | /* | ||
| 674 | * if that's an anonymous mapping, let it. | ||
| 675 | */ | ||
| 676 | if (!file) | ||
| 677 | return prot | PROT_EXEC; | ||
| 678 | /* | ||
| 679 | * ditto if it's not on noexec mount, except that on !MMU we need | ||
| 680 | * BDI_CAP_EXEC_MMAP (== VM_MAYEXEC) in this case | ||
| 681 | */ | ||
| 682 | if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { | ||
| 683 | #ifndef CONFIG_MMU | ||
| 684 | unsigned long caps = 0; | ||
| 685 | struct address_space *mapping = file->f_mapping; | ||
| 686 | if (mapping && mapping->backing_dev_info) | ||
| 687 | caps = mapping->backing_dev_info->capabilities; | ||
| 688 | if (!(caps & BDI_CAP_EXEC_MAP)) | ||
| 689 | return prot; | ||
| 690 | #endif | ||
| 691 | return prot | PROT_EXEC; | ||
| 692 | } | ||
| 693 | /* anything on noexec mount won't get PROT_EXEC */ | ||
| 694 | return prot; | ||
| 695 | } | ||
| 665 | 696 | ||
| 666 | ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); | 697 | int security_mmap_file(struct file *file, unsigned long prot, |
| 698 | unsigned long flags) | ||
| 699 | { | ||
| 700 | int ret; | ||
| 701 | ret = security_ops->mmap_file(file, prot, | ||
| 702 | mmap_prot(file, prot), flags); | ||
| 667 | if (ret) | 703 | if (ret) |
| 668 | return ret; | 704 | return ret; |
| 669 | return ima_file_mmap(file, prot); | 705 | return ima_file_mmap(file, prot); |
| 670 | } | 706 | } |
| 671 | 707 | ||
| 708 | int security_mmap_addr(unsigned long addr) | ||
| 709 | { | ||
| 710 | return security_ops->mmap_addr(addr); | ||
| 711 | } | ||
| 712 | |||
| 672 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 713 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
| 673 | unsigned long prot) | 714 | unsigned long prot) |
| 674 | { | 715 | { |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fa2341b68331..372ec6502aa8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -3083,9 +3083,7 @@ error: | |||
| 3083 | return rc; | 3083 | return rc; |
| 3084 | } | 3084 | } |
| 3085 | 3085 | ||
| 3086 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, | 3086 | static int selinux_mmap_addr(unsigned long addr) |
| 3087 | unsigned long prot, unsigned long flags, | ||
| 3088 | unsigned long addr, unsigned long addr_only) | ||
| 3089 | { | 3087 | { |
| 3090 | int rc = 0; | 3088 | int rc = 0; |
| 3091 | u32 sid = current_sid(); | 3089 | u32 sid = current_sid(); |
| @@ -3104,10 +3102,12 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot, | |||
| 3104 | } | 3102 | } |
| 3105 | 3103 | ||
| 3106 | /* do DAC check on address space usage */ | 3104 | /* do DAC check on address space usage */ |
| 3107 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | 3105 | return cap_mmap_addr(addr); |
| 3108 | if (rc || addr_only) | 3106 | } |
| 3109 | return rc; | ||
| 3110 | 3107 | ||
| 3108 | static int selinux_mmap_file(struct file *file, unsigned long reqprot, | ||
| 3109 | unsigned long prot, unsigned long flags) | ||
| 3110 | { | ||
| 3111 | if (selinux_checkreqprot) | 3111 | if (selinux_checkreqprot) |
| 3112 | prot = reqprot; | 3112 | prot = reqprot; |
| 3113 | 3113 | ||
| @@ -5570,7 +5570,8 @@ static struct security_operations selinux_ops = { | |||
| 5570 | .file_alloc_security = selinux_file_alloc_security, | 5570 | .file_alloc_security = selinux_file_alloc_security, |
| 5571 | .file_free_security = selinux_file_free_security, | 5571 | .file_free_security = selinux_file_free_security, |
| 5572 | .file_ioctl = selinux_file_ioctl, | 5572 | .file_ioctl = selinux_file_ioctl, |
| 5573 | .file_mmap = selinux_file_mmap, | 5573 | .mmap_file = selinux_mmap_file, |
| 5574 | .mmap_addr = selinux_mmap_addr, | ||
| 5574 | .file_mprotect = selinux_file_mprotect, | 5575 | .file_mprotect = selinux_file_mprotect, |
| 5575 | .file_lock = selinux_file_lock, | 5576 | .file_lock = selinux_file_lock, |
| 5576 | .file_fcntl = selinux_file_fcntl, | 5577 | .file_fcntl = selinux_file_fcntl, |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 4e93f9ef970b..3ad290251288 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -1259,12 +1259,8 @@ static int sel_make_bools(void) | |||
| 1259 | if (!inode) | 1259 | if (!inode) |
| 1260 | goto out; | 1260 | goto out; |
| 1261 | 1261 | ||
| 1262 | ret = -EINVAL; | ||
| 1263 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | ||
| 1264 | if (len < 0) | ||
| 1265 | goto out; | ||
| 1266 | |||
| 1267 | ret = -ENAMETOOLONG; | 1262 | ret = -ENAMETOOLONG; |
| 1263 | len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]); | ||
| 1268 | if (len >= PAGE_SIZE) | 1264 | if (len >= PAGE_SIZE) |
| 1269 | goto out; | 1265 | goto out; |
| 1270 | 1266 | ||
| @@ -1557,19 +1553,10 @@ static inline u32 sel_ino_to_perm(unsigned long ino) | |||
| 1557 | static ssize_t sel_read_class(struct file *file, char __user *buf, | 1553 | static ssize_t sel_read_class(struct file *file, char __user *buf, |
| 1558 | size_t count, loff_t *ppos) | 1554 | size_t count, loff_t *ppos) |
| 1559 | { | 1555 | { |
| 1560 | ssize_t rc, len; | ||
| 1561 | char *page; | ||
| 1562 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1556 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
| 1563 | 1557 | char res[TMPBUFLEN]; | |
| 1564 | page = (char *)__get_free_page(GFP_KERNEL); | 1558 | ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_class(ino)); |
| 1565 | if (!page) | 1559 | return simple_read_from_buffer(buf, count, ppos, res, len); |
| 1566 | return -ENOMEM; | ||
| 1567 | |||
| 1568 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); | ||
| 1569 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | ||
| 1570 | free_page((unsigned long)page); | ||
| 1571 | |||
| 1572 | return rc; | ||
| 1573 | } | 1560 | } |
| 1574 | 1561 | ||
| 1575 | static const struct file_operations sel_class_ops = { | 1562 | static const struct file_operations sel_class_ops = { |
| @@ -1580,19 +1567,10 @@ static const struct file_operations sel_class_ops = { | |||
| 1580 | static ssize_t sel_read_perm(struct file *file, char __user *buf, | 1567 | static ssize_t sel_read_perm(struct file *file, char __user *buf, |
| 1581 | size_t count, loff_t *ppos) | 1568 | size_t count, loff_t *ppos) |
| 1582 | { | 1569 | { |
| 1583 | ssize_t rc, len; | ||
| 1584 | char *page; | ||
| 1585 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; | 1570 | unsigned long ino = file->f_path.dentry->d_inode->i_ino; |
| 1586 | 1571 | char res[TMPBUFLEN]; | |
| 1587 | page = (char *)__get_free_page(GFP_KERNEL); | 1572 | ssize_t len = snprintf(res, sizeof(res), "%d", sel_ino_to_perm(ino)); |
| 1588 | if (!page) | 1573 | return simple_read_from_buffer(buf, count, ppos, res, len); |
| 1589 | return -ENOMEM; | ||
| 1590 | |||
| 1591 | len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_perm(ino)); | ||
| 1592 | rc = simple_read_from_buffer(buf, count, ppos, page, len); | ||
| 1593 | free_page((unsigned long)page); | ||
| 1594 | |||
| 1595 | return rc; | ||
| 1596 | } | 1574 | } |
| 1597 | 1575 | ||
| 1598 | static const struct file_operations sel_perm_ops = { | 1576 | static const struct file_operations sel_perm_ops = { |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d583c0545808..ee0bb5735f35 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -1171,7 +1171,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
| 1171 | } | 1171 | } |
| 1172 | 1172 | ||
| 1173 | /** | 1173 | /** |
| 1174 | * smack_file_mmap : | 1174 | * smack_mmap_file : |
| 1175 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | 1175 | * Check permissions for a mmap operation. The @file may be NULL, e.g. |
| 1176 | * if mapping anonymous memory. | 1176 | * if mapping anonymous memory. |
| 1177 | * @file contains the file structure for file to map (may be NULL). | 1177 | * @file contains the file structure for file to map (may be NULL). |
| @@ -1180,10 +1180,9 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
| 1180 | * @flags contains the operational flags. | 1180 | * @flags contains the operational flags. |
| 1181 | * Return 0 if permission is granted. | 1181 | * Return 0 if permission is granted. |
| 1182 | */ | 1182 | */ |
| 1183 | static int smack_file_mmap(struct file *file, | 1183 | static int smack_mmap_file(struct file *file, |
| 1184 | unsigned long reqprot, unsigned long prot, | 1184 | unsigned long reqprot, unsigned long prot, |
| 1185 | unsigned long flags, unsigned long addr, | 1185 | unsigned long flags) |
| 1186 | unsigned long addr_only) | ||
| 1187 | { | 1186 | { |
| 1188 | struct smack_known *skp; | 1187 | struct smack_known *skp; |
| 1189 | struct smack_rule *srp; | 1188 | struct smack_rule *srp; |
| @@ -1198,11 +1197,6 @@ static int smack_file_mmap(struct file *file, | |||
| 1198 | int tmay; | 1197 | int tmay; |
| 1199 | int rc; | 1198 | int rc; |
| 1200 | 1199 | ||
| 1201 | /* do DAC check on address space usage */ | ||
| 1202 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
| 1203 | if (rc || addr_only) | ||
| 1204 | return rc; | ||
| 1205 | |||
| 1206 | if (file == NULL || file->f_dentry == NULL) | 1200 | if (file == NULL || file->f_dentry == NULL) |
| 1207 | return 0; | 1201 | return 0; |
| 1208 | 1202 | ||
| @@ -3482,7 +3476,8 @@ struct security_operations smack_ops = { | |||
| 3482 | .file_ioctl = smack_file_ioctl, | 3476 | .file_ioctl = smack_file_ioctl, |
| 3483 | .file_lock = smack_file_lock, | 3477 | .file_lock = smack_file_lock, |
| 3484 | .file_fcntl = smack_file_fcntl, | 3478 | .file_fcntl = smack_file_fcntl, |
| 3485 | .file_mmap = smack_file_mmap, | 3479 | .mmap_file = smack_mmap_file, |
| 3480 | .mmap_addr = cap_mmap_addr, | ||
| 3486 | .file_set_fowner = smack_file_set_fowner, | 3481 | .file_set_fowner = smack_file_set_fowner, |
| 3487 | .file_send_sigiotask = smack_file_send_sigiotask, | 3482 | .file_send_sigiotask = smack_file_send_sigiotask, |
| 3488 | .file_receive = smack_file_receive, | 3483 | .file_receive = smack_file_receive, |
