From Linux NFS

Jump to: navigation, search

Whenever a client wishes to zero the blocks backing a particular region in the file, it calls the WRITE_PLUS operation with the current filehandle set to the filehandle of the file in question, and the equivalent of start offset and length in bytes of the region set in wpa_hole.di_offset and wpa_hole.di_length respectively. If the wpa_hole.di_allocated is set to TRUE, then the blocks will be zeroed and if it is set to FALSE, then they will be deallocated. All further reads to this region MUST return zeros until overwritten. The filehandle specified must be that of a regular file.


Data type reference

typedef uint32_t count4
typedef uint64_t length4
typedef uint64_t offset4

enum stable_how4 {
        UNSTABLE4       = 0,
        DATA_SYNC4      = 1,
        FILE_SYNC4      = 2

enum data_content4 {
        NFS4_CONTENT_DATA = 0,
        NFS4_CONTENT_HOLE = 2,

struct data_info4 {
        offset4         di_offset;
        length4         di_length;
        bool            di_allocated;


union write_plus_arg4 switch (data_content4 wpa_content) {
        data_info4      wpa_hole;

struct WRITE_PLUS4args {
        /* CURRENT_FH: file */
        stateid4        wp_stateid;
        stable_how4     wp_stable;
        write_plus_arg4 wp_data<>;


struct write_response4 {
        stateid4        wr_callback_id<1>;
        count4          wr_count;
        stable_how4     wr_committed;
        verifier4       wr_writeverf;

union WRITE_PLUS4res switch (nfsstat4 wp_status) {
case NFS4_OK:
        write_response4         wp_resok4;

Sync Client

  • Fill in the fallocate field in the struct file_operations for NFS v4
    • Return -EOPNOTSUPP for NFS < 4.2
  • Punch holes one at a time through the system call
    • The spec allows for many, but the system call only allows for one / call.
    • Simpler design, whoo!
  • Create a nfs42_proc_fallocate()
    • Check the flags provided by the VFS
    • If zero, set di_allocated to true
    • If FALLOC_FL_PUNCH_HOLE is set, set di_allocated to false
  • Would setting wp_stable to FILE_SYNC4 disable the callback from the server?
  • Send the compound:

Sync Server

  • Define operation to use the same server flags as WRITE
  • Call do_fallocate() once the request arrives
    • Need to return an error if the underlying filesystem doesn't support hole punching (check for -EOPNOTSUPP)
  • Check the di_allocated flag
    • If true, call do_fallocate() with mode = 0
    • If false, call do_fallocate() with mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE
  • Decode list, process everything in order.
  • Return NFS4ERR_UNION_NOTSUPP for data_content4 != NFS4_CONTENT_HOLE

Async Client

  • Similar to COPY
    • Check for an offload stateid, add to offload list
  • Use wait_for_completion() before returning

Async Server

  • Similar to COPY
  • Run the entire operation later through a work queue
  • Send CB_OFFLOAD to the client when complete
  • Don't submit this patch since OFFLOAD_STATUS and OFFLOAD_ABORT aren't implemented (yet?).


  • XFS test #285 should run test 9 and 10 once fallocate support is added
  • /usr/bin/fallocate can be used to punch holes and preallocate space in files
Personal tools