]> git.lizzy.rs Git - plan9front.git/blob - sys/doc/venti/venti.html
6in4: add -m mtu option to specify outer MTU
[plan9front.git] / sys / doc / venti / venti.html
1 <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
2 <html>
3
4 <head>
5
6 <meta http-equiv="Content-Language" content="en-us">
7 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
8
9 <title>Venti: a new approach to archival storage</title>
10 </head>
11
12 <body bgcolor="white">
13
14 <h1>Venti: a new approach to archival storage</h1>
15
16 <p>
17
18 Sean Quinlan and Sean Dorward
19 <br>
20
21 Bell Labs, Lucent Technologies
22 <p>
23
24 <h1>Abstract</h1>
25 <p>
26
27 This paper describes a network storage system, called Venti, intended
28 for archival data.  In this system, a unique hash of a block's
29 contents acts as the block identifier for read and write operations.
30 This approach enforces a write-once policy, preventing accidental or
31 malicious destruction of data.  In addition, duplicate copies of a
32 block can be coalesced, reducing the consumption of storage and
33 simplifying the implementation of clients.  Venti is a building block
34 for constructing a variety of storage applications such as logical
35 backup, physical backup, and snapshot file systems.
36 <p>
37
38 We have built a prototype of the system and present some preliminary
39 performance results.  The system uses magnetic disks as the storage
40 technology, resulting in an access time for archival data that is
41 comparable to non-archival data.  The feasibility of the write-once
42 model for storage is demonstrated using data from over a decade's use
43 of two Plan 9 file systems.
44 <p>
45
46 <h1>1.  Introduction</h1>
47 <p>
48
49 Archival storage is a second class citizen.  Many computer
50 environments provide access to a few recent versions of the
51 information stored in file systems and databases, though this access
52 can be tedious and may require the assistance of a system
53 administrator.  Less common is the ability for a user to examine data
54 from last month or last year or last decade.  Such a feature may not
55 be needed frequently, but when it is needed it is often crucial.
56 <p>
57
58 The growth in capacity of storage technologies exceeds the ability of
59 many users to generate data, making it practical to archive data in
60 perpetuity.  Plan 9, the computing environment that the authors use,
61 includes a file system that stores archival data to an optical jukebox
62 [16, 17].  Ken Thompson observed that, for our usage patterns, the
63 capacity of the jukebox could be considered infinite.  In the time it
64 took for us to fill the jukebox, the improvement in technology would
65 allow us to upgrade to a new jukebox with twice the capacity.
66 <p>
67
68 Abundant storage suggests that an archival system impose a write-once
69 policy.  Such a policy prohibits either a user or administrator from
70 deleting or modifying data once it is stored.  This approach greatly
71 reduces the opportunities for accidental or malicious data loss and
72 simplifies the system's implementation.
73 <p>
74
75 Moreover, our experience with Plan 9 is that a write-once policy
76 changes the way one views storage.  Obviously, some data is temporary,
77 derivative, or so large that it is either undesirable or impractical
78 to retain forever and should not be archived.  However, once it is
79 decided that the data is worth keeping, the resources needed to store
80 the data have been consumed and cannot be reclaimed.  This eliminates
81 the task of periodically "cleaning up" and deciding whether the data
82 is still worth keeping.  More thought is required before storing the
83 data to a write-once archive, but as the cost of storage continues to
84 fall, this becomes an easy decision.
85 <p>
86
87 This paper describes the design and implementation of an archival
88 server, called Venti.  The goal of Venti is to provide a write-once
89 archival repository that can be shared by multiple client machines and
90 applications.  In addition, by using magnetic disks as the primary
91 storage technology, the performance of the system approaches that of
92 non-archival storage.
93 <p>
94
95 <h1>2.  Background</h1>
96 <p>
97
98 A prevalent form of archival storage is the regular backup of data to
99 magnetic tape [15].  A typical scenario is to provide backup as a
100 central service for a number of client machines.  Client software
101 interfaces with a database or file system and determines what data to
102 back up.  The data is copied from the client to the tape device, often
103 over a network, and a record of what was copied is stored in a catalog
104 database.
105 <p>
106
107 Restoring data from a tape backup system can be tedious and error
108 prone.  The backup system violates the access permission of the file
109 system, requiring a system administrator or privileged software to
110 perform the task.  Since they are tedious, restore operations are
111 infrequent and problems with the process may go undetected.  Potential
112 sources of error abound: tapes are mislabeled or reused or lost,
113 drives wander out of alignment and cannot read their old tapes,
114 technology becomes obsolete.
115 <p>
116
117 For tape backup systems, a tradeoff exists between the performance of
118 backup and restore operations [1].  A full backup simplifies the
119 process of restoring data since all the data is copied to a continuous
120 region on the tape media.  For large file systems and databases,
121 incremental backups are more efficient to generate, but such backups
122 are not self-contained; the data for a restore operation is scattered
123 across multiple incremental backups and perhaps multiple tapes.  The
124 conventional solution is to limit the extent of this scattering by
125 performing a full backup followed by a small number of incremental
126 backups.
127 <p>
128
129 File systems such as Plan 9 [16, 17], WAFL [5], and AFS [7] provide a
130 more unified approach to the backup problem by implementing a snapshot
131 feature.  A snapshot is a consistent read-only view of the file system
132 at some point in the past.  The snapshot retains the file system
133 permissions and can be accessed with standard tools (ls, cat, cp,
134 grep, diff) without special privileges or assistance from an
135 administrator.  In our experience, snapshots are a relied-upon and
136 frequently-used resource because they are always available and easy to
137 access.
138 <p>
139
140 Snapshots avoid the tradeoff between full and incremental backups.
141 Each snapshot is a complete file system tree, much like a full backup.
142 The implementation, however, resembles an incremental backup because
143 the snapshots and the active file system share any blocks that remain
144 unmodified; a snapshot only requires additional storage for the blocks
145 that have changed.  To achieve reasonable performance, the device that
146 stores the snapshots must efficiently support random access, limiting
147 the suitability of tape storage for this approach.
148 <p>
149
150 In the WAFL and AFS systems, snapshots are ephemeral; only a small
151 number of recent versions of the file system are retained.  This
152 policy is reasonable since the most recent versions of files are the
153 most useful.  For these systems, archival storage requires an
154 additional mechanism such as tape backup.
155 <p>
156
157 The philosophy of the Plan 9 file system is that random access storage
158 is sufficiently cheap that it is feasible to retain snapshots
159 permanently.  The storage required to retain all daily snapshots of a
160 file system is surprisingly modest; later in the paper we present
161 statistics for two file servers that have been in use over the last 10
162 years.
163 <p>
164
165 Like Plan 9, the Elephant file system [18] retains many versions of
166 data.  This system allows a variety of storage reclamation policies
167 that determine when a version of a file should be deleted.  In
168 particular, "landmark" versions of files are retained permanently and
169 provide an archival record.
170 <p>
171
172 <h1>3.  The Venti Archival Server</h1>
173 <p>
174
175 Venti is a block-level network storage system intended for archival
176 data.  The interface to the system is a simple protocol that enables
177 client applications to read and write variable sized blocks of data.
178 Venti itself does not provide the services of a file or backup system,
179 but rather the backend archival storage for these types of
180 applications.
181 <p>
182
183 Venti identifies data blocks by a hash of their contents.  By using a
184 collision-resistant hash function with a sufficiently large output, it
185 is possible to consider the hash of a data block as unique.  Such a
186 unique hash is called the fingerprint of a block and can be used as
187 the address for read and write operations.  This approach results in a
188 storage system with a number of interesting properties.
189 <p>
190
191 As blocks are addressed by the fingerprint of their contents, a block
192 cannot be modified without changing its address; the behavior is
193 intrinsically write-once.  This property distinguishes Venti from most
194 other storage systems, in which the address of a block and its
195 contents are independent.
196 <p>
197
198 Moreover, writes are idempotent.  Multiple writes of the same data can
199 be coalesced and do not require additional storage space.  This
200 property can greatly increase the effective storage capacity of the
201 server since it does not rely on the behavior of client applications.
202 For example, an incremental backup application may not be able to
203 determine exactly which blocks have changed, resulting in unnecessary
204 duplication of data.  On Venti, such duplicate blocks will be
205 discarded and only one copy of the data will be retained.  In fact,
206 replacing the incremental backup with a full backup will consume the
207 same amount of storage.  Even duplicate data from different
208 applications and machines can be eliminated if the clients write the
209 data using the same block size and alignment.
210 <p>
211
212 The hash function can be viewed as generating a universal name space
213 for data blocks.  Without cooperating or coordinating, multiple
214 clients can share this name space and share a Venti server.  Moreover,
215 the block level interface places few restrictions on the structures
216 and format that clients use to store their data.  In contrast,
217 traditional backup and archival systems require more centralized
218 control.  For example, backup systems include some form of job
219 scheduler to serialize access to tape devices and may only support a
220 small number of predetermined data formats so that the catalog system
221 can extract pertinent meta-data.
222 <p>
223
224 Venti provides inherent integrity checking of data.  When a block is
225 retrieved, both the client and the server can compute the fingerprint
226 of the data and compare it to the requested fingerprint.  This
227 operation allows the client to avoid errors from undetected data
228 corruption and enables the server to identify when error recovery is
229 necessary.
230 <p>
231
232 Using the fingerprint of a block as its identity facilitates features
233 such as replication, caching, and load balancing.  Since the contents
234 of a particular block are immutable, the problem of data coherency is
235 greatly reduced; a cache or a mirror cannot contain a stale or out of
236 date version of a block.
237 <p>
238
239 <h2>3.1.  Choice of Hash Function</h2>
240 <p>
241
242 The design of Venti requires a hash function that generates a unique
243 fingerprint for every data block that a client may want to store.
244 Obviously, if the size of the fingerprint is smaller than the size of
245 the data blocks, such a hash function cannot exist since there are
246 fewer possible fingerprints than blocks.  If the fingerprint is large
247 enough and randomly distributed, this problem does not arise in
248 practice.  For a server of a given capacity, the likelihood that two
249 different blocks will have the same hash value, also known as a
250 collision, can be determined.  If the probability of a collision is
251 vanishingly small, we can be confident that each fingerprint is
252 unique.
253 <p>
254
255 It is desirable that Venti employ a cryptographic hash function.  For
256 such a function, it is computationally infeasible to find two distinct
257 inputs that hash to the same value [10].  This property is important
258 because it prevents a malicious client from intentionally creating
259 blocks that violate the assumption that each block has a unique
260 fingerprint.  As an additional benefit, using a cryptographic hash
261 function strengthens a client's integrity check, preventing a
262 malicious server from fulfilling a read request with fraudulent data.
263 If the fingerprint of the returned block matches the requested
264 fingerprint, the client can be confident the server returned the
265 original data.
266 <p>
267
268 Venti uses the Sha1 hash function [13] developed by the US National
269 Institute for Standards and Technology (NIST).  Sha1 is a popular hash
270 algorithm for many security systems and, to date, there are no known
271 collisions.  The output of Sha1 is a 160 bit (20 byte) hash value.
272 Software implementations of Sha1 are relatively efficient; for
273 example, a 700Mhz Pentium 3 can compute the Sha1 hash of 8 Kbyte data
274 blocks in about 130 microseconds, a rate of 60 Mbytes per second.
275 <p>
276
277 Are the 160 bit hash values generated by Sha1 large enough to ensure
278 the fingerprint of every block is unique?  Assuming random hash values
279 with a uniform distribution, a collection of n different data blocks
280 and a hash function that generates b bits, the probability p that
281 there will be one or more collisions is bounded by the number of pairs
282 of blocks multiplied by the probability that a given pair will
283 collide, i.e.
284 <p>
285 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
286 <img src="probablity.gif" ALT="probablity">
287 <p>
288
289 Today, a large storage system may contain a petabyte (10^15 bytes) of data.
290 Consider an even larger system that contains an exabyte (10^18 bytes)
291 stored as 8 Kbyte blocks (~10^14 blocks).  Using the Sha1 hash function, the
292 probability of a collision is less than 10^-20.  Such a scenario seems
293 sufficiently unlikely that we ignore it and use the Sha1 hash as a
294 unique identifier for a block.  Obviously, as storage technology
295 advances, it may become feasible to store much more than an exabyte,
296 at which point it maybe necessary to move to a larger hash function.
297 NIST has already proposed variants of Sha1 that produce 256, 384, and
298 512 bit results [14].  For the immediate future, however, Sha1 is a
299 suitable choice for generating the fingerprint of a block.
300 <p>
301
302 <h2>3.2.  Choice of Storage Technology</h2>
303 <p>
304
305 When the Plan 9 file system was designed in 1989, optical jukeboxes
306 offered high capacity with respectable random access performance and
307 thus were an obvious candidate for archival storage.  The last decade,
308 however, has seen the capacity of magnetic disks increase at a far
309 faster rate than optical technologies [20].  Today, a disk array costs
310 less than the equivalent capacity optical jukebox and occupies less
311 physical space.  Disk technology is even approaching tape in cost per
312 bit.
313 <p>
314
315 Magnetic disk storage is not as stable or permanent as optical media.
316 Reliability can be improved with technology such as RAID, but unlike
317 write-once optical disks, there is little protection from erasure due
318 to failures of the storage server or RAID array firmware.  This issue
319 is discussed in Section 7.
320 <p>
321
322 Using magnetic disks for Venti has the benefit of reducing the
323 disparity in performance between conventional and archival storage.
324 Operations that previously required data to be restored to magnetic
325 disk can be accomplished directly from the archive.  Similarly, the
326 archive can contain the primary copy of often-accessed read-only data.
327 In effect, archival data need not be further down the storage
328 hierarchy; it is differentiated by the write-once policy of the
329 server.
330 <p>
331
332 <h1>4.  Applications</h1>
333 <p>
334
335 Venti is a building block on which to construct a variety of storage
336 applications.  Venti provides a large repository for data that can be
337 shared by many clients, much as tape libraries are currently the
338 foundation of many centralized backup systems.  Applications need to
339 accommodate the unique properties of Venti, which are different from
340 traditional block level storage devices, but these properties enable a
341 number of interesting features.
342 <p>
343
344 Applications use the block level service provided by Venti to store
345 more complex data structures.  Data is divided into blocks and written
346 to the server.  To enable this data to be retrieved, the application
347 must record the fingerprints of these blocks.  One approach is to pack
348 the fingerprints into additional blocks, called pointer blocks, that
349 are also written to the server, a process that can be repeated
350 recursively until a single fingerprint is obtained.  This fingerprint
351 represents the root of a tree of blocks and corresponds to a
352 hierarchical hash of the original data.
353 <p>
354
355 A simple data structure for storing a linear sequence of data blocks
356 is shown in Figure 1.  The data blocks are located via a fixed depth
357 tree of pointer blocks which itself is addressed by a root
358 fingerprint.  Applications can use such a structure to store a single
359 file or to mimic the behavior of a physical device such as a tape or a
360 disk drive.  The write-once nature of Venti does not allow such a tree
361 to be modified, but new versions of the tree can be generated
362 efficiently by storing the new or modified data blocks and reusing the
363 unchanged sections of the tree as depicted in Figure 2.
364 <p>
365
366
367 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
368 <img src="SimpleTree.gif" ALT="simple tree">
369 <p>
370 Figure 1.  A tree structure for storing a linear sequence of blocks
371 <p>
372
373
374 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
375 <img src="ModifiedTree.gif" ALT="modified tree">
376 <p>
377 Figure 2.  Build a new version of the tree.
378 <p>
379
380 By mixing data and fingerprints in a block, more complex data
381 structures can be constructed.  For example, a structure for storing a
382 file system may include three types of blocks: directory, pointer, and
383 data.  A directory block combines the meta information for a file and
384 the fingerprint to a tree of data blocks containing the file's
385 contents.  The depth of the tree can be determined from the size of
386 the file, assuming the pointer and data blocks have a fixed size.
387 Other structures are obviously possible.  Venti's block-level
388 interface leaves the choice of format to client applications and
389 different data structures can coexist on a single server.
390 <p>
391
392 The following sections describes three applications that use Venti as
393 an archival data repository: a user level archive utility called vac,
394 a proposal for a physical level backup utility, and our preliminary
395 work on a new version of the Plan 9 file system.
396 <p>
397
398 <h2>4.1.  Vac</h2>
399 <p>
400
401 Vac is an application for storing a collection of files and
402 directories as a single object, similar in functionality to the
403 utilities tar and zip.  With vac, the contents of the selected files
404 are stored as a tree of blocks on a Venti server.  The root
405 fingerprint for this tree is written to a vac archive file specified
406 by the user, which consists of an ASCII representation of the 20 byte
407 root fingerprint plus a fixed header string, and is always 45 bytes
408 long.  A corresponding program, called unvac, enables the user to
409 restore files from a vac archive.  Naturally, unvac requires access to
410 the Venti server that contains the actual data, but in most situations
411 this is transparent.  For a user, it appears that vac compresses any
412 amount of data down to 45 bytes.
413 <p>
414
415 An important attribute of vac is that it writes each file as a
416 separate collection of Venti blocks, thus ensuring that duplicate
417 copies of a file will be coalesced on the server.  If multiple users
418 vac the same data, only one copy will be stored on the server.
419 Similarly, a user may repeatedly vac a directory over time and even if
420 the contents of the directory change, the additional storage consumed
421 on the server will be related to the extent of the changes rather than
422 the total size of the contents.  Since Venti coalesces data at the
423 block level, even files that change may share many blocks with
424 previous versions and thus require little space on the server; log and
425 database files are good examples of this scenario.
426 <p>
427
428 On many Unix systems, the dump utility is used to back up file
429 systems.  Dump has the ability to perform incremental backups of data;
430 a user specifies a dump level, and only files that are new or have
431 changed since the last dump at this level are written to the archive.
432 To implement incremental backups, dump examines the modified time
433 associated with each file, which is an efficient method of filtering
434 out the unchanged files.
435 <p>
436
437 Vac also implements an incremental option based on the file
438 modification times.  The user specifies an existing vac file and this
439 archive is used to reduce the number of blocks written to the Venti
440 server.  For each file, vac examines the modified time in both the
441 file system and the vac archive.  If they are the same, vac copies the
442 fingerprint for the file from the old archive into the new archive.
443 Copying just the 20-byte fingerprint enables the new archive to
444 include the entire file without reading the data from the file system
445 nor writing the data across the network to the Venti server.  In
446 addition, unlike an incremental dump, the resulting archive will be
447 identical to an archive generated without the incremental option; it
448 is only a performance improvement.  This means there is no need to
449 have multiple levels of backups, some incremental, some full, and so
450 restore operations are greatly simplified.
451 <p>
452
453 A variant of the incremental option improves the backup of files
454 without reference to modification times.  As vac reads a file, it
455 computes the fingerprint for each block.  Concurrently, the pointer
456 blocks of the old archive are examined to determine the fingerprint
457 for the block at the same offset in the old version of the file.  If
458 the fingerprints are the same, the block does not need to be written
459 to Venti.  Instead, the fingerprint can simply be copied into the
460 appropriate pointer block.  This optimization reduces the number of
461 writes to the Venti server, saving both network and disk bandwidth.
462 Like the file level optimization above, the resulting vac file is no
463 different from the one produced without this optimization.  It does,
464 however, require the data for the file to be read and is only
465 effective if there are a significant number of unchanged blocks.
466 <p>
467
468 <h2>4.2.  Physical backup</h2>
469 <p>
470
471 Utilities such as vac, tar, and dump archive data at the file or
472 logical level: they walk the file hierarchy converting both data and
473 meta-data into their own internal format.  An alternative approach is
474 block-level or physical backup, in which the disk blocks that make up
475 the file system are directly copied without interpretation.  Physical
476 backup has a number of benefits including simplicity and potentially
477 much higher throughput [8].  A physical backup utility for file
478 systems that stores the resulting data on Venti appears attractive,
479 though we have not yet implemented such an application.
480 <p>
481
482 The simplest form of physical backup is to copy the raw contents of
483 one or mores disk drives to Venti.  The backup also includes a tree of
484 pointer blocks, which enables access to the data blocks.  Like vac,
485 the end result is a single fingerprint representing the root of the
486 tree; that fingerprint needs to be recorded outside of Venti.
487 <p>
488
489 Coalescing duplicate blocks is the main advantage of making a physical
490 backup to Venti rather than copying the data to another storage medium
491 such as tape.  Since file systems are inherently block based, we
492 expect coalescing to be effective.  Not only will backups of a file
493 system over time share many unchanged blocks, but even file systems
494 for different machines that are running the same operating system may
495 have many blocks in common.  As with vac, the user sees a full backup
496 of the device, while retaining the storage space advantages of an
497 incremental backup.
498 <p>
499
500 One enhancement to physical backup is to copy only blocks that are
501 actively in use in the file system.  For most file system formats it
502 is relatively easy to determine if a block is in use or free without
503 walking the file system hierarchy.  Free blocks generally contain the
504 remnants of temporary files that were created and removed in the time
505 between backups and it is advantageous not to store such blocks.  This
506 optimization requires that the backup format be able to represent
507 missing blocks, which can easily be achieved on Venti by storing a
508 null value for the appropriate entry in the pointer tree.
509 <p>
510
511 The random access performance of Venti is sufficiently good that it is
512 possible to use a physical backup without first restoring it to disk.
513 With operating system support, it is feasible to directly mount a
514 backup file system image from Venti.  Access to this file system is
515 read only, but it provides a natural method of restoring a subset of
516 files.  For situations where a full restore is required, it might be
517 possible to do this restore in a lazy fashion, copying blocks from
518 Venti to the file system as needed, instead of copying the entire
519 contents of the file system before resuming normal operation.
520 <p>
521
522 The time to perform a physical backup can be reduced using a variety
523 of incremental techniques.  Like vac, the backup utility can compute
524 the fingerprint of each block and compare this fingerprint with the
525 appropriate entry in the pointer tree of a previous backup.  This
526 optimization reduces the number of writes to the Venti server.  If the
527 file system provides information about which blocks have changed, as
528 is the case with WAFL, the backup utility can avoid even reading the
529 unchanged blocks.  Again, a major advantage of using Venti is that the
530 backup utility can implement these incremental techniques while still
531 providing the user with a full backup.  The backup utility writes the
532 new blocks to the Venti server and constructs a pointer tree with the
533 appropriate fingerprint for the unchanged blocks.
534 <p>
535
536 <h2>4.3.  Plan 9 File system</h2>
537 <p>
538
539 When combined with a small amount of read/write storage, Venti can be
540 used as the primary location for data rather than a place to store
541 backups.  A new version of the Plan 9 file system, which we are
542 developing, exemplifies this approach.
543 <p>
544
545 Previously, the Plan 9 file system was stored on a combination of
546 magnetic disks and a write-once optical jukebox.  The jukebox
547 furnishes the permanent storage for the system, while the magnetic
548 disks act as a cache for the jukebox.  The cache provides faster file
549 access and, more importantly, accumulates the changes to the file
550 system during the period between snapshots.  When a snapshot is taken,
551 new or modified blocks are written from the disk cache to the jukebox.
552 <p>
553
554 The disk cache can be smaller than the active file system, needing
555 only to be big enough to contain the daily changes to the file system.
556 However, accesses that miss the cache are significantly slower since
557 changing platters in the jukebox takes several seconds.  This
558 performance penalty makes certain operations on old snapshots
559 prohibitively expensive.  Also, on the rare occasions when the disk
560 cache has been reinitialized due to corruption, the file server spends
561 several days filling the cache before performance returns to normal.
562 <p>
563
564 The new version of the Plan 9 file system uses Venti instead of an
565 optical jukebox as its storage device.  Since the performance of Venti
566 is comparable to disk, this substitution equalizes access both to the
567 active and to the archival view of the file system.  It also allows
568 the disk cache to be quite small; the cache accumulates changes to the
569 file system between snapshots, but does not speed file access.
570 <p>
571
572 <h1>5.  Implementation</h1>
573 <p>
574
575 We have implemented a prototype of Venti.  The implementation uses an
576 append-only log of data blocks and an index that maps fingerprints to
577 locations in this log.  It also includes a number of features that
578 improve robustness and performance.  This section gives a brief
579 overview of the implementation.  Figure 3 shows a block diagram of the
580 server.
581 <p>
582
583
584 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
585 <img src="Block.gif" ALT="block diagram">
586 <p>
587 Figure 3.  A block diagram of the Venti prototype.
588 <p>
589
590 Since Venti is intended for archival storage, one goal of our
591 prototype is robustness.  The approach we have taken is to separate
592 the storage of data blocks from the index used to locate a block.  In
593 particular, blocks are stored in an append-only log on a RAID array of
594 disk drives.  The simplicity of the append-only log structure
595 eliminates many possible software errors that might cause data
596 corruption and facilitates a variety of additional integrity
597 strategies.  A separate index structure allows a block to be
598 efficiently located in the log; however, the index can be regenerated
599 from the data log if required and thus does not have the same
600 reliability constraints as the log itself.
601 <p>
602
603 The structure of the data log is illustrated in Figure 4.  To ease
604 maintenance, the log is divided into self-contained sections called
605 arenas.  Each arena contains a large number of data blocks and is
606 sized to facilitate operations such as copying to removable media.
607 Within an arena is a section for data bocks that is filled in an
608 append-only manner.  In Venti, data blocks are variable sized, up to a
609 current limit of 52 Kbytes, but since blocks are immutable they can be
610 densely packed into an arena without fragmentation.
611 <p>
612
613 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
614 <img src="LogFormat.gif" ALT="log format">
615 <p>
616 Figure 4.  The format of the data log.
617 <p>
618
619 Each block is prefixed by a header that describes the contents of the
620 block.  The primary purpose of the header is to provide integrity
621 checking during normal operation and to assist in data recovery.  The
622 header includes a magic number, the fingerprint and size of the block,
623 the time when the block was first written, and identity of the user
624 that wrote it.  The header also includes a user-supplied type
625 identifier, which is explained in Section 7.  Note, only one copy of a
626 given block is stored in the log, thus the user and wtime fields
627 correspond to the first time the block was stored to the server.
628 <p>
629
630 Before storing a block in the log, an attempt is made to compress its
631 contents.  The inclusion of data compression increases the effective
632 capacity of the archive and is simple to add given the log structure.
633 Obviously, some blocks are incompressible.  The encoding field in the
634 block header indicates whether the data was compressed and, if so, the
635 algorithm used.  The esize field indicates the size of the data after
636 compression, enabling the location of the next block in the arena to
637 be determined.  The downside of using compression is the computational
638 cost, typically resulting in a decrease in the rate that blocks can be
639 stored and retrieved.  Our prototype uses a custom Lempel-Ziv '77 [21]
640 algorithm that is optimized for speed.  Compression is not a
641 performance bottleneck for our existing server.  Future
642 implementations may benefit from hardware solutions.
643 <p>
644
645 In addition to a log of data blocks, an arena includes a header, a
646 directory, and a trailer.  The header identifies the arena.  The
647 directory contains a copy of the block header and offset for every
648 block in the arena.  By replicating the headers of all the blocks in
649 one relatively small part of the arena, the server can rapidly check
650 or rebuild the system's global block index.  The directory also
651 facilitates error recovery if part of the arena is destroyed or
652 corrupted.  The trailer summarizes the current state of the arena
653 itself, including the number of blocks and the size of the log.
654 Within the arena, the data log and the directory start at opposite
655 ends and grow towards each other.  When the arena is filled, it is
656 marked as sealed, and a fingerprint is computed for the contents of
657 the entire arena.  Sealed arenas are never modified.
658 <p>
659
660 The basic operation of Venti is to store and retrieve blocks based on
661 their fingerprints.  A fingerprint is 160 bits long, and the number of
662 possible fingerprints far exceeds the number of blocks stored on a
663 server.  The disparity between the number of fingerprints and blocks
664 means it is impractical to map the fingerprint directly to a location
665 on a storage device.  Instead, we use an index to locate a block
666 within the log.
667 <p>
668
669 We implement the index using a disk-resident hash table as illustrated
670 in Figure 5.  The index is divided into fixed-sized buckets, each of
671 which is stored as a single disk block.  Each bucket contains the
672 index map for a small section of the fingerprint space.  A hash
673 function is used to map fingerprints to index buckets in a roughly
674 uniform manner, and then the bucket is examined using binary search.
675 If provisioned with sufficient buckets, the index hash table will be
676 relatively empty and bucket overflows will be extremely rare.  If a
677 bucket does overflow, the extra entries are placed in an adjacent
678 bucket.  This structure is simple and efficient, requiring one disk
679 access to locate a block in almost all cases.
680 <p>
681
682
683 <p>
684 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
685 <img src="Index.gif" ALT="index format">
686 <p>
687
688 Figure 5.  Format of the index.
689 <p>
690
691 The need to go through an index is the main performance penalty for
692 Venti compared to a conventional block storage device.  Our prototype
693 uses three techniques to increase the performance: caching, striping,
694 and write buffering.
695 <p>
696
697 The current implementation has two important caches of approximately
698 equal size: a block cache and an index cache.  A hit in the block
699 cache returns the data for that fingerprint, bypassing the both the
700 index lookup and access to the data log.  Hits in the index cache
701 eliminate only the index lookup, but the entries are much smaller and
702 the hit rate correspondingly higher.
703 <p>
704
705 Unfortunately, these caches do not speed the process of storing a new
706 block to Venti.  The server must check that the block is not a
707 duplicate by examining the index.  If the block is not contained on
708 the server, it will obviously not be in any cache.  Since the
709 fingerprint of the block contains no internal structure, the location
710 of a fingerprint in the index is essentially random.  Furthermore, the
711 archival nature of Venti means the entire index will not fit in memory
712 because of the large number of blocks.  Combining these factors means
713 that the write performance of Venti will be limited to the random IO
714 performance of the index disk, which for current technology is a few
715 hundred accesses per second.  By striping the index across multiple
716 disks, however, we get a linear speedup.  This requires a sufficient
717 number of concurrent accesses, which we assure by buffering the writes
718 before accessing the index.
719 <p>
720
721 The prototype Venti server is implemented for the Plan 9 operating
722 system in about 10,000 lines of C. The server runs on a dedicated dual
723 550Mhz Pentium III processor system with 2 Gbyte of memory and is
724 accessed over a 100Mbs Ethernet network.  The data log is stored on a
725 500 Gbyte MaxTronic IDE Raid 5 Array and the index resides on a string
726 of 8 Seagate Cheetah 18XL 9 Gbyte SCSI drives.
727 <p>
728
729 <h1>6.  Performance</h1>
730 <p>
731
732 Table 1 gives the preliminary performance results for read and write
733 operations in a variety of situations.  For comparison, we include the
734 SCSI performance of the RAID array.  Although the performance is still
735 several times slower than directly accessing the disk, we believe the
736 results are promising and will improve as the system matures.
737 <p>
738 Table 1.  The performance of read and write operations in Mbytes/s for 8 Kbyte blocks.
739 <p>
740 <p>
741 <table align=center>
742 <tr>
743 <th></th>
744 <th width=150>sequential reads</th>
745 <th width=150>random reads</th>
746 <th width=150>virgin writes</th>
747 <th width=150>duplicate writes</th>
748 </tr>
749 <tr>
750 <td>uncached</td>
751 <td align=center>0.9</td>
752 <td align=center>0.4</td>
753 <td align=center>3.7</td>
754 <td align=center>5.6</td>
755 </tr>
756 <tr>
757 <td>index cache</td>
758 <td align=center>4.2</td>
759 <td align=center>0.7</td>
760 <td align=center>-</td>
761 <td align=center>6.2</td>
762 </tr>
763 <tr>
764 <td>block cache</td>
765 <td align=center>6.8</td>
766 <td align=center>-</td>
767 <td align=center>-</td>
768 <td align=center>6.5</td>
769 </tr>
770 <tr>
771 <td>raw raid</td>
772 <td align=center>14.8</td>
773 <td align=center>1.0</td>
774 <td align=center>12.4</td>
775 <td align=center>12.4</td>
776 </tr>
777 </table>
778 <p>
779
780
781 The uncached sequential read performance is particularly bad.  The
782 problem is that these sequential reads require a random read of the
783 index.  Without assistance from the client, the read operations are
784 not overlapped and do not benefit from the striping of the index.  One
785 possible solution is a form of read-ahead.  When reading a block from
786 the data log, it is feasible to also read several following blocks.
787 These extra blocks can be added to the caches without referencing the
788 index.  If blocks are read in the same order they were written to the
789 log, the latency of uncached index lookups will be avoided.  This
790 strategy should work well for streaming data such as multimedia files.
791 <p>
792
793 The basic assumption in Venti is that the growth in capacity of disks
794 combined with the removal of duplicate blocks and compression of their
795 contents enables a model in which it is not necessary to reclaim space
796 by deleting archival data.  To demonstrate why we believe this model
797 is practical, we present some statistics derived from a decade's use
798 of the Plan 9 file system.
799 <p>
800
801 The computing environment in which we work includes two Plan 9 file
802 servers named bootes and emelie.  Bootes was our primary file
803 repository from 1990 until 1997 at which point it was superseded by
804 emelie.  Over the life of these two file servers there have been 522
805 user accounts of which between 50 and 100 were active at any given
806 time.  The file servers have hosted numerous development projects and
807 also contain several large data sets including chess end games,
808 astronomical data, satellite imagery, and multimedia files.
809 <p>
810
811 Figure 6 depicts the size of the active file system as measured over
812 time by du, the space consumed on the jukebox, and the size of the
813 jukebox's data if it were to be stored on Venti.  The ratio of the
814 size of the archival data and the active file system is also given.
815 As can be seen, even without using Venti, the storage required to
816 implement the daily snapshots in Plan 9 is relatively modest, a result
817 of the block level incremental approach to generating a snapshot.
818 When the archival data is stored to Venti the cost of retaining the
819 snapshots is reduced significantly.  In the case of the emelie file
820 system, the size on Venti is only slightly larger than the active file
821 system; the cost of retaining the daily snapshots is almost zero.
822 Note that the amount of storage that Venti uses for the snapshots
823 would be the same even if more conventional methods were used to back
824 up the file system.  The Plan 9 approach to snapshots is not a
825 necessity, since Venti will remove duplicate blocks.
826 <p>
827 <img src="bootes.gif" ALT="storage sizes for bootes">
828 <img src="emelie.gif" ALT="storage sizes for emelie">
829 <img src="bootes2.gif" ALT="ratio of sizes for bootes">
830 <img src="emelie2.gif" ALT="ratio of sizes for emelie">
831 <p>
832 Figure 6. Graphs of the various sizes of two Plan 9 file servers.
833 <p>
834
835 When stored on Venti, the size of the jukebox data is reduced by three
836 factors: elimination of duplicate blocks, elimination of block
837 fragmentation, and compression of the block contents.  Table 2
838 presents the percent reduction for each of these factors.  Note,
839 bootes uses a 6 Kbyte block size while emelie uses 16 Kbyte, so the
840 effect of removing fragmentation is more significant on emelie.
841 <p>
842
843 The 10 year history of the two Plan 9 file servers may be of interest
844 to other researchers.  We have made available per-block information
845 including a hash of each block's contents, all the block pointers, and
846 most of the directory information.  The traces do not include the
847 actual contents of files nor the file names.  There is sufficient
848 information to reconstruct the structure of the file system and to
849 track the daily changes to this structure over time.  The traces are
850 available at http://www.cs.bell-labs.com/~seanq/p9trace.html.
851 <p>
852
853 Table 2.  The percentage reduction in the size of data stored on
854 Venti.
855 <p>
856 <table align=center>
857 <tr>
858 <th></th>
859 <th width=150>bootes</th>
860 <th width=150>emelie</th>
861 </tr>
862 <tr>
863 <td>Elimination of duplicates</td>
864 <td align=center>27.8%</td>
865 <td align=center>31.3%</td>
866 </tr>
867 <tr>
868 <td>Elimination of fragments</td>
869 <td align=center>10.2%</td>
870 <td align=center>25.4%</td>
871 </tr>
872 <tr>
873 <td>Data Compression</td>
874 <td align=center>33.8%</td>
875 <td align=center>54.1%</td>
876 </tr>
877 <tr>
878 <td>Total Reduction</td>
879 <td align=center>59.7%</td>
880 <td align=center>76.5%</td>
881 </tr>
882 </table>
883 <p>
884
885
886 <p>
887
888 <h1>7.  Reliability and Recovery</h1>
889 <p>
890
891 In concert with the development of the Venti prototype, we have built
892 a collection of tools for integrity checking and error recovery.
893 Example uses of these tools include: verifying the structure of an
894 arena, checking there is an index entry for every block in the data
895 log and vice versa, rebuilding the index from the data log, and
896 copying an arena to removable media.  These tools directly access the
897 storage devices containing the data log and index and are executed on
898 the server.
899 <p>
900
901 The directory structure at the end of each area enhances the
902 efficiency of many integrity and recovery operations, since it is
903 typically two orders of magnitude smaller than the arena, yet contains
904 most of the needed information.  The index checking utility, for
905 example, is implemented as a disk based sort of all the arena
906 directories, followed by a comparison between this sorted list and the
907 index.  Our prototype currently contains approximately 150 million
908 blocks using 250 Gbytes of storage.  An index check takes 2.2 hours,
909 which is significantly less than the 6 hours it takes to read all the
910 log data.
911 <p>
912
913 An additional integrity and recovery feature is the association of a
914 type identifier with every block.  This 8 bit identifier is included
915 with all client read and write operations and has the effect of
916 partitioning the server into multiple independent domains.  The idea
917 is that type indicates the interpretation of the data contained in the
918 block.  A client can use this feature, for example, to indicate that a
919 block is the root node for a tree of blocks.  Currently, the data
920 format associated with a type is left entirely to the client; the
921 server does not interpret the type other that to use it in conjunction
922 with a fingerprint as the key with which to index a block.
923 <p>
924
925 One use of the type identifier is to assist the administrator in
926 locating blocks for which a user has accidentally lost the
927 fingerprint.  Using a tool on the server, the data log can be scanned
928 for blocks that match specified criteria, including the block type,
929 the write time, and user identifier.  The type makes it relatively
930 simple to locate forgotten root blocks.  Future uses for the type
931 might include the ability for the server to determine the location of
932 fingerprints within a block, enabling the server to traverse the data
933 structures that have been stored.
934 <p>
935
936 By storing the data log on a RAID 5 disk array, our server is
937 protected against single drive failures.  Obviously, there are many
938 scenarios where this is not sufficient: multiple drives may fail,
939 there may be a fire in the machine room, the RAID firmware may contain
940 bugs, or the device may be stolen.
941 <p>
942
943 Additional protection could be obtained by using one or more off-site
944 mirrors for the server.  We have not yet implemented this strategy,
945 but the architecture of Venti makes this relatively simple.  A
946 background process on the server copies new blocks from the data log
947 to the mirrors.  This copying can be achieved using the Venti
948 protocol; the server is simply another client to the mirror.
949 <p>
950
951 Even mirroring may not be sufficient.  The implementation of Venti may
952 contain bugs that can be exploited to compromise the server.  An
953 automated attack may delete data on many servers simultaneously.
954 Storage devices that provide low level enforcement of a write-once
955 policy would provide protection for such an attack.  Write-once
956 read-many optical jukeboxes often provide such protection, but this is
957 not yet common for magnetic disk based storage systems.  We have thus
958 resorted to copying the sealed arenas onto removable media.
959 <p>
960
961 <h1>8.  Related Work</h1>
962 <p>
963
964 The Stanford Archival Vault [2] is a prototype archival repository
965 intended for digital libraries.  The archive consists of a write-once
966 log of digital objects (files) and several auxiliary indexes for
967 locating objects within the log.  Objects are identified by the hash
968 of their contents using a cyclic redundancy check (CRC).  Unlike
969 Venti, this system has no way to share data between objects that are
970 partially the same, or to build up complex data structures such as a
971 file system hierarchy.  Rather, the archive consists of a collection
972 of separate objects with a limited ability to group objects into sets.
973 <p>
974
975 On Venti, blocks are organized into more complex data structures by
976 creating hash-trees, an idea originally proposed by Merkle [11] for an
977 efficient digital signature scheme.
978 <p>
979
980 The approach to block retrieval in the Read-Only Secure File System
981 (SFSRO) [3] is comparable to Venti.  Blocks are identified by the Sha1
982 hash of their contents and this idea is applied recursively to build
983 up more complex structures.  The focus of this system is security, not
984 archival storage.  An administrator creates a digitally signed
985 database offline.  The database contains a public read-only file
986 system that can be published on multiple servers and efficiently and
987 securely accessed by clients.  SFSRO outperforms traditional methods
988 for providing data integrity between a client and a file server,
989 demonstrating an attractive property of hash-based addressing.
990 <p>
991
992 Given their similarities, it would be simple to implement SFSRO on top
993 of Venti.  The goal of Venti is to provide a flexible location for
994 archival storage and SFSRO is a good example of an application that
995 could use this capability.  In fact, using Venti would provide a
996 trivial solution to SFSRO's problem with stale NFS handles since data
997 is never deleted from Venti and thus a stale handle will never be
998 encountered.
999 <p>
1000
1001 Content-Derived Names [6] are another example of naming objects based
1002 on a secure hash of its contents.  This work addresses the issue of
1003 naming and managing the various binary software components, in
1004 particular shared libraries, that make up an application.
1005 <p>
1006
1007 The philosophy of the Elephant file system [18] is similar to Venti;
1008 large, cheap disks make it feasible to retain many versions of data.
1009 A feature of the Elephant system is the ability to specify a variety
1010 of data retention policies, which can be applied to individual files
1011 or directories.  These policies attempt to strike a balance between
1012 the costs and benefits of storing every version of a file.  In
1013 contrast, Venti focuses on the problem of how to store information
1014 after deciding that it should be retained in perpetuity.  A system
1015 such as the Elephant file system could incorporate Venti as the
1016 storage device for the permanent "landmark" versions of files, much as
1017 the Plan 9 file system will use Venti to archive snapshots.
1018 <p>
1019
1020 Self-Securing Storage [19] retains all versions of file system data in
1021 order to provide diagnosis and recovery from security breaches.  The
1022 system is implemented as a self-contained network service that exports
1023 an object-based disk interface, providing protection from compromise
1024 of the client operating system.  Old data is retained for a window of
1025 time and then deleted to reclaim storage.
1026 <p>
1027
1028 Venti provides many of the features of self-securing storage: the
1029 server is self-contained and accessed through a simple low-level
1030 protocol, malicious users cannot corrupt or delete existing data on
1031 the server, and old versions of data are available for inspection.  It
1032 is unlikely that a system would write every file system operation to
1033 Venti since storage is never reclaimed, but not deleting data removes
1034 the constraint that an intrusion must be detected within a limited
1035 window of time.  A hybrid approach might retain every version for some
1036 time and some versions for all time.  Venti could provide the
1037 long-term storage for such a hybrid.
1038 <p>
1039
1040 <h1>9.  Future Work</h1>
1041 <p>
1042
1043 Venti could be distributed across multiple machines; the approach of
1044 identifying data by a hash of its contents simplifies such an
1045 extension.  For example, the IO performance could be improved by
1046 replicating the server and using a simple load balancing algorithm.
1047 When storing or retrieving a block, clients direct the operation to a
1048 server based on a few bits of the fingerprint.  Such load balancing
1049 could even be hidden from the client application by interposing a
1050 proxy server that performs this operation on behalf of the client.
1051 <p>
1052
1053 Today, Venti provides little security.  After authenticating to the
1054 server, clients can read any block for which they know the
1055 fingerprint.  A fingerprint does act as a capability since the space
1056 of fingerprints is large and the Venti protocol does not include a
1057 means of enumerating the blocks on the server.  However, this
1058 protection is weak as a single root fingerprint enables access to an
1059 entire file tree and once a fingerprint is known, there is no way to
1060 restrict access to a particular user.  We are exploring ways of
1061 providing better access control.
1062 <p>
1063
1064 To date, the structures we have used for storing data on Venti break
1065 files into a series of fixed sized blocks.  Identical blocks are
1066 consolidated on Venti, but this consolidation will not occur if the
1067 data is shifted within the file or an application uses a different
1068 block size.  This limitation can be overcome using an adaptation of
1069 Manber's algorithm for finding similarities in files [9].  The idea is
1070 to break files into variable sized blocks based on the identification
1071 of anchor or break points, increasing the occurrence of duplicate
1072 blocks [12].  Such a strategy can be implemented in client
1073 applications with no change to the Venti server.
1074 <p>
1075
1076 A more detailed analysis of the decade of daily snapshots of the Plan
1077 9 file systems might be interesting.  The trace data we have made
1078 publicly available contains approximately the same information used
1079 for other studies of long term file activity [4].
1080 <p>
1081
1082 <h1>10.  Conclusion</h1>
1083 <p>
1084
1085 The approach of identifying a block by the Sha1 hash of its contents
1086 is well suited to archival storage.  The write-once model and the
1087 ability to coalesce duplicate copies of a block makes Venti a useful
1088 building block for a number of interesting storage applications.
1089 <p>
1090
1091 The large capacity of magnetic disks allows archival data to be
1092 retained and available on-line with performance that is comparable to
1093 conventional disks.  Stored on our prototype server is over a decade
1094 of daily snapshots of two major departmental file servers.  These
1095 snapshots are stored in a little over 200 Gbytes of disk space.
1096 Today, 100 Gbytes drives cost less than $300 and IDE RAID controllers
1097 are included on many motherboards.  A scaled down version of our
1098 server could provide archival storage for a home user at an attractive
1099 price.  Tomorrow, when terabyte disks can be had for the same price,
1100 it seems unlikely that archival data will be deleted to reclaim space.
1101 Venti provides an attractive approach to storing that data.
1102 <p>
1103
1104 <h1>11.  Acknowledgments</h1>
1105 <p>
1106
1107 This paper was improved by comments and suggestions from Peter Bosch,
1108 Eric Grosse, Lorenz Huelsbergen, Rob Pike, Ross Quinlan, and Cliff
1109 Young and six anonymous reviewers.  The paper's shepherd was Ethan L.
1110 Miller.  We thank them all for their help.
1111 <p>
1112
1113 <h1>12.  References</h1>
1114 <p>
1115
1116 [1] Ann Chervenak, Vivekenand Vellanki, and Zachary Kurmas.
1117 Protecting file systems: A survey of backup techniques.  In
1118 Proceedings Joint NASA and IEEE Mass Storage Conference, March 1998.
1119 <p>
1120
1121 [2] Arturo Crespo and Hector Garcia-Molina.  Archival storage for
1122 digital libraries.  In Proceedings of the 3rd ACM International
1123 Conference on Digital Libraries, 1998.
1124 <p>
1125
1126 [3] Kevin Fu, Frans Kaashoek, and David Mazières.  Fast and secure
1127 distributed read-only file system.  In Proceedings of the 4th
1128 Symposium on Operating Systems Design and Implementation, 2000.
1129 <p>
1130
1131 [4] Timothy J. Gibson, Ethan L. Miller, and Darrell D. E. Long.
1132 Long-term file activity and inter-reference patterns.  In Proceedings,
1133 24th International Conference on Technology Management and Performance
1134 Evaluation of Enterprise-Wide Information Systems, Computer
1135 Measurement Group, December 1998.
1136 <p>
1137
1138 [5] Dave Hitz, James Lau, and Michael Malcolm, File system design for
1139 an NFS file server appliance, In Proceedings of the Winter 1994 USENIX
1140 Conference, San Francisco, CA, January 1994.
1141 <p>
1142
1143 [6] J. K. Hollingsworth and E. L. Miller.  Using content-derived names
1144 for configuration management.  In Proceeding of the 1997 ACM Symposium
1145 on Software Reusability, Boston, May 1997.
1146 <p>
1147
1148 [7] John Howard, Michael Kazar, Sherri Menees, David Nichols, Mahadev
1149 Satyanarayanan, Robert Sidebotham, and Michael West.  Scale and
1150 performance in a distributed file system.  ACM Transactions on
1151 Computer Systems, 6(1):51-81, February 1988.
1152 <p>
1153
1154 [8] Norman C. Hutchinson, Stephen Manley, Mike Federwisch, Guy Harris,
1155 Dave Hitz, Steven Kleiman, and Sean O'Malley.  Logical vs.  physical
1156 file system backup.  In Proceedings of the 3rd USENIX Symposium on
1157 Operating Systems Design and Implementation (OSDI), 1999.
1158 <p>
1159
1160 [9] Udi Manber.  Finding similar files in a large file system.  In
1161 Proceedings of the Winter 1994 USENIX Conference, San Francisco, CA,
1162 January 1994.
1163 <p>
1164
1165 [10] Alfred J. Menezes, Paul C. van Oorschot, and Scott A. Vanstone.
1166 Handbook of Applied Cryptography.  CRC Press, 1996.
1167 <p>
1168
1169 [11] Ralph C. Merkle.  Protocols for public-key cryptosystems.  In
1170 Proceedings of the IEEE Symposium on Security and Privacy, pp.
1171 122-133, April 1980.
1172 <p>
1173
1174 [12] Athicha Muthitacharoen, Benjie Chen, and David Mazières.  A
1175 low-bandwidth network file system.  In Proceedings of the 18th
1176 Symposium on Operating Systems Principles, October 2001.
1177 <p>
1178
1179 [13] National Institute of Standards and Technology, FIPS 180-1.
1180 Secure Hash Standard.  US Department of Commerce, April 1995.
1181 <p>
1182
1183 [14] National Institute of Standards and Technology, Draft FIPS 180-2.
1184 Secure Hash Standard.  US Department of Commerce, May 2001.
1185 <p>
1186
1187 [15] Evi Nemeth, Garth Snyder, Scott Seebass, and Trent R. Hein.  UNIX
1188 System Administration Handbook 3rd Edition, Prentice Hall, 2001.
1189 <p>
1190
1191 [16] Rob Pike, Dave Presotto, Sean Dorward, Bob Flandrena, Ken
1192 Thompson, Howard Trickey, and Phil Winterbottom.  Plan 9 from Bell
1193 Labs, Computing Systems, Vol. 8, 3, pp.  221-254, Summer 1995.
1194 <p>
1195
1196 [17] Sean Quinlan.  A cache worm file system.  Software-Practice and
1197 Experience, Vol 21, 12, pp 1289-1299, December 1991.
1198 <p>
1199
1200 [18] Douglas S. Santry, Michael J. Feeley, Norman C. Hutchinson,
1201 Alistair C. Veitch, Ross W. Carton and Jacob Ofir.  Deciding when to
1202 forget in the Elephant file system.  In Proceedings of the 17th
1203 Symposium on Operating Systems Principles, December 12-15, 1999.
1204 <p>
1205
1206 [19] John.  D. Strunk, Garth R. Goodson, Michael L. Scheinholtz, Craig
1207 A.N. Soules, and Gregory R. Ganger.  Self-securing storage: protecting
1208 data in compromised systems.  In Proceedings of the 4th Symposium on
1209 Operating Systems Design and Implementation, October 2000.
1210 <p>
1211
1212 [20] D. A. Thompson and J. S. Best.  The future of magnetic data
1213 storage technology, IBM Journal of Research and Development, Vol 44,
1214 3, pp.  311-322, May 2000.
1215 <p>
1216
1217 [21] J. Ziv and A. Lempel.  A universal algorithm for sequential data
1218 compression, IEEE Trans.  Inform.  Theory, vol.  IT-23, pp.  337-343,
1219 May 1977.
1220 <p>
1221