| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /****************************************************************************** |
|---|
| 2 | 3 | ******************************************************************************* |
|---|
| 3 | 4 | ** |
|---|
| 4 | 5 | ** Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved. |
|---|
| 5 | 6 | ** |
|---|
| 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 | 7 | ** |
|---|
| 10 | 8 | ******************************************************************************* |
|---|
| 11 | 9 | ******************************************************************************/ |
|---|
| .. | .. |
|---|
| 1553 | 1551 | lkb->lkb_wait_type = 0; |
|---|
| 1554 | 1552 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; |
|---|
| 1555 | 1553 | lkb->lkb_wait_count--; |
|---|
| 1554 | + unhold_lkb(lkb); |
|---|
| 1556 | 1555 | goto out_del; |
|---|
| 1557 | 1556 | } |
|---|
| 1558 | 1557 | |
|---|
| .. | .. |
|---|
| 1579 | 1578 | log_error(ls, "remwait error %x reply %d wait_type %d overlap", |
|---|
| 1580 | 1579 | lkb->lkb_id, mstype, lkb->lkb_wait_type); |
|---|
| 1581 | 1580 | lkb->lkb_wait_count--; |
|---|
| 1581 | + unhold_lkb(lkb); |
|---|
| 1582 | 1582 | lkb->lkb_wait_type = 0; |
|---|
| 1583 | 1583 | } |
|---|
| 1584 | 1584 | |
|---|
| .. | .. |
|---|
| 1856 | 1856 | void dlm_scan_timeout(struct dlm_ls *ls) |
|---|
| 1857 | 1857 | { |
|---|
| 1858 | 1858 | struct dlm_rsb *r; |
|---|
| 1859 | | - struct dlm_lkb *lkb; |
|---|
| 1859 | + struct dlm_lkb *lkb = NULL, *iter; |
|---|
| 1860 | 1860 | int do_cancel, do_warn; |
|---|
| 1861 | 1861 | s64 wait_us; |
|---|
| 1862 | 1862 | |
|---|
| .. | .. |
|---|
| 1867 | 1867 | do_cancel = 0; |
|---|
| 1868 | 1868 | do_warn = 0; |
|---|
| 1869 | 1869 | mutex_lock(&ls->ls_timeout_mutex); |
|---|
| 1870 | | - list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) { |
|---|
| 1870 | + list_for_each_entry(iter, &ls->ls_timeout, lkb_time_list) { |
|---|
| 1871 | 1871 | |
|---|
| 1872 | 1872 | wait_us = ktime_to_us(ktime_sub(ktime_get(), |
|---|
| 1873 | | - lkb->lkb_timestamp)); |
|---|
| 1873 | + iter->lkb_timestamp)); |
|---|
| 1874 | 1874 | |
|---|
| 1875 | | - if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) && |
|---|
| 1876 | | - wait_us >= (lkb->lkb_timeout_cs * 10000)) |
|---|
| 1875 | + if ((iter->lkb_exflags & DLM_LKF_TIMEOUT) && |
|---|
| 1876 | + wait_us >= (iter->lkb_timeout_cs * 10000)) |
|---|
| 1877 | 1877 | do_cancel = 1; |
|---|
| 1878 | 1878 | |
|---|
| 1879 | | - if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) && |
|---|
| 1879 | + if ((iter->lkb_flags & DLM_IFL_WATCH_TIMEWARN) && |
|---|
| 1880 | 1880 | wait_us >= dlm_config.ci_timewarn_cs * 10000) |
|---|
| 1881 | 1881 | do_warn = 1; |
|---|
| 1882 | 1882 | |
|---|
| 1883 | 1883 | if (!do_cancel && !do_warn) |
|---|
| 1884 | 1884 | continue; |
|---|
| 1885 | | - hold_lkb(lkb); |
|---|
| 1885 | + hold_lkb(iter); |
|---|
| 1886 | + lkb = iter; |
|---|
| 1886 | 1887 | break; |
|---|
| 1887 | 1888 | } |
|---|
| 1888 | 1889 | mutex_unlock(&ls->ls_timeout_mutex); |
|---|
| 1889 | 1890 | |
|---|
| 1890 | | - if (!do_cancel && !do_warn) |
|---|
| 1891 | + if (!lkb) |
|---|
| 1891 | 1892 | break; |
|---|
| 1892 | 1893 | |
|---|
| 1893 | 1894 | r = lkb->lkb_resource; |
|---|
| .. | .. |
|---|
| 2888 | 2889 | static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, |
|---|
| 2889 | 2890 | struct dlm_args *args) |
|---|
| 2890 | 2891 | { |
|---|
| 2891 | | - int rv = -EINVAL; |
|---|
| 2892 | + int rv = -EBUSY; |
|---|
| 2892 | 2893 | |
|---|
| 2893 | 2894 | if (args->flags & DLM_LKF_CONVERT) { |
|---|
| 2894 | | - if (lkb->lkb_flags & DLM_IFL_MSTCPY) |
|---|
| 2895 | | - goto out; |
|---|
| 2896 | | - |
|---|
| 2897 | | - if (args->flags & DLM_LKF_QUECVT && |
|---|
| 2898 | | - !__quecvt_compat_matrix[lkb->lkb_grmode+1][args->mode+1]) |
|---|
| 2899 | | - goto out; |
|---|
| 2900 | | - |
|---|
| 2901 | | - rv = -EBUSY; |
|---|
| 2902 | 2895 | if (lkb->lkb_status != DLM_LKSTS_GRANTED) |
|---|
| 2903 | 2896 | goto out; |
|---|
| 2904 | 2897 | |
|---|
| .. | .. |
|---|
| 2906 | 2899 | goto out; |
|---|
| 2907 | 2900 | |
|---|
| 2908 | 2901 | if (is_overlap(lkb)) |
|---|
| 2902 | + goto out; |
|---|
| 2903 | + |
|---|
| 2904 | + rv = -EINVAL; |
|---|
| 2905 | + if (lkb->lkb_flags & DLM_IFL_MSTCPY) |
|---|
| 2906 | + goto out; |
|---|
| 2907 | + |
|---|
| 2908 | + if (args->flags & DLM_LKF_QUECVT && |
|---|
| 2909 | + !__quecvt_compat_matrix[lkb->lkb_grmode+1][args->mode+1]) |
|---|
| 2909 | 2910 | goto out; |
|---|
| 2910 | 2911 | } |
|---|
| 2911 | 2912 | |
|---|
| .. | .. |
|---|
| 4067 | 4068 | rv = _create_message(ls, sizeof(struct dlm_message) + len, |
|---|
| 4068 | 4069 | dir_nodeid, DLM_MSG_REMOVE, &ms, &mh); |
|---|
| 4069 | 4070 | if (rv) |
|---|
| 4070 | | - return; |
|---|
| 4071 | + goto out; |
|---|
| 4071 | 4072 | |
|---|
| 4072 | 4073 | memcpy(ms->m_extra, name, len); |
|---|
| 4073 | 4074 | ms->m_hash = hash; |
|---|
| 4074 | 4075 | |
|---|
| 4075 | 4076 | send_message(mh, ms); |
|---|
| 4076 | 4077 | |
|---|
| 4078 | +out: |
|---|
| 4077 | 4079 | spin_lock(&ls->ls_remove_spin); |
|---|
| 4078 | 4080 | ls->ls_remove_len = 0; |
|---|
| 4079 | 4081 | memset(ls->ls_remove_name, 0, DLM_RESNAME_MAXLEN); |
|---|
| .. | .. |
|---|
| 5240 | 5242 | |
|---|
| 5241 | 5243 | static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls) |
|---|
| 5242 | 5244 | { |
|---|
| 5243 | | - struct dlm_lkb *lkb; |
|---|
| 5244 | | - int found = 0; |
|---|
| 5245 | + struct dlm_lkb *lkb = NULL, *iter; |
|---|
| 5245 | 5246 | |
|---|
| 5246 | 5247 | mutex_lock(&ls->ls_waiters_mutex); |
|---|
| 5247 | | - list_for_each_entry(lkb, &ls->ls_waiters, lkb_wait_reply) { |
|---|
| 5248 | | - if (lkb->lkb_flags & DLM_IFL_RESEND) { |
|---|
| 5249 | | - hold_lkb(lkb); |
|---|
| 5250 | | - found = 1; |
|---|
| 5248 | + list_for_each_entry(iter, &ls->ls_waiters, lkb_wait_reply) { |
|---|
| 5249 | + if (iter->lkb_flags & DLM_IFL_RESEND) { |
|---|
| 5250 | + hold_lkb(iter); |
|---|
| 5251 | + lkb = iter; |
|---|
| 5251 | 5252 | break; |
|---|
| 5252 | 5253 | } |
|---|
| 5253 | 5254 | } |
|---|
| 5254 | 5255 | mutex_unlock(&ls->ls_waiters_mutex); |
|---|
| 5255 | 5256 | |
|---|
| 5256 | | - if (!found) |
|---|
| 5257 | | - lkb = NULL; |
|---|
| 5258 | 5257 | return lkb; |
|---|
| 5259 | 5258 | } |
|---|
| 5260 | 5259 | |
|---|
| .. | .. |
|---|
| 5314 | 5313 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK; |
|---|
| 5315 | 5314 | lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL; |
|---|
| 5316 | 5315 | lkb->lkb_wait_type = 0; |
|---|
| 5317 | | - lkb->lkb_wait_count = 0; |
|---|
| 5316 | + /* drop all wait_count references we still |
|---|
| 5317 | + * hold a reference for this iteration. |
|---|
| 5318 | + */ |
|---|
| 5319 | + while (lkb->lkb_wait_count) { |
|---|
| 5320 | + lkb->lkb_wait_count--; |
|---|
| 5321 | + unhold_lkb(lkb); |
|---|
| 5322 | + } |
|---|
| 5318 | 5323 | mutex_lock(&ls->ls_waiters_mutex); |
|---|
| 5319 | 5324 | list_del_init(&lkb->lkb_wait_reply); |
|---|
| 5320 | 5325 | mutex_unlock(&ls->ls_waiters_mutex); |
|---|
| 5321 | | - unhold_lkb(lkb); /* for waiters list */ |
|---|
| 5322 | 5326 | |
|---|
| 5323 | 5327 | if (oc || ou) { |
|---|
| 5324 | 5328 | /* do an unlock or cancel instead of resending */ |
|---|
| .. | .. |
|---|
| 5828 | 5832 | break; |
|---|
| 5829 | 5833 | case -EAGAIN: |
|---|
| 5830 | 5834 | error = 0; |
|---|
| 5831 | | - /* fall through */ |
|---|
| 5835 | + fallthrough; |
|---|
| 5832 | 5836 | default: |
|---|
| 5833 | 5837 | __put_lkb(ls, lkb); |
|---|
| 5834 | 5838 | goto out; |
|---|
| .. | .. |
|---|
| 5908 | 5912 | int mode, uint32_t flags, void *name, unsigned int namelen, |
|---|
| 5909 | 5913 | unsigned long timeout_cs, uint32_t *lkid) |
|---|
| 5910 | 5914 | { |
|---|
| 5911 | | - struct dlm_lkb *lkb; |
|---|
| 5915 | + struct dlm_lkb *lkb = NULL, *iter; |
|---|
| 5912 | 5916 | struct dlm_user_args *ua; |
|---|
| 5913 | 5917 | int found_other_mode = 0; |
|---|
| 5914 | | - int found = 0; |
|---|
| 5915 | 5918 | int rv = 0; |
|---|
| 5916 | 5919 | |
|---|
| 5917 | 5920 | mutex_lock(&ls->ls_orphans_mutex); |
|---|
| 5918 | | - list_for_each_entry(lkb, &ls->ls_orphans, lkb_ownqueue) { |
|---|
| 5919 | | - if (lkb->lkb_resource->res_length != namelen) |
|---|
| 5921 | + list_for_each_entry(iter, &ls->ls_orphans, lkb_ownqueue) { |
|---|
| 5922 | + if (iter->lkb_resource->res_length != namelen) |
|---|
| 5920 | 5923 | continue; |
|---|
| 5921 | | - if (memcmp(lkb->lkb_resource->res_name, name, namelen)) |
|---|
| 5924 | + if (memcmp(iter->lkb_resource->res_name, name, namelen)) |
|---|
| 5922 | 5925 | continue; |
|---|
| 5923 | | - if (lkb->lkb_grmode != mode) { |
|---|
| 5926 | + if (iter->lkb_grmode != mode) { |
|---|
| 5924 | 5927 | found_other_mode = 1; |
|---|
| 5925 | 5928 | continue; |
|---|
| 5926 | 5929 | } |
|---|
| 5927 | 5930 | |
|---|
| 5928 | | - found = 1; |
|---|
| 5929 | | - list_del_init(&lkb->lkb_ownqueue); |
|---|
| 5930 | | - lkb->lkb_flags &= ~DLM_IFL_ORPHAN; |
|---|
| 5931 | | - *lkid = lkb->lkb_id; |
|---|
| 5931 | + lkb = iter; |
|---|
| 5932 | + list_del_init(&iter->lkb_ownqueue); |
|---|
| 5933 | + iter->lkb_flags &= ~DLM_IFL_ORPHAN; |
|---|
| 5934 | + *lkid = iter->lkb_id; |
|---|
| 5932 | 5935 | break; |
|---|
| 5933 | 5936 | } |
|---|
| 5934 | 5937 | mutex_unlock(&ls->ls_orphans_mutex); |
|---|
| 5935 | 5938 | |
|---|
| 5936 | | - if (!found && found_other_mode) { |
|---|
| 5939 | + if (!lkb && found_other_mode) { |
|---|
| 5937 | 5940 | rv = -EAGAIN; |
|---|
| 5938 | 5941 | goto out; |
|---|
| 5939 | 5942 | } |
|---|
| 5940 | 5943 | |
|---|
| 5941 | | - if (!found) { |
|---|
| 5944 | + if (!lkb) { |
|---|
| 5942 | 5945 | rv = -ENOENT; |
|---|
| 5943 | 5946 | goto out; |
|---|
| 5944 | 5947 | } |
|---|