Commit f25cc71e634edcf8a15bc60a48f2b5f3ec9fbb1d
Committed by
J. Bruce Fields
1 parent
deb4534f4f
Exists in
master
and in
20 other branches
lockd: nlmclnt_reclaim(): avoid stack overflow
Even though nlmclnt_reclaim() is only one call into the stack frame, 928 bytes on the stack seems like a lot. Recode to dynamically allocate the request structure once from within the reclaimer task, then pass this pointer into nlmclnt_reclaim() for reuse on subsequent calls. smatch analysis: fs/lockd/clntproc.c:620 nlmclnt_reclaim() warn: 'reqst' puts 928 bytes on stack Also remove redundant assignment of 0 after memset. Cc: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Tim Gardner <tim.gardner@canonical.com> Reviewed-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Showing 3 changed files with 15 additions and 6 deletions Side-by-side Diff
fs/lockd/clntlock.c
... | ... | @@ -220,10 +220,19 @@ |
220 | 220 | { |
221 | 221 | struct nlm_host *host = (struct nlm_host *) ptr; |
222 | 222 | struct nlm_wait *block; |
223 | + struct nlm_rqst *req; | |
223 | 224 | struct file_lock *fl, *next; |
224 | 225 | u32 nsmstate; |
225 | 226 | struct net *net = host->net; |
226 | 227 | |
228 | + req = kmalloc(sizeof(*req), GFP_KERNEL); | |
229 | + if (!req) { | |
230 | + printk(KERN_ERR "lockd: reclaimer unable to alloc memory." | |
231 | + " Locks for %s won't be reclaimed!\n", | |
232 | + host->h_name); | |
233 | + return 0; | |
234 | + } | |
235 | + | |
227 | 236 | allow_signal(SIGKILL); |
228 | 237 | |
229 | 238 | down_write(&host->h_rwsem); |
... | ... | @@ -253,7 +262,7 @@ |
253 | 262 | */ |
254 | 263 | if (signalled()) |
255 | 264 | continue; |
256 | - if (nlmclnt_reclaim(host, fl) != 0) | |
265 | + if (nlmclnt_reclaim(host, fl, req) != 0) | |
257 | 266 | continue; |
258 | 267 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); |
259 | 268 | if (host->h_nsmstate != nsmstate) { |
... | ... | @@ -279,6 +288,7 @@ |
279 | 288 | /* Release host handle after use */ |
280 | 289 | nlmclnt_release_host(host); |
281 | 290 | lockd_down(net); |
291 | + kfree(req); | |
282 | 292 | return 0; |
283 | 293 | } |
fs/lockd/clntproc.c
... | ... | @@ -615,17 +615,15 @@ |
615 | 615 | * RECLAIM: Try to reclaim a lock |
616 | 616 | */ |
617 | 617 | int |
618 | -nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl) | |
618 | +nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl, | |
619 | + struct nlm_rqst *req) | |
619 | 620 | { |
620 | - struct nlm_rqst reqst, *req; | |
621 | 621 | int status; |
622 | 622 | |
623 | - req = &reqst; | |
624 | 623 | memset(req, 0, sizeof(*req)); |
625 | 624 | locks_init_lock(&req->a_args.lock.fl); |
626 | 625 | locks_init_lock(&req->a_res.lock.fl); |
627 | 626 | req->a_host = host; |
628 | - req->a_flags = 0; | |
629 | 627 | |
630 | 628 | /* Set up the argument struct */ |
631 | 629 | nlmclnt_setlockargs(req, fl); |
include/linux/lockd/lockd.h
... | ... | @@ -212,7 +212,8 @@ |
212 | 212 | __be32 nlmclnt_grant(const struct sockaddr *addr, |
213 | 213 | const struct nlm_lock *lock); |
214 | 214 | void nlmclnt_recovery(struct nlm_host *); |
215 | -int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); | |
215 | +int nlmclnt_reclaim(struct nlm_host *, struct file_lock *, | |
216 | + struct nlm_rqst *); | |
216 | 217 | void nlmclnt_next_cookie(struct nlm_cookie *); |
217 | 218 | |
218 | 219 | /* |