diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig.binfmt | 4 | ||||
-rw-r--r-- | fs/Makefile | 1 | ||||
-rw-r--r-- | fs/aio.c | 2 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 677 | ||||
-rw-r--r-- | fs/compat_binfmt_elf.c | 131 | ||||
-rw-r--r-- | fs/dlm/dir.c | 76 | ||||
-rw-r--r-- | fs/dlm/dlm_internal.h | 16 | ||||
-rw-r--r-- | fs/dlm/lock.c | 249 | ||||
-rw-r--r-- | fs/dlm/lock.h | 2 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 16 | ||||
-rw-r--r-- | fs/dlm/lowcomms.c | 15 | ||||
-rw-r--r-- | fs/dlm/main.c | 10 | ||||
-rw-r--r-- | fs/dlm/member.c | 4 | ||||
-rw-r--r-- | fs/dlm/member.h | 3 | ||||
-rw-r--r-- | fs/dlm/memory.c | 32 | ||||
-rw-r--r-- | fs/dlm/memory.h | 16 | ||||
-rw-r--r-- | fs/dlm/midcomms.c | 15 | ||||
-rw-r--r-- | fs/dlm/rcom.c | 25 | ||||
-rw-r--r-- | fs/dlm/recover.c | 27 | ||||
-rw-r--r-- | fs/dlm/recoverd.c | 11 | ||||
-rw-r--r-- | fs/dlm/user.c | 29 | ||||
-rw-r--r-- | fs/dlm/util.c | 82 | ||||
-rw-r--r-- | fs/jbd/checkpoint.c | 3 | ||||
-rw-r--r-- | fs/jbd/commit.c | 2 | ||||
-rw-r--r-- | fs/jbd2/checkpoint.c | 3 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 2 |
26 files changed, 1051 insertions, 402 deletions
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index d4fc6095466d..7c3d5f923da1 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -23,6 +23,10 @@ config BINFMT_ELF | |||
23 | ld.so (check the file <file:Documentation/Changes> for location and | 23 | ld.so (check the file <file:Documentation/Changes> for location and |
24 | latest version). | 24 | latest version). |
25 | 25 | ||
26 | config COMPAT_BINFMT_ELF | ||
27 | bool | ||
28 | depends on COMPAT && MMU | ||
29 | |||
26 | config BINFMT_ELF_FDPIC | 30 | config BINFMT_ELF_FDPIC |
27 | bool "Kernel support for FDPIC ELF binaries" | 31 | bool "Kernel support for FDPIC ELF binaries" |
28 | default y | 32 | default y |
diff --git a/fs/Makefile b/fs/Makefile index 500cf15cdb4b..1e7a11bd4da1 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o | |||
39 | obj-y += binfmt_script.o | 39 | obj-y += binfmt_script.o |
40 | 40 | ||
41 | obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o | 41 | obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o |
42 | obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o | ||
42 | obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o | 43 | obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o |
43 | obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o | 44 | obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o |
44 | obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o | 45 | obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o |
@@ -397,7 +397,7 @@ void fastcall __put_ioctx(struct kioctx *ctx) | |||
397 | * This prevents races between the aio code path referencing the | 397 | * This prevents races between the aio code path referencing the |
398 | * req (after submitting it) and aio_complete() freeing the req. | 398 | * req (after submitting it) and aio_complete() freeing the req. |
399 | */ | 399 | */ |
400 | static struct kiocb *FASTCALL(__aio_get_req(struct kioctx *ctx)); | 400 | static struct kiocb *__aio_get_req(struct kioctx *ctx); |
401 | static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) | 401 | static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) |
402 | { | 402 | { |
403 | struct kiocb *req = NULL; | 403 | struct kiocb *req = NULL; |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index f0b3171842f2..18ed6dd906c1 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -45,7 +45,8 @@ | |||
45 | 45 | ||
46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); | 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); |
47 | static int load_elf_library(struct file *); | 47 | static int load_elf_library(struct file *); |
48 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); | 48 | static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *, |
49 | int, int, unsigned long); | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * If we don't support core dumping, then supply a NULL so we | 52 | * If we don't support core dumping, then supply a NULL so we |
@@ -298,33 +299,70 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
298 | #ifndef elf_map | 299 | #ifndef elf_map |
299 | 300 | ||
300 | static unsigned long elf_map(struct file *filep, unsigned long addr, | 301 | static unsigned long elf_map(struct file *filep, unsigned long addr, |
301 | struct elf_phdr *eppnt, int prot, int type) | 302 | struct elf_phdr *eppnt, int prot, int type, |
303 | unsigned long total_size) | ||
302 | { | 304 | { |
303 | unsigned long map_addr; | 305 | unsigned long map_addr; |
304 | unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); | 306 | unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr); |
307 | unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr); | ||
308 | addr = ELF_PAGESTART(addr); | ||
309 | size = ELF_PAGEALIGN(size); | ||
305 | 310 | ||
306 | down_write(¤t->mm->mmap_sem); | ||
307 | /* mmap() will return -EINVAL if given a zero size, but a | 311 | /* mmap() will return -EINVAL if given a zero size, but a |
308 | * segment with zero filesize is perfectly valid */ | 312 | * segment with zero filesize is perfectly valid */ |
309 | if (eppnt->p_filesz + pageoffset) | 313 | if (!size) |
310 | map_addr = do_mmap(filep, ELF_PAGESTART(addr), | 314 | return addr; |
311 | eppnt->p_filesz + pageoffset, prot, type, | 315 | |
312 | eppnt->p_offset - pageoffset); | 316 | down_write(¤t->mm->mmap_sem); |
313 | else | 317 | /* |
314 | map_addr = ELF_PAGESTART(addr); | 318 | * total_size is the size of the ELF (interpreter) image. |
319 | * The _first_ mmap needs to know the full size, otherwise | ||
320 | * randomization might put this image into an overlapping | ||
321 | * position with the ELF binary image. (since size < total_size) | ||
322 | * So we first map the 'big' image - and unmap the remainder at | ||
323 | * the end. (which unmap is needed for ELF images with holes.) | ||
324 | */ | ||
325 | if (total_size) { | ||
326 | total_size = ELF_PAGEALIGN(total_size); | ||
327 | map_addr = do_mmap(filep, addr, total_size, prot, type, off); | ||
328 | if (!BAD_ADDR(map_addr)) | ||
329 | do_munmap(current->mm, map_addr+size, total_size-size); | ||
330 | } else | ||
331 | map_addr = do_mmap(filep, addr, size, prot, type, off); | ||
332 | |||
315 | up_write(¤t->mm->mmap_sem); | 333 | up_write(¤t->mm->mmap_sem); |
316 | return(map_addr); | 334 | return(map_addr); |
317 | } | 335 | } |
318 | 336 | ||
319 | #endif /* !elf_map */ | 337 | #endif /* !elf_map */ |
320 | 338 | ||
339 | static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr) | ||
340 | { | ||
341 | int i, first_idx = -1, last_idx = -1; | ||
342 | |||
343 | for (i = 0; i < nr; i++) { | ||
344 | if (cmds[i].p_type == PT_LOAD) { | ||
345 | last_idx = i; | ||
346 | if (first_idx == -1) | ||
347 | first_idx = i; | ||
348 | } | ||
349 | } | ||
350 | if (first_idx == -1) | ||
351 | return 0; | ||
352 | |||
353 | return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz - | ||
354 | ELF_PAGESTART(cmds[first_idx].p_vaddr); | ||
355 | } | ||
356 | |||
357 | |||
321 | /* This is much more generalized than the library routine read function, | 358 | /* This is much more generalized than the library routine read function, |
322 | so we keep this separate. Technically the library read function | 359 | so we keep this separate. Technically the library read function |
323 | is only provided so that we can read a.out libraries that have | 360 | is only provided so that we can read a.out libraries that have |
324 | an ELF header */ | 361 | an ELF header */ |
325 | 362 | ||
326 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | 363 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, |
327 | struct file *interpreter, unsigned long *interp_load_addr) | 364 | struct file *interpreter, unsigned long *interp_map_addr, |
365 | unsigned long no_base) | ||
328 | { | 366 | { |
329 | struct elf_phdr *elf_phdata; | 367 | struct elf_phdr *elf_phdata; |
330 | struct elf_phdr *eppnt; | 368 | struct elf_phdr *eppnt; |
@@ -332,6 +370,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
332 | int load_addr_set = 0; | 370 | int load_addr_set = 0; |
333 | unsigned long last_bss = 0, elf_bss = 0; | 371 | unsigned long last_bss = 0, elf_bss = 0; |
334 | unsigned long error = ~0UL; | 372 | unsigned long error = ~0UL; |
373 | unsigned long total_size; | ||
335 | int retval, i, size; | 374 | int retval, i, size; |
336 | 375 | ||
337 | /* First of all, some simple consistency checks */ | 376 | /* First of all, some simple consistency checks */ |
@@ -370,6 +409,12 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
370 | goto out_close; | 409 | goto out_close; |
371 | } | 410 | } |
372 | 411 | ||
412 | total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum); | ||
413 | if (!total_size) { | ||
414 | error = -EINVAL; | ||
415 | goto out_close; | ||
416 | } | ||
417 | |||
373 | eppnt = elf_phdata; | 418 | eppnt = elf_phdata; |
374 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { | 419 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { |
375 | if (eppnt->p_type == PT_LOAD) { | 420 | if (eppnt->p_type == PT_LOAD) { |
@@ -387,9 +432,14 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
387 | vaddr = eppnt->p_vaddr; | 432 | vaddr = eppnt->p_vaddr; |
388 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) | 433 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
389 | elf_type |= MAP_FIXED; | 434 | elf_type |= MAP_FIXED; |
435 | else if (no_base && interp_elf_ex->e_type == ET_DYN) | ||
436 | load_addr = -vaddr; | ||
390 | 437 | ||
391 | map_addr = elf_map(interpreter, load_addr + vaddr, | 438 | map_addr = elf_map(interpreter, load_addr + vaddr, |
392 | eppnt, elf_prot, elf_type); | 439 | eppnt, elf_prot, elf_type, total_size); |
440 | total_size = 0; | ||
441 | if (!*interp_map_addr) | ||
442 | *interp_map_addr = map_addr; | ||
393 | error = map_addr; | 443 | error = map_addr; |
394 | if (BAD_ADDR(map_addr)) | 444 | if (BAD_ADDR(map_addr)) |
395 | goto out_close; | 445 | goto out_close; |
@@ -455,8 +505,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
455 | goto out_close; | 505 | goto out_close; |
456 | } | 506 | } |
457 | 507 | ||
458 | *interp_load_addr = load_addr; | 508 | error = load_addr; |
459 | error = ((unsigned long)interp_elf_ex->e_entry) + load_addr; | ||
460 | 509 | ||
461 | out_close: | 510 | out_close: |
462 | kfree(elf_phdata); | 511 | kfree(elf_phdata); |
@@ -546,14 +595,14 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
546 | int load_addr_set = 0; | 595 | int load_addr_set = 0; |
547 | char * elf_interpreter = NULL; | 596 | char * elf_interpreter = NULL; |
548 | unsigned int interpreter_type = INTERPRETER_NONE; | 597 | unsigned int interpreter_type = INTERPRETER_NONE; |
549 | unsigned char ibcs2_interpreter = 0; | ||
550 | unsigned long error; | 598 | unsigned long error; |
551 | struct elf_phdr *elf_ppnt, *elf_phdata; | 599 | struct elf_phdr *elf_ppnt, *elf_phdata; |
552 | unsigned long elf_bss, elf_brk; | 600 | unsigned long elf_bss, elf_brk; |
553 | int elf_exec_fileno; | 601 | int elf_exec_fileno; |
554 | int retval, i; | 602 | int retval, i; |
555 | unsigned int size; | 603 | unsigned int size; |
556 | unsigned long elf_entry, interp_load_addr = 0; | 604 | unsigned long elf_entry; |
605 | unsigned long interp_load_addr = 0; | ||
557 | unsigned long start_code, end_code, start_data, end_data; | 606 | unsigned long start_code, end_code, start_data, end_data; |
558 | unsigned long reloc_func_desc = 0; | 607 | unsigned long reloc_func_desc = 0; |
559 | char passed_fileno[6]; | 608 | char passed_fileno[6]; |
@@ -663,14 +712,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
663 | if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') | 712 | if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') |
664 | goto out_free_interp; | 713 | goto out_free_interp; |
665 | 714 | ||
666 | /* If the program interpreter is one of these two, | ||
667 | * then assume an iBCS2 image. Otherwise assume | ||
668 | * a native linux image. | ||
669 | */ | ||
670 | if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || | ||
671 | strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) | ||
672 | ibcs2_interpreter = 1; | ||
673 | |||
674 | /* | 715 | /* |
675 | * The early SET_PERSONALITY here is so that the lookup | 716 | * The early SET_PERSONALITY here is so that the lookup |
676 | * for the interpreter happens in the namespace of the | 717 | * for the interpreter happens in the namespace of the |
@@ -690,7 +731,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
690 | * switch really is going to happen - do this in | 731 | * switch really is going to happen - do this in |
691 | * flush_thread(). - akpm | 732 | * flush_thread(). - akpm |
692 | */ | 733 | */ |
693 | SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter); | 734 | SET_PERSONALITY(loc->elf_ex, 0); |
694 | 735 | ||
695 | interpreter = open_exec(elf_interpreter); | 736 | interpreter = open_exec(elf_interpreter); |
696 | retval = PTR_ERR(interpreter); | 737 | retval = PTR_ERR(interpreter); |
@@ -769,7 +810,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
769 | goto out_free_dentry; | 810 | goto out_free_dentry; |
770 | } else { | 811 | } else { |
771 | /* Executables without an interpreter also need a personality */ | 812 | /* Executables without an interpreter also need a personality */ |
772 | SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter); | 813 | SET_PERSONALITY(loc->elf_ex, 0); |
773 | } | 814 | } |
774 | 815 | ||
775 | /* OK, we are done with that, now set up the arg stuff, | 816 | /* OK, we are done with that, now set up the arg stuff, |
@@ -803,7 +844,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
803 | 844 | ||
804 | /* Do this immediately, since STACK_TOP as used in setup_arg_pages | 845 | /* Do this immediately, since STACK_TOP as used in setup_arg_pages |
805 | may depend on the personality. */ | 846 | may depend on the personality. */ |
806 | SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter); | 847 | SET_PERSONALITY(loc->elf_ex, 0); |
807 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) | 848 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) |
808 | current->personality |= READ_IMPLIES_EXEC; | 849 | current->personality |= READ_IMPLIES_EXEC; |
809 | 850 | ||
@@ -825,9 +866,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
825 | current->mm->start_stack = bprm->p; | 866 | current->mm->start_stack = bprm->p; |
826 | 867 | ||
827 | /* Now we do a little grungy work by mmaping the ELF image into | 868 | /* Now we do a little grungy work by mmaping the ELF image into |
828 | the correct location in memory. At this point, we assume that | 869 | the correct location in memory. */ |
829 | the image should be loaded at fixed address, not at a variable | ||
830 | address. */ | ||
831 | for(i = 0, elf_ppnt = elf_phdata; | 870 | for(i = 0, elf_ppnt = elf_phdata; |
832 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 871 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { |
833 | int elf_prot = 0, elf_flags; | 872 | int elf_prot = 0, elf_flags; |
@@ -881,11 +920,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
881 | * default mmap base, as well as whatever program they | 920 | * default mmap base, as well as whatever program they |
882 | * might try to exec. This is because the brk will | 921 | * might try to exec. This is because the brk will |
883 | * follow the loader, and is not movable. */ | 922 | * follow the loader, and is not movable. */ |
923 | #ifdef CONFIG_X86 | ||
924 | load_bias = 0; | ||
925 | #else | ||
884 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); | 926 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); |
927 | #endif | ||
885 | } | 928 | } |
886 | 929 | ||
887 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, | 930 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, |
888 | elf_prot, elf_flags); | 931 | elf_prot, elf_flags, 0); |
889 | if (BAD_ADDR(error)) { | 932 | if (BAD_ADDR(error)) { |
890 | send_sig(SIGKILL, current, 0); | 933 | send_sig(SIGKILL, current, 0); |
891 | retval = IS_ERR((void *)error) ? | 934 | retval = IS_ERR((void *)error) ? |
@@ -961,13 +1004,25 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
961 | } | 1004 | } |
962 | 1005 | ||
963 | if (elf_interpreter) { | 1006 | if (elf_interpreter) { |
964 | if (interpreter_type == INTERPRETER_AOUT) | 1007 | if (interpreter_type == INTERPRETER_AOUT) { |
965 | elf_entry = load_aout_interp(&loc->interp_ex, | 1008 | elf_entry = load_aout_interp(&loc->interp_ex, |
966 | interpreter); | 1009 | interpreter); |
967 | else | 1010 | } else { |
1011 | unsigned long uninitialized_var(interp_map_addr); | ||
1012 | |||
968 | elf_entry = load_elf_interp(&loc->interp_elf_ex, | 1013 | elf_entry = load_elf_interp(&loc->interp_elf_ex, |
969 | interpreter, | 1014 | interpreter, |
970 | &interp_load_addr); | 1015 | &interp_map_addr, |
1016 | load_bias); | ||
1017 | if (!IS_ERR((void *)elf_entry)) { | ||
1018 | /* | ||
1019 | * load_elf_interp() returns relocation | ||
1020 | * adjustment | ||
1021 | */ | ||
1022 | interp_load_addr = elf_entry; | ||
1023 | elf_entry += loc->interp_elf_ex.e_entry; | ||
1024 | } | ||
1025 | } | ||
971 | if (BAD_ADDR(elf_entry)) { | 1026 | if (BAD_ADDR(elf_entry)) { |
972 | force_sig(SIGSEGV, current); | 1027 | force_sig(SIGSEGV, current); |
973 | retval = IS_ERR((void *)elf_entry) ? | 1028 | retval = IS_ERR((void *)elf_entry) ? |
@@ -1021,6 +1076,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
1021 | current->mm->end_data = end_data; | 1076 | current->mm->end_data = end_data; |
1022 | current->mm->start_stack = bprm->p; | 1077 | current->mm->start_stack = bprm->p; |
1023 | 1078 | ||
1079 | #ifdef arch_randomize_brk | ||
1080 | if (current->flags & PF_RANDOMIZE) | ||
1081 | current->mm->brk = current->mm->start_brk = | ||
1082 | arch_randomize_brk(current->mm); | ||
1083 | #endif | ||
1084 | |||
1024 | if (current->personality & MMAP_PAGE_ZERO) { | 1085 | if (current->personality & MMAP_PAGE_ZERO) { |
1025 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, | 1086 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, |
1026 | and some applications "depend" upon this behavior. | 1087 | and some applications "depend" upon this behavior. |
@@ -1325,7 +1386,8 @@ static int writenote(struct memelfnote *men, struct file *file, | |||
1325 | if (!dump_seek(file, (off))) \ | 1386 | if (!dump_seek(file, (off))) \ |
1326 | goto end_coredump; | 1387 | goto end_coredump; |
1327 | 1388 | ||
1328 | static void fill_elf_header(struct elfhdr *elf, int segs) | 1389 | static void fill_elf_header(struct elfhdr *elf, int segs, |
1390 | u16 machine, u32 flags, u8 osabi) | ||
1329 | { | 1391 | { |
1330 | memcpy(elf->e_ident, ELFMAG, SELFMAG); | 1392 | memcpy(elf->e_ident, ELFMAG, SELFMAG); |
1331 | elf->e_ident[EI_CLASS] = ELF_CLASS; | 1393 | elf->e_ident[EI_CLASS] = ELF_CLASS; |
@@ -1335,12 +1397,12 @@ static void fill_elf_header(struct elfhdr *elf, int segs) | |||
1335 | memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); | 1397 | memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); |
1336 | 1398 | ||
1337 | elf->e_type = ET_CORE; | 1399 | elf->e_type = ET_CORE; |
1338 | elf->e_machine = ELF_ARCH; | 1400 | elf->e_machine = machine; |
1339 | elf->e_version = EV_CURRENT; | 1401 | elf->e_version = EV_CURRENT; |
1340 | elf->e_entry = 0; | 1402 | elf->e_entry = 0; |
1341 | elf->e_phoff = sizeof(struct elfhdr); | 1403 | elf->e_phoff = sizeof(struct elfhdr); |
1342 | elf->e_shoff = 0; | 1404 | elf->e_shoff = 0; |
1343 | elf->e_flags = ELF_CORE_EFLAGS; | 1405 | elf->e_flags = flags; |
1344 | elf->e_ehsize = sizeof(struct elfhdr); | 1406 | elf->e_ehsize = sizeof(struct elfhdr); |
1345 | elf->e_phentsize = sizeof(struct elf_phdr); | 1407 | elf->e_phentsize = sizeof(struct elf_phdr); |
1346 | elf->e_phnum = segs; | 1408 | elf->e_phnum = segs; |
@@ -1447,6 +1509,238 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, | |||
1447 | return 0; | 1509 | return 0; |
1448 | } | 1510 | } |
1449 | 1511 | ||
1512 | static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm) | ||
1513 | { | ||
1514 | elf_addr_t *auxv = (elf_addr_t *) mm->saved_auxv; | ||
1515 | int i = 0; | ||
1516 | do | ||
1517 | i += 2; | ||
1518 | while (auxv[i - 2] != AT_NULL); | ||
1519 | fill_note(note, "CORE", NT_AUXV, i * sizeof(elf_addr_t), auxv); | ||
1520 | } | ||
1521 | |||
1522 | #ifdef CORE_DUMP_USE_REGSET | ||
1523 | #include <linux/regset.h> | ||
1524 | |||
1525 | struct elf_thread_core_info { | ||
1526 | struct elf_thread_core_info *next; | ||
1527 | struct task_struct *task; | ||
1528 | struct elf_prstatus prstatus; | ||
1529 | struct memelfnote notes[0]; | ||
1530 | }; | ||
1531 | |||
1532 | struct elf_note_info { | ||
1533 | struct elf_thread_core_info *thread; | ||
1534 | struct memelfnote psinfo; | ||
1535 | struct memelfnote auxv; | ||
1536 | size_t size; | ||
1537 | int thread_notes; | ||
1538 | }; | ||
1539 | |||
1540 | static int fill_thread_core_info(struct elf_thread_core_info *t, | ||
1541 | const struct user_regset_view *view, | ||
1542 | long signr, size_t *total) | ||
1543 | { | ||
1544 | unsigned int i; | ||
1545 | |||
1546 | /* | ||
1547 | * NT_PRSTATUS is the one special case, because the regset data | ||
1548 | * goes into the pr_reg field inside the note contents, rather | ||
1549 | * than being the whole note contents. We fill the reset in here. | ||
1550 | * We assume that regset 0 is NT_PRSTATUS. | ||
1551 | */ | ||
1552 | fill_prstatus(&t->prstatus, t->task, signr); | ||
1553 | (void) view->regsets[0].get(t->task, &view->regsets[0], | ||
1554 | 0, sizeof(t->prstatus.pr_reg), | ||
1555 | &t->prstatus.pr_reg, NULL); | ||
1556 | |||
1557 | fill_note(&t->notes[0], "CORE", NT_PRSTATUS, | ||
1558 | sizeof(t->prstatus), &t->prstatus); | ||
1559 | *total += notesize(&t->notes[0]); | ||
1560 | |||
1561 | /* | ||
1562 | * Each other regset might generate a note too. For each regset | ||
1563 | * that has no core_note_type or is inactive, we leave t->notes[i] | ||
1564 | * all zero and we'll know to skip writing it later. | ||
1565 | */ | ||
1566 | for (i = 1; i < view->n; ++i) { | ||
1567 | const struct user_regset *regset = &view->regsets[i]; | ||
1568 | if (regset->core_note_type && | ||
1569 | (!regset->active || regset->active(t->task, regset))) { | ||
1570 | int ret; | ||
1571 | size_t size = regset->n * regset->size; | ||
1572 | void *data = kmalloc(size, GFP_KERNEL); | ||
1573 | if (unlikely(!data)) | ||
1574 | return 0; | ||
1575 | ret = regset->get(t->task, regset, | ||
1576 | 0, size, data, NULL); | ||
1577 | if (unlikely(ret)) | ||
1578 | kfree(data); | ||
1579 | else { | ||
1580 | if (regset->core_note_type != NT_PRFPREG) | ||
1581 | fill_note(&t->notes[i], "LINUX", | ||
1582 | regset->core_note_type, | ||
1583 | size, data); | ||
1584 | else { | ||
1585 | t->prstatus.pr_fpvalid = 1; | ||
1586 | fill_note(&t->notes[i], "CORE", | ||
1587 | NT_PRFPREG, size, data); | ||
1588 | } | ||
1589 | *total += notesize(&t->notes[i]); | ||
1590 | } | ||
1591 | } | ||
1592 | } | ||
1593 | |||
1594 | return 1; | ||
1595 | } | ||
1596 | |||
1597 | static int fill_note_info(struct elfhdr *elf, int phdrs, | ||
1598 | struct elf_note_info *info, | ||
1599 | long signr, struct pt_regs *regs) | ||
1600 | { | ||
1601 | struct task_struct *dump_task = current; | ||
1602 | const struct user_regset_view *view = task_user_regset_view(dump_task); | ||
1603 | struct elf_thread_core_info *t; | ||
1604 | struct elf_prpsinfo *psinfo; | ||
1605 | struct task_struct *g, *p; | ||
1606 | unsigned int i; | ||
1607 | |||
1608 | info->size = 0; | ||
1609 | info->thread = NULL; | ||
1610 | |||
1611 | psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); | ||
1612 | fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); | ||
1613 | |||
1614 | if (psinfo == NULL) | ||
1615 | return 0; | ||
1616 | |||
1617 | /* | ||
1618 | * Figure out how many notes we're going to need for each thread. | ||
1619 | */ | ||
1620 | info->thread_notes = 0; | ||
1621 | for (i = 0; i < view->n; ++i) | ||
1622 | if (view->regsets[i].core_note_type != 0) | ||
1623 | ++info->thread_notes; | ||
1624 | |||
1625 | /* | ||
1626 | * Sanity check. We rely on regset 0 being in NT_PRSTATUS, | ||
1627 | * since it is our one special case. | ||
1628 | */ | ||
1629 | if (unlikely(info->thread_notes == 0) || | ||
1630 | unlikely(view->regsets[0].core_note_type != NT_PRSTATUS)) { | ||
1631 | WARN_ON(1); | ||
1632 | return 0; | ||
1633 | } | ||
1634 | |||
1635 | /* | ||
1636 | * Initialize the ELF file header. | ||
1637 | */ | ||
1638 | fill_elf_header(elf, phdrs, | ||
1639 | view->e_machine, view->e_flags, view->ei_osabi); | ||
1640 | |||
1641 | /* | ||
1642 | * Allocate a structure for each thread. | ||
1643 | */ | ||
1644 | rcu_read_lock(); | ||
1645 | do_each_thread(g, p) | ||
1646 | if (p->mm == dump_task->mm) { | ||
1647 | t = kzalloc(offsetof(struct elf_thread_core_info, | ||
1648 | notes[info->thread_notes]), | ||
1649 | GFP_ATOMIC); | ||
1650 | if (unlikely(!t)) { | ||
1651 | rcu_read_unlock(); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | t->task = p; | ||
1655 | if (p == dump_task || !info->thread) { | ||
1656 | t->next = info->thread; | ||
1657 | info->thread = t; | ||
1658 | } else { | ||
1659 | /* | ||
1660 | * Make sure to keep the original task at | ||
1661 | * the head of the list. | ||
1662 | */ | ||
1663 | t->next = info->thread->next; | ||
1664 | info->thread->next = t; | ||
1665 | } | ||
1666 | } | ||
1667 | while_each_thread(g, p); | ||
1668 | rcu_read_unlock(); | ||
1669 | |||
1670 | /* | ||
1671 | * Now fill in each thread's information. | ||
1672 | */ | ||
1673 | for (t = info->thread; t != NULL; t = t->next) | ||
1674 | if (!fill_thread_core_info(t, view, signr, &info->size)) | ||
1675 | return 0; | ||
1676 | |||
1677 | /* | ||
1678 | * Fill in the two process-wide notes. | ||
1679 | */ | ||
1680 | fill_psinfo(psinfo, dump_task->group_leader, dump_task->mm); | ||
1681 | info->size += notesize(&info->psinfo); | ||
1682 | |||
1683 | fill_auxv_note(&info->auxv, current->mm); | ||
1684 | info->size += notesize(&info->auxv); | ||
1685 | |||
1686 | return 1; | ||
1687 | } | ||
1688 | |||
1689 | static size_t get_note_info_size(struct elf_note_info *info) | ||
1690 | { | ||
1691 | return info->size; | ||
1692 | } | ||
1693 | |||
1694 | /* | ||
1695 | * Write all the notes for each thread. When writing the first thread, the | ||
1696 | * process-wide notes are interleaved after the first thread-specific note. | ||
1697 | */ | ||
1698 | static int write_note_info(struct elf_note_info *info, | ||
1699 | struct file *file, loff_t *foffset) | ||
1700 | { | ||
1701 | bool first = 1; | ||
1702 | struct elf_thread_core_info *t = info->thread; | ||
1703 | |||
1704 | do { | ||
1705 | int i; | ||
1706 | |||
1707 | if (!writenote(&t->notes[0], file, foffset)) | ||
1708 | return 0; | ||
1709 | |||
1710 | if (first && !writenote(&info->psinfo, file, foffset)) | ||
1711 | return 0; | ||
1712 | if (first && !writenote(&info->auxv, file, foffset)) | ||
1713 | return 0; | ||
1714 | |||
1715 | for (i = 1; i < info->thread_notes; ++i) | ||
1716 | if (t->notes[i].data && | ||
1717 | !writenote(&t->notes[i], file, foffset)) | ||
1718 | return 0; | ||
1719 | |||
1720 | first = 0; | ||
1721 | t = t->next; | ||
1722 | } while (t); | ||
1723 | |||
1724 | return 1; | ||
1725 | } | ||
1726 | |||
1727 | static void free_note_info(struct elf_note_info *info) | ||
1728 | { | ||
1729 | struct elf_thread_core_info *threads = info->thread; | ||
1730 | while (threads) { | ||
1731 | unsigned int i; | ||
1732 | struct elf_thread_core_info *t = threads; | ||
1733 | threads = t->next; | ||
1734 | WARN_ON(t->notes[0].data && t->notes[0].data != &t->prstatus); | ||
1735 | for (i = 1; i < info->thread_notes; ++i) | ||
1736 | kfree(t->notes[i].data); | ||
1737 | kfree(t); | ||
1738 | } | ||
1739 | kfree(info->psinfo.data); | ||
1740 | } | ||
1741 | |||
1742 | #else | ||
1743 | |||
1450 | /* Here is the structure in which status of each thread is captured. */ | 1744 | /* Here is the structure in which status of each thread is captured. */ |
1451 | struct elf_thread_status | 1745 | struct elf_thread_status |
1452 | { | 1746 | { |
@@ -1499,6 +1793,176 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
1499 | return sz; | 1793 | return sz; |
1500 | } | 1794 | } |
1501 | 1795 | ||
1796 | struct elf_note_info { | ||
1797 | struct memelfnote *notes; | ||
1798 | struct elf_prstatus *prstatus; /* NT_PRSTATUS */ | ||
1799 | struct elf_prpsinfo *psinfo; /* NT_PRPSINFO */ | ||
1800 | struct list_head thread_list; | ||
1801 | elf_fpregset_t *fpu; | ||
1802 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1803 | elf_fpxregset_t *xfpu; | ||
1804 | #endif | ||
1805 | int thread_status_size; | ||
1806 | int numnote; | ||
1807 | }; | ||
1808 | |||
1809 | static int fill_note_info(struct elfhdr *elf, int phdrs, | ||
1810 | struct elf_note_info *info, | ||
1811 | long signr, struct pt_regs *regs) | ||
1812 | { | ||
1813 | #define NUM_NOTES 6 | ||
1814 | struct list_head *t; | ||
1815 | struct task_struct *g, *p; | ||
1816 | |||
1817 | info->notes = NULL; | ||
1818 | info->prstatus = NULL; | ||
1819 | info->psinfo = NULL; | ||
1820 | info->fpu = NULL; | ||
1821 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1822 | info->xfpu = NULL; | ||
1823 | #endif | ||
1824 | INIT_LIST_HEAD(&info->thread_list); | ||
1825 | |||
1826 | info->notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), | ||
1827 | GFP_KERNEL); | ||
1828 | if (!info->notes) | ||
1829 | return 0; | ||
1830 | info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); | ||
1831 | if (!info->psinfo) | ||
1832 | return 0; | ||
1833 | info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); | ||
1834 | if (!info->prstatus) | ||
1835 | return 0; | ||
1836 | info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); | ||
1837 | if (!info->fpu) | ||
1838 | return 0; | ||
1839 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1840 | info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); | ||
1841 | if (!info->xfpu) | ||
1842 | return 0; | ||
1843 | #endif | ||
1844 | |||
1845 | info->thread_status_size = 0; | ||
1846 | if (signr) { | ||
1847 | struct elf_thread_status *tmp; | ||
1848 | rcu_read_lock(); | ||
1849 | do_each_thread(g, p) | ||
1850 | if (current->mm == p->mm && current != p) { | ||
1851 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); | ||
1852 | if (!tmp) { | ||
1853 | rcu_read_unlock(); | ||
1854 | return 0; | ||
1855 | } | ||
1856 | tmp->thread = p; | ||
1857 | list_add(&tmp->list, &info->thread_list); | ||
1858 | } | ||
1859 | while_each_thread(g, p); | ||
1860 | rcu_read_unlock(); | ||
1861 | list_for_each(t, &info->thread_list) { | ||
1862 | struct elf_thread_status *tmp; | ||
1863 | int sz; | ||
1864 | |||
1865 | tmp = list_entry(t, struct elf_thread_status, list); | ||
1866 | sz = elf_dump_thread_status(signr, tmp); | ||
1867 | info->thread_status_size += sz; | ||
1868 | } | ||
1869 | } | ||
1870 | /* now collect the dump for the current */ | ||
1871 | memset(info->prstatus, 0, sizeof(*info->prstatus)); | ||
1872 | fill_prstatus(info->prstatus, current, signr); | ||
1873 | elf_core_copy_regs(&info->prstatus->pr_reg, regs); | ||
1874 | |||
1875 | /* Set up header */ | ||
1876 | fill_elf_header(elf, phdrs, ELF_ARCH, ELF_CORE_EFLAGS, ELF_OSABI); | ||
1877 | |||
1878 | /* | ||
1879 | * Set up the notes in similar form to SVR4 core dumps made | ||
1880 | * with info from their /proc. | ||
1881 | */ | ||
1882 | |||
1883 | fill_note(info->notes + 0, "CORE", NT_PRSTATUS, | ||
1884 | sizeof(*info->prstatus), info->prstatus); | ||
1885 | fill_psinfo(info->psinfo, current->group_leader, current->mm); | ||
1886 | fill_note(info->notes + 1, "CORE", NT_PRPSINFO, | ||
1887 | sizeof(*info->psinfo), info->psinfo); | ||
1888 | |||
1889 | info->numnote = 2; | ||
1890 | |||
1891 | fill_auxv_note(&info->notes[info->numnote++], current->mm); | ||
1892 | |||
1893 | /* Try to dump the FPU. */ | ||
1894 | info->prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, | ||
1895 | info->fpu); | ||
1896 | if (info->prstatus->pr_fpvalid) | ||
1897 | fill_note(info->notes + info->numnote++, | ||
1898 | "CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu); | ||
1899 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1900 | if (elf_core_copy_task_xfpregs(current, info->xfpu)) | ||
1901 | fill_note(info->notes + info->numnote++, | ||
1902 | "LINUX", ELF_CORE_XFPREG_TYPE, | ||
1903 | sizeof(*info->xfpu), info->xfpu); | ||
1904 | #endif | ||
1905 | |||
1906 | return 1; | ||
1907 | |||
1908 | #undef NUM_NOTES | ||
1909 | } | ||
1910 | |||
1911 | static size_t get_note_info_size(struct elf_note_info *info) | ||
1912 | { | ||
1913 | int sz = 0; | ||
1914 | int i; | ||
1915 | |||
1916 | for (i = 0; i < info->numnote; i++) | ||
1917 | sz += notesize(info->notes + i); | ||
1918 | |||
1919 | sz += info->thread_status_size; | ||
1920 | |||
1921 | return sz; | ||
1922 | } | ||
1923 | |||
1924 | static int write_note_info(struct elf_note_info *info, | ||
1925 | struct file *file, loff_t *foffset) | ||
1926 | { | ||
1927 | int i; | ||
1928 | struct list_head *t; | ||
1929 | |||
1930 | for (i = 0; i < info->numnote; i++) | ||
1931 | if (!writenote(info->notes + i, file, foffset)) | ||
1932 | return 0; | ||
1933 | |||
1934 | /* write out the thread status notes section */ | ||
1935 | list_for_each(t, &info->thread_list) { | ||
1936 | struct elf_thread_status *tmp = | ||
1937 | list_entry(t, struct elf_thread_status, list); | ||
1938 | |||
1939 | for (i = 0; i < tmp->num_notes; i++) | ||
1940 | if (!writenote(&tmp->notes[i], file, foffset)) | ||
1941 | return 0; | ||
1942 | } | ||
1943 | |||
1944 | return 1; | ||
1945 | } | ||
1946 | |||
1947 | static void free_note_info(struct elf_note_info *info) | ||
1948 | { | ||
1949 | while (!list_empty(&info->thread_list)) { | ||
1950 | struct list_head *tmp = info->thread_list.next; | ||
1951 | list_del(tmp); | ||
1952 | kfree(list_entry(tmp, struct elf_thread_status, list)); | ||
1953 | } | ||
1954 | |||
1955 | kfree(info->prstatus); | ||
1956 | kfree(info->psinfo); | ||
1957 | kfree(info->notes); | ||
1958 | kfree(info->fpu); | ||
1959 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1960 | kfree(info->xfpu); | ||
1961 | #endif | ||
1962 | } | ||
1963 | |||
1964 | #endif | ||
1965 | |||
1502 | static struct vm_area_struct *first_vma(struct task_struct *tsk, | 1966 | static struct vm_area_struct *first_vma(struct task_struct *tsk, |
1503 | struct vm_area_struct *gate_vma) | 1967 | struct vm_area_struct *gate_vma) |
1504 | { | 1968 | { |
@@ -1534,29 +1998,15 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma, | |||
1534 | */ | 1998 | */ |
1535 | static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit) | 1999 | static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit) |
1536 | { | 2000 | { |
1537 | #define NUM_NOTES 6 | ||
1538 | int has_dumped = 0; | 2001 | int has_dumped = 0; |
1539 | mm_segment_t fs; | 2002 | mm_segment_t fs; |
1540 | int segs; | 2003 | int segs; |
1541 | size_t size = 0; | 2004 | size_t size = 0; |
1542 | int i; | ||
1543 | struct vm_area_struct *vma, *gate_vma; | 2005 | struct vm_area_struct *vma, *gate_vma; |
1544 | struct elfhdr *elf = NULL; | 2006 | struct elfhdr *elf = NULL; |
1545 | loff_t offset = 0, dataoff, foffset; | 2007 | loff_t offset = 0, dataoff, foffset; |
1546 | int numnote; | ||
1547 | struct memelfnote *notes = NULL; | ||
1548 | struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ | ||
1549 | struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */ | ||
1550 | struct task_struct *g, *p; | ||
1551 | LIST_HEAD(thread_list); | ||
1552 | struct list_head *t; | ||
1553 | elf_fpregset_t *fpu = NULL; | ||
1554 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1555 | elf_fpxregset_t *xfpu = NULL; | ||
1556 | #endif | ||
1557 | int thread_status_size = 0; | ||
1558 | elf_addr_t *auxv; | ||
1559 | unsigned long mm_flags; | 2008 | unsigned long mm_flags; |
2009 | struct elf_note_info info; | ||
1560 | 2010 | ||
1561 | /* | 2011 | /* |
1562 | * We no longer stop all VM operations. | 2012 | * We no longer stop all VM operations. |
@@ -1574,52 +2024,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un | |||
1574 | elf = kmalloc(sizeof(*elf), GFP_KERNEL); | 2024 | elf = kmalloc(sizeof(*elf), GFP_KERNEL); |
1575 | if (!elf) | 2025 | if (!elf) |
1576 | goto cleanup; | 2026 | goto cleanup; |
1577 | prstatus = kmalloc(sizeof(*prstatus), GFP_KERNEL); | ||
1578 | if (!prstatus) | ||
1579 | goto cleanup; | ||
1580 | psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); | ||
1581 | if (!psinfo) | ||
1582 | goto cleanup; | ||
1583 | notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL); | ||
1584 | if (!notes) | ||
1585 | goto cleanup; | ||
1586 | fpu = kmalloc(sizeof(*fpu), GFP_KERNEL); | ||
1587 | if (!fpu) | ||
1588 | goto cleanup; | ||
1589 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1590 | xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL); | ||
1591 | if (!xfpu) | ||
1592 | goto cleanup; | ||
1593 | #endif | ||
1594 | |||
1595 | if (signr) { | ||
1596 | struct elf_thread_status *tmp; | ||
1597 | rcu_read_lock(); | ||
1598 | do_each_thread(g,p) | ||
1599 | if (current->mm == p->mm && current != p) { | ||
1600 | tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC); | ||
1601 | if (!tmp) { | ||
1602 | rcu_read_unlock(); | ||
1603 | goto cleanup; | ||
1604 | } | ||
1605 | tmp->thread = p; | ||
1606 | list_add(&tmp->list, &thread_list); | ||
1607 | } | ||
1608 | while_each_thread(g,p); | ||
1609 | rcu_read_unlock(); | ||
1610 | list_for_each(t, &thread_list) { | ||
1611 | struct elf_thread_status *tmp; | ||
1612 | int sz; | ||
1613 | |||
1614 | tmp = list_entry(t, struct elf_thread_status, list); | ||
1615 | sz = elf_dump_thread_status(signr, tmp); | ||
1616 | thread_status_size += sz; | ||
1617 | } | ||
1618 | } | ||
1619 | /* now collect the dump for the current */ | ||
1620 | memset(prstatus, 0, sizeof(*prstatus)); | ||
1621 | fill_prstatus(prstatus, current, signr); | ||
1622 | elf_core_copy_regs(&prstatus->pr_reg, regs); | ||
1623 | 2027 | ||
1624 | segs = current->mm->map_count; | 2028 | segs = current->mm->map_count; |
1625 | #ifdef ELF_CORE_EXTRA_PHDRS | 2029 | #ifdef ELF_CORE_EXTRA_PHDRS |
@@ -1630,42 +2034,16 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un | |||
1630 | if (gate_vma != NULL) | 2034 | if (gate_vma != NULL) |
1631 | segs++; | 2035 | segs++; |
1632 | 2036 | ||
1633 | /* Set up header */ | ||
1634 | fill_elf_header(elf, segs + 1); /* including notes section */ | ||
1635 | |||
1636 | has_dumped = 1; | ||
1637 | current->flags |= PF_DUMPCORE; | ||
1638 | |||
1639 | /* | 2037 | /* |
1640 | * Set up the notes in similar form to SVR4 core dumps made | 2038 | * Collect all the non-memory information about the process for the |
1641 | * with info from their /proc. | 2039 | * notes. This also sets up the file header. |
1642 | */ | 2040 | */ |
2041 | if (!fill_note_info(elf, segs + 1, /* including notes section */ | ||
2042 | &info, signr, regs)) | ||
2043 | goto cleanup; | ||
1643 | 2044 | ||
1644 | fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); | 2045 | has_dumped = 1; |
1645 | fill_psinfo(psinfo, current->group_leader, current->mm); | 2046 | current->flags |= PF_DUMPCORE; |
1646 | fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); | ||
1647 | |||
1648 | numnote = 2; | ||
1649 | |||
1650 | auxv = (elf_addr_t *)current->mm->saved_auxv; | ||
1651 | |||
1652 | i = 0; | ||
1653 | do | ||
1654 | i += 2; | ||
1655 | while (auxv[i - 2] != AT_NULL); | ||
1656 | fill_note(¬es[numnote++], "CORE", NT_AUXV, | ||
1657 | i * sizeof(elf_addr_t), auxv); | ||
1658 | |||
1659 | /* Try to dump the FPU. */ | ||
1660 | if ((prstatus->pr_fpvalid = | ||
1661 | elf_core_copy_task_fpregs(current, regs, fpu))) | ||
1662 | fill_note(notes + numnote++, | ||
1663 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); | ||
1664 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1665 | if (elf_core_copy_task_xfpregs(current, xfpu)) | ||
1666 | fill_note(notes + numnote++, | ||
1667 | "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu); | ||
1668 | #endif | ||
1669 | 2047 | ||
1670 | fs = get_fs(); | 2048 | fs = get_fs(); |
1671 | set_fs(KERNEL_DS); | 2049 | set_fs(KERNEL_DS); |
@@ -1678,12 +2056,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un | |||
1678 | /* Write notes phdr entry */ | 2056 | /* Write notes phdr entry */ |
1679 | { | 2057 | { |
1680 | struct elf_phdr phdr; | 2058 | struct elf_phdr phdr; |
1681 | int sz = 0; | 2059 | size_t sz = get_note_info_size(&info); |
1682 | |||
1683 | for (i = 0; i < numnote; i++) | ||
1684 | sz += notesize(notes + i); | ||
1685 | |||
1686 | sz += thread_status_size; | ||
1687 | 2060 | ||
1688 | sz += elf_coredump_extra_notes_size(); | 2061 | sz += elf_coredump_extra_notes_size(); |
1689 | 2062 | ||
@@ -1728,23 +2101,12 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un | |||
1728 | #endif | 2101 | #endif |
1729 | 2102 | ||
1730 | /* write out the notes section */ | 2103 | /* write out the notes section */ |
1731 | for (i = 0; i < numnote; i++) | 2104 | if (!write_note_info(&info, file, &foffset)) |
1732 | if (!writenote(notes + i, file, &foffset)) | 2105 | goto end_coredump; |
1733 | goto end_coredump; | ||
1734 | 2106 | ||
1735 | if (elf_coredump_extra_notes_write(file, &foffset)) | 2107 | if (elf_coredump_extra_notes_write(file, &foffset)) |
1736 | goto end_coredump; | 2108 | goto end_coredump; |
1737 | 2109 | ||
1738 | /* write out the thread status notes section */ | ||
1739 | list_for_each(t, &thread_list) { | ||
1740 | struct elf_thread_status *tmp = | ||
1741 | list_entry(t, struct elf_thread_status, list); | ||
1742 | |||
1743 | for (i = 0; i < tmp->num_notes; i++) | ||
1744 | if (!writenote(&tmp->notes[i], file, &foffset)) | ||
1745 | goto end_coredump; | ||
1746 | } | ||
1747 | |||
1748 | /* Align to page */ | 2110 | /* Align to page */ |
1749 | DUMP_SEEK(dataoff - foffset); | 2111 | DUMP_SEEK(dataoff - foffset); |
1750 | 2112 | ||
@@ -1795,22 +2157,9 @@ end_coredump: | |||
1795 | set_fs(fs); | 2157 | set_fs(fs); |
1796 | 2158 | ||
1797 | cleanup: | 2159 | cleanup: |
1798 | while (!list_empty(&thread_list)) { | ||
1799 | struct list_head *tmp = thread_list.next; | ||
1800 | list_del(tmp); | ||
1801 | kfree(list_entry(tmp, struct elf_thread_status, list)); | ||
1802 | } | ||
1803 | |||
1804 | kfree(elf); | 2160 | kfree(elf); |
1805 | kfree(prstatus); | 2161 | free_note_info(&info); |
1806 | kfree(psinfo); | ||
1807 | kfree(notes); | ||
1808 | kfree(fpu); | ||
1809 | #ifdef ELF_CORE_COPY_XFPREGS | ||
1810 | kfree(xfpu); | ||
1811 | #endif | ||
1812 | return has_dumped; | 2162 | return has_dumped; |
1813 | #undef NUM_NOTES | ||
1814 | } | 2163 | } |
1815 | 2164 | ||
1816 | #endif /* USE_ELF_CORE_DUMP */ | 2165 | #endif /* USE_ELF_CORE_DUMP */ |
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c new file mode 100644 index 000000000000..0adced2f296f --- /dev/null +++ b/fs/compat_binfmt_elf.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * 32-bit compatibility support for ELF format executables and core dumps. | ||
3 | * | ||
4 | * Copyright (C) 2007 Red Hat, Inc. All rights reserved. | ||
5 | * | ||
6 | * This copyrighted material is made available to anyone wishing to use, | ||
7 | * modify, copy, or redistribute it subject to the terms and conditions | ||
8 | * of the GNU General Public License v.2. | ||
9 | * | ||
10 | * Red Hat Author: Roland McGrath. | ||
11 | * | ||
12 | * This file is used in a 64-bit kernel that wants to support 32-bit ELF. | ||
13 | * asm/elf.h is responsible for defining the compat_* and COMPAT_* macros | ||
14 | * used below, with definitions appropriate for 32-bit ABI compatibility. | ||
15 | * | ||
16 | * We use macros to rename the ABI types and machine-dependent | ||
17 | * functions used in binfmt_elf.c to compat versions. | ||
18 | */ | ||
19 | |||
20 | #include <linux/elfcore-compat.h> | ||
21 | #include <linux/time.h> | ||
22 | |||
23 | /* | ||
24 | * Rename the basic ELF layout types to refer to the 32-bit class of files. | ||
25 | */ | ||
26 | #undef ELF_CLASS | ||
27 | #define ELF_CLASS ELFCLASS32 | ||
28 | |||
29 | #undef elfhdr | ||
30 | #undef elf_phdr | ||
31 | #undef elf_note | ||
32 | #undef elf_addr_t | ||
33 | #define elfhdr elf32_hdr | ||
34 | #define elf_phdr elf32_phdr | ||
35 | #define elf_note elf32_note | ||
36 | #define elf_addr_t Elf32_Addr | ||
37 | |||
38 | /* | ||
39 | * The machine-dependent core note format types are defined in elfcore-compat.h, | ||
40 | * which requires asm/elf.h to define compat_elf_gregset_t et al. | ||
41 | */ | ||
42 | #define elf_prstatus compat_elf_prstatus | ||
43 | #define elf_prpsinfo compat_elf_prpsinfo | ||
44 | |||
45 | /* | ||
46 | * Compat version of cputime_to_compat_timeval, perhaps this | ||
47 | * should be an inline in <linux/compat.h>. | ||
48 | */ | ||
49 | static void cputime_to_compat_timeval(const cputime_t cputime, | ||
50 | struct compat_timeval *value) | ||
51 | { | ||
52 | struct timeval tv; | ||
53 | cputime_to_timeval(cputime, &tv); | ||
54 | value->tv_sec = tv.tv_sec; | ||
55 | value->tv_usec = tv.tv_usec; | ||
56 | } | ||
57 | |||
58 | #undef cputime_to_timeval | ||
59 | #define cputime_to_timeval cputime_to_compat_timeval | ||
60 | |||
61 | |||
62 | /* | ||
63 | * To use this file, asm/elf.h must define compat_elf_check_arch. | ||
64 | * The other following macros can be defined if the compat versions | ||
65 | * differ from the native ones, or omitted when they match. | ||
66 | */ | ||
67 | |||
68 | #undef ELF_ARCH | ||
69 | #undef elf_check_arch | ||
70 | #define elf_check_arch compat_elf_check_arch | ||
71 | |||
72 | #ifdef COMPAT_ELF_PLATFORM | ||
73 | #undef ELF_PLATFORM | ||
74 | #define ELF_PLATFORM COMPAT_ELF_PLATFORM | ||
75 | #endif | ||
76 | |||
77 | #ifdef COMPAT_ELF_HWCAP | ||
78 | #undef ELF_HWCAP | ||
79 | #define ELF_HWCAP COMPAT_ELF_HWCAP | ||
80 | #endif | ||
81 | |||
82 | #ifdef COMPAT_ARCH_DLINFO | ||
83 | #undef ARCH_DLINFO | ||
84 | #define ARCH_DLINFO COMPAT_ARCH_DLINFO | ||
85 | #endif | ||
86 | |||
87 | #ifdef COMPAT_ELF_ET_DYN_BASE | ||
88 | #undef ELF_ET_DYN_BASE | ||
89 | #define ELF_ET_DYN_BASE COMPAT_ELF_ET_DYN_BASE | ||
90 | #endif | ||
91 | |||
92 | #ifdef COMPAT_ELF_EXEC_PAGESIZE | ||
93 | #undef ELF_EXEC_PAGESIZE | ||
94 | #define ELF_EXEC_PAGESIZE COMPAT_ELF_EXEC_PAGESIZE | ||
95 | #endif | ||
96 | |||
97 | #ifdef COMPAT_ELF_PLAT_INIT | ||
98 | #undef ELF_PLAT_INIT | ||
99 | #define ELF_PLAT_INIT COMPAT_ELF_PLAT_INIT | ||
100 | #endif | ||
101 | |||
102 | #ifdef COMPAT_SET_PERSONALITY | ||
103 | #undef SET_PERSONALITY | ||
104 | #define SET_PERSONALITY COMPAT_SET_PERSONALITY | ||
105 | #endif | ||
106 | |||
107 | #ifdef compat_start_thread | ||
108 | #undef start_thread | ||
109 | #define start_thread compat_start_thread | ||
110 | #endif | ||
111 | |||
112 | #ifdef compat_arch_setup_additional_pages | ||
113 | #undef ARCH_HAS_SETUP_ADDITIONAL_PAGES | ||
114 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 | ||
115 | #undef arch_setup_additional_pages | ||
116 | #define arch_setup_additional_pages compat_arch_setup_additional_pages | ||
117 | #endif | ||
118 | |||
119 | /* | ||
120 | * Rename a few of the symbols that binfmt_elf.c will define. | ||
121 | * These are all local so the names don't really matter, but it | ||
122 | * might make some debugging less confusing not to duplicate them. | ||
123 | */ | ||
124 | #define elf_format compat_elf_format | ||
125 | #define init_elf_binfmt init_compat_elf_binfmt | ||
126 | #define exit_elf_binfmt exit_compat_elf_binfmt | ||
127 | |||
128 | /* | ||
129 | * We share all the actual code with the native (64-bit) version. | ||
130 | */ | ||
131 | #include "binfmt_elf.c" | ||
diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c index 46754553fdcc..ff97ba924333 100644 --- a/fs/dlm/dir.c +++ b/fs/dlm/dir.c | |||
@@ -49,7 +49,7 @@ static struct dlm_direntry *get_free_de(struct dlm_ls *ls, int len) | |||
49 | spin_unlock(&ls->ls_recover_list_lock); | 49 | spin_unlock(&ls->ls_recover_list_lock); |
50 | 50 | ||
51 | if (!found) | 51 | if (!found) |
52 | de = allocate_direntry(ls, len); | 52 | de = kzalloc(sizeof(struct dlm_direntry) + len, GFP_KERNEL); |
53 | return de; | 53 | return de; |
54 | } | 54 | } |
55 | 55 | ||
@@ -62,7 +62,7 @@ void dlm_clear_free_entries(struct dlm_ls *ls) | |||
62 | de = list_entry(ls->ls_recover_list.next, struct dlm_direntry, | 62 | de = list_entry(ls->ls_recover_list.next, struct dlm_direntry, |
63 | list); | 63 | list); |
64 | list_del(&de->list); | 64 | list_del(&de->list); |
65 | free_direntry(de); | 65 | kfree(de); |
66 | } | 66 | } |
67 | spin_unlock(&ls->ls_recover_list_lock); | 67 | spin_unlock(&ls->ls_recover_list_lock); |
68 | } | 68 | } |
@@ -171,7 +171,7 @@ void dlm_dir_remove_entry(struct dlm_ls *ls, int nodeid, char *name, int namelen | |||
171 | } | 171 | } |
172 | 172 | ||
173 | list_del(&de->list); | 173 | list_del(&de->list); |
174 | free_direntry(de); | 174 | kfree(de); |
175 | out: | 175 | out: |
176 | write_unlock(&ls->ls_dirtbl[bucket].lock); | 176 | write_unlock(&ls->ls_dirtbl[bucket].lock); |
177 | } | 177 | } |
@@ -302,7 +302,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, | |||
302 | 302 | ||
303 | write_unlock(&ls->ls_dirtbl[bucket].lock); | 303 | write_unlock(&ls->ls_dirtbl[bucket].lock); |
304 | 304 | ||
305 | de = allocate_direntry(ls, namelen); | 305 | de = kzalloc(sizeof(struct dlm_direntry) + namelen, GFP_KERNEL); |
306 | if (!de) | 306 | if (!de) |
307 | return -ENOMEM; | 307 | return -ENOMEM; |
308 | 308 | ||
@@ -313,7 +313,7 @@ static int get_entry(struct dlm_ls *ls, int nodeid, char *name, | |||
313 | write_lock(&ls->ls_dirtbl[bucket].lock); | 313 | write_lock(&ls->ls_dirtbl[bucket].lock); |
314 | tmp = search_bucket(ls, name, namelen, bucket); | 314 | tmp = search_bucket(ls, name, namelen, bucket); |
315 | if (tmp) { | 315 | if (tmp) { |
316 | free_direntry(de); | 316 | kfree(de); |
317 | de = tmp; | 317 | de = tmp; |
318 | } else { | 318 | } else { |
319 | list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list); | 319 | list_add_tail(&de->list, &ls->ls_dirtbl[bucket].list); |
@@ -329,49 +329,47 @@ int dlm_dir_lookup(struct dlm_ls *ls, int nodeid, char *name, int namelen, | |||
329 | return get_entry(ls, nodeid, name, namelen, r_nodeid); | 329 | return get_entry(ls, nodeid, name, namelen, r_nodeid); |
330 | } | 330 | } |
331 | 331 | ||
332 | /* Copy the names of master rsb's into the buffer provided. | 332 | static struct dlm_rsb *find_rsb_root(struct dlm_ls *ls, char *name, int len) |
333 | Only select names whose dir node is the given nodeid. */ | 333 | { |
334 | struct dlm_rsb *r; | ||
335 | |||
336 | down_read(&ls->ls_root_sem); | ||
337 | list_for_each_entry(r, &ls->ls_root_list, res_root_list) { | ||
338 | if (len == r->res_length && !memcmp(name, r->res_name, len)) { | ||
339 | up_read(&ls->ls_root_sem); | ||
340 | return r; | ||
341 | } | ||
342 | } | ||
343 | up_read(&ls->ls_root_sem); | ||
344 | return NULL; | ||
345 | } | ||
346 | |||
347 | /* Find the rsb where we left off (or start again), then send rsb names | ||
348 | for rsb's we're master of and whose directory node matches the requesting | ||
349 | node. inbuf is the rsb name last sent, inlen is the name's length */ | ||
334 | 350 | ||
335 | void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen, | 351 | void dlm_copy_master_names(struct dlm_ls *ls, char *inbuf, int inlen, |
336 | char *outbuf, int outlen, int nodeid) | 352 | char *outbuf, int outlen, int nodeid) |
337 | { | 353 | { |
338 | struct list_head *list; | 354 | struct list_head *list; |
339 | struct dlm_rsb *start_r = NULL, *r = NULL; | 355 | struct dlm_rsb *r; |
340 | int offset = 0, start_namelen, error, dir_nodeid; | 356 | int offset = 0, dir_nodeid; |
341 | char *start_name; | ||
342 | uint16_t be_namelen; | 357 | uint16_t be_namelen; |
343 | 358 | ||
344 | /* | ||
345 | * Find the rsb where we left off (or start again) | ||
346 | */ | ||
347 | |||
348 | start_namelen = inlen; | ||
349 | start_name = inbuf; | ||
350 | |||
351 | if (start_namelen > 1) { | ||
352 | /* | ||
353 | * We could also use a find_rsb_root() function here that | ||
354 | * searched the ls_root_list. | ||
355 | */ | ||
356 | error = dlm_find_rsb(ls, start_name, start_namelen, R_MASTER, | ||
357 | &start_r); | ||
358 | DLM_ASSERT(!error && start_r, | ||
359 | printk("error %d\n", error);); | ||
360 | DLM_ASSERT(!list_empty(&start_r->res_root_list), | ||
361 | dlm_print_rsb(start_r);); | ||
362 | dlm_put_rsb(start_r); | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * Send rsb names for rsb's we're master of and whose directory node | ||
367 | * matches the requesting node. | ||
368 | */ | ||
369 | |||
370 | down_read(&ls->ls_root_sem); | 359 | down_read(&ls->ls_root_sem); |
371 | if (start_r) | 360 | |
372 | list = start_r->res_root_list.next; | 361 | if (inlen > 1) { |
373 | else | 362 | r = find_rsb_root(ls, inbuf, inlen); |
363 | if (!r) { | ||
364 | inbuf[inlen - 1] = '\0'; | ||
365 | log_error(ls, "copy_master_names from %d start %d %s", | ||
366 | nodeid, inlen, inbuf); | ||
367 | goto out; | ||
368 | } | ||
369 | list = r->res_root_list.next; | ||
370 | } else { | ||
374 | list = ls->ls_root_list.next; | 371 | list = ls->ls_root_list.next; |
372 | } | ||
375 | 373 | ||
376 | for (offset = 0; list != &ls->ls_root_list; list = list->next) { | 374 | for (offset = 0; list != &ls->ls_root_list; list = list->next) { |
377 | r = list_entry(list, struct dlm_rsb, res_root_list); | 375 | r = list_entry(list, struct dlm_rsb, res_root_list); |
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h index d2fc2384c3be..ec61bbaf25df 100644 --- a/fs/dlm/dlm_internal.h +++ b/fs/dlm/dlm_internal.h | |||
@@ -570,5 +570,21 @@ static inline int dlm_no_directory(struct dlm_ls *ls) | |||
570 | return (ls->ls_exflags & DLM_LSFL_NODIR) ? 1 : 0; | 570 | return (ls->ls_exflags & DLM_LSFL_NODIR) ? 1 : 0; |
571 | } | 571 | } |
572 | 572 | ||
573 | int dlm_netlink_init(void); | ||
574 | void dlm_netlink_exit(void); | ||
575 | void dlm_timeout_warn(struct dlm_lkb *lkb); | ||
576 | |||
577 | #ifdef CONFIG_DLM_DEBUG | ||
578 | int dlm_register_debugfs(void); | ||
579 | void dlm_unregister_debugfs(void); | ||
580 | int dlm_create_debug_file(struct dlm_ls *ls); | ||
581 | void dlm_delete_debug_file(struct dlm_ls *ls); | ||
582 | #else | ||
583 | static inline int dlm_register_debugfs(void) { return 0; } | ||
584 | static inline void dlm_unregister_debugfs(void) { } | ||
585 | static inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; } | ||
586 | static inline void dlm_delete_debug_file(struct dlm_ls *ls) { } | ||
587 | #endif | ||
588 | |||
573 | #endif /* __DLM_INTERNAL_DOT_H__ */ | 589 | #endif /* __DLM_INTERNAL_DOT_H__ */ |
574 | 590 | ||
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 3915b8e14146..ff4a198fa677 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -88,7 +88,6 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, | |||
88 | static int receive_extralen(struct dlm_message *ms); | 88 | static int receive_extralen(struct dlm_message *ms); |
89 | static void do_purge(struct dlm_ls *ls, int nodeid, int pid); | 89 | static void do_purge(struct dlm_ls *ls, int nodeid, int pid); |
90 | static void del_timeout(struct dlm_lkb *lkb); | 90 | static void del_timeout(struct dlm_lkb *lkb); |
91 | void dlm_timeout_warn(struct dlm_lkb *lkb); | ||
92 | 91 | ||
93 | /* | 92 | /* |
94 | * Lock compatibilty matrix - thanks Steve | 93 | * Lock compatibilty matrix - thanks Steve |
@@ -335,7 +334,7 @@ static struct dlm_rsb *create_rsb(struct dlm_ls *ls, char *name, int len) | |||
335 | { | 334 | { |
336 | struct dlm_rsb *r; | 335 | struct dlm_rsb *r; |
337 | 336 | ||
338 | r = allocate_rsb(ls, len); | 337 | r = dlm_allocate_rsb(ls, len); |
339 | if (!r) | 338 | if (!r) |
340 | return NULL; | 339 | return NULL; |
341 | 340 | ||
@@ -478,7 +477,7 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen, | |||
478 | error = _search_rsb(ls, name, namelen, bucket, 0, &tmp); | 477 | error = _search_rsb(ls, name, namelen, bucket, 0, &tmp); |
479 | if (!error) { | 478 | if (!error) { |
480 | write_unlock(&ls->ls_rsbtbl[bucket].lock); | 479 | write_unlock(&ls->ls_rsbtbl[bucket].lock); |
481 | free_rsb(r); | 480 | dlm_free_rsb(r); |
482 | r = tmp; | 481 | r = tmp; |
483 | goto out; | 482 | goto out; |
484 | } | 483 | } |
@@ -490,12 +489,6 @@ static int find_rsb(struct dlm_ls *ls, char *name, int namelen, | |||
490 | return error; | 489 | return error; |
491 | } | 490 | } |
492 | 491 | ||
493 | int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen, | ||
494 | unsigned int flags, struct dlm_rsb **r_ret) | ||
495 | { | ||
496 | return find_rsb(ls, name, namelen, flags, r_ret); | ||
497 | } | ||
498 | |||
499 | /* This is only called to add a reference when the code already holds | 492 | /* This is only called to add a reference when the code already holds |
500 | a valid reference to the rsb, so there's no need for locking. */ | 493 | a valid reference to the rsb, so there's no need for locking. */ |
501 | 494 | ||
@@ -519,7 +512,7 @@ static void toss_rsb(struct kref *kref) | |||
519 | list_move(&r->res_hashchain, &ls->ls_rsbtbl[r->res_bucket].toss); | 512 | list_move(&r->res_hashchain, &ls->ls_rsbtbl[r->res_bucket].toss); |
520 | r->res_toss_time = jiffies; | 513 | r->res_toss_time = jiffies; |
521 | if (r->res_lvbptr) { | 514 | if (r->res_lvbptr) { |
522 | free_lvb(r->res_lvbptr); | 515 | dlm_free_lvb(r->res_lvbptr); |
523 | r->res_lvbptr = NULL; | 516 | r->res_lvbptr = NULL; |
524 | } | 517 | } |
525 | } | 518 | } |
@@ -589,7 +582,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) | |||
589 | uint32_t lkid = 0; | 582 | uint32_t lkid = 0; |
590 | uint16_t bucket; | 583 | uint16_t bucket; |
591 | 584 | ||
592 | lkb = allocate_lkb(ls); | 585 | lkb = dlm_allocate_lkb(ls); |
593 | if (!lkb) | 586 | if (!lkb) |
594 | return -ENOMEM; | 587 | return -ENOMEM; |
595 | 588 | ||
@@ -683,8 +676,8 @@ static int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb) | |||
683 | 676 | ||
684 | /* for local/process lkbs, lvbptr points to caller's lksb */ | 677 | /* for local/process lkbs, lvbptr points to caller's lksb */ |
685 | if (lkb->lkb_lvbptr && is_master_copy(lkb)) | 678 | if (lkb->lkb_lvbptr && is_master_copy(lkb)) |
686 | free_lvb(lkb->lkb_lvbptr); | 679 | dlm_free_lvb(lkb->lkb_lvbptr); |
687 | free_lkb(lkb); | 680 | dlm_free_lkb(lkb); |
688 | return 1; | 681 | return 1; |
689 | } else { | 682 | } else { |
690 | write_unlock(&ls->ls_lkbtbl[bucket].lock); | 683 | write_unlock(&ls->ls_lkbtbl[bucket].lock); |
@@ -988,7 +981,7 @@ static int shrink_bucket(struct dlm_ls *ls, int b) | |||
988 | 981 | ||
989 | if (is_master(r)) | 982 | if (is_master(r)) |
990 | dir_remove(r); | 983 | dir_remove(r); |
991 | free_rsb(r); | 984 | dlm_free_rsb(r); |
992 | count++; | 985 | count++; |
993 | } else { | 986 | } else { |
994 | write_unlock(&ls->ls_rsbtbl[b].lock); | 987 | write_unlock(&ls->ls_rsbtbl[b].lock); |
@@ -1171,7 +1164,7 @@ static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1171 | return; | 1164 | return; |
1172 | 1165 | ||
1173 | if (!r->res_lvbptr) | 1166 | if (!r->res_lvbptr) |
1174 | r->res_lvbptr = allocate_lvb(r->res_ls); | 1167 | r->res_lvbptr = dlm_allocate_lvb(r->res_ls); |
1175 | 1168 | ||
1176 | if (!r->res_lvbptr) | 1169 | if (!r->res_lvbptr) |
1177 | return; | 1170 | return; |
@@ -1203,7 +1196,7 @@ static void set_lvb_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1203 | return; | 1196 | return; |
1204 | 1197 | ||
1205 | if (!r->res_lvbptr) | 1198 | if (!r->res_lvbptr) |
1206 | r->res_lvbptr = allocate_lvb(r->res_ls); | 1199 | r->res_lvbptr = dlm_allocate_lvb(r->res_ls); |
1207 | 1200 | ||
1208 | if (!r->res_lvbptr) | 1201 | if (!r->res_lvbptr) |
1209 | return; | 1202 | return; |
@@ -1852,7 +1845,7 @@ static void send_blocking_asts_all(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1852 | static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb) | 1845 | static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb) |
1853 | { | 1846 | { |
1854 | struct dlm_ls *ls = r->res_ls; | 1847 | struct dlm_ls *ls = r->res_ls; |
1855 | int error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid(); | 1848 | int i, error, dir_nodeid, ret_nodeid, our_nodeid = dlm_our_nodeid(); |
1856 | 1849 | ||
1857 | if (rsb_flag(r, RSB_MASTER_UNCERTAIN)) { | 1850 | if (rsb_flag(r, RSB_MASTER_UNCERTAIN)) { |
1858 | rsb_clear_flag(r, RSB_MASTER_UNCERTAIN); | 1851 | rsb_clear_flag(r, RSB_MASTER_UNCERTAIN); |
@@ -1886,7 +1879,7 @@ static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1886 | return 1; | 1879 | return 1; |
1887 | } | 1880 | } |
1888 | 1881 | ||
1889 | for (;;) { | 1882 | for (i = 0; i < 2; i++) { |
1890 | /* It's possible for dlm_scand to remove an old rsb for | 1883 | /* It's possible for dlm_scand to remove an old rsb for |
1891 | this same resource from the toss list, us to create | 1884 | this same resource from the toss list, us to create |
1892 | a new one, look up the master locally, and find it | 1885 | a new one, look up the master locally, and find it |
@@ -1900,6 +1893,8 @@ static int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
1900 | log_debug(ls, "dir_lookup error %d %s", error, r->res_name); | 1893 | log_debug(ls, "dir_lookup error %d %s", error, r->res_name); |
1901 | schedule(); | 1894 | schedule(); |
1902 | } | 1895 | } |
1896 | if (error && error != -EEXIST) | ||
1897 | return error; | ||
1903 | 1898 | ||
1904 | if (ret_nodeid == our_nodeid) { | 1899 | if (ret_nodeid == our_nodeid) { |
1905 | r->res_first_lkid = 0; | 1900 | r->res_first_lkid = 0; |
@@ -1941,8 +1936,11 @@ static void confirm_master(struct dlm_rsb *r, int error) | |||
1941 | break; | 1936 | break; |
1942 | 1937 | ||
1943 | case -EAGAIN: | 1938 | case -EAGAIN: |
1944 | /* the remote master didn't queue our NOQUEUE request; | 1939 | case -EBADR: |
1945 | make a waiting lkb the first_lkid */ | 1940 | case -ENOTBLK: |
1941 | /* the remote request failed and won't be retried (it was | ||
1942 | a NOQUEUE, or has been canceled/unlocked); make a waiting | ||
1943 | lkb the first_lkid */ | ||
1946 | 1944 | ||
1947 | r->res_first_lkid = 0; | 1945 | r->res_first_lkid = 0; |
1948 | 1946 | ||
@@ -2108,17 +2106,18 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) | |||
2108 | /* an lkb may be waiting for an rsb lookup to complete where the | 2106 | /* an lkb may be waiting for an rsb lookup to complete where the |
2109 | lookup was initiated by another lock */ | 2107 | lookup was initiated by another lock */ |
2110 | 2108 | ||
2111 | if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) { | 2109 | if (!list_empty(&lkb->lkb_rsb_lookup)) { |
2112 | if (!list_empty(&lkb->lkb_rsb_lookup)) { | 2110 | if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) { |
2113 | log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id); | 2111 | log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id); |
2114 | list_del_init(&lkb->lkb_rsb_lookup); | 2112 | list_del_init(&lkb->lkb_rsb_lookup); |
2115 | queue_cast(lkb->lkb_resource, lkb, | 2113 | queue_cast(lkb->lkb_resource, lkb, |
2116 | args->flags & DLM_LKF_CANCEL ? | 2114 | args->flags & DLM_LKF_CANCEL ? |
2117 | -DLM_ECANCEL : -DLM_EUNLOCK); | 2115 | -DLM_ECANCEL : -DLM_EUNLOCK); |
2118 | unhold_lkb(lkb); /* undoes create_lkb() */ | 2116 | unhold_lkb(lkb); /* undoes create_lkb() */ |
2119 | rv = -EBUSY; | ||
2120 | goto out; | ||
2121 | } | 2117 | } |
2118 | /* caller changes -EBUSY to 0 for CANCEL and FORCEUNLOCK */ | ||
2119 | rv = -EBUSY; | ||
2120 | goto out; | ||
2122 | } | 2121 | } |
2123 | 2122 | ||
2124 | /* cancel not allowed with another cancel/unlock in progress */ | 2123 | /* cancel not allowed with another cancel/unlock in progress */ |
@@ -2986,7 +2985,7 @@ static int receive_lvb(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
2986 | 2985 | ||
2987 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { | 2986 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { |
2988 | if (!lkb->lkb_lvbptr) | 2987 | if (!lkb->lkb_lvbptr) |
2989 | lkb->lkb_lvbptr = allocate_lvb(ls); | 2988 | lkb->lkb_lvbptr = dlm_allocate_lvb(ls); |
2990 | if (!lkb->lkb_lvbptr) | 2989 | if (!lkb->lkb_lvbptr) |
2991 | return -ENOMEM; | 2990 | return -ENOMEM; |
2992 | len = receive_extralen(ms); | 2991 | len = receive_extralen(ms); |
@@ -3006,11 +3005,9 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
3006 | lkb->lkb_bastaddr = (void *) (long) (ms->m_asts & AST_BAST); | 3005 | lkb->lkb_bastaddr = (void *) (long) (ms->m_asts & AST_BAST); |
3007 | lkb->lkb_astaddr = (void *) (long) (ms->m_asts & AST_COMP); | 3006 | lkb->lkb_astaddr = (void *) (long) (ms->m_asts & AST_COMP); |
3008 | 3007 | ||
3009 | DLM_ASSERT(is_master_copy(lkb), dlm_print_lkb(lkb);); | ||
3010 | |||
3011 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { | 3008 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { |
3012 | /* lkb was just created so there won't be an lvb yet */ | 3009 | /* lkb was just created so there won't be an lvb yet */ |
3013 | lkb->lkb_lvbptr = allocate_lvb(ls); | 3010 | lkb->lkb_lvbptr = dlm_allocate_lvb(ls); |
3014 | if (!lkb->lkb_lvbptr) | 3011 | if (!lkb->lkb_lvbptr) |
3015 | return -ENOMEM; | 3012 | return -ENOMEM; |
3016 | } | 3013 | } |
@@ -3021,16 +3018,6 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
3021 | static int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | 3018 | static int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb, |
3022 | struct dlm_message *ms) | 3019 | struct dlm_message *ms) |
3023 | { | 3020 | { |
3024 | if (lkb->lkb_nodeid != ms->m_header.h_nodeid) { | ||
3025 | log_error(ls, "convert_args nodeid %d %d lkid %x %x", | ||
3026 | lkb->lkb_nodeid, ms->m_header.h_nodeid, | ||
3027 | lkb->lkb_id, lkb->lkb_remid); | ||
3028 | return -EINVAL; | ||
3029 | } | ||
3030 | |||
3031 | if (!is_master_copy(lkb)) | ||
3032 | return -EINVAL; | ||
3033 | |||
3034 | if (lkb->lkb_status != DLM_LKSTS_GRANTED) | 3021 | if (lkb->lkb_status != DLM_LKSTS_GRANTED) |
3035 | return -EBUSY; | 3022 | return -EBUSY; |
3036 | 3023 | ||
@@ -3046,8 +3033,6 @@ static int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
3046 | static int receive_unlock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | 3033 | static int receive_unlock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, |
3047 | struct dlm_message *ms) | 3034 | struct dlm_message *ms) |
3048 | { | 3035 | { |
3049 | if (!is_master_copy(lkb)) | ||
3050 | return -EINVAL; | ||
3051 | if (receive_lvb(ls, lkb, ms)) | 3036 | if (receive_lvb(ls, lkb, ms)) |
3052 | return -ENOMEM; | 3037 | return -ENOMEM; |
3053 | return 0; | 3038 | return 0; |
@@ -3063,6 +3048,50 @@ static void setup_stub_lkb(struct dlm_ls *ls, struct dlm_message *ms) | |||
3063 | lkb->lkb_remid = ms->m_lkid; | 3048 | lkb->lkb_remid = ms->m_lkid; |
3064 | } | 3049 | } |
3065 | 3050 | ||
3051 | /* This is called after the rsb is locked so that we can safely inspect | ||
3052 | fields in the lkb. */ | ||
3053 | |||
3054 | static int validate_message(struct dlm_lkb *lkb, struct dlm_message *ms) | ||
3055 | { | ||
3056 | int from = ms->m_header.h_nodeid; | ||
3057 | int error = 0; | ||
3058 | |||
3059 | switch (ms->m_type) { | ||
3060 | case DLM_MSG_CONVERT: | ||
3061 | case DLM_MSG_UNLOCK: | ||
3062 | case DLM_MSG_CANCEL: | ||
3063 | if (!is_master_copy(lkb) || lkb->lkb_nodeid != from) | ||
3064 | error = -EINVAL; | ||
3065 | break; | ||
3066 | |||
3067 | case DLM_MSG_CONVERT_REPLY: | ||
3068 | case DLM_MSG_UNLOCK_REPLY: | ||
3069 | case DLM_MSG_CANCEL_REPLY: | ||
3070 | case DLM_MSG_GRANT: | ||
3071 | case DLM_MSG_BAST: | ||
3072 | if (!is_process_copy(lkb) || lkb->lkb_nodeid != from) | ||
3073 | error = -EINVAL; | ||
3074 | break; | ||
3075 | |||
3076 | case DLM_MSG_REQUEST_REPLY: | ||
3077 | if (!is_process_copy(lkb)) | ||
3078 | error = -EINVAL; | ||
3079 | else if (lkb->lkb_nodeid != -1 && lkb->lkb_nodeid != from) | ||
3080 | error = -EINVAL; | ||
3081 | break; | ||
3082 | |||
3083 | default: | ||
3084 | error = -EINVAL; | ||
3085 | } | ||
3086 | |||
3087 | if (error) | ||
3088 | log_error(lkb->lkb_resource->res_ls, | ||
3089 | "ignore invalid message %d from %d %x %x %x %d", | ||
3090 | ms->m_type, from, lkb->lkb_id, lkb->lkb_remid, | ||
3091 | lkb->lkb_flags, lkb->lkb_nodeid); | ||
3092 | return error; | ||
3093 | } | ||
3094 | |||
3066 | static void receive_request(struct dlm_ls *ls, struct dlm_message *ms) | 3095 | static void receive_request(struct dlm_ls *ls, struct dlm_message *ms) |
3067 | { | 3096 | { |
3068 | struct dlm_lkb *lkb; | 3097 | struct dlm_lkb *lkb; |
@@ -3124,17 +3153,21 @@ static void receive_convert(struct dlm_ls *ls, struct dlm_message *ms) | |||
3124 | hold_rsb(r); | 3153 | hold_rsb(r); |
3125 | lock_rsb(r); | 3154 | lock_rsb(r); |
3126 | 3155 | ||
3156 | error = validate_message(lkb, ms); | ||
3157 | if (error) | ||
3158 | goto out; | ||
3159 | |||
3127 | receive_flags(lkb, ms); | 3160 | receive_flags(lkb, ms); |
3128 | error = receive_convert_args(ls, lkb, ms); | 3161 | error = receive_convert_args(ls, lkb, ms); |
3129 | if (error) | 3162 | if (error) |
3130 | goto out; | 3163 | goto out_reply; |
3131 | reply = !down_conversion(lkb); | 3164 | reply = !down_conversion(lkb); |
3132 | 3165 | ||
3133 | error = do_convert(r, lkb); | 3166 | error = do_convert(r, lkb); |
3134 | out: | 3167 | out_reply: |
3135 | if (reply) | 3168 | if (reply) |
3136 | send_convert_reply(r, lkb, error); | 3169 | send_convert_reply(r, lkb, error); |
3137 | 3170 | out: | |
3138 | unlock_rsb(r); | 3171 | unlock_rsb(r); |
3139 | put_rsb(r); | 3172 | put_rsb(r); |
3140 | dlm_put_lkb(lkb); | 3173 | dlm_put_lkb(lkb); |
@@ -3160,15 +3193,19 @@ static void receive_unlock(struct dlm_ls *ls, struct dlm_message *ms) | |||
3160 | hold_rsb(r); | 3193 | hold_rsb(r); |
3161 | lock_rsb(r); | 3194 | lock_rsb(r); |
3162 | 3195 | ||
3196 | error = validate_message(lkb, ms); | ||
3197 | if (error) | ||
3198 | goto out; | ||
3199 | |||
3163 | receive_flags(lkb, ms); | 3200 | receive_flags(lkb, ms); |
3164 | error = receive_unlock_args(ls, lkb, ms); | 3201 | error = receive_unlock_args(ls, lkb, ms); |
3165 | if (error) | 3202 | if (error) |
3166 | goto out; | 3203 | goto out_reply; |
3167 | 3204 | ||
3168 | error = do_unlock(r, lkb); | 3205 | error = do_unlock(r, lkb); |
3169 | out: | 3206 | out_reply: |
3170 | send_unlock_reply(r, lkb, error); | 3207 | send_unlock_reply(r, lkb, error); |
3171 | 3208 | out: | |
3172 | unlock_rsb(r); | 3209 | unlock_rsb(r); |
3173 | put_rsb(r); | 3210 | put_rsb(r); |
3174 | dlm_put_lkb(lkb); | 3211 | dlm_put_lkb(lkb); |
@@ -3196,9 +3233,13 @@ static void receive_cancel(struct dlm_ls *ls, struct dlm_message *ms) | |||
3196 | hold_rsb(r); | 3233 | hold_rsb(r); |
3197 | lock_rsb(r); | 3234 | lock_rsb(r); |
3198 | 3235 | ||
3236 | error = validate_message(lkb, ms); | ||
3237 | if (error) | ||
3238 | goto out; | ||
3239 | |||
3199 | error = do_cancel(r, lkb); | 3240 | error = do_cancel(r, lkb); |
3200 | send_cancel_reply(r, lkb, error); | 3241 | send_cancel_reply(r, lkb, error); |
3201 | 3242 | out: | |
3202 | unlock_rsb(r); | 3243 | unlock_rsb(r); |
3203 | put_rsb(r); | 3244 | put_rsb(r); |
3204 | dlm_put_lkb(lkb); | 3245 | dlm_put_lkb(lkb); |
@@ -3217,22 +3258,26 @@ static void receive_grant(struct dlm_ls *ls, struct dlm_message *ms) | |||
3217 | 3258 | ||
3218 | error = find_lkb(ls, ms->m_remid, &lkb); | 3259 | error = find_lkb(ls, ms->m_remid, &lkb); |
3219 | if (error) { | 3260 | if (error) { |
3220 | log_error(ls, "receive_grant no lkb"); | 3261 | log_debug(ls, "receive_grant from %d no lkb %x", |
3262 | ms->m_header.h_nodeid, ms->m_remid); | ||
3221 | return; | 3263 | return; |
3222 | } | 3264 | } |
3223 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | ||
3224 | 3265 | ||
3225 | r = lkb->lkb_resource; | 3266 | r = lkb->lkb_resource; |
3226 | 3267 | ||
3227 | hold_rsb(r); | 3268 | hold_rsb(r); |
3228 | lock_rsb(r); | 3269 | lock_rsb(r); |
3229 | 3270 | ||
3271 | error = validate_message(lkb, ms); | ||
3272 | if (error) | ||
3273 | goto out; | ||
3274 | |||
3230 | receive_flags_reply(lkb, ms); | 3275 | receive_flags_reply(lkb, ms); |
3231 | if (is_altmode(lkb)) | 3276 | if (is_altmode(lkb)) |
3232 | munge_altmode(lkb, ms); | 3277 | munge_altmode(lkb, ms); |
3233 | grant_lock_pc(r, lkb, ms); | 3278 | grant_lock_pc(r, lkb, ms); |
3234 | queue_cast(r, lkb, 0); | 3279 | queue_cast(r, lkb, 0); |
3235 | 3280 | out: | |
3236 | unlock_rsb(r); | 3281 | unlock_rsb(r); |
3237 | put_rsb(r); | 3282 | put_rsb(r); |
3238 | dlm_put_lkb(lkb); | 3283 | dlm_put_lkb(lkb); |
@@ -3246,18 +3291,22 @@ static void receive_bast(struct dlm_ls *ls, struct dlm_message *ms) | |||
3246 | 3291 | ||
3247 | error = find_lkb(ls, ms->m_remid, &lkb); | 3292 | error = find_lkb(ls, ms->m_remid, &lkb); |
3248 | if (error) { | 3293 | if (error) { |
3249 | log_error(ls, "receive_bast no lkb"); | 3294 | log_debug(ls, "receive_bast from %d no lkb %x", |
3295 | ms->m_header.h_nodeid, ms->m_remid); | ||
3250 | return; | 3296 | return; |
3251 | } | 3297 | } |
3252 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | ||
3253 | 3298 | ||
3254 | r = lkb->lkb_resource; | 3299 | r = lkb->lkb_resource; |
3255 | 3300 | ||
3256 | hold_rsb(r); | 3301 | hold_rsb(r); |
3257 | lock_rsb(r); | 3302 | lock_rsb(r); |
3258 | 3303 | ||
3259 | queue_bast(r, lkb, ms->m_bastmode); | 3304 | error = validate_message(lkb, ms); |
3305 | if (error) | ||
3306 | goto out; | ||
3260 | 3307 | ||
3308 | queue_bast(r, lkb, ms->m_bastmode); | ||
3309 | out: | ||
3261 | unlock_rsb(r); | 3310 | unlock_rsb(r); |
3262 | put_rsb(r); | 3311 | put_rsb(r); |
3263 | dlm_put_lkb(lkb); | 3312 | dlm_put_lkb(lkb); |
@@ -3323,15 +3372,19 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3323 | 3372 | ||
3324 | error = find_lkb(ls, ms->m_remid, &lkb); | 3373 | error = find_lkb(ls, ms->m_remid, &lkb); |
3325 | if (error) { | 3374 | if (error) { |
3326 | log_error(ls, "receive_request_reply no lkb"); | 3375 | log_debug(ls, "receive_request_reply from %d no lkb %x", |
3376 | ms->m_header.h_nodeid, ms->m_remid); | ||
3327 | return; | 3377 | return; |
3328 | } | 3378 | } |
3329 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | ||
3330 | 3379 | ||
3331 | r = lkb->lkb_resource; | 3380 | r = lkb->lkb_resource; |
3332 | hold_rsb(r); | 3381 | hold_rsb(r); |
3333 | lock_rsb(r); | 3382 | lock_rsb(r); |
3334 | 3383 | ||
3384 | error = validate_message(lkb, ms); | ||
3385 | if (error) | ||
3386 | goto out; | ||
3387 | |||
3335 | mstype = lkb->lkb_wait_type; | 3388 | mstype = lkb->lkb_wait_type; |
3336 | error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY); | 3389 | error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY); |
3337 | if (error) | 3390 | if (error) |
@@ -3383,6 +3436,7 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3383 | if (is_overlap(lkb)) { | 3436 | if (is_overlap(lkb)) { |
3384 | /* we'll ignore error in cancel/unlock reply */ | 3437 | /* we'll ignore error in cancel/unlock reply */ |
3385 | queue_cast_overlap(r, lkb); | 3438 | queue_cast_overlap(r, lkb); |
3439 | confirm_master(r, result); | ||
3386 | unhold_lkb(lkb); /* undoes create_lkb() */ | 3440 | unhold_lkb(lkb); /* undoes create_lkb() */ |
3387 | } else | 3441 | } else |
3388 | _request_lock(r, lkb); | 3442 | _request_lock(r, lkb); |
@@ -3463,6 +3517,10 @@ static void _receive_convert_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | |||
3463 | hold_rsb(r); | 3517 | hold_rsb(r); |
3464 | lock_rsb(r); | 3518 | lock_rsb(r); |
3465 | 3519 | ||
3520 | error = validate_message(lkb, ms); | ||
3521 | if (error) | ||
3522 | goto out; | ||
3523 | |||
3466 | /* stub reply can happen with waiters_mutex held */ | 3524 | /* stub reply can happen with waiters_mutex held */ |
3467 | error = remove_from_waiters_ms(lkb, ms); | 3525 | error = remove_from_waiters_ms(lkb, ms); |
3468 | if (error) | 3526 | if (error) |
@@ -3481,10 +3539,10 @@ static void receive_convert_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3481 | 3539 | ||
3482 | error = find_lkb(ls, ms->m_remid, &lkb); | 3540 | error = find_lkb(ls, ms->m_remid, &lkb); |
3483 | if (error) { | 3541 | if (error) { |
3484 | log_error(ls, "receive_convert_reply no lkb"); | 3542 | log_debug(ls, "receive_convert_reply from %d no lkb %x", |
3543 | ms->m_header.h_nodeid, ms->m_remid); | ||
3485 | return; | 3544 | return; |
3486 | } | 3545 | } |
3487 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | ||
3488 | 3546 | ||
3489 | _receive_convert_reply(lkb, ms); | 3547 | _receive_convert_reply(lkb, ms); |
3490 | dlm_put_lkb(lkb); | 3548 | dlm_put_lkb(lkb); |
@@ -3498,6 +3556,10 @@ static void _receive_unlock_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | |||
3498 | hold_rsb(r); | 3556 | hold_rsb(r); |
3499 | lock_rsb(r); | 3557 | lock_rsb(r); |
3500 | 3558 | ||
3559 | error = validate_message(lkb, ms); | ||
3560 | if (error) | ||
3561 | goto out; | ||
3562 | |||
3501 | /* stub reply can happen with waiters_mutex held */ | 3563 | /* stub reply can happen with waiters_mutex held */ |
3502 | error = remove_from_waiters_ms(lkb, ms); | 3564 | error = remove_from_waiters_ms(lkb, ms); |
3503 | if (error) | 3565 | if (error) |
@@ -3529,10 +3591,10 @@ static void receive_unlock_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3529 | 3591 | ||
3530 | error = find_lkb(ls, ms->m_remid, &lkb); | 3592 | error = find_lkb(ls, ms->m_remid, &lkb); |
3531 | if (error) { | 3593 | if (error) { |
3532 | log_error(ls, "receive_unlock_reply no lkb"); | 3594 | log_debug(ls, "receive_unlock_reply from %d no lkb %x", |
3595 | ms->m_header.h_nodeid, ms->m_remid); | ||
3533 | return; | 3596 | return; |
3534 | } | 3597 | } |
3535 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | ||
3536 | 3598 | ||
3537 | _receive_unlock_reply(lkb, ms); | 3599 | _receive_unlock_reply(lkb, ms); |
3538 | dlm_put_lkb(lkb); | 3600 | dlm_put_lkb(lkb); |
@@ -3546,6 +3608,10 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms) | |||
3546 | hold_rsb(r); | 3608 | hold_rsb(r); |
3547 | lock_rsb(r); | 3609 | lock_rsb(r); |
3548 | 3610 | ||
3611 | error = validate_message(lkb, ms); | ||
3612 | if (error) | ||
3613 | goto out; | ||
3614 | |||
3549 | /* stub reply can happen with waiters_mutex held */ | 3615 | /* stub reply can happen with waiters_mutex held */ |
3550 | error = remove_from_waiters_ms(lkb, ms); | 3616 | error = remove_from_waiters_ms(lkb, ms); |
3551 | if (error) | 3617 | if (error) |
@@ -3577,10 +3643,10 @@ static void receive_cancel_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3577 | 3643 | ||
3578 | error = find_lkb(ls, ms->m_remid, &lkb); | 3644 | error = find_lkb(ls, ms->m_remid, &lkb); |
3579 | if (error) { | 3645 | if (error) { |
3580 | log_error(ls, "receive_cancel_reply no lkb"); | 3646 | log_debug(ls, "receive_cancel_reply from %d no lkb %x", |
3647 | ms->m_header.h_nodeid, ms->m_remid); | ||
3581 | return; | 3648 | return; |
3582 | } | 3649 | } |
3583 | DLM_ASSERT(is_process_copy(lkb), dlm_print_lkb(lkb);); | ||
3584 | 3650 | ||
3585 | _receive_cancel_reply(lkb, ms); | 3651 | _receive_cancel_reply(lkb, ms); |
3586 | dlm_put_lkb(lkb); | 3652 | dlm_put_lkb(lkb); |
@@ -3640,6 +3706,13 @@ static void receive_lookup_reply(struct dlm_ls *ls, struct dlm_message *ms) | |||
3640 | 3706 | ||
3641 | static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms) | 3707 | static void _receive_message(struct dlm_ls *ls, struct dlm_message *ms) |
3642 | { | 3708 | { |
3709 | if (!dlm_is_member(ls, ms->m_header.h_nodeid)) { | ||
3710 | log_debug(ls, "ignore non-member message %d from %d %x %x %d", | ||
3711 | ms->m_type, ms->m_header.h_nodeid, ms->m_lkid, | ||
3712 | ms->m_remid, ms->m_result); | ||
3713 | return; | ||
3714 | } | ||
3715 | |||
3643 | switch (ms->m_type) { | 3716 | switch (ms->m_type) { |
3644 | 3717 | ||
3645 | /* messages sent to a master node */ | 3718 | /* messages sent to a master node */ |
@@ -3778,8 +3851,9 @@ void dlm_receive_buffer(struct dlm_header *hd, int nodeid) | |||
3778 | 3851 | ||
3779 | ls = dlm_find_lockspace_global(hd->h_lockspace); | 3852 | ls = dlm_find_lockspace_global(hd->h_lockspace); |
3780 | if (!ls) { | 3853 | if (!ls) { |
3781 | log_print("invalid h_lockspace %x from %d cmd %d type %d", | 3854 | if (dlm_config.ci_log_debug) |
3782 | hd->h_lockspace, nodeid, hd->h_cmd, type); | 3855 | log_print("invalid lockspace %x from %d cmd %d type %d", |
3856 | hd->h_lockspace, nodeid, hd->h_cmd, type); | ||
3783 | 3857 | ||
3784 | if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS) | 3858 | if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS) |
3785 | dlm_send_ls_not_ready(nodeid, rc); | 3859 | dlm_send_ls_not_ready(nodeid, rc); |
@@ -3806,6 +3880,7 @@ static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb) | |||
3806 | ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY; | 3880 | ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY; |
3807 | ls->ls_stub_ms.m_result = -EINPROGRESS; | 3881 | ls->ls_stub_ms.m_result = -EINPROGRESS; |
3808 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 3882 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
3883 | ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid; | ||
3809 | _receive_convert_reply(lkb, &ls->ls_stub_ms); | 3884 | _receive_convert_reply(lkb, &ls->ls_stub_ms); |
3810 | 3885 | ||
3811 | /* Same special case as in receive_rcom_lock_args() */ | 3886 | /* Same special case as in receive_rcom_lock_args() */ |
@@ -3847,6 +3922,7 @@ static int waiter_needs_recovery(struct dlm_ls *ls, struct dlm_lkb *lkb) | |||
3847 | void dlm_recover_waiters_pre(struct dlm_ls *ls) | 3922 | void dlm_recover_waiters_pre(struct dlm_ls *ls) |
3848 | { | 3923 | { |
3849 | struct dlm_lkb *lkb, *safe; | 3924 | struct dlm_lkb *lkb, *safe; |
3925 | int wait_type, stub_unlock_result, stub_cancel_result; | ||
3850 | 3926 | ||
3851 | mutex_lock(&ls->ls_waiters_mutex); | 3927 | mutex_lock(&ls->ls_waiters_mutex); |
3852 | 3928 | ||
@@ -3865,7 +3941,33 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) | |||
3865 | if (!waiter_needs_recovery(ls, lkb)) | 3941 | if (!waiter_needs_recovery(ls, lkb)) |
3866 | continue; | 3942 | continue; |
3867 | 3943 | ||
3868 | switch (lkb->lkb_wait_type) { | 3944 | wait_type = lkb->lkb_wait_type; |
3945 | stub_unlock_result = -DLM_EUNLOCK; | ||
3946 | stub_cancel_result = -DLM_ECANCEL; | ||
3947 | |||
3948 | /* Main reply may have been received leaving a zero wait_type, | ||
3949 | but a reply for the overlapping op may not have been | ||
3950 | received. In that case we need to fake the appropriate | ||
3951 | reply for the overlap op. */ | ||
3952 | |||
3953 | if (!wait_type) { | ||
3954 | if (is_overlap_cancel(lkb)) { | ||
3955 | wait_type = DLM_MSG_CANCEL; | ||
3956 | if (lkb->lkb_grmode == DLM_LOCK_IV) | ||
3957 | stub_cancel_result = 0; | ||
3958 | } | ||
3959 | if (is_overlap_unlock(lkb)) { | ||
3960 | wait_type = DLM_MSG_UNLOCK; | ||
3961 | if (lkb->lkb_grmode == DLM_LOCK_IV) | ||
3962 | stub_unlock_result = -ENOENT; | ||
3963 | } | ||
3964 | |||
3965 | log_debug(ls, "rwpre overlap %x %x %d %d %d", | ||
3966 | lkb->lkb_id, lkb->lkb_flags, wait_type, | ||
3967 | stub_cancel_result, stub_unlock_result); | ||
3968 | } | ||
3969 | |||
3970 | switch (wait_type) { | ||
3869 | 3971 | ||
3870 | case DLM_MSG_REQUEST: | 3972 | case DLM_MSG_REQUEST: |
3871 | lkb->lkb_flags |= DLM_IFL_RESEND; | 3973 | lkb->lkb_flags |= DLM_IFL_RESEND; |
@@ -3878,8 +3980,9 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) | |||
3878 | case DLM_MSG_UNLOCK: | 3980 | case DLM_MSG_UNLOCK: |
3879 | hold_lkb(lkb); | 3981 | hold_lkb(lkb); |
3880 | ls->ls_stub_ms.m_type = DLM_MSG_UNLOCK_REPLY; | 3982 | ls->ls_stub_ms.m_type = DLM_MSG_UNLOCK_REPLY; |
3881 | ls->ls_stub_ms.m_result = -DLM_EUNLOCK; | 3983 | ls->ls_stub_ms.m_result = stub_unlock_result; |
3882 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 3984 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
3985 | ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid; | ||
3883 | _receive_unlock_reply(lkb, &ls->ls_stub_ms); | 3986 | _receive_unlock_reply(lkb, &ls->ls_stub_ms); |
3884 | dlm_put_lkb(lkb); | 3987 | dlm_put_lkb(lkb); |
3885 | break; | 3988 | break; |
@@ -3887,15 +3990,16 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls) | |||
3887 | case DLM_MSG_CANCEL: | 3990 | case DLM_MSG_CANCEL: |
3888 | hold_lkb(lkb); | 3991 | hold_lkb(lkb); |
3889 | ls->ls_stub_ms.m_type = DLM_MSG_CANCEL_REPLY; | 3992 | ls->ls_stub_ms.m_type = DLM_MSG_CANCEL_REPLY; |
3890 | ls->ls_stub_ms.m_result = -DLM_ECANCEL; | 3993 | ls->ls_stub_ms.m_result = stub_cancel_result; |
3891 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; | 3994 | ls->ls_stub_ms.m_flags = lkb->lkb_flags; |
3995 | ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid; | ||
3892 | _receive_cancel_reply(lkb, &ls->ls_stub_ms); | 3996 | _receive_cancel_reply(lkb, &ls->ls_stub_ms); |
3893 | dlm_put_lkb(lkb); | 3997 | dlm_put_lkb(lkb); |
3894 | break; | 3998 | break; |
3895 | 3999 | ||
3896 | default: | 4000 | default: |
3897 | log_error(ls, "invalid lkb wait_type %d", | 4001 | log_error(ls, "invalid lkb wait_type %d %d", |
3898 | lkb->lkb_wait_type); | 4002 | lkb->lkb_wait_type, wait_type); |
3899 | } | 4003 | } |
3900 | schedule(); | 4004 | schedule(); |
3901 | } | 4005 | } |
@@ -4184,7 +4288,7 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, | |||
4184 | lkb->lkb_astaddr = (void *) (long) (rl->rl_asts & AST_COMP); | 4288 | lkb->lkb_astaddr = (void *) (long) (rl->rl_asts & AST_COMP); |
4185 | 4289 | ||
4186 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { | 4290 | if (lkb->lkb_exflags & DLM_LKF_VALBLK) { |
4187 | lkb->lkb_lvbptr = allocate_lvb(ls); | 4291 | lkb->lkb_lvbptr = dlm_allocate_lvb(ls); |
4188 | if (!lkb->lkb_lvbptr) | 4292 | if (!lkb->lkb_lvbptr) |
4189 | return -ENOMEM; | 4293 | return -ENOMEM; |
4190 | lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - | 4294 | lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) - |
@@ -4259,7 +4363,7 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc) | |||
4259 | put_rsb(r); | 4363 | put_rsb(r); |
4260 | out: | 4364 | out: |
4261 | if (error) | 4365 | if (error) |
4262 | log_print("recover_master_copy %d %x", error, rl->rl_lkid); | 4366 | log_debug(ls, "recover_master_copy %d %x", error, rl->rl_lkid); |
4263 | rl->rl_result = error; | 4367 | rl->rl_result = error; |
4264 | return error; | 4368 | return error; |
4265 | } | 4369 | } |
@@ -4342,7 +4446,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, | |||
4342 | } | 4446 | } |
4343 | } | 4447 | } |
4344 | 4448 | ||
4345 | /* After ua is attached to lkb it will be freed by free_lkb(). | 4449 | /* After ua is attached to lkb it will be freed by dlm_free_lkb(). |
4346 | When DLM_IFL_USER is set, the dlm knows that this is a userspace | 4450 | When DLM_IFL_USER is set, the dlm knows that this is a userspace |
4347 | lock and that lkb_astparam is the dlm_user_args structure. */ | 4451 | lock and that lkb_astparam is the dlm_user_args structure. */ |
4348 | 4452 | ||
@@ -4679,6 +4783,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) | |||
4679 | } | 4783 | } |
4680 | 4784 | ||
4681 | list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { | 4785 | list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) { |
4786 | lkb->lkb_ast_type = 0; | ||
4682 | list_del(&lkb->lkb_astqueue); | 4787 | list_del(&lkb->lkb_astqueue); |
4683 | dlm_put_lkb(lkb); | 4788 | dlm_put_lkb(lkb); |
4684 | } | 4789 | } |
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h index ada04680a1e5..27b6ed302911 100644 --- a/fs/dlm/lock.h +++ b/fs/dlm/lock.h | |||
@@ -19,8 +19,6 @@ void dlm_print_lkb(struct dlm_lkb *lkb); | |||
19 | void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms); | 19 | void dlm_receive_message_saved(struct dlm_ls *ls, struct dlm_message *ms); |
20 | void dlm_receive_buffer(struct dlm_header *hd, int nodeid); | 20 | void dlm_receive_buffer(struct dlm_header *hd, int nodeid); |
21 | int dlm_modes_compat(int mode1, int mode2); | 21 | int dlm_modes_compat(int mode1, int mode2); |
22 | int dlm_find_rsb(struct dlm_ls *ls, char *name, int namelen, | ||
23 | unsigned int flags, struct dlm_rsb **r_ret); | ||
24 | void dlm_put_rsb(struct dlm_rsb *r); | 22 | void dlm_put_rsb(struct dlm_rsb *r); |
25 | void dlm_hold_rsb(struct dlm_rsb *r); | 23 | void dlm_hold_rsb(struct dlm_rsb *r); |
26 | int dlm_put_lkb(struct dlm_lkb *lkb); | 24 | int dlm_put_lkb(struct dlm_lkb *lkb); |
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 5c108c49cb8c..b180fdc51085 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c | |||
@@ -24,14 +24,6 @@ | |||
24 | #include "recover.h" | 24 | #include "recover.h" |
25 | #include "requestqueue.h" | 25 | #include "requestqueue.h" |
26 | 26 | ||
27 | #ifdef CONFIG_DLM_DEBUG | ||
28 | int dlm_create_debug_file(struct dlm_ls *ls); | ||
29 | void dlm_delete_debug_file(struct dlm_ls *ls); | ||
30 | #else | ||
31 | static inline int dlm_create_debug_file(struct dlm_ls *ls) { return 0; } | ||
32 | static inline void dlm_delete_debug_file(struct dlm_ls *ls) { } | ||
33 | #endif | ||
34 | |||
35 | static int ls_count; | 27 | static int ls_count; |
36 | static struct mutex ls_lock; | 28 | static struct mutex ls_lock; |
37 | static struct list_head lslist; | 29 | static struct list_head lslist; |
@@ -684,9 +676,9 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
684 | dlm_del_ast(lkb); | 676 | dlm_del_ast(lkb); |
685 | 677 | ||
686 | if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY) | 678 | if (lkb->lkb_lvbptr && lkb->lkb_flags & DLM_IFL_MSTCPY) |
687 | free_lvb(lkb->lkb_lvbptr); | 679 | dlm_free_lvb(lkb->lkb_lvbptr); |
688 | 680 | ||
689 | free_lkb(lkb); | 681 | dlm_free_lkb(lkb); |
690 | } | 682 | } |
691 | } | 683 | } |
692 | dlm_astd_resume(); | 684 | dlm_astd_resume(); |
@@ -704,7 +696,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
704 | res_hashchain); | 696 | res_hashchain); |
705 | 697 | ||
706 | list_del(&rsb->res_hashchain); | 698 | list_del(&rsb->res_hashchain); |
707 | free_rsb(rsb); | 699 | dlm_free_rsb(rsb); |
708 | } | 700 | } |
709 | 701 | ||
710 | head = &ls->ls_rsbtbl[i].toss; | 702 | head = &ls->ls_rsbtbl[i].toss; |
@@ -712,7 +704,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) | |||
712 | rsb = list_entry(head->next, struct dlm_rsb, | 704 | rsb = list_entry(head->next, struct dlm_rsb, |
713 | res_hashchain); | 705 | res_hashchain); |
714 | list_del(&rsb->res_hashchain); | 706 | list_del(&rsb->res_hashchain); |
715 | free_rsb(rsb); | 707 | dlm_free_rsb(rsb); |
716 | } | 708 | } |
717 | } | 709 | } |
718 | 710 | ||
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index e9923ca9c2d9..7c1e5e5cccd8 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -864,7 +864,7 @@ static void sctp_init_assoc(struct connection *con) | |||
864 | static void tcp_connect_to_sock(struct connection *con) | 864 | static void tcp_connect_to_sock(struct connection *con) |
865 | { | 865 | { |
866 | int result = -EHOSTUNREACH; | 866 | int result = -EHOSTUNREACH; |
867 | struct sockaddr_storage saddr; | 867 | struct sockaddr_storage saddr, src_addr; |
868 | int addr_len; | 868 | int addr_len; |
869 | struct socket *sock; | 869 | struct socket *sock; |
870 | 870 | ||
@@ -898,6 +898,17 @@ static void tcp_connect_to_sock(struct connection *con) | |||
898 | con->connect_action = tcp_connect_to_sock; | 898 | con->connect_action = tcp_connect_to_sock; |
899 | add_sock(sock, con); | 899 | add_sock(sock, con); |
900 | 900 | ||
901 | /* Bind to our cluster-known address connecting to avoid | ||
902 | routing problems */ | ||
903 | memcpy(&src_addr, dlm_local_addr[0], sizeof(src_addr)); | ||
904 | make_sockaddr(&src_addr, 0, &addr_len); | ||
905 | result = sock->ops->bind(sock, (struct sockaddr *) &src_addr, | ||
906 | addr_len); | ||
907 | if (result < 0) { | ||
908 | log_print("could not bind for connect: %d", result); | ||
909 | /* This *may* not indicate a critical error */ | ||
910 | } | ||
911 | |||
901 | make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len); | 912 | make_sockaddr(&saddr, dlm_config.ci_tcp_port, &addr_len); |
902 | 913 | ||
903 | log_print("connecting to %d", con->nodeid); | 914 | log_print("connecting to %d", con->nodeid); |
@@ -1426,6 +1437,8 @@ void dlm_lowcomms_stop(void) | |||
1426 | con = __nodeid2con(i, 0); | 1437 | con = __nodeid2con(i, 0); |
1427 | if (con) { | 1438 | if (con) { |
1428 | close_connection(con, true); | 1439 | close_connection(con, true); |
1440 | if (con->othercon) | ||
1441 | kmem_cache_free(con_cache, con->othercon); | ||
1429 | kmem_cache_free(con_cache, con); | 1442 | kmem_cache_free(con_cache, con); |
1430 | } | 1443 | } |
1431 | } | 1444 | } |
diff --git a/fs/dlm/main.c b/fs/dlm/main.c index eca2907f2386..58487fb95a4c 100644 --- a/fs/dlm/main.c +++ b/fs/dlm/main.c | |||
@@ -18,16 +18,6 @@ | |||
18 | #include "memory.h" | 18 | #include "memory.h" |
19 | #include "config.h" | 19 | #include "config.h" |
20 | 20 | ||
21 | #ifdef CONFIG_DLM_DEBUG | ||
22 | int dlm_register_debugfs(void); | ||
23 | void dlm_unregister_debugfs(void); | ||
24 | #else | ||
25 | static inline int dlm_register_debugfs(void) { return 0; } | ||
26 | static inline void dlm_unregister_debugfs(void) { } | ||
27 | #endif | ||
28 | int dlm_netlink_init(void); | ||
29 | void dlm_netlink_exit(void); | ||
30 | |||
31 | static int __init init_dlm(void) | 21 | static int __init init_dlm(void) |
32 | { | 22 | { |
33 | int error; | 23 | int error; |
diff --git a/fs/dlm/member.c b/fs/dlm/member.c index e9cdcab306e2..fa17f5a27883 100644 --- a/fs/dlm/member.c +++ b/fs/dlm/member.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -70,7 +70,7 @@ static void dlm_remove_member(struct dlm_ls *ls, struct dlm_member *memb) | |||
70 | ls->ls_num_nodes--; | 70 | ls->ls_num_nodes--; |
71 | } | 71 | } |
72 | 72 | ||
73 | static int dlm_is_member(struct dlm_ls *ls, int nodeid) | 73 | int dlm_is_member(struct dlm_ls *ls, int nodeid) |
74 | { | 74 | { |
75 | struct dlm_member *memb; | 75 | struct dlm_member *memb; |
76 | 76 | ||
diff --git a/fs/dlm/member.h b/fs/dlm/member.h index 927c08c19214..7a26fca1e0b5 100644 --- a/fs/dlm/member.h +++ b/fs/dlm/member.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -19,6 +19,7 @@ void dlm_clear_members(struct dlm_ls *ls); | |||
19 | void dlm_clear_members_gone(struct dlm_ls *ls); | 19 | void dlm_clear_members_gone(struct dlm_ls *ls); |
20 | int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out); | 20 | int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv,int *neg_out); |
21 | int dlm_is_removed(struct dlm_ls *ls, int nodeid); | 21 | int dlm_is_removed(struct dlm_ls *ls, int nodeid); |
22 | int dlm_is_member(struct dlm_ls *ls, int nodeid); | ||
22 | 23 | ||
23 | #endif /* __MEMBER_DOT_H__ */ | 24 | #endif /* __MEMBER_DOT_H__ */ |
24 | 25 | ||
diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index ecf0e5cb2035..f7783867491a 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -35,7 +35,7 @@ void dlm_memory_exit(void) | |||
35 | kmem_cache_destroy(lkb_cache); | 35 | kmem_cache_destroy(lkb_cache); |
36 | } | 36 | } |
37 | 37 | ||
38 | char *allocate_lvb(struct dlm_ls *ls) | 38 | char *dlm_allocate_lvb(struct dlm_ls *ls) |
39 | { | 39 | { |
40 | char *p; | 40 | char *p; |
41 | 41 | ||
@@ -43,7 +43,7 @@ char *allocate_lvb(struct dlm_ls *ls) | |||
43 | return p; | 43 | return p; |
44 | } | 44 | } |
45 | 45 | ||
46 | void free_lvb(char *p) | 46 | void dlm_free_lvb(char *p) |
47 | { | 47 | { |
48 | kfree(p); | 48 | kfree(p); |
49 | } | 49 | } |
@@ -51,7 +51,7 @@ void free_lvb(char *p) | |||
51 | /* FIXME: have some minimal space built-in to rsb for the name and | 51 | /* FIXME: have some minimal space built-in to rsb for the name and |
52 | kmalloc a separate name if needed, like dentries are done */ | 52 | kmalloc a separate name if needed, like dentries are done */ |
53 | 53 | ||
54 | struct dlm_rsb *allocate_rsb(struct dlm_ls *ls, int namelen) | 54 | struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen) |
55 | { | 55 | { |
56 | struct dlm_rsb *r; | 56 | struct dlm_rsb *r; |
57 | 57 | ||
@@ -61,14 +61,14 @@ struct dlm_rsb *allocate_rsb(struct dlm_ls *ls, int namelen) | |||
61 | return r; | 61 | return r; |
62 | } | 62 | } |
63 | 63 | ||
64 | void free_rsb(struct dlm_rsb *r) | 64 | void dlm_free_rsb(struct dlm_rsb *r) |
65 | { | 65 | { |
66 | if (r->res_lvbptr) | 66 | if (r->res_lvbptr) |
67 | free_lvb(r->res_lvbptr); | 67 | dlm_free_lvb(r->res_lvbptr); |
68 | kfree(r); | 68 | kfree(r); |
69 | } | 69 | } |
70 | 70 | ||
71 | struct dlm_lkb *allocate_lkb(struct dlm_ls *ls) | 71 | struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls) |
72 | { | 72 | { |
73 | struct dlm_lkb *lkb; | 73 | struct dlm_lkb *lkb; |
74 | 74 | ||
@@ -76,7 +76,7 @@ struct dlm_lkb *allocate_lkb(struct dlm_ls *ls) | |||
76 | return lkb; | 76 | return lkb; |
77 | } | 77 | } |
78 | 78 | ||
79 | void free_lkb(struct dlm_lkb *lkb) | 79 | void dlm_free_lkb(struct dlm_lkb *lkb) |
80 | { | 80 | { |
81 | if (lkb->lkb_flags & DLM_IFL_USER) { | 81 | if (lkb->lkb_flags & DLM_IFL_USER) { |
82 | struct dlm_user_args *ua; | 82 | struct dlm_user_args *ua; |
@@ -90,19 +90,3 @@ void free_lkb(struct dlm_lkb *lkb) | |||
90 | kmem_cache_free(lkb_cache, lkb); | 90 | kmem_cache_free(lkb_cache, lkb); |
91 | } | 91 | } |
92 | 92 | ||
93 | struct dlm_direntry *allocate_direntry(struct dlm_ls *ls, int namelen) | ||
94 | { | ||
95 | struct dlm_direntry *de; | ||
96 | |||
97 | DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN, | ||
98 | printk("namelen = %d\n", namelen);); | ||
99 | |||
100 | de = kzalloc(sizeof(*de) + namelen, GFP_KERNEL); | ||
101 | return de; | ||
102 | } | ||
103 | |||
104 | void free_direntry(struct dlm_direntry *de) | ||
105 | { | ||
106 | kfree(de); | ||
107 | } | ||
108 | |||
diff --git a/fs/dlm/memory.h b/fs/dlm/memory.h index 6ead158ccc5c..485fb29143bd 100644 --- a/fs/dlm/memory.h +++ b/fs/dlm/memory.h | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -16,14 +16,12 @@ | |||
16 | 16 | ||
17 | int dlm_memory_init(void); | 17 | int dlm_memory_init(void); |
18 | void dlm_memory_exit(void); | 18 | void dlm_memory_exit(void); |
19 | struct dlm_rsb *allocate_rsb(struct dlm_ls *ls, int namelen); | 19 | struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen); |
20 | void free_rsb(struct dlm_rsb *r); | 20 | void dlm_free_rsb(struct dlm_rsb *r); |
21 | struct dlm_lkb *allocate_lkb(struct dlm_ls *ls); | 21 | struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls); |
22 | void free_lkb(struct dlm_lkb *l); | 22 | void dlm_free_lkb(struct dlm_lkb *l); |
23 | struct dlm_direntry *allocate_direntry(struct dlm_ls *ls, int namelen); | 23 | char *dlm_allocate_lvb(struct dlm_ls *ls); |
24 | void free_direntry(struct dlm_direntry *de); | 24 | void dlm_free_lvb(char *l); |
25 | char *allocate_lvb(struct dlm_ls *ls); | ||
26 | void free_lvb(char *l); | ||
27 | 25 | ||
28 | #endif /* __MEMORY_DOT_H__ */ | 26 | #endif /* __MEMORY_DOT_H__ */ |
29 | 27 | ||
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c index f8c69dda16a0..e69926e984db 100644 --- a/fs/dlm/midcomms.c +++ b/fs/dlm/midcomms.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -58,8 +58,12 @@ static void copy_from_cb(void *dst, const void *base, unsigned offset, | |||
58 | int dlm_process_incoming_buffer(int nodeid, const void *base, | 58 | int dlm_process_incoming_buffer(int nodeid, const void *base, |
59 | unsigned offset, unsigned len, unsigned limit) | 59 | unsigned offset, unsigned len, unsigned limit) |
60 | { | 60 | { |
61 | unsigned char __tmp[DLM_INBUF_LEN]; | 61 | union { |
62 | struct dlm_header *msg = (struct dlm_header *) __tmp; | 62 | unsigned char __buf[DLM_INBUF_LEN]; |
63 | /* this is to force proper alignment on some arches */ | ||
64 | struct dlm_header dlm; | ||
65 | } __tmp; | ||
66 | struct dlm_header *msg = &__tmp.dlm; | ||
63 | int ret = 0; | 67 | int ret = 0; |
64 | int err = 0; | 68 | int err = 0; |
65 | uint16_t msglen; | 69 | uint16_t msglen; |
@@ -100,8 +104,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, | |||
100 | in the buffer on the stack (which should work for most | 104 | in the buffer on the stack (which should work for most |
101 | ordinary messages). */ | 105 | ordinary messages). */ |
102 | 106 | ||
103 | if (msglen > sizeof(__tmp) && | 107 | if (msglen > DLM_INBUF_LEN && msg == &__tmp.dlm) { |
104 | msg == (struct dlm_header *) __tmp) { | ||
105 | msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); | 108 | msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); |
106 | if (msg == NULL) | 109 | if (msg == NULL) |
107 | return ret; | 110 | return ret; |
@@ -119,7 +122,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, | |||
119 | dlm_receive_buffer(msg, nodeid); | 122 | dlm_receive_buffer(msg, nodeid); |
120 | } | 123 | } |
121 | 124 | ||
122 | if (msg != (struct dlm_header *) __tmp) | 125 | if (msg != &__tmp.dlm) |
123 | kfree(msg); | 126 | kfree(msg); |
124 | 127 | ||
125 | return err ? err : ret; | 128 | return err ? err : ret; |
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c index ae2fd97fa4ad..026824cd3acb 100644 --- a/fs/dlm/rcom.c +++ b/fs/dlm/rcom.c | |||
@@ -2,7 +2,7 @@ | |||
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 4 | ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
5 | ** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. | 5 | ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. |
6 | ** | 6 | ** |
7 | ** This copyrighted material is made available to anyone wishing to use, | 7 | ** This copyrighted material is made available to anyone wishing to use, |
8 | ** modify, copy, or redistribute it subject to the terms and conditions | 8 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -197,11 +197,6 @@ static void receive_sync_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
197 | spin_unlock(&ls->ls_rcom_spin); | 197 | spin_unlock(&ls->ls_rcom_spin); |
198 | } | 198 | } |
199 | 199 | ||
200 | static void receive_rcom_status_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | ||
201 | { | ||
202 | receive_sync_reply(ls, rc_in); | ||
203 | } | ||
204 | |||
205 | int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) | 200 | int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len) |
206 | { | 201 | { |
207 | struct dlm_rcom *rc; | 202 | struct dlm_rcom *rc; |
@@ -254,11 +249,6 @@ static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
254 | send_rcom(ls, mh, rc); | 249 | send_rcom(ls, mh, rc); |
255 | } | 250 | } |
256 | 251 | ||
257 | static void receive_rcom_names_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | ||
258 | { | ||
259 | receive_sync_reply(ls, rc_in); | ||
260 | } | ||
261 | |||
262 | int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid) | 252 | int dlm_send_rcom_lookup(struct dlm_rsb *r, int dir_nodeid) |
263 | { | 253 | { |
264 | struct dlm_rcom *rc; | 254 | struct dlm_rcom *rc; |
@@ -381,11 +371,6 @@ static void receive_rcom_lock(struct dlm_ls *ls, struct dlm_rcom *rc_in) | |||
381 | send_rcom(ls, mh, rc); | 371 | send_rcom(ls, mh, rc); |
382 | } | 372 | } |
383 | 373 | ||
384 | static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in) | ||
385 | { | ||
386 | dlm_recover_process_copy(ls, rc_in); | ||
387 | } | ||
388 | |||
389 | /* If the lockspace doesn't exist then still send a status message | 374 | /* If the lockspace doesn't exist then still send a status message |
390 | back; it's possible that it just doesn't have its global_id yet. */ | 375 | back; it's possible that it just doesn't have its global_id yet. */ |
391 | 376 | ||
@@ -481,11 +466,11 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | |||
481 | break; | 466 | break; |
482 | 467 | ||
483 | case DLM_RCOM_STATUS_REPLY: | 468 | case DLM_RCOM_STATUS_REPLY: |
484 | receive_rcom_status_reply(ls, rc); | 469 | receive_sync_reply(ls, rc); |
485 | break; | 470 | break; |
486 | 471 | ||
487 | case DLM_RCOM_NAMES_REPLY: | 472 | case DLM_RCOM_NAMES_REPLY: |
488 | receive_rcom_names_reply(ls, rc); | 473 | receive_sync_reply(ls, rc); |
489 | break; | 474 | break; |
490 | 475 | ||
491 | case DLM_RCOM_LOOKUP_REPLY: | 476 | case DLM_RCOM_LOOKUP_REPLY: |
@@ -493,11 +478,11 @@ void dlm_receive_rcom(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid) | |||
493 | break; | 478 | break; |
494 | 479 | ||
495 | case DLM_RCOM_LOCK_REPLY: | 480 | case DLM_RCOM_LOCK_REPLY: |
496 | receive_rcom_lock_reply(ls, rc); | 481 | dlm_recover_process_copy(ls, rc); |
497 | break; | 482 | break; |
498 | 483 | ||
499 | default: | 484 | default: |
500 | DLM_ASSERT(0, printk("rc_type=%x\n", rc->rc_type);); | 485 | log_error(ls, "receive_rcom bad type %d", rc->rc_type); |
501 | } | 486 | } |
502 | out: | 487 | out: |
503 | return; | 488 | return; |
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c index c2cc7694cd16..df075dc300fa 100644 --- a/fs/dlm/recover.c +++ b/fs/dlm/recover.c | |||
@@ -629,7 +629,7 @@ static void recover_lvb(struct dlm_rsb *r) | |||
629 | goto out; | 629 | goto out; |
630 | 630 | ||
631 | if (!r->res_lvbptr) { | 631 | if (!r->res_lvbptr) { |
632 | r->res_lvbptr = allocate_lvb(r->res_ls); | 632 | r->res_lvbptr = dlm_allocate_lvb(r->res_ls); |
633 | if (!r->res_lvbptr) | 633 | if (!r->res_lvbptr) |
634 | goto out; | 634 | goto out; |
635 | } | 635 | } |
@@ -731,6 +731,20 @@ int dlm_create_root_list(struct dlm_ls *ls) | |||
731 | list_add(&r->res_root_list, &ls->ls_root_list); | 731 | list_add(&r->res_root_list, &ls->ls_root_list); |
732 | dlm_hold_rsb(r); | 732 | dlm_hold_rsb(r); |
733 | } | 733 | } |
734 | |||
735 | /* If we're using a directory, add tossed rsbs to the root | ||
736 | list; they'll have entries created in the new directory, | ||
737 | but no other recovery steps should do anything with them. */ | ||
738 | |||
739 | if (dlm_no_directory(ls)) { | ||
740 | read_unlock(&ls->ls_rsbtbl[i].lock); | ||
741 | continue; | ||
742 | } | ||
743 | |||
744 | list_for_each_entry(r, &ls->ls_rsbtbl[i].toss, res_hashchain) { | ||
745 | list_add(&r->res_root_list, &ls->ls_root_list); | ||
746 | dlm_hold_rsb(r); | ||
747 | } | ||
734 | read_unlock(&ls->ls_rsbtbl[i].lock); | 748 | read_unlock(&ls->ls_rsbtbl[i].lock); |
735 | } | 749 | } |
736 | out: | 750 | out: |
@@ -750,6 +764,11 @@ void dlm_release_root_list(struct dlm_ls *ls) | |||
750 | up_write(&ls->ls_root_sem); | 764 | up_write(&ls->ls_root_sem); |
751 | } | 765 | } |
752 | 766 | ||
767 | /* If not using a directory, clear the entire toss list, there's no benefit to | ||
768 | caching the master value since it's fixed. If we are using a dir, keep the | ||
769 | rsb's we're the master of. Recovery will add them to the root list and from | ||
770 | there they'll be entered in the rebuilt directory. */ | ||
771 | |||
753 | void dlm_clear_toss_list(struct dlm_ls *ls) | 772 | void dlm_clear_toss_list(struct dlm_ls *ls) |
754 | { | 773 | { |
755 | struct dlm_rsb *r, *safe; | 774 | struct dlm_rsb *r, *safe; |
@@ -759,8 +778,10 @@ void dlm_clear_toss_list(struct dlm_ls *ls) | |||
759 | write_lock(&ls->ls_rsbtbl[i].lock); | 778 | write_lock(&ls->ls_rsbtbl[i].lock); |
760 | list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss, | 779 | list_for_each_entry_safe(r, safe, &ls->ls_rsbtbl[i].toss, |
761 | res_hashchain) { | 780 | res_hashchain) { |
762 | list_del(&r->res_hashchain); | 781 | if (dlm_no_directory(ls) || !is_master(r)) { |
763 | free_rsb(r); | 782 | list_del(&r->res_hashchain); |
783 | dlm_free_rsb(r); | ||
784 | } | ||
764 | } | 785 | } |
765 | write_unlock(&ls->ls_rsbtbl[i].lock); | 786 | write_unlock(&ls->ls_rsbtbl[i].lock); |
766 | } | 787 | } |
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c index 4b89e20eebe7..997f9531d594 100644 --- a/fs/dlm/recoverd.c +++ b/fs/dlm/recoverd.c | |||
@@ -67,17 +67,18 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv) | |||
67 | dlm_astd_resume(); | 67 | dlm_astd_resume(); |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * This list of root rsb's will be the basis of most of the recovery | 70 | * Free non-master tossed rsb's. Master rsb's are kept on toss |
71 | * routines. | 71 | * list and put on root list to be included in resdir recovery. |
72 | */ | 72 | */ |
73 | 73 | ||
74 | dlm_create_root_list(ls); | 74 | dlm_clear_toss_list(ls); |
75 | 75 | ||
76 | /* | 76 | /* |
77 | * Free all the tossed rsb's so we don't have to recover them. | 77 | * This list of root rsb's will be the basis of most of the recovery |
78 | * routines. | ||
78 | */ | 79 | */ |
79 | 80 | ||
80 | dlm_clear_toss_list(ls); | 81 | dlm_create_root_list(ls); |
81 | 82 | ||
82 | /* | 83 | /* |
83 | * Add or remove nodes from the lockspace's ls_nodes list. | 84 | * Add or remove nodes from the lockspace's ls_nodes list. |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 4f741546f4bb..7cbc6826239b 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -24,8 +24,7 @@ | |||
24 | #include "lvb_table.h" | 24 | #include "lvb_table.h" |
25 | #include "user.h" | 25 | #include "user.h" |
26 | 26 | ||
27 | static const char *name_prefix="dlm"; | 27 | static const char name_prefix[] = "dlm"; |
28 | static struct miscdevice ctl_device; | ||
29 | static const struct file_operations device_fops; | 28 | static const struct file_operations device_fops; |
30 | 29 | ||
31 | #ifdef CONFIG_COMPAT | 30 | #ifdef CONFIG_COMPAT |
@@ -82,7 +81,8 @@ struct dlm_lock_result32 { | |||
82 | }; | 81 | }; |
83 | 82 | ||
84 | static void compat_input(struct dlm_write_request *kb, | 83 | static void compat_input(struct dlm_write_request *kb, |
85 | struct dlm_write_request32 *kb32) | 84 | struct dlm_write_request32 *kb32, |
85 | int max_namelen) | ||
86 | { | 86 | { |
87 | kb->version[0] = kb32->version[0]; | 87 | kb->version[0] = kb32->version[0]; |
88 | kb->version[1] = kb32->version[1]; | 88 | kb->version[1] = kb32->version[1]; |
@@ -112,7 +112,11 @@ static void compat_input(struct dlm_write_request *kb, | |||
112 | kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr; | 112 | kb->i.lock.bastaddr = (void *)(long)kb32->i.lock.bastaddr; |
113 | kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb; | 113 | kb->i.lock.lksb = (void *)(long)kb32->i.lock.lksb; |
114 | memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN); | 114 | memcpy(kb->i.lock.lvb, kb32->i.lock.lvb, DLM_USER_LVB_LEN); |
115 | memcpy(kb->i.lock.name, kb32->i.lock.name, kb->i.lock.namelen); | 115 | if (kb->i.lock.namelen <= max_namelen) |
116 | memcpy(kb->i.lock.name, kb32->i.lock.name, | ||
117 | kb->i.lock.namelen); | ||
118 | else | ||
119 | kb->i.lock.namelen = max_namelen; | ||
116 | } | 120 | } |
117 | } | 121 | } |
118 | 122 | ||
@@ -236,12 +240,12 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type) | |||
236 | spin_unlock(&proc->asts_spin); | 240 | spin_unlock(&proc->asts_spin); |
237 | 241 | ||
238 | if (eol) { | 242 | if (eol) { |
239 | spin_lock(&ua->proc->locks_spin); | 243 | spin_lock(&proc->locks_spin); |
240 | if (!list_empty(&lkb->lkb_ownqueue)) { | 244 | if (!list_empty(&lkb->lkb_ownqueue)) { |
241 | list_del_init(&lkb->lkb_ownqueue); | 245 | list_del_init(&lkb->lkb_ownqueue); |
242 | dlm_put_lkb(lkb); | 246 | dlm_put_lkb(lkb); |
243 | } | 247 | } |
244 | spin_unlock(&ua->proc->locks_spin); | 248 | spin_unlock(&proc->locks_spin); |
245 | } | 249 | } |
246 | out: | 250 | out: |
247 | mutex_unlock(&ls->ls_clear_proc_locks); | 251 | mutex_unlock(&ls->ls_clear_proc_locks); |
@@ -529,7 +533,8 @@ static ssize_t device_write(struct file *file, const char __user *buf, | |||
529 | 533 | ||
530 | if (proc) | 534 | if (proc) |
531 | set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); | 535 | set_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags); |
532 | compat_input(kbuf, k32buf); | 536 | compat_input(kbuf, k32buf, |
537 | count - sizeof(struct dlm_write_request32)); | ||
533 | kfree(k32buf); | 538 | kfree(k32buf); |
534 | } | 539 | } |
535 | #endif | 540 | #endif |
@@ -896,14 +901,16 @@ static const struct file_operations ctl_device_fops = { | |||
896 | .owner = THIS_MODULE, | 901 | .owner = THIS_MODULE, |
897 | }; | 902 | }; |
898 | 903 | ||
904 | static struct miscdevice ctl_device = { | ||
905 | .name = "dlm-control", | ||
906 | .fops = &ctl_device_fops, | ||
907 | .minor = MISC_DYNAMIC_MINOR, | ||
908 | }; | ||
909 | |||
899 | int dlm_user_init(void) | 910 | int dlm_user_init(void) |
900 | { | 911 | { |
901 | int error; | 912 | int error; |
902 | 913 | ||
903 | ctl_device.name = "dlm-control"; | ||
904 | ctl_device.fops = &ctl_device_fops; | ||
905 | ctl_device.minor = MISC_DYNAMIC_MINOR; | ||
906 | |||
907 | error = misc_register(&ctl_device); | 914 | error = misc_register(&ctl_device); |
908 | if (error) | 915 | if (error) |
909 | log_print("misc_register failed for control device"); | 916 | log_print("misc_register failed for control device"); |
diff --git a/fs/dlm/util.c b/fs/dlm/util.c index 963889cf6740..4d9c1f4e1bd1 100644 --- a/fs/dlm/util.c +++ b/fs/dlm/util.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /****************************************************************************** | 1 | /****************************************************************************** |
2 | ******************************************************************************* | 2 | ******************************************************************************* |
3 | ** | 3 | ** |
4 | ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. | 4 | ** Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. |
5 | ** | 5 | ** |
6 | ** This copyrighted material is made available to anyone wishing to use, | 6 | ** This copyrighted material is made available to anyone wishing to use, |
7 | ** modify, copy, or redistribute it subject to the terms and conditions | 7 | ** modify, copy, or redistribute it subject to the terms and conditions |
@@ -14,6 +14,14 @@ | |||
14 | #include "rcom.h" | 14 | #include "rcom.h" |
15 | #include "util.h" | 15 | #include "util.h" |
16 | 16 | ||
17 | #define DLM_ERRNO_EDEADLK 35 | ||
18 | #define DLM_ERRNO_EBADR 53 | ||
19 | #define DLM_ERRNO_EBADSLT 57 | ||
20 | #define DLM_ERRNO_EPROTO 71 | ||
21 | #define DLM_ERRNO_EOPNOTSUPP 95 | ||
22 | #define DLM_ERRNO_ETIMEDOUT 110 | ||
23 | #define DLM_ERRNO_EINPROGRESS 115 | ||
24 | |||
17 | static void header_out(struct dlm_header *hd) | 25 | static void header_out(struct dlm_header *hd) |
18 | { | 26 | { |
19 | hd->h_version = cpu_to_le32(hd->h_version); | 27 | hd->h_version = cpu_to_le32(hd->h_version); |
@@ -30,11 +38,54 @@ static void header_in(struct dlm_header *hd) | |||
30 | hd->h_length = le16_to_cpu(hd->h_length); | 38 | hd->h_length = le16_to_cpu(hd->h_length); |
31 | } | 39 | } |
32 | 40 | ||
33 | void dlm_message_out(struct dlm_message *ms) | 41 | /* higher errno values are inconsistent across architectures, so select |
42 | one set of values for on the wire */ | ||
43 | |||
44 | static int to_dlm_errno(int err) | ||
45 | { | ||
46 | switch (err) { | ||
47 | case -EDEADLK: | ||
48 | return -DLM_ERRNO_EDEADLK; | ||
49 | case -EBADR: | ||
50 | return -DLM_ERRNO_EBADR; | ||
51 | case -EBADSLT: | ||
52 | return -DLM_ERRNO_EBADSLT; | ||
53 | case -EPROTO: | ||
54 | return -DLM_ERRNO_EPROTO; | ||
55 | case -EOPNOTSUPP: | ||
56 | return -DLM_ERRNO_EOPNOTSUPP; | ||
57 | case -ETIMEDOUT: | ||
58 | return -DLM_ERRNO_ETIMEDOUT; | ||
59 | case -EINPROGRESS: | ||
60 | return -DLM_ERRNO_EINPROGRESS; | ||
61 | } | ||
62 | return err; | ||
63 | } | ||
64 | |||
65 | static int from_dlm_errno(int err) | ||
34 | { | 66 | { |
35 | struct dlm_header *hd = (struct dlm_header *) ms; | 67 | switch (err) { |
68 | case -DLM_ERRNO_EDEADLK: | ||
69 | return -EDEADLK; | ||
70 | case -DLM_ERRNO_EBADR: | ||
71 | return -EBADR; | ||
72 | case -DLM_ERRNO_EBADSLT: | ||
73 | return -EBADSLT; | ||
74 | case -DLM_ERRNO_EPROTO: | ||
75 | return -EPROTO; | ||
76 | case -DLM_ERRNO_EOPNOTSUPP: | ||
77 | return -EOPNOTSUPP; | ||
78 | case -DLM_ERRNO_ETIMEDOUT: | ||
79 | return -ETIMEDOUT; | ||
80 | case -DLM_ERRNO_EINPROGRESS: | ||
81 | return -EINPROGRESS; | ||
82 | } | ||
83 | return err; | ||
84 | } | ||
36 | 85 | ||
37 | header_out(hd); | 86 | void dlm_message_out(struct dlm_message *ms) |
87 | { | ||
88 | header_out(&ms->m_header); | ||
38 | 89 | ||
39 | ms->m_type = cpu_to_le32(ms->m_type); | 90 | ms->m_type = cpu_to_le32(ms->m_type); |
40 | ms->m_nodeid = cpu_to_le32(ms->m_nodeid); | 91 | ms->m_nodeid = cpu_to_le32(ms->m_nodeid); |
@@ -53,14 +104,12 @@ void dlm_message_out(struct dlm_message *ms) | |||
53 | ms->m_rqmode = cpu_to_le32(ms->m_rqmode); | 104 | ms->m_rqmode = cpu_to_le32(ms->m_rqmode); |
54 | ms->m_bastmode = cpu_to_le32(ms->m_bastmode); | 105 | ms->m_bastmode = cpu_to_le32(ms->m_bastmode); |
55 | ms->m_asts = cpu_to_le32(ms->m_asts); | 106 | ms->m_asts = cpu_to_le32(ms->m_asts); |
56 | ms->m_result = cpu_to_le32(ms->m_result); | 107 | ms->m_result = cpu_to_le32(to_dlm_errno(ms->m_result)); |
57 | } | 108 | } |
58 | 109 | ||
59 | void dlm_message_in(struct dlm_message *ms) | 110 | void dlm_message_in(struct dlm_message *ms) |
60 | { | 111 | { |
61 | struct dlm_header *hd = (struct dlm_header *) ms; | 112 | header_in(&ms->m_header); |
62 | |||
63 | header_in(hd); | ||
64 | 113 | ||
65 | ms->m_type = le32_to_cpu(ms->m_type); | 114 | ms->m_type = le32_to_cpu(ms->m_type); |
66 | ms->m_nodeid = le32_to_cpu(ms->m_nodeid); | 115 | ms->m_nodeid = le32_to_cpu(ms->m_nodeid); |
@@ -79,7 +128,7 @@ void dlm_message_in(struct dlm_message *ms) | |||
79 | ms->m_rqmode = le32_to_cpu(ms->m_rqmode); | 128 | ms->m_rqmode = le32_to_cpu(ms->m_rqmode); |
80 | ms->m_bastmode = le32_to_cpu(ms->m_bastmode); | 129 | ms->m_bastmode = le32_to_cpu(ms->m_bastmode); |
81 | ms->m_asts = le32_to_cpu(ms->m_asts); | 130 | ms->m_asts = le32_to_cpu(ms->m_asts); |
82 | ms->m_result = le32_to_cpu(ms->m_result); | 131 | ms->m_result = from_dlm_errno(le32_to_cpu(ms->m_result)); |
83 | } | 132 | } |
84 | 133 | ||
85 | static void rcom_lock_out(struct rcom_lock *rl) | 134 | static void rcom_lock_out(struct rcom_lock *rl) |
@@ -126,10 +175,9 @@ static void rcom_config_in(struct rcom_config *rf) | |||
126 | 175 | ||
127 | void dlm_rcom_out(struct dlm_rcom *rc) | 176 | void dlm_rcom_out(struct dlm_rcom *rc) |
128 | { | 177 | { |
129 | struct dlm_header *hd = (struct dlm_header *) rc; | ||
130 | int type = rc->rc_type; | 178 | int type = rc->rc_type; |
131 | 179 | ||
132 | header_out(hd); | 180 | header_out(&rc->rc_header); |
133 | 181 | ||
134 | rc->rc_type = cpu_to_le32(rc->rc_type); | 182 | rc->rc_type = cpu_to_le32(rc->rc_type); |
135 | rc->rc_result = cpu_to_le32(rc->rc_result); | 183 | rc->rc_result = cpu_to_le32(rc->rc_result); |
@@ -137,7 +185,7 @@ void dlm_rcom_out(struct dlm_rcom *rc) | |||
137 | rc->rc_seq = cpu_to_le64(rc->rc_seq); | 185 | rc->rc_seq = cpu_to_le64(rc->rc_seq); |
138 | rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply); | 186 | rc->rc_seq_reply = cpu_to_le64(rc->rc_seq_reply); |
139 | 187 | ||
140 | if (type == DLM_RCOM_LOCK) | 188 | if ((type == DLM_RCOM_LOCK) || (type == DLM_RCOM_LOCK_REPLY)) |
141 | rcom_lock_out((struct rcom_lock *) rc->rc_buf); | 189 | rcom_lock_out((struct rcom_lock *) rc->rc_buf); |
142 | 190 | ||
143 | else if (type == DLM_RCOM_STATUS_REPLY) | 191 | else if (type == DLM_RCOM_STATUS_REPLY) |
@@ -146,9 +194,9 @@ void dlm_rcom_out(struct dlm_rcom *rc) | |||
146 | 194 | ||
147 | void dlm_rcom_in(struct dlm_rcom *rc) | 195 | void dlm_rcom_in(struct dlm_rcom *rc) |
148 | { | 196 | { |
149 | struct dlm_header *hd = (struct dlm_header *) rc; | 197 | int type; |
150 | 198 | ||
151 | header_in(hd); | 199 | header_in(&rc->rc_header); |
152 | 200 | ||
153 | rc->rc_type = le32_to_cpu(rc->rc_type); | 201 | rc->rc_type = le32_to_cpu(rc->rc_type); |
154 | rc->rc_result = le32_to_cpu(rc->rc_result); | 202 | rc->rc_result = le32_to_cpu(rc->rc_result); |
@@ -156,10 +204,12 @@ void dlm_rcom_in(struct dlm_rcom *rc) | |||
156 | rc->rc_seq = le64_to_cpu(rc->rc_seq); | 204 | rc->rc_seq = le64_to_cpu(rc->rc_seq); |
157 | rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply); | 205 | rc->rc_seq_reply = le64_to_cpu(rc->rc_seq_reply); |
158 | 206 | ||
159 | if (rc->rc_type == DLM_RCOM_LOCK) | 207 | type = rc->rc_type; |
208 | |||
209 | if ((type == DLM_RCOM_LOCK) || (type == DLM_RCOM_LOCK_REPLY)) | ||
160 | rcom_lock_in((struct rcom_lock *) rc->rc_buf); | 210 | rcom_lock_in((struct rcom_lock *) rc->rc_buf); |
161 | 211 | ||
162 | else if (rc->rc_type == DLM_RCOM_STATUS_REPLY) | 212 | else if (type == DLM_RCOM_STATUS_REPLY) |
163 | rcom_config_in((struct rcom_config *) rc->rc_buf); | 213 | rcom_config_in((struct rcom_config *) rc->rc_buf); |
164 | } | 214 | } |
165 | 215 | ||
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 0f69c416eebc..a5432bbbfb88 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
@@ -347,7 +347,8 @@ restart: | |||
347 | break; | 347 | break; |
348 | } | 348 | } |
349 | retry = __process_buffer(journal, jh, bhs,&batch_count); | 349 | retry = __process_buffer(journal, jh, bhs,&batch_count); |
350 | if (!retry && lock_need_resched(&journal->j_list_lock)){ | 350 | if (!retry && (need_resched() || |
351 | spin_needbreak(&journal->j_list_lock))) { | ||
351 | spin_unlock(&journal->j_list_lock); | 352 | spin_unlock(&journal->j_list_lock); |
352 | retry = 1; | 353 | retry = 1; |
353 | break; | 354 | break; |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 610264b99a8e..31853eb65b4c 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -265,7 +265,7 @@ write_out_data: | |||
265 | put_bh(bh); | 265 | put_bh(bh); |
266 | } | 266 | } |
267 | 267 | ||
268 | if (lock_need_resched(&journal->j_list_lock)) { | 268 | if (need_resched() || spin_needbreak(&journal->j_list_lock)) { |
269 | spin_unlock(&journal->j_list_lock); | 269 | spin_unlock(&journal->j_list_lock); |
270 | goto write_out_data; | 270 | goto write_out_data; |
271 | } | 271 | } |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 1b7f282c1ae9..6914598022ce 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -353,7 +353,8 @@ restart: | |||
353 | } | 353 | } |
354 | retry = __process_buffer(journal, jh, bhs, &batch_count, | 354 | retry = __process_buffer(journal, jh, bhs, &batch_count, |
355 | transaction); | 355 | transaction); |
356 | if (!retry && lock_need_resched(&journal->j_list_lock)){ | 356 | if (!retry && (need_resched() || |
357 | spin_needbreak(&journal->j_list_lock))) { | ||
357 | spin_unlock(&journal->j_list_lock); | 358 | spin_unlock(&journal->j_list_lock); |
358 | retry = 1; | 359 | retry = 1; |
359 | break; | 360 | break; |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index da8d0eb3b7b9..4f302d279279 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -341,7 +341,7 @@ write_out_data: | |||
341 | put_bh(bh); | 341 | put_bh(bh); |
342 | } | 342 | } |
343 | 343 | ||
344 | if (lock_need_resched(&journal->j_list_lock)) { | 344 | if (need_resched() || spin_needbreak(&journal->j_list_lock)) { |
345 | spin_unlock(&journal->j_list_lock); | 345 | spin_unlock(&journal->j_list_lock); |
346 | goto write_out_data; | 346 | goto write_out_data; |
347 | } | 347 | } |