Subject: [nfsv4] NFSv4.2 issues list

From: Tom Haynes <[email-masked]>
Date: Thu, 24 Apr 2014 12:00:18 -0700

Here is the issues list I promised. It does not include several of the items that Christoph has
highlighted.

I’ve also added this to the repo, so Christoph, feel free to add them if needed.

1) space_reserved flag - what does it mean now that reservations
   are byte ranges?

   See the recent chatter on the WG.

2) Do we want to maintain punch hole versus write zeros OR do we
   want to leave that to the server?

   We added this, but is it realistic?

   Also, is it a hint or mandatory?

   Either way, I want us to revisit it.

3) Need to document that we honor all NFSv4.1 Layout Types, stateids
   have not changed, etc.

   See the recent WG ML chatter over all of this.

4) Labeled NFS - FATTR4_CHANGE_SEC_LABEL - how big does it need to
   be?  Is seLinux going to support it?

   The Labeled NFS prototype in use does not currently support
   change_sec_label.

   In the past, we argued about how big it needed to be - we need
   to close down on this.

5) Consecutive byte copy flag and status updates for SSC

   Source modifies the cnr_copy_source to inform both the client
   and the destination as to whether each copy engine is going to
   copy bytes in consecutive order or not.

   Destination will need to modify the return from COPY to tell the
   client whether the copy engine it selected is doing consecutive
   order or not.

   Actually, it could return the item in the ca_copy_source that
   it selected.  This would allow the client to be aware of the
   selected copy engine as well.

6) Client wants to only do synchronous SSC or ALLOCATE or WRITE_HOLE

   The client wants to inform the destination in a SSC that it only
   wants to do the COPY iff the operation is going to synchronous.

   The client wants to inform the server that it only wants to
   do the ALLOCATE iff the operation is going to synchronous.

   The client wants to inform the server that it only wants to
   do the WRITE_HOLE iff the operation is going to synchronous.

   Some issues here are that for the SSC, the destination might
   have done some I/O before it decides that the COPY is going to
   be asynchronous???

---

From: Christoph Hellwig <[email-masked]>
Date: Thu, 24 Apr 2014 22:16:15 +0200

>    See the recent chatter on the WG.

Here is my proposal to address this issue:

The terminology of allocated vs unallocated blocks in READ_PLUS and SEEK
is confusing as there it doesn't have a whole lot of meaning for a remote
filesystem, especially if it sits on top of complex COW or snapshotting
filesystem.  Even if a block is allocated writes into it might return NOSPC,
and even if it's not allocated it might have space reserved making writes
into it semaingless.

So intead of returning the allocated/unallocated information return the
reservation status of a hole or data block range, as that actually is
meaninful to the client.  For a traditional, simple Unix filesystem the
two are equivalent, but the the strictly defined meaning of reserved
vs unreserved actually does matter for more complex server implementations.

Because we want the answert to be exact but servers might not always be able
to get the exact information add a third possible unknown state to the
reservation status.  This should also help with the earlier discussions if
the allocation status should be exact or a hint.

diff --git a/Makefile b/Makefile
index 9958a28..bb026f9 100755
--- a/Makefile
+++ b/Makefile
@@ -166,6 +166,7 @@ SPITGEN =	dotx.d/type_nfstime4.x \
 		dotx.d/type_netloc_type4.x \
 		dotx.d/type_chattr_type.x \
 		dotx.d/type_label_format.x \
+		dotx.d/type_space_info4.x \
 		dotx.d/copy_confirm_auth.x \
 		dotx.d/copy_from_auth.x \
 		dotx.d/copy_to_auth.x \
@@ -244,6 +245,7 @@ SPITGENXML =	autogen/type_nfstime4.xml \
 		autogen/type_netloc_type4.xml \
 		autogen/type_chattr_type.xml \
 		autogen/type_label_format.xml \
+		autogen/type_space_info4.xml \
 		autogen/copy_confirm_auth.xml \
 		autogen/copy_from_auth.xml \
 		autogen/copy_to_auth.xml \
diff --git a/dotx.d/Makefile b/dotx.d/Makefile
index baee8e9..00aba28 100755
--- a/dotx.d/Makefile
+++ b/dotx.d/Makefile
@@ -228,6 +228,7 @@ SPITGEN =	basic_types.x \
 		type_COMPOUND4args.x \
 		type_COMPOUND4res.x \
 		type_netloc_type4.x \
+		type_space_info4.x \
 		copy_confirm_auth.x \
 		copy_from_auth.x \
 		copy_to_auth.x \
diff --git a/dotx.d/head.x b/dotx.d/head.x
index 821232e..c4acda8 100644
--- a/dotx.d/head.x
+++ b/dotx.d/head.x
@@ -404,7 +404,7 @@ include(copy_confirm_auth.x)
 include(app_data_block4.x)
 
 include(data4.x)
-
+include(type_space_info4.x)
 include(data_info4.x)
 
 include(data_content4.x)
@@ -498,7 +498,6 @@ typedef change_policy4	fattr4_change_policy;
 /*
  * attributes new to NFSv4.2
  */
-typedef bool		fattr_space_reserved;
 typedef uint64_t	fattr_space_freed;
 typedef change_attr_type4
 		fattr4_change_attr_type;
diff --git a/dotx.d/spit_types.sh b/dotx.d/spit_types.sh
index 7ef6772..cd21667 100755
--- a/dotx.d/spit_types.sh
+++ b/dotx.d/spit_types.sh
@@ -1390,13 +1390,25 @@ EOF
 
 	;;
 
+	type_space_info4.x )
+
+cat << EOF > $i
+enum space_info4 {
+	SPACE_RESERVED4		= 0,
+	SPACE_UNRESERVED4	= 1,
+	SPACE_UNKNOWN4		= 2,
+};
+EOF
+	;;
+
+
 	data_info4.x )
 
 cat << EOF > $i
 struct data_info4 {
 	offset4		di_offset;
 	length4		di_length;
-	bool		di_allocated;
+	space_info4	di_reserved;
 };
 EOF
 
diff --git a/nfsv42_back_references.xml b/nfsv42_back_references.xml
index bb10581..6c5d625 100644
--- a/nfsv42_back_references.xml
+++ b/nfsv42_back_references.xml
@@ -22,6 +22,25 @@
 	      target="ftp://ftp.isi.edu/in-notes/rfc5661.txt"/>
     </reference>
 
