From: David Teigland <teigland@redhat.com> Date: Tue, 18 Nov 2008 12:57:15 -0600 Subject: [dlm] fix up memory allocation flags Message-id: 20081118185715.GC10717@redhat.com O-Subject: [RHEL5.3 PATCH] dlm: fix up memory allocation flags Bugzilla: 471871 RH-Acked-by: Abhijith Das <adas@redhat.com> RH-Acked-by: Bob Peterson <rpeterso@redhat.com> RH-Acked-by: Steven Whitehouse <swhiteho@redhat.com> bz 471871 dlm: fix up memory allocation flags Memory allocations in the dlm should use GFP_NOFS to avoid looping back into gfs to free memory, which may require dlm operations, causing deadlock. Most dlm allocations already use GFP_NOFS (usually via ls_allocation), but this patch fixes up some that have been missed. AFAIK, no one has actually observed deadlock between dlm and gfs due to any of the allocations changed by this patch. But apparently the patch still has an effect somehow, in delaying the onset of gfs2 bug 460218. brew build including this patch https://brewweb.devel.redhat.com/taskinfo?taskID=1578524 upstream commit (in linux-next for 2.6.29) Use ls_allocation for memory allocations, which a cluster fs sets to GFP_NOFS. Use GFP_NOFS for allocations when no lockspace struct is available. Taking dlm locks needs to avoid calling back into the cluster fs because write-out can require taking dlm locks. Signed-off-by: David Teigland <teigland@redhat.com> diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 222867d..e79c18d 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -294,6 +294,7 @@ static int add_sock(struct socket *sock, struct connection *con) con->sock->sk->sk_write_space = lowcomms_write_space; con->sock->sk->sk_state_change = lowcomms_state_change; con->sock->sk->sk_user_data = con; + con->sock->sk->sk_allocation = GFP_NOFS; return 0; } diff --git a/fs/dlm/memory.c b/fs/dlm/memory.c index 55416ae..38f525c 100644 --- a/fs/dlm/memory.c +++ b/fs/dlm/memory.c @@ -39,7 +39,7 @@ char *dlm_allocate_lvb(struct dlm_ls *ls) { char *p; - p = kmalloc(ls->ls_lvblen, GFP_KERNEL); + p = kmalloc(ls->ls_lvblen, ls->ls_allocation); if (p) memset(p, 0, ls->ls_lvblen); return p; @@ -59,7 +59,7 @@ struct dlm_rsb *dlm_allocate_rsb(struct dlm_ls *ls, int namelen) DLM_ASSERT(namelen <= DLM_RESNAME_MAXLEN,); - r = kmalloc(sizeof(*r) + namelen, GFP_KERNEL); + r = kmalloc(sizeof(*r) + namelen, ls->ls_allocation); if (r) memset(r, 0, sizeof(*r) + namelen); return r; @@ -76,7 +76,7 @@ struct dlm_lkb *dlm_allocate_lkb(struct dlm_ls *ls) { struct dlm_lkb *lkb; - lkb = kmem_cache_alloc(lkb_cache, GFP_KERNEL); + lkb = kmem_cache_alloc(lkb_cache, ls->ls_allocation); if (lkb) memset(lkb, 0, sizeof(*lkb)); return lkb; diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c index e69926e..8e32381 100644 --- a/fs/dlm/midcomms.c +++ b/fs/dlm/midcomms.c @@ -105,7 +105,7 @@ int dlm_process_incoming_buffer(int nodeid, const void *base, ordinary messages). */ if (msglen > DLM_INBUF_LEN && msg == &__tmp.dlm) { - msg = kmalloc(dlm_config.ci_buffer_size, GFP_KERNEL); + msg = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS); if (msg == NULL) return ret; }