close()d).
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);
}
}
/* 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"
/* 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;
/* 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;
+}
+#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.
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 */
#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>
/* 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);
/* 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);
}
/* 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;
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);
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);
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);
}
_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) );