+    <reference anchor='RFC5663'>
+      <front>
+	<title>Parallel NFS (pNFS) Block/Volume Layout</title>
+	<author initials="D." surname="Black" fullname="D. Black">
+	  <organization>EMC Corporation</organization>
+	</author>
+	<author initials="S." surname="Fridella" fullname="S. Fridella">
+	  <organization>Nasuni Inc</organization>
+	</author>
+	<author initials="J." surname="Glasgow" fullname="J. Glasgow">
+	  <organization>Google</organization>
+	</author>
+	<date year="2010" month="January"/>
+      </front>
+      <seriesInfo name="RFC" value="5663"/>
+      <format type="TXT"
+	      target="ftp://ftp.isi.edu/in-notes/rfc5663.txt"/>
+    </reference>
+
     <reference anchor='RFC5664'>
       <front>
 	<title>Object-Based Parallel NFS (pNFS) Operations</title>
diff --git a/nfsv42_middle_fileattributes.xml b/nfsv42_middle_fileattributes.xml
index 29e74cb..b5a6b33 100644
--- a/nfsv42_middle_fileattributes.xml
+++ b/nfsv42_middle_fileattributes.xml
@@ -56,7 +56,6 @@
       <c>change_attr_type</c> <c>79</c> <c>change_attr_type4</c>  <c>R  </c> <c><xref target="ss:fattr:chattr" /></c>
       <c>sec_label</c>        <c>80</c> <c>sec_label4</c>         <c>R W</c> <c><xref target="ss:fattr:sec" /></c>
       <c>change_sec_label</c> <c>81</c> <c>change_sec_label4</c>  <c>R  </c> <c><xref target="ss:fattr:chsec" /></c>
-      <c>space_reserved</c>   <c>77</c> <c>boolean</c>            <c>R W</c> <c><xref target="ss:fattr:sr" /></c>
       <c>space_freed</c>      <c>78</c> <c>length4</c>            <c>R  </c> <c><xref target="ss:fattr:sf" /></c>
     </texttable>
   </section>
@@ -213,14 +212,6 @@ typedef uint32_t  policy4;
       </t>
     </section>
 
-    <section toc='exclude' anchor="ss:fattr:sr" title="Attribute 77: space_reserved">
-      <t>
-        The space_reserved attribute is a read-only attribute per file.
-        If it is true if there are any space reservations on the file, or false
-        otherwise.
-      </t>
-    </section>
-
     <section toc='exclude' anchor="ss:fattr:sf" title="Attribute 78: space_freed">
       <t>
         space_freed gives the number of bytes freed if the file is deleted.
diff --git a/nfsv42_middle_introduction.xml b/nfsv42_middle_introduction.xml
index dd02c3d..106bc99 100644
--- a/nfsv42_middle_introduction.xml
+++ b/nfsv42_middle_introduction.xml
@@ -99,8 +99,8 @@
 
     <section title="Sparse Files">
       <t>
-        Sparse files are ones which have unallocated data blocks
-        as holes in the file. Such holes are typically transferred
+        Sparse files are ones which have unallocated or uninitialized data
+        blocks as holes in the file. Such holes are typically transferred
         as 0s during I/O. READ_PLUS (see <xref target='op:read_plus' />)
         allows a server to send back to the client metadata describing
         the hole and WRITE_HOLE (see <xref target='op:write_hole' />)
diff --git a/nfsv42_middle_op_allocate.xml b/nfsv42_middle_op_allocate.xml
index 93c141e..58d41fe 100644
--- a/nfsv42_middle_op_allocate.xml
+++ b/nfsv42_middle_op_allocate.xml
@@ -43,8 +43,7 @@
     <t>
       The ALLOCATE operation will result in the space_used attribute and
       space_freed attributes being increased by the number of bytes reserved
-      unless they were previously reserved or written and not shared. And
-      it will set the space_reserved attribute to be true.
+      unless they were previously reserved or written and not shared.
     </t>
   </section>
 </section>
diff --git a/nfsv42_middle_op_read_plus.xml b/nfsv42_middle_op_read_plus.xml
index ef8ebda..e9381ce 100644
--- a/nfsv42_middle_op_read_plus.xml
+++ b/nfsv42_middle_op_read_plus.xml
@@ -7,6 +7,7 @@
   </section>
 
   <section toc='exclude' title="RESULT">
+    <?rfc include='autogen/type_space_info4.xml'?>
     <?rfc include='autogen/data_info4.xml'?>
     <?rfc include='autogen/data4.xml'?>
     <?rfc include='autogen/read_plus_res.xml'?>
@@ -35,7 +36,7 @@
       NFSv4.2, the allowed values are data and hole. A server MUST
       support both the data type and the hole if it uses READ_PLUS.
       If it does not want to support a hole, it MUST use READ. The
-      hole must be returned in its entirety - clients must be
+      hole SHOULD be returned in its entirety - clients must be
       prepared to get more information than they requested. Both
       the start and the end of the hole may exceed what was requested.
       The array contents MUST be contiguous in the file.
@@ -43,14 +44,12 @@
 
     <t>
       If the data to be returned is comprised entirely of zeros,
-      then the server may elect to return that data as a hole. The
-      server differentiates this to the client by setting di_allocated
-      to TRUE in this case. Note that in such a scenario, the server
-      is not required to determine the full extent of the "hole" -
-      it does not need to determine where the zeros start and end.
-      If the server elects to return the hole as data, then it can
-      set the d_allocted to FALSE in the rpc_data to indicate it
-      is a hole.
+      then the server SHOULD return that data as a hole. The di_reserved
+      field is used to tell the client if a hole is unreservers, that is
+      writes to it MAY return NFS4ERR_NOSPC, or it is reserved in which
+      cases writes into the hole MUST NOT return ENOSPC.  If the server
+      does not know the reservations status it may set the di_reserved
+      field to SPACE_UNKNOWN4.
     </t>
 
     <t>
diff --git a/nfsv42_middle_op_seek.xml b/nfsv42_middle_op_seek.xml
index 6245182..ebdb799 100644
--- a/nfsv42_middle_op_seek.xml
+++ b/nfsv42_middle_op_seek.xml
@@ -14,6 +14,7 @@
   </section>
 
   <section toc='exclude' title="RESULT">
+    <?rfc include='autogen/type_space_info4.xml'?>
     <?rfc include='autogen/data_info4.xml'?>
     <?rfc include='autogen/seek_res.xml'?>
   </section>
diff --git a/nfsv42_middle_op_write_hole.xml b/nfsv42_middle_op_write_hole.xml
index 52e3b57..df69c3f 100644
--- a/nfsv42_middle_op_write_hole.xml
+++ b/nfsv42_middle_op_write_hole.xml
@@ -4,6 +4,7 @@
 <section anchor='op:write_hole' title='Operation 64: WRITE_HOLE'>
   <section toc='exclude' title="ARGUMENT">
     <?rfc include='autogen/stable_how4.xml'?>
+    <?rfc include='autogen/type_space_info4.xml'?>
     <?rfc include='autogen/data_info4.xml'?>
     <?rfc include='autogen/write_hole_args.xml'?>
   </section>
@@ -20,11 +21,13 @@
       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 wh_hole.di_offset
-      and wh_hole.di_length respectively.  If the wh_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.
+      and wh_hole.di_length respectively.  If wh_hole.di_reserved
+      is set to SPACE_RESERVED4, then the blocks will be zeroed and
+      if it is set to SPACE_UNRESERVED4, then they will be deallocated.
+      A server must reject a WRITE_HOLE call with wh_hole.di_reserved
+      set to SPACE_UNKNOWN4 with NFS4ERR_INVAL. All further reads to
+      this region MUST return zeros until overwritten.  The filehandle
+      specified must be that of a regular file.
     </t>
 
     <t>
diff --git a/nfsv42_middle_space.xml b/nfsv42_middle_space.xml
index 837cab1..b167044 100644
--- a/nfsv42_middle_space.xml
+++ b/nfsv42_middle_space.xml
@@ -88,11 +88,6 @@
 
     <t>
       <list style="hanging">
-        <t hangText="space_reserved">
-          This attribute specifies that there are some space reservations
-          on a file.
-        </t>
-
         <t hangText="space_freed">
           This attribute specifies the space freed when a file is
           deleted, taking block sharing into consideration.
@@ -102,6 +97,11 @@
           This operation zeros and/or deallocates the blocks
           backing a region of the file.
         </t>
+        
+	<t hangText="READ_PLUS or SEEK">
+          These operations can return the reservation status of blocks
+	  backing a region of the file.
+        </t>
       </list>
     </t>
 
@@ -146,4 +146,18 @@
       over-reported.  However, over-reporting is better than under-reporting.
     </t>
   </section>
+  <section anchor='ss:space:info' title='Space Reservation Information'>
+  <?rfc include='autogen/type_space_info4.xml'?>
+      <t>
+        The space_info4 type is used to report the reservation space
+	in the READ_PLUS (see <xref target='op:read_plus' />) and SEEK
+	(see <xref target='op:seek' /> operations to report the
+	reservation state of a data block or hole.  A data block or
+	hole may either be reserved, that means a future write MUST not
+	return NFS4ERR_NOSPC, or it might be unreserved in which case
+	a future write may return NFS4ERR_NOSPC.  Servers may not know
+	the allocation state, in which case it might return unknown
+	in the space_info fields in the READ_PLUS and SEEK return values.
+      </t>
+  </section>
 </section>
diff --git a/nfsv42_middle_sparse.xml b/nfsv42_middle_sparse.xml
index 3b56d5e..f98f550 100644
--- a/nfsv42_middle_sparse.xml
+++ b/nfsv42_middle_sparse.xml
@@ -16,6 +16,15 @@
     </t>
 
     <t>
+      In addition many modern filesystems support the concept of 'unwritten'
+      or 'uninitialized' blocks, which have uninitialized space allocated to
+      them on disk, but will return 0s until data is written to them.  Such
+      functionality is already present in the data model of the pNFS
+      Block/Volume Layout (see <xref target="RFC5663" />).  Uninitialized
+      blocks can thought as holes inside a space reservation window.
+    </t>
+
+    <t>
       If an application reads a hole in a sparse file, the file system must
       return all zeros to the application.   For local data access there
       is little penalty, but with NFS these zeroes must be transferred back
@@ -71,8 +80,8 @@
 
         <t hangText="Hole:">
           A byte range within a Sparse file that contains regions of
-          all zeroes.  For block-based file systems, this could also be an
-          unallocated region of the file.
+          all zeroes.  A hole might or might not have space allocated
+          or reserved to it.
         </t>
 
         <t hangText='Hole Threshold:'>
@@ -86,27 +95,24 @@
   </section>
 
   <section anchor="ss:sparse:new_ops" title="New Operations">
-    <t>
-      READ_PLUS and WRITE_HOLE are new variants of the NFSv4.1 READ
-      and WRITE operations <xref target="RFC5661" />.  Besides being
-      able to support all of the data semantics of those operations,
-      they can also be used by the client and server to efficiently
-      transfer holes.  Note that as the client has no a priori
-      knowledge of whether a hole is present or not, if it supports
-      these operations and so does the server, then it should always
-      use the READ_PLUS operation in preference to the READ operation..
-    </t>
-
     <section anchor="ss:sparse:read_plus" title="READ_PLUS">
       <t>
-       For holes, READ_PLUS extends the response to avoid returning
-       data for portions of the file which are initialized and
-       contain no backing store.  Additionally it will do so if
-       the result would appear to be a hole. I.e., if the result
-       was a data block composed entirely of zeros, then it is
-       easier to return a hole. Returning data blocks of uninitialized
-       data wastes computational and network resources, thus
-       reducing performance.
+       READ_PLUS is a new variant of the NFSv4.1 READ operation
+       <xref target="RFC5661" />.  Besides being able to support all of
+       the data semantics of the READ operation, it can also be used by
+       the client and server to efficiently transfer holes.  Note that as
+       the client has no a priori knowledge of whether a hole is present
+       or not, if the client supports READ_PLUS and so does the server,
+       then it should always use the READ_PLUS operation in preference
+       to the READ operation.
+      </t>
+
+      <t>
+       READ_PLUS extends the response with a new arm representing holes to
+       avoid returning data for portions of the file which are initialized
+       to zero and may or may not contain a backing store. Returning data
+       blocks of uninitialized data wastes computational and network
+       resources, thus reducing performance.
       </t>
 
       <t>

---

From: Christoph Hellwig <[email-masked]>
Date: Thu, 24 Apr 2014 22:49:06 +0200

>    Either way, I want us to revisit it.

Hole punching vs zeroing is an important difference in semantics, and it
becomes even more important with the strictly defined space reservation
semantics.

I've attached a patch (ontop of my previous patch in this thread) which
tries to address these issues by splitting them up into different operations.

Zeroing a file of parts of it can be done with the WRITE_SAME operation
in the current ADB form - an ADB without pattern or block number will
simply zero the file, so that part of WRITE_HOLE is properly replaces by
WRITE_SAME already, I've just added an example section for it.

The hole punch now becomes a simple metadata operation mirroring ALLOCATE,
thus termed 'DEALLOCATE', and it now actually drops the reservation, which
is the only sensible semantic for it to implement the sort of hole punches
clients expect.  It also is purely synchronous as it just is a generalization
of SETATTR to a smaller size, which servers must handle synchronously already.

diff --git a/Makefile b/Makefile
index bb026f9..ff35b1a 100755
--- a/Makefile
+++ b/Makefile
@@ -346,8 +346,8 @@ AUTOGEN =	\
 		autogen/getdevicelist_res.xml \
 		autogen/getfh_res.xml \
 		autogen/illegal_res.xml \
-		autogen/write_hole_args.xml \
-		autogen/write_hole_res.xml \
+		autogen/deallocate_args.xml \
+		autogen/deallocate_res.xml \
 		autogen/write_same_args.xml \
 		autogen/write_same_res.xml \
 		autogen/io_advise_args.xml \
@@ -451,7 +451,7 @@ IDXMLSRC_BASE = \
 	${DOC_PREFIX}_middle_op_layoutreturn.xml \
 	${DOC_PREFIX}_middle_op_read_plus.xml \
 	${DOC_PREFIX}_middle_op_seek.xml \
-	${DOC_PREFIX}_middle_op_write_hole.xml \
+	${DOC_PREFIX}_middle_op_deallocate.xml \
 	${DOC_PREFIX}_middle_op_write_same.xml \
 	${DOC_PREFIX}_middle_op_zzz.xml \
 	${DOC_PREFIX}_middle_op_cb_aaa.xml \
diff --git a/dotx.d/Makefile b/dotx.d/Makefile
index 00aba28..7e231e1 100755
--- a/dotx.d/Makefile
+++ b/dotx.d/Makefile
@@ -118,8 +118,8 @@ FORE_OPS_AS_IS2 = \
                 offload_revoke_res.x \
                 offload_status_args.x \
                 offload_status_res.x \
-		write_hole_args.x \
-		write_hole_res.x \
+		deallocate_args.x \
+		deallocate_res.x \
 		io_advise_args.x \
 		io_advise_res.x \
 		read_plus_args.x \
diff --git a/dotx.d/deallocate_args.x b/dotx.d/deallocate_args.x
new file mode 100644
index 0000000..03f498e
--- /dev/null
+++ b/dotx.d/deallocate_args.x
@@ -0,0 +1,8 @@
+
+struct DEALLOCATE4args {
+        /* CURRENT_FH: file */
+        stateid4	da_stateid;
+        offset4         da_offset;
+        length4         da_length;
+};
+
diff --git a/dotx.d/deallocate_res.x b/dotx.d/deallocate_res.x
new file mode 100644
index 0000000..412e115
--- /dev/null
+++ b/dotx.d/deallocate_res.x
@@ -0,0 +1,3 @@
+struct DEALLOCATE4res {
+	nfsstat4		dr_status;
+};
diff --git a/dotx.d/spit_types.sh b/dotx.d/spit_types.sh
index cd21667..19d75d7 100755
--- a/dotx.d/spit_types.sh
+++ b/dotx.d/spit_types.sh
@@ -999,12 +999,12 @@ enum nfs_opnum4 {
  OP_COPY_NOTIFY		= 61,
  OP_OFFLOAD_REVOKE	= 62,
  OP_OFFLOAD_STATUS	= 63,
- OP_WRITE_HOLE		= 64,
  OP_READ_PLUS		= 65,
  OP_SEEK		= 66,
  OP_IO_ADVISE		= 67,
  OP_WRITE_SAME		= 68,
  OP_ALLOCATE		= 69,
+ OP_DEALLOCATE		= 70,
  OP_ILLEGAL		= 10044
 };
 EOF
@@ -1121,12 +1121,12 @@ union nfs_argop4 switch (nfs_opnum4 argop) {
  case OP_COPY:		COPY4args opcopy;
  case OP_OFFLOAD_ABORT:	OFFLOAD_ABORT4args opoffload_abort;
  case OP_OFFLOAD_STATUS: OFFLOAD_STATUS4args opoffload_status;
- case OP_WRITE_HOLE:	WRITE_HOLE4args opwrite_hole;
  case OP_READ_PLUS:	READ_PLUS4args opread_plus;
  case OP_SEEK:		SEEK4args opseek;
  case OP_IO_ADVISE:	IO_ADVISE4args opio_advise;
  case OP_WRITE_SAME:	WRITE_SAME4args opwrite_same;
  case OP_ALLOCATE:	ALLOCATE4args opallocate;
+ case OP_DEALLOCATE:	DEALLOCATE4args opdeallocate;
 
  /* Operations not new to NFSv4.1 */
  case OP_ILLEGAL:	void;
@@ -1253,12 +1253,12 @@ union nfs_resop4 switch (nfs_opnum4 resop) {
  case OP_COPY:		COPY4res opcopy;
  case OP_OFFLOAD_ABORT:	OFFLOAD_ABORT4res opoffload_abort;
  case OP_OFFLOAD_STATUS: OFFLOAD_STATUS4res opoffload_status;
- case OP_WRITE_HOLE:	WRITE_HOLE4res opwrite_hole;
  case OP_READ_PLUS:	READ_PLUS4res opread_plus;
  case OP_SEEK:		SEEK4res opseek;
  case OP_IO_ADVISE:	IO_ADVISE4res opio_advise;
  case OP_WRITE_SAME:	WRITE_SAME4res opwrite_same;
- case OP_ALLOCATE:	ALLOCATE4res opallocate_plus;
+ case OP_ALLOCATE:	ALLOCATE4res opallocate;
+ case OP_DEALLOCATE:	DEALLOCATE4res opdeallocate;
 
  /* Operations not new to NFSv4.1 */
  case OP_ILLEGAL:	ILLEGAL4res opillegal;
diff --git a/dotx.d/write_hole_args.x b/dotx.d/write_hole_args.x
deleted file mode 100644
index bcf67bd..0000000
--- a/dotx.d/write_hole_args.x
+++ /dev/null
@@ -1,8 +0,0 @@
-
-struct WRITE_HOLE4args {
-	/* CURRENT_FH: file */
-	stateid4	wh_stateid;
-	stable_how4	wh_stable;
-	data_info4	wh_hole;
-};
-
diff --git a/dotx.d/write_hole_res.x b/dotx.d/write_hole_res.x
deleted file mode 100644
index b67e9e5..0000000
--- a/dotx.d/write_hole_res.x
+++ /dev/null
@@ -1,8 +0,0 @@
-
-union WRITE_HOLE4res switch (nfsstat4 wh_status) {
-case NFS4_OK:
-	write_response4		wh_resok4;
-default:
-	void;
-};
-
diff --git a/nfsv42_middle_application.xml b/nfsv42_middle_application.xml
index 89d34df..624d120 100644
--- a/nfsv42_middle_application.xml
+++ b/nfsv42_middle_application.xml
@@ -291,4 +291,17 @@
       </artwork>
     </figure>
   </section>
+  <section anchor='ss:adb:zero' title='An Example of Zeroing Space'>
+    <t>
+      A simpler use case for WRITE_SAME are applications that want to
+      efficiently zero out a file, but do not want to modify space
+      reservations.  This can easily be archived by a call to WRITE_SAME
+      without a ADB block numbers and pattern, e.g.:
+    </t>
+    <figure>
+      <artwork>
+   WRITE_SAME {0, 1k, 10000, 0, 0, 0, 0}
+      </artwork>
+    </figure>
+  </section>
 </section>
diff --git a/nfsv42_middle_errors.xml b/nfsv42_middle_errors.xml
index 9e07264..3da98c5 100644
--- a/nfsv42_middle_errors.xml
+++ b/nfsv42_middle_errors.xml
@@ -1581,6 +1581,40 @@
         NFS4ERR_WRONG_CRED
       </c>
 
+      <c>DEALLOCATE</c>
+      <c>
+        NFS4ERR_ACCESS,
+        NFS4ERR_ADMIN_REVOKED,
+        NFS4ERR_BADXDR,
+        NFS4ERR_BAD_STATEID,
+        NFS4ERR_DEADSESSION,
+        NFS4ERR_DELAY,
+        NFS4ERR_DELEG_REVOKED,
+        NFS4ERR_EXPIRED,
+        NFS4ERR_FBIG,
+        NFS4ERR_FHEXPIRED,
+        NFS4ERR_GRACE,
+        NFS4ERR_INVAL,
+        NFS4ERR_IO,
+        NFS4ERR_ISDIR,
+        NFS4ERR_MOVED,
+        NFS4ERR_NOFILEHANDLE,
+        NFS4ERR_NOTSUPP,
+        NFS4ERR_OLD_STATEID,
+        NFS4ERR_OPENMODE,
+        NFS4ERR_OP_NOT_IN_SESSION,
+        NFS4ERR_REP_TOO_BIG,
+        NFS4ERR_REP_TOO_BIG_TO_CACHE,
+        NFS4ERR_REQ_TOO_BIG,
+        NFS4ERR_RETRY_UNCACHED_REP,
+        NFS4ERR_ROFS,
+        NFS4ERR_SERVERFAULT,
+        NFS4ERR_STALE,
+        NFS4ERR_SYMLINK,
+        NFS4ERR_TOO_MANY_OPS,
+        NFS4ERR_WRONG_TYPE
+      </c>
+
       <c>DELEGPURGE</c>
       <c>
         NFS4ERR_BADXDR,
@@ -2843,45 +2877,6 @@
         NFS4ERR_WRONG_TYPE
       </c>
 
-      <c>WRITE_HOLE</c>
-      <c>
-        NFS4ERR_ACCESS,
-        NFS4ERR_ADMIN_REVOKED,
-        NFS4ERR_BADXDR,
-        NFS4ERR_BAD_STATEID,
-        NFS4ERR_DEADSESSION,
-        NFS4ERR_DELAY,
-        NFS4ERR_DELEG_REVOKED,
-        NFS4ERR_DQUOT,
-        NFS4ERR_EXPIRED,
-        NFS4ERR_FBIG,
-        NFS4ERR_FHEXPIRED,
-        NFS4ERR_GRACE,
-        NFS4ERR_INVAL,
-        NFS4ERR_IO,
-        NFS4ERR_ISDIR,
-        NFS4ERR_LOCKED,
-        NFS4ERR_MOVED,
-        NFS4ERR_NOFILEHANDLE,
-        NFS4ERR_NOSPC,
-        NFS4ERR_NOTSUPP,
-        NFS4ERR_OLD_STATEID,
-        NFS4ERR_OPENMODE,
-        NFS4ERR_OP_NOT_IN_SESSION,
-        NFS4ERR_PNFS_IO_HOLE,
-        NFS4ERR_PNFS_NO_LAYOUT,
-        NFS4ERR_REP_TOO_BIG,
-        NFS4ERR_REP_TOO_BIG_TO_CACHE,
-        NFS4ERR_REQ_TOO_BIG,
-        NFS4ERR_RETRY_UNCACHED_REP,
-        NFS4ERR_ROFS,
-        NFS4ERR_SERVERFAULT,
-        NFS4ERR_STALE,
-        NFS4ERR_SYMLINK,
-        NFS4ERR_TOO_MANY_OPS,
-        NFS4ERR_WRONG_TYPE
-      </c>
-
       <c>WRITE_SAME</c>
       <c>
         NFS4ERR_ACCESS,
diff --git a/nfsv42_middle_introduction.xml b/nfsv42_middle_introduction.xml
index 106bc99..ad28802 100644
--- a/nfsv42_middle_introduction.xml
+++ b/nfsv42_middle_introduction.xml
@@ -103,7 +103,7 @@
         blocks as holes in the file. Such holes are typically transferred
         as 0s during I/O. READ_PLUS (see <xref target='op:read_plus' />)
         allows a server to send back to the client metadata describing
-        the hole and WRITE_HOLE (see <xref target='op:write_hole' />)
+        the hole and DEALLOCATE (see <xref target='op:deallocate' />)
         allows the client to punch holes into a file. In addition,
         SEEK (see <xref target='op:seek' />) is provided to scan
         for the next hole or data from a given location.
@@ -116,7 +116,9 @@
         that there will always be enough data blocks available for the
         file during future writes. ALLOCATE
 	(see <xref target='op:allocate' />) allows a client to request
-        a guarantee that space will be available.
+        a guarantee that space will be available. And DEALLOCATE
+        (see <xref target='op:deallocate' />) allows the client
+	to punch a hole into a file, thus releasing a space reservation.
       </t>
     </section>
 
diff --git a/nfsv42_middle_new_errors.xml b/nfsv42_middle_new_errors.xml
index 23aa07a..123fb44 100644
--- a/nfsv42_middle_new_errors.xml
+++ b/nfsv42_middle_new_errors.xml
@@ -224,6 +224,40 @@
         NFS4ERR_WRONG_TYPE
       </c>
 
+      <c>DEALLOCATE</c>
+      <c>
+        NFS4ERR_ACCESS,
+        NFS4ERR_ADMIN_REVOKED,
+        NFS4ERR_BADXDR,
+        NFS4ERR_BAD_STATEID,
+        NFS4ERR_DEADSESSION,
+        NFS4ERR_DELAY,
+        NFS4ERR_DELEG_REVOKED,
+        NFS4ERR_EXPIRED,
+        NFS4ERR_FBIG,
+        NFS4ERR_FHEXPIRED,
+        NFS4ERR_GRACE,
+        NFS4ERR_INVAL,
+        NFS4ERR_IO,
+        NFS4ERR_ISDIR,
+        NFS4ERR_MOVED,
+        NFS4ERR_NOFILEHANDLE,
+        NFS4ERR_NOTSUPP,
+        NFS4ERR_OLD_STATEID,
+        NFS4ERR_OPENMODE,
+        NFS4ERR_OP_NOT_IN_SESSION,
+        NFS4ERR_REP_TOO_BIG,
+        NFS4ERR_REP_TOO_BIG_TO_CACHE,
+        NFS4ERR_REQ_TOO_BIG,
+        NFS4ERR_RETRY_UNCACHED_REP,
+        NFS4ERR_ROFS,
+        NFS4ERR_SERVERFAULT,
+        NFS4ERR_STALE,
+        NFS4ERR_SYMLINK,
+        NFS4ERR_TOO_MANY_OPS,
+        NFS4ERR_WRONG_TYPE
+      </c>
+
       <c>OFFLOAD_ABORT</c>
       <c>
         NFS4ERR_ADMIN_REVOKED,
@@ -363,45 +397,6 @@
         NFS4ERR_TOO_MANY_OPS
       </c>
 
-      <c>WRITE_HOLE</c>
-      <c>
-        NFS4ERR_ACCESS,
-        NFS4ERR_ADMIN_REVOKED,
-        NFS4ERR_BADXDR,
-        NFS4ERR_BAD_STATEID,
-        NFS4ERR_DEADSESSION,
-        NFS4ERR_DELAY,
-        NFS4ERR_DELEG_REVOKED,
-        NFS4ERR_DQUOT,
-        NFS4ERR_EXPIRED,
-        NFS4ERR_FBIG,
-        NFS4ERR_FHEXPIRED,
-        NFS4ERR_GRACE,
-        NFS4ERR_INVAL,
-        NFS4ERR_IO,
-        NFS4ERR_ISDIR,
-        NFS4ERR_LOCKED,
-        NFS4ERR_MOVED,
-        NFS4ERR_NOFILEHANDLE,
-        NFS4ERR_NOSPC,
-        NFS4ERR_NOTSUPP,
-        NFS4ERR_OLD_STATEID,
-        NFS4ERR_OPENMODE,
-        NFS4ERR_OP_NOT_IN_SESSION,
-        NFS4ERR_PNFS_IO_HOLE,
-        NFS4ERR_PNFS_NO_LAYOUT,
-        NFS4ERR_REP_TOO_BIG,
-        NFS4ERR_REP_TOO_BIG_TO_CACHE,
-        NFS4ERR_REQ_TOO_BIG,
-        NFS4ERR_RETRY_UNCACHED_REP,
-        NFS4ERR_ROFS,
-        NFS4ERR_SERVERFAULT,
-        NFS4ERR_STALE,
-        NFS4ERR_SYMLINK,
-        NFS4ERR_TOO_MANY_OPS,
-        NFS4ERR_WRONG_TYPE
-      </c>
-
       <c>WRITE_SAME</c>
       <c>
         NFS4ERR_ACCESS,
diff --git a/nfsv42_middle_op_cb_offload.xml b/nfsv42_middle_op_cb_offload.xml
index bbd5676..d94ead0 100644
--- a/nfsv42_middle_op_cb_offload.xml
+++ b/nfsv42_middle_op_cb_offload.xml
@@ -31,10 +31,6 @@
           for both intra- and inter-server asynchronous copies
         </t>
 
-        <t hangText='WRITE_HOLE:'>
-          for a hole punch
-        </t>
-
         <t hangText='WRITE_SAME:'>
           for ADB initialization
         </t>
@@ -59,11 +55,6 @@
           the total number of bytes copied
         </t>
 
-        <t hangText='WRITE_HOLE:'>
-          the same information that a synchronous WRITE_HOLE
-          would provide
-        </t>
-
         <t hangText='WRITE_SAME:'>
           the same information that a synchronous WRITE_SAME
           would provide
diff --git a/nfsv42_middle_op_deallocate.xml b/nfsv42_middle_op_deallocate.xml
new file mode 100644
index 0000000..21ed1e4
--- /dev/null
+++ b/nfsv42_middle_op_deallocate.xml
@@ -0,0 +1,43 @@
+<!-- Copyright (C) The IETF Trust (2011-2014) -->
+<!-- Copyright (C) The Internet Society (2011-2014) -->
+
+<section anchor='op:deallocate' title='Operation 70: DEALLOCATE'>
+  <section toc='exclude' title="ARGUMENT">
+    <?rfc include='autogen/deallocate_args.xml'?>
+  </section>
+
+  <section toc='exclude' title="RESULT">
+    <?rfc include='autogen/deallocate_res.xml'?>
+  </section>
+
+  <section toc='exclude' anchor='op:deallocate:desc'  title="DESCRIPTION">
+    <t>
+      Whenever a client wishes to unreserve space for a region in a file it calls
+      the DEALLOCATE operation with the current filehandle set to the filehandle
+      of the file in question, and the start offset and length in bytes of
+      the region set in aa_offset and aa_length respectively.  If no space was
+      allocated to or reservered for all or parts of the region, the DEALLOCATE
+      operation will have no effect for the region that already is in unreserved
+      state.
+      All further reads from the region passed to DEALLOCATE MUST return zeros
+      until overwritten.  The filehandle specified must be that of a regular file.
+    </t>
+
+    <t>
+      Situations may arise where da_offset and/or da_offset + da_length will
+      not be aligned to a boundary for which the server does allocations or
+      deallocations.  For most file systems, this is the block size of the
+      filesystem.  In such a case, the server can deallocate as many bytes as
+      it can in the region.  The blocks that cannot be deallocated MUST be
+      zeroed.
+    </t>
+
+    <t>
+      DEALLOCATE will result in the space_used attribute being decreased by
+      the number of bytes that were deallocated.  The space_freed attribute
+      may or may not decrease, depending on the support and whether the
+      blocks backing the specified range were shared or not.  The size
+      attribute will remain unchanged.
+    </t>
+  </section>
+</section>
diff --git a/nfsv42_middle_op_mandlist.xml b/nfsv42_middle_op_mandlist.xml
index 417de68..e78a671 100644
--- a/nfsv42_middle_op_mandlist.xml
+++ b/nfsv42_middle_op_mandlist.xml
@@ -125,6 +125,7 @@
       <c>COPY                 </c> <c> OPT </c> <c> COPY (REQ)   </c>
       <c>OFFLOAD_ABORT        </c> <c> OPT </c> <c> COPY (REQ)   </c>
       <c>COPY_NOTIFY          </c> <c> OPT </c> <c> COPY (REQ)   </c>
+      <c>DEALLOCATE           </c> <c> OPT </c> <c>              </c>
       <c>OFFLOAD_REVOKE       </c> <c> OPT </c> <c> COPY (REQ)   </c>
       <c>OFFLOAD_STATUS       </c> <c> OPT </c> <c> COPY (REQ)   </c>
       <c>CREATE               </c> <c> REQ </c> <c>              </c>
@@ -179,7 +180,6 @@
       <c>VERIFY               </c> <c> REQ </c> <c>              </c>
       <c>WANT_DELEGATION      </c> <c> OPT </c> <c> FDELG (OPT)  </c>
       <c>WRITE                </c> <c> REQ </c> <c>              </c>
-      <c>WRITE_HOLE           </c> <c> OPT </c> <c>              </c>
       <c>WRITE_SAME           </c> <c> OPT </c> <c> ADB (REQ)    </c>
   </texttable>
 
diff --git a/nfsv42_middle_op_write_hole.xml b/nfsv42_middle_op_write_hole.xml
deleted file mode 100644
index df69c3f..0000000
--- a/nfsv42_middle_op_write_hole.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<!-- Copyright (C) The IETF Trust (2011-2014) -->
-<!-- Copyright (C) The Internet Society (2011-2014) -->
-
-<section anchor='op:write_hole' title='Operation 64: WRITE_HOLE'>
-  <section toc='exclude' title="ARGUMENT">
-    <?rfc include='autogen/stable_how4.xml'?>
-    <?rfc include='autogen/type_space_info4.xml'?>
-    <?rfc include='autogen/data_info4.xml'?>
-    <?rfc include='autogen/write_hole_args.xml'?>
-  </section>
-
-  <section toc='exclude' title="RESULT">
-    <?rfc include='autogen/write_response4.xml'?>
-    <?rfc include='autogen/write_hole_res.xml'?>
-  </section>
-
-  <section toc='exclude' anchor='op:write_hole:desc'  title="DESCRIPTION">
-    <t>
-      Whenever a client wishes to reinitialize the blocks backing
-      a particular region in the file, it calls the WRITE_HOLE
-      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 wh_hole.di_offset
-      and wh_hole.di_length respectively.  If wh_hole.di_reserved
-      is set to SPACE_RESERVED4, then the blocks will be zeroed and
-      if it is set to SPACE_UNRESERVED4, then they will be deallocated.
-      A server must reject a WRITE_HOLE call with wh_hole.di_reserved
-      set to SPACE_UNKNOWN4 with NFS4ERR_INVAL. All further reads to
-      this region MUST return zeros until overwritten.  The filehandle
-      specified must be that of a regular file.
-    </t>
-
-    <t>
-      The client specifies with the ws_stable parameter the method of how the
-      data is to be processed by the server.  It is treated like the stable
-      parameter in the NFSv4.1 WRITE operation (see Section 18.2 of
-      <xref target="RFC5661" />).
-    </t>
-
-    <t>
-      Situations may arise where di_offset and/or di_offset +
-      di_length will not be aligned to a boundary for which the
-      server does allocations or deallocations.  For most file
-      systems, this is the block size of the file system.  In such
-      a case, the server can deallocate as many bytes as it can in
-      the region.  The blocks that cannot be deallocated MUST be
-      zeroed.  Except for the block deallocation and maximum hole
-      punching capability, a WRITE_HOLE operation is to be treated
-      similar to a write of zeroes.
-    </t>
-
-    <t>
-      The server is not required to complete deallocating the blocks
-      specified in the operation before returning.  The server
-      SHOULD return an asynchronous result if it can determine the
-      operation will be long running (see
-      <xref target='op:write_hole:async' />).
-    </t>
-
-    <t>
-      A successful WRITE_HOLE will construct a reply for wr_count,
-      wr_committed, and wr_writeverf as per the NFSv4.1 WRITE
-      operation results.  If wr_callback_id is set, it indicates
-      an asynchronous reply (see <xref target='op:write_hole:async' />).
-    </t>
-
-    <t>
-      WRITE_HOLE has to support all of the errors which are returned by WRITE
-      plus NFS4ERR_NOTSUPP, i.e., it is an OPTIONAL operation.
-      If the client supports WRITE_HOLE, it MUST support CB_OFFLOAD.
-    </t>
-
-    <t>
-      If used to hole punch, WRITE_HOLE will result in the space_used
-      attribute being decreased by the number of bytes that were
-      deallocated.  The space_freed attribute
-      may or may not decrease, depending on the support and whether the
-      blocks backing the specified range were shared or not.  The size
-      attribute will remain unchanged.
-    </t>
-
-    <t>
-      The WRITE_HOLE operation MUST NOT change the space reservation
-      guarantee of the file.  While the server can deallocate the blocks
-      specified by di_offset and di_length, future writes to this region
-      MUST NOT fail with NFSERR_NOSPC.
-    </t>
-
-    <section anchor='op:write_hole:async' title='Asynchronous Transactions'>
-      <t>
-        Hole punching may lead to server determining to service the
-        operation asynchronously. If it decides to do so, it sets the
-        stateid in wr_callback_id to be that of the wh_stateid. If it
-        does not set the wr_callback_id, then the result is synchronous.
-      </t>
-
-      <t>
-        When the client determines that the reply will be given
-        asynchronously, it should not assume anything about the
-        contents of what it wrote until it is informed by the server
-        that the operation is complete. It can use OFFLOAD_STATUS
-        (<xref target="op:offload_status" />) to monitor the operation
-        and OFFLOAD_ABORT (<xref target="op:offload_abort" />) to cancel
-        the operation. An example of a asynchronous WRITE_HOLE is shown
-        in <xref target='fig:async-write_hole' />. Note that as with the
-        COPY operation, WRITE_HOLE must provide a stateid for tracking
-        the asynchronous operation.
-      </t>
-
-      <figure title="An asynchronous WRITE_HOLE." anchor="fig:async-write_hole">
-        <artwork><![CDATA[
-  Client                                  Server
-     +                                      +
-     |                                      |
-     |--- OPEN ---------------------------->| Client opens
-     |<------------------------------------/| the file
-     |                                      |
-     |--- WRITE_HOLE ---------------------->| Client punches
-     |<------------------------------------/| a hole
-     |                                      |
-     |                                      |
-     |--- OFFLOAD_STATUS ------------------>| Client may poll
-     |<------------------------------------/| for status
-     |                                      |
-     |                  .                   | Multiple OFFLOAD_STATUS
-     |                  .                   | operations may be sent.
-     |                  .                   |
-     |                                      |
-     |<-- CB_OFFLOAD -----------------------| Server reports results
-     |\------------------------------------>|
-     |                                      |
-     |--- CLOSE --------------------------->| Client closes
-     |<------------------------------------/| the file
-     |                                      |
-     |                                      |
-        ]]></artwork>
-      </figure>
-
-      <t>
-        When CB_OFFLOAD informs the client of
-        the successful WRITE_HOLE, the write_response4
-        embedded in the operation will provide
-        the necessary information that a synchronous
-        WRITE_HOLE would have provided.
-      </t>
-
-      <t>
-        Regardless of whether the operation is asynchronous or
-        synchronous, it MUST still support the COMMIT operation semantics
-        as outlined in Section 18.3 of <xref target="RFC5661" />.
-        I.e., COMMIT works on one or more WRITE operations and the
-        WRITE_HOLE operation can appear as several WRITE operations
-        to the server.  The client can use locking operations to control the behavior
-        on the server with respect to long running asynchronous
-        write operations.
-      </t>
-    </section>
-  </section>
-</section>
diff --git a/nfsv42_middle_space.xml b/nfsv42_middle_space.xml
index b167044..6fc7137 100644
--- a/nfsv42_middle_space.xml
+++ b/nfsv42_middle_space.xml
@@ -93,9 +93,8 @@
           deleted, taking block sharing into consideration.
         </t>
 
-        <t hangText="WRITE_HOLE">
-          This operation zeros and/or deallocates the blocks
-          backing a region of the file.
+        <t hangText="DEALLOCATE">
+          This operation deallocates the blocks backing a region of the file.
         </t>
         
 	<t hangText="READ_PLUS or SEEK">
diff --git a/nfsv42_middle_sparse.xml b/nfsv42_middle_sparse.xml
index f98f550..1efb1dd 100644
--- a/nfsv42_middle_sparse.xml
+++ b/nfsv42_middle_sparse.xml
@@ -54,10 +54,11 @@
     </t>
 
     <t>
-      Two new operations WRITE_HOLE (<xref target="op:write_hole" />)
+      Two new operations DEALLOCATE (<xref target="op:deallocate" />)
       and READ_PLUS (<xref target="op:read_plus" />) are
-      introduced.  WRITE_HOLE allows for the hole punching.  I.e.,
-      an application might want to reinitialize a range of the file.
+      introduced.  DEALLOCATE allows for the hole punching.  I.e.,
+      an application might want to reset the allocation and reservation
+      status of a range of the file.
       READ_PLUS supports all the features of READ but includes
       an extension to support sparse files.  READ_PLUS is guaranteed
       to perform no worse than READ, and can dramatically improve
@@ -128,16 +129,11 @@
       </t>
     </section>
 
-    <section anchor="ss:sparse:write_hole" title="WRITE_HOLE">
+    <section anchor="ss:sparse:deallocate" title="DEALLOCATE">
       <t>
-        WRITE_HOLE can be used to hole punch, which allows the
+        DEALLOCATE can be used to hole punch, which allows the
         client to avoid the transfer of a repetitive pattern of zeros
-        across the network.  If the filesystem on the server does not
-        support sparse files, the WRITE_HOLE operation may return
-        the result asynchronously via the CB_OFFLOAD operation.  As
-        a hole punch may entail deallocating data blocks, even if
-        the filesystem supports sparse files, it may still have to
-        return the result via CB_OFFLOAD.
+        across the network.
       </t>
     </section>
   </section>

---

From: Tom Haynes <[email-masked]>
Date: Thu, 24 Apr 2014 14:24:35 -0700

Other than it becomes OP 64 rather than 70, looks good.

Okay, strike that, I think we need to be a little more clearer
that ALLOCATE is completely synchronous. This:

   It is not required that the server allocate the space to the file
   before returning success.  The allocation can be deferred, however,
   it must be guaranteed that it will not fail for lack of space.

leaves it open that it can be asynchronous.

I’m not advocating we replace the WRITE_HOLE text you deleted
with ALLOCATED in Section 15.1.3.

I think the following change handles my concern:

   It is not required that the server allocate the space to the file
   before returning success.  The allocation can be deferred, however,
   it must be guaranteed that it will not fail for lack of space. The
   deferral does not result in an asynchronous reply.

Thoughts?

---

From: Tom Haynes <[email-masked]>
Date: Thu, 24 Apr 2014 15:19:04 -0700

Thanks Christoph.

I’ve taken both patch sets and fixed up some nits.

---

From: Thomas Haynes <[email-masked]>
Date: Thu, 24 Apr 2014 22:08:43 -0700

On Apr 24, 2014, at 9:56 PM, Christoph Hellwig <[email-masked]> wrote:

> On Thu, Apr 24, 2014 at 02:24:35PM -0700, Tom Haynes wrote:
> I wanted to keep DEALLOCATE after ALLOCATE in the list, as it seems
> more logical to me.
> 

The opcode list is not sparse. :-)