Skip to content

Commit

Permalink
ksmbd: use wait_event instead of schedule_timeout()
Browse files Browse the repository at this point in the history
ksmbd threads eating masses of cputime when connection is disconnected.
If connection is disconnected, ksmbd thread waits for pending requests
to be processed using schedule_timeout. schedule_timeout() incorrectly
is used, and it is more efficient to use wait_event/wake_up than to check
r_count every time with timeout.

Signed-off-by: Namjae Jeon <[email protected]>
  • Loading branch information
namjaejeon committed Jul 25, 2022
1 parent 6080e04 commit ca16111
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 18 deletions.
6 changes: 3 additions & 3 deletions connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
conn->outstanding_credits = 0;

init_waitqueue_head(&conn->req_running_q);
init_waitqueue_head(&conn->r_count_q);
INIT_LIST_HEAD(&conn->conns_list);
INIT_LIST_HEAD(&conn->requests);
INIT_LIST_HEAD(&conn->async_requests);
Expand Down Expand Up @@ -181,7 +182,6 @@ int ksmbd_conn_write(struct ksmbd_work *work)
struct kvec iov[3];
int iov_idx = 0;

ksmbd_conn_try_dequeue_request(work);
if (!work->response_buf) {
pr_err("NULL response header\n");
return -EINVAL;
Expand Down Expand Up @@ -364,8 +364,8 @@ int ksmbd_conn_handler_loop(void *p)

out:
/* Wait till all reference dropped to the Server object*/
while (atomic_read(&conn->r_count) > 0)
schedule_timeout(HZ);
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);


unload_nls(conn->local_nls);
if (default_conn_ops.terminate_fn)
Expand Down
1 change: 1 addition & 0 deletions connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct ksmbd_conn {
unsigned int outstanding_credits;
spinlock_t credits_lock;
wait_queue_head_t req_running_q;
wait_queue_head_t r_count_q;
/* Lock to protect requests list*/
spinlock_t request_lock;
struct list_head requests;
Expand Down
28 changes: 14 additions & 14 deletions oplock.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,8 @@ static void __smb1_oplock_break_noti(struct work_struct *wk)

ksmbd_conn_write(work);
ksmbd_free_work_struct(work);
atomic_dec(&conn->r_count);
if (atomic_dec_return(&conn->r_count) == 0)
wake_up_all(&conn->r_count_q);
}

/**
Expand Down Expand Up @@ -819,18 +820,13 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
struct ksmbd_file *fp;

fp = ksmbd_lookup_durable_fd(br_info->fid);
if (!fp) {
atomic_dec(&conn->r_count);
ksmbd_free_work_struct(work);
return;
}
if (!fp)
goto out;

if (allocate_oplock_break_buf(work)) {
pr_err("smb2_allocate_rsp_buf failed! ");
atomic_dec(&conn->r_count);
ksmbd_fd_put(work, fp);
ksmbd_free_work_struct(work);
return;
goto out;
}

rsp_hdr = smb2_get_msg(work->response_buf);
Expand Down Expand Up @@ -871,8 +867,11 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)

ksmbd_fd_put(work, fp);
ksmbd_conn_write(work);

out:
ksmbd_free_work_struct(work);
atomic_dec(&conn->r_count);
if (atomic_dec_return(&conn->r_count) == 0)
wake_up_all(&conn->r_count_q);
}

/**
Expand Down Expand Up @@ -935,9 +934,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)

if (allocate_oplock_break_buf(work)) {
ksmbd_debug(OPLOCK, "smb2_allocate_rsp_buf failed! ");
ksmbd_free_work_struct(work);
atomic_dec(&conn->r_count);
return;
goto out;
}

rsp_hdr = smb2_get_msg(work->response_buf);
Expand Down Expand Up @@ -975,8 +972,11 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
inc_rfc1001_len(work->response_buf, 44);

ksmbd_conn_write(work);

out:
ksmbd_free_work_struct(work);
atomic_dec(&conn->r_count);
if (atomic_dec_return(&conn->r_count) == 0)
wake_up_all(&conn->r_count_q);
}

/**
Expand Down
3 changes: 2 additions & 1 deletion server.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ static void handle_ksmbd_work(struct work_struct *wk)

ksmbd_conn_try_dequeue_request(work);
ksmbd_free_work_struct(work);
atomic_dec(&conn->r_count);
if (atomic_dec_return(&conn->r_count) == 0)
wake_up_all(&conn->r_count_q);
}

/**
Expand Down

0 comments on commit ca16111

Please sign in to comment.