Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm:
dlm: make plock operation killable
dlm: remove shared message stub for recovery
dlm: delayed reply message warning
dlm: Remove superfluous call to recalc_sigpending()

+223 -51
+8 -1
fs/dlm/config.c
··· 100 100 unsigned int cl_log_debug; 101 101 unsigned int cl_protocol; 102 102 unsigned int cl_timewarn_cs; 103 + unsigned int cl_waitwarn_us; 103 104 }; 104 105 105 106 enum { ··· 115 114 CLUSTER_ATTR_LOG_DEBUG, 116 115 CLUSTER_ATTR_PROTOCOL, 117 116 CLUSTER_ATTR_TIMEWARN_CS, 117 + CLUSTER_ATTR_WAITWARN_US, 118 118 }; 119 119 120 120 struct cluster_attribute { ··· 168 166 CLUSTER_ATTR(log_debug, 0); 169 167 CLUSTER_ATTR(protocol, 0); 170 168 CLUSTER_ATTR(timewarn_cs, 1); 169 + CLUSTER_ATTR(waitwarn_us, 0); 171 170 172 171 static struct configfs_attribute *cluster_attrs[] = { 173 172 [CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr, ··· 182 179 [CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr, 183 180 [CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr, 184 181 [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr, 182 + [CLUSTER_ATTR_WAITWARN_US] = &cluster_attr_waitwarn_us.attr, 185 183 NULL, 186 184 }; 187 185 ··· 443 439 cl->cl_log_debug = dlm_config.ci_log_debug; 444 440 cl->cl_protocol = dlm_config.ci_protocol; 445 441 cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs; 442 + cl->cl_waitwarn_us = dlm_config.ci_waitwarn_us; 446 443 447 444 space_list = &sps->ss_group; 448 445 comm_list = &cms->cs_group; ··· 991 986 #define DEFAULT_LOG_DEBUG 0 992 987 #define DEFAULT_PROTOCOL 0 993 988 #define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */ 989 + #define DEFAULT_WAITWARN_US 0 994 990 995 991 struct dlm_config_info dlm_config = { 996 992 .ci_tcp_port = DEFAULT_TCP_PORT, ··· 1004 998 .ci_scan_secs = DEFAULT_SCAN_SECS, 1005 999 .ci_log_debug = DEFAULT_LOG_DEBUG, 1006 1000 .ci_protocol = DEFAULT_PROTOCOL, 1007 - .ci_timewarn_cs = DEFAULT_TIMEWARN_CS 1001 + .ci_timewarn_cs = DEFAULT_TIMEWARN_CS, 1002 + .ci_waitwarn_us = DEFAULT_WAITWARN_US 1008 1003 }; 1009 1004
+1
fs/dlm/config.h
··· 28 28 int ci_log_debug; 29 29 int ci_protocol; 30 30 int ci_timewarn_cs; 31 + int ci_waitwarn_us; 31 32 }; 32 33 33 34 extern struct dlm_config_info dlm_config;
+3
fs/dlm/dlm_internal.h
··· 209 209 #define DLM_IFL_WATCH_TIMEWARN 0x00400000 210 210 #define DLM_IFL_TIMEOUT_CANCEL 0x00800000 211 211 #define DLM_IFL_DEADLOCK_CANCEL 0x01000000 212 + #define DLM_IFL_STUB_MS 0x02000000 /* magic number for m_flags */ 212 213 #define DLM_IFL_USER 0x00000001 213 214 #define DLM_IFL_ORPHAN 0x00000002 214 215 ··· 246 245 247 246 int8_t lkb_wait_type; /* type of reply waiting for */ 248 247 int8_t lkb_wait_count; 248 + int lkb_wait_nodeid; /* for debugging */ 249 249 250 250 struct list_head lkb_idtbl_list; /* lockspace lkbtbl */ 251 251 struct list_head lkb_statequeue; /* rsb g/c/w list */ ··· 256 254 struct list_head lkb_ownqueue; /* list of locks for a process */ 257 255 struct list_head lkb_time_list; 258 256 ktime_t lkb_timestamp; 257 + ktime_t lkb_wait_time; 259 258 unsigned long lkb_timeout_cs; 260 259 261 260 struct dlm_callback lkb_callbacks[DLM_CALLBACKS_SIZE];
+142 -40
fs/dlm/lock.c
··· 799 799 return -1; 800 800 } 801 801 802 + static int nodeid_warned(int nodeid, int num_nodes, int *warned) 803 + { 804 + int i; 805 + 806 + for (i = 0; i < num_nodes; i++) { 807 + if (!warned[i]) { 808 + warned[i] = nodeid; 809 + return 0; 810 + } 811 + if (warned[i] == nodeid) 812 + return 1; 813 + } 814 + return 0; 815 + } 816 + 817 + void dlm_scan_waiters(struct dlm_ls *ls) 818 + { 819 + struct dlm_lkb *lkb; 820 + ktime_t zero = ktime_set(0, 0); 821 + s64 us; 822 + s64 debug_maxus = 0; 823 + u32 debug_scanned = 0; 824 + u32 debug_expired = 0; 825 + int num_nodes = 0; 826 + int *warned = NULL; 827 + 828 + if (!dlm_config.ci_waitwarn_us) 829 + return; 830 + 831 + mutex_lock(&ls->ls_waiters_mutex); 832 + 833 + list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { 834 + if (ktime_equal(lkb->lkb_wait_time, zero)) 835 + continue; 836 + 837 + debug_scanned++; 838 + 839 + us = ktime_to_us(ktime_sub(ktime_get(), lkb->lkb_wait_time)); 840 + 841 + if (us < dlm_config.ci_waitwarn_us) 842 + continue; 843 + 844 + lkb->lkb_wait_time = zero; 845 + 846 + debug_expired++; 847 + if (us > debug_maxus) 848 + debug_maxus = us; 849 + 850 + if (!num_nodes) { 851 + num_nodes = ls->ls_num_nodes; 852 + warned = kmalloc(GFP_KERNEL, num_nodes * sizeof(int)); 853 + if (warned) 854 + memset(warned, 0, num_nodes * sizeof(int)); 855 + } 856 + if (!warned) 857 + continue; 858 + if (nodeid_warned(lkb->lkb_wait_nodeid, num_nodes, warned)) 859 + continue; 860 + 861 + log_error(ls, "waitwarn %x %lld %d us check connection to " 862 + "node %d", lkb->lkb_id, (long long)us, 863 + dlm_config.ci_waitwarn_us, lkb->lkb_wait_nodeid); 864 + } 865 + mutex_unlock(&ls->ls_waiters_mutex); 866 + 867 + if (warned) 868 + kfree(warned); 869 + 870 + if (debug_expired) 871 + log_debug(ls, "scan_waiters %u warn %u over %d us max %lld us", 872 + debug_scanned, debug_expired, 873 + dlm_config.ci_waitwarn_us, (long long)debug_maxus); 874 + } 875 + 802 876 /* add/remove lkb from global waiters list of lkb's waiting for 803 877 a reply from a remote node */ 804 878 805 - static int add_to_waiters(struct dlm_lkb *lkb, int mstype) 879 + static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid) 806 880 { 807 881 struct dlm_ls *ls = lkb->lkb_resource->res_ls; 808 882 int error = 0; ··· 916 842 917 843 lkb->lkb_wait_count++; 918 844 lkb->lkb_wait_type = mstype; 845 + lkb->lkb_wait_time = ktime_get(); 846 + lkb->lkb_wait_nodeid = to_nodeid; /* for debugging */ 919 847 hold_lkb(lkb); 920 848 list_add(&lkb->lkb_wait_reply, &ls->ls_waiters); 921 849 out: ··· 1037 961 struct dlm_ls *ls = lkb->lkb_resource->res_ls; 1038 962 int error; 1039 963 1040 - if (ms != &ls->ls_stub_ms) 964 + if (ms->m_flags != DLM_IFL_STUB_MS) 1041 965 mutex_lock(&ls->ls_waiters_mutex); 1042 966 error = _remove_from_waiters(lkb, ms->m_type, ms); 1043 - if (ms != &ls->ls_stub_ms) 967 + if (ms->m_flags != DLM_IFL_STUB_MS) 1044 968 mutex_unlock(&ls->ls_waiters_mutex); 1045 969 return error; 1046 970 } ··· 1233 1157 list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) 1234 1158 lkb->lkb_timestamp = ktime_add_us(lkb->lkb_timestamp, adj_us); 1235 1159 mutex_unlock(&ls->ls_timeout_mutex); 1160 + 1161 + if (!dlm_config.ci_waitwarn_us) 1162 + return; 1163 + 1164 + mutex_lock(&ls->ls_waiters_mutex); 1165 + list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { 1166 + if (ktime_to_us(lkb->lkb_wait_time)) 1167 + lkb->lkb_wait_time = ktime_get(); 1168 + } 1169 + mutex_unlock(&ls->ls_waiters_mutex); 1236 1170 } 1237 1171 1238 1172 /* lkb is master or local copy */ ··· 1462 1376 ALTPR/ALTCW: our rqmode may have been changed to PR or CW to become 1463 1377 compatible with other granted locks */ 1464 1378 1465 - static void munge_demoted(struct dlm_lkb *lkb, struct dlm_message *ms) 1379 + static void munge_demoted(struct dlm_lkb *lkb) 1466 1380 { 1467 - if (ms->m_type != DLM_MSG_CONVERT_REPLY) { 1468 - log_print("munge_demoted %x invalid reply type %d", 1469 - lkb->lkb_id, ms->m_type); 1470 - return; 1471 - } 1472 - 1473 1381 if (lkb->lkb_rqmode == DLM_LOCK_IV || lkb->lkb_grmode == DLM_LOCK_IV) { 1474 1382 log_print("munge_demoted %x invalid modes gr %d rq %d", 1475 1383 lkb->lkb_id, lkb->lkb_grmode, lkb->lkb_rqmode); ··· 2924 2844 struct dlm_mhandle *mh; 2925 2845 int to_nodeid, error; 2926 2846 2927 - error = add_to_waiters(lkb, mstype); 2847 + to_nodeid = r->res_nodeid; 2848 + 2849 + error = add_to_waiters(lkb, mstype, to_nodeid); 2928 2850 if (error) 2929 2851 return error; 2930 - 2931 - to_nodeid = r->res_nodeid; 2932 2852 2933 2853 error = create_message(r, lkb, to_nodeid, mstype, &ms, &mh); 2934 2854 if (error) ··· 2960 2880 /* down conversions go without a reply from the master */ 2961 2881 if (!error && down_conversion(lkb)) { 2962 2882 remove_from_waiters(lkb, DLM_MSG_CONVERT_REPLY); 2883 + r->res_ls->ls_stub_ms.m_flags = DLM_IFL_STUB_MS; 2963 2884 r->res_ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY; 2964 2885 r->res_ls->ls_stub_ms.m_result = 0; 2965 - r->res_ls->ls_stub_ms.m_flags = lkb->lkb_flags; 2966 2886 __receive_convert_reply(r, lkb, &r->res_ls->ls_stub_ms); 2967 2887 } 2968 2888 ··· 3031 2951 struct dlm_mhandle *mh; 3032 2952 int to_nodeid, error; 3033 2953 3034 - error = add_to_waiters(lkb, DLM_MSG_LOOKUP); 2954 + to_nodeid = dlm_dir_nodeid(r); 2955 + 2956 + error = add_to_waiters(lkb, DLM_MSG_LOOKUP, to_nodeid); 3035 2957 if (error) 3036 2958 return error; 3037 - 3038 - to_nodeid = dlm_dir_nodeid(r); 3039 2959 3040 2960 error = create_message(r, NULL, to_nodeid, DLM_MSG_LOOKUP, &ms, &mh); 3041 2961 if (error) ··· 3150 3070 3151 3071 static void receive_flags_reply(struct dlm_lkb *lkb, struct dlm_message *ms) 3152 3072 { 3073 + if (ms->m_flags == DLM_IFL_STUB_MS) 3074 + return; 3075 + 3153 3076 lkb->lkb_sbflags = ms->m_sbflags; 3154 3077 lkb->lkb_flags = (lkb->lkb_flags & 0xFFFF0000) | 3155 3078 (ms->m_flags & 0x0000FFFF); ··· 3695 3612 /* convert was queued on remote master */ 3696 3613 receive_flags_reply(lkb, ms); 3697 3614 if (is_demoted(lkb)) 3698 - munge_demoted(lkb, ms); 3615 + munge_demoted(lkb); 3699 3616 del_lkb(r, lkb); 3700 3617 add_lkb(r, lkb, DLM_LKSTS_CONVERT); 3701 3618 add_timeout(lkb); ··· 3705 3622 /* convert was granted on remote master */ 3706 3623 receive_flags_reply(lkb, ms); 3707 3624 if (is_demoted(lkb)) 3708 - munge_demoted(lkb, ms); 3625 + munge_demoted(lkb); 3709 3626 grant_lock_pc(r, lkb, ms); 3710 3627 queue_cast(r, lkb, 0); 3711 3628 break; ··· 4079 3996 dlm_put_lockspace(ls); 4080 3997 } 4081 3998 4082 - static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb) 3999 + static void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb, 4000 + struct dlm_message *ms_stub) 4083 4001 { 4084 4002 if (middle_conversion(lkb)) { 4085 4003 hold_lkb(lkb); 4086 - ls->ls_stub_ms.m_type = DLM_MSG_CONVERT_REPLY; 4087 - ls->ls_stub_ms.m_result = -EINPROGRESS; 4088 - ls->ls_stub_ms.m_flags = lkb->lkb_flags; 4089 - ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid; 4090 - _receive_convert_reply(lkb, &ls->ls_stub_ms); 4004 + memset(ms_stub, 0, sizeof(struct dlm_message)); 4005 + ms_stub->m_flags = DLM_IFL_STUB_MS; 4006 + ms_stub->m_type = DLM_MSG_CONVERT_REPLY; 4007 + ms_stub->m_result = -EINPROGRESS; 4008 + ms_stub->m_header.h_nodeid = lkb->lkb_nodeid; 4009 + _receive_convert_reply(lkb, ms_stub); 4091 4010 4092 4011 /* Same special case as in receive_rcom_lock_args() */ 4093 4012 lkb->lkb_grmode = DLM_LOCK_IV; ··· 4130 4045 void dlm_recover_waiters_pre(struct dlm_ls *ls) 4131 4046 { 4132 4047 struct dlm_lkb *lkb, *safe; 4048 + struct dlm_message *ms_stub; 4133 4049 int wait_type, stub_unlock_result, stub_cancel_result; 4050 + 4051 + ms_stub = kmalloc(GFP_KERNEL, sizeof(struct dlm_message)); 4052 + if (!ms_stub) { 4053 + log_error(ls, "dlm_recover_waiters_pre no mem"); 4054 + return; 4055 + } 4134 4056 4135 4057 mutex_lock(&ls->ls_waiters_mutex); 4136 4058 4137 4059 list_for_each_entry_safe(lkb, safe, &ls->ls_waiters, lkb_wait_reply) { 4138 - log_debug(ls, "pre recover waiter lkid %x type %d flags %x", 4139 - lkb->lkb_id, lkb->lkb_wait_type, lkb->lkb_flags); 4060 + 4061 + /* exclude debug messages about unlocks because there can be so 4062 + many and they aren't very interesting */ 4063 + 4064 + if (lkb->lkb_wait_type != DLM_MSG_UNLOCK) { 4065 + log_debug(ls, "recover_waiter %x nodeid %d " 4066 + "msg %d to %d", lkb->lkb_id, lkb->lkb_nodeid, 4067 + lkb->lkb_wait_type, lkb->lkb_wait_nodeid); 4068 + } 4140 4069 4141 4070 /* all outstanding lookups, regardless of destination will be 4142 4071 resent after recovery is done */ ··· 4196 4097 break; 4197 4098 4198 4099 case DLM_MSG_CONVERT: 4199 - recover_convert_waiter(ls, lkb); 4100 + recover_convert_waiter(ls, lkb, ms_stub); 4200 4101 break; 4201 4102 4202 4103 case DLM_MSG_UNLOCK: 4203 4104 hold_lkb(lkb); 4204 - ls->ls_stub_ms.m_type = DLM_MSG_UNLOCK_REPLY; 4205 - ls->ls_stub_ms.m_result = stub_unlock_result; 4206 - ls->ls_stub_ms.m_flags = lkb->lkb_flags; 4207 - ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid; 4208 - _receive_unlock_reply(lkb, &ls->ls_stub_ms); 4105 + memset(ms_stub, 0, sizeof(struct dlm_message)); 4106 + ms_stub->m_flags = DLM_IFL_STUB_MS; 4107 + ms_stub->m_type = DLM_MSG_UNLOCK_REPLY; 4108 + ms_stub->m_result = stub_unlock_result; 4109 + ms_stub->m_header.h_nodeid = lkb->lkb_nodeid; 4110 + _receive_unlock_reply(lkb, ms_stub); 4209 4111 dlm_put_lkb(lkb); 4210 4112 break; 4211 4113 4212 4114 case DLM_MSG_CANCEL: 4213 4115 hold_lkb(lkb); 4214 - ls->ls_stub_ms.m_type = DLM_MSG_CANCEL_REPLY; 4215 - ls->ls_stub_ms.m_result = stub_cancel_result; 4216 - ls->ls_stub_ms.m_flags = lkb->lkb_flags; 4217 - ls->ls_stub_ms.m_header.h_nodeid = lkb->lkb_nodeid; 4218 - _receive_cancel_reply(lkb, &ls->ls_stub_ms); 4116 + memset(ms_stub, 0, sizeof(struct dlm_message)); 4117 + ms_stub->m_flags = DLM_IFL_STUB_MS; 4118 + ms_stub->m_type = DLM_MSG_CANCEL_REPLY; 4119 + ms_stub->m_result = stub_cancel_result; 4120 + ms_stub->m_header.h_nodeid = lkb->lkb_nodeid; 4121 + _receive_cancel_reply(lkb, ms_stub); 4219 4122 dlm_put_lkb(lkb); 4220 4123 break; 4221 4124 ··· 4228 4127 schedule(); 4229 4128 } 4230 4129 mutex_unlock(&ls->ls_waiters_mutex); 4130 + kfree(ms_stub); 4231 4131 } 4232 4132 4233 4133 static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls) ··· 4293 4191 ou = is_overlap_unlock(lkb); 4294 4192 err = 0; 4295 4193 4296 - log_debug(ls, "recover_waiters_post %x type %d flags %x %s", 4297 - lkb->lkb_id, mstype, lkb->lkb_flags, r->res_name); 4194 + log_debug(ls, "recover_waiter %x nodeid %d msg %d r_nodeid %d", 4195 + lkb->lkb_id, lkb->lkb_nodeid, mstype, r->res_nodeid); 4298 4196 4299 4197 /* At this point we assume that we won't get a reply to any 4300 4198 previous op or overlap op on this lock. First, do a big
+1
fs/dlm/lock.h
··· 24 24 void dlm_scan_rsbs(struct dlm_ls *ls); 25 25 int dlm_lock_recovery_try(struct dlm_ls *ls); 26 26 void dlm_unlock_recovery(struct dlm_ls *ls); 27 + void dlm_scan_waiters(struct dlm_ls *ls); 27 28 void dlm_scan_timeout(struct dlm_ls *ls); 28 29 void dlm_adjust_timeouts(struct dlm_ls *ls); 29 30
+3 -3
fs/dlm/lockspace.c
··· 243 243 static int dlm_scand(void *data) 244 244 { 245 245 struct dlm_ls *ls; 246 - int timeout_jiffies = dlm_config.ci_scan_secs * HZ; 247 246 248 247 while (!kthread_should_stop()) { 249 248 ls = find_ls_to_scan(); ··· 251 252 ls->ls_scan_time = jiffies; 252 253 dlm_scan_rsbs(ls); 253 254 dlm_scan_timeout(ls); 255 + dlm_scan_waiters(ls); 254 256 dlm_unlock_recovery(ls); 255 257 } else { 256 258 ls->ls_scan_time += HZ; 257 259 } 258 - } else { 259 - schedule_timeout_interruptible(timeout_jiffies); 260 + continue; 260 261 } 262 + schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); 261 263 } 262 264 return 0; 263 265 }
+61 -4
fs/dlm/plock.c
··· 71 71 wake_up(&send_wq); 72 72 } 73 73 74 + /* If a process was killed while waiting for the only plock on a file, 75 + locks_remove_posix will not see any lock on the file so it won't 76 + send an unlock-close to us to pass on to userspace to clean up the 77 + abandoned waiter. So, we have to insert the unlock-close when the 78 + lock call is interrupted. */ 79 + 80 + static void do_unlock_close(struct dlm_ls *ls, u64 number, 81 + struct file *file, struct file_lock *fl) 82 + { 83 + struct plock_op *op; 84 + 85 + op = kzalloc(sizeof(*op), GFP_NOFS); 86 + if (!op) 87 + return; 88 + 89 + op->info.optype = DLM_PLOCK_OP_UNLOCK; 90 + op->info.pid = fl->fl_pid; 91 + op->info.fsid = ls->ls_global_id; 92 + op->info.number = number; 93 + op->info.start = 0; 94 + op->info.end = OFFSET_MAX; 95 + if (fl->fl_lmops && fl->fl_lmops->fl_grant) 96 + op->info.owner = (__u64) fl->fl_pid; 97 + else 98 + op->info.owner = (__u64)(long) fl->fl_owner; 99 + 100 + op->info.flags |= DLM_PLOCK_FL_CLOSE; 101 + send_op(op); 102 + } 103 + 74 104 int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file, 75 105 int cmd, struct file_lock *fl) 76 106 { ··· 144 114 145 115 send_op(op); 146 116 147 - if (xop->callback == NULL) 148 - wait_event(recv_wq, (op->done != 0)); 149 - else { 117 + if (xop->callback == NULL) { 118 + rv = wait_event_killable(recv_wq, (op->done != 0)); 119 + if (rv == -ERESTARTSYS) { 120 + log_debug(ls, "dlm_posix_lock: wait killed %llx", 121 + (unsigned long long)number); 122 + spin_lock(&ops_lock); 123 + list_del(&op->list); 124 + spin_unlock(&ops_lock); 125 + kfree(xop); 126 + do_unlock_close(ls, number, file, fl); 127 + goto out; 128 + } 129 + } else { 150 130 rv = FILE_LOCK_DEFERRED; 151 131 goto out; 152 132 } ··· 273 233 else 274 234 op->info.owner = (__u64)(long) fl->fl_owner; 275 235 236 + if (fl->fl_flags & FL_CLOSE) { 237 + op->info.flags |= DLM_PLOCK_FL_CLOSE; 238 + send_op(op); 239 + rv = 0; 240 + goto out; 241 + } 242 + 276 243 send_op(op); 277 244 wait_event(recv_wq, (op->done != 0)); 278 245 ··· 381 334 spin_lock(&ops_lock); 382 335 if (!list_empty(&send_list)) { 383 336 op = list_entry(send_list.next, struct plock_op, list); 384 - list_move(&op->list, &recv_list); 337 + if (op->info.flags & DLM_PLOCK_FL_CLOSE) 338 + list_del(&op->list); 339 + else 340 + list_move(&op->list, &recv_list); 385 341 memcpy(&info, &op->info, sizeof(info)); 386 342 } 387 343 spin_unlock(&ops_lock); 388 344 389 345 if (!op) 390 346 return -EAGAIN; 347 + 348 + /* there is no need to get a reply from userspace for unlocks 349 + that were generated by the vfs cleaning up for a close 350 + (the process did not make an unlock call). */ 351 + 352 + if (op->info.flags & DLM_PLOCK_FL_CLOSE) 353 + kfree(op); 391 354 392 355 if (copy_to_user(u, &info, sizeof(info))) 393 356 return -EFAULT;
-1
fs/dlm/user.c
··· 611 611 612 612 out_sig: 613 613 sigprocmask(SIG_SETMASK, &tmpsig, NULL); 614 - recalc_sigpending(); 615 614 out_free: 616 615 kfree(kbuf); 617 616 return error;
+4 -2
include/linux/dlm_plock.h
··· 14 14 #define DLM_PLOCK_MISC_NAME "dlm_plock" 15 15 16 16 #define DLM_PLOCK_VERSION_MAJOR 1 17 - #define DLM_PLOCK_VERSION_MINOR 1 17 + #define DLM_PLOCK_VERSION_MINOR 2 18 18 #define DLM_PLOCK_VERSION_PATCH 0 19 19 20 20 enum { ··· 23 23 DLM_PLOCK_OP_GET, 24 24 }; 25 25 26 + #define DLM_PLOCK_FL_CLOSE 1 27 + 26 28 struct dlm_plock_info { 27 29 __u32 version[3]; 28 30 __u8 optype; 29 31 __u8 ex; 30 32 __u8 wait; 31 - __u8 pad; 33 + __u8 flags; 32 34 __u32 pid; 33 35 __s32 nodeid; 34 36 __s32 rv;