From: cheshirekow <che...@gm...> - 2012-07-09 14:55:49
|
On Sun, 2012-07-08 at 22:33 -0400, cheshirekow wrote: > Hi all, I'm trying to get started with fuse and having some trouble > implementing a simple "big brother" clone file system in c++. I've > followed the tutorial from > http://www.cs.nmsu.edu/~pfeiffer/fuse-tutorial/. My implementation is > essentially the same thing except that each function is a member > function of my file system class, and there's a singleton object of > that class. > > The problem that I am having is that, when testing with "cat", I get > the following error message: > > cat: openbook/test.txt: Input/output error > cat: openbook/test.txt: Input/output error > > Whenever I try to read from the mounted file system (the message > occurs after actually spitting out the contents of the file). My > implementation of open, read, and release are, as far as I can tell, > identical to the bbfs example. However, when I run the bbfs example, I > do NOT get these errors. > > I have noticed that if I mount with "-o direct_io" or if I set the > direct_io flag of the fuse_file_info structure in open... then this > error does not present itself. > > Here is my implementation of open, read, and release. These are the > only things that are logged when I cat the test file so I suspect the > problem has to be in here. Also, please note that "wrap()" appends the > root directory (of the underlying file system) to the requested path, > and "result_or_errno" returns the parameter unless it's less than > zero, in which case it returns -errno. > > Can anyone help me understand what is my problem? One more thing to note. I just learned about strace, so I ran strace cat openbook/test.txt I wont paste all the lines, but here is the interesting part: open("openbook/test.txt", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0664, st_size=23, ...}) = 0 read(3, "this is a line of text\n", 32768) = 23 write(1, "this is a line of text\n", 23this is a line of text ) = 23 read(3, 0x23d5000, 32768) = -1 EIO (Input/output error) So apparently, cat calls read once, and it works, then calls read again, and fuse returns -1. The interesting thing is that my file system doesn't receive this second call to read. I suspect that because the first read returns a value less than the requested number of bytes fuse sets the read offset for that file to be EOF. Then the second read that cat issues, fuse returns EIO because the offset is at EOF... this is just a guess. Also, I found this entry in the FAQ, but I'm not sure if it's related: ---FAQ--- I can not know the file size in advance, how do I force EOF from fs_read() to be seen in the application? Set direct_io in fs_open(). ---FAQ--- I don't think this is relevant though because I *do* know the file size in advance. In fact, my file system does tell that size to cat (in it's call to fstat). > > Thanks in advance > > > > > > int OpenbookFS::open (const char *path, struct fuse_file_info *fi) > { > std::cerr << "open: " > "\n path: " << path << > "\n : " << (m_dataDir/path) << > std::endl; > > int fh = ::open( wrap(path), fi->flags ); > fi->fh = fh; > > // evidently files must be opened with direct_io, otherwise cat will fail > // though I dont understand why > // fi->direct_io = 1; > > std::cerr << "Attempted to open " << wrap(path) << "\n fh: " << fh << std::endl; > > return result_or_errno(( fh > 0 ) ? 0 : fh); > } > > > > int OpenbookFS::read (const char *pathname, > char *buf, > size_t bufsize, > off_t offset, > struct fuse_file_info *fi) > { > std::cerr << "read: " > "\n path: " << pathname << > "\n : " << (m_dataDir/pathname) << > "\n size: " << bufsize << > "\n off: " << offset << > "\n fh: " << fi->fh << > std::endl; > > if(fi->fh) > { > int result = result_or_errno( ::pread(fi->fh,buf,bufsize,offset) ); > std::cerr << "Result of reading: " << result << std::endl; > return result; > > } > else > return -EBADF; > } > > int OpenbookFS::release (const char *path, struct fuse_file_info *fi) > { > std::cerr << "release: " > "\n path: " << path << > "\n : " << (m_dataDir / path) << > "\n fh: " << fi->fh; > > if(fi->fh) > { > int result = result_or_errno( ::close(fi->fh) ); > return result; > } > else > return -EBADF; > } |