Skip to content

Commit 568f915

Browse files
Alexander Aringteigland
authored andcommitted
fs: dlm: allow to F_SETLKW getting interrupted
This patch implements dlm plock F_SETLKW interruption feature. If a blocking posix lock request got interrupted in user space by a signal a cancellation request for a non granted lock request to the user space lock manager will be send. The user lock manager answers either with zero or a negative errno code. A errno of -ENOENT signals that there is currently no blocking lock request waiting to being granted. In case of -ENOENT it was probably to late to request a cancellation and the pending lock got granted. In any error case we will wait until the lock is being granted as cancellation failed, this causes also that in case of an older user lock manager returning -EINVAL we will wait as cancellation is not supported which should be fine. If a user requires this feature the user should update dlm user space to support lock request cancellation. Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
1 parent 99c58d6 commit 568f915

2 files changed

Lines changed: 37 additions & 20 deletions

File tree

fs/dlm/plock.c

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,30 +74,26 @@ static void send_op(struct plock_op *op)
7474
wake_up(&send_wq);
7575
}
7676

77-
/* If a process was killed while waiting for the only plock on a file,
78-
locks_remove_posix will not see any lock on the file so it won't
79-
send an unlock-close to us to pass on to userspace to clean up the
80-
abandoned waiter. So, we have to insert the unlock-close when the
81-
lock call is interrupted. */
82-
83-
static void do_unlock_close(const struct dlm_plock_info *info)
77+
static int do_lock_cancel(const struct dlm_plock_info *orig_info)
8478
{
8579
struct plock_op *op;
80+
int rv;
8681

8782
op = kzalloc(sizeof(*op), GFP_NOFS);
8883
if (!op)
89-
return;
84+
return -ENOMEM;
85+
86+
op->info = *orig_info;
87+
op->info.optype = DLM_PLOCK_OP_CANCEL;
88+
op->info.wait = 0;
9089

91-
op->info.optype = DLM_PLOCK_OP_UNLOCK;
92-
op->info.pid = info->pid;
93-
op->info.fsid = info->fsid;
94-
op->info.number = info->number;
95-
op->info.start = 0;
96-
op->info.end = OFFSET_MAX;
97-
op->info.owner = info->owner;
98-
99-
op->info.flags |= DLM_PLOCK_FL_CLOSE;
10090
send_op(op);
91+
wait_event(recv_wq, (op->done != 0));
92+
93+
rv = op->info.rv;
94+
95+
dlm_release_plock_op(op);
96+
return rv;
10197
}
10298

10399
int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
@@ -156,7 +152,7 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
156152
send_op(op);
157153

158154
if (op->info.wait) {
159-
rv = wait_event_killable(recv_wq, (op->done != 0));
155+
rv = wait_event_interruptible(recv_wq, (op->done != 0));
160156
if (rv == -ERESTARTSYS) {
161157
spin_lock(&ops_lock);
162158
/* recheck under ops_lock if we got a done != 0,
@@ -166,17 +162,37 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
166162
spin_unlock(&ops_lock);
167163
goto do_lock_wait;
168164
}
169-
list_del(&op->list);
170165
spin_unlock(&ops_lock);
171166

167+
rv = do_lock_cancel(&op->info);
168+
switch (rv) {
169+
case 0:
170+
/* waiter was deleted in user space, answer will never come
171+
* remove original request. The original request must be
172+
* on recv_list because the answer of do_lock_cancel()
173+
* synchronized it.
174+
*/
175+
spin_lock(&ops_lock);
176+
list_del(&op->list);
177+
spin_unlock(&ops_lock);
178+
rv = -EINTR;
179+
break;
180+
case -ENOENT:
181+
/* cancellation wasn't successful but op should be done */
182+
fallthrough;
183+
default:
184+
/* internal error doing cancel we need to wait */
185+
goto wait;
186+
}
187+
172188
log_debug(ls, "%s: wait interrupted %x %llx pid %d",
173189
__func__, ls->ls_global_id,
174190
(unsigned long long)number, op->info.pid);
175-
do_unlock_close(&op->info);
176191
dlm_release_plock_op(op);
177192
goto out;
178193
}
179194
} else {
195+
wait:
180196
wait_event(recv_wq, (op->done != 0));
181197
}
182198

include/uapi/linux/dlm_plock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum {
2222
DLM_PLOCK_OP_LOCK = 1,
2323
DLM_PLOCK_OP_UNLOCK,
2424
DLM_PLOCK_OP_GET,
25+
DLM_PLOCK_OP_CANCEL,
2526
};
2627

2728
#define DLM_PLOCK_FL_CLOSE 1

0 commit comments

Comments
 (0)