diff options
Diffstat (limited to 'fs/file.c')
| -rw-r--r-- | fs/file.c | 52 |
1 files changed, 25 insertions, 27 deletions
| @@ -40,7 +40,7 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */ | |||
| 40 | */ | 40 | */ |
| 41 | static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); | 41 | static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); |
| 42 | 42 | ||
| 43 | static void *alloc_fdmem(unsigned int size) | 43 | static void *alloc_fdmem(size_t size) |
| 44 | { | 44 | { |
| 45 | /* | 45 | /* |
| 46 | * Very large allocations can stress page reclaim, so fall back to | 46 | * Very large allocations can stress page reclaim, so fall back to |
| @@ -142,7 +142,7 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt) | |||
| 142 | static struct fdtable * alloc_fdtable(unsigned int nr) | 142 | static struct fdtable * alloc_fdtable(unsigned int nr) |
| 143 | { | 143 | { |
| 144 | struct fdtable *fdt; | 144 | struct fdtable *fdt; |
| 145 | char *data; | 145 | void *data; |
| 146 | 146 | ||
| 147 | /* | 147 | /* |
| 148 | * Figure out how many fds we actually want to support in this fdtable. | 148 | * Figure out how many fds we actually want to support in this fdtable. |
| @@ -172,14 +172,15 @@ static struct fdtable * alloc_fdtable(unsigned int nr) | |||
| 172 | data = alloc_fdmem(nr * sizeof(struct file *)); | 172 | data = alloc_fdmem(nr * sizeof(struct file *)); |
| 173 | if (!data) | 173 | if (!data) |
| 174 | goto out_fdt; | 174 | goto out_fdt; |
| 175 | fdt->fd = (struct file **)data; | 175 | fdt->fd = data; |
| 176 | data = alloc_fdmem(max_t(unsigned int, | 176 | |
| 177 | data = alloc_fdmem(max_t(size_t, | ||
| 177 | 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES)); | 178 | 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES)); |
| 178 | if (!data) | 179 | if (!data) |
| 179 | goto out_arr; | 180 | goto out_arr; |
| 180 | fdt->open_fds = (fd_set *)data; | 181 | fdt->open_fds = data; |
| 181 | data += nr / BITS_PER_BYTE; | 182 | data += nr / BITS_PER_BYTE; |
| 182 | fdt->close_on_exec = (fd_set *)data; | 183 | fdt->close_on_exec = data; |
| 183 | fdt->next = NULL; | 184 | fdt->next = NULL; |
| 184 | 185 | ||
| 185 | return fdt; | 186 | return fdt; |
| @@ -275,11 +276,11 @@ static int count_open_files(struct fdtable *fdt) | |||
| 275 | int i; | 276 | int i; |
| 276 | 277 | ||
| 277 | /* Find the last open fd */ | 278 | /* Find the last open fd */ |
| 278 | for (i = size/(8*sizeof(long)); i > 0; ) { | 279 | for (i = size / BITS_PER_LONG; i > 0; ) { |
| 279 | if (fdt->open_fds->fds_bits[--i]) | 280 | if (fdt->open_fds[--i]) |
| 280 | break; | 281 | break; |
| 281 | } | 282 | } |
| 282 | i = (i+1) * 8 * sizeof(long); | 283 | i = (i + 1) * BITS_PER_LONG; |
| 283 | return i; | 284 | return i; |
| 284 | } | 285 | } |
| 285 | 286 | ||
| @@ -306,8 +307,8 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | |||
| 306 | newf->next_fd = 0; | 307 | newf->next_fd = 0; |
| 307 | new_fdt = &newf->fdtab; | 308 | new_fdt = &newf->fdtab; |
| 308 | new_fdt->max_fds = NR_OPEN_DEFAULT; | 309 | new_fdt->max_fds = NR_OPEN_DEFAULT; |
| 309 | new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; | 310 | new_fdt->close_on_exec = newf->close_on_exec_init; |
| 310 | new_fdt->open_fds = (fd_set *)&newf->open_fds_init; | 311 | new_fdt->open_fds = newf->open_fds_init; |
| 311 | new_fdt->fd = &newf->fd_array[0]; | 312 | new_fdt->fd = &newf->fd_array[0]; |
| 312 | new_fdt->next = NULL; | 313 | new_fdt->next = NULL; |
| 313 | 314 | ||
| @@ -350,10 +351,8 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | |||
| 350 | old_fds = old_fdt->fd; | 351 | old_fds = old_fdt->fd; |
| 351 | new_fds = new_fdt->fd; | 352 | new_fds = new_fdt->fd; |
| 352 | 353 | ||
| 353 | memcpy(new_fdt->open_fds->fds_bits, | 354 | memcpy(new_fdt->open_fds, old_fdt->open_fds, open_files / 8); |
| 354 | old_fdt->open_fds->fds_bits, open_files/8); | 355 | memcpy(new_fdt->close_on_exec, old_fdt->close_on_exec, open_files / 8); |
| 355 | memcpy(new_fdt->close_on_exec->fds_bits, | ||
| 356 | old_fdt->close_on_exec->fds_bits, open_files/8); | ||
| 357 | 356 | ||
| 358 | for (i = open_files; i != 0; i--) { | 357 | for (i = open_files; i != 0; i--) { |
| 359 | struct file *f = *old_fds++; | 358 | struct file *f = *old_fds++; |
| @@ -366,7 +365,7 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | |||
| 366 | * is partway through open(). So make sure that this | 365 | * is partway through open(). So make sure that this |
| 367 | * fd is available to the new process. | 366 | * fd is available to the new process. |
| 368 | */ | 367 | */ |
| 369 | FD_CLR(open_files - i, new_fdt->open_fds); | 368 | __clear_open_fd(open_files - i, new_fdt); |
| 370 | } | 369 | } |
| 371 | rcu_assign_pointer(*new_fds++, f); | 370 | rcu_assign_pointer(*new_fds++, f); |
| 372 | } | 371 | } |
| @@ -379,11 +378,11 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | |||
| 379 | memset(new_fds, 0, size); | 378 | memset(new_fds, 0, size); |
| 380 | 379 | ||
| 381 | if (new_fdt->max_fds > open_files) { | 380 | if (new_fdt->max_fds > open_files) { |
| 382 | int left = (new_fdt->max_fds-open_files)/8; | 381 | int left = (new_fdt->max_fds - open_files) / 8; |
| 383 | int start = open_files / (8 * sizeof(unsigned long)); | 382 | int start = open_files / BITS_PER_LONG; |
| 384 | 383 | ||
| 385 | memset(&new_fdt->open_fds->fds_bits[start], 0, left); | 384 | memset(&new_fdt->open_fds[start], 0, left); |
| 386 | memset(&new_fdt->close_on_exec->fds_bits[start], 0, left); | 385 | memset(&new_fdt->close_on_exec[start], 0, left); |
| 387 | } | 386 | } |
| 388 | 387 | ||
| 389 | rcu_assign_pointer(newf->fdt, new_fdt); | 388 | rcu_assign_pointer(newf->fdt, new_fdt); |
| @@ -419,8 +418,8 @@ struct files_struct init_files = { | |||
| 419 | .fdtab = { | 418 | .fdtab = { |
| 420 | .max_fds = NR_OPEN_DEFAULT, | 419 | .max_fds = NR_OPEN_DEFAULT, |
| 421 | .fd = &init_files.fd_array[0], | 420 | .fd = &init_files.fd_array[0], |
| 422 | .close_on_exec = (fd_set *)&init_files.close_on_exec_init, | 421 | .close_on_exec = init_files.close_on_exec_init, |
| 423 | .open_fds = (fd_set *)&init_files.open_fds_init, | 422 | .open_fds = init_files.open_fds_init, |
| 424 | }, | 423 | }, |
| 425 | .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), | 424 | .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), |
| 426 | }; | 425 | }; |
| @@ -443,8 +442,7 @@ repeat: | |||
| 443 | fd = files->next_fd; | 442 | fd = files->next_fd; |
| 444 | 443 | ||
| 445 | if (fd < fdt->max_fds) | 444 | if (fd < fdt->max_fds) |
| 446 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, | 445 | fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, fd); |
| 447 | fdt->max_fds, fd); | ||
| 448 | 446 | ||
| 449 | error = expand_files(files, fd); | 447 | error = expand_files(files, fd); |
| 450 | if (error < 0) | 448 | if (error < 0) |
| @@ -460,11 +458,11 @@ repeat: | |||
| 460 | if (start <= files->next_fd) | 458 | if (start <= files->next_fd) |
| 461 | files->next_fd = fd + 1; | 459 | files->next_fd = fd + 1; |
| 462 | 460 | ||
| 463 | FD_SET(fd, fdt->open_fds); | 461 | __set_open_fd(fd, fdt); |
| 464 | if (flags & O_CLOEXEC) | 462 | if (flags & O_CLOEXEC) |
| 465 | FD_SET(fd, fdt->close_on_exec); | 463 | __set_close_on_exec(fd, fdt); |
| 466 | else | 464 | else |
| 467 | FD_CLR(fd, fdt->close_on_exec); | 465 | __clear_close_on_exec(fd, fdt); |
| 468 | error = fd; | 466 | error = fd; |
| 469 | #if 1 | 467 | #if 1 |
| 470 | /* Sanity check */ | 468 | /* Sanity check */ |
