diff options
| -rw-r--r-- | fs/dlm/lock.c | 5 | ||||
| -rw-r--r-- | fs/dlm/user.c | 88 |
2 files changed, 75 insertions, 18 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 17903b491298..031dbe3a15ca 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
| @@ -733,10 +733,7 @@ static void lkb_add_ordered(struct list_head *new, struct list_head *head, | |||
| 733 | if (lkb->lkb_rqmode < mode) | 733 | if (lkb->lkb_rqmode < mode) |
| 734 | break; | 734 | break; |
| 735 | 735 | ||
| 736 | if (!lkb) | 736 | __list_add(new, lkb->lkb_statequeue.prev, &lkb->lkb_statequeue); |
| 737 | list_add_tail(new, head); | ||
| 738 | else | ||
| 739 | __list_add(new, lkb->lkb_statequeue.prev, &lkb->lkb_statequeue); | ||
| 740 | } | 737 | } |
| 741 | 738 | ||
| 742 | /* add/remove lkb to rsb's grant/convert/wait queue */ | 739 | /* add/remove lkb to rsb's grant/convert/wait queue */ |
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 8b6e73c47435..b6272853130c 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
| @@ -215,6 +215,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode) | |||
| 215 | if (!ast_type) { | 215 | if (!ast_type) { |
| 216 | kref_get(&lkb->lkb_ref); | 216 | kref_get(&lkb->lkb_ref); |
| 217 | list_add_tail(&lkb->lkb_astqueue, &proc->asts); | 217 | list_add_tail(&lkb->lkb_astqueue, &proc->asts); |
| 218 | lkb->lkb_ast_first = type; | ||
| 218 | wake_up_interruptible(&proc->wait); | 219 | wake_up_interruptible(&proc->wait); |
| 219 | } | 220 | } |
| 220 | if (type == AST_COMP && (ast_type & AST_COMP)) | 221 | if (type == AST_COMP && (ast_type & AST_COMP)) |
| @@ -223,7 +224,6 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode) | |||
| 223 | 224 | ||
| 224 | eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); | 225 | eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); |
| 225 | if (eol) { | 226 | if (eol) { |
| 226 | lkb->lkb_ast_type &= ~AST_BAST; | ||
| 227 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; | 227 | lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| @@ -706,7 +706,7 @@ static int device_close(struct inode *inode, struct file *file) | |||
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | 708 | static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, |
| 709 | int bmode, char __user *buf, size_t count) | 709 | int mode, char __user *buf, size_t count) |
| 710 | { | 710 | { |
| 711 | #ifdef CONFIG_COMPAT | 711 | #ifdef CONFIG_COMPAT |
| 712 | struct dlm_lock_result32 result32; | 712 | struct dlm_lock_result32 result32; |
| @@ -733,7 +733,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type, | |||
| 733 | if (type == AST_BAST) { | 733 | if (type == AST_BAST) { |
| 734 | result.user_astaddr = ua->bastaddr; | 734 | result.user_astaddr = ua->bastaddr; |
| 735 | result.user_astparam = ua->bastparam; | 735 | result.user_astparam = ua->bastparam; |
| 736 | result.bast_mode = bmode; | 736 | result.bast_mode = mode; |
| 737 | } else { | 737 | } else { |
| 738 | result.user_astaddr = ua->castaddr; | 738 | result.user_astaddr = ua->castaddr; |
| 739 | result.user_astparam = ua->castparam; | 739 | result.user_astparam = ua->castparam; |
| @@ -801,7 +801,9 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
| 801 | struct dlm_user_proc *proc = file->private_data; | 801 | struct dlm_user_proc *proc = file->private_data; |
| 802 | struct dlm_lkb *lkb; | 802 | struct dlm_lkb *lkb; |
| 803 | DECLARE_WAITQUEUE(wait, current); | 803 | DECLARE_WAITQUEUE(wait, current); |
| 804 | int error, type=0, bmode=0, removed = 0; | 804 | int error = 0, removed; |
| 805 | int ret_type, ret_mode; | ||
| 806 | int bastmode, castmode, do_bast, do_cast; | ||
| 805 | 807 | ||
| 806 | if (count == sizeof(struct dlm_device_version)) { | 808 | if (count == sizeof(struct dlm_device_version)) { |
| 807 | error = copy_version_to_user(buf, count); | 809 | error = copy_version_to_user(buf, count); |
| @@ -820,6 +822,8 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
| 820 | #endif | 822 | #endif |
| 821 | return -EINVAL; | 823 | return -EINVAL; |
| 822 | 824 | ||
| 825 | try_another: | ||
| 826 | |||
| 823 | /* do we really need this? can a read happen after a close? */ | 827 | /* do we really need this? can a read happen after a close? */ |
| 824 | if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags)) | 828 | if (test_bit(DLM_PROC_FLAGS_CLOSING, &proc->flags)) |
| 825 | return -EINVAL; | 829 | return -EINVAL; |
| @@ -855,13 +859,55 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
| 855 | 859 | ||
| 856 | lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue); | 860 | lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue); |
| 857 | 861 | ||
| 858 | if (lkb->lkb_ast_type & AST_COMP) { | 862 | removed = 0; |
| 859 | lkb->lkb_ast_type &= ~AST_COMP; | 863 | ret_type = 0; |
| 860 | type = AST_COMP; | 864 | ret_mode = 0; |
| 861 | } else if (lkb->lkb_ast_type & AST_BAST) { | 865 | do_bast = lkb->lkb_ast_type & AST_BAST; |
| 862 | lkb->lkb_ast_type &= ~AST_BAST; | 866 | do_cast = lkb->lkb_ast_type & AST_COMP; |
| 863 | type = AST_BAST; | 867 | bastmode = lkb->lkb_bastmode; |
| 864 | bmode = lkb->lkb_bastmode; | 868 | castmode = lkb->lkb_castmode; |
| 869 | |||
| 870 | /* when both are queued figure out which to do first and | ||
| 871 | switch first so the other goes in the next read */ | ||
| 872 | |||
| 873 | if (do_cast && do_bast) { | ||
| 874 | if (lkb->lkb_ast_first == AST_COMP) { | ||
| 875 | ret_type = AST_COMP; | ||
| 876 | ret_mode = castmode; | ||
| 877 | lkb->lkb_ast_type &= ~AST_COMP; | ||
| 878 | lkb->lkb_ast_first = AST_BAST; | ||
| 879 | } else { | ||
| 880 | ret_type = AST_BAST; | ||
| 881 | ret_mode = bastmode; | ||
| 882 | lkb->lkb_ast_type &= ~AST_BAST; | ||
| 883 | lkb->lkb_ast_first = AST_COMP; | ||
| 884 | } | ||
| 885 | } else { | ||
| 886 | ret_type = lkb->lkb_ast_first; | ||
| 887 | ret_mode = (ret_type == AST_COMP) ? castmode : bastmode; | ||
| 888 | lkb->lkb_ast_type &= ~ret_type; | ||
| 889 | lkb->lkb_ast_first = 0; | ||
| 890 | } | ||
| 891 | |||
| 892 | /* if we're doing a bast but the bast is unnecessary, then | ||
| 893 | switch to do nothing or do a cast if that was needed next */ | ||
| 894 | |||
| 895 | if ((ret_type == AST_BAST) && | ||
| 896 | dlm_modes_compat(bastmode, lkb->lkb_castmode_done)) { | ||
| 897 | ret_type = 0; | ||
| 898 | ret_mode = 0; | ||
| 899 | |||
| 900 | if (do_cast) { | ||
| 901 | ret_type = AST_COMP; | ||
| 902 | ret_mode = castmode; | ||
| 903 | lkb->lkb_ast_type &= ~AST_COMP; | ||
| 904 | lkb->lkb_ast_first = 0; | ||
| 905 | } | ||
| 906 | } | ||
| 907 | |||
| 908 | if (lkb->lkb_ast_first != lkb->lkb_ast_type) { | ||
| 909 | log_print("device_read %x ast_first %x ast_type %x", | ||
| 910 | lkb->lkb_id, lkb->lkb_ast_first, lkb->lkb_ast_type); | ||
| 865 | } | 911 | } |
| 866 | 912 | ||
| 867 | if (!lkb->lkb_ast_type) { | 913 | if (!lkb->lkb_ast_type) { |
| @@ -870,15 +916,29 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count, | |||
| 870 | } | 916 | } |
| 871 | spin_unlock(&proc->asts_spin); | 917 | spin_unlock(&proc->asts_spin); |
| 872 | 918 | ||
| 873 | error = copy_result_to_user(lkb->lkb_ua, | 919 | if (ret_type) { |
| 874 | test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), | 920 | error = copy_result_to_user(lkb->lkb_ua, |
| 875 | type, bmode, buf, count); | 921 | test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags), |
| 922 | ret_type, ret_mode, buf, count); | ||
| 923 | |||
| 924 | if (ret_type == AST_COMP) | ||
| 925 | lkb->lkb_castmode_done = castmode; | ||
| 926 | if (ret_type == AST_BAST) | ||
| 927 | lkb->lkb_bastmode_done = bastmode; | ||
| 928 | } | ||
| 876 | 929 | ||
| 877 | /* removes reference for the proc->asts lists added by | 930 | /* removes reference for the proc->asts lists added by |
| 878 | dlm_user_add_ast() and may result in the lkb being freed */ | 931 | dlm_user_add_ast() and may result in the lkb being freed */ |
| 932 | |||
| 879 | if (removed) | 933 | if (removed) |
| 880 | dlm_put_lkb(lkb); | 934 | dlm_put_lkb(lkb); |
| 881 | 935 | ||
| 936 | /* the bast that was queued was eliminated (see unnecessary above), | ||
| 937 | leaving nothing to return */ | ||
| 938 | |||
| 939 | if (!ret_type) | ||
| 940 | goto try_another; | ||
| 941 | |||
| 882 | return error; | 942 | return error; |
| 883 | } | 943 | } |
| 884 | 944 | ||
