diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 21:34:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-10 21:34:42 -0500 |
commit | b6da0076bab5a12afb19312ffee41c95490af2a0 (patch) | |
tree | 52a5675b9c2ff95d88b981d5b9a3822f6073c112 /fs | |
parent | cbfe0de303a55ed96d8831c2d5f56f8131cd6612 (diff) | |
parent | a53b831549141aa060a8b54b76e3a42870d74cc0 (diff) |
Merge branch 'akpm' (patchbomb from Andrew)
Merge first patchbomb from Andrew Morton:
- a few minor cifs fixes
- dma-debug upadtes
- ocfs2
- slab
- about half of MM
- procfs
- kernel/exit.c
- panic.c tweaks
- printk upates
- lib/ updates
- checkpatch updates
- fs/binfmt updates
- the drivers/rtc tree
- nilfs
- kmod fixes
- more kernel/exit.c
- various other misc tweaks and fixes
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (190 commits)
exit: pidns: fix/update the comments in zap_pid_ns_processes()
exit: pidns: alloc_pid() leaks pid_namespace if child_reaper is exiting
exit: exit_notify: re-use "dead" list to autoreap current
exit: reparent: call forget_original_parent() under tasklist_lock
exit: reparent: avoid find_new_reaper() if no children
exit: reparent: introduce find_alive_thread()
exit: reparent: introduce find_child_reaper()
exit: reparent: document the ->has_child_subreaper checks
exit: reparent: s/while_each_thread/for_each_thread/ in find_new_reaper()
exit: reparent: fix the cross-namespace PR_SET_CHILD_SUBREAPER reparenting
exit: reparent: fix the dead-parent PR_SET_CHILD_SUBREAPER reparenting
exit: proc: don't try to flush /proc/tgid/task/tgid
exit: release_task: fix the comment about group leader accounting
exit: wait: drop tasklist_lock before psig->c* accounting
exit: wait: don't use zombie->real_parent
exit: wait: cleanup the ptrace_reparented() checks
usermodehelper: kill the kmod_thread_locker logic
usermodehelper: don't use CLONE_VFORK for ____call_usermodehelper()
fs/hfs/catalog.c: fix comparison bug in hfs_cat_keycmp
nilfs2: fix the nilfs_iget() vs. nilfs_new_inode() races
...
Diffstat (limited to 'fs')
41 files changed, 648 insertions, 397 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d8fc0605b9d2..3a6175fe10c0 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -1994,18 +1994,6 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, | |||
1994 | shdr4extnum->sh_info = segs; | 1994 | shdr4extnum->sh_info = segs; |
1995 | } | 1995 | } |
1996 | 1996 | ||
1997 | static size_t elf_core_vma_data_size(struct vm_area_struct *gate_vma, | ||
1998 | unsigned long mm_flags) | ||
1999 | { | ||
2000 | struct vm_area_struct *vma; | ||
2001 | size_t size = 0; | ||
2002 | |||
2003 | for (vma = first_vma(current, gate_vma); vma != NULL; | ||
2004 | vma = next_vma(vma, gate_vma)) | ||
2005 | size += vma_dump_size(vma, mm_flags); | ||
2006 | return size; | ||
2007 | } | ||
2008 | |||
2009 | /* | 1997 | /* |
2010 | * Actual dumper | 1998 | * Actual dumper |
2011 | * | 1999 | * |
@@ -2017,7 +2005,8 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2017 | { | 2005 | { |
2018 | int has_dumped = 0; | 2006 | int has_dumped = 0; |
2019 | mm_segment_t fs; | 2007 | mm_segment_t fs; |
2020 | int segs; | 2008 | int segs, i; |
2009 | size_t vma_data_size = 0; | ||
2021 | struct vm_area_struct *vma, *gate_vma; | 2010 | struct vm_area_struct *vma, *gate_vma; |
2022 | struct elfhdr *elf = NULL; | 2011 | struct elfhdr *elf = NULL; |
2023 | loff_t offset = 0, dataoff; | 2012 | loff_t offset = 0, dataoff; |
@@ -2026,6 +2015,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2026 | struct elf_shdr *shdr4extnum = NULL; | 2015 | struct elf_shdr *shdr4extnum = NULL; |
2027 | Elf_Half e_phnum; | 2016 | Elf_Half e_phnum; |
2028 | elf_addr_t e_shoff; | 2017 | elf_addr_t e_shoff; |
2018 | elf_addr_t *vma_filesz = NULL; | ||
2029 | 2019 | ||
2030 | /* | 2020 | /* |
2031 | * We no longer stop all VM operations. | 2021 | * We no longer stop all VM operations. |
@@ -2093,7 +2083,20 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2093 | 2083 | ||
2094 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 2084 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
2095 | 2085 | ||
2096 | offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags); | 2086 | vma_filesz = kmalloc_array(segs - 1, sizeof(*vma_filesz), GFP_KERNEL); |
2087 | if (!vma_filesz) | ||
2088 | goto end_coredump; | ||
2089 | |||
2090 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; | ||
2091 | vma = next_vma(vma, gate_vma)) { | ||
2092 | unsigned long dump_size; | ||
2093 | |||
2094 | dump_size = vma_dump_size(vma, cprm->mm_flags); | ||
2095 | vma_filesz[i++] = dump_size; | ||
2096 | vma_data_size += dump_size; | ||
2097 | } | ||
2098 | |||
2099 | offset += vma_data_size; | ||
2097 | offset += elf_core_extra_data_size(); | 2100 | offset += elf_core_extra_data_size(); |
2098 | e_shoff = offset; | 2101 | e_shoff = offset; |
2099 | 2102 | ||
@@ -2113,7 +2116,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2113 | goto end_coredump; | 2116 | goto end_coredump; |
2114 | 2117 | ||
2115 | /* Write program headers for segments dump */ | 2118 | /* Write program headers for segments dump */ |
2116 | for (vma = first_vma(current, gate_vma); vma != NULL; | 2119 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; |
2117 | vma = next_vma(vma, gate_vma)) { | 2120 | vma = next_vma(vma, gate_vma)) { |
2118 | struct elf_phdr phdr; | 2121 | struct elf_phdr phdr; |
2119 | 2122 | ||
@@ -2121,7 +2124,7 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2121 | phdr.p_offset = offset; | 2124 | phdr.p_offset = offset; |
2122 | phdr.p_vaddr = vma->vm_start; | 2125 | phdr.p_vaddr = vma->vm_start; |
2123 | phdr.p_paddr = 0; | 2126 | phdr.p_paddr = 0; |
2124 | phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags); | 2127 | phdr.p_filesz = vma_filesz[i++]; |
2125 | phdr.p_memsz = vma->vm_end - vma->vm_start; | 2128 | phdr.p_memsz = vma->vm_end - vma->vm_start; |
2126 | offset += phdr.p_filesz; | 2129 | offset += phdr.p_filesz; |
2127 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 2130 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
@@ -2149,12 +2152,12 @@ static int elf_core_dump(struct coredump_params *cprm) | |||
2149 | if (!dump_skip(cprm, dataoff - cprm->written)) | 2152 | if (!dump_skip(cprm, dataoff - cprm->written)) |
2150 | goto end_coredump; | 2153 | goto end_coredump; |
2151 | 2154 | ||
2152 | for (vma = first_vma(current, gate_vma); vma != NULL; | 2155 | for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; |
2153 | vma = next_vma(vma, gate_vma)) { | 2156 | vma = next_vma(vma, gate_vma)) { |
2154 | unsigned long addr; | 2157 | unsigned long addr; |
2155 | unsigned long end; | 2158 | unsigned long end; |
2156 | 2159 | ||
2157 | end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags); | 2160 | end = vma->vm_start + vma_filesz[i++]; |
2158 | 2161 | ||
2159 | for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { | 2162 | for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { |
2160 | struct page *page; | 2163 | struct page *page; |
@@ -2187,6 +2190,7 @@ end_coredump: | |||
2187 | cleanup: | 2190 | cleanup: |
2188 | free_note_info(&info); | 2191 | free_note_info(&info); |
2189 | kfree(shdr4extnum); | 2192 | kfree(shdr4extnum); |
2193 | kfree(vma_filesz); | ||
2190 | kfree(phdr4note); | 2194 | kfree(phdr4note); |
2191 | kfree(elf); | 2195 | kfree(elf); |
2192 | out: | 2196 | out: |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index fd8beb9657a2..70789e198dea 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -1,21 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * binfmt_misc.c | 2 | * binfmt_misc.c |
3 | * | 3 | * |
4 | * Copyright (C) 1997 Richard Günther | 4 | * Copyright (C) 1997 Richard Günther |
5 | * | 5 | * |
6 | * binfmt_misc detects binaries via a magic or filename extension and invokes | 6 | * binfmt_misc detects binaries via a magic or filename extension and invokes |
7 | * a specified wrapper. This should obsolete binfmt_java, binfmt_em86 and | 7 | * a specified wrapper. See Documentation/binfmt_misc.txt for more details. |
8 | * binfmt_mz. | ||
9 | * | ||
10 | * 1997-04-25 first version | ||
11 | * [...] | ||
12 | * 1997-05-19 cleanup | ||
13 | * 1997-06-26 hpa: pass the real filename rather than argv[0] | ||
14 | * 1997-06-30 minor cleanup | ||
15 | * 1997-08-09 removed extension stripping, locking cleanup | ||
16 | * 2001-02-28 AV: rewritten into something that resembles C. Original didn't. | ||
17 | */ | 8 | */ |
18 | 9 | ||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | |||
19 | #include <linux/module.h> | 12 | #include <linux/module.h> |
20 | #include <linux/init.h> | 13 | #include <linux/init.h> |
21 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
@@ -30,8 +23,13 @@ | |||
30 | #include <linux/mount.h> | 23 | #include <linux/mount.h> |
31 | #include <linux/syscalls.h> | 24 | #include <linux/syscalls.h> |
32 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
26 | #include <linux/uaccess.h> | ||
33 | 27 | ||
34 | #include <asm/uaccess.h> | 28 | #ifdef DEBUG |
29 | # define USE_DEBUG 1 | ||
30 | #else | ||
31 | # define USE_DEBUG 0 | ||
32 | #endif | ||
35 | 33 | ||
36 | enum { | 34 | enum { |
37 | VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */ | 35 | VERBOSE_STATUS = 1 /* make it zero to save 400 bytes kernel memory */ |
@@ -41,9 +39,9 @@ static LIST_HEAD(entries); | |||
41 | static int enabled = 1; | 39 | static int enabled = 1; |
42 | 40 | ||
43 | enum {Enabled, Magic}; | 41 | enum {Enabled, Magic}; |
44 | #define MISC_FMT_PRESERVE_ARGV0 (1<<31) | 42 | #define MISC_FMT_PRESERVE_ARGV0 (1 << 31) |
45 | #define MISC_FMT_OPEN_BINARY (1<<30) | 43 | #define MISC_FMT_OPEN_BINARY (1 << 30) |
46 | #define MISC_FMT_CREDENTIALS (1<<29) | 44 | #define MISC_FMT_CREDENTIALS (1 << 29) |
47 | 45 | ||
48 | typedef struct { | 46 | typedef struct { |
49 | struct list_head list; | 47 | struct list_head list; |
@@ -87,20 +85,24 @@ static Node *check_file(struct linux_binprm *bprm) | |||
87 | char *p = strrchr(bprm->interp, '.'); | 85 | char *p = strrchr(bprm->interp, '.'); |
88 | struct list_head *l; | 86 | struct list_head *l; |
89 | 87 | ||
88 | /* Walk all the registered handlers. */ | ||
90 | list_for_each(l, &entries) { | 89 | list_for_each(l, &entries) { |
91 | Node *e = list_entry(l, Node, list); | 90 | Node *e = list_entry(l, Node, list); |
92 | char *s; | 91 | char *s; |
93 | int j; | 92 | int j; |
94 | 93 | ||
94 | /* Make sure this one is currently enabled. */ | ||
95 | if (!test_bit(Enabled, &e->flags)) | 95 | if (!test_bit(Enabled, &e->flags)) |
96 | continue; | 96 | continue; |
97 | 97 | ||
98 | /* Do matching based on extension if applicable. */ | ||
98 | if (!test_bit(Magic, &e->flags)) { | 99 | if (!test_bit(Magic, &e->flags)) { |
99 | if (p && !strcmp(e->magic, p + 1)) | 100 | if (p && !strcmp(e->magic, p + 1)) |
100 | return e; | 101 | return e; |
101 | continue; | 102 | continue; |
102 | } | 103 | } |
103 | 104 | ||
105 | /* Do matching based on magic & mask. */ | ||
104 | s = bprm->buf + e->offset; | 106 | s = bprm->buf + e->offset; |
105 | if (e->mask) { | 107 | if (e->mask) { |
106 | for (j = 0; j < e->size; j++) | 108 | for (j = 0; j < e->size; j++) |
@@ -123,7 +125,7 @@ static Node *check_file(struct linux_binprm *bprm) | |||
123 | static int load_misc_binary(struct linux_binprm *bprm) | 125 | static int load_misc_binary(struct linux_binprm *bprm) |
124 | { | 126 | { |
125 | Node *fmt; | 127 | Node *fmt; |
126 | struct file * interp_file = NULL; | 128 | struct file *interp_file = NULL; |
127 | char iname[BINPRM_BUF_SIZE]; | 129 | char iname[BINPRM_BUF_SIZE]; |
128 | const char *iname_addr = iname; | 130 | const char *iname_addr = iname; |
129 | int retval; | 131 | int retval; |
@@ -131,7 +133,7 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
131 | 133 | ||
132 | retval = -ENOEXEC; | 134 | retval = -ENOEXEC; |
133 | if (!enabled) | 135 | if (!enabled) |
134 | goto _ret; | 136 | goto ret; |
135 | 137 | ||
136 | /* to keep locking time low, we copy the interpreter string */ | 138 | /* to keep locking time low, we copy the interpreter string */ |
137 | read_lock(&entries_lock); | 139 | read_lock(&entries_lock); |
@@ -140,25 +142,26 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
140 | strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE); | 142 | strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE); |
141 | read_unlock(&entries_lock); | 143 | read_unlock(&entries_lock); |
142 | if (!fmt) | 144 | if (!fmt) |
143 | goto _ret; | 145 | goto ret; |
144 | 146 | ||
145 | if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { | 147 | if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) { |
146 | retval = remove_arg_zero(bprm); | 148 | retval = remove_arg_zero(bprm); |
147 | if (retval) | 149 | if (retval) |
148 | goto _ret; | 150 | goto ret; |
149 | } | 151 | } |
150 | 152 | ||
151 | if (fmt->flags & MISC_FMT_OPEN_BINARY) { | 153 | if (fmt->flags & MISC_FMT_OPEN_BINARY) { |
152 | 154 | ||
153 | /* if the binary should be opened on behalf of the | 155 | /* if the binary should be opened on behalf of the |
154 | * interpreter than keep it open and assign descriptor | 156 | * interpreter than keep it open and assign descriptor |
155 | * to it */ | 157 | * to it |
156 | fd_binary = get_unused_fd(); | 158 | */ |
157 | if (fd_binary < 0) { | 159 | fd_binary = get_unused_fd_flags(0); |
158 | retval = fd_binary; | 160 | if (fd_binary < 0) { |
159 | goto _ret; | 161 | retval = fd_binary; |
160 | } | 162 | goto ret; |
161 | fd_install(fd_binary, bprm->file); | 163 | } |
164 | fd_install(fd_binary, bprm->file); | ||
162 | 165 | ||
163 | /* if the binary is not readable than enforce mm->dumpable=0 | 166 | /* if the binary is not readable than enforce mm->dumpable=0 |
164 | regardless of the interpreter's permissions */ | 167 | regardless of the interpreter's permissions */ |
@@ -171,32 +174,32 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
171 | bprm->interp_flags |= BINPRM_FLAGS_EXECFD; | 174 | bprm->interp_flags |= BINPRM_FLAGS_EXECFD; |
172 | bprm->interp_data = fd_binary; | 175 | bprm->interp_data = fd_binary; |
173 | 176 | ||
174 | } else { | 177 | } else { |
175 | allow_write_access(bprm->file); | 178 | allow_write_access(bprm->file); |
176 | fput(bprm->file); | 179 | fput(bprm->file); |
177 | bprm->file = NULL; | 180 | bprm->file = NULL; |
178 | } | 181 | } |
179 | /* make argv[1] be the path to the binary */ | 182 | /* make argv[1] be the path to the binary */ |
180 | retval = copy_strings_kernel (1, &bprm->interp, bprm); | 183 | retval = copy_strings_kernel(1, &bprm->interp, bprm); |
181 | if (retval < 0) | 184 | if (retval < 0) |
182 | goto _error; | 185 | goto error; |
183 | bprm->argc++; | 186 | bprm->argc++; |
184 | 187 | ||
185 | /* add the interp as argv[0] */ | 188 | /* add the interp as argv[0] */ |
186 | retval = copy_strings_kernel (1, &iname_addr, bprm); | 189 | retval = copy_strings_kernel(1, &iname_addr, bprm); |
187 | if (retval < 0) | 190 | if (retval < 0) |
188 | goto _error; | 191 | goto error; |
189 | bprm->argc ++; | 192 | bprm->argc++; |
190 | 193 | ||
191 | /* Update interp in case binfmt_script needs it. */ | 194 | /* Update interp in case binfmt_script needs it. */ |
192 | retval = bprm_change_interp(iname, bprm); | 195 | retval = bprm_change_interp(iname, bprm); |
193 | if (retval < 0) | 196 | if (retval < 0) |
194 | goto _error; | 197 | goto error; |
195 | 198 | ||
196 | interp_file = open_exec (iname); | 199 | interp_file = open_exec(iname); |
197 | retval = PTR_ERR (interp_file); | 200 | retval = PTR_ERR(interp_file); |
198 | if (IS_ERR (interp_file)) | 201 | if (IS_ERR(interp_file)) |
199 | goto _error; | 202 | goto error; |
200 | 203 | ||
201 | bprm->file = interp_file; | 204 | bprm->file = interp_file; |
202 | if (fmt->flags & MISC_FMT_CREDENTIALS) { | 205 | if (fmt->flags & MISC_FMT_CREDENTIALS) { |
@@ -207,23 +210,23 @@ static int load_misc_binary(struct linux_binprm *bprm) | |||
207 | memset(bprm->buf, 0, BINPRM_BUF_SIZE); | 210 | memset(bprm->buf, 0, BINPRM_BUF_SIZE); |
208 | retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE); | 211 | retval = kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE); |
209 | } else | 212 | } else |
210 | retval = prepare_binprm (bprm); | 213 | retval = prepare_binprm(bprm); |
211 | 214 | ||
212 | if (retval < 0) | 215 | if (retval < 0) |
213 | goto _error; | 216 | goto error; |
214 | 217 | ||
215 | retval = search_binary_handler(bprm); | 218 | retval = search_binary_handler(bprm); |
216 | if (retval < 0) | 219 | if (retval < 0) |
217 | goto _error; | 220 | goto error; |
218 | 221 | ||
219 | _ret: | 222 | ret: |
220 | return retval; | 223 | return retval; |
221 | _error: | 224 | error: |
222 | if (fd_binary > 0) | 225 | if (fd_binary > 0) |
223 | sys_close(fd_binary); | 226 | sys_close(fd_binary); |
224 | bprm->interp_flags = 0; | 227 | bprm->interp_flags = 0; |
225 | bprm->interp_data = 0; | 228 | bprm->interp_data = 0; |
226 | goto _ret; | 229 | goto ret; |
227 | } | 230 | } |
228 | 231 | ||
229 | /* Command parsers */ | 232 | /* Command parsers */ |
@@ -250,36 +253,40 @@ static char *scanarg(char *s, char del) | |||
250 | return s; | 253 | return s; |
251 | } | 254 | } |
252 | 255 | ||
253 | static char * check_special_flags (char * sfs, Node * e) | 256 | static char *check_special_flags(char *sfs, Node *e) |
254 | { | 257 | { |
255 | char * p = sfs; | 258 | char *p = sfs; |
256 | int cont = 1; | 259 | int cont = 1; |
257 | 260 | ||
258 | /* special flags */ | 261 | /* special flags */ |
259 | while (cont) { | 262 | while (cont) { |
260 | switch (*p) { | 263 | switch (*p) { |
261 | case 'P': | 264 | case 'P': |
262 | p++; | 265 | pr_debug("register: flag: P (preserve argv0)\n"); |
263 | e->flags |= MISC_FMT_PRESERVE_ARGV0; | 266 | p++; |
264 | break; | 267 | e->flags |= MISC_FMT_PRESERVE_ARGV0; |
265 | case 'O': | 268 | break; |
266 | p++; | 269 | case 'O': |
267 | e->flags |= MISC_FMT_OPEN_BINARY; | 270 | pr_debug("register: flag: O (open binary)\n"); |
268 | break; | 271 | p++; |
269 | case 'C': | 272 | e->flags |= MISC_FMT_OPEN_BINARY; |
270 | p++; | 273 | break; |
271 | /* this flags also implies the | 274 | case 'C': |
272 | open-binary flag */ | 275 | pr_debug("register: flag: C (preserve creds)\n"); |
273 | e->flags |= (MISC_FMT_CREDENTIALS | | 276 | p++; |
274 | MISC_FMT_OPEN_BINARY); | 277 | /* this flags also implies the |
275 | break; | 278 | open-binary flag */ |
276 | default: | 279 | e->flags |= (MISC_FMT_CREDENTIALS | |
277 | cont = 0; | 280 | MISC_FMT_OPEN_BINARY); |
281 | break; | ||
282 | default: | ||
283 | cont = 0; | ||
278 | } | 284 | } |
279 | } | 285 | } |
280 | 286 | ||
281 | return p; | 287 | return p; |
282 | } | 288 | } |
289 | |||
283 | /* | 290 | /* |
284 | * This registers a new binary format, it recognises the syntax | 291 | * This registers a new binary format, it recognises the syntax |
285 | * ':name:type:offset:magic:mask:interpreter:flags' | 292 | * ':name:type:offset:magic:mask:interpreter:flags' |
@@ -292,6 +299,8 @@ static Node *create_entry(const char __user *buffer, size_t count) | |||
292 | char *buf, *p; | 299 | char *buf, *p; |
293 | char del; | 300 | char del; |
294 | 301 | ||
302 | pr_debug("register: received %zu bytes\n", count); | ||
303 | |||
295 | /* some sanity checks */ | 304 | /* some sanity checks */ |
296 | err = -EINVAL; | 305 | err = -EINVAL; |
297 | if ((count < 11) || (count > MAX_REGISTER_LENGTH)) | 306 | if ((count < 11) || (count > MAX_REGISTER_LENGTH)) |
@@ -299,7 +308,7 @@ static Node *create_entry(const char __user *buffer, size_t count) | |||
299 | 308 | ||
300 | err = -ENOMEM; | 309 | err = -ENOMEM; |
301 | memsize = sizeof(Node) + count + 8; | 310 | memsize = sizeof(Node) + count + 8; |
302 | e = kmalloc(memsize, GFP_USER); | 311 | e = kmalloc(memsize, GFP_KERNEL); |
303 | if (!e) | 312 | if (!e) |
304 | goto out; | 313 | goto out; |
305 | 314 | ||
@@ -307,98 +316,175 @@ static Node *create_entry(const char __user *buffer, size_t count) | |||
307 | 316 | ||
308 | memset(e, 0, sizeof(Node)); | 317 | memset(e, 0, sizeof(Node)); |
309 | if (copy_from_user(buf, buffer, count)) | 318 | if (copy_from_user(buf, buffer, count)) |
310 | goto Efault; | 319 | goto efault; |
311 | 320 | ||
312 | del = *p++; /* delimeter */ | 321 | del = *p++; /* delimeter */ |
313 | 322 | ||
314 | memset(buf+count, del, 8); | 323 | pr_debug("register: delim: %#x {%c}\n", del, del); |
324 | |||
325 | /* Pad the buffer with the delim to simplify parsing below. */ | ||
326 | memset(buf + count, del, 8); | ||
315 | 327 | ||
328 | /* Parse the 'name' field. */ | ||
316 | e->name = p; | 329 | e->name = p; |
317 | p = strchr(p, del); | 330 | p = strchr(p, del); |
318 | if (!p) | 331 | if (!p) |
319 | goto Einval; | 332 | goto einval; |
320 | *p++ = '\0'; | 333 | *p++ = '\0'; |
321 | if (!e->name[0] || | 334 | if (!e->name[0] || |
322 | !strcmp(e->name, ".") || | 335 | !strcmp(e->name, ".") || |
323 | !strcmp(e->name, "..") || | 336 | !strcmp(e->name, "..") || |
324 | strchr(e->name, '/')) | 337 | strchr(e->name, '/')) |
325 | goto Einval; | 338 | goto einval; |
339 | |||
340 | pr_debug("register: name: {%s}\n", e->name); | ||
341 | |||
342 | /* Parse the 'type' field. */ | ||
326 | switch (*p++) { | 343 | switch (*p++) { |
327 | case 'E': e->flags = 1<<Enabled; break; | 344 | case 'E': |
328 | case 'M': e->flags = (1<<Enabled) | (1<<Magic); break; | 345 | pr_debug("register: type: E (extension)\n"); |
329 | default: goto Einval; | 346 | e->flags = 1 << Enabled; |
347 | break; | ||
348 | case 'M': | ||
349 | pr_debug("register: type: M (magic)\n"); | ||
350 | e->flags = (1 << Enabled) | (1 << Magic); | ||
351 | break; | ||
352 | default: | ||
353 | goto einval; | ||
330 | } | 354 | } |
331 | if (*p++ != del) | 355 | if (*p++ != del) |
332 | goto Einval; | 356 | goto einval; |
357 | |||
333 | if (test_bit(Magic, &e->flags)) { | 358 | if (test_bit(Magic, &e->flags)) { |
334 | char *s = strchr(p, del); | 359 | /* Handle the 'M' (magic) format. */ |
360 | char *s; | ||
361 | |||
362 | /* Parse the 'offset' field. */ | ||
363 | s = strchr(p, del); | ||
335 | if (!s) | 364 | if (!s) |
336 | goto Einval; | 365 | goto einval; |
337 | *s++ = '\0'; | 366 | *s++ = '\0'; |
338 | e->offset = simple_strtoul(p, &p, 10); | 367 | e->offset = simple_strtoul(p, &p, 10); |
339 | if (*p++) | 368 | if (*p++) |
340 | goto Einval; | 369 | goto einval; |
370 | pr_debug("register: offset: %#x\n", e->offset); | ||
371 | |||
372 | /* Parse the 'magic' field. */ | ||
341 | e->magic = p; | 373 | e->magic = p; |
342 | p = scanarg(p, del); | 374 | p = scanarg(p, del); |
343 | if (!p) | 375 | if (!p) |
344 | goto Einval; | 376 | goto einval; |
345 | p[-1] = '\0'; | 377 | p[-1] = '\0'; |
346 | if (!e->magic[0]) | 378 | if (p == e->magic) |
347 | goto Einval; | 379 | goto einval; |
380 | if (USE_DEBUG) | ||
381 | print_hex_dump_bytes( | ||
382 | KBUILD_MODNAME ": register: magic[raw]: ", | ||
383 | DUMP_PREFIX_NONE, e->magic, p - e->magic); | ||
384 | |||
385 | /* Parse the 'mask' field. */ | ||
348 | e->mask = p; | 386 | e->mask = p; |
349 | p = scanarg(p, del); | 387 | p = scanarg(p, del); |
350 | if (!p) | 388 | if (!p) |
351 | goto Einval; | 389 | goto einval; |
352 | p[-1] = '\0'; | 390 | p[-1] = '\0'; |
353 | if (!e->mask[0]) | 391 | if (p == e->mask) { |
354 | e->mask = NULL; | 392 | e->mask = NULL; |
393 | pr_debug("register: mask[raw]: none\n"); | ||
394 | } else if (USE_DEBUG) | ||
395 | print_hex_dump_bytes( | ||
396 | KBUILD_MODNAME ": register: mask[raw]: ", | ||
397 | DUMP_PREFIX_NONE, e->mask, p - e->mask); | ||
398 | |||
399 | /* | ||
400 | * Decode the magic & mask fields. | ||
401 | * Note: while we might have accepted embedded NUL bytes from | ||
402 | * above, the unescape helpers here will stop at the first one | ||
403 | * it encounters. | ||
404 | */ | ||
355 | e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX); | 405 | e->size = string_unescape_inplace(e->magic, UNESCAPE_HEX); |
356 | if (e->mask && | 406 | if (e->mask && |
357 | string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size) | 407 | string_unescape_inplace(e->mask, UNESCAPE_HEX) != e->size) |
358 | goto Einval; | 408 | goto einval; |
359 | if (e->size + e->offset > BINPRM_BUF_SIZE) | 409 | if (e->size + e->offset > BINPRM_BUF_SIZE) |
360 | goto Einval; | 410 | goto einval; |
411 | pr_debug("register: magic/mask length: %i\n", e->size); | ||
412 | if (USE_DEBUG) { | ||
413 | print_hex_dump_bytes( | ||
414 | KBUILD_MODNAME ": register: magic[decoded]: ", | ||
415 | DUMP_PREFIX_NONE, e->magic, e->size); | ||
416 | |||
417 | if (e->mask) { | ||
418 | int i; | ||
419 | char *masked = kmalloc(e->size, GFP_KERNEL); | ||
420 | |||
421 | print_hex_dump_bytes( | ||
422 | KBUILD_MODNAME ": register: mask[decoded]: ", | ||
423 | DUMP_PREFIX_NONE, e->mask, e->size); | ||
424 | |||
425 | if (masked) { | ||
426 | for (i = 0; i < e->size; ++i) | ||
427 | masked[i] = e->magic[i] & e->mask[i]; | ||
428 | print_hex_dump_bytes( | ||
429 | KBUILD_MODNAME ": register: magic[masked]: ", | ||
430 | DUMP_PREFIX_NONE, masked, e->size); | ||
431 | |||
432 | kfree(masked); | ||
433 | } | ||
434 | } | ||
435 | } | ||
361 | } else { | 436 | } else { |
437 | /* Handle the 'E' (extension) format. */ | ||
438 | |||
439 | /* Skip the 'offset' field. */ | ||
362 | p = strchr(p, del); | 440 | p = strchr(p, del); |
363 | if (!p) | 441 | if (!p) |
364 | goto Einval; | 442 | goto einval; |
365 | *p++ = '\0'; | 443 | *p++ = '\0'; |
444 | |||
445 | /* Parse the 'magic' field. */ | ||
366 | e->magic = p; | 446 | e->magic = p; |
367 | p = strchr(p, del); | 447 | p = strchr(p, del); |
368 | if (!p) | 448 | if (!p) |
369 | goto Einval; | 449 | goto einval; |
370 | *p++ = '\0'; | 450 | *p++ = '\0'; |
371 | if (!e->magic[0] || strchr(e->magic, '/')) | 451 | if (!e->magic[0] || strchr(e->magic, '/')) |
372 | goto Einval; | 452 | goto einval; |
453 | pr_debug("register: extension: {%s}\n", e->magic); | ||
454 | |||
455 | /* Skip the 'mask' field. */ | ||
373 | p = strchr(p, del); | 456 | p = strchr(p, del); |
374 | if (!p) | 457 | if (!p) |
375 | goto Einval; | 458 | goto einval; |
376 | *p++ = '\0'; | 459 | *p++ = '\0'; |
377 | } | 460 | } |
461 | |||
462 | /* Parse the 'interpreter' field. */ | ||
378 | e->interpreter = p; | 463 | e->interpreter = p; |
379 | p = strchr(p, del); | 464 | p = strchr(p, del); |
380 | if (!p) | 465 | if (!p) |
381 | goto Einval; | 466 | goto einval; |
382 | *p++ = '\0'; | 467 | *p++ = '\0'; |
383 | if (!e->interpreter[0]) | 468 | if (!e->interpreter[0]) |
384 | goto Einval; | 469 | goto einval; |
385 | 470 | pr_debug("register: interpreter: {%s}\n", e->interpreter); | |
386 | |||
387 | p = check_special_flags (p, e); | ||
388 | 471 | ||
472 | /* Parse the 'flags' field. */ | ||
473 | p = check_special_flags(p, e); | ||
389 | if (*p == '\n') | 474 | if (*p == '\n') |
390 | p++; | 475 | p++; |
391 | if (p != buf + count) | 476 | if (p != buf + count) |
392 | goto Einval; | 477 | goto einval; |
478 | |||
393 | return e; | 479 | return e; |
394 | 480 | ||
395 | out: | 481 | out: |
396 | return ERR_PTR(err); | 482 | return ERR_PTR(err); |
397 | 483 | ||
398 | Efault: | 484 | efault: |
399 | kfree(e); | 485 | kfree(e); |
400 | return ERR_PTR(-EFAULT); | 486 | return ERR_PTR(-EFAULT); |
401 | Einval: | 487 | einval: |
402 | kfree(e); | 488 | kfree(e); |
403 | return ERR_PTR(-EINVAL); | 489 | return ERR_PTR(-EINVAL); |
404 | } | 490 | } |
@@ -417,7 +503,7 @@ static int parse_command(const char __user *buffer, size_t count) | |||
417 | return -EFAULT; | 503 | return -EFAULT; |
418 | if (!count) | 504 | if (!count) |
419 | return 0; | 505 | return 0; |
420 | if (s[count-1] == '\n') | 506 | if (s[count - 1] == '\n') |
421 | count--; | 507 | count--; |
422 | if (count == 1 && s[0] == '0') | 508 | if (count == 1 && s[0] == '0') |
423 | return 1; | 509 | return 1; |
@@ -434,7 +520,7 @@ static void entry_status(Node *e, char *page) | |||
434 | { | 520 | { |
435 | char *dp; | 521 | char *dp; |
436 | char *status = "disabled"; | 522 | char *status = "disabled"; |
437 | const char * flags = "flags: "; | 523 | const char *flags = "flags: "; |
438 | 524 | ||
439 | if (test_bit(Enabled, &e->flags)) | 525 | if (test_bit(Enabled, &e->flags)) |
440 | status = "enabled"; | 526 | status = "enabled"; |
@@ -448,19 +534,15 @@ static void entry_status(Node *e, char *page) | |||
448 | dp = page + strlen(page); | 534 | dp = page + strlen(page); |
449 | 535 | ||
450 | /* print the special flags */ | 536 | /* print the special flags */ |
451 | sprintf (dp, "%s", flags); | 537 | sprintf(dp, "%s", flags); |
452 | dp += strlen (flags); | 538 | dp += strlen(flags); |
453 | if (e->flags & MISC_FMT_PRESERVE_ARGV0) { | 539 | if (e->flags & MISC_FMT_PRESERVE_ARGV0) |
454 | *dp ++ = 'P'; | 540 | *dp++ = 'P'; |
455 | } | 541 | if (e->flags & MISC_FMT_OPEN_BINARY) |
456 | if (e->flags & MISC_FMT_OPEN_BINARY) { | 542 | *dp++ = 'O'; |
457 | *dp ++ = 'O'; | 543 | if (e->flags & MISC_FMT_CREDENTIALS) |
458 | } | 544 | *dp++ = 'C'; |
459 | if (e->flags & MISC_FMT_CREDENTIALS) { | 545 | *dp++ = '\n'; |
460 | *dp ++ = 'C'; | ||
461 | } | ||
462 | *dp ++ = '\n'; | ||
463 | |||
464 | 546 | ||
465 | if (!test_bit(Magic, &e->flags)) { | 547 | if (!test_bit(Magic, &e->flags)) { |
466 | sprintf(dp, "extension .%s\n", e->magic); | 548 | sprintf(dp, "extension .%s\n", e->magic); |
@@ -488,7 +570,7 @@ static void entry_status(Node *e, char *page) | |||
488 | 570 | ||
489 | static struct inode *bm_get_inode(struct super_block *sb, int mode) | 571 | static struct inode *bm_get_inode(struct super_block *sb, int mode) |
490 | { | 572 | { |
491 | struct inode * inode = new_inode(sb); | 573 | struct inode *inode = new_inode(sb); |
492 | 574 | ||
493 | if (inode) { | 575 | if (inode) { |
494 | inode->i_ino = get_next_ino(); | 576 | inode->i_ino = get_next_ino(); |
@@ -528,13 +610,14 @@ static void kill_node(Node *e) | |||
528 | /* /<entry> */ | 610 | /* /<entry> */ |
529 | 611 | ||
530 | static ssize_t | 612 | static ssize_t |
531 | bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) | 613 | bm_entry_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) |
532 | { | 614 | { |
533 | Node *e = file_inode(file)->i_private; | 615 | Node *e = file_inode(file)->i_private; |
534 | ssize_t res; | 616 | ssize_t res; |
535 | char *page; | 617 | char *page; |
536 | 618 | ||
537 | if (!(page = (char*) __get_free_page(GFP_KERNEL))) | 619 | page = (char *) __get_free_page(GFP_KERNEL); |
620 | if (!page) | ||
538 | return -ENOMEM; | 621 | return -ENOMEM; |
539 | 622 | ||
540 | entry_status(e, page); | 623 | entry_status(e, page); |
@@ -553,20 +636,28 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, | |||
553 | int res = parse_command(buffer, count); | 636 | int res = parse_command(buffer, count); |
554 | 637 | ||
555 | switch (res) { | 638 | switch (res) { |
556 | case 1: clear_bit(Enabled, &e->flags); | 639 | case 1: |
557 | break; | 640 | /* Disable this handler. */ |
558 | case 2: set_bit(Enabled, &e->flags); | 641 | clear_bit(Enabled, &e->flags); |
559 | break; | 642 | break; |
560 | case 3: root = dget(file->f_path.dentry->d_sb->s_root); | 643 | case 2: |
561 | mutex_lock(&root->d_inode->i_mutex); | 644 | /* Enable this handler. */ |
562 | 645 | set_bit(Enabled, &e->flags); | |
563 | kill_node(e); | 646 | break; |
564 | 647 | case 3: | |
565 | mutex_unlock(&root->d_inode->i_mutex); | 648 | /* Delete this handler. */ |
566 | dput(root); | 649 | root = dget(file->f_path.dentry->d_sb->s_root); |
567 | break; | 650 | mutex_lock(&root->d_inode->i_mutex); |
568 | default: return res; | 651 | |
652 | kill_node(e); | ||
653 | |||
654 | mutex_unlock(&root->d_inode->i_mutex); | ||
655 | dput(root); | ||
656 | break; | ||
657 | default: | ||
658 | return res; | ||
569 | } | 659 | } |
660 | |||
570 | return count; | 661 | return count; |
571 | } | 662 | } |
572 | 663 | ||
@@ -654,26 +745,36 @@ bm_status_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
654 | return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s)); | 745 | return simple_read_from_buffer(buf, nbytes, ppos, s, strlen(s)); |
655 | } | 746 | } |
656 | 747 | ||
657 | static ssize_t bm_status_write(struct file * file, const char __user * buffer, | 748 | static ssize_t bm_status_write(struct file *file, const char __user *buffer, |
658 | size_t count, loff_t *ppos) | 749 | size_t count, loff_t *ppos) |
659 | { | 750 | { |
660 | int res = parse_command(buffer, count); | 751 | int res = parse_command(buffer, count); |
661 | struct dentry *root; | 752 | struct dentry *root; |
662 | 753 | ||
663 | switch (res) { | 754 | switch (res) { |
664 | case 1: enabled = 0; break; | 755 | case 1: |
665 | case 2: enabled = 1; break; | 756 | /* Disable all handlers. */ |
666 | case 3: root = dget(file->f_path.dentry->d_sb->s_root); | 757 | enabled = 0; |
667 | mutex_lock(&root->d_inode->i_mutex); | 758 | break; |
668 | 759 | case 2: | |
669 | while (!list_empty(&entries)) | 760 | /* Enable all handlers. */ |
670 | kill_node(list_entry(entries.next, Node, list)); | 761 | enabled = 1; |
671 | 762 | break; | |
672 | mutex_unlock(&root->d_inode->i_mutex); | 763 | case 3: |
673 | dput(root); | 764 | /* Delete all handlers. */ |
674 | break; | 765 | root = dget(file->f_path.dentry->d_sb->s_root); |
675 | default: return res; | 766 | mutex_lock(&root->d_inode->i_mutex); |
767 | |||
768 | while (!list_empty(&entries)) | ||
769 | kill_node(list_entry(entries.next, Node, list)); | ||
770 | |||
771 | mutex_unlock(&root->d_inode->i_mutex); | ||
772 | dput(root); | ||
773 | break; | ||
774 | default: | ||
775 | return res; | ||
676 | } | 776 | } |
777 | |||
677 | return count; | 778 | return count; |
678 | } | 779 | } |
679 | 780 | ||
@@ -690,14 +791,16 @@ static const struct super_operations s_ops = { | |||
690 | .evict_inode = bm_evict_inode, | 791 | .evict_inode = bm_evict_inode, |
691 | }; | 792 | }; |
692 | 793 | ||
693 | static int bm_fill_super(struct super_block * sb, void * data, int silent) | 794 | static int bm_fill_super(struct super_block *sb, void *data, int silent) |
694 | { | 795 | { |
796 | int err; | ||
695 | static struct tree_descr bm_files[] = { | 797 | static struct tree_descr bm_files[] = { |
696 | [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO}, | 798 | [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO}, |
697 | [3] = {"register", &bm_register_operations, S_IWUSR}, | 799 | [3] = {"register", &bm_register_operations, S_IWUSR}, |
698 | /* last one */ {""} | 800 | /* last one */ {""} |
699 | }; | 801 | }; |
700 | int err = simple_fill_super(sb, BINFMTFS_MAGIC, bm_files); | 802 | |
803 | err = simple_fill_super(sb, BINFMTFS_MAGIC, bm_files); | ||
701 | if (!err) | 804 | if (!err) |
702 | sb->s_op = &s_ops; | 805 | sb->s_op = &s_ops; |
703 | return err; | 806 | return err; |
diff --git a/fs/char_dev.c b/fs/char_dev.c index f77f7702fabe..67b2007f10fe 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -117,7 +117,6 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, | |||
117 | goto out; | 117 | goto out; |
118 | } | 118 | } |
119 | major = i; | 119 | major = i; |
120 | ret = major; | ||
121 | } | 120 | } |
122 | 121 | ||
123 | cd->major = major; | 122 | cd->major = major; |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 6d00c419cbae..1ea780bc6376 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -38,7 +38,7 @@ static const struct cifs_sid sid_everyone = { | |||
38 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; | 38 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; |
39 | /* security id for Authenticated Users system group */ | 39 | /* security id for Authenticated Users system group */ |
40 | static const struct cifs_sid sid_authusers = { | 40 | static const struct cifs_sid sid_authusers = { |
41 | 1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} }; | 41 | 1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} }; |
42 | /* group users */ | 42 | /* group users */ |
43 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | 43 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; |
44 | 44 | ||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 61d00a6e398f..fa13d5e79f64 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -2477,14 +2477,14 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, | |||
2477 | } | 2477 | } |
2478 | parm_data = (struct cifs_posix_lock *) | 2478 | parm_data = (struct cifs_posix_lock *) |
2479 | ((char *)&pSMBr->hdr.Protocol + data_offset); | 2479 | ((char *)&pSMBr->hdr.Protocol + data_offset); |
2480 | if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK)) | 2480 | if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK)) |
2481 | pLockData->fl_type = F_UNLCK; | 2481 | pLockData->fl_type = F_UNLCK; |
2482 | else { | 2482 | else { |
2483 | if (parm_data->lock_type == | 2483 | if (parm_data->lock_type == |
2484 | __constant_cpu_to_le16(CIFS_RDLCK)) | 2484 | cpu_to_le16(CIFS_RDLCK)) |
2485 | pLockData->fl_type = F_RDLCK; | 2485 | pLockData->fl_type = F_RDLCK; |
2486 | else if (parm_data->lock_type == | 2486 | else if (parm_data->lock_type == |
2487 | __constant_cpu_to_le16(CIFS_WRLCK)) | 2487 | cpu_to_le16(CIFS_WRLCK)) |
2488 | pLockData->fl_type = F_WRLCK; | 2488 | pLockData->fl_type = F_WRLCK; |
2489 | 2489 | ||
2490 | pLockData->fl_start = le64_to_cpu(parm_data->start); | 2490 | pLockData->fl_start = le64_to_cpu(parm_data->start); |
@@ -3276,25 +3276,25 @@ CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon, | |||
3276 | pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); | 3276 | pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); |
3277 | 3277 | ||
3278 | pSMB->TotalParameterCount = 0; | 3278 | pSMB->TotalParameterCount = 0; |
3279 | pSMB->TotalDataCount = __constant_cpu_to_le32(2); | 3279 | pSMB->TotalDataCount = cpu_to_le32(2); |
3280 | pSMB->MaxParameterCount = 0; | 3280 | pSMB->MaxParameterCount = 0; |
3281 | pSMB->MaxDataCount = 0; | 3281 | pSMB->MaxDataCount = 0; |
3282 | pSMB->MaxSetupCount = 4; | 3282 | pSMB->MaxSetupCount = 4; |
3283 | pSMB->Reserved = 0; | 3283 | pSMB->Reserved = 0; |
3284 | pSMB->ParameterOffset = 0; | 3284 | pSMB->ParameterOffset = 0; |
3285 | pSMB->DataCount = __constant_cpu_to_le32(2); | 3285 | pSMB->DataCount = cpu_to_le32(2); |
3286 | pSMB->DataOffset = | 3286 | pSMB->DataOffset = |
3287 | cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req, | 3287 | cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req, |
3288 | compression_state) - 4); /* 84 */ | 3288 | compression_state) - 4); /* 84 */ |
3289 | pSMB->SetupCount = 4; | 3289 | pSMB->SetupCount = 4; |
3290 | pSMB->SubCommand = __constant_cpu_to_le16(NT_TRANSACT_IOCTL); | 3290 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL); |
3291 | pSMB->ParameterCount = 0; | 3291 | pSMB->ParameterCount = 0; |
3292 | pSMB->FunctionCode = __constant_cpu_to_le32(FSCTL_SET_COMPRESSION); | 3292 | pSMB->FunctionCode = cpu_to_le32(FSCTL_SET_COMPRESSION); |
3293 | pSMB->IsFsctl = 1; /* FSCTL */ | 3293 | pSMB->IsFsctl = 1; /* FSCTL */ |
3294 | pSMB->IsRootFlag = 0; | 3294 | pSMB->IsRootFlag = 0; |
3295 | pSMB->Fid = fid; /* file handle always le */ | 3295 | pSMB->Fid = fid; /* file handle always le */ |
3296 | /* 3 byte pad, followed by 2 byte compress state */ | 3296 | /* 3 byte pad, followed by 2 byte compress state */ |
3297 | pSMB->ByteCount = __constant_cpu_to_le16(5); | 3297 | pSMB->ByteCount = cpu_to_le16(5); |
3298 | inc_rfc1001_len(pSMB, 5); | 3298 | inc_rfc1001_len(pSMB, 5); |
3299 | 3299 | ||
3300 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3300 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3430,10 +3430,10 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL, | |||
3430 | cifs_acl->version = cpu_to_le16(1); | 3430 | cifs_acl->version = cpu_to_le16(1); |
3431 | if (acl_type == ACL_TYPE_ACCESS) { | 3431 | if (acl_type == ACL_TYPE_ACCESS) { |
3432 | cifs_acl->access_entry_count = cpu_to_le16(count); | 3432 | cifs_acl->access_entry_count = cpu_to_le16(count); |
3433 | cifs_acl->default_entry_count = __constant_cpu_to_le16(0xFFFF); | 3433 | cifs_acl->default_entry_count = cpu_to_le16(0xFFFF); |
3434 | } else if (acl_type == ACL_TYPE_DEFAULT) { | 3434 | } else if (acl_type == ACL_TYPE_DEFAULT) { |
3435 | cifs_acl->default_entry_count = cpu_to_le16(count); | 3435 | cifs_acl->default_entry_count = cpu_to_le16(count); |
3436 | cifs_acl->access_entry_count = __constant_cpu_to_le16(0xFFFF); | 3436 | cifs_acl->access_entry_count = cpu_to_le16(0xFFFF); |
3437 | } else { | 3437 | } else { |
3438 | cifs_dbg(FYI, "unknown ACL type %d\n", acl_type); | 3438 | cifs_dbg(FYI, "unknown ACL type %d\n", acl_type); |
3439 | return 0; | 3439 | return 0; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index d535e168a9d3..96b7e9b7706d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1066,7 +1066,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
1066 | 1066 | ||
1067 | max_num = (max_buf - sizeof(struct smb_hdr)) / | 1067 | max_num = (max_buf - sizeof(struct smb_hdr)) / |
1068 | sizeof(LOCKING_ANDX_RANGE); | 1068 | sizeof(LOCKING_ANDX_RANGE); |
1069 | buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); | 1069 | buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); |
1070 | if (!buf) { | 1070 | if (!buf) { |
1071 | free_xid(xid); | 1071 | free_xid(xid); |
1072 | return -ENOMEM; | 1072 | return -ENOMEM; |
@@ -1401,7 +1401,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
1401 | 1401 | ||
1402 | max_num = (max_buf - sizeof(struct smb_hdr)) / | 1402 | max_num = (max_buf - sizeof(struct smb_hdr)) / |
1403 | sizeof(LOCKING_ANDX_RANGE); | 1403 | sizeof(LOCKING_ANDX_RANGE); |
1404 | buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); | 1404 | buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); |
1405 | if (!buf) | 1405 | if (!buf) |
1406 | return -ENOMEM; | 1406 | return -ENOMEM; |
1407 | 1407 | ||
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 446cb7fb3f58..bce6fdcd5d48 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -46,7 +46,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) | |||
46 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, | 46 | CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, |
47 | USHRT_MAX)); | 47 | USHRT_MAX)); |
48 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 48 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
49 | pSMB->req.VcNumber = __constant_cpu_to_le16(1); | 49 | pSMB->req.VcNumber = cpu_to_le16(1); |
50 | 50 | ||
51 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ | 51 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ |
52 | 52 | ||
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index 45992944e238..7198eac5dddd 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c | |||
@@ -111,7 +111,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, | |||
111 | return -EINVAL; | 111 | return -EINVAL; |
112 | 112 | ||
113 | max_num = max_buf / sizeof(struct smb2_lock_element); | 113 | max_num = max_buf / sizeof(struct smb2_lock_element); |
114 | buf = kzalloc(max_num * sizeof(struct smb2_lock_element), GFP_KERNEL); | 114 | buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL); |
115 | if (!buf) | 115 | if (!buf) |
116 | return -ENOMEM; | 116 | return -ENOMEM; |
117 | 117 | ||
@@ -247,7 +247,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | max_num = max_buf / sizeof(struct smb2_lock_element); | 249 | max_num = max_buf / sizeof(struct smb2_lock_element); |
250 | buf = kzalloc(max_num * sizeof(struct smb2_lock_element), GFP_KERNEL); | 250 | buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL); |
251 | if (!buf) { | 251 | if (!buf) { |
252 | free_xid(xid); | 252 | free_xid(xid); |
253 | return -ENOMEM; | 253 | return -ENOMEM; |
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 1a08a34838fc..f1cefc9763ed 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c | |||
@@ -67,27 +67,27 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) | |||
67 | * indexed by command in host byte order | 67 | * indexed by command in host byte order |
68 | */ | 68 | */ |
69 | static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { | 69 | static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { |
70 | /* SMB2_NEGOTIATE */ __constant_cpu_to_le16(65), | 70 | /* SMB2_NEGOTIATE */ cpu_to_le16(65), |
71 | /* SMB2_SESSION_SETUP */ __constant_cpu_to_le16(9), | 71 | /* SMB2_SESSION_SETUP */ cpu_to_le16(9), |
72 | /* SMB2_LOGOFF */ __constant_cpu_to_le16(4), | 72 | /* SMB2_LOGOFF */ cpu_to_le16(4), |
73 | /* SMB2_TREE_CONNECT */ __constant_cpu_to_le16(16), | 73 | /* SMB2_TREE_CONNECT */ cpu_to_le16(16), |
74 | /* SMB2_TREE_DISCONNECT */ __constant_cpu_to_le16(4), | 74 | /* SMB2_TREE_DISCONNECT */ cpu_to_le16(4), |
75 | /* SMB2_CREATE */ __constant_cpu_to_le16(89), | 75 | /* SMB2_CREATE */ cpu_to_le16(89), |
76 | /* SMB2_CLOSE */ __constant_cpu_to_le16(60), | 76 | /* SMB2_CLOSE */ cpu_to_le16(60), |
77 | /* SMB2_FLUSH */ __constant_cpu_to_le16(4), | 77 | /* SMB2_FLUSH */ cpu_to_le16(4), |
78 | /* SMB2_READ */ __constant_cpu_to_le16(17), | 78 | /* SMB2_READ */ cpu_to_le16(17), |
79 | /* SMB2_WRITE */ __constant_cpu_to_le16(17), | 79 | /* SMB2_WRITE */ cpu_to_le16(17), |
80 | /* SMB2_LOCK */ __constant_cpu_to_le16(4), | 80 | /* SMB2_LOCK */ cpu_to_le16(4), |
81 | /* SMB2_IOCTL */ __constant_cpu_to_le16(49), | 81 | /* SMB2_IOCTL */ cpu_to_le16(49), |
82 | /* BB CHECK this ... not listed in documentation */ | 82 | /* BB CHECK this ... not listed in documentation */ |
83 | /* SMB2_CANCEL */ __constant_cpu_to_le16(0), | 83 | /* SMB2_CANCEL */ cpu_to_le16(0), |
84 | /* SMB2_ECHO */ __constant_cpu_to_le16(4), | 84 | /* SMB2_ECHO */ cpu_to_le16(4), |
85 | /* SMB2_QUERY_DIRECTORY */ __constant_cpu_to_le16(9), | 85 | /* SMB2_QUERY_DIRECTORY */ cpu_to_le16(9), |
86 | /* SMB2_CHANGE_NOTIFY */ __constant_cpu_to_le16(9), | 86 | /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(9), |
87 | /* SMB2_QUERY_INFO */ __constant_cpu_to_le16(9), | 87 | /* SMB2_QUERY_INFO */ cpu_to_le16(9), |
88 | /* SMB2_SET_INFO */ __constant_cpu_to_le16(2), | 88 | /* SMB2_SET_INFO */ cpu_to_le16(2), |
89 | /* BB FIXME can also be 44 for lease break */ | 89 | /* BB FIXME can also be 44 for lease break */ |
90 | /* SMB2_OPLOCK_BREAK */ __constant_cpu_to_le16(24) | 90 | /* SMB2_OPLOCK_BREAK */ cpu_to_le16(24) |
91 | }; | 91 | }; |
92 | 92 | ||
93 | int | 93 | int |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 568f323665c8..93fd0586f9ec 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -600,7 +600,7 @@ smb2_clone_range(const unsigned int xid, | |||
600 | goto cchunk_out; | 600 | goto cchunk_out; |
601 | 601 | ||
602 | /* For now array only one chunk long, will make more flexible later */ | 602 | /* For now array only one chunk long, will make more flexible later */ |
603 | pcchunk->ChunkCount = __constant_cpu_to_le32(1); | 603 | pcchunk->ChunkCount = cpu_to_le32(1); |
604 | pcchunk->Reserved = 0; | 604 | pcchunk->Reserved = 0; |
605 | pcchunk->Reserved2 = 0; | 605 | pcchunk->Reserved2 = 0; |
606 | 606 | ||
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 0ca7f6364754..3417340bf89e 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -1358,7 +1358,7 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, | |||
1358 | char *ret_data = NULL; | 1358 | char *ret_data = NULL; |
1359 | 1359 | ||
1360 | fsctl_input.CompressionState = | 1360 | fsctl_input.CompressionState = |
1361 | __constant_cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); | 1361 | cpu_to_le16(COMPRESSION_FORMAT_DEFAULT); |
1362 | 1362 | ||
1363 | rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, | 1363 | rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, |
1364 | FSCTL_SET_COMPRESSION, true /* is_fsctl */, | 1364 | FSCTL_SET_COMPRESSION, true /* is_fsctl */, |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index d84f46c5b2c5..ce858477002a 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -85,7 +85,7 @@ | |||
85 | /* BB FIXME - analyze following length BB */ | 85 | /* BB FIXME - analyze following length BB */ |
86 | #define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ | 86 | #define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */ |
87 | 87 | ||
88 | #define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe) | 88 | #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) |
89 | 89 | ||
90 | /* | 90 | /* |
91 | * SMB2 Header Definition | 91 | * SMB2 Header Definition |
@@ -96,7 +96,7 @@ | |||
96 | * | 96 | * |
97 | */ | 97 | */ |
98 | 98 | ||
99 | #define SMB2_HEADER_STRUCTURE_SIZE __constant_cpu_to_le16(64) | 99 | #define SMB2_HEADER_STRUCTURE_SIZE cpu_to_le16(64) |
100 | 100 | ||
101 | struct smb2_hdr { | 101 | struct smb2_hdr { |
102 | __be32 smb2_buf_length; /* big endian on wire */ | 102 | __be32 smb2_buf_length; /* big endian on wire */ |
@@ -137,16 +137,16 @@ struct smb2_transform_hdr { | |||
137 | } __packed; | 137 | } __packed; |
138 | 138 | ||
139 | /* Encryption Algorithms */ | 139 | /* Encryption Algorithms */ |
140 | #define SMB2_ENCRYPTION_AES128_CCM __constant_cpu_to_le16(0x0001) | 140 | #define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001) |
141 | 141 | ||
142 | /* | 142 | /* |
143 | * SMB2 flag definitions | 143 | * SMB2 flag definitions |
144 | */ | 144 | */ |
145 | #define SMB2_FLAGS_SERVER_TO_REDIR __constant_cpu_to_le32(0x00000001) | 145 | #define SMB2_FLAGS_SERVER_TO_REDIR cpu_to_le32(0x00000001) |
146 | #define SMB2_FLAGS_ASYNC_COMMAND __constant_cpu_to_le32(0x00000002) | 146 | #define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002) |
147 | #define SMB2_FLAGS_RELATED_OPERATIONS __constant_cpu_to_le32(0x00000004) | 147 | #define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004) |
148 | #define SMB2_FLAGS_SIGNED __constant_cpu_to_le32(0x00000008) | 148 | #define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008) |
149 | #define SMB2_FLAGS_DFS_OPERATIONS __constant_cpu_to_le32(0x10000000) | 149 | #define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000) |
150 | 150 | ||
151 | /* | 151 | /* |
152 | * Definitions for SMB2 Protocol Data Units (network frames) | 152 | * Definitions for SMB2 Protocol Data Units (network frames) |
@@ -157,7 +157,7 @@ struct smb2_transform_hdr { | |||
157 | * | 157 | * |
158 | */ | 158 | */ |
159 | 159 | ||
160 | #define SMB2_ERROR_STRUCTURE_SIZE2 __constant_cpu_to_le16(9) | 160 | #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9) |
161 | 161 | ||
162 | struct smb2_err_rsp { | 162 | struct smb2_err_rsp { |
163 | struct smb2_hdr hdr; | 163 | struct smb2_hdr hdr; |
@@ -502,12 +502,12 @@ struct create_context { | |||
502 | #define SMB2_LEASE_HANDLE_CACHING_HE 0x02 | 502 | #define SMB2_LEASE_HANDLE_CACHING_HE 0x02 |
503 | #define SMB2_LEASE_WRITE_CACHING_HE 0x04 | 503 | #define SMB2_LEASE_WRITE_CACHING_HE 0x04 |
504 | 504 | ||
505 | #define SMB2_LEASE_NONE __constant_cpu_to_le32(0x00) | 505 | #define SMB2_LEASE_NONE cpu_to_le32(0x00) |
506 | #define SMB2_LEASE_READ_CACHING __constant_cpu_to_le32(0x01) | 506 | #define SMB2_LEASE_READ_CACHING cpu_to_le32(0x01) |
507 | #define SMB2_LEASE_HANDLE_CACHING __constant_cpu_to_le32(0x02) | 507 | #define SMB2_LEASE_HANDLE_CACHING cpu_to_le32(0x02) |
508 | #define SMB2_LEASE_WRITE_CACHING __constant_cpu_to_le32(0x04) | 508 | #define SMB2_LEASE_WRITE_CACHING cpu_to_le32(0x04) |
509 | 509 | ||
510 | #define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS __constant_cpu_to_le32(0x02) | 510 | #define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS cpu_to_le32(0x02) |
511 | 511 | ||
512 | #define SMB2_LEASE_KEY_SIZE 16 | 512 | #define SMB2_LEASE_KEY_SIZE 16 |
513 | 513 | ||
@@ -869,7 +869,7 @@ SYSCALL_DEFINE1(dup, unsigned int, fildes) | |||
869 | struct file *file = fget_raw(fildes); | 869 | struct file *file = fget_raw(fildes); |
870 | 870 | ||
871 | if (file) { | 871 | if (file) { |
872 | ret = get_unused_fd(); | 872 | ret = get_unused_fd_flags(0); |
873 | if (ret >= 0) | 873 | if (ret >= 0) |
874 | fd_install(ret, file); | 874 | fd_install(ret, file); |
875 | else | 875 | else |
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c index ff0316b925a5..db458ee3a546 100644 --- a/fs/hfs/catalog.c +++ b/fs/hfs/catalog.c | |||
@@ -162,14 +162,16 @@ err2: | |||
162 | */ | 162 | */ |
163 | int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2) | 163 | int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2) |
164 | { | 164 | { |
165 | int retval; | 165 | __be32 k1p, k2p; |
166 | 166 | ||
167 | retval = be32_to_cpu(key1->cat.ParID) - be32_to_cpu(key2->cat.ParID); | 167 | k1p = key1->cat.ParID; |
168 | if (!retval) | 168 | k2p = key2->cat.ParID; |
169 | retval = hfs_strcmp(key1->cat.CName.name, key1->cat.CName.len, | ||
170 | key2->cat.CName.name, key2->cat.CName.len); | ||
171 | 169 | ||
172 | return retval; | 170 | if (k1p != k2p) |
171 | return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; | ||
172 | |||
173 | return hfs_strcmp(key1->cat.CName.name, key1->cat.CName.len, | ||
174 | key2->cat.CName.name, key2->cat.CName.len); | ||
173 | } | 175 | } |
174 | 176 | ||
175 | /* Try to get a catalog entry for given catalog id */ | 177 | /* Try to get a catalog entry for given catalog id */ |
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index d5659d96ee7f..cf7e043a9447 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c | |||
@@ -447,7 +447,6 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg | |||
447 | result = -EIO; | 447 | result = -EIO; |
448 | } | 448 | } |
449 | } | 449 | } |
450 | result = 0; | ||
451 | } | 450 | } |
452 | mutex_unlock(&server->root_setup_lock); | 451 | mutex_unlock(&server->root_setup_lock); |
453 | 452 | ||
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index e9e3325f29f3..3a03e0aea1fb 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c | |||
@@ -39,21 +39,15 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
39 | */ | 39 | */ |
40 | struct the_nilfs *nilfs; | 40 | struct the_nilfs *nilfs; |
41 | struct inode *inode = file->f_mapping->host; | 41 | struct inode *inode = file->f_mapping->host; |
42 | int err; | 42 | int err = 0; |
43 | |||
44 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
45 | if (err) | ||
46 | return err; | ||
47 | mutex_lock(&inode->i_mutex); | ||
48 | 43 | ||
49 | if (nilfs_inode_dirty(inode)) { | 44 | if (nilfs_inode_dirty(inode)) { |
50 | if (datasync) | 45 | if (datasync) |
51 | err = nilfs_construct_dsync_segment(inode->i_sb, inode, | 46 | err = nilfs_construct_dsync_segment(inode->i_sb, inode, |
52 | 0, LLONG_MAX); | 47 | start, end); |
53 | else | 48 | else |
54 | err = nilfs_construct_segment(inode->i_sb); | 49 | err = nilfs_construct_segment(inode->i_sb); |
55 | } | 50 | } |
56 | mutex_unlock(&inode->i_mutex); | ||
57 | 51 | ||
58 | nilfs = inode->i_sb->s_fs_info; | 52 | nilfs = inode->i_sb->s_fs_info; |
59 | if (!err) | 53 | if (!err) |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index e1fa69b341b9..8b5969538f39 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -49,6 +49,8 @@ struct nilfs_iget_args { | |||
49 | int for_gc; | 49 | int for_gc; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static int nilfs_iget_test(struct inode *inode, void *opaque); | ||
53 | |||
52 | void nilfs_inode_add_blocks(struct inode *inode, int n) | 54 | void nilfs_inode_add_blocks(struct inode *inode, int n) |
53 | { | 55 | { |
54 | struct nilfs_root *root = NILFS_I(inode)->i_root; | 56 | struct nilfs_root *root = NILFS_I(inode)->i_root; |
@@ -348,6 +350,17 @@ const struct address_space_operations nilfs_aops = { | |||
348 | .is_partially_uptodate = block_is_partially_uptodate, | 350 | .is_partially_uptodate = block_is_partially_uptodate, |
349 | }; | 351 | }; |
350 | 352 | ||
353 | static int nilfs_insert_inode_locked(struct inode *inode, | ||
354 | struct nilfs_root *root, | ||
355 | unsigned long ino) | ||
356 | { | ||
357 | struct nilfs_iget_args args = { | ||
358 | .ino = ino, .root = root, .cno = 0, .for_gc = 0 | ||
359 | }; | ||
360 | |||
361 | return insert_inode_locked4(inode, ino, nilfs_iget_test, &args); | ||
362 | } | ||
363 | |||
351 | struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) | 364 | struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) |
352 | { | 365 | { |
353 | struct super_block *sb = dir->i_sb; | 366 | struct super_block *sb = dir->i_sb; |
@@ -383,7 +396,7 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) | |||
383 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 396 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
384 | err = nilfs_bmap_read(ii->i_bmap, NULL); | 397 | err = nilfs_bmap_read(ii->i_bmap, NULL); |
385 | if (err < 0) | 398 | if (err < 0) |
386 | goto failed_bmap; | 399 | goto failed_after_creation; |
387 | 400 | ||
388 | set_bit(NILFS_I_BMAP, &ii->i_state); | 401 | set_bit(NILFS_I_BMAP, &ii->i_state); |
389 | /* No lock is needed; iget() ensures it. */ | 402 | /* No lock is needed; iget() ensures it. */ |
@@ -399,21 +412,24 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) | |||
399 | spin_lock(&nilfs->ns_next_gen_lock); | 412 | spin_lock(&nilfs->ns_next_gen_lock); |
400 | inode->i_generation = nilfs->ns_next_generation++; | 413 | inode->i_generation = nilfs->ns_next_generation++; |
401 | spin_unlock(&nilfs->ns_next_gen_lock); | 414 | spin_unlock(&nilfs->ns_next_gen_lock); |
402 | insert_inode_hash(inode); | 415 | if (nilfs_insert_inode_locked(inode, root, ino) < 0) { |
416 | err = -EIO; | ||
417 | goto failed_after_creation; | ||
418 | } | ||
403 | 419 | ||
404 | err = nilfs_init_acl(inode, dir); | 420 | err = nilfs_init_acl(inode, dir); |
405 | if (unlikely(err)) | 421 | if (unlikely(err)) |
406 | goto failed_acl; /* never occur. When supporting | 422 | goto failed_after_creation; /* never occur. When supporting |
407 | nilfs_init_acl(), proper cancellation of | 423 | nilfs_init_acl(), proper cancellation of |
408 | above jobs should be considered */ | 424 | above jobs should be considered */ |
409 | 425 | ||
410 | return inode; | 426 | return inode; |
411 | 427 | ||
412 | failed_acl: | 428 | failed_after_creation: |
413 | failed_bmap: | ||
414 | clear_nlink(inode); | 429 | clear_nlink(inode); |
430 | unlock_new_inode(inode); | ||
415 | iput(inode); /* raw_inode will be deleted through | 431 | iput(inode); /* raw_inode will be deleted through |
416 | generic_delete_inode() */ | 432 | nilfs_evict_inode() */ |
417 | goto failed; | 433 | goto failed; |
418 | 434 | ||
419 | failed_ifile_create_inode: | 435 | failed_ifile_create_inode: |
@@ -461,8 +477,8 @@ int nilfs_read_inode_common(struct inode *inode, | |||
461 | inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); | 477 | inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); |
462 | inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); | 478 | inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec); |
463 | inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); | 479 | inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec); |
464 | if (inode->i_nlink == 0 && inode->i_mode == 0) | 480 | if (inode->i_nlink == 0) |
465 | return -EINVAL; /* this inode is deleted */ | 481 | return -ESTALE; /* this inode is deleted */ |
466 | 482 | ||
467 | inode->i_blocks = le64_to_cpu(raw_inode->i_blocks); | 483 | inode->i_blocks = le64_to_cpu(raw_inode->i_blocks); |
468 | ii->i_flags = le32_to_cpu(raw_inode->i_flags); | 484 | ii->i_flags = le32_to_cpu(raw_inode->i_flags); |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 9de78f08989e..0f84b257932c 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
@@ -51,9 +51,11 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) | |||
51 | int err = nilfs_add_link(dentry, inode); | 51 | int err = nilfs_add_link(dentry, inode); |
52 | if (!err) { | 52 | if (!err) { |
53 | d_instantiate(dentry, inode); | 53 | d_instantiate(dentry, inode); |
54 | unlock_new_inode(inode); | ||
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
56 | inode_dec_link_count(inode); | 57 | inode_dec_link_count(inode); |
58 | unlock_new_inode(inode); | ||
57 | iput(inode); | 59 | iput(inode); |
58 | return err; | 60 | return err; |
59 | } | 61 | } |
@@ -182,6 +184,7 @@ out: | |||
182 | out_fail: | 184 | out_fail: |
183 | drop_nlink(inode); | 185 | drop_nlink(inode); |
184 | nilfs_mark_inode_dirty(inode); | 186 | nilfs_mark_inode_dirty(inode); |
187 | unlock_new_inode(inode); | ||
185 | iput(inode); | 188 | iput(inode); |
186 | goto out; | 189 | goto out; |
187 | } | 190 | } |
@@ -201,11 +204,15 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir, | |||
201 | inode_inc_link_count(inode); | 204 | inode_inc_link_count(inode); |
202 | ihold(inode); | 205 | ihold(inode); |
203 | 206 | ||
204 | err = nilfs_add_nondir(dentry, inode); | 207 | err = nilfs_add_link(dentry, inode); |
205 | if (!err) | 208 | if (!err) { |
209 | d_instantiate(dentry, inode); | ||
206 | err = nilfs_transaction_commit(dir->i_sb); | 210 | err = nilfs_transaction_commit(dir->i_sb); |
207 | else | 211 | } else { |
212 | inode_dec_link_count(inode); | ||
213 | iput(inode); | ||
208 | nilfs_transaction_abort(dir->i_sb); | 214 | nilfs_transaction_abort(dir->i_sb); |
215 | } | ||
209 | 216 | ||
210 | return err; | 217 | return err; |
211 | } | 218 | } |
@@ -243,6 +250,7 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
243 | 250 | ||
244 | nilfs_mark_inode_dirty(inode); | 251 | nilfs_mark_inode_dirty(inode); |
245 | d_instantiate(dentry, inode); | 252 | d_instantiate(dentry, inode); |
253 | unlock_new_inode(inode); | ||
246 | out: | 254 | out: |
247 | if (!err) | 255 | if (!err) |
248 | err = nilfs_transaction_commit(dir->i_sb); | 256 | err = nilfs_transaction_commit(dir->i_sb); |
@@ -255,6 +263,7 @@ out_fail: | |||
255 | drop_nlink(inode); | 263 | drop_nlink(inode); |
256 | drop_nlink(inode); | 264 | drop_nlink(inode); |
257 | nilfs_mark_inode_dirty(inode); | 265 | nilfs_mark_inode_dirty(inode); |
266 | unlock_new_inode(inode); | ||
258 | iput(inode); | 267 | iput(inode); |
259 | out_dir: | 268 | out_dir: |
260 | drop_nlink(dir); | 269 | drop_nlink(dir); |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 9da25fe9ea61..69bd801afb53 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -808,8 +808,7 @@ void nilfs_put_root(struct nilfs_root *root) | |||
808 | spin_lock(&nilfs->ns_cptree_lock); | 808 | spin_lock(&nilfs->ns_cptree_lock); |
809 | rb_erase(&root->rb_node, &nilfs->ns_cptree); | 809 | rb_erase(&root->rb_node, &nilfs->ns_cptree); |
810 | spin_unlock(&nilfs->ns_cptree_lock); | 810 | spin_unlock(&nilfs->ns_cptree_lock); |
811 | if (root->ifile) | 811 | iput(root->ifile); |
812 | iput(root->ifile); | ||
813 | 812 | ||
814 | kfree(root); | 813 | kfree(root); |
815 | } | 814 | } |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1ef547e49373..d9f222987f24 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1251,7 +1251,7 @@ static int ocfs2_write_cluster(struct address_space *mapping, | |||
1251 | ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL, | 1251 | ret = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, NULL, |
1252 | NULL); | 1252 | NULL); |
1253 | if (ret < 0) { | 1253 | if (ret < 0) { |
1254 | ocfs2_error(inode->i_sb, "Corrupting extend for inode %llu, " | 1254 | mlog(ML_ERROR, "Get physical blkno failed for inode %llu, " |
1255 | "at logical block %llu", | 1255 | "at logical block %llu", |
1256 | (unsigned long long)OCFS2_I(inode)->ip_blkno, | 1256 | (unsigned long long)OCFS2_I(inode)->ip_blkno, |
1257 | (unsigned long long)v_blkno); | 1257 | (unsigned long long)v_blkno); |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index eb9d48746ab4..16eff45727ee 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
@@ -1127,10 +1127,10 @@ static int o2hb_thread(void *data) | |||
1127 | elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); | 1127 | elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb); |
1128 | 1128 | ||
1129 | mlog(ML_HEARTBEAT, | 1129 | mlog(ML_HEARTBEAT, |
1130 | "start = %lu.%lu, end = %lu.%lu, msec = %u\n", | 1130 | "start = %lu.%lu, end = %lu.%lu, msec = %u, ret = %d\n", |
1131 | before_hb.tv_sec, (unsigned long) before_hb.tv_usec, | 1131 | before_hb.tv_sec, (unsigned long) before_hb.tv_usec, |
1132 | after_hb.tv_sec, (unsigned long) after_hb.tv_usec, | 1132 | after_hb.tv_sec, (unsigned long) after_hb.tv_usec, |
1133 | elapsed_msec); | 1133 | elapsed_msec, ret); |
1134 | 1134 | ||
1135 | if (!kthread_should_stop() && | 1135 | if (!kthread_should_stop() && |
1136 | elapsed_msec < reg->hr_timeout_ms) { | 1136 | elapsed_msec < reg->hr_timeout_ms) { |
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index a96044004064..2e355e0f8335 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c | |||
@@ -1736,7 +1736,7 @@ static void o2net_connect_expired(struct work_struct *work) | |||
1736 | o2net_idle_timeout() / 1000, | 1736 | o2net_idle_timeout() / 1000, |
1737 | o2net_idle_timeout() % 1000); | 1737 | o2net_idle_timeout() % 1000); |
1738 | 1738 | ||
1739 | o2net_set_nn_state(nn, NULL, 0, -ENOTCONN); | 1739 | o2net_set_nn_state(nn, NULL, 0, 0); |
1740 | } | 1740 | } |
1741 | spin_unlock(&nn->nn_lock); | 1741 | spin_unlock(&nn->nn_lock); |
1742 | } | 1742 | } |
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index c43d9b4a1ec0..79d56dc981bc 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -744,7 +744,7 @@ restart: | |||
744 | if (ocfs2_read_dir_block(dir, block, &bh, 0)) { | 744 | if (ocfs2_read_dir_block(dir, block, &bh, 0)) { |
745 | /* read error, skip block & hope for the best. | 745 | /* read error, skip block & hope for the best. |
746 | * ocfs2_read_dir_block() has released the bh. */ | 746 | * ocfs2_read_dir_block() has released the bh. */ |
747 | ocfs2_error(dir->i_sb, "reading directory %llu, " | 747 | mlog(ML_ERROR, "reading directory %llu, " |
748 | "offset %lu\n", | 748 | "offset %lu\n", |
749 | (unsigned long long)OCFS2_I(dir)->ip_blkno, | 749 | (unsigned long long)OCFS2_I(dir)->ip_blkno, |
750 | block); | 750 | block); |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 02d315fef432..50a59d2337b2 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -877,7 +877,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data, | |||
877 | * to be put in someone's domain map. | 877 | * to be put in someone's domain map. |
878 | * Also, explicitly disallow joining at certain troublesome | 878 | * Also, explicitly disallow joining at certain troublesome |
879 | * times (ie. during recovery). */ | 879 | * times (ie. during recovery). */ |
880 | if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) { | 880 | if (dlm->dlm_state != DLM_CTXT_LEAVING) { |
881 | int bit = query->node_idx; | 881 | int bit = query->node_idx; |
882 | spin_lock(&dlm->spinlock); | 882 | spin_lock(&dlm->spinlock); |
883 | 883 | ||
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 215e41abf101..3689b3592042 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -1460,6 +1460,18 @@ way_up_top: | |||
1460 | 1460 | ||
1461 | /* take care of the easy cases up front */ | 1461 | /* take care of the easy cases up front */ |
1462 | spin_lock(&res->spinlock); | 1462 | spin_lock(&res->spinlock); |
1463 | |||
1464 | /* | ||
1465 | * Right after dlm spinlock was released, dlm_thread could have | ||
1466 | * purged the lockres. Check if lockres got unhashed. If so | ||
1467 | * start over. | ||
1468 | */ | ||
1469 | if (hlist_unhashed(&res->hash_node)) { | ||
1470 | spin_unlock(&res->spinlock); | ||
1471 | dlm_lockres_put(res); | ||
1472 | goto way_up_top; | ||
1473 | } | ||
1474 | |||
1463 | if (res->state & (DLM_LOCK_RES_RECOVERING| | 1475 | if (res->state & (DLM_LOCK_RES_RECOVERING| |
1464 | DLM_LOCK_RES_MIGRATING)) { | 1476 | DLM_LOCK_RES_MIGRATING)) { |
1465 | spin_unlock(&res->spinlock); | 1477 | spin_unlock(&res->spinlock); |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 3365839d2971..79b5af5e6a7b 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
@@ -1656,14 +1656,18 @@ int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, | |||
1656 | req.namelen = res->lockname.len; | 1656 | req.namelen = res->lockname.len; |
1657 | memcpy(req.name, res->lockname.name, res->lockname.len); | 1657 | memcpy(req.name, res->lockname.name, res->lockname.len); |
1658 | 1658 | ||
1659 | resend: | ||
1659 | ret = o2net_send_message(DLM_MASTER_REQUERY_MSG, dlm->key, | 1660 | ret = o2net_send_message(DLM_MASTER_REQUERY_MSG, dlm->key, |
1660 | &req, sizeof(req), nodenum, &status); | 1661 | &req, sizeof(req), nodenum, &status); |
1661 | /* XXX: negative status not handled properly here. */ | ||
1662 | if (ret < 0) | 1662 | if (ret < 0) |
1663 | mlog(ML_ERROR, "Error %d when sending message %u (key " | 1663 | mlog(ML_ERROR, "Error %d when sending message %u (key " |
1664 | "0x%x) to node %u\n", ret, DLM_MASTER_REQUERY_MSG, | 1664 | "0x%x) to node %u\n", ret, DLM_MASTER_REQUERY_MSG, |
1665 | dlm->key, nodenum); | 1665 | dlm->key, nodenum); |
1666 | else { | 1666 | else if (status == -ENOMEM) { |
1667 | mlog_errno(status); | ||
1668 | msleep(50); | ||
1669 | goto resend; | ||
1670 | } else { | ||
1667 | BUG_ON(status < 0); | 1671 | BUG_ON(status < 0); |
1668 | BUG_ON(status > DLM_LOCK_RES_OWNER_UNKNOWN); | 1672 | BUG_ON(status > DLM_LOCK_RES_OWNER_UNKNOWN); |
1669 | *real_master = (u8) (status & 0xff); | 1673 | *real_master = (u8) (status & 0xff); |
@@ -1705,9 +1709,13 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data, | |||
1705 | int ret = dlm_dispatch_assert_master(dlm, res, | 1709 | int ret = dlm_dispatch_assert_master(dlm, res, |
1706 | 0, 0, flags); | 1710 | 0, 0, flags); |
1707 | if (ret < 0) { | 1711 | if (ret < 0) { |
1708 | mlog_errno(-ENOMEM); | 1712 | mlog_errno(ret); |
1709 | /* retry!? */ | 1713 | spin_unlock(&res->spinlock); |
1710 | BUG(); | 1714 | dlm_lockres_put(res); |
1715 | spin_unlock(&dlm->spinlock); | ||
1716 | dlm_put(dlm); | ||
1717 | /* sender will take care of this and retry */ | ||
1718 | return ret; | ||
1711 | } else | 1719 | } else |
1712 | __dlm_lockres_grab_inflight_worker(dlm, res); | 1720 | __dlm_lockres_grab_inflight_worker(dlm, res); |
1713 | spin_unlock(&res->spinlock); | 1721 | spin_unlock(&res->spinlock); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 37297c14f9a3..1c423af04c69 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -861,8 +861,13 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo | |||
861 | * We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing | 861 | * We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing |
862 | * the OCFS2_LOCK_BUSY flag to prevent the dc thread from | 862 | * the OCFS2_LOCK_BUSY flag to prevent the dc thread from |
863 | * downconverting the lock before the upconvert has fully completed. | 863 | * downconverting the lock before the upconvert has fully completed. |
864 | * Do not prevent the dc thread from downconverting if NONBLOCK lock | ||
865 | * had already returned. | ||
864 | */ | 866 | */ |
865 | lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); | 867 | if (!(lockres->l_flags & OCFS2_LOCK_NONBLOCK_FINISHED)) |
868 | lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); | ||
869 | else | ||
870 | lockres_clear_flags(lockres, OCFS2_LOCK_NONBLOCK_FINISHED); | ||
866 | 871 | ||
867 | lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); | 872 | lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); |
868 | } | 873 | } |
@@ -1324,13 +1329,12 @@ static void lockres_add_mask_waiter(struct ocfs2_lock_res *lockres, | |||
1324 | 1329 | ||
1325 | /* returns 0 if the mw that was removed was already satisfied, -EBUSY | 1330 | /* returns 0 if the mw that was removed was already satisfied, -EBUSY |
1326 | * if the mask still hadn't reached its goal */ | 1331 | * if the mask still hadn't reached its goal */ |
1327 | static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, | 1332 | static int __lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, |
1328 | struct ocfs2_mask_waiter *mw) | 1333 | struct ocfs2_mask_waiter *mw) |
1329 | { | 1334 | { |
1330 | unsigned long flags; | ||
1331 | int ret = 0; | 1335 | int ret = 0; |
1332 | 1336 | ||
1333 | spin_lock_irqsave(&lockres->l_lock, flags); | 1337 | assert_spin_locked(&lockres->l_lock); |
1334 | if (!list_empty(&mw->mw_item)) { | 1338 | if (!list_empty(&mw->mw_item)) { |
1335 | if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal) | 1339 | if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal) |
1336 | ret = -EBUSY; | 1340 | ret = -EBUSY; |
@@ -1338,6 +1342,18 @@ static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, | |||
1338 | list_del_init(&mw->mw_item); | 1342 | list_del_init(&mw->mw_item); |
1339 | init_completion(&mw->mw_complete); | 1343 | init_completion(&mw->mw_complete); |
1340 | } | 1344 | } |
1345 | |||
1346 | return ret; | ||
1347 | } | ||
1348 | |||
1349 | static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, | ||
1350 | struct ocfs2_mask_waiter *mw) | ||
1351 | { | ||
1352 | unsigned long flags; | ||
1353 | int ret = 0; | ||
1354 | |||
1355 | spin_lock_irqsave(&lockres->l_lock, flags); | ||
1356 | ret = __lockres_remove_mask_waiter(lockres, mw); | ||
1341 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 1357 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
1342 | 1358 | ||
1343 | return ret; | 1359 | return ret; |
@@ -1373,6 +1389,7 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, | |||
1373 | unsigned long flags; | 1389 | unsigned long flags; |
1374 | unsigned int gen; | 1390 | unsigned int gen; |
1375 | int noqueue_attempted = 0; | 1391 | int noqueue_attempted = 0; |
1392 | int dlm_locked = 0; | ||
1376 | 1393 | ||
1377 | ocfs2_init_mask_waiter(&mw); | 1394 | ocfs2_init_mask_waiter(&mw); |
1378 | 1395 | ||
@@ -1481,6 +1498,7 @@ again: | |||
1481 | ocfs2_recover_from_dlm_error(lockres, 1); | 1498 | ocfs2_recover_from_dlm_error(lockres, 1); |
1482 | goto out; | 1499 | goto out; |
1483 | } | 1500 | } |
1501 | dlm_locked = 1; | ||
1484 | 1502 | ||
1485 | mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n", | 1503 | mlog(0, "lock %s, successful return from ocfs2_dlm_lock\n", |
1486 | lockres->l_name); | 1504 | lockres->l_name); |
@@ -1514,10 +1532,17 @@ out: | |||
1514 | if (wait && arg_flags & OCFS2_LOCK_NONBLOCK && | 1532 | if (wait && arg_flags & OCFS2_LOCK_NONBLOCK && |
1515 | mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) { | 1533 | mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) { |
1516 | wait = 0; | 1534 | wait = 0; |
1517 | if (lockres_remove_mask_waiter(lockres, &mw)) | 1535 | spin_lock_irqsave(&lockres->l_lock, flags); |
1536 | if (__lockres_remove_mask_waiter(lockres, &mw)) { | ||
1537 | if (dlm_locked) | ||
1538 | lockres_or_flags(lockres, | ||
1539 | OCFS2_LOCK_NONBLOCK_FINISHED); | ||
1540 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
1518 | ret = -EAGAIN; | 1541 | ret = -EAGAIN; |
1519 | else | 1542 | } else { |
1543 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
1520 | goto again; | 1544 | goto again; |
1545 | } | ||
1521 | } | 1546 | } |
1522 | if (wait) { | 1547 | if (wait) { |
1523 | ret = ocfs2_wait_for_mask(&mw); | 1548 | ret = ocfs2_wait_for_mask(&mw); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 324dc93ac896..69fb9f75b082 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -2381,9 +2381,7 @@ out_dio: | |||
2381 | if (ret < 0) | 2381 | if (ret < 0) |
2382 | written = ret; | 2382 | written = ret; |
2383 | 2383 | ||
2384 | if (!ret && ((old_size != i_size_read(inode)) || | 2384 | if (!ret) { |
2385 | (old_clusters != OCFS2_I(inode)->ip_clusters) || | ||
2386 | has_refcount)) { | ||
2387 | ret = jbd2_journal_force_commit(osb->journal->j_journal); | 2385 | ret = jbd2_journal_force_commit(osb->journal->j_journal); |
2388 | if (ret < 0) | 2386 | if (ret < 0) |
2389 | written = ret; | 2387 | written = ret; |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 437de7f768c6..c8b25de9efbb 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -540,8 +540,7 @@ bail: | |||
540 | if (status < 0) | 540 | if (status < 0) |
541 | make_bad_inode(inode); | 541 | make_bad_inode(inode); |
542 | 542 | ||
543 | if (args && bh) | 543 | brelse(bh); |
544 | brelse(bh); | ||
545 | 544 | ||
546 | return status; | 545 | return status; |
547 | } | 546 | } |
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 74caffeeee1d..56a768d06aa6 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
@@ -904,9 +904,6 @@ static int ocfs2_move_extents(struct ocfs2_move_extents_context *context) | |||
904 | struct buffer_head *di_bh = NULL; | 904 | struct buffer_head *di_bh = NULL; |
905 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 905 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
906 | 906 | ||
907 | if (!inode) | ||
908 | return -ENOENT; | ||
909 | |||
910 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) | 907 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) |
911 | return -EROFS; | 908 | return -EROFS; |
912 | 909 | ||
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index bbec539230fd..7d6b7d090452 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -144,6 +144,12 @@ enum ocfs2_unlock_action { | |||
144 | * before the upconvert | 144 | * before the upconvert |
145 | * has completed */ | 145 | * has completed */ |
146 | 146 | ||
147 | #define OCFS2_LOCK_NONBLOCK_FINISHED (0x00001000) /* NONBLOCK cluster | ||
148 | * lock has already | ||
149 | * returned, do not block | ||
150 | * dc thread from | ||
151 | * downconverting */ | ||
152 | |||
147 | struct ocfs2_lock_res_ops; | 153 | struct ocfs2_lock_res_ops; |
148 | 154 | ||
149 | typedef void (*ocfs2_lock_callback)(int status, unsigned long data); | 155 | typedef void (*ocfs2_lock_callback)(int status, unsigned long data); |
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index a88b2a4fcc85..d5493e361a38 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c | |||
@@ -306,7 +306,7 @@ int ocfs2_slot_to_node_num_locked(struct ocfs2_super *osb, int slot_num, | |||
306 | assert_spin_locked(&osb->osb_lock); | 306 | assert_spin_locked(&osb->osb_lock); |
307 | 307 | ||
308 | BUG_ON(slot_num < 0); | 308 | BUG_ON(slot_num < 0); |
309 | BUG_ON(slot_num > osb->max_slots); | 309 | BUG_ON(slot_num >= osb->max_slots); |
310 | 310 | ||
311 | if (!si->si_slots[slot_num].sl_valid) | 311 | if (!si->si_slots[slot_num].sl_valid) |
312 | return -ENOENT; | 312 | return -ENOENT; |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 0945814ddb7b..83723179e1ec 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -1629,8 +1629,9 @@ static int __init ocfs2_init(void) | |||
1629 | 1629 | ||
1630 | ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); | 1630 | ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); |
1631 | if (!ocfs2_debugfs_root) { | 1631 | if (!ocfs2_debugfs_root) { |
1632 | status = -EFAULT; | 1632 | status = -ENOMEM; |
1633 | mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n"); | 1633 | mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n"); |
1634 | goto out4; | ||
1634 | } | 1635 | } |
1635 | 1636 | ||
1636 | ocfs2_set_locking_protocol(); | 1637 | ocfs2_set_locking_protocol(); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 016f01df3825..662f8dee149f 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -1284,7 +1284,7 @@ int ocfs2_xattr_get_nolock(struct inode *inode, | |||
1284 | return -EOPNOTSUPP; | 1284 | return -EOPNOTSUPP; |
1285 | 1285 | ||
1286 | if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL)) | 1286 | if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL)) |
1287 | ret = -ENODATA; | 1287 | return -ENODATA; |
1288 | 1288 | ||
1289 | xis.inode_bh = xbs.inode_bh = di_bh; | 1289 | xis.inode_bh = xbs.inode_bh = di_bh; |
1290 | di = (struct ocfs2_dinode *)di_bh->b_data; | 1290 | di = (struct ocfs2_dinode *)di_bh->b_data; |
diff --git a/fs/proc/array.c b/fs/proc/array.c index cd3653e4f35c..bd117d065b82 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -157,20 +157,29 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | |||
157 | struct user_namespace *user_ns = seq_user_ns(m); | 157 | struct user_namespace *user_ns = seq_user_ns(m); |
158 | struct group_info *group_info; | 158 | struct group_info *group_info; |
159 | int g; | 159 | int g; |
160 | struct fdtable *fdt = NULL; | 160 | struct task_struct *tracer; |
161 | const struct cred *cred; | 161 | const struct cred *cred; |
162 | pid_t ppid, tpid; | 162 | pid_t ppid, tpid = 0, tgid, ngid; |
163 | unsigned int max_fds = 0; | ||
163 | 164 | ||
164 | rcu_read_lock(); | 165 | rcu_read_lock(); |
165 | ppid = pid_alive(p) ? | 166 | ppid = pid_alive(p) ? |
166 | task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; | 167 | task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0; |
167 | tpid = 0; | 168 | |
168 | if (pid_alive(p)) { | 169 | tracer = ptrace_parent(p); |
169 | struct task_struct *tracer = ptrace_parent(p); | 170 | if (tracer) |
170 | if (tracer) | 171 | tpid = task_pid_nr_ns(tracer, ns); |
171 | tpid = task_pid_nr_ns(tracer, ns); | 172 | |
172 | } | 173 | tgid = task_tgid_nr_ns(p, ns); |
174 | ngid = task_numa_group_id(p); | ||
173 | cred = get_task_cred(p); | 175 | cred = get_task_cred(p); |
176 | |||
177 | task_lock(p); | ||
178 | if (p->files) | ||
179 | max_fds = files_fdtable(p->files)->max_fds; | ||
180 | task_unlock(p); | ||
181 | rcu_read_unlock(); | ||
182 | |||
174 | seq_printf(m, | 183 | seq_printf(m, |
175 | "State:\t%s\n" | 184 | "State:\t%s\n" |
176 | "Tgid:\t%d\n" | 185 | "Tgid:\t%d\n" |
@@ -179,12 +188,10 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | |||
179 | "PPid:\t%d\n" | 188 | "PPid:\t%d\n" |
180 | "TracerPid:\t%d\n" | 189 | "TracerPid:\t%d\n" |
181 | "Uid:\t%d\t%d\t%d\t%d\n" | 190 | "Uid:\t%d\t%d\t%d\t%d\n" |
182 | "Gid:\t%d\t%d\t%d\t%d\n", | 191 | "Gid:\t%d\t%d\t%d\t%d\n" |
192 | "FDSize:\t%d\nGroups:\t", | ||
183 | get_task_state(p), | 193 | get_task_state(p), |
184 | task_tgid_nr_ns(p, ns), | 194 | tgid, ngid, pid_nr_ns(pid, ns), ppid, tpid, |
185 | task_numa_group_id(p), | ||
186 | pid_nr_ns(pid, ns), | ||
187 | ppid, tpid, | ||
188 | from_kuid_munged(user_ns, cred->uid), | 195 | from_kuid_munged(user_ns, cred->uid), |
189 | from_kuid_munged(user_ns, cred->euid), | 196 | from_kuid_munged(user_ns, cred->euid), |
190 | from_kuid_munged(user_ns, cred->suid), | 197 | from_kuid_munged(user_ns, cred->suid), |
@@ -192,20 +199,10 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | |||
192 | from_kgid_munged(user_ns, cred->gid), | 199 | from_kgid_munged(user_ns, cred->gid), |
193 | from_kgid_munged(user_ns, cred->egid), | 200 | from_kgid_munged(user_ns, cred->egid), |
194 | from_kgid_munged(user_ns, cred->sgid), | 201 | from_kgid_munged(user_ns, cred->sgid), |
195 | from_kgid_munged(user_ns, cred->fsgid)); | 202 | from_kgid_munged(user_ns, cred->fsgid), |
196 | 203 | max_fds); | |
197 | task_lock(p); | ||
198 | if (p->files) | ||
199 | fdt = files_fdtable(p->files); | ||
200 | seq_printf(m, | ||
201 | "FDSize:\t%d\n" | ||
202 | "Groups:\t", | ||
203 | fdt ? fdt->max_fds : 0); | ||
204 | rcu_read_unlock(); | ||
205 | 204 | ||
206 | group_info = cred->group_info; | 205 | group_info = cred->group_info; |
207 | task_unlock(p); | ||
208 | |||
209 | for (g = 0; g < group_info->ngroups; g++) | 206 | for (g = 0; g < group_info->ngroups; g++) |
210 | seq_printf(m, "%d ", | 207 | seq_printf(m, "%d ", |
211 | from_kgid_munged(user_ns, GROUP_AT(group_info, g))); | 208 | from_kgid_munged(user_ns, GROUP_AT(group_info, g))); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 64891f3e41bd..590aeda5af12 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2618,6 +2618,9 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid) | |||
2618 | dput(dentry); | 2618 | dput(dentry); |
2619 | } | 2619 | } |
2620 | 2620 | ||
2621 | if (pid == tgid) | ||
2622 | return; | ||
2623 | |||
2621 | name.name = buf; | 2624 | name.name = buf; |
2622 | name.len = snprintf(buf, sizeof(buf), "%d", tgid); | 2625 | name.len = snprintf(buf, sizeof(buf), "%d", tgid); |
2623 | leader = d_hash_and_lookup(mnt->mnt_root, &name); | 2626 | leader = d_hash_and_lookup(mnt->mnt_root, &name); |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 317b72641ebf..7fea13229f33 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -31,9 +31,73 @@ static DEFINE_SPINLOCK(proc_subdir_lock); | |||
31 | 31 | ||
32 | static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) | 32 | static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) |
33 | { | 33 | { |
34 | if (de->namelen != len) | 34 | if (len < de->namelen) |
35 | return 0; | 35 | return -1; |
36 | return !memcmp(name, de->name, len); | 36 | if (len > de->namelen) |
37 | return 1; | ||
38 | |||
39 | return memcmp(name, de->name, len); | ||
40 | } | ||
41 | |||
42 | static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir) | ||
43 | { | ||
44 | return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry, | ||
45 | subdir_node); | ||
46 | } | ||
47 | |||
48 | static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir) | ||
49 | { | ||
50 | return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry, | ||
51 | subdir_node); | ||
52 | } | ||
53 | |||
54 | static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir, | ||
55 | const char *name, | ||
56 | unsigned int len) | ||
57 | { | ||
58 | struct rb_node *node = dir->subdir.rb_node; | ||
59 | |||
60 | while (node) { | ||
61 | struct proc_dir_entry *de = container_of(node, | ||
62 | struct proc_dir_entry, | ||
63 | subdir_node); | ||
64 | int result = proc_match(len, name, de); | ||
65 | |||
66 | if (result < 0) | ||
67 | node = node->rb_left; | ||
68 | else if (result > 0) | ||
69 | node = node->rb_right; | ||
70 | else | ||
71 | return de; | ||
72 | } | ||
73 | return NULL; | ||
74 | } | ||
75 | |||
76 | static bool pde_subdir_insert(struct proc_dir_entry *dir, | ||
77 | struct proc_dir_entry *de) | ||
78 | { | ||
79 | struct rb_root *root = &dir->subdir; | ||
80 | struct rb_node **new = &root->rb_node, *parent = NULL; | ||
81 | |||
82 | /* Figure out where to put new node */ | ||
83 | while (*new) { | ||
84 | struct proc_dir_entry *this = | ||
85 | container_of(*new, struct proc_dir_entry, subdir_node); | ||
86 | int result = proc_match(de->namelen, de->name, this); | ||
87 | |||
88 | parent = *new; | ||
89 | if (result < 0) | ||
90 | new = &(*new)->rb_left; | ||
91 | else if (result > 0) | ||
92 | new = &(*new)->rb_right; | ||
93 | else | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | /* Add new node and rebalance tree. */ | ||
98 | rb_link_node(&de->subdir_node, parent, new); | ||
99 | rb_insert_color(&de->subdir_node, root); | ||
100 | return true; | ||
37 | } | 101 | } |
38 | 102 | ||
39 | static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) | 103 | static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) |
@@ -92,10 +156,7 @@ static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret, | |||
92 | break; | 156 | break; |
93 | 157 | ||
94 | len = next - cp; | 158 | len = next - cp; |
95 | for (de = de->subdir; de ; de = de->next) { | 159 | de = pde_subdir_find(de, cp, len); |
96 | if (proc_match(len, cp, de)) | ||
97 | break; | ||
98 | } | ||
99 | if (!de) { | 160 | if (!de) { |
100 | WARN(1, "name '%s'\n", name); | 161 | WARN(1, "name '%s'\n", name); |
101 | return -ENOENT; | 162 | return -ENOENT; |
@@ -183,19 +244,16 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, | |||
183 | struct inode *inode; | 244 | struct inode *inode; |
184 | 245 | ||
185 | spin_lock(&proc_subdir_lock); | 246 | spin_lock(&proc_subdir_lock); |
186 | for (de = de->subdir; de ; de = de->next) { | 247 | de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len); |
187 | if (de->namelen != dentry->d_name.len) | 248 | if (de) { |
188 | continue; | 249 | pde_get(de); |
189 | if (!memcmp(dentry->d_name.name, de->name, de->namelen)) { | 250 | spin_unlock(&proc_subdir_lock); |
190 | pde_get(de); | 251 | inode = proc_get_inode(dir->i_sb, de); |
191 | spin_unlock(&proc_subdir_lock); | 252 | if (!inode) |
192 | inode = proc_get_inode(dir->i_sb, de); | 253 | return ERR_PTR(-ENOMEM); |
193 | if (!inode) | 254 | d_set_d_op(dentry, &simple_dentry_operations); |
194 | return ERR_PTR(-ENOMEM); | 255 | d_add(dentry, inode); |
195 | d_set_d_op(dentry, &simple_dentry_operations); | 256 | return NULL; |
196 | d_add(dentry, inode); | ||
197 | return NULL; | ||
198 | } | ||
199 | } | 257 | } |
200 | spin_unlock(&proc_subdir_lock); | 258 | spin_unlock(&proc_subdir_lock); |
201 | return ERR_PTR(-ENOENT); | 259 | return ERR_PTR(-ENOENT); |
@@ -225,7 +283,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file, | |||
225 | return 0; | 283 | return 0; |
226 | 284 | ||
227 | spin_lock(&proc_subdir_lock); | 285 | spin_lock(&proc_subdir_lock); |
228 | de = de->subdir; | 286 | de = pde_subdir_first(de); |
229 | i = ctx->pos - 2; | 287 | i = ctx->pos - 2; |
230 | for (;;) { | 288 | for (;;) { |
231 | if (!de) { | 289 | if (!de) { |
@@ -234,7 +292,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file, | |||
234 | } | 292 | } |
235 | if (!i) | 293 | if (!i) |
236 | break; | 294 | break; |
237 | de = de->next; | 295 | de = pde_subdir_next(de); |
238 | i--; | 296 | i--; |
239 | } | 297 | } |
240 | 298 | ||
@@ -249,7 +307,7 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *file, | |||
249 | } | 307 | } |
250 | spin_lock(&proc_subdir_lock); | 308 | spin_lock(&proc_subdir_lock); |
251 | ctx->pos++; | 309 | ctx->pos++; |
252 | next = de->next; | 310 | next = pde_subdir_next(de); |
253 | pde_put(de); | 311 | pde_put(de); |
254 | de = next; | 312 | de = next; |
255 | } while (de); | 313 | } while (de); |
@@ -286,9 +344,8 @@ static const struct inode_operations proc_dir_inode_operations = { | |||
286 | 344 | ||
287 | static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) | 345 | static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) |
288 | { | 346 | { |
289 | struct proc_dir_entry *tmp; | ||
290 | int ret; | 347 | int ret; |
291 | 348 | ||
292 | ret = proc_alloc_inum(&dp->low_ino); | 349 | ret = proc_alloc_inum(&dp->low_ino); |
293 | if (ret) | 350 | if (ret) |
294 | return ret; | 351 | return ret; |
@@ -304,21 +361,21 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
304 | dp->proc_iops = &proc_file_inode_operations; | 361 | dp->proc_iops = &proc_file_inode_operations; |
305 | } else { | 362 | } else { |
306 | WARN_ON(1); | 363 | WARN_ON(1); |
364 | proc_free_inum(dp->low_ino); | ||
307 | return -EINVAL; | 365 | return -EINVAL; |
308 | } | 366 | } |
309 | 367 | ||
310 | spin_lock(&proc_subdir_lock); | 368 | spin_lock(&proc_subdir_lock); |
311 | |||
312 | for (tmp = dir->subdir; tmp; tmp = tmp->next) | ||
313 | if (strcmp(tmp->name, dp->name) == 0) { | ||
314 | WARN(1, "proc_dir_entry '%s/%s' already registered\n", | ||
315 | dir->name, dp->name); | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | dp->next = dir->subdir; | ||
320 | dp->parent = dir; | 369 | dp->parent = dir; |
321 | dir->subdir = dp; | 370 | if (pde_subdir_insert(dir, dp) == false) { |
371 | WARN(1, "proc_dir_entry '%s/%s' already registered\n", | ||
372 | dir->name, dp->name); | ||
373 | spin_unlock(&proc_subdir_lock); | ||
374 | if (S_ISDIR(dp->mode)) | ||
375 | dir->nlink--; | ||
376 | proc_free_inum(dp->low_ino); | ||
377 | return -EEXIST; | ||
378 | } | ||
322 | spin_unlock(&proc_subdir_lock); | 379 | spin_unlock(&proc_subdir_lock); |
323 | 380 | ||
324 | return 0; | 381 | return 0; |
@@ -354,6 +411,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent, | |||
354 | ent->namelen = qstr.len; | 411 | ent->namelen = qstr.len; |
355 | ent->mode = mode; | 412 | ent->mode = mode; |
356 | ent->nlink = nlink; | 413 | ent->nlink = nlink; |
414 | ent->subdir = RB_ROOT; | ||
357 | atomic_set(&ent->count, 1); | 415 | atomic_set(&ent->count, 1); |
358 | spin_lock_init(&ent->pde_unload_lock); | 416 | spin_lock_init(&ent->pde_unload_lock); |
359 | INIT_LIST_HEAD(&ent->pde_openers); | 417 | INIT_LIST_HEAD(&ent->pde_openers); |
@@ -485,7 +543,6 @@ void pde_put(struct proc_dir_entry *pde) | |||
485 | */ | 543 | */ |
486 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | 544 | void remove_proc_entry(const char *name, struct proc_dir_entry *parent) |
487 | { | 545 | { |
488 | struct proc_dir_entry **p; | ||
489 | struct proc_dir_entry *de = NULL; | 546 | struct proc_dir_entry *de = NULL; |
490 | const char *fn = name; | 547 | const char *fn = name; |
491 | unsigned int len; | 548 | unsigned int len; |
@@ -497,14 +554,9 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
497 | } | 554 | } |
498 | len = strlen(fn); | 555 | len = strlen(fn); |
499 | 556 | ||
500 | for (p = &parent->subdir; *p; p=&(*p)->next ) { | 557 | de = pde_subdir_find(parent, fn, len); |
501 | if (proc_match(len, fn, *p)) { | 558 | if (de) |
502 | de = *p; | 559 | rb_erase(&de->subdir_node, &parent->subdir); |
503 | *p = de->next; | ||
504 | de->next = NULL; | ||
505 | break; | ||
506 | } | ||
507 | } | ||
508 | spin_unlock(&proc_subdir_lock); | 560 | spin_unlock(&proc_subdir_lock); |
509 | if (!de) { | 561 | if (!de) { |
510 | WARN(1, "name '%s'\n", name); | 562 | WARN(1, "name '%s'\n", name); |
@@ -516,16 +568,15 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
516 | if (S_ISDIR(de->mode)) | 568 | if (S_ISDIR(de->mode)) |
517 | parent->nlink--; | 569 | parent->nlink--; |
518 | de->nlink = 0; | 570 | de->nlink = 0; |
519 | WARN(de->subdir, "%s: removing non-empty directory " | 571 | WARN(pde_subdir_first(de), |
520 | "'%s/%s', leaking at least '%s'\n", __func__, | 572 | "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n", |
521 | de->parent->name, de->name, de->subdir->name); | 573 | __func__, de->parent->name, de->name, pde_subdir_first(de)->name); |
522 | pde_put(de); | 574 | pde_put(de); |
523 | } | 575 | } |
524 | EXPORT_SYMBOL(remove_proc_entry); | 576 | EXPORT_SYMBOL(remove_proc_entry); |
525 | 577 | ||
526 | int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) | 578 | int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) |
527 | { | 579 | { |
528 | struct proc_dir_entry **p; | ||
529 | struct proc_dir_entry *root = NULL, *de, *next; | 580 | struct proc_dir_entry *root = NULL, *de, *next; |
530 | const char *fn = name; | 581 | const char *fn = name; |
531 | unsigned int len; | 582 | unsigned int len; |
@@ -537,24 +588,18 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) | |||
537 | } | 588 | } |
538 | len = strlen(fn); | 589 | len = strlen(fn); |
539 | 590 | ||
540 | for (p = &parent->subdir; *p; p=&(*p)->next ) { | 591 | root = pde_subdir_find(parent, fn, len); |
541 | if (proc_match(len, fn, *p)) { | ||
542 | root = *p; | ||
543 | *p = root->next; | ||
544 | root->next = NULL; | ||
545 | break; | ||
546 | } | ||
547 | } | ||
548 | if (!root) { | 592 | if (!root) { |
549 | spin_unlock(&proc_subdir_lock); | 593 | spin_unlock(&proc_subdir_lock); |
550 | return -ENOENT; | 594 | return -ENOENT; |
551 | } | 595 | } |
596 | rb_erase(&root->subdir_node, &parent->subdir); | ||
597 | |||
552 | de = root; | 598 | de = root; |
553 | while (1) { | 599 | while (1) { |
554 | next = de->subdir; | 600 | next = pde_subdir_first(de); |
555 | if (next) { | 601 | if (next) { |
556 | de->subdir = next->next; | 602 | rb_erase(&next->subdir_node, &de->subdir); |
557 | next->next = NULL; | ||
558 | de = next; | 603 | de = next; |
559 | continue; | 604 | continue; |
560 | } | 605 | } |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index aa7a0ee182e1..7fb1a4869fd0 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -24,10 +24,9 @@ struct mempolicy; | |||
24 | * tree) of these proc_dir_entries, so that we can dynamically | 24 | * tree) of these proc_dir_entries, so that we can dynamically |
25 | * add new files to /proc. | 25 | * add new files to /proc. |
26 | * | 26 | * |
27 | * The "next" pointer creates a linked list of one /proc directory, | 27 | * parent/subdir are used for the directory structure (every /proc file has a |
28 | * while parent/subdir create the directory structure (every | 28 | * parent, but "subdir" is empty for all non-directory entries). |
29 | * /proc file has a parent, but "subdir" is NULL for all | 29 | * subdir_node is used to build the rb tree "subdir" of the parent. |
30 | * non-directory entries). | ||
31 | */ | 30 | */ |
32 | struct proc_dir_entry { | 31 | struct proc_dir_entry { |
33 | unsigned int low_ino; | 32 | unsigned int low_ino; |
@@ -38,7 +37,9 @@ struct proc_dir_entry { | |||
38 | loff_t size; | 37 | loff_t size; |
39 | const struct inode_operations *proc_iops; | 38 | const struct inode_operations *proc_iops; |
40 | const struct file_operations *proc_fops; | 39 | const struct file_operations *proc_fops; |
41 | struct proc_dir_entry *next, *parent, *subdir; | 40 | struct proc_dir_entry *parent; |
41 | struct rb_root subdir; | ||
42 | struct rb_node subdir_node; | ||
42 | void *data; | 43 | void *data; |
43 | atomic_t count; /* use count */ | 44 | atomic_t count; /* use count */ |
44 | atomic_t in_use; /* number of callers into module in progress; */ | 45 | atomic_t in_use; /* number of callers into module in progress; */ |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index a63af3e0a612..1bde894bc624 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -192,6 +192,7 @@ static __net_init int proc_net_ns_init(struct net *net) | |||
192 | if (!netd) | 192 | if (!netd) |
193 | goto out; | 193 | goto out; |
194 | 194 | ||
195 | netd->subdir = RB_ROOT; | ||
195 | netd->data = net; | 196 | netd->data = net; |
196 | netd->nlink = 2; | 197 | netd->nlink = 2; |
197 | netd->namelen = 3; | 198 | netd->namelen = 3; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 094e44d4a6be..e74ac9f1a2c0 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -251,6 +251,7 @@ struct proc_dir_entry proc_root = { | |||
251 | .proc_iops = &proc_root_inode_operations, | 251 | .proc_iops = &proc_root_inode_operations, |
252 | .proc_fops = &proc_root_operations, | 252 | .proc_fops = &proc_root_operations, |
253 | .parent = &proc_root, | 253 | .parent = &proc_root, |
254 | .subdir = RB_ROOT, | ||
254 | .name = "/proc", | 255 | .name = "/proc", |
255 | }; | 256 | }; |
256 | 257 | ||
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index f6734c6b66a6..246eae84b13b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -447,58 +447,91 @@ struct mem_size_stats { | |||
447 | u64 pss; | 447 | u64 pss; |
448 | }; | 448 | }; |
449 | 449 | ||
450 | static void smaps_account(struct mem_size_stats *mss, struct page *page, | ||
451 | unsigned long size, bool young, bool dirty) | ||
452 | { | ||
453 | int mapcount; | ||
454 | |||
455 | if (PageAnon(page)) | ||
456 | mss->anonymous += size; | ||
450 | 457 | ||
451 | static void smaps_pte_entry(pte_t ptent, unsigned long addr, | 458 | mss->resident += size; |
452 | unsigned long ptent_size, struct mm_walk *walk) | 459 | /* Accumulate the size in pages that have been accessed. */ |
460 | if (young || PageReferenced(page)) | ||
461 | mss->referenced += size; | ||
462 | mapcount = page_mapcount(page); | ||
463 | if (mapcount >= 2) { | ||
464 | u64 pss_delta; | ||
465 | |||
466 | if (dirty || PageDirty(page)) | ||
467 | mss->shared_dirty += size; | ||
468 | else | ||
469 | mss->shared_clean += size; | ||
470 | pss_delta = (u64)size << PSS_SHIFT; | ||
471 | do_div(pss_delta, mapcount); | ||
472 | mss->pss += pss_delta; | ||
473 | } else { | ||
474 | if (dirty || PageDirty(page)) | ||
475 | mss->private_dirty += size; | ||
476 | else | ||
477 | mss->private_clean += size; | ||
478 | mss->pss += (u64)size << PSS_SHIFT; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | static void smaps_pte_entry(pte_t *pte, unsigned long addr, | ||
483 | struct mm_walk *walk) | ||
453 | { | 484 | { |
454 | struct mem_size_stats *mss = walk->private; | 485 | struct mem_size_stats *mss = walk->private; |
455 | struct vm_area_struct *vma = mss->vma; | 486 | struct vm_area_struct *vma = mss->vma; |
456 | pgoff_t pgoff = linear_page_index(vma, addr); | 487 | pgoff_t pgoff = linear_page_index(vma, addr); |
457 | struct page *page = NULL; | 488 | struct page *page = NULL; |
458 | int mapcount; | ||
459 | 489 | ||
460 | if (pte_present(ptent)) { | 490 | if (pte_present(*pte)) { |
461 | page = vm_normal_page(vma, addr, ptent); | 491 | page = vm_normal_page(vma, addr, *pte); |
462 | } else if (is_swap_pte(ptent)) { | 492 | } else if (is_swap_pte(*pte)) { |
463 | swp_entry_t swpent = pte_to_swp_entry(ptent); | 493 | swp_entry_t swpent = pte_to_swp_entry(*pte); |
464 | 494 | ||
465 | if (!non_swap_entry(swpent)) | 495 | if (!non_swap_entry(swpent)) |
466 | mss->swap += ptent_size; | 496 | mss->swap += PAGE_SIZE; |
467 | else if (is_migration_entry(swpent)) | 497 | else if (is_migration_entry(swpent)) |
468 | page = migration_entry_to_page(swpent); | 498 | page = migration_entry_to_page(swpent); |
469 | } else if (pte_file(ptent)) { | 499 | } else if (pte_file(*pte)) { |
470 | if (pte_to_pgoff(ptent) != pgoff) | 500 | if (pte_to_pgoff(*pte) != pgoff) |
471 | mss->nonlinear += ptent_size; | 501 | mss->nonlinear += PAGE_SIZE; |
472 | } | 502 | } |
473 | 503 | ||
474 | if (!page) | 504 | if (!page) |
475 | return; | 505 | return; |
476 | 506 | ||
477 | if (PageAnon(page)) | ||
478 | mss->anonymous += ptent_size; | ||
479 | |||
480 | if (page->index != pgoff) | 507 | if (page->index != pgoff) |
481 | mss->nonlinear += ptent_size; | 508 | mss->nonlinear += PAGE_SIZE; |
482 | 509 | ||
483 | mss->resident += ptent_size; | 510 | smaps_account(mss, page, PAGE_SIZE, pte_young(*pte), pte_dirty(*pte)); |
484 | /* Accumulate the size in pages that have been accessed. */ | 511 | } |
485 | if (pte_young(ptent) || PageReferenced(page)) | 512 | |
486 | mss->referenced += ptent_size; | 513 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
487 | mapcount = page_mapcount(page); | 514 | static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, |
488 | if (mapcount >= 2) { | 515 | struct mm_walk *walk) |
489 | if (pte_dirty(ptent) || PageDirty(page)) | 516 | { |
490 | mss->shared_dirty += ptent_size; | 517 | struct mem_size_stats *mss = walk->private; |
491 | else | 518 | struct vm_area_struct *vma = mss->vma; |
492 | mss->shared_clean += ptent_size; | 519 | struct page *page; |
493 | mss->pss += (ptent_size << PSS_SHIFT) / mapcount; | 520 | |
494 | } else { | 521 | /* FOLL_DUMP will return -EFAULT on huge zero page */ |
495 | if (pte_dirty(ptent) || PageDirty(page)) | 522 | page = follow_trans_huge_pmd(vma, addr, pmd, FOLL_DUMP); |
496 | mss->private_dirty += ptent_size; | 523 | if (IS_ERR_OR_NULL(page)) |
497 | else | 524 | return; |
498 | mss->private_clean += ptent_size; | 525 | mss->anonymous_thp += HPAGE_PMD_SIZE; |
499 | mss->pss += (ptent_size << PSS_SHIFT); | 526 | smaps_account(mss, page, HPAGE_PMD_SIZE, |
500 | } | 527 | pmd_young(*pmd), pmd_dirty(*pmd)); |
501 | } | 528 | } |
529 | #else | ||
530 | static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, | ||
531 | struct mm_walk *walk) | ||
532 | { | ||
533 | } | ||
534 | #endif | ||
502 | 535 | ||
503 | static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | 536 | static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, |
504 | struct mm_walk *walk) | 537 | struct mm_walk *walk) |
@@ -509,9 +542,8 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
509 | spinlock_t *ptl; | 542 | spinlock_t *ptl; |
510 | 543 | ||
511 | if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { | 544 | if (pmd_trans_huge_lock(pmd, vma, &ptl) == 1) { |
512 | smaps_pte_entry(*(pte_t *)pmd, addr, HPAGE_PMD_SIZE, walk); | 545 | smaps_pmd_entry(pmd, addr, walk); |
513 | spin_unlock(ptl); | 546 | spin_unlock(ptl); |
514 | mss->anonymous_thp += HPAGE_PMD_SIZE; | ||
515 | return 0; | 547 | return 0; |
516 | } | 548 | } |
517 | 549 | ||
@@ -524,7 +556,7 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
524 | */ | 556 | */ |
525 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | 557 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); |
526 | for (; addr != end; pte++, addr += PAGE_SIZE) | 558 | for (; addr != end; pte++, addr += PAGE_SIZE) |
527 | smaps_pte_entry(*pte, addr, PAGE_SIZE, walk); | 559 | smaps_pte_entry(pte, addr, walk); |
528 | pte_unmap_unlock(pte - 1, ptl); | 560 | pte_unmap_unlock(pte - 1, ptl); |
529 | cond_resched(); | 561 | cond_resched(); |
530 | return 0; | 562 | return 0; |