int nblocks;
uint16_t inum;
+ i_lock(wd);
+
nblocks = (wd->c_node.i_size + BLKMASK) >> BLKSHIFT;
for(curblock=0; curblock < nblocks; ++curblock) {
if(namecomp(compname, d->d_name)) {
inum = d->d_ino;
brelse(buf);
+ i_unlock(wd);
return i_open(wd->c_dev, inum);
}
}
brelse(buf);
}
+ i_unlock(wd);
return NULLINODE;
}
struct direct curentry;
int i;
+ i_islocked(wd);
+
if (wd->c_flags & CRDONLY) {
udata.u_error = EROFS;
return false;
* file, and initializes the inode table entry for the new file.
* The new file will have one reference, and 0 links to it.
* Better make sure there isn't already an entry with the same name.
+ *
+ * Returns the new inode locked so nobody can access it before ready. We need
+ * to think hard about newfile taking a callback to fix up the ino struct so
+ * it's cleaner ???
*/
inoptr newfile(inoptr pino, char *name)
goto nogood;
}
+ i_lock(pino); /* Lock in tree order */
+ i_lock(ino);
/* This does not implement BSD style "sticky" groups */
nindex->c_node.i_uid = udata.u_euid;
nindex->c_node.i_gid = udata.u_egid;
nindex->c_node.i_addr[j] = 0;
}
wr_inode(nindex);
-
if (!ch_link(pino, "", name, nindex)) {
i_deref(nindex);
/* ch_link sets udata.u_error */
goto nogood;
}
- i_deref(pino);
+ i_unlock_deref(pino);
return nindex;
nogood:
- i_deref(pino);
+ i_unlock_deref(pino);
return NULLINODE;
}
#define HIBYTE32(x) ((uint8_t)((x) >> 24))
#endif
+#ifndef CONFIG_BLOCK_SLEEP
+#define i_unlock(x) do {} while(0)
+#define i_lock(x) do {} while(0)
+#define i_islocked(x) do {} while(0)
+#define i_unlock_deref(x) i_deref(x)
+#define n_open_lock(a,b) n_open((a),(b))
+#define getinode_lock(x) getinode(x)
+#endif
+
#ifdef CONFIG_LEVEL_2
#include "level2.h"
#else
oftp->o_ptr = ino->c_node.i_size;
/* Initialize u_offset from file pointer */
udata.u_offset = oftp->o_ptr;
+ i_lock(ino);
return (ino);
}
top = ramtop;
- if (!(ino = n_open(name, NULLINOPTR)))
+ if (!(ino = n_open_lock(name, NULLINOPTR)))
return (-1);
if (!((getperm(ino) & OTH_EX) &&
tmpfree(ebuf);
nogood2:
nogood:
- i_deref(ino);
+ i_unlock_deref(ino);
return (-1);
}
i_deref(parent);
return 0;
}
- if (parent && (ino = newfile(parent, "core"))) {
+ if (parent && i_lock(parent) && (ino = newfile(parent, "core"))) {
ino->c_node.i_mode = F_REG | 0400;
setftime(ino, A_TIME | M_TIME | C_TIME);
wr_inode(ino);
udata.u_base = udata.u_sp;
udata.u_count = PROGTOP - (uint16_t)udata.u_sp;
writei(ino, 0);
- i_deref(ino);
+ i_unlock_deref(ino);
return W_COREDUMP;
}
return 0;
uaddr_t go;
uint32_t true_brk;
- if (!(ino = n_open(name, NULLINOPTR)))
+ if (!(ino = n_open_lock(name, NULLINOPTR)))
return (-1);
if (!((getperm(ino) & OTH_EX) &&
tmpfree(abuf);
tmpfree(ebuf);
- i_deref(ino);
+ i_unlock_deref(ino);
/* Shove argc and the address of argv just below envp */
uputl((uint32_t) nargv, nenvp - 1);
tmpfree(ebuf);
nogood2:
nogood:
- i_deref(ino);
+ i_unlock_deref(ino);
return (-1);
}
* copy sequential runs of identical types (the only members which the
* compiler guarantees are next to each other). */
+ /* VIRTUAL: If we ever do true virtual memory we'll need to copy the
+ structure first or we may sleep and copy bits from different inode
+ states */
uint32_t zero = 0;
struct _uzistat* st = (struct _uzistat*) buf;
int err = uput(&ino->c_dev, &st->st_dev, 2 * sizeof(uint16_t));
if (!valaddr(buf, nbytes))
return -1;
+
/* Set up u_base, u_offset, ino; check permissions, file num. */
if ((ino = rwsetup(reading, &flag)) == NULLINODE)
return -1; /* bomb out if error */
(reading ? readi : writei)(ino, flag);
updoff();
+ i_unlock(ino);
return udata.u_done;
}
setftime(ino, A_TIME | M_TIME | C_TIME);
wr_inode(ino);
- i_deref(ino);
+ i_unlock_deref(ino);
return (0);
nogood:
inoptr ino;
int ret;
- if (!(ino = n_open(path, NULLINOPTR)))
+ if (!(ino = n_open_lock(path, NULLINOPTR)))
return (-1);
ret = chmod_op(ino);
- i_deref(ino);
+ i_unlock_deref(ino);
return ret;
}
arg_t _fchmod(void)
{
inoptr ino;
+ int ret;
- if ((ino = getinode(fd)) == NULLINODE)
+ if ((ino = getinode_lock(fd)) == NULLINODE)
return (-1);
- return chmod_op(ino);
+ ret = chmod_op(ino);
+ i_unlock_deref(ino);
+ return ret;
}
#undef fd
inoptr ino;
int ret;
- if (!(ino = n_open(path, NULLINOPTR)))
+ if (!(ino = n_open_lock(path, NULLINOPTR)))
return (-1);
ret = chown_op(ino);
- i_deref(ino);
+ i_unlock_deref(ino);
return ret;
}
#undef path
/*******************************************
- fchown (path, owner, group) Function 50
+ fchown (fd, owner, group) Function 50
int fd;
int owner;
int group;
arg_t _fchown(void)
{
inoptr ino;
+ int ret;
- if ((ino = getinode(fd)) == NULLINODE)
+ if ((ino = getinode_lock(fd)) == NULLINODE)
return (-1);
- return chown_op(ino);
+ ret = chown_op(ino);
+ i_unlock(ino);
+ return ret;
}
#undef fd
regptr inoptr ino;
time_t t[2];
- if (!(ino = n_open(file, NULLINOPTR)))
+ if (!(ino = n_open_lock(file, NULLINOPTR)))
return (-1);
if (ino->c_flags & CRDONLY) {
udata.u_error = EROFS;
ino->c_node.i_atime = t[0].low;
ino->c_node.i_mtime = t[1].low;
setftime(ino, C_TIME);
- i_deref(ino);
+ i_unlock_deref(ino);
return (0);
out:
udata.u_error = EPERM;
out2:
- i_deref(ino);
+ i_unlock_deref(ino);
return -1;
}
if ((oftindex = oft_alloc()) == -1)
goto nooft;
- ino = n_open(name, &parent);
+ ino = n_open_lock(name, &parent);
if (ino) {
i_deref(parent);
/* O_EXCL test */
udata.u_error = ENOENT;
goto cantopen;
}
- /* newfile drops parent for us */
+ /* newfile drops parent for us, ino is now locked */
ino = newfile(parent, lastname);
if (!ino) {
/* on error, newfile sets udata.u_error */
perm = getperm(ino);
if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) {
udata.u_error = EACCES;
- goto cantopen;
+ goto idrop;//cantopen;
}
if (w) {
if (getmode(ino) == MODE_R(F_DIR)) {
udata.u_error = EISDIR;
- goto cantopen;
+ goto idrop;//cantopen;
}
/* Special case - devices on a read only file system may
be opened read/write */
if (!isdevice(ino) && (ino->c_flags & CRDONLY)) {
udata.u_error = EROFS;
- goto cantopen;
+ goto idrop;//cantopen;
}
}
parent (but we don't need it again). It may also be changed
by the call to dev_openi */
- if (dev_openi(iptr, flag) != 0)
+ i_unlock(*iptr);
+ if (dev_openi(iptr, flag) != 0) {
+ i_deref(*iptr);
goto cantopen;
-
+ }
/* May have changed */
/* get the static pointer back in case it changed via dev
usage or just because we blocked */
ino = *iptr;
- }
-
- if (w && trunc && getmode(ino) == MODE_R(F_REG)) {
+ i_lock(ino);
+ } else if (w && trunc && getmode(ino) == MODE_R(F_REG)) {
if (f_trunc(ino))
goto idrop;
for (j = 0; j < OFTSIZE; ++j)
if (O_ACCMODE(flag) != O_WRONLY)
ino->c_readers++;
+ i_unlock(ino);
+
/* FIXME: ATIME ? */
/*
* Sleep process if no writer or reader.
return (uindex);
idrop:
- i_deref(ino);
+ i_unlock_deref(ino);
cantopen:
oft_deref(oftindex); /* This will call i_deref() */
nooft:
goto nogood;
}
+ i_lock(parent2);
if (!ch_link(parent2, "", lastname, ino)) {
- i_deref(parent2);
- goto nogood;
+ i_unlock_deref(parent2);
+ goto nogoodl;
}
/* Update the link count. */
wr_inode(ino);
setftime(ino, C_TIME);
- i_deref(parent2);
+ i_unlock_deref(parent2);
i_deref(ino);
return 0;
- nogood:
+nogoodl:
+ i_unlock(ino);
+nogood:
i_deref(ino);
return -1;
}
/* Drop the reference to the unlinked file */
i_deref(dsti);
}
+ i_lock(dstp);
/* Ok we may proceed: we set up fname earlier */
- if (!ch_link(dstp, "", lastname, srci))
+ if (!ch_link(dstp, "", lastname, srci)) {
+ i_unlock(dstp);
goto nogood2;
+ }
+ i_unlock(dstp);
/* A fail here is bad */
+ i_lock(srcp);
if (!ch_link(srcp, fname, "", NULLINODE)) {
+ i_unlock(srcp);
kputs("WARNING: rename: unlink fail\n");
goto nogood2;
}
/* get it onto disk - probably overkill */
+ i_unlock(srcp);
wr_inode(dstp);
wr_inode(srcp);
sync();
i_ref(parent); /* We need it again in a minute */
if (!(ino = newfile(parent, lastname))) {
- i_deref(parent);
+// i_deref(parent);
goto nogood2; /* parent inode is derefed in newfile. */
}
ino->c_node.i_mode = ((mode & ~udata.u_mask) & MODE_MASK) | F_DIR;
i_deref(parent);
wr_inode(ino);
- i_deref(ino);
+ i_unlock_deref(ino);
return (0);
- cleanup:
+cleanup:
+ i_lock(parent);
if (!ch_link(parent, fname, "", NULLINODE))
kprintf("_mkdir: bad rec\n");
+ i_unlock(parent);
/* i_deref will put the blocks */
ino->c_node.i_nlink = 0;
wr_inode(ino);
nogood:
- i_deref(ino);
+ i_unlock_deref(ino);
nogood2:
i_deref(parent);
return (-1);
return (-1);
}
+ i_lock(parent);
/* Fixme: check for rmdir of /. - ditto for unlink ? */
/* Not a directory */
setftime(ino, C_TIME);
wr_inode(parent);
wr_inode(ino);
- i_deref(parent);
+ i_unlock_deref(parent);
i_deref(ino);
return (0);
if (!(sino = n_open(spec, NULLINOPTR)))
return (-1);
- if (!(dino = n_open(dir, NULLINOPTR))) {
+ if (!(dino = n_open_lock(dir, NULLINOPTR))) {
i_deref(sino);
return (-1);
}
goto nogood;
}
- i_deref(dino);
+ i_unlock_deref(dino);
i_deref(sino);
return (0);
if (esuper())
return -1;
- if (!(sino = n_open(spec, NULLINOPTR)))
+ if (!(sino = n_open_lock(spec, NULLINOPTR)))
return -1;
if (getmode(sino) != MODE_R(F_BDEV)) {
}
ret = do_umount(dev);
nogood:
- i_deref(sino);
+ i_unlock_deref(sino);
return ret;
}