Hi,

On Thu, Feb 16, 2023 at 8:06 PM Alexander Aring <aahri...@redhat.com> wrote:
>
> This patch moves all upper bits of lkb->lkb_flags to lkb->lkb_insflags,
> except DLM_IFL_STUB_MS which needs a special handling. Those upper bits
> are non shared internal flags which should be separated from
> lkb->lkb_flags because they get read, masked and assigned again in
> a non atomic way e.g. in receive_flags(). Due concurrent possible flag
> like dlm_lock()/unlock() or user device handling changes could be
> reverted. When moving to lkb->lkb_insflags we converted all bit
> operations to atomic set/test/clear bit operation functions.
>
> Signed-off-by: Alexander Aring <aahri...@redhat.com>
> ---
>  fs/dlm/dlm_internal.h      |  32 +++++------
>  fs/dlm/lock.c              | 114 ++++++++++++++++++-------------------
>  fs/dlm/lockspace.c         |   2 +-
>  fs/dlm/recover.c           |   2 +-
>  fs/dlm/user.c              |  10 ++--
>  include/trace/events/dlm.h |   7 ---
>  6 files changed, 79 insertions(+), 88 deletions(-)
>
> diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
> index b967b4d7d55d..ce0a15858ae3 100644
> --- a/fs/dlm/dlm_internal.h
> +++ b/fs/dlm/dlm_internal.h
> @@ -197,26 +197,25 @@ struct dlm_args {
>  #define DLM_LKSTS_GRANTED      2
>  #define DLM_LKSTS_CONVERT      3
>
> -/* lkb_flags */
> -
> -#define DLM_IFL_MSTCPY         0x00010000
> -#define DLM_IFL_RESEND         0x00020000
> -#define DLM_IFL_DEAD           0x00040000
> -#define DLM_IFL_OVERLAP_UNLOCK  0x00080000
> -#define DLM_IFL_OVERLAP_CANCEL  0x00100000
> -#define DLM_IFL_ENDOFLIFE      0x00200000
> -#ifdef CONFIG_DLM_DEPRECATED_API
> -#define DLM_IFL_WATCH_TIMEWARN 0x00400000
> -#define DLM_IFL_TIMEOUT_CANCEL 0x00800000
> -#endif
> -#define DLM_IFL_DEADLOCK_CANCEL        0x01000000
> -#define DLM_IFL_STUB_MS                0x02000000 /* magic number for 
> m_flags */
> -
>  /* lkb_insflags */
>
>  #define DLM_IFLNS_CB_PENDING   0
> +#define DLM_IFLNS_MSTCPY       1
> +#define DLM_IFLNS_RESEND       2
> +#define DLM_IFLNS_DEAD         3
> +#define DLM_IFLNS_OVERLAP_UNLOCK 4
> +#define DLM_IFLNS_OVERLAP_CANCEL 5
> +#define DLM_IFLNS_ENDOFLIFE    6
> +#ifdef CONFIG_DLM_DEPRECATED_API
> +#define DLM_IFLNS_WATCH_TIMEWARN 7
> +#define DLM_IFLNS_TIMEOUT_CANCEL 8
> +#endif
> +#define DLM_IFLNS_DEADLOCK_CANCEL 9
> +
>
> -/* least significant 2 bytes are message changed, they are full transmitted
> +/* lkb_flags
> + *
> + * least significant 2 bytes are message changed, they are full transmitted
>   * but at receive side only the 2 bytes LSB will be set.
>   *
>   * Even wireshark dlm dissector does only evaluate the lower bytes and note
> @@ -226,6 +225,7 @@ struct dlm_args {
>   */
>  #define DLM_IFL_USER           0x00000001
>  #define DLM_IFL_ORPHAN         0x00000002
> +#define DLM_IFL_STUB_MS                0x00010000
>
>  #define DLM_CB_CAST            0x00000001
>  #define DLM_CB_BAST            0x00000002
> diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
> index e1adfa5aed05..b73f809f4012 100644
> --- a/fs/dlm/lock.c
> +++ b/fs/dlm/lock.c
> @@ -250,12 +250,12 @@ static inline int is_remote(struct dlm_rsb *r)
>
>  static inline int is_process_copy(struct dlm_lkb *lkb)
>  {
> -       return (lkb->lkb_nodeid && !(lkb->lkb_flags & DLM_IFL_MSTCPY));
> +       return lkb->lkb_nodeid && !test_bit(DLM_IFLNS_MSTCPY, 
> &lkb->lkb_insflags);
>  }
>
>  static inline int is_master_copy(struct dlm_lkb *lkb)
>  {
> -       return (lkb->lkb_flags & DLM_IFL_MSTCPY) ? 1 : 0;
> +       return test_bit(DLM_IFLNS_MSTCPY, &lkb->lkb_insflags);
>  }
>
>  static inline int middle_conversion(struct dlm_lkb *lkb)
> @@ -273,18 +273,18 @@ static inline int down_conversion(struct dlm_lkb *lkb)
>
>  static inline int is_overlap_unlock(struct dlm_lkb *lkb)
>  {
> -       return lkb->lkb_flags & DLM_IFL_OVERLAP_UNLOCK;
> +       return test_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags);
>  }
>
>  static inline int is_overlap_cancel(struct dlm_lkb *lkb)
>  {
> -       return lkb->lkb_flags & DLM_IFL_OVERLAP_CANCEL;
> +       return test_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
>  }
>
>  static inline int is_overlap(struct dlm_lkb *lkb)
>  {
> -       return (lkb->lkb_flags & (DLM_IFL_OVERLAP_UNLOCK |
> -                                 DLM_IFL_OVERLAP_CANCEL));
> +       return test_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags) ||
> +              test_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
>  }
>
>  static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
> @@ -299,16 +299,12 @@ static void queue_cast(struct dlm_rsb *r, struct 
> dlm_lkb *lkb, int rv)
>  #ifdef CONFIG_DLM_DEPRECATED_API
>         /* if the operation was a cancel, then return -DLM_ECANCEL, if a
>            timeout caused the cancel then return -ETIMEDOUT */
> -       if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
> -               lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
> +       if (rv == -DLM_ECANCEL && 
> test_and_clear_bit(DLM_IFLNS_TIMEOUT_CANCEL, &lkb->lkb_insflags))
>                 rv = -ETIMEDOUT;
> -       }
>  #endif
>
> -       if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) 
> {
> -               lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL;
> +       if (rv == -DLM_ECANCEL && 
> test_and_clear_bit(DLM_IFLNS_DEADLOCK_CANCEL, &lkb->lkb_insflags))
>                 rv = -EDEADLK;
> -       }
>
>         dlm_add_cb(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, lkb->lkb_sbflags);
>  }
> @@ -1434,10 +1430,10 @@ static int add_to_waiters(struct dlm_lkb *lkb, int 
> mstype, int to_nodeid)
>         if (lkb->lkb_wait_type || is_overlap_cancel(lkb)) {
>                 switch (mstype) {
>                 case DLM_MSG_UNLOCK:
> -                       lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
> +                       set_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags);
>                         break;
>                 case DLM_MSG_CANCEL:
> -                       lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
> +                       set_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
>                         break;
>                 default:
>                         error = -EBUSY;
> @@ -1481,16 +1477,16 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, 
> int mstype,
>         struct dlm_ls *ls = lkb->lkb_resource->res_ls;
>         int overlap_done = 0;
>
> -       if (is_overlap_unlock(lkb) && (mstype == DLM_MSG_UNLOCK_REPLY)) {
> +       if (mstype == DLM_MSG_UNLOCK_REPLY &&
> +           test_and_clear_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags)) 
> {
>                 log_debug(ls, "remwait %x unlock_reply overlap", lkb->lkb_id);
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
>                 overlap_done = 1;
>                 goto out_del;
>         }
>
> -       if (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL_REPLY)) {
> +       if (mstype == DLM_MSG_CANCEL_REPLY &&
> +           test_and_clear_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags)) 
> {
>                 log_debug(ls, "remwait %x cancel_reply overlap", lkb->lkb_id);
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
>                 overlap_done = 1;
>                 goto out_del;
>         }
> @@ -1515,11 +1511,11 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, 
> int mstype,
>
>         if ((mstype == DLM_MSG_CONVERT_REPLY) &&
>             (lkb->lkb_wait_type == DLM_MSG_CONVERT) &&
> -           is_overlap_cancel(lkb) && ms && !ms->m_result) {
> +           ms && !ms->m_result && 
> test_and_clear_bit(DLM_IFLNS_OVERLAP_CANCEL,
> +                                                     &lkb->lkb_insflags)) {
>                 log_debug(ls, "remwait %x convert_reply zap overlap_cancel",
>                           lkb->lkb_id);
>                 lkb->lkb_wait_type = 0;
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
>                 lkb->lkb_wait_count--;
>                 unhold_lkb(lkb);
>                 goto out_del;
> @@ -1554,7 +1550,7 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, 
> int mstype,
>
>         DLM_ASSERT(lkb->lkb_wait_count, dlm_print_lkb(lkb););
>
> -       lkb->lkb_flags &= ~DLM_IFL_RESEND;
> +       clear_bit(DLM_IFLNS_RESEND, &lkb->lkb_insflags);
>         lkb->lkb_wait_count--;
>         if (!lkb->lkb_wait_count)
>                 list_del_init(&lkb->lkb_wait_reply);
> @@ -1745,7 +1741,7 @@ static void add_timeout(struct dlm_lkb *lkb)
>
>         if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
>             !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
> -               lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
> +               set_bit(DLM_IFLNS_WATCH_TIMEWARN, &lkb->lkb_insflags);
>                 goto add_it;
>         }
>         if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
> @@ -1801,7 +1797,7 @@ void dlm_scan_timeout(struct dlm_ls *ls)
>                             wait_us >= (iter->lkb_timeout_cs * 10000))
>                                 do_cancel = 1;
>
> -                       if ((iter->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
> +                       if (test_bit(DLM_IFLNS_WATCH_TIMEWARN, 
> &iter->lkb_insflags) &&
>                             wait_us >= dlm_config.ci_timewarn_cs * 10000)
>                                 do_warn = 1;
>
> @@ -1822,7 +1818,7 @@ void dlm_scan_timeout(struct dlm_ls *ls)
>
>                 if (do_warn) {
>                         /* clear flag so we only warn once */
> -                       lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
> +                       clear_bit(DLM_IFLNS_WATCH_TIMEWARN, 
> &lkb->lkb_insflags);
>                         if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
>                                 del_timeout(lkb);
>                         dlm_timeout_warn(lkb);
> @@ -1831,8 +1827,8 @@ void dlm_scan_timeout(struct dlm_ls *ls)
>                 if (do_cancel) {
>                         log_debug(ls, "timeout cancel %x node %d %s",
>                                   lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
> -                       lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
> -                       lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
> +                       clear_bit(DLM_IFLNS_WATCH_TIMEWARN, 
> &lkb->lkb_insflags);
> +                       set_bit(DLM_IFLNS_TIMEOUT_CANCEL, &lkb->lkb_insflags);
>                         del_timeout(lkb);
>                         _cancel_lock(r, lkb);
>                 }
> @@ -2830,7 +2826,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct 
> dlm_lkb *lkb,
>                         goto out;
>
>                 rv = -EINVAL;
> -               if (lkb->lkb_flags & DLM_IFL_MSTCPY)
> +               if (test_bit(DLM_IFLNS_MSTCPY, &lkb->lkb_insflags))
>                         goto out;
>
>                 if (args->flags & DLM_LKF_QUECVT &&
> @@ -2908,7 +2904,7 @@ static int validate_unlock_args(struct dlm_lkb *lkb, 
> struct dlm_args *args)
>         }
>
>         rv = -EINVAL;
> -       if (lkb->lkb_flags & DLM_IFL_MSTCPY) {
> +       if (test_bit(DLM_IFLNS_MSTCPY, &lkb->lkb_insflags)) {
>                 log_error(ls, "unlock on MSTCPY %x", lkb->lkb_id);
>                 dlm_print_lkb(lkb);
>                 goto out;
> @@ -2919,7 +2915,7 @@ static int validate_unlock_args(struct dlm_lkb *lkb, 
> struct dlm_args *args)
>          * locks; return same error as if the lkid had not been found at all
>          */
>
> -       if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) {
> +       if (test_bit(DLM_IFLNS_ENDOFLIFE, &lkb->lkb_insflags)) {
>                 log_debug(ls, "unlock on ENDOFLIFE %x", lkb->lkb_id);
>                 rv = -ENOENT;
>                 goto out;
> @@ -2937,8 +2933,8 @@ static int validate_unlock_args(struct dlm_lkb *lkb, 
> struct dlm_args *args)
>                 /* don't let scand try to do a cancel */
>                 del_timeout(lkb);
>
> -               if (lkb->lkb_flags & DLM_IFL_RESEND) {
> -                       lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
> +               if (test_bit(DLM_IFLNS_RESEND, &lkb->lkb_insflags)) {
> +                       set_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
>                         rv = -EBUSY;
>                         goto out;
>                 }
> @@ -2953,7 +2949,7 @@ static int validate_unlock_args(struct dlm_lkb *lkb, 
> struct dlm_args *args)
>                 switch (lkb->lkb_wait_type) {
>                 case DLM_MSG_LOOKUP:
>                 case DLM_MSG_REQUEST:
> -                       lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
> +                       set_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
>                         rv = -EBUSY;
>                         goto out;
>                 case DLM_MSG_UNLOCK:
> @@ -2978,8 +2974,8 @@ static int validate_unlock_args(struct dlm_lkb *lkb, 
> struct dlm_args *args)
>                 /* don't let scand try to do a cancel */
>                 del_timeout(lkb);
>
> -               if (lkb->lkb_flags & DLM_IFL_RESEND) {
> -                       lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
> +               if (test_bit(DLM_IFLNS_RESEND, &lkb->lkb_insflags)) {
> +                       set_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags);
>                         rv = -EBUSY;
>                         goto out;
>                 }
> @@ -2987,7 +2983,7 @@ static int validate_unlock_args(struct dlm_lkb *lkb, 
> struct dlm_args *args)
>                 switch (lkb->lkb_wait_type) {
>                 case DLM_MSG_LOOKUP:
>                 case DLM_MSG_REQUEST:
> -                       lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
> +                       set_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags);
>                         rv = -EBUSY;
>                         goto out;
>                 case DLM_MSG_UNLOCK:
> @@ -4016,7 +4012,7 @@ static int receive_request(struct dlm_ls *ls, struct 
> dlm_message *ms)
>                 goto fail;
>
>         receive_flags(lkb, ms);
> -       lkb->lkb_flags |= DLM_IFL_MSTCPY;
> +       set_bit(DLM_IFLNS_MSTCPY, &lkb->lkb_insflags);
>         error = receive_request_args(ls, lkb, ms);
>         if (error) {
>                 __put_lkb(ls, lkb);
> @@ -4496,20 +4492,20 @@ static int receive_request_reply(struct dlm_ls *ls, 
> struct dlm_message *ms)
>                           lkb->lkb_id, result);
>         }
>
> -       if (is_overlap_unlock(lkb) && (result == 0 || result == 
> -EINPROGRESS)) {
> +       if ((result == 0 || result == -EINPROGRESS) &&
> +           test_and_clear_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags)) 
> {
>                 log_debug(ls, "receive_request_reply %x result %d unlock",
>                           lkb->lkb_id, result);
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
> +               clear_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
>                 send_unlock(r, lkb);
> -       } else if (is_overlap_cancel(lkb) && (result == -EINPROGRESS)) {
> +       } else if ((result == -EINPROGRESS) &&
> +                  test_and_clear_bit(DLM_IFLNS_OVERLAP_CANCEL, 
> &lkb->lkb_insflags)) {
>                 log_debug(ls, "receive_request_reply %x cancel", lkb->lkb_id);
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
> +               clear_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags);
>                 send_cancel(r, lkb);
>         } else {
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_CANCEL;
> -               lkb->lkb_flags &= ~DLM_IFL_OVERLAP_UNLOCK;
> +               clear_bit(DLM_IFLNS_OVERLAP_CANCEL, &lkb->lkb_insflags);
> +               clear_bit(DLM_IFLNS_OVERLAP_UNLOCK, &lkb->lkb_insflags);
>         }
>   out:
>         unlock_rsb(r);
> @@ -5023,7 +5019,7 @@ static void recover_convert_waiter(struct dlm_ls *ls, 
> struct dlm_lkb *lkb,
>                 unhold_lkb(lkb);
>
>         } else if (lkb->lkb_rqmode >= lkb->lkb_grmode) {
> -               lkb->lkb_flags |= DLM_IFL_RESEND;
> +               set_bit(DLM_IFLNS_RESEND, &lkb->lkb_insflags);
>         }
>
>         /* lkb->lkb_rqmode < lkb->lkb_grmode shouldn't happen since down
> @@ -5087,7 +5083,7 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
>                    resent after recovery is done */
>
>                 if (lkb->lkb_wait_type == DLM_MSG_LOOKUP) {
> -                       lkb->lkb_flags |= DLM_IFL_RESEND;
> +                       set_bit(DLM_IFLNS_RESEND, &lkb->lkb_insflags);
>                         continue;
>                 }
>
> @@ -5123,7 +5119,7 @@ void dlm_recover_waiters_pre(struct dlm_ls *ls)
>                 switch (wait_type) {
>
>                 case DLM_MSG_REQUEST:
> -                       lkb->lkb_flags |= DLM_IFL_RESEND;
> +                       set_bit(DLM_IFLNS_RESEND, &lkb->lkb_insflags);
>                         break;
>
>                 case DLM_MSG_CONVERT:
> @@ -5168,7 +5164,7 @@ static struct dlm_lkb *find_resend_waiter(struct dlm_ls 
> *ls)
>
>         mutex_lock(&ls->ls_waiters_mutex);
>         list_for_each_entry(iter, &ls->ls_waiters, lkb_wait_reply) {
> -               if (iter->lkb_flags & DLM_IFL_RESEND) {
> +               if (test_bit(DLM_IFLNS_RESEND, &iter->lkb_insflags)) {
>                         hold_lkb(iter);
>                         lkb = iter;
>                         break;
> @@ -5217,8 +5213,10 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
>                 lock_rsb(r);
>
>                 mstype = lkb->lkb_wait_type;
> -               oc = is_overlap_cancel(lkb);
> -               ou = is_overlap_unlock(lkb);
> +               oc = test_and_clear_bit(DLM_IFLNS_OVERLAP_UNLOCK,
> +                                       &lkb->lkb_insflags);
> +               ou = test_and_clear_bit(DLM_IFLNS_OVERLAP_CANCEL,
> +                                       &lkb->lkb_insflags);

oc is cancel, ou is unlock, it got mixed up here...

I will send a v2.

- Alex

Reply via email to