patch-2.3.12 linux/fs/open.c
Next file: linux/fs/proc/array.c
Previous file: linux/fs/minix/file.c
Back to the patch index
Back to the overall index
- Lines: 103
- Date:
Mon Jul 26 22:41:09 1999
- Orig file:
v2.3.11/linux/fs/open.c
- Orig date:
Wed Jul 21 15:46:48 1999
diff -u --recursive --new-file v2.3.11/linux/fs/open.c linux/fs/open.c
@@ -685,10 +685,14 @@
struct files_struct * files = current->files;
int fd, error;
- error = -EMFILE;
-
+ error = -EMFILE;
write_lock(&files->file_lock);
- fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
+
+repeat:
+ fd = find_next_zero_bit(files->open_fds,
+ current->files->max_fdset,
+ files->next_fd);
+
/*
* N.B. For clone tasks sharing a files structure, this test
* will limit the total number of files that can be opened.
@@ -696,10 +700,31 @@
if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
goto out;
- /* Check here for fd > files->max_fds to do dynamic expansion */
+ /* Do we need to expand the fdset array? */
+ if (fd >= current->files->max_fdset) {
+ error = expand_fdset(files, 0);
+ if (!error) {
+ error = -EMFILE;
+ goto repeat;
+ }
+ goto out;
+ }
+
+ /*
+ * Check whether we need to expand the fd array.
+ */
+ if (fd >= files->max_fds) {
+ error = expand_fd_array(files, 0);
+ if (!error) {
+ error = -EMFILE;
+ goto repeat;
+ }
+ goto out;
+ }
- FD_SET(fd, &files->open_fds);
- FD_CLR(fd, &files->close_on_exec);
+ FD_SET(fd, files->open_fds);
+ FD_CLR(fd, files->close_on_exec);
+ files->next_fd = fd + 1;
#if 1
/* Sanity check */
if (files->fd[fd] != NULL) {
@@ -717,7 +742,9 @@
inline void put_unused_fd(unsigned int fd)
{
write_lock(¤t->files->file_lock);
- FD_CLR(fd, ¤t->files->open_fds);
+ FD_CLR(fd, current->files->open_fds);
+ if (fd < current->files->next_fd)
+ current->files->next_fd = fd;
write_unlock(¤t->files->file_lock);
}
@@ -790,8 +817,12 @@
* Careful here! We test whether the file pointer is NULL before
* releasing the fd. This ensures that one clone task can't release
* an fd while another clone is opening it.
+ *
+ * The "release" argument tells us whether or not to mark the fd as free
+ * or not in the open-files bitmap. dup2 uses this to retain the fd
+ * without races.
*/
-asmlinkage int sys_close(unsigned int fd)
+int do_close(unsigned int fd, int release)
{
int error;
struct file * filp;
@@ -802,9 +833,10 @@
filp = frip(fd);
if (!filp)
goto out_unlock;
- FD_CLR(fd, &files->close_on_exec);
+ FD_CLR(fd, files->close_on_exec);
write_unlock(&files->file_lock);
- put_unused_fd(fd);
+ if (release)
+ put_unused_fd(fd);
lock_kernel();
error = filp_close(filp, files);
unlock_kernel();
@@ -813,6 +845,11 @@
out_unlock:
write_unlock(&files->file_lock);
goto out;
+}
+
+asmlinkage int sys_close(unsigned int fd)
+{
+ return do_close(fd, 1);
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)