263 lines
4.7 KiB
C
263 lines
4.7 KiB
C
/* Copyright (c) 20XX 9front
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
enum {
|
|
/* affects on-disk structure */
|
|
BLOCK = 4096,
|
|
RBLOCK = BLOCK - 1,
|
|
SUPERMAGIC = 0x6E0DE51C,
|
|
SUPERBLK = 0,
|
|
|
|
NAMELEN = 256,
|
|
NDIRECT = 15,
|
|
NINDIRECT = 4,
|
|
|
|
ROOTQID = 1,
|
|
DUMPROOTQID = 2,
|
|
|
|
/* affects just run-time behaviour */
|
|
SYNCINTERVAL = 10000,
|
|
FREELISTLEN = 256,
|
|
BUFHASHBITS = 8,
|
|
BUFHASH = (1<<BUFHASHBITS)-1,
|
|
NWORKERS = 5,
|
|
EXCLDUR = 300,
|
|
|
|
NOUID = (short)0x8000,
|
|
USERLEN = 64,
|
|
};
|
|
|
|
typedef struct Fs Fs;
|
|
typedef struct Buf Buf;
|
|
typedef struct Dev Dev;
|
|
typedef struct BufReq BufReq;
|
|
typedef struct ThrData ThrData;
|
|
typedef struct Superblock Superblock;
|
|
typedef struct Dentry Dentry;
|
|
typedef struct Chan Chan;
|
|
typedef struct FLoc FLoc;
|
|
typedef struct Loc Loc;
|
|
typedef struct User User;
|
|
|
|
#pragma incomplete struct User
|
|
#pragma varargck type "T" int
|
|
#pragma varargck type "T" uint
|
|
enum {
|
|
TRAW,
|
|
TSUPERBLOCK,
|
|
TDENTRY,
|
|
TINDIR,
|
|
TREF,
|
|
TDONTCARE = -1,
|
|
};
|
|
|
|
struct Superblock {
|
|
uint32_t magic;
|
|
uint64_t size;
|
|
uint64_t fstart;
|
|
uint64_t fend;
|
|
uint64_t root;
|
|
uint64_t qidpath;
|
|
};
|
|
|
|
enum {
|
|
DALLOC = 1<<15,
|
|
DGONE = 1<<14,
|
|
};
|
|
|
|
struct Dentry {
|
|
char name[NAMELEN];
|
|
short uid;
|
|
short muid;
|
|
short gid;
|
|
uint16_t mode;
|
|
Qid;
|
|
uint64_t size; /* bytes for files and blocks for dirs */
|
|
uint64_t db[NDIRECT];
|
|
uint64_t ib[NINDIRECT];
|
|
int64_t atime;
|
|
int64_t mtime;
|
|
};
|
|
|
|
enum {
|
|
DENTRYSIZ = NAMELEN + 4 * sizeof(uint16_t) + 13 + (3 + NDIRECT + NINDIRECT) * sizeof(uint64_t),
|
|
DEPERBLK = RBLOCK / DENTRYSIZ,
|
|
/* Given any opportunity to make a breaking change to hjfs,
|
|
* make this 12 an 8. Indirect offsets to blocks used to
|
|
* hold an incrementing 4 byte generation number. That
|
|
* design has changed.
|
|
*/
|
|
OFFPERBLK = RBLOCK / 12,
|
|
REFSIZ = 3,
|
|
REFPERBLK = RBLOCK / REFSIZ,
|
|
REFSENTINEL = (1 << 8*REFSIZ) - 1,
|
|
};
|
|
|
|
struct BufReq {
|
|
Dev *d;
|
|
uint64_t off;
|
|
int nodata;
|
|
Channel *resp;
|
|
BufReq *next;
|
|
};
|
|
|
|
enum {
|
|
BWRITE = 1, /* used only for the worker */
|
|
BWRIM = 2, /* write immediately after putbuf */
|
|
BDELWRI = 4, /* write delayed */
|
|
};
|
|
|
|
struct Buf {
|
|
uint8_t op, type;
|
|
union {
|
|
uint8_t data[RBLOCK];
|
|
Superblock sb;
|
|
Dentry de[DEPERBLK];
|
|
uint64_t offs[OFFPERBLK];
|
|
uint32_t refs[REFPERBLK];
|
|
};
|
|
|
|
/* do not use anything below (for the bufproc only) */
|
|
uint8_t busy;
|
|
char *error;
|
|
Buf *dnext, *dprev;
|
|
Buf *fnext, *fprev;
|
|
BufReq;
|
|
BufReq *last;
|
|
uint32_t callerpc; /* debugging */
|
|
|
|
Buf *wnext, *wprev;
|
|
};
|
|
|
|
struct ThrData {
|
|
Channel *resp;
|
|
};
|
|
|
|
struct Dev {
|
|
char *name;
|
|
int size;
|
|
Buf buf[BUFHASH+1]; /* doubly-linked list */
|
|
Dev *next;
|
|
int fd;
|
|
Rendez workr;
|
|
QLock workl;
|
|
Buf work;
|
|
};
|
|
|
|
extern Dev *devs;
|
|
|
|
struct FLoc {
|
|
uint64_t blk;
|
|
int deind;
|
|
Qid;
|
|
};
|
|
|
|
enum {
|
|
LGONE = 1,
|
|
LDUMPED = 2,
|
|
};
|
|
|
|
struct Loc {
|
|
FLoc;
|
|
int ref, flags;
|
|
Loc *next, *child;
|
|
Loc *cnext, *cprev;
|
|
Loc *gnext, *gprev;
|
|
|
|
QLock ex;
|
|
Chan *exlock;
|
|
uint32_t lwrite;
|
|
};
|
|
|
|
enum {
|
|
FSNOAUTH = 1,
|
|
FSNOPERM = 2,
|
|
FSCHOWN = 4,
|
|
};
|
|
|
|
struct Fs {
|
|
RWLock;
|
|
Dev *d;
|
|
int flags;
|
|
uint64_t root, fstart;
|
|
|
|
Channel *freelist;
|
|
Loc *rootloc, *dumprootloc;
|
|
QLock loctree;
|
|
|
|
User *udata;
|
|
int nudata;
|
|
RWLock udatal;
|
|
};
|
|
|
|
enum {
|
|
CHREAD = 1,
|
|
CHWRITE = 2,
|
|
CHRCLOSE = 4,
|
|
|
|
CHFDUMP = 1,
|
|
CHFNOLOCK = 2,
|
|
CHFRO = 4,
|
|
CHFNOPERM = 8,
|
|
|
|
CHWBUSY = 1,
|
|
CHWCLUNK = 2,
|
|
};
|
|
|
|
|
|
struct Chan {
|
|
Fs *fs;
|
|
Loc *loc;
|
|
uint8_t open;
|
|
uint8_t flags;
|
|
uint16_t uid;
|
|
|
|
/* dir walk */
|
|
uint64_t dwloff;
|
|
uint64_t dwblk;
|
|
int dwind;
|
|
|
|
/* workers */
|
|
void *freq, *lreq;
|
|
Chan *qnext, *qprev;
|
|
int wflags;
|
|
};
|
|
|
|
extern QLock chanqu;
|
|
extern Rendez chanre;
|
|
extern Chan readych;
|
|
|
|
extern char Eio[];
|
|
extern char Enotadir[];
|
|
extern char Enoent[];
|
|
extern char Einval[];
|
|
extern char Eperm[];
|
|
extern char Eexists[];
|
|
extern char Elocked[];
|
|
|
|
enum { /* getblk modes */
|
|
GBREAD = 0,
|
|
GBWRITE = 1,
|
|
GBCREATE = 2,
|
|
GBOVERWR = 3,
|
|
};
|
|
|
|
#define HOWMANY(a) (((a)+(RBLOCK-1))/RBLOCK)
|