From 19c28396a574a2ddae1165cc463c438f57a9fe93 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 6 Nov 2008 15:45:32 -0800 Subject: [PATCH] --- yaml --- r: 118547 b: refs/heads/master c: 3b53fbf4314594fa04544b02b2fc6e607912da18 h: refs/heads/master i: 118545: 59653c191c3fc6479fe31b81d8f7574d756ba8a7 118543: deaaab1556397306bfc67df85248748c821b6c62 v: v3 --- [refs] | 2 +- trunk/include/linux/sched.h | 2 ++ trunk/include/net/scm.h | 5 +++-- trunk/net/core/scm.c | 24 +++++++++++++++++++++--- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index b6af1b6a3a3c..6ca957e78d5c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 518a09ef11f8454f4676125d47c3e775b300c6a5 +refs/heads/master: 3b53fbf4314594fa04544b02b2fc6e607912da18 diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index b483f39a7112..295b7c756ca6 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -1349,6 +1349,8 @@ struct task_struct { */ unsigned long timer_slack_ns; unsigned long default_timer_slack_ns; + + struct list_head *scm_work_list; }; /* diff --git a/trunk/include/net/scm.h b/trunk/include/net/scm.h index 06df126103ca..33e9986beb86 100644 --- a/trunk/include/net/scm.h +++ b/trunk/include/net/scm.h @@ -14,8 +14,9 @@ struct scm_fp_list { - int count; - struct file *fp[SCM_MAX_FD]; + struct list_head list; + int count; + struct file *fp[SCM_MAX_FD]; }; struct scm_cookie diff --git a/trunk/net/core/scm.c b/trunk/net/core/scm.c index 10f5c65f6a47..ab242cc1acca 100644 --- a/trunk/net/core/scm.c +++ b/trunk/net/core/scm.c @@ -75,6 +75,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) if (!fpl) return -ENOMEM; *fplp = fpl; + INIT_LIST_HEAD(&fpl->list); fpl->count = 0; } fpp = &fpl->fp[fpl->count]; @@ -106,9 +107,25 @@ void __scm_destroy(struct scm_cookie *scm) if (fpl) { scm->fp = NULL; - for (i=fpl->count-1; i>=0; i--) - fput(fpl->fp[i]); - kfree(fpl); + if (current->scm_work_list) { + list_add_tail(&fpl->list, current->scm_work_list); + } else { + LIST_HEAD(work_list); + + current->scm_work_list = &work_list; + + list_add(&fpl->list, &work_list); + while (!list_empty(&work_list)) { + fpl = list_first_entry(&work_list, struct scm_fp_list, list); + + list_del(&fpl->list); + for (i=fpl->count-1; i>=0; i--) + fput(fpl->fp[i]); + kfree(fpl); + } + + current->scm_work_list = NULL; + } } } @@ -284,6 +301,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); if (new_fpl) { + INIT_LIST_HEAD(&new_fpl->list); for (i=fpl->count-1; i>=0; i--) get_file(fpl->fp[i]); memcpy(new_fpl, fpl, sizeof(*fpl));