From 6746ee10f5744d92ed52011887768bc30e06ec4e Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 9 Mar 2006 16:00:33 +0000 Subject: [PATCH] If re-open fails, mark fd as unusable but not-reusable either (until close()d). --- servers/fs/device.c | 19 ++++++++++++++++--- servers/fs/filedes.c | 30 ++++++++++++++++++++++++++---- servers/fs/fproc.h | 3 +++ servers/fs/main.c | 2 ++ servers/fs/misc.c | 1 + servers/fs/open.c | 3 +++ servers/fs/pipe.c | 5 +++++ servers/fs/proto.h | 1 + 8 files changed, 57 insertions(+), 7 deletions(-) diff --git a/servers/fs/device.c b/servers/fs/device.c index c6a1879b9..8db6342e0 100644 --- a/servers/fs/device.c +++ b/servers/fs/device.c @@ -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); } } diff --git a/servers/fs/filedes.c b/servers/fs/filedes.c index 87b64a072..3d5c13ed2 100644 --- a/servers/fs/filedes.c +++ b/servers/fs/filedes.c @@ -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 + #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; +} diff --git a/servers/fs/fproc.h b/servers/fs/fproc.h index e56762b07..a9889094f 100644 --- a/servers/fs/fproc.h +++ b/servers/fs/fproc.h @@ -1,3 +1,5 @@ +#include + /* 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 */ diff --git a/servers/fs/main.c b/servers/fs/main.c index be7b2e506..074e51289 100644 --- a/servers/fs/main.c +++ b/servers/fs/main.c @@ -18,6 +18,7 @@ struct super_block; /* proto.h needs to know this */ #include #include #include +#include #include #include #include @@ -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); diff --git a/servers/fs/misc.c b/servers/fs/misc.c index cd30e12a9..4b53ef8e4 100644 --- a/servers/fs/misc.c +++ b/servers/fs/misc.c @@ -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); } diff --git a/servers/fs/open.c b/servers/fs/open.c index 1462efca4..31f6eaf30 100644 --- a/servers/fs/open.c +++ b/servers/fs/open.c @@ -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); diff --git a/servers/fs/pipe.c b/servers/fs/pipe.c index eee19a646..e49717d2d 100644 --- a/servers/fs/pipe.c +++ b/servers/fs/pipe.c @@ -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); } diff --git a/servers/fs/proto.h b/servers/fs/proto.h index cb49b200f..5066c86b5 100644 --- a/servers/fs/proto.h +++ b/servers/fs/proto.h @@ -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) ); -- 2.44.0