return -1;
}
-/* Check if an inode is open for reading or for writing. Needed for pipe
- * EOF and will one day be needed for shared code segments (8086 etc)
- */
-int8_t oft_inuse(inoptr ino, uint8_t rw)
-{
- struct oft *ofptr = of_tab;
- while(ofptr <= &of_tab[OFTSIZE - 1]) {
- if (ofptr->o_refs && ofptr->o_inode == ino &&
- O_ACCMODE(ofptr->o_access) != rw)
- return 1;
- ofptr++;
- }
- return 0;
-}
-
/*
* To minimise storage we don't track exclusive locks explicitly. We know
* that if we are dropping an exclusive lock then we must be the owner,
#define major(x) ((x) >> 8)
#define minor(x) ((x) & 0xFF)
-typedef struct cinode { // note: exists in memory *and* on disk
- uint16_t c_magic; /* Used to check for corruption. */
- uint16_t c_dev; /* Inode's device */
- uint16_t c_num; /* Inode # */
- dinode c_node;
- uint8_t c_refs; /* In-core reference count */
+/* In memory inode structure */
+typedef struct cinode {
+ uint16_t c_magic; /* Used to check for corruption. */
+ uint16_t c_dev; /* Inode's device */
+ uint16_t c_num; /* Inode # */
+ dinode c_node; /* On disk inode data */
+ uint8_t c_refs; /* In-core reference count */
+ uint8_t c_readers; /* Count of readers by oft entry */
+ uint8_t c_writers; /* Count of writers by oft entry */
uint8_t c_flags;
#define CDIRTY 0x80 /* Modified flag. */
#define CRDONLY 0x40 /* On a read only file system */
extern blkno_t blk_alloc(uint16_t devno);
extern void blk_free(uint16_t devno, blkno_t blk);
extern int8_t oft_alloc(void);
-extern int8_t oft_inuse(inoptr ino, uint8_t rw);
-/* Yes these are intentionally backwards - there are 3 modes so the loop looks
- for "not this mode" */
-#define INUSE_R O_WRONLY
-#define INUSE_W O_RDONLY
extern void deflock(struct oft *ofptr);
extern void oft_deref(int8_t of);
/* returns index of slot, or -1 on failure */
how we handle the psleep_flags bit */
static uint8_t pipewait(inoptr ino, uint8_t flag)
{
- int8_t n;
while(ino->c_node.i_size == 0) {
- n = oft_inuse(ino, INUSE_W);
- if (n == 0 || psleep_flags(ino, flag)) {
+ if (ino->c_writers == 0 || psleep_flags(ino, flag)) {
udata.u_count = 0;
return 0;
}
in one go - needs merging into the loop */
while ((towrite = udata.u_count) > (16 * BLKSIZE) -
ino->c_node.i_size) {
- if (!oft_inuse(ino, INUSE_R)) { /* No readers */
+ if (ino->c_readers == 0) { /* No readers */
udata.u_count = (usize_t)-1;
udata.u_error = EPIPE;
ssig(udata.u_ptab, SIGPIPE);
int16_t doclose(uint8_t uindex)
{
int8_t oftindex;
+ struct oft *oftp;
inoptr ino;
uint16_t flush_dev = NO_DEVICE;
+ uint8_t m;
if (!(ino = getinode(uindex)))
return (-1);
oftindex = udata.u_files[uindex];
+ oftp = of_tab + udata.u_files[uindex];
+ m = O_ACCMODE(oftp->o_access);
- if (of_tab[oftindex].o_refs == 1) {
+ if (oftp->o_refs == 1) {
if (isdevice(ino))
d_close((int) (ino->c_node.i_addr[0]));
- if (getmode(ino) == MODE_R(F_REG) && O_ACCMODE(of_tab[oftindex].o_access))
+ if (getmode(ino) == MODE_R(F_REG) && m)
flush_dev = ino->c_dev;
#ifdef CONFIG_NET
if (issocket(ino))
udata.u_cloexec &= ~(1 << uindex);
oft_deref(oftindex);
+ if (m != O_RDONLY)
+ ino->c_writers--;
+ if (m != O_WRONLY)
+ ino->c_readers--;
+
/* if we closed a file in write mode, flush the device's cache after inode has been deferenced */
if(flush_dev != NO_DEVICE)
d_flush(flush_dev);
++ino->c_refs;
ino->c_node.i_mode = F_PIPE | 0777; /* No permissions necessary on pipes */
ino->c_node.i_nlink = 0; /* a pipe is not in any directory */
+ ino->c_readers++;
+ ino->c_writers++;
// write results to userspace
uputw(u1, fildes);
of_tab[oftindex].o_access = flag; /* Save the low bits only */
if (flag & O_CLOEXEC)
udata.u_cloexec |= (1 << oftindex);
- /* FIXME: ATIME ? */
+ if (O_ACCMODE(flag) != O_RDONLY)
+ ino->c_writers++;
+ if (O_ACCMODE(flag) != O_WRONLY)
+ ino->c_readers++;
+
+ /* FIXME: ATIME ? */
/*
* Sleep process if no writer or reader
*/
/* The nlink cheat needs to be taught to fsck! */
ino->c_node.i_mode = F_SOCK | 0777;
ino->c_node.i_nlink = n->s_num; /* Cheat !! */
+ ino->c_readers = 1;
+ ino->c_writers = 1;
of_tab[oftindex].o_inode = ino;
of_tab[oftindex].o_access = O_RDWR;