diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 41 |
1 files changed, 19 insertions, 22 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index be1ff8ddbb9c..f6b929e69f5b 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -555,7 +555,7 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) { struct files_struct *oldf, *newf; struct file **old_fds, **new_fds; - int open_files, nfds, size, i, error = 0; + int open_files, size, i, error = 0, expand; /* * A background process may not have any files ... @@ -590,36 +590,32 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) newf->open_fds = &newf->open_fds_init; newf->fd = &newf->fd_array[0]; - /* We don't yet have the oldf readlock, but even if the old - fdset gets grown now, we'll only copy up to "size" fds */ - size = oldf->max_fdset; - if (size > __FD_SETSIZE) { - newf->max_fdset = 0; - spin_lock(&newf->file_lock); - error = expand_fdset(newf, size-1); - spin_unlock(&newf->file_lock); - if (error) - goto out_release; - } spin_lock(&oldf->file_lock); - open_files = count_open_files(oldf, size); + open_files = count_open_files(oldf, oldf->max_fdset); + expand = 0; /* - * Check whether we need to allocate a larger fd array. - * Note: we're not a clone task, so the open count won't - * change. + * Check whether we need to allocate a larger fd array or fd set. + * Note: we're not a clone task, so the open count won't change. */ - nfds = NR_OPEN_DEFAULT; - if (open_files > nfds) { - spin_unlock(&oldf->file_lock); + if (open_files > newf->max_fdset) { + newf->max_fdset = 0; + expand = 1; + } + if (open_files > newf->max_fds) { newf->max_fds = 0; + expand = 1; + } + + /* if the old fdset gets grown now, we'll only copy up to "size" fds */ + if (expand) { + spin_unlock(&oldf->file_lock); spin_lock(&newf->file_lock); - error = expand_fd_array(newf, open_files-1); + error = expand_files(newf, open_files-1); spin_unlock(&newf->file_lock); - if (error) + if (error < 0) goto out_release; - nfds = newf->max_fds; spin_lock(&oldf->file_lock); } @@ -668,6 +664,7 @@ out: out_release: free_fdset (newf->close_on_exec, newf->max_fdset); free_fdset (newf->open_fds, newf->max_fdset); + free_fd_array(newf->fd, newf->max_fds); kmem_cache_free(files_cachep, newf); goto out; } |
