If re-open fails, mark fd as unusable but not-reusable either (until

close()d).
This commit is contained in:
Ben Gras 2006-03-09 16:00:33 +00:00
parent 1353798747
commit 6746ee10f5
8 changed files with 57 additions and 7 deletions

View 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);
}
}

View 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;
}

View 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 */

View 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);

View 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);
}

View 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);

View 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);
}

View 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) );