Subject: [nfsv4] 0000-Get-rid-of-ADHs-long-live-ADB

From: Thomas Haynes <[email-masked]>
Date: Mon, 21 Apr 2014 23:12:03 -0700

Proposal to get rid of the ADH (and WRITE_SAME) and replace
it with an ADB. This will reduce the complexity in READ_PLUS
and SEEK.

---

From: Thomas Haynes <[email-masked]>
Date: Mon, 21 Apr 2014 23:12:04 -0700

From: Tom Haynes <[email-masked]>

Signed-off-by: loghyr <[email-masked]>
---
 Makefile                        |  10 +-
 dotx.d/Makefile                 |   6 +-
 dotx.d/read_plus_res.x          |   2 -
 dotx.d/seek_res.x               |   2 -
 dotx.d/spit_types.sh            |  27 +++---
 dotx.d/write_adb_args.x         |   8 ++
 dotx.d/write_adb_res.x          |   8 ++
 dotx.d/write_same_args.x        |   8 --
 dotx.d/write_same_res.x         |   8 --
 nfsv42_middle_application.xml   | 124 +++++++-----------------
 nfsv42_middle_errors.xml        |   4 +-
 nfsv42_middle_introduction.xml  |   9 +-
 nfsv42_middle_new_errors.xml    |   4 +-
 nfsv42_middle_op_cb_offload.xml |  15 +--
 nfsv42_middle_op_mandlist.xml   |   8 +-
 nfsv42_middle_op_read_plus.xml  |  49 ++++------
 nfsv42_middle_op_seek.xml       |   3 +-
 nfsv42_middle_op_write_adb.xml  | 158 ++++++++++++++++++++++++++++++
 nfsv42_middle_op_write_same.xml | 209 ----------------------------------------
 nfsv42_middle_space.xml         |   4 +-
 nfsv42_middle_sparse.xml        |  79 +++++++--------
 21 files changed, 309 insertions(+), 436 deletions(-)
 create mode 100644 dotx.d/write_adb_args.x
 create mode 100644 dotx.d/write_adb_res.x
 delete mode 100644 dotx.d/write_same_args.x
 delete mode 100644 dotx.d/write_same_res.x
 create mode 100644 nfsv42_middle_op_write_adb.xml
 delete mode 100644 nfsv42_middle_op_write_same.xml

diff --git a/Makefile b/Makefile
index 1c04c33..704c5a5 100755
--- a/Makefile
+++ b/Makefile
@@ -169,7 +169,7 @@ SPITGEN =	dotx.d/type_nfstime4.x \
 		dotx.d/copy_confirm_auth.x \
 		dotx.d/copy_from_auth.x \
 		dotx.d/copy_to_auth.x \
-		dotx.d/app_data_hole4.x \
+		dotx.d/app_data_block4.x \
 		dotx.d/data_info4.x \
 		dotx.d/data4.x \
 		dotx.d/data_content4.x \
@@ -247,7 +247,7 @@ SPITGENXML =	autogen/type_nfstime4.xml \
 		autogen/copy_confirm_auth.xml \
 		autogen/copy_from_auth.xml \
 		autogen/copy_to_auth.xml \
-		autogen/app_data_hole4.xml \
+		autogen/app_data_block4.xml \
 		autogen/data_info4.xml \
 		autogen/data4.xml \
 		autogen/data_content4.xml \
@@ -344,8 +344,8 @@ AUTOGEN =	\
 		autogen/illegal_res.xml \
 		autogen/write_hole_args.xml \
 		autogen/write_hole_res.xml \
-		autogen/write_same_args.xml \
-		autogen/write_same_res.xml \
+		autogen/write_adb_args.xml \
+		autogen/write_adb_res.xml \
 		autogen/io_advise_args.xml \
 		autogen/io_advise_res.xml \
 		autogen/layoutcommit_args.xml \
@@ -447,7 +447,7 @@ IDXMLSRC_BASE = \
 	${DOC_PREFIX}_middle_op_read_plus.xml \
 	${DOC_PREFIX}_middle_op_seek.xml \
 	${DOC_PREFIX}_middle_op_write_hole.xml \
-	${DOC_PREFIX}_middle_op_write_same.xml \
+	${DOC_PREFIX}_middle_op_write_adb.xml \
 	${DOC_PREFIX}_middle_op_zzz.xml \
 	${DOC_PREFIX}_middle_op_cb_aaa.xml \
 	${DOC_PREFIX}_middle_op_cb_offload.xml \
diff --git a/dotx.d/Makefile b/dotx.d/Makefile
index dd1a2b5..eac06f6 100755
--- a/dotx.d/Makefile
+++ b/dotx.d/Makefile
@@ -126,8 +126,8 @@ FORE_OPS_AS_IS2 = \
 		read_plus_res.x \
 		seek_args.x \
 		seek_res.x \
-		write_same_args.x \
-		write_same_res.x
+		write_adb_args.x \
+		write_adb_res.x
 
 FORE_OPS = $(FORE_OPS_AS_IS1) open_args_gen.x $(FORE_OPS_AS_IS2)
 
@@ -231,7 +231,7 @@ SPITGEN =	basic_types.x \
 		copy_confirm_auth.x \
 		copy_from_auth.x \
 		copy_to_auth.x \
-		app_data_hole4.x \
+		app_data_block4.x \
 		data_info4.x \
 		data4.x \
 		data_content4.x \
diff --git a/dotx.d/read_plus_res.x b/dotx.d/read_plus_res.x
index bd0acb6..8ab3682 100644
--- a/dotx.d/read_plus_res.x
+++ b/dotx.d/read_plus_res.x
@@ -2,8 +2,6 @@
 union read_plus_content switch (data_content4 rpc_content) {
 case NFS4_CONTENT_DATA:
 	data4		rpc_data;
-case NFS4_CONTENT_APP_DATA_HOLE:
-	app_data_hole4	rpc_adh;
 case NFS4_CONTENT_HOLE:
 	data_info4	rpc_hole;
 default:
diff --git a/dotx.d/seek_res.x b/dotx.d/seek_res.x
index df11142..44fb273 100644
--- a/dotx.d/seek_res.x
+++ b/dotx.d/seek_res.x
@@ -2,8 +2,6 @@
 union seek_content switch (data_content4 content) {
 case NFS4_CONTENT_DATA:
 	data_info4	sc_data;
-case NFS4_CONTENT_APP_DATA_HOLE:
-	app_data_hole4	sc_adh;
 case NFS4_CONTENT_HOLE:
 	data_info4	sc_hole;
 default:
diff --git a/dotx.d/spit_types.sh b/dotx.d/spit_types.sh
index 8e3b227..db139b2 100755
--- a/dotx.d/spit_types.sh
+++ b/dotx.d/spit_types.sh
@@ -1003,7 +1003,7 @@ enum nfs_opnum4 {
  OP_READ_PLUS		= 65,
  OP_SEEK		= 66,
  OP_IO_ADVISE		= 67,
- OP_WRITE_SAME		= 68,
+ OP_WRITE_ADB		= 68,
  OP_ILLEGAL		= 10044
 };
 EOF
@@ -1124,7 +1124,7 @@ union nfs_argop4 switch (nfs_opnum4 argop) {
  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_WRITE_ADB:	WRITE_ADB4args opwrite_adb;
 
  /* Operations not new to NFSv4.1 */
  case OP_ILLEGAL:	void;
@@ -1255,7 +1255,7 @@ union nfs_resop4 switch (nfs_opnum4 resop) {
  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_WRITE_ADB:	WRITE_ADB4res opwrite_adb;
 
  /* Operations not new to NFSv4.1 */
  case OP_ILLEGAL:	ILLEGAL4res opillegal;
@@ -1371,17 +1371,17 @@ EOF
 
 	;;
 
-	app_data_hole4.x )
+	app_data_block4.x )
 
 cat << EOF > $i
-struct app_data_hole4 {
-	offset4		adh_offset;
-	length4		adh_block_size;
-	length4		adh_block_count;
-	length4		adh_reloff_blocknum;
-	count4		adh_block_num;
-	length4		adh_reloff_pattern;
-	opaque		adh_pattern<>;
+struct app_data_block4 {
+	offset4		adb_offset;
+	length4		adb_block_size;
+	length4		adb_block_count;
+	length4		adb_reloff_blocknum;
+	count4		adb_block_num;
+	length4		adb_reloff_pattern;
+	opaque		adb_pattern<>;
 };
 EOF
 
@@ -1419,8 +1419,7 @@ cat << EOF > $i
  */
 enum data_content4 {
 	NFS4_CONTENT_DATA = 0,
-	NFS4_CONTENT_APP_DATA_HOLE = 1,
-	NFS4_CONTENT_HOLE = 2
+	NFS4_CONTENT_HOLE = 1
 };
 EOF
 
diff --git a/dotx.d/write_adb_args.x b/dotx.d/write_adb_args.x
new file mode 100644
index 0000000..ba29d32
--- /dev/null
+++ b/dotx.d/write_adb_args.x
@@ -0,0 +1,8 @@
+
+struct WRITE_ADB4args {
+	/* CURRENT_FH: file */
+	stateid4	wa_stateid;
+	stable_how4	wa_stable;
+	app_data_block4	wa_adb;
+};
+
diff --git a/dotx.d/write_adb_res.x b/dotx.d/write_adb_res.x
new file mode 100644
index 0000000..b668f89
--- /dev/null
+++ b/dotx.d/write_adb_res.x
@@ -0,0 +1,8 @@
+
+union WRITE_ADB4res switch (nfsstat4 wa_status) {
+case NFS4_OK:
+	write_response4		wa_resok4;
+default:
+	void;
+};
+
diff --git a/dotx.d/write_same_args.x b/dotx.d/write_same_args.x
deleted file mode 100644
index 43a8615..0000000
--- a/dotx.d/write_same_args.x
+++ /dev/null
@@ -1,8 +0,0 @@
-
-struct WRITE_SAME4args {
-	/* CURRENT_FH: file */
-	stateid4	ws_stateid;
-	stable_how4	ws_stable;
-	app_data_hole4	ws_adh;
-};
-
diff --git a/dotx.d/write_same_res.x b/dotx.d/write_same_res.x
deleted file mode 100644
index 7a5b927..0000000
--- a/dotx.d/write_same_res.x
+++ /dev/null
@@ -1,8 +0,0 @@
-
-union WRITE_SAME4res switch (nfsstat4 ws_status) {
-case NFS4_OK:
-	write_response4		ws_resok4;
-default:
-	void;
-};
-
diff --git a/nfsv42_middle_application.xml b/nfsv42_middle_application.xml
index 8e67ddd..8081315 100644
--- a/nfsv42_middle_application.xml
+++ b/nfsv42_middle_application.xml
@@ -1,7 +1,7 @@
 <!-- Copyright (C) The IETF Trust (2011-2014) -->
 <!-- Copyright (C) The Internet Society (2011-2014) -->
 
-<section anchor='sec:adh' title='Application Data Hole Support'>
+<section anchor='sec:adb' title='Application Data Block Support'>
   <t>
     At the OS level, files are contained on disk
     blocks.  Applications are also free to impose structure on the
@@ -23,9 +23,11 @@
   <t>
     <list style='numbers'>
       <t>
-        A logical block number which allows the application to determine which
-        data block is being referenced.  This is useful when the
-        client is not storing the blocks in contiguous memory.
+        An Application Data Block Number (ADBN) which allows
+        the application to determine which data block is being
+        referenced.  This is useful when the client is not
+        storing the blocks in contiguous memory, i.e., a logical
+        block number.
       </t>
 
       <t>
@@ -46,34 +48,30 @@
     in data blocks <xref target='Ashdown08' />.
     What they are not able to do is efficiently transfer and
     store ADBs. To initialize a file with ADBs, the client
-    must send the full ADB to the server and that must be stored
+    must send each full ADB to the server and that must be stored
     on the server.
   </t>
 
   <t>
-    In this section, we are going to define an Application Data
-    Hole (ADH), which is a generic framework
-    for transferring the  ADB, present one approach to detecting corruption in
-    a given ADH implementation, and describe the model for
-    how the client and server can support efficient initialization
-    of ADHs, reading of ADH holes, punching ADH holes in a file, and space
-    reservation. We define the ADHN to be the Application Data Hole
-    Number, which is the logical block number discussed earlier.
+    In this section, we are going to define a framework
+    for transferring the ADB from client to server and
+    present one approach to detecting corruption in
+    a given ADB implementation.
   </t>
 
-  <section anchor='ss:adh:framework' title='Generic Framework'>
+  <section anchor='ss:adb:framework' title='Generic Framework'>
     <t>
-      We want the representation of the ADH to be flexible
+      We want the representation of the ADB to be flexible
       enough to support many different applications. The most
       basic approach is no imposition of a block at all, which
       means we are working with the raw bytes. Such an approach
       would be useful for storing holes, punching holes, etc.
       In more complex deployments, a server might be supporting
       multiple applications, each with their own definition of
-      the ADH. One might store the ADHN at the start of the block
+      the ADB. One might store the ADBN at the start of the block
       and then have a guard pattern to detect corruption
       <xref target='McDougall07' />. The next
-      might store the ADHN at an offset of 100 bytes within the
+      might store the ADBN at an offset of 100 bytes within the
       block and have no guard pattern at all, i.e.,
       existing applications might already have well defined
       formats for their data blocks.
@@ -83,7 +81,7 @@
       The guard pattern can be used to represent the state of
       the block, to protect against corruption, or both. Again,
       it needs to be able to be placed anywhere within the
-      ADH.
+      ADB.
     </t>
 
     <t>
@@ -93,41 +91,30 @@
       sized blocks in a file.
     </t>
 
-    <section anchor='ss:adh:dh' title='Data Hole Representation'>
-      <?rfc include='autogen/app_data_hole4.xml'?>
+    <section anchor='ss:adb:dh' title='Data Block Representation'>
+      <?rfc include='autogen/app_data_block4.xml'?>
 
       <t>
-        The app_data_hole4 structure captures the abstraction presented
-        for the ADH. The additional fields present are to allow
-        the transmission of adh_block_count ADHs at one time.  We
-        also use adh_block_num to convey the ADHN of the first block
-        in the sequence.  Each ADH will contain the same adh_pattern
+        The app_data_block4 structure captures the abstraction presented
+        for the ADB. The additional fields present are to allow
+        the transmission of adb_block_count ADBs at one time.  We
+        also use adb_block_num to convey the ADBN of the first block
+        in the sequence.  Each ADB will contain the same adb_pattern
         string.
       </t>
 
       <t>
-        As both adh_block_num and adh_pattern are optional, if
-        either adh_reloff_pattern or adh_reloff_blocknum is set
+        As both adb_block_num and adb_pattern are optional, if
+        either adb_reloff_pattern or adb_reloff_blocknum is set
         to NFS4_UINT64_MAX, then the corresponding field is not
-        set in any of the ADH.
-      </t>
-    </section>
-
-    <section anchor='ss:adh:dc' title='Data Content'>
-      <?rfc include='autogen/data_content4.xml'?>
-
-      <t>
-        New operations might need to differentiate between
-        wanting to access data versus an ADH. Also, future
-        minor versions might want to introduce new data
-        formats. This enumeration allows that to occur.
+        set in any of the ADB.
       </t>
     </section>
   </section>
 
-  <section anchor='ss:adh:corrupt' title='An Example of Detecting Corruption'>
+  <section anchor='ss:adb:corrupt' title='An Example of Detecting Corruption'>
     <t>
-      In this section, we define an ADH format in which
+      In this section, we define an ADB format in which
       corruption can be detected. Note that this is just
       one possible format and means to detect corruption.
     </t>
@@ -155,7 +142,7 @@
       <list style='hanging'>
         <t hangText='0xfeedface - '>
           This is the FREE state and indicates that the
-          ADH format has been applied.
+          ADB format has been applied.
         </t>
 
         <t hangText='0xcafedead - '>
@@ -183,7 +170,7 @@
       contents of the block. If the state is FREE, then
       that checksum is trivially zero. As such, the application
       has no need to transfer the checksum implicitly inside the
-      ADH - it need not make the transfer layer aware of the
+      ADB - it need not make the transfer layer aware of the
       fact that there is a checksum (see
       <xref target='Ashdown08' /> for an example
       of checksums used to detect corruption in application
@@ -191,7 +178,7 @@
     </t>
 
     <t>
-      Corruption in each ADH can thus be detected:
+      Corruption in each ADB can thus be detected:
     </t>
 
     <t>
@@ -203,7 +190,7 @@
 
         <t>
           If the guard pattern is FREE and any other
-          byte in the remainder of the ADH is anything other
+          byte in the remainder of the ADB is anything other
           than zero.
         </t>
 
@@ -216,7 +203,7 @@
         <t>
           If the guard pattern is INDIRECT and one of the
           stored indirect block numbers has a value greater
-          than the number of ADHs in the file.
+          than the number of ADBs in the file.
         </t>
 
         <t>
@@ -231,7 +218,7 @@
       As can be seen, the application can detect errors based
       on the combination of the guard pattern state and the
       checksum. But also, the application can detect corruption
-      based on the state and the contents of the ADH.
+      based on the state and the contents of the ADB.
       This last point is important in validating the minimum
       amount of data we incorporated into our generic
       framework. I.e., the guard pattern is sufficient
@@ -248,47 +235,4 @@
       detects corruption.
     </t>
   </section>
-
-  <section anchor='ss:adh:ex_rp' title='Example of READ_PLUS'>
-    <t>
-      The hypothetical application presented in
-      <xref target='ss:adh:corrupt' /> can be used to
-      illustrate how READ_PLUS would return an array
-      of results. A file is created and initialized
-      with 100 4k ADHs in the FREE state:
-    </t>
-
-    <figure>
-      <artwork>
-   WRITE_SAME {0, 4k, 100, 0, 0, 8, 0xfeedface}
-      </artwork>
-    </figure>
-
-    <t>
-      Further, assume the application writes a single
-      ADH at 16k, changing the guard pattern to 0xcafedead,
-      we would then have in memory:
-    </t>
-
-    <figure>
-      <artwork>
-   0 -> (16k - 1)   : 4k, 4, 0, 0, 8, 0xfeedface
-   16k -> (20k - 1) : 00 00 00 05 ca fe de ad XX XX ... XX XX
-   20k -> 400k      : 4k, 95, 0, 6, 0xfeedface
-      </artwork>
-    </figure>
-
-    <t>
-     And when the client did a READ_PLUS of 64k at the start of the file,
-     it would get back a result of an ADH, some data, and a final ADH:
-    </t>
-
-    <figure>
-      <artwork>
-   ADH {0, 4, 0, 0, 8, 0xfeedface}
-   data 4k
-   ADH {20k, 4k, 59, 0, 6, 0xfeedface}
-      </artwork>
-    </figure>
-  </section>
 </section>
diff --git a/nfsv42_middle_errors.xml b/nfsv42_middle_errors.xml
index 495b0a6..4c028d2 100644
--- a/nfsv42_middle_errors.xml
+++ b/nfsv42_middle_errors.xml
@@ -2807,7 +2807,7 @@
         NFS4ERR_WRONG_TYPE
       </c>
 
-      <c>WRITE_HOLE</c>
+      <c>WRITE_ADB</c>
       <c>
         NFS4ERR_ACCESS,
         NFS4ERR_ADMIN_REVOKED,
@@ -2846,7 +2846,7 @@
         NFS4ERR_WRONG_TYPE
       </c>
 
-      <c>WRITE_SAME</c>
+      <c>WRITE_HOLE</c>
       <c>
         NFS4ERR_ACCESS,
         NFS4ERR_ADMIN_REVOKED,
diff --git a/nfsv42_middle_introduction.xml b/nfsv42_middle_introduction.xml
index 72ce829..ce37372 100644
--- a/nfsv42_middle_introduction.xml
+++ b/nfsv42_middle_introduction.xml
@@ -120,12 +120,13 @@
       </t>
     </section>
 
-    <section title="Application Data Hole (ADH) Support">
+    <section title="Application Data Block (ADB) Support">
       <t>
         Some applications treat a file as if it were a disk and as such
-        want to initialize (or format) the file image. We extend both
-        READ_PLUS and introduce WRITE_SAME (see <xref target='op:write_same' />)
-        to understand this metadata as a new form of a hole.
+        want to initialize (or format) the file image. We 
+        introduce WRITE_ADB (see <xref target='op:write_adb' />)
+        to send this metadata to the server to allow it to write
+        the block contents.
       </t>
     </section>
 
diff --git a/nfsv42_middle_new_errors.xml b/nfsv42_middle_new_errors.xml
index c10d9b4..1149f08 100644
--- a/nfsv42_middle_new_errors.xml
+++ b/nfsv42_middle_new_errors.xml
@@ -327,7 +327,7 @@
         NFS4ERR_TOO_MANY_OPS
       </c>
 
-      <c>WRITE_HOLE</c>
+      <c>WRITE_ADB</c>
       <c>
         NFS4ERR_ACCESS,
         NFS4ERR_ADMIN_REVOKED,
@@ -366,7 +366,7 @@
         NFS4ERR_WRONG_TYPE
       </c>
 
-      <c>WRITE_SAME</c>
+      <c>WRITE_HOLE</c>
       <c>
         NFS4ERR_ACCESS,
         NFS4ERR_ADMIN_REVOKED,
diff --git a/nfsv42_middle_op_cb_offload.xml b/nfsv42_middle_op_cb_offload.xml
index dcd3d57..b2bea2d 100644
--- a/nfsv42_middle_op_cb_offload.xml
+++ b/nfsv42_middle_op_cb_offload.xml
@@ -24,13 +24,16 @@
     </t>
 
     <t>
-      If the client supports either
+      If the client supports any of the following operations:
       <list style="numbers">
         <t>
-          the COPY operation
+          COPY
         </t>
         <t>
-          either the WRITE_HOLE or WRITE_SAME operations
+          WRITE_HOLE
+        </t>
+        <t>
+          WRITE_ADB
         </t>
       </list>
 
@@ -54,12 +57,12 @@
       </t>
     </section>
 
-    <section toc='exclude' title='WRITE_HOLE and WRITE_SAME'>
+    <section toc='exclude' title='WRITE_HOLE and WRITE_ADB'>
       <t>
         CB_OFFLOAD is used to report the completion of either
-        a hole punch or an ADH initialization. Upon success,
+        a hole punch or an ADB initialization. Upon success,
         the coa_resok4 will contain the same information that
-        the corresponding synchronous WRITE_HOLE or WRITE_SAME
+        the corresponding synchronous WRITE_HOLE or WRITE_ADB
         would have returned.
       </t>
     </section>
diff --git a/nfsv42_middle_op_mandlist.xml b/nfsv42_middle_op_mandlist.xml
index 854079c..1dd5b14 100644
--- a/nfsv42_middle_op_mandlist.xml
+++ b/nfsv42_middle_op_mandlist.xml
@@ -105,8 +105,8 @@
         Server Side Copy
       </t>
 
-      <t hangText='ADH'>
-        Application Data Holes
+      <t hangText='ADB'>
+        Application Data Blocks
       </t>
     </list>
   </t>
@@ -159,7 +159,7 @@
       <c>READ                 </c> <c> REQ (OBS)</c> <c>              </c>
       <c>READDIR              </c> <c> REQ </c> <c>              </c>
       <c>READLINK             </c> <c> OPT </c> <c>              </c>
-      <c>READ_PLUS            </c> <c> OPT </c> <c> ADH (REQ)    </c>
+      <c>READ_PLUS            </c> <c> OPT </c> <c>              </c>
       <c>RECLAIM_COMPLETE     </c> <c> REQ </c> <c>              </c>
       <c>RELEASE_LOCKOWNER    </c> <c> MNI </c> <c>              </c>
       <c>REMOVE               </c> <c> REQ </c> <c>              </c>
@@ -178,8 +178,8 @@
       <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_ADB            </c> <c> OPT </c> <c> ADB (REQ)    </c>
       <c>WRITE_HOLE           </c> <c> OPT </c> <c>              </c>
-      <c>WRITE_SAME           </c> <c> OPT </c> <c> ADH (REQ)    </c>
   </texttable>
 
   <texttable>
diff --git a/nfsv42_middle_op_read_plus.xml b/nfsv42_middle_op_read_plus.xml
index e04a219..af368e0 100644
--- a/nfsv42_middle_op_read_plus.xml
+++ b/nfsv42_middle_op_read_plus.xml
@@ -1,5 +1,5 @@
-<!-- Copyright (C) The IETF Trust (2011-2013) -->
-<!-- Copyright (C) The Internet Society (2011-2013) -->
+<!-- Copyright (C) The IETF Trust (2011-2014) -->
+<!-- Copyright (C) The Internet Society (2011-2014) -->
 
 <section anchor='op:read_plus' title='Operation 65: READ_PLUS'>
   <section toc='exclude' title="ARGUMENT">
@@ -29,15 +29,14 @@
     </t>
 
     <t>
-      The READ_PLUS result is comprised of an array of rpr_contents, each of
-      which describe a data_content4 type of data (<xref target="ss:adh:dc" />).
-      For NFSv4.2, the allowed
-      values are data, ADH, and hole. A server is required to support the
-      data type, but neither ADH nor hole. Both an ADH and a hole must 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.
+      The READ_PLUS result is comprised of an array of rpr_contents,
+      each of which describe a data_content4 type of data.  For
+      NFSv4.2, the allowed values are data and hole. A server MUST
+      support the data type, but not the hole. The hole must 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.
     </t>
 
     <t>
@@ -52,11 +51,10 @@
     </t>
 
     <t>
-      The server may elect to return adjacent elements of the same type. For
-      example, the guard pattern or block size of an ADH might change, which
-      would require adjacent elements of type ADH. Likewise if the server
-      has a range of data comprised entirely of zeros and then a hole, it
-      might want to return two adjacent holes to the client.
+      The server may elect to return adjacent elements of the same
+      type. For example, if the server has a range of data comprised
+      entirely of zeros and then a hole, it might want to return
+      two adjacent holes to the client.
     </t>
 
     <t>
@@ -137,7 +135,7 @@
     <section toc='exclude' title="Additional pNFS Implementation Information">
       <t>
         With pNFS, the semantics of using READ_PLUS remains the same.  Any
-        data server MAY return a hole or ADH result for a READ_PLUS request that
+        data server MAY return a hole result for a READ_PLUS request that
         it receives.  When a data server chooses to return such a result, it has the
         option of returning information for the data stored on that
         data server (as defined by the data layout), but it MUST NOT return
@@ -145,13 +143,6 @@
       </t>
 
       <t>
-        A data server should do its best to return as much information about
-        a ADH as is feasible without having to contact the metadata server.
-        If communication with the metadata server is required, then every
-        attempt should be taken to minimize the number of requests.
-      </t>
-
-      <t>
         If mandatory locking is enforced, then the data server must also
         ensure that to return only information that is within
         the owner’s locked byte range.
@@ -179,10 +170,12 @@
     </texttable>
 
     <t>
-      Under the given circumstances, if a client was to read from the file
-      with a max read size of 64K, the following will be
-      the results for the given READ_PLUS calls.  This assumes the client has already opened the file,
-      acquired a valid stateid ('s' in the example), and just needs to issue READ_PLUS requests.
+      Under the given circumstances, if a client was to read from
+      the file with a max read size of 64K, the following will be
+      the results for the given READ_PLUS calls.  This assumes the
+      client has already opened the file, acquired a valid stateid
+      ('s' in the example), and just needs to issue READ_PLUS
+      requests.
     </t>
 
     <t>
diff --git a/nfsv42_middle_op_seek.xml b/nfsv42_middle_op_seek.xml
index 47af9c1..6245182 100644
--- a/nfsv42_middle_op_seek.xml
+++ b/nfsv42_middle_op_seek.xml
@@ -15,14 +15,13 @@
 
   <section toc='exclude' title="RESULT">
     <?rfc include='autogen/data_info4.xml'?>
-    <?rfc include='autogen/app_data_hole4.xml'?>
     <?rfc include='autogen/seek_res.xml'?>
   </section>
 
   <section toc='exclude' title="DESCRIPTION">
     <t>
       From the given sa_offset, find the next data_content4 of type
-      sa_what in the file. For either a hole or ADH, this must return
+      sa_what in the file. For a hole, this must return
       the data_content4 in its entirety. For data, it must not return
       the actual data.
     </t>
diff --git a/nfsv42_middle_op_write_adb.xml b/nfsv42_middle_op_write_adb.xml
new file mode 100644
index 0000000..d489348
--- /dev/null
+++ b/nfsv42_middle_op_write_adb.xml
@@ -0,0 +1,158 @@
+<!-- Copyright (C) The IETF Trust (2011-2014) -->
+<!-- Copyright (C) The Internet Society (2011-2014) -->
+
+<section anchor='op:write_adb' title='Operation 68: WRITE_ADB'>
+  <section toc='exclude' title="ARGUMENT">
+    <?rfc include='autogen/app_data_block4.xml'?>
+    <?rfc include='autogen/write_adb_args.xml'?>
+  </section>
+
+  <section toc='exclude' title="RESULT">
+    <?rfc include='autogen/write_response4.xml'?>
+    <?rfc include='autogen/write_adb_res.xml'?>
+  </section>
+
+  <section toc='exclude' anchor='op:write_adb:desc'  title="DESCRIPTION">
+    <t>
+      The WRITE_ADB operation is an extension of the NFSv4.1 WRITE
+      operation (see Section 18.2 of <xref target="RFC5661" />) and
+      writes ADBs (see <xref target='sec:adb' />) to the regular file
+      identified by the current filehandle.  The server MAY write
+      fewer bytes than requested by the client.
+    </t>
+
+    <t>
+      A successful WRITE_ADB 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_adb:async' />).
+    </t>
+
+    <t>
+      WRITE_ADB 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_ADB, it MUST support
+      CB_OFFLOAD.
+    </t>
+
+    <t>
+     If the server supports ADBs, then it MUST support the
+     WRITE_ADB operation.  The server has no concept of the
+     structure imposed by the application. It is only when the
+     application writes to a section of the file does order get
+     imposed.  In order to detect corruption even before the
+     application utilizes the file, the application will want
+     to initialize a range of ADBs using WRITE_ADB.
+    </t>
+
+    <t>
+      When the client invokes the WRITE_ADB operation, it wants
+      to impose the structure described by the app_data_block4
+      on to the file.
+    </t>
+
+    <t>
+      When the server receives the WRITE_ADB operation, it MUST
+      populate adb_block_count ADBs in the file starting at adb_offset.
+      The block size will be given by adb_block_size. The ADBN (if
+      provided) will start at adb_reloff_blocknum and each block
+      will be monotonically numbered starting from adb_block_num
+      in the first block. The pattern (if provided) will be at
+      adb_reloff_pattern of each block and will be provided in
+      adb_pattern.
+    </t>
+
+    <t>
+      The server SHOULD return an asynchronous result
+      if it can determine the operation will be long running (see
+      <xref target='op:write_adb:async' />). This document does
+      not mandate the manner in which the server stores ADBs for
+      a file. It is possible for them to be stored sparsely. But
+      regardless of how they are stored, once either the
+      WRITE_ADB finishes synchronously or the server uses
+      CB_OFFLOAD to inform the client of the asynchronous completion
+      of the WRITE_ADB, the server MUST return the ADBs to clients
+      as data.
+    </t>
+
+    <t>
+      Since the server has no knowledge of ADBs, it should not
+      report misaligned creation of ADBs.  Even while it can detect
+      them, it cannot disallow them, as the application might be
+      in the process of changing the size of the ADBs. Thus the
+      server must be prepared to handle a WRITE_ADB into an existing
+      ADB.
+    </t>
+
+    <section anchor='op:write_adb:async' title='Asynchronous Transactions'>
+      <t>
+	      ADB initialization 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
+	      ws_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_ADB
+	      is shown in <xref target='fig:async-write_adb' />. Note
+	      that as with the COPY operation, WRITE_ADB must provide a
+	      stateid for tracking the asynchronous operation.
+      </t>
+
+      <figure title="An asynchronous WRITE_ADB." anchor="fig:async-write_adb">
+        <artwork><![CDATA[
+  Client                                  Server
+     +                                      +
+     |                                      |
+     |--- OPEN ---------------------------->| Client opens
+     |<------------------------------------/| the file
+     |                                      |
+     |--- WRITE_ADB ----------------------->| Client initializes
+     |<------------------------------------/| an ADB
+     |                                      |
+     |                                      |
+     |--- 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_ADB, the write_response4
+        embedded in the operation will provide
+        the necessary information that a synchronous
+        WRITE_ADB 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_ADB 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_op_write_same.xml b/nfsv42_middle_op_write_same.xml
deleted file mode 100644
index 01c695f..0000000
--- a/nfsv42_middle_op_write_same.xml
+++ /dev/null
@@ -1,209 +0,0 @@
-<!-- Copyright (C) The IETF Trust (2011-2014) -->
-<!-- Copyright (C) The Internet Society (2011-2014) -->
-
-<section anchor='op:write_same' title='Operation 68: WRITE_SAME'>
-  <section toc='exclude' title="ARGUMENT">
-    <?rfc include='autogen/app_data_hole4.xml'?>
-    <?rfc include='autogen/write_same_args.xml'?>
-  </section>
-
-  <section toc='exclude' title="RESULT">
-    <?rfc include='autogen/write_response4.xml'?>
-    <?rfc include='autogen/write_same_res.xml'?>
-  </section>
-
-  <section toc='exclude' anchor='op:write_same:desc'  title="DESCRIPTION">
-    <t>
-      The WRITE_SAME operation is an extension of the NFSv4.1 WRITE
-      operation (see Section 18.2 of <xref target="RFC5661" />) and
-      writes data to the regular file identified by the
-      current filehandle.  The server MAY write fewer bytes than
-      requested by the client.
-    </t>
-
-    <t>
-      The WRITE_SAME argument is comprised of an array of rpr_contents, each of
-      which describe a data_content4 type of data (<xref target="ss:adh:dc" />).
-      For NFSv4.2, the allowed values are data, ADH, and hole.
-      The array contents MUST be contiguous in the file. A successful
-      WRITE_SAME 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_same:async' />).
-    </t>
-
-    <t>
-      WRITE_SAME 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_SAME, it MUST support CB_OFFLOAD.
-    </t>
-
-    <section title="ADHs">
-      <t>
-        If the server supports ADHs, then it MUST support the
-        WRITE_SAME operation.
-        The server has no concept of the structure imposed
-        by the application. It is only when the application
-        writes to a section of the file does order get imposed.
-        In order to detect corruption even before the application
-        utilizes the file, the application will want to initialize
-        a range of ADHs using WRITE_SAME.
-      </t>
-
-      <t>
-        For ADHs, when the client invokes the WRITE_SAME operation, it has
-        two desired results:
-      </t>
-
-      <t>
-        <list style='numbers'>
-          <t>
-            The structure described by the app_data_block4 be imposed
-            on the file.
-          </t>
-
-          <t>
-            The contents described by the app_data_block4 be sparse.
-          </t>
-        </list>
-      </t>
-
-      <t>
-        If the server supports the WRITE_SAME operation, it still
-        might not support sparse files. So if it receives the
-        WRITE_SAME operation, then it MUST populate the contents
-        of the file with the initialized ADHs. The server SHOULD
-        return an asynchronous result if it can determine the
-        operation will be long running
-        (see <xref target='op:write_same:async' />).
-      </t>
-
-      <t>
-        If the data was already initialized, there are two
-        interesting scenarios:
-      </t>
-
-      <t>
-        <list style='numbers'>
-          <t>
-            The data blocks are allocated.
-          </t>
-
-          <t>
-            Initializing in the middle of an existing ADH.
-          </t>
-        </list>
-      </t>
-
-      <t>
-        If the data blocks were already allocated, then
-        the WRITE_SAME is a hole punch operation. If
-        WRITE_SAME supports sparse files, then the data
-        blocks are to be deallocated. If not, then the
-        data blocks are to be rewritten in the indicated
-        ADH format.
-      </t>
-
-      <t>
-        Since the server has no knowledge of ADHs, it
-        should not report misaligned creation of ADHs.
-        Even while it can detect them, it cannot disallow
-        them, as the application might be in the process of
-        changing the size of the ADHs. Thus the server
-        must be prepared to handle an WRITE_SAME into
-        an existing ADH.
-      </t>
-
-      <t>
-        This document does not mandate the manner in
-        which the server stores ADHs sparsely for a
-        file. However, if an WRITE_SAME arrives that
-        will force a new ADH to start inside an
-        existing ADH then the server will have three
-        ADHs instead of two. It will have one up to
-        the new one for the WRITE_SAME, one for the
-        WRITE_SAME, and one for after the WRITE_SAME.
-        Note that depending on server specific policies
-        for block allocation, there may also be some
-        physical blocks allocated to align the boundaries.
-      </t>
-    </section>
-
-    <section anchor='op:write_same:async' title='Asynchronous Transactions'>
-      <t>
-        ADH initialization 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 ws_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_SAME is shown in
-        <xref target='fig:async-write_same' />. Note that
-        as with the COPY operation, WRITE_SAME must
-        provide a stateid for tracking the asynchronous
-        operation.
-      </t>
-
-      <figure title="An asynchronous WRITE_SAME." anchor="fig:async-write_same">
-        <artwork><![CDATA[
-  Client                                  Server
-     +                                      +
-     |                                      |
-     |--- OPEN ---------------------------->| Client opens
-     |<------------------------------------/| the file
-     |                                      |
-     |--- WRITE_SAME ---------------------->| Client initializes
-     |<------------------------------------/| an ADH
-     |                                      |
-     |                                      |
-     |--- 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_SAME, the write_response4
-        embedded in the operation will provide
-        the necessary information that a synchronous
-        WRITE_SAME 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_SAME 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 701b6ff..0eab7c9 100644
--- a/nfsv42_middle_space.xml
+++ b/nfsv42_middle_space.xml
@@ -96,8 +96,8 @@
           deleted, taking block sharing into consideration.
         </t>
 
-        <t hangText="WRITE_HOLE and WRITE_SAME">
-          These operations zero and/or deallocate the blocks
+        <t hangText="WRITE_HOLE">
+          This operation zeros and/or deallocates the blocks
           backing a region of the file.
         </t>
       </list>
diff --git a/nfsv42_middle_sparse.xml b/nfsv42_middle_sparse.xml
index ab095d4..2a7abcc 100644
--- a/nfsv42_middle_sparse.xml
+++ b/nfsv42_middle_sparse.xml
@@ -45,20 +45,16 @@
     </t>
 
     <t>
-      Three new operations WRITE_HOLE (<xref target="op:write_hole" />),
-      WRITE_SAME (<xref target="op:write_same" />), 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.  WRITE_SAME allows for
-      the creation of application
-      specific block structures in a file which is treated by the
-      application as if it were a disk.  READ_PLUS supports all the
-      features of READ but includes extensions to support both sparse
-      files and sparse pattern files (<xref target="ss:adh:dc" />).  READ_PLUS is
-      guaranteed to perform no worse than READ, and can dramatically
-      improve performance with sparse files.  READ_PLUS does not
-      depend on pNFS protocol features, but can be used by pNFS to
-      support sparse files.
+      Two new operations WRITE_HOLE (<xref target="op:write_hole" />)
+      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.
+      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
+      performance with sparse files.  READ_PLUS does not depend on
+      pNFS protocol features, but can be used by pNFS to support
+      sparse files.
     </t>
   </section>
 
@@ -91,19 +87,16 @@
 
   <section anchor="ss:sparse:new_ops" title="New Operations">
     <t>
-      READ_PLUS, WRITE_HOLE, and WRITE_SAME 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 both holes and ADHs
-      (see <xref target='ss:adh:dh' />). As READ 
-      is inefficient for transfer of sparse sections of the file,
-      it is marked as OBSOLESCENT in NFSv4.2. Instead, a client
-      should utilize READ_PLUS. Note that as
-      the client has no a priori knowledge of whether either
-      an ADH or a hole is present or not, if it supports
-      these operations and so does the server, then it should
-      always use these operations.
+      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.  As READ is inefficient for transfer of sparse
+      sections of the file, it is marked as OBSOLESCENT in NFSv4.2.
+      Instead, a client should utilize READ_PLUS. 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.
     </t>
 
     <section anchor="ss:sparse:read_plus" title="READ_PLUS">
@@ -115,36 +108,32 @@
        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.  For ADHs, READ_PLUS is used to return
-       the metadata describing the portions of the file which are
-       initialized and contain no backing store.
+       reducing performance.
       </t>
 
       <t>
         If the client sends a READ operation, it is explicitly
-        stating that it is neither supporting sparse files nor ADHs. So
-        if a READ occurs on a sparse ADH or file, then the server must
+        stating that it is not supporting sparse files. So
+        if a READ occurs on a sparse file, then the server must
         expand such data to be raw bytes. If a READ occurs in
-        the middle of a hole or ADH, the server can only send back
+        the middle of a hole, the server can only send back
         bytes starting from that offset. In contrast, if a READ_PLUS
-        occurs in the middle of a hole or ADH, the server can send
+        occurs in the middle of a hole, the server can send
         back a range which starts before the offset and extends past
         the range.
       </t>
     </section>
 
-    <section anchor="ss:sparse:write_hole_same" title="WRITE_HOLE and WRITE_SAME">
+    <section anchor="ss:sparse:write_hole" title="WRITE_HOLE">
       <t>
-        WRITE_HOLE can be used to hole punch and WRITE_SAME
-        can be used to initialize ADHs. For either purpose,
-        the client can avoid the
-        transfer of a repetitive pattern across the network.
-        If the filesystem on the server does not support
-        sparse files, the WRITE_HOLE and WRITE_SAME operations 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.
+        WRITE_HOLE 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.
       </t>
     </section>
   </section>
-- 
1.9.2