kernel: minimal patches and defines ready for parallel fs access support
authorAlan Cox <alan@linux.intel.com>
Tue, 20 Feb 2018 22:14:33 +0000 (22:14 +0000)
committerAlan Cox <alan@linux.intel.com>
Tue, 20 Feb 2018 22:14:33 +0000 (22:14 +0000)
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.

Kernel/filesys.c
Kernel/include/kernel.h
Kernel/inode.c
Kernel/syscall_exec16.c
Kernel/syscall_exec32.c
Kernel/syscall_fs.c
Kernel/syscall_fs2.c
Kernel/syscall_fs3.c
Kernel/syscall_other.c

index 8158ab4..cf64a9c 100644 (file)
@@ -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;
 }
 
index 63595ee..f956ca8 100644 (file)
@@ -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
index 8c8650f..57c4ad3 100644 (file)
@@ -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);
 }
 
index d5ec65e..1f0aad6 100644 (file)
@@ -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;
index e1380d5..c6f99ae 100644 (file)
@@ -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);
 }
 
index c1aa779..94dae7a 100644 (file)
@@ -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;
 }
index 564a333..0bac3e5 100644 (file)
@@ -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;
 }
 
index 10cdeb9..f85334d 100644 (file)
@@ -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;
 }
index 23e3029..f951714 100644 (file)
@@ -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;
 }