int gfs_create_file(char *name, int *IOP_list, int num_iops)
name
. The application has
the option of specifying the number of IOPs it wishes the file to be created
on, and even which IOPs. This call implicitly creates a subfile on each IOP.
int gfs_open_file(char *name)
int gfs_close_file(int file_id)
int gfs_delete_file(char *name)
name
. This implicitly deletes all of
the files subfiles and their forks.
int gfs_create_fork(int file_id, int subfile, char *name)
name
in subfile subfile
of the previously opened file file
.
int gfs_all_create(int file_id, char *name)
name
in each subfile of the open
file file_id
.
int gfs_open_fork(int file_id, int subfile, char *name)
name
in subfile subfile
of the previously opened file file
. Return either an
open fork ID or an error code.
int gfs_all_open(int file_id, int *fork_ids, char *name)
name
in each subfile of the previously
opened file file
. The array, fork_ids
, is filled
with fork IDs. This call returns the number of forks opened or an error code.
int gfs_extend_fork(int fork_id, ulong_t size)
fork_id
to be size
bytes
long. Explictly extending a file increases the likelihood that a file will
have good disk locality.
int gfs_close_fork(int fork_id)
int gfs_all_close(int file_id, int *fork_ids)
gfs_all_open()
call, but it is not
required.
int gfs_delete_fork(int file_id, int subfile, char *name)
name
in subfile subfile
of the open file file_id
.
int gfs_all_delete(int file_id, char *name)
name
in each subfile of the file
file_id
.
int gfs_read(int fork_id, char *buf, ulong_t offset, ulong_t size)
read()
, reading a contiguous range of size
bytes, and storing them in memory at buf
. Unlike Unix,
however, Galley does not maintain an implicit file pointer, marking the
location of the previous access. As a result, the application must
explicitly indicate the starting offset of the request in the fork.
int gfs_read_block(int fork_id, char *buf, int block)
gfs_read()
). Specifically, Galley is
able to schedule disk accesses intelligently, reducing the amount of
time that is wasted seeking from one portion of the disk to another.
Galley is also able to reduce the number of messages that are exchanged
between the CP and IOP. For example, rather than sending 512 messages,
each with 64 bytes of data, Galley can pack those pieces into a single
32768 byte message.
int gfs_read_strided(int fork_id, char *buf, ulong_t offset,
ulong_t size, int file_stride, int mem_stride, int quant)
offset
, Galley will read
quant
records of size
bytes. The offset of
each record is file_stride
bytes greater than the previous
record's offset. The records will be stored in memory at
buf
, with mem_stride
bytes between each
record.
If file_stride
is equal to size
,
then data will be read contiguously from disk (as with the
gfs_read()
call), but will be scattered in
memory. On the other hand, if mem_stride
is equal to
size
, then data will be gathered from disk, but
stored contiguously in memory. Of course, the more adventurous
programmer may scatter and gather in the same operation. Note also
that either file_stride
or mem_stride
may be
negative.
int gfs_read_nested(int fork_id, char *buf, ulong_t offset,
ulong_t size, struct gfs_stride *vector, int levels)
vector
is a pointer to an array of (file_stride,
mem_stride, quantity)
triples listed from the innermost level of
nesting to the outermost. The number of levels of nesting is indicated
by levels
. As with the gfs_strided()
call,
appropriate choices of file_stride
and
mem_stride
allow the application a wide array of
scatter/gather possibilities.
int gfs_read_listio(int fork_id, char *buf, struct gfs_list
*list, int quant)
list
points
to a vector of (file_offset, memory_offset, size)
triples,
and quant
indicates how many triples are in the vector.
Unlike the previous interfaces, the listio
interface does
not require that the requests exhibit any sort of regularity. Although
this interface does not reduce the amount of work performed by the
application (it must still calculate every offset explicitly), it does
allow Galley to perform the same optimizations as other batched requests.
gfs_handle
as the
first parameter of each call. For example, a gfs_read(fork_id, buf,
offset, size)
becomes gfs_nb_read(handle, fork_id, buf,
offset, size)
. A non-blocking call cannot return the amount of data
transferred, since that information is not available at the time the call is
made. So, non-blocking calls simply return an error code if one or more
parameters to the call are invalid.
There are a number of extra calls required to support non-blocking I/O.
gfs_handle gfs_new_handle()
int gfs_test(gfs_handle handle)
int gfs_wait(gfs_handle h)
wait()
for a non-blocking operation to complete before the
handle may be reused.
int gfs_free_handle(gfs_handle h)