]> Zhao Yanbai Git Server - minix.git/commitdiff
If re-open fails, mark fd as unusable but not-reusable either (until
authorBen Gras <ben@minix3.org>
Thu, 9 Mar 2006 16:00:33 +0000 (16:00 +0000)
committerBen Gras <ben@minix3.org>
Thu, 9 Mar 2006 16:00:33 +0000 (16:00 +0000)
close()d).

servers/fs/device.c
servers/fs/filedes.c
servers/fs/fproc.h
servers/fs/main.c
servers/fs/misc.c
servers/fs/open.c
servers/fs/pipe.c
servers/fs/proto.h

index c6a1879b946260f56bb10664e6b47855385f22e2..8db6342e00758c9775d96fd6960cbfa166edc55e 100644 (file)
@@ -596,10 +596,23 @@ PUBLIC void dev_up(int maj)
                
                minor = ((in->i_zone[0] >> MINOR) & BYTE);
 
-               if((r = dev_open(in->i_dev, FS_PROC_NR,
+               printf("FS: reopening special %d/%d..\n", maj, minor);
+
+               if((r = dev_open(in->i_zone[0], FS_PROC_NR,
                   in->i_mode & (R_BIT|W_BIT))) != OK) {
-                       printf("FS: file on dev %d/%d re-open failed: %d.\n",
-                               maj, minor, r);
+                       int n;
+                       /* This function will set the fp_filp[]s of processes
+                        * holding that fp to NULL, but _not_ clear
+                        * fp_filp_inuse, so that fd can't be recycled until
+                        * it's close()d.
+                        */
+                       n = inval_filp(fp);
+                       if(n != fp->filp_count)
+                               printf("FS: warning: invalidate/count "
+                                "discrepancy (%d, %d)\n", n, fp->filp_count);
+                       fp->filp_count = 0;
+                       printf("FS: file on dev %d/%d re-open failed: %d; "
+                               "invalidated %d fd's.\n", maj, minor, r, n);
                }
        }
 
index 87b64a0729780cceed574b522062164da3ce7589..3d5c13ed2eeecae153c712a8254a177d3e6ec759 100644 (file)
@@ -1,11 +1,15 @@
 /* This file contains the procedures that manipulate file descriptors.
  *
  * The entry points into this file are
- *   get_fd:   look for free file descriptor and free filp slots
- *   get_filp: look up the filp entry for a given file descriptor
- *   find_filp:        find a filp slot that points to a given inode
+ *   get_fd:    look for free file descriptor and free filp slots
+ *   get_filp:  look up the filp entry for a given file descriptor
+ *   find_filp:         find a filp slot that points to a given inode
+ *   inval_filp: invalidate a filp and associated fd's, only let close()
+ *               happen on it
  */
 
+#include <sys/select.h>
+
 #include "fs.h"
 #include "file.h"
 #include "fproc.h"
@@ -28,7 +32,7 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
 
   /* Search the fproc fp_filp table for a free file descriptor. */
   for (i = start; i < OPEN_MAX; i++) {
-       if (fp->fp_filp[i] == NIL_FILP) {
+       if (fp->fp_filp[i] == NIL_FILP && !FD_ISSET(i, &fp->fp_filp_inuse)) {
                /* A file descriptor has been located. */
                *k = i;
                break;
@@ -92,3 +96,21 @@ PUBLIC struct filp *find_filp(register struct inode *rip, mode_t bits)
   /* If control passes here, the filp wasn't there.  Report that back. */
   return(NIL_FILP);
 }
+
+/*===========================================================================*
+ *                             inval_filp                                   *
+ *===========================================================================*/
+PUBLIC int inval_filp(struct filp *fp)
+{
+       int f, fd, n = 0;
+       for(f = 0; f < NR_PROCS; f++) {
+               if(fproc[f].fp_pid == PID_FREE) continue;
+               for(fd = 0; fd < OPEN_MAX; fd++) {
+                       if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
+                               fproc[f].fp_filp[fd] = NIL_FILP;
+                       }
+               }
+       }
+
+       return n;
+}
index e56762b07753d61ec9ea3e56c690548f791830d7..a9889094f6b496b48621db6c4a7aa47c97bc48ef 100644 (file)
@@ -1,3 +1,5 @@
+#include <sys/select.h>
+
 /* This is the per-process information.  A slot is reserved for each potential
  * process. Thus NR_PROCS must be the same as in the kernel. It is not 
  * possible or even necessary to tell when a slot is free here.
@@ -7,6 +9,7 @@ EXTERN struct fproc {
   struct inode *fp_workdir;    /* pointer to working directory's inode */
   struct inode *fp_rootdir;    /* pointer to current root dir (see chroot) */
   struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
+  fd_set fp_filp_inuse;                /* which fd's are in use? */
   uid_t fp_realuid;            /* real user id */
   uid_t fp_effuid;             /* effective user id */
   gid_t fp_realgid;            /* real group id */
index be7b2e506fca9add25459c80da48e2adfdc588cd..074e512894ed0ed2f20cc75e272ed05ceee39068 100644 (file)
@@ -18,6 +18,7 @@ struct super_block;           /* proto.h needs to know this */
 #include <stdlib.h>
 #include <sys/ioc_memory.h>
 #include <sys/svrctl.h>
+#include <sys/select.h>
 #include <minix/callnr.h>
 #include <minix/com.h>
 #include <minix/keymap.h>
@@ -251,6 +252,7 @@ PRIVATE void fs_init()
 
   /* The root device can now be accessed; set process directories. */
   for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+       FD_ZERO(&(rfp->fp_filp_inuse));
        if (rfp->fp_pid != PID_FREE) {
                rip = get_inode(root_dev, ROOT_INODE);
                dup_inode(rip);
index cd30e12a96818865039835cbc9816c15b3e522ef..4b53ef8e49edc669009d22e4dda509d25c8490b8 100644 (file)
@@ -101,6 +101,7 @@ PUBLIC int do_dup()
   /* Success. Set up new file descriptors. */
   f->filp_count++;
   fp->fp_filp[m_in.fd2] = f;
+  FD_SET(m_in.fd2, &fp->fp_filp_inuse);
   return(m_in.fd2);
 }
 
index 1462efca475df2ea3d77f90fea79f4eada2c8ed5..31f6eaf30e3e75d9bfc100e86667407a6a4581ba 100644 (file)
@@ -108,6 +108,7 @@ PRIVATE int common_open(register int oflags, mode_t omode)
 
   /* Claim the file descriptor and filp slot and fill them in. */
   fp->fp_filp[m_in.fd] = fil_ptr;
+  FD_SET(m_in.fd, &fp->fp_filp_inuse);
   fil_ptr->filp_count = 1;
   fil_ptr->filp_ino = rip;
   fil_ptr->filp_flags = oflags;
@@ -187,6 +188,7 @@ PRIVATE int common_open(register int oflags, mode_t omode)
   if (r != OK) {
        if (r == SUSPEND) return(r);            /* Oops, just suspended */
        fp->fp_filp[m_in.fd] = NIL_FILP;
+       FD_CLR(m_in.fd, &fp->fp_filp_inuse);
        fil_ptr->filp_count= 0;
        put_inode(rip);
        return(r);
@@ -434,6 +436,7 @@ PUBLIC int do_close()
 
   fp->fp_cloexec &= ~(1L << m_in.fd);  /* turn off close-on-exec bit */
   fp->fp_filp[m_in.fd] = NIL_FILP;
+  FD_CLR(m_in.fd, &fp->fp_filp_inuse);
 
   /* Check to see if the file is locked.  If so, release all locks. */
   if (nr_locks == 0) return(OK);
index eee19a646f59806ad3ef4e3883c085da2622206f..e49717d2d234aafeeb0d972417cf5cfd92f6eb6a 100644 (file)
@@ -47,20 +47,25 @@ PUBLIC int do_pipe()
   rfp = fp;
   if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
   rfp->fp_filp[fil_des[0]] = fil_ptr0;
+  FD_SET(fil_des[0], &rfp->fp_filp_inuse);
   fil_ptr0->filp_count = 1;
   if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
        rfp->fp_filp[fil_des[0]] = NIL_FILP;
+       FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
        fil_ptr0->filp_count = 0;
        return(r);
   }
   rfp->fp_filp[fil_des[1]] = fil_ptr1;
+  FD_SET(fil_des[1], &rfp->fp_filp_inuse);
   fil_ptr1->filp_count = 1;
 
   /* Make the inode on the pipe device. */
   if ( (rip = alloc_inode(root_dev, I_REGULAR) ) == NIL_INODE) {
        rfp->fp_filp[fil_des[0]] = NIL_FILP;
+       FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
        fil_ptr0->filp_count = 0;
        rfp->fp_filp[fil_des[1]] = NIL_FILP;
+       FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
        fil_ptr1->filp_count = 0;
        return(err_code);
   }
index cb49b200fdab46336085a331a3d5a1d0ebc88004..5066c86b51a35d878da1044918e34e0ab30d771e 100644 (file)
@@ -59,6 +59,7 @@ _PROTOTYPE( void dmap_endpt_up, (int proc_nr)                         );
 _PROTOTYPE( struct filp *find_filp, (struct inode *rip, mode_t bits)   );
 _PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, struct filp **fpt) );
 _PROTOTYPE( struct filp *get_filp, (int fild)                          );
+_PROTOTYPE( int inval_filp, (struct filp *)                            );
 
 /* inode.c */
 _PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits)                );