From: Alan Cox Date: Tue, 20 Feb 2018 22:14:33 +0000 (+0000) Subject: kernel: minimal patches and defines ready for parallel fs access support X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=a812280cbe88aaad3472b2e2f47843431af569a4;p=FUZIX.git kernel: minimal patches and defines ready for parallel fs access support This puts in place the pieces we will need to hook up in order to support sleeping file system accesses. We also need to add 'D' state to the scheduler but that is needed anyway to fix some other corner cases. --- diff --git a/Kernel/filesys.c b/Kernel/filesys.c index 8158ab47..cf64a9c0 100644 --- a/Kernel/filesys.c +++ b/Kernel/filesys.c @@ -158,6 +158,8 @@ inoptr srch_dir(inoptr wd, char *compname) int nblocks; uint16_t inum; + i_lock(wd); + nblocks = (wd->c_node.i_size + BLKMASK) >> BLKSHIFT; for(curblock=0; curblock < nblocks; ++curblock) { @@ -169,11 +171,13 @@ inoptr srch_dir(inoptr wd, char *compname) 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; } @@ -293,6 +297,8 @@ bool ch_link(inoptr wd, char *oldname, char *newname, inoptr nindex) struct direct curentry; int i; + i_islocked(wd); + if (wd->c_flags & CRDONLY) { udata.u_error = EROFS; return false; @@ -394,6 +400,10 @@ bool namecomp(char *n1, char *n2) // return true if n1 == n2 * 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) @@ -423,6 +433,8 @@ 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; @@ -434,17 +446,16 @@ inoptr newfile(inoptr pino, char *name) 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; } diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index 63595ee4..f956ca82 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -49,6 +49,15 @@ From UZI by Doug Braun and UZI280 by Stefan Nitschke. #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 diff --git a/Kernel/inode.c b/Kernel/inode.c index 8c8650f8..57c4ad39 100644 --- a/Kernel/inode.c +++ b/Kernel/inode.c @@ -317,6 +317,7 @@ inoptr rwsetup(bool is_read, uint8_t * flag) 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); } diff --git a/Kernel/syscall_exec16.c b/Kernel/syscall_exec16.c index d5ec65e9..1f0aad67 100644 --- a/Kernel/syscall_exec16.c +++ b/Kernel/syscall_exec16.c @@ -61,7 +61,7 @@ arg_t _execve(void) top = ramtop; - if (!(ino = n_open(name, NULLINOPTR))) + if (!(ino = n_open_lock(name, NULLINOPTR))) return (-1); if (!((getperm(ino) & OTH_EX) && @@ -230,7 +230,7 @@ nogood3: tmpfree(ebuf); nogood2: nogood: - i_deref(ino); + i_unlock_deref(ino); return (-1); } @@ -351,7 +351,7 @@ uint8_t write_core_image(void) 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); @@ -377,7 +377,7 @@ uint8_t write_core_image(void) 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; diff --git a/Kernel/syscall_exec32.c b/Kernel/syscall_exec32.c index e1380d5a..c6f99ae4 100644 --- a/Kernel/syscall_exec32.c +++ b/Kernel/syscall_exec32.c @@ -128,7 +128,7 @@ arg_t _execve(void) 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) && @@ -262,7 +262,7 @@ arg_t _execve(void) 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); @@ -290,7 +290,7 @@ nogood3: tmpfree(ebuf); nogood2: nogood: - i_deref(ino); + i_unlock_deref(ino); return (-1); } diff --git a/Kernel/syscall_fs.c b/Kernel/syscall_fs.c index c1aa7797..94dae7a1 100644 --- a/Kernel/syscall_fs.c +++ b/Kernel/syscall_fs.c @@ -144,6 +144,9 @@ int stcpy(inoptr ino, char *buf) * 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)); @@ -422,12 +425,14 @@ arg_t readwrite(uint8_t reading) 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; } diff --git a/Kernel/syscall_fs2.c b/Kernel/syscall_fs2.c index 564a3336..0bac3e59 100644 --- a/Kernel/syscall_fs2.c +++ b/Kernel/syscall_fs2.c @@ -116,7 +116,7 @@ arg_t _mknod(void) setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); - i_deref(ino); + i_unlock_deref(ino); return (0); nogood: @@ -209,10 +209,10 @@ arg_t _chmod(void) 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; } @@ -228,11 +228,14 @@ arg_t _chmod(void) 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 @@ -271,17 +274,17 @@ arg_t _chown(void) 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; @@ -291,10 +294,13 @@ arg_t _chown(void) 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 @@ -313,7 +319,7 @@ arg_t _utime(void) 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; @@ -337,12 +343,12 @@ arg_t _utime(void) 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; } diff --git a/Kernel/syscall_fs3.c b/Kernel/syscall_fs3.c index 10cdeb97..f85334d5 100644 --- a/Kernel/syscall_fs3.c +++ b/Kernel/syscall_fs3.c @@ -42,7 +42,7 @@ arg_t _open(void) 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 */ @@ -60,7 +60,7 @@ arg_t _open(void) 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 */ @@ -80,18 +80,18 @@ arg_t _open(void) 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; } } @@ -101,16 +101,17 @@ arg_t _open(void) 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) @@ -131,6 +132,8 @@ arg_t _open(void) if (O_ACCMODE(flag) != O_WRONLY) ino->c_readers++; + i_unlock(ino); + /* FIXME: ATIME ? */ /* * Sleep process if no writer or reader. @@ -144,7 +147,7 @@ arg_t _open(void) return (uindex); idrop: - i_deref(ino); + i_unlock_deref(ino); cantopen: oft_deref(oftindex); /* This will call i_deref() */ nooft: @@ -200,9 +203,10 @@ arg_t _link(void) 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. */ @@ -210,11 +214,13 @@ arg_t _link(void) 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; } diff --git a/Kernel/syscall_other.c b/Kernel/syscall_other.c index 23e3029b..f951714c 100644 --- a/Kernel/syscall_other.c +++ b/Kernel/syscall_other.c @@ -94,15 +94,22 @@ arg_t _rename(void) /* 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(); @@ -159,7 +166,7 @@ arg_t _mkdir(void) 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. */ } @@ -176,17 +183,19 @@ arg_t _mkdir(void) 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); @@ -221,6 +230,7 @@ arg_t _rmdir(void) return (-1); } + i_lock(parent); /* Fixme: check for rmdir of /. - ditto for unlink ? */ /* Not a directory */ @@ -254,7 +264,7 @@ arg_t _rmdir(void) setftime(ino, C_TIME); wr_inode(parent); wr_inode(ino); - i_deref(parent); + i_unlock_deref(parent); i_deref(ino); return (0); @@ -294,7 +304,7 @@ arg_t _mount(void) 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); } @@ -328,7 +338,7 @@ arg_t _mount(void) goto nogood; } - i_deref(dino); + i_unlock_deref(dino); i_deref(sino); return (0); @@ -426,7 +436,7 @@ arg_t _umount(void) 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)) { @@ -441,7 +451,7 @@ arg_t _umount(void) } ret = do_umount(dev); nogood: - i_deref(sino); + i_unlock_deref(sino); return ret; }