[an error occurred while processing this directive]

NFS Client Library

The NFS client library provides a simple interface for accessing files on an NFS server. The majority of these functions provide an asynchronous interface. Instead of blocking until the NFS transaction is complete you instead pass a function pointer, which will be called when the operation is complete. The first argument of these function is token which you also specify on the call. More information on NFS can be found in the NFS RFC.

This documents the basic functionality and functions provided. You will probably want to look at the header files rpc.h and nfs.h which defines the structures used.

If you are running this code at home you will need to set up an NFS server on your machine. This requires running portmapper, mountd and nfsd. The NFS code also relies on the UDP time protocol to generate a unique transaction ID on boot.

nfs_init

int nfs_init(struct ip_addr server);

This function should be called once at startup, passing the adderss of your NFS server.

nfs_timeout

void nfs_timeout(void);

Since NFS runs over UDP, an unreliable protocol, it is possible that packets may be dropped. To allow NFS to retransmit packets that might have been dropped you must arrange for nfs_timeout to be called every 100ms. This could be achieved by either extending your clock driver, or using L4_Sleep.

mnt_get_export_list

int mnt_get_export_list(void)

This is simply a debugging function which will print out a list of mount points available on the server.

mnt_mount

unsigned int mnt_mount(char* dir, struct cookie *pfh);

This will mount a filesystem and return a cookie to it in pfh. In your assignment you will be mounting the /tftpboot filesystem. The returned cookie will be used on subsequent NFS transactions.

nfs_lookup

int nfs_lookup(struct cookie *directory, char *name, void (*func) (uintptr_t token, int status, struct cookie * fh, fattr_t *attr), uintptr_t token);

Before you are able to complete any operation on a file you must obtain a handle to it. This is what the nfs_lookup function provides. This function will find a file named name in the specified directory. The root directory is of course the handle returned from mnt_mount. When the transaction has completed it will call the func you pass. This will be called with your token, and a status code. If the call is successful status will be zero, and you will also be passed a handle to the file, and its current attributes. NB: The pointers *fh and *attr are only valid during the call, if you need to keep them you must copy them into some other memory.

nfs_getattr

int nfs_getattr(struct cookie *fh, void (*func) (uintptr_t, int, fattr_t *), uintptr_t token);

This function is the equivilant of the UNIX stat function. It will find the current attributes on a given file handle (*fh). The attributes are passed back through the callback func. You may be able to avoid using this call since nfs_lookup, nfs_read and nfs_write also return the current file attributes.

nfs_create

int nfs_create(struct cookie *fh, char *name, sattr_t *sat, void (*func) (uintptr_t, int, struct cookie *, fattr_t *), uintptr_t token);

This function is used to create a new file named name with the attributes sat. On completion func is called with a handle to the new file and its attributes.

nfs_read

int nfs_read(struct cookie *fh, int pos, int count, void (*func) (uintptr_t, int, fattr_t *attr, int bytes_read, char *data), uintptr_t token);

nfs_read will read count bytes of data, starting at a given pos from the provided file handle. On completion your func is called with the current file attributes, the number of bytes_read and a pointer to the data. The data is only available for the duration of the system call, after which it is reused for other network packets. You will most likely need to copy this data into a user's data buffer.

nfs_write

int nfs_write(struct cookie *fh, int offset, int count, void *data, void (*func) (uintptr_t, int, fattr_t *), uintptr_t token);

nfs_write will write count bytes of data at a specific offset. When the transaction is completed your func will be called with the status and the current file attributes.

nfs_readdir

int nfs_readdir(struct cookie *pfh, int cookie, int read_size, void (*func) (uintptr_t token, int status, int num_entries, struct nfs_filename *filenames, int next_cookie), uintptr_t token);

struct nfs_filename {
  int size;
  const char *filename;
};

This function reads the contents, that is the filenames, from a directory pfh. When complete this transaction will call func with a pointer an array of filenames. This array is num_entries long. Each entry in the array contains a size and a pointer to the filename. Note that filename is NOT a null terminated string. Its length is specified by the size. As with other NFS callbacks the data here is only valid for the duration of the call and must be copied elsewhere if required.

The next_cookie argument indicates whether there are more directory entries available. If next_cookie is zero then all directory entries have been read. If it is greater than zero then there are more entries available and this value should be passed as the cookie argument to another nfs_readdir request. Note that zero should be passed as the initial cookie value.

The read_size parameter specifies the number of bytes of data to read on each request.


Last modified: 27 Jul 2004. [an error occurred while processing this directive]