diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-18 00:06:54 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-18 00:06:54 +0100 |
commit | 9a3942718357a83c534ee5a37ae9bd3bc85a2f50 (patch) | |
tree | 5ea4f3abfc6e2eba63739cb36dbe8fbc2a7ef2f3 | |
parent | 08cd0ea8d4cb921004e8f06caf0f99c944057bdf (diff) |
hjfs: fix dump / create
getdent() introduced a bug as the qid check fails in
the case when we walk to DUMPROOTQID, but get ROOTQID
in the directory instead.
newentry() getblk(..., GBCREATE) caused the whole
directory to get dumped until it hit a free slot.
we cannot do this because this changes the addresses
of Dentries of files but doesnt update the loctree.
this caused the bogus walks when we hit a different
directory than we expected.
what we do now is the following: newentry() was changed
to never dump anything. it will just read the directory
and return a the address of a free slot or create a
new block having space for one. chancreat() then makes
a loc in the loctree for the free slot, drops the dirent
buffer and calls willmodify() on the new slot. this will
dump the block containing the slot (and possible other
slots) and updates the loctree to the new version.
after that, chancreate() modifies the slot filling the
Dentry. there should be no race, as newentry() skips
slots that have a loc in the loctree.
theres one case where newentry() can dump the block
immidiately when it is called from dump. added new
parameter for that and documented in the comment.
createuserdir() was simplified by just calling chancreat().
to get arround the permission check, a new per channel
flag CHFNOPERM was added.
-rw-r--r-- | sys/src/cmd/hjfs/auth.c | 50 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/buf.c | 10 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/conv.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/dat.h | 2 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/dump.c | 21 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/fns.h | 2 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/fs1.c | 98 | ||||
-rw-r--r-- | sys/src/cmd/hjfs/fs2.c | 61 |
8 files changed, 123 insertions, 123 deletions
diff --git a/sys/src/cmd/hjfs/auth.c b/sys/src/cmd/hjfs/auth.c index fc2e41dca..a72b0e397 100644 --- a/sys/src/cmd/hjfs/auth.c +++ b/sys/src/cmd/hjfs/auth.c @@ -366,54 +366,14 @@ static void createuserdir(Fs *fs, char *name, short uid) { Chan *ch; - Buf *b, *c; - Dentry *d; - FLoc f; - ch = chanattach(fs, 0); + ch = chanattach(fs, CHFNOPERM); if(ch == nil) return; - ch->uid = -1; - if(chanwalk(ch, "usr") <= 0 || (ch->loc->type & QTDIR) == 0){ - direrr: - chanclunk(ch); - return; - } - chbegin(ch); - if(willmodify(ch->fs, ch->loc, 0) < 0){ - direrr1: - chend(ch); - goto direrr; - } - b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); - if(b == nil) - goto direrr1; - if(newentry(ch->fs, ch->loc, b, name, &f) <= 0){ - direrr2: - putbuf(b); - goto direrr1; - } - modified(ch, &b->de[ch->loc->deind]); - c = getbuf(ch->fs->d, f.blk, TDENTRY, 0); - if(c == nil) - goto direrr2; - c->op |= BDELWRI; - d = &c->de[f.deind]; - memset(d, 0, sizeof(*d)); - if(newqid(fs, &d->path) < 0){ - direrr3: - putbuf(c); - goto direrr2; - } - strncpy(d->name, name, NAMELEN - 1); - d->uid = uid; - d->muid = uid; - d->gid = uid; - d->mode = DALLOC | 0775; - d->type = QTDIR; - d->atime = time(0); - d->mtime = d->atime; - goto direrr3; + ch->uid = uid; + if(chanwalk(ch, "usr") > 0) + chancreat(ch, name, DMDIR | 0775, OREAD); + chanclunk(ch); } int diff --git a/sys/src/cmd/hjfs/buf.c b/sys/src/cmd/hjfs/buf.c index 51fdff162..46faa0991 100644 --- a/sys/src/cmd/hjfs/buf.c +++ b/sys/src/cmd/hjfs/buf.c @@ -266,6 +266,11 @@ getbuf(Dev *d, uvlong off, int type, int nodata) req.nodata = nodata; send(getb, &req); recv(th->resp, &b); + if(b->error != nil){ + werrstr("%s", b->error); + putbuf(b); + return nil; + } if(nodata) b->type = type; if(b->type != type && type != -1){ @@ -275,11 +280,6 @@ getbuf(Dev *d, uvlong off, int type, int nodata) putbuf(b); return nil; } - if(b->error != nil){ - werrstr("%s", b->error); - putbuf(b); - return nil; - } b->callerpc = getcallerpc(&d); return b; } diff --git a/sys/src/cmd/hjfs/conv.c b/sys/src/cmd/hjfs/conv.c index 21333e222..abedbe47a 100644 --- a/sys/src/cmd/hjfs/conv.c +++ b/sys/src/cmd/hjfs/conv.c @@ -53,7 +53,7 @@ unpack(Buf *b, uchar *p) GET64(b->sb.qidpath); break; case TDENTRY: - for(d = b->de; d < b->de + nelem(b->de); d++){ + for(d = b->de; d < &b->de[DEPERBLK]; d++){ GETS(d->name, NAMELEN); GET16(d->uid); GET16(d->muid); diff --git a/sys/src/cmd/hjfs/dat.h b/sys/src/cmd/hjfs/dat.h index 014eba424..83359d48f 100644 --- a/sys/src/cmd/hjfs/dat.h +++ b/sys/src/cmd/hjfs/dat.h @@ -185,8 +185,10 @@ enum { CHWRITE = 2, CHRCLOSE = 4, CHFDUMP = 1, + CHFNOLOCK = 2, CHFRO = 4, + CHFNOPERM = 8, CHWBUSY = 1, CHWCLUNK = 2, diff --git a/sys/src/cmd/hjfs/dump.c b/sys/src/cmd/hjfs/dump.c index 210e57964..4a9982693 100644 --- a/sys/src/cmd/hjfs/dump.c +++ b/sys/src/cmd/hjfs/dump.c @@ -24,7 +24,7 @@ copydentry(Fs *fs, FLoc *a, Loc *b, char *nname) putbuf(ba); return -1; } - rc = newentry(fs, b, bb, nname, &c); + rc = newentry(fs, b, bb, nname, &c, 1); if(rc < 0){ err1: putbuf(bb); @@ -35,7 +35,7 @@ copydentry(Fs *fs, FLoc *a, Loc *b, char *nname) if(bc == nil) goto err1; d = &bc->de[c.deind]; - memcpy(d, &ba->de[a->deind], sizeof(Dentry)); + memcpy(d, &ba->de[a->deind], sizeof(*d)); strcpy(d->name, nname); for(i = 0; i < NDIRECT; i++) if(d->db[i] != 0) @@ -116,6 +116,7 @@ int willmodify(Fs *fs, Loc *l, int nolock) { Buf *p; + Loc *m; uvlong i, r; Dentry *d; int rc; @@ -150,7 +151,7 @@ again: continue; if(r == l->blk) goto found; - } + } phase: werrstr("willmodify -- phase error"); putbuf(p); @@ -164,7 +165,19 @@ found: if(rc == 0) goto phase; putbuf(p); - l->blk = r; + + if(r != l->blk){ + /* + * block got dumped, update the loctree so locs + * point to the new block. + */ + qlock(&fs->loctree); + for(m = l->cnext; m != l; m = m->cnext) + if(m->blk == l->blk) + m->blk = r; + l->blk = r; + qunlock(&fs->loctree); + } done: l->flags |= LDUMPED; if(!nolock){ diff --git a/sys/src/cmd/hjfs/fns.h b/sys/src/cmd/hjfs/fns.h index 0a917191e..26e525e27 100644 --- a/sys/src/cmd/hjfs/fns.h +++ b/sys/src/cmd/hjfs/fns.h @@ -44,7 +44,7 @@ int trunc(Fs *, FLoc *, Buf *, uvlong); int dprint(char *fmt, ...); int delete(Fs *, FLoc *, Buf *); int chref(Fs *, uvlong, int); -int newentry(Fs *, Loc *, Buf *, char *, FLoc *); +int newentry(Fs *, Loc *, Buf *, char *, FLoc *, int); int namevalid(char *); int usersload(Fs *, Chan *); int userssave(Fs *, Chan *); diff --git a/sys/src/cmd/hjfs/fs1.c b/sys/src/cmd/hjfs/fs1.c index 6f914f911..1d463f2db 100644 --- a/sys/src/cmd/hjfs/fs1.c +++ b/sys/src/cmd/hjfs/fs1.c @@ -34,8 +34,12 @@ qidcmp(Qid *a, Qid *b) { if(a->type != b->type) return 1; - if(a->path != b->path) + if(a->path != b->path){ + /* special case for dump, this is ok */ + if(a->path==ROOTQID && b->path==DUMPROOTQID) + return 0; return 1; + } return 0; } @@ -46,12 +50,14 @@ getdent(FLoc *l, Buf *b) d = &b->de[l->deind]; if((d->mode & (DGONE | DALLOC)) == 0){ - dprint("hjfs: getdent: file gone, callerpc %#p\n", getcallerpc(&l)); + dprint("hjfs: getdent: file gone, d=%llux, l=%llud/%d %llux, callerpc %#p\n", + d->path, l->blk, l->deind, l->path, getcallerpc(&l)); werrstr("phase error -- getdent"); return nil; } if(qidcmp(d, l) != 0){ - dprint("hjfs: getdent: wrong qid, callerpc %#p\n", getcallerpc(&l)); + dprint("hjfs: getdent: wrong qid d=%llux != l=%llud/%d %llux, callerpc %#p\n", + d->path, l->blk, l->deind, l->path, getcallerpc(&l)); werrstr("phase error -- getdent"); return nil; } @@ -950,66 +956,70 @@ delete(Fs *fs, FLoc *l, Buf *b) return 0; } +/* + * newentry() looks for a free slot in the directory + * and returns FLoc pointing to the slot. if no free + * slot is available a new block is allocated. if + * dump == 0, then the resulting blk from the FLoc + * *is not* dumped, so to finally allocate the Dentry, + * one has to call willmodify() on res before modyfing it. + */ int -newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res) +newentry(Fs *fs, Loc *l, Buf *b, char *name, FLoc *res, int dump) { Dentry *d, *dd; uvlong i, si, r; - int j, sj, rc; + int j, sj; Buf *c; - FLoc f; si = sj = -1; d = getdent(l, b); - if(d != nil) for(i = 0; i <= d->size; i++){ - if(i >= d->size && si != -1) - break; - rc = getblk(fs, l, b, i, &r, si == -1 ? GBCREATE : GBREAD); - if(rc < 0) - continue; - if(rc == 0 && si != -1) - continue; - c = getbuf(fs->d, r, TDENTRY, rc == 0); - if(c == nil) - continue; - if(rc == 0){ - memset(c->de, 0, sizeof(c->de)); - if(i >= d->size){ - d->size = i+1; - b->op |= BDELWRI; + if(d != nil){ + for(i = 0; i < d->size; i++){ + if(getblk(fs, l, b, i, &r, GBREAD) <= 0) + continue; + c = getbuf(fs->d, r, TDENTRY, 0); + if(c == nil) + continue; + for(j = 0; j < DEPERBLK; j++){ + dd = &c->de[j]; + if((dd->mode & DGONE) != 0) + continue; + if((dd->mode & DALLOC) != 0){ + if(strcmp(dd->name, name) == 0){ + werrstr(Eexists); + putbuf(c); + return 0; + } + continue; + } + if(si != -1 || haveloc(fs, r, j, l)) + continue; + si = i; + sj = j; } - c->op |= BDELWRI; + putbuf(c); } - for(j = 0; j < DEPERBLK; j++){ - dd = &c->de[j]; - if((dd->mode & DALLOC) != 0){ - if(strcmp(dd->name, name) == 0){ - werrstr(Eexists); + if(si == -1 && i == d->size){ + if(getblk(fs, l, b, i, &r, GBCREATE) >= 0){ + c = getbuf(fs->d, r, TDENTRY, 1); + if(c != nil){ + si = i; + sj = 0; + d->size = i+1; + b->op |= BDELWRI; + memset(c->de, 0, sizeof(c->de)); + c->op |= BDELWRI; putbuf(c); - return 0; } - continue; } - if(si != -1 || haveloc(fs, r, j, l)) - continue; - if((dd->mode & DGONE) != 0){ - memset(&f, 0, sizeof(f)); - f.blk = r; - f.deind = j; - f.Qid = dd->Qid; - if(delete(fs, &f, c) < 0) - continue; - } - si = i; - sj = j; } - putbuf(c); } if(si == -1 || sj == -1){ werrstr("phase error -- create"); return -1; } - if(getblk(fs, l, b, si, &res->blk, GBWRITE) <= 0) + if(getblk(fs, l, b, si, &res->blk, dump != 0 ? GBWRITE : GBREAD) <= 0) return -1; res->deind = sj; res->Qid = (Qid){0, 0, 0}; diff --git a/sys/src/cmd/hjfs/fs2.c b/sys/src/cmd/hjfs/fs2.c index d2a4a8830..d2fd918a4 100644 --- a/sys/src/cmd/hjfs/fs2.c +++ b/sys/src/cmd/hjfs/fs2.c @@ -104,11 +104,12 @@ namevalid(char *name) int chancreat(Chan *ch, char *name, int perm, int mode) { - Buf *b, *c; + Buf *b; Dentry *d; int isdir; + Loc *l; FLoc f; - + if((ch->flags & CHFRO) != 0){ werrstr(Einval); return -1; @@ -134,6 +135,7 @@ chancreat(Chan *ch, char *name, int perm, int mode) chend(ch); return -1; } + l = nil; d = getdent(ch->loc, b); if(d == nil) goto error; @@ -141,44 +143,49 @@ chancreat(Chan *ch, char *name, int perm, int mode) werrstr(Enotadir); goto error; } - if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ - werrstr(Eperm); - goto error; - } - if(newentry(ch->fs, ch->loc, b, name, &f) <= 0) - goto error; - c = getbuf(ch->fs->d, f.blk, TDENTRY, 0); - if(c == nil) + if((ch->flags & CHFNOPERM) == 0) /* for console */ + if(!permcheck(ch->fs, d, ch->uid, OWRITE)){ + werrstr(Eperm); + goto error; + } + if(newentry(ch->fs, ch->loc, b, name, &f, 0) <= 0) goto error; - modified(ch, d); - b->op |= BDELWRI; - c->op |= BDELWRI; if(isdir) perm &= ~0777 | d->mode & 0777; else perm &= ~0666 | d->mode & 0666; - d = &c->de[f.deind]; - memset(d, 0, sizeof(*d)); - if(newqid(ch->fs, &d->path) < 0){ - putbuf(c); + f.type = perm >> 24; + if(newqid(ch->fs, &f.path) < 0) goto error; - } - d->type = perm >> 24; + l = getloc(ch->fs, f, ch->loc); + modified(ch, d); + b->op |= BDELWRI; + putbuf(b); + b = nil; + + if(willmodify(ch->fs, l, ch->flags & CHFNOLOCK) < 0) + goto error; + b = getbuf(ch->fs->d, l->blk, TDENTRY, 0); + if(b == nil) + goto error; + ch->loc = l; + d = &b->de[l->deind]; + memset(d, 0, sizeof(*d)); + d->Qid = l->Qid; strcpy(d->name, name); d->mtime = time(0); d->atime = d->mtime; d->gid = d->uid = d->muid = ch->uid; d->mode = DALLOC | perm & 0777; - f.Qid = d->Qid; - ch->loc = getloc(ch->fs, f, ch->loc); if((d->type & QTEXCL) != 0){ qlock(&ch->loc->ex); ch->loc->exlock = ch; ch->loc->lwrite = d->atime; qunlock(&ch->loc->ex); } - putbuf(c); + b->op |= BDELWRI; putbuf(b); + switch(mode & OEXEC){ case ORDWR: ch->open |= CHREAD; @@ -194,7 +201,10 @@ chancreat(Chan *ch, char *name, int perm, int mode) return 1; error: - putbuf(b); + if(l != nil) + putloc(ch->fs, l, 0); + if(b != nil) + putbuf(b); chend(ch); return -1; } @@ -212,6 +222,11 @@ chanopen(Chan *ch, int mode) chend(ch); return -1; } + if((mode & OTRUNC) != 0) + if(willmodify(ch->fs, ch->loc, ch->flags & CHFNOLOCK) < 0){ + chend(ch); + return -1; + } b = getbuf(ch->fs->d, ch->loc->blk, TDENTRY, 0); if(b == nil){ chend(ch); |