fhtab::fh * fhtab::alloc (aiod_file *af, int *errp, bool create, mode_t mode) { int oflags = af->oflags; if (!create) oflags &= ~(O_CREAT|O_TRUNC|O_EXCL); int fd = open (af->path, oflags, mode); if (fd < 0) { *errp = errno; tab.remove (af->handle); return NULL; } struct stat sb; if (fstat (fd, &sb) < 0) { *errp = errno; ::close (fd); tab.remove (af->handle); return NULL; } if (create) { af->dev = sb.st_dev; af->ino = sb.st_ino; } else if (af->dev != sb.st_dev || af->ino != sb.st_ino) { *errp = ESTALE; ::close (fd); tab.remove (af->handle); return NULL; } ref<fh> h = New refcounted<fh> (fd, sb.st_dev, sb.st_ino, af->path); tab.insert (af->handle, h); return h; }
dhtab::fh * dhtab::alloc (aiod_file *af, int *errp) { DIR *fd = opendir (af->path); if (fd == NULL) { *errp = errno; tab.remove (af->handle); return NULL; } ref<fh> h = New refcounted<fh> (fd, 0, 0, af->path); tab.insert (af->handle, h); return h; }
int fhtab::close (aiod_file *af, int *errp) { errno = 0; tab.remove (af->handle); if (errno) { *errp = errno; return -1; } return 0; }
int fhtab::lookup (aiod_file *af, int *errp) { fh *h = tab[af->handle]; if (!h) { h = alloc (af, errp); if (!h) return -1; } else if (af->dev != h->dev || af->ino != h->ino) { /* This shouldn't happen, unless someone closes a file descriptor * with outstanding requests (in which case the close could get * reordered). However such usage is really a bug in the calling * program. */ warn ("stale handle on already open file\n"); tab.remove (af->handle); h = alloc (af, errp); if (!h) return -1; } return h->fd; }