[PATCH] FD array expansion problem

Savochkin Andrey Vladimirovich (saw@msu.ru)
Sat, 30 Oct 1999 19:21:12 +0400


Hi,

I've spotted a bug in the dynamic fd array expansion code.
Here is the patch which
- fixes wrong parameters of expand_fdset() and expand_fd_array() calls
in expand_files() and get_unused_fd(); and
- moves expand_files() function from sched.h to fs/fcntl.c.

Best wishes
Andrey V.
Savochkin

--- ./fs/fcntl.c.expandfd Sat Oct 30 18:48:27 1999
+++ ./fs/fcntl.c Sat Oct 30 18:48:27 1999
@@ -12,6 +12,39 @@

extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);

+/* Expand files.
+ * `nr' is the number of the last fd.
+ * Return <0 on error; 0 nothing done; 1 files expanded,
+ * we may have blocked.
+ *
+ * Should be called with the files->file_lock spinlock held for write.
+ */
+static inline int expand_files(struct files_struct *files, int nr)
+{
+ int err, expand = 0;
+#ifdef FDSET_DEBUG
+ printk (KERN_ERR __FUNCTION__ " %d: nr = %d\n", current->pid, nr);
+#endif
+
+ if (nr >= files->max_fdset) {
+ expand = 1;
+ if ((err = expand_fdset(files, nr + 1)))
+ goto out;
+ }
+ if (nr >= files->max_fds) {
+ expand = 1;
+ if ((err = expand_fd_array(files, nr + 1)))
+ goto out;
+ }
+ err = expand;
+ out:
+#ifdef FDSET_DEBUG
+ if (err)
+ printk (KERN_ERR __FUNCTION__ " %d: return %d\n", current->pid, err);
+#endif
+ return err;
+}
+
/*
* locate_fd finds a free file descriptor in the open_fds fdset,
* expanding the fd arrays if necessary. The files write lock will be
--- ./fs/file.c.expandfd Sat Oct 30 18:48:27 1999
+++ ./fs/file.c Sat Oct 30 18:48:27 1999
@@ -53,8 +53,9 @@
}

/*
- * Expand the fd array in the files_struct. Called with the files
- * spinlock held for write.
+ * Expand the fd array in the files_struct.
+ * `nr' is the desired array size.
+ * Called with the files spinlock held for write.
*/

int expand_fd_array(struct files_struct *files, int nr)
--- ./fs/open.c.expandfd Sat Oct 30 18:48:27 1999
+++ ./fs/open.c Sat Oct 30 18:48:27 1999
@@ -702,7 +702,7 @@

/* Do we need to expand the fdset array? */
if (fd >= current->files->max_fdset) {
- error = expand_fdset(files, 0);
+ error = expand_fdset(files, fd + 1);
if (!error) {
error = -EMFILE;
goto repeat;
@@ -714,7 +714,7 @@
* Check whether we need to expand the fd array.
*/
if (fd >= files->max_fds) {
- error = expand_fd_array(files, 0);
+ error = expand_fd_array(files, fd + 1);
if (!error) {
error = -EMFILE;
goto repeat;
--- ./include/linux/sched.h.expandfd Sat Oct 30 18:48:27 1999
+++ ./include/linux/sched.h Sat Oct 30 18:48:27 1999
@@ -657,37 +657,6 @@
extern int expand_fdset(struct files_struct *, int nr);
extern void free_fdset(fd_set *, int);

-/* Expand files. Return <0 on error; 0 nothing done; 1 files expanded,
- * we may have blocked.
- *
- * Should be called with the files->file_lock spinlock held for write.
- */
-static inline int expand_files(struct files_struct *files, int nr)
-{
- int err, expand = 0;
-#ifdef FDSET_DEBUG
- printk (KERN_ERR __FUNCTION__ " %d: nr = %d\n", current->pid, nr);
-#endif
-
- if (nr >= files->max_fdset) {
- expand = 1;
- if ((err = expand_fdset(files, nr)))
- goto out;
- }
- if (nr >= files->max_fds) {
- expand = 1;
- if ((err = expand_fd_array(files, nr)))
- goto out;
- }
- err = expand;
- out:
-#ifdef FDSET_DEBUG
- if (err)
- printk (KERN_ERR __FUNCTION__ " %d: return %d\n", current->pid, err);
-#endif
- return err;
-}
-
extern int copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
extern void flush_thread(void);
extern void exit_thread(void);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/