Skip to content

Commit c51b022

Browse files
Alexander Aringteigland
authored andcommitted
fs: dlm: fix multiple empty writequeue alloc
This patch will add a mutex that a connection can allocate a writequeue entry buffer only at a sleepable context at one time. If multiple caller waits at the writequeue spinlock and the spinlock gets release it could be that multiple new writequeue page buffers were allocated instead of allocate one writequeue page buffer and other waiters will use remaining buffer of it. It will only be the case for sleepable context which is the common case. In non-sleepable contexts like retransmission we just don't care about such behaviour. Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
1 parent 8728a45 commit c51b022

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

fs/dlm/lowcomms.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct connection {
8484
struct list_head writequeue; /* List of outgoing writequeue_entries */
8585
spinlock_t writequeue_lock;
8686
atomic_t writequeue_cnt;
87+
struct mutex wq_alloc;
8788
int retries;
8889
#define MAX_CONNECT_RETRIES 3
8990
struct hlist_node list;
@@ -264,6 +265,8 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
264265
return NULL;
265266
}
266267

268+
mutex_init(&con->wq_alloc);
269+
267270
spin_lock(&connections_lock);
268271
/* Because multiple workqueues/threads calls this function it can
269272
* race on multiple cpu's. Instead of locking hot path __find_con()
@@ -1251,19 +1254,37 @@ static struct dlm_msg *dlm_lowcomms_new_msg_con(struct connection *con, int len,
12511254
{
12521255
struct writequeue_entry *e;
12531256
struct dlm_msg *msg;
1257+
bool sleepable;
12541258

12551259
msg = kzalloc(sizeof(*msg), allocation);
12561260
if (!msg)
12571261
return NULL;
12581262

1263+
/* this mutex is being used as a wait to avoid multiple "fast"
1264+
* new writequeue page list entry allocs in new_wq_entry in
1265+
* normal operation which is sleepable context. Without it
1266+
* we could end in multiple writequeue entries with one
1267+
* dlm message because multiple callers were waiting at
1268+
* the writequeue_lock in new_wq_entry().
1269+
*/
1270+
sleepable = gfpflags_normal_context(allocation);
1271+
if (sleepable)
1272+
mutex_lock(&con->wq_alloc);
1273+
12591274
kref_init(&msg->ref);
12601275

12611276
e = new_wq_entry(con, len, allocation, ppc, cb, mh);
12621277
if (!e) {
1278+
if (sleepable)
1279+
mutex_unlock(&con->wq_alloc);
1280+
12631281
kfree(msg);
12641282
return NULL;
12651283
}
12661284

1285+
if (sleepable)
1286+
mutex_unlock(&con->wq_alloc);
1287+
12671288
msg->ppc = *ppc;
12681289
msg->len = len;
12691290
msg->entry = e;

0 commit comments

Comments
 (0)