From: Antiochus A. <ant...@gm...> - 2008-05-30 19:55:11
|
On Fri, May 30, 2008 at 2:06 PM, Miklos Szeredi <mi...@sz...> wrote: > > Please let me know if that is not the right place for this type of > > questions. > > > > I am seeing this message in the log file of our virtual file system and > was > > trying to track its root cause. Inspecting > fuse-2.7.2/lib/fuse_kern_chan.c > > shows that this message is printed from fuse_kern_chan_receive() after > > verifying that errno after read() return -1 is not in the set (ENOENT, > > ENODEV, EINTR, EAGAIN). However, per the read() manual pages, read() > would > > not set errno to 512, which is strange. And 512 is not a valid errno > value. > > My user-space read() implementation appears below and fi->fh was > previously > > initialized by opening a temporary file created on the fly on the local > > filesystem (ext3) when calling my open() callback. > > > > static int read(const char *path, char *buf, size_t size, off_t > > offset, struct fuse_file_info *fi) > > { > > int res; > > (void) path; > > res = pread(fi->fh, buf, size, offset); > > if (res == -1) > > res = -errno; > > return res; > > } > > Would anyone have a suggestion, please? > > This is strange indeed. 512 means ERESTARTSYS, which is a kernel > internal errno value. But it should never be seen in userspace. > > > cat /proc/version > > Linux version 2.6.18-53.1.13.el5xen (moc...@bu...) (gcc > > version 4.1.2 20070626 (Red Hat 4.1.2-14)) #1 SMP Tue Feb 12 13:33:07 EST > > 2008 > > It doesn't look like a fuse problem (fuse is correctly rejecting the > errno as invalid). Perhaps it is xen related? > > Miklos > Thanks for you answer, Miklos. Given that ERSTARTSYS tells drivers to re-perform system call, are we supposed to add the followingto fuse_kern_chan_receive(): static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf, size_t size) { struct fuse_chan *ch = *chp; int err; ssize_t res; struct fuse_session *se = fuse_chan_session(ch); assert(se != NULL); restart: res = read(fuse_chan_fd(ch), buf, size); err = errno; if (fuse_session_exited(se)) return 0; if (res == -1) { /* ENOENT and ERSTARTSYS means the operation was interrupted, it's safe to restart */ if (err == ENOENT || err == ERSTARTSYS) goto restart; if (err == ENODEV) { fuse_session_exit(se); return 0; } /* Errors occuring during normal operation: EINTR (read interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem umounted) */ if (err != EINTR && err != EAGAIN) perror("fuse: reading device"); return -err; } if ((size_t) res < sizeof(struct fuse_in_header)) { fprintf(stderr, "short read on fuse device\n"); return -EIO; } return res; } |