Ported more methods.

geesefs-0-30-9
Aaron Jacobs 2015-03-24 14:16:59 +11:00
parent f4c58fac66
commit 680eaa899d
1 changed files with 165 additions and 192 deletions

View File

@ -239,6 +239,92 @@ type OpenDirOp struct {
// Read entries from a directory previously opened with OpenDir.
type ReadDirOp struct {
Header RequestHeader
// The directory inode that we are reading, and the handle previously
// returned by OpenDir when opening that inode.
Inode InodeID
Handle HandleID
// The offset within the directory at which to read.
//
// Warning: this field is not necessarily a count of bytes. Its legal values
// are defined by the results returned in ReadDirResponse. See the notes
// below and the notes on that struct.
//
// In the Linux kernel this ultimately comes from file::f_pos, which starts
// at zero and is set by llseek and by the final consumed result returned by
// each call to ReadDir:
//
// * (http://goo.gl/2nWJPL) iterate_dir, which is called by getdents(2) and
// readdir(2), sets dir_context::pos to file::f_pos before calling
// f_op->iterate, and then does the opposite assignment afterward.
//
// * (http://goo.gl/rTQVSL) fuse_readdir, which implements iterate for fuse
// directories, passes dir_context::pos as the offset to fuse_read_fill,
// which passes it on to user-space. fuse_readdir later calls
// parse_dirfile with the same context.
//
// * (http://goo.gl/vU5ukv) For each returned result (except perhaps the
// last, which may be truncated by the page boundary), parse_dirfile
// updates dir_context::pos with fuse_dirent::off.
//
// It is affected by the Posix directory stream interfaces in the following
// manner:
//
// * (http://goo.gl/fQhbyn, http://goo.gl/ns1kDF) opendir initially causes
// filepos to be set to zero.
//
// * (http://goo.gl/ezNKyR, http://goo.gl/xOmDv0) readdir allows the user
// to iterate through the directory one entry at a time. As each entry is
// consumed, its d_off field is stored in __dirstream::filepos.
//
// * (http://goo.gl/WEOXG8, http://goo.gl/rjSXl3) telldir allows the user
// to obtain the d_off field from the most recently returned entry.
//
// * (http://goo.gl/WG3nDZ, http://goo.gl/Lp0U6W) seekdir allows the user
// to seek backward to an offset previously returned by telldir. It
// stores the new offset in filepos, and calls llseek to update the
// kernel's struct file.
//
// * (http://goo.gl/gONQhz, http://goo.gl/VlrQkc) rewinddir allows the user
// to go back to the beginning of the directory, obtaining a fresh view.
// It updates filepos and calls llseek to update the kernel's struct
// file.
//
// Unfortunately, FUSE offers no way to intercept seeks
// (http://goo.gl/H6gEXa), so there is no way to cause seekdir or rewinddir
// to fail. Additionally, there is no way to distinguish an explicit
// rewinddir followed by readdir from the initial readdir, or a rewinddir
// from a seekdir to the value returned by telldir just after opendir.
//
// Luckily, Posix is vague about what the user will see if they seek
// backwards, and requires the user not to seek to an old offset after a
// rewind. The only requirement on freshness is that rewinddir results in
// something that looks like a newly-opened directory. So FUSE file systems
// may e.g. cache an entire fresh listing for each ReadDir with a zero
// offset, and return array offsets into that cached listing.
Offset DirOffset
// The maximum number of bytes to return in ReadDirResponse.Data. A smaller
// number is acceptable.
Size int
// Set by the file system: a buffer consisting of a sequence of FUSE
// directory entries in the format generated by fuse_add_direntry
// (http://goo.gl/qCcHCV), which is consumed by parse_dirfile
// (http://goo.gl/2WUmD2). Use fuseutil.AppendDirent to generate this data.
//
// The buffer must not exceed the length specified in ReadDirRequest.Size. It
// is okay for the final entry to be truncated; parse_dirfile copes with this
// by ignoring the partial record.
//
// Each entry returned exposes a directory offset to the user that may later
// show up in ReadDirRequest.Offset. See notes on that field for more
// information.
//
// An empty buffer indicates the end of the directory has been reached.
Data []byte
}
// Release a previously-minted directory handle. The kernel sends this when
@ -248,6 +334,12 @@ type ReadDirOp struct {
// The kernel guarantees that the handle ID will not be used in further ops
// sent to the file system (unless it is reissued by the file system).
type ReleaseDirHandleOp struct {
Header RequestHeader
// The handle ID to be released. The kernel guarantees that this ID will not
// be used in further calls to the file system (unless it is reissued by the
// file system).
Handle HandleID
}
////////////////////////////////////////////////////////////////////////
@ -261,6 +353,22 @@ type ReleaseDirHandleOp struct {
// process. On OS X it may not be sent for every open(2)
// (cf.https://github.com/osxfuse/osxfuse/issues/199).
type OpenFileOp struct {
Header RequestHeader
// The ID of the inode to be opened.
Inode InodeID
// Mode and options flags.
Flags bazilfuse.OpenFlags
// An opaque ID that will be echoed in follow-up calls for this file using
// the same struct file in the kernel. In practice this usually means
// follow-up calls using the file descriptor returned by open(2).
//
// The handle may be supplied in future ops like ReadFileOp that contain a
// file handle. The file system must ensure this ID remains valid until a
// later call to ReleaseFileHandle.
Handle HandleID
}
// Read data from a file previously opened with CreateFile or OpenFile.
@ -269,6 +377,27 @@ type OpenFileOp struct {
// some reads may be served by the page cache. See notes on WriteFileOp for
// more.
type ReadFileOp struct {
Header RequestHeader
// The file inode that we are reading, and the handle previously returned by
// CreateFile or OpenFile when opening that inode.
Inode InodeID
Handle HandleID
// The range of the file to read.
//
// The FUSE documentation requires that exactly the number of bytes be
// returned, except in the case of EOF or error (http://goo.gl/ZgfBkF). This
// appears to be because it uses file mmapping machinery
// (http://goo.gl/SGxnaN) to read a page at a time. It appears to understand
// where EOF is by checking the inode size (http://goo.gl/0BkqKD), returned
// by a previous call to LookUpInode, GetInodeAttributes, etc.
Offset int64
Size int
// Set by the file system: the data read. If this is less than the requested
// size, it indicates EOF. An error should not be returned in this case.
Data []byte
}
// Write data to a file previously opened with CreateFile or OpenFile.
@ -300,6 +429,42 @@ type ReadFileOp struct {
// flush request.
//
type WriteFileOp struct {
Header RequestHeader
// The file inode that we are modifying, and the handle previously returned
// by CreateFile or OpenFile when opening that inode.
Inode InodeID
Handle HandleID
// The offset at which to write the data below.
//
// The man page for pwrite(2) implies that aside from changing the file
// handle's offset, using pwrite is equivalent to using lseek(2) and then
// write(2). The man page for lseek(2) says the following:
//
// "The lseek() function allows the file offset to be set beyond the end of
// the file (but this does not change the size of the file). If data is later
// written at this point, subsequent reads of the data in the gap (a "hole")
// return null bytes (aq\0aq) until data is actually written into the gap."
//
// It is therefore reasonable to assume that the kernel is looking for
// the following semantics:
//
// * If the offset is less than or equal to the current size, extend the
// file as necessary to fit any data that goes past the end of the file.
//
// * If the offset is greater than the current size, extend the file
// with null bytes until it is not, then do the above.
//
Offset int64
// The data to write.
//
// The FUSE documentation requires that exactly the number of bytes supplied
// be written, except on error (http://goo.gl/KUpwwn). This appears to be
// because it uses file mmapping machinery (http://goo.gl/SGxnaN) to write a
// page at a time.
Data []byte
}
// Synchronize the current contents of an open file to storage.
@ -384,198 +549,6 @@ type ReleaseFileHandleOp struct {
// Requests and responses
////////////////////////////////////////////////////////////////////////
type ReadDirRequest struct {
Header RequestHeader
// The directory inode that we are reading, and the handle previously
// returned by OpenDir when opening that inode.
Inode InodeID
Handle HandleID
// The offset within the directory at which to read.
//
// Warning: this field is not necessarily a count of bytes. Its legal values
// are defined by the results returned in ReadDirResponse. See the notes
// below and the notes on that struct.
//
// In the Linux kernel this ultimately comes from file::f_pos, which starts
// at zero and is set by llseek and by the final consumed result returned by
// each call to ReadDir:
//
// * (http://goo.gl/2nWJPL) iterate_dir, which is called by getdents(2) and
// readdir(2), sets dir_context::pos to file::f_pos before calling
// f_op->iterate, and then does the opposite assignment afterward.
//
// * (http://goo.gl/rTQVSL) fuse_readdir, which implements iterate for fuse
// directories, passes dir_context::pos as the offset to fuse_read_fill,
// which passes it on to user-space. fuse_readdir later calls
// parse_dirfile with the same context.
//
// * (http://goo.gl/vU5ukv) For each returned result (except perhaps the
// last, which may be truncated by the page boundary), parse_dirfile
// updates dir_context::pos with fuse_dirent::off.
//
// It is affected by the Posix directory stream interfaces in the following
// manner:
//
// * (http://goo.gl/fQhbyn, http://goo.gl/ns1kDF) opendir initially causes
// filepos to be set to zero.
//
// * (http://goo.gl/ezNKyR, http://goo.gl/xOmDv0) readdir allows the user
// to iterate through the directory one entry at a time. As each entry is
// consumed, its d_off field is stored in __dirstream::filepos.
//
// * (http://goo.gl/WEOXG8, http://goo.gl/rjSXl3) telldir allows the user
// to obtain the d_off field from the most recently returned entry.
//
// * (http://goo.gl/WG3nDZ, http://goo.gl/Lp0U6W) seekdir allows the user
// to seek backward to an offset previously returned by telldir. It
// stores the new offset in filepos, and calls llseek to update the
// kernel's struct file.
//
// * (http://goo.gl/gONQhz, http://goo.gl/VlrQkc) rewinddir allows the user
// to go back to the beginning of the directory, obtaining a fresh view.
// It updates filepos and calls llseek to update the kernel's struct
// file.
//
// Unfortunately, FUSE offers no way to intercept seeks
// (http://goo.gl/H6gEXa), so there is no way to cause seekdir or rewinddir
// to fail. Additionally, there is no way to distinguish an explicit
// rewinddir followed by readdir from the initial readdir, or a rewinddir
// from a seekdir to the value returned by telldir just after opendir.
//
// Luckily, Posix is vague about what the user will see if they seek
// backwards, and requires the user not to seek to an old offset after a
// rewind. The only requirement on freshness is that rewinddir results in
// something that looks like a newly-opened directory. So FUSE file systems
// may e.g. cache an entire fresh listing for each ReadDir with a zero
// offset, and return array offsets into that cached listing.
Offset DirOffset
// The maximum number of bytes to return in ReadDirResponse.Data. A smaller
// number is acceptable.
Size int
}
type ReadDirResponse struct {
// A buffer consisting of a sequence of FUSE directory entries in the format
// generated by fuse_add_direntry (http://goo.gl/qCcHCV), which is consumed
// by parse_dirfile (http://goo.gl/2WUmD2). Use fuseutil.AppendDirent to
// generate this data.
//
// The buffer must not exceed the length specified in ReadDirRequest.Size. It
// is okay for the final entry to be truncated; parse_dirfile copes with this
// by ignoring the partial record.
//
// Each entry returned exposes a directory offset to the user that may later
// show up in ReadDirRequest.Offset. See notes on that field for more
// information.
//
// An empty buffer indicates the end of the directory has been reached.
Data []byte
}
type ReleaseDirHandleRequest struct {
Header RequestHeader
// The handle ID to be released. The kernel guarantees that this ID will not
// be used in further calls to the file system (unless it is reissued by the
// file system).
Handle HandleID
}
type ReleaseDirHandleResponse struct {
}
type OpenFileRequest struct {
Header RequestHeader
// The ID of the inode to be opened.
Inode InodeID
// Mode and options flags.
Flags bazilfuse.OpenFlags
}
type OpenFileResponse struct {
// An opaque ID that will be echoed in follow-up calls for this file using
// the same struct file in the kernel. In practice this usually means
// follow-up calls using the file descriptor returned by open(2).
//
// The handle may be supplied in future ops like ReadFileOp that contain a
// file handle. The file system must ensure this ID remains valid until a
// later call to ReleaseFileHandle.
Handle HandleID
}
type ReadFileRequest struct {
Header RequestHeader
// The file inode that we are reading, and the handle previously returned by
// CreateFile or OpenFile when opening that inode.
Inode InodeID
Handle HandleID
// The range of the file to read.
//
// The FUSE documentation requires that exactly the number of bytes be
// returned, except in the case of EOF or error (http://goo.gl/ZgfBkF). This
// appears to be because it uses file mmapping machinery
// (http://goo.gl/SGxnaN) to read a page at a time. It appears to understand
// where EOF is by checking the inode size (http://goo.gl/0BkqKD), returned
// by a previous call to LookUpInode, GetInodeAttributes, etc.
Offset int64
Size int
}
type ReadFileResponse struct {
// The data read. If this is less than the requested size, it indicates EOF.
// An error should not be returned in this case.
Data []byte
}
type WriteFileRequest struct {
Header RequestHeader
// The file inode that we are modifying, and the handle previously returned
// by CreateFile or OpenFile when opening that inode.
Inode InodeID
Handle HandleID
// The offset at which to write the data below.
//
// The man page for pwrite(2) implies that aside from changing the file
// handle's offset, using pwrite is equivalent to using lseek(2) and then
// write(2). The man page for lseek(2) says the following:
//
// "The lseek() function allows the file offset to be set beyond the end of
// the file (but this does not change the size of the file). If data is later
// written at this point, subsequent reads of the data in the gap (a "hole")
// return null bytes (aq\0aq) until data is actually written into the gap."
//
// It is therefore reasonable to assume that the kernel is looking for
// the following semantics:
//
// * If the offset is less than or equal to the current size, extend the
// file as necessary to fit any data that goes past the end of the file.
//
// * If the offset is greater than the current size, extend the file
// with null bytes until it is not, then do the above.
//
Offset int64
// The data to write.
//
// The FUSE documentation requires that exactly the number of bytes supplied
// be written, except on error (http://goo.gl/KUpwwn). This appears to be
// because it uses file mmapping machinery (http://goo.gl/SGxnaN) to write a
// page at a time.
Data []byte
}
type WriteFileResponse struct {
}
type SyncFileRequest struct {
Header RequestHeader