aboutsummaryrefslogtreecommitdiffstats
path: root/fs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/file.c')
-rw-r--r--fs/file.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/fs/file.c b/fs/file.c
index 7b3887e054d0..f313314f996f 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -6,6 +6,7 @@
6 * Manage the dynamic fd arrays in the process files_struct. 6 * Manage the dynamic fd arrays in the process files_struct.
7 */ 7 */
8 8
9#include <linux/module.h>
9#include <linux/fs.h> 10#include <linux/fs.h>
10#include <linux/mm.h> 11#include <linux/mm.h>
11#include <linux/time.h> 12#include <linux/time.h>
@@ -250,9 +251,18 @@ int expand_files(struct files_struct *files, int nr)
250 struct fdtable *fdt; 251 struct fdtable *fdt;
251 252
252 fdt = files_fdtable(files); 253 fdt = files_fdtable(files);
254
255 /*
256 * N.B. For clone tasks sharing a files structure, this test
257 * will limit the total number of files that can be opened.
258 */
259 if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
260 return -EMFILE;
261
253 /* Do we need to expand? */ 262 /* Do we need to expand? */
254 if (nr < fdt->max_fds) 263 if (nr < fdt->max_fds)
255 return 0; 264 return 0;
265
256 /* Can we expand? */ 266 /* Can we expand? */
257 if (nr >= sysctl_nr_open) 267 if (nr >= sysctl_nr_open)
258 return -EMFILE; 268 return -EMFILE;
@@ -423,3 +433,63 @@ struct files_struct init_files = {
423 }, 433 },
424 .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), 434 .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock),
425}; 435};
436
437/*
438 * allocate a file descriptor, mark it busy.
439 */
440int alloc_fd(unsigned start, unsigned flags)
441{
442 struct files_struct *files = current->files;
443 unsigned int fd;
444 int error;
445 struct fdtable *fdt;
446
447 spin_lock(&files->file_lock);
448repeat:
449 fdt = files_fdtable(files);
450 fd = start;
451 if (fd < files->next_fd)
452 fd = files->next_fd;
453
454 if (fd < fdt->max_fds)
455 fd = find_next_zero_bit(fdt->open_fds->fds_bits,
456 fdt->max_fds, fd);
457
458 error = expand_files(files, fd);
459 if (error < 0)
460 goto out;
461
462 /*
463 * If we needed to expand the fs array we
464 * might have blocked - try again.
465 */
466 if (error)
467 goto repeat;
468
469 if (start <= files->next_fd)
470 files->next_fd = fd + 1;
471
472 FD_SET(fd, fdt->open_fds);
473 if (flags & O_CLOEXEC)
474 FD_SET(fd, fdt->close_on_exec);
475 else
476 FD_CLR(fd, fdt->close_on_exec);
477 error = fd;
478#if 1
479 /* Sanity check */
480 if (rcu_dereference(fdt->fd[fd]) != NULL) {
481 printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
482 rcu_assign_pointer(fdt->fd[fd], NULL);
483 }
484#endif
485
486out:
487 spin_unlock(&files->file_lock);
488 return error;
489}
490
491int get_unused_fd(void)
492{
493 return alloc_fd(0, 0);
494}
495EXPORT_SYMBOL(get_unused_fd);