Certain port Makefiles expect variables like ARCH or HAVE_GNOME to be set
[dragonfly.git] / share / doc / smm / 06.nfs / 2.t
1 .\" Copyright (c) 1993
2 .\"     The Regents of the University of California.  All rights reserved.
3 .\"
4 .\" This document is derived from software contributed to Berkeley by
5 .\" Rick Macklem at The University of Guelph.
6 .\"
7 .\" Redistribution and use in source and binary forms, with or without
8 .\" modification, are permitted provided that the following conditions
9 .\" are met:
10 .\" 1. Redistributions of source code must retain the above copyright
11 .\"    notice, this list of conditions and the following disclaimer.
12 .\" 2. Redistributions in binary form must reproduce the above copyright
13 .\"    notice, this list of conditions and the following disclaimer in the
14 .\"    documentation and/or other materials provided with the distribution.
15 .\" 3. All advertising materials mentioning features or use of this software
16 .\"    must display the following acknowledgement:
17 .\"     This product includes software developed by the University of
18 .\"     California, Berkeley and its contributors.
19 .\" 4. Neither the name of the University nor the names of its contributors
20 .\"    may be used to endorse or promote products derived from this software
21 .\"    without specific prior written permission.
22 .\"
34 .\"
35 .\"     @(#)2.t 8.1 (Berkeley) 6/8/93
36 .\"
37 .sh 1 "Not Quite NFS, Crash Tolerant Cache Consistency for NFS"
38 .pp
39 Not Quite NFS (NQNFS) is an NFS like protocol designed to maintain full cache
40 consistency between clients in a crash tolerant manner.
41 It is an adaptation of the NFS protocol such that the server supports both NFS
42 and NQNFS clients while maintaining full consistency between the server and
43 NQNFS clients.
44 This section borrows heavily from work done on Spritely-NFS [Srinivasan89],
45 but uses Leases [Gray89] to avoid the need to recover server state information
46 after a crash.
47 The reader is strongly encouraged to read these references before
48 trying to grasp the material presented here.
49 .sh 2 "Overview"
50 .pp
51 The protocol maintains cache consistency by using a somewhat
52 Sprite [Nelson88] like protocol,
53 but is based on short term leases\** instead of hard state information
54 about open files.
55 .(f
56 \** A lease is a ticket permitting an activity that is
57 valid until some expiry time.
58 .)f
59 The basic principal is that the protocol will disable client caching of a
60 file whenever that file is write shared\**.
61 .(f
62 \** Write sharing occurs when at least one client is modifying a file while
63 other client(s) are reading the file.
64 .)f
65 Whenever a client wishes to cache data for a file it must hold a valid lease.
66 There are three types of leases: read caching, write caching and non-caching.
67 The latter type requires that all file operations be done synchronously with
68 the server via. RPCs.
69 A read caching lease allows for client data caching, but no file modifications
70 may be done.
71 A write caching lease allows for client caching of writes,
72 but requires that all writes be pushed to the server when the lease expires.
73 If a client has dirty buffers\**
74 .(f
75 \** Cached write data is not yet pushed (written) to the server.
76 .)f
77 when a write cache lease has almost expired, it will attempt to
78 extend the lease but is required to push the dirty buffers if extension fails.
79 A client gets leases by either doing a \fBGetLease RPC\fR or by piggybacking
80 a \fBGetLease Request\fR onto another RPC. Piggybacking is supported for the
81 frequent RPCs Getattr, Setattr, Lookup, Readlink, Read, Write and Readdir
82 in an effort to minimize the number of \fBGetLease RPCs\fR required.
83 All leases are at the granularity of a file, since all NFS RPCs operate on
84 individual files and NFS has no intrinsic notion of a file hierarchy.
85 Directories, symbolic links and file attributes may be read cached but
86 are not write cached.
87 The exception here is the attribute file_size, which is updated during cached
88 writing on the client to reflect a growing file.
89 .pp
90 It is the server's responsibility to ensure that consistency is maintained
91 among the NQNFS clients by disabling client caching whenever a server file
92 operation would cause inconsistencies.
93 The possibility of inconsistencies occurs whenever a client has
94 a write caching lease and any other client,
95 or local operations on the server,
96 tries to access the file or when
97 a modify operation is attempted on a file being read cached by client(s).
98 At this time, the server sends an \fBeviction notice\fR to all clients holding
99 the lease and then waits for lease termination.
100 Lease termination occurs when a \fBvacated the premises\fR message has been
101 received from all the clients that have signed the lease or when the lease
102 expires via. timeout.
103 The message pair \fBeviction notice\fR and \fBvacated the premises\fR roughly
104 correspond to a Sprite server\(->client callback, but are not implemented as an
105 actual RPC, to avoid the server waiting indefinitely for a reply from a dead
106 client.
107 .pp
108 Server consistency checking can be viewed as issuing intrinsic leases for a
109 file operation for the duration of the operation only. For example, the
110 \fBCreate RPC\fR will get an intrinsic write lease on the directory in which
111 the file is being created, disabling client read caches for that directory.
112 .pp
113 By relegating this responsibility to the server, consistency between the
114 server and NQNFS clients is maintained when NFS clients are modifying the
115 file system as well.\**
116 .(f
117 \** The NFS clients will continue to be \fIapproximately\fR consistent with
118 the server.
119 .)f
120 .pp
121 The leases are issued as time intervals to avoid the requirement of time of day
122 clock synchronization. There are three important time constants known to
123 the server. The \fBmaximum_lease_term\fR sets an upper bound on lease duration.
124 The \fBclock_skew\fR is added to all lease terms on the server to correct for
125 differing clock speeds between the client and server and \fBwrite_slack\fR is
126 the number of seconds the server is willing to wait for a client with
127 an expired write caching lease to push dirty writes.
128 .pp
129 The server maintains a \fBmodify_revision\fR number for each file. It is
130 defined as a unsigned quadword integer that is never zero and that must
131 increase whenever the corresponding file is modified on the server.
132 It is used
133 by the client to determine whether or not cached data for the file is
134 stale.
135 Generating this value is easier said than done. The current implementation
136 uses the following technique, which is believed to be adequate.
137 The high order longword is stored in the ufs inode and is initialized to one
138 when an inode is first allocated.
139 The low order longword is stored in main memory only and is initialized to
140 zero when an inode is read in from disk.
141 When the file is modified for the first time within a given second of
142 wall clock time, the high order longword is incremented by one and
143 the low order longword reset to zero.
144 For subsequent modifications within the same second of wall clock
145 time, the low order longword is incremented. If the low order longword wraps
146 around to zero, the high order longword is incremented again.
147 Since the high order longword only increments once per second and the inode
148 is pushed to disk frequently during file modification, this implies
149 0 \(<= Current\(miDisk \(<= 5.
150 When the inode is read in from disk, 10
151 is added to the high order longword, which ensures that the quadword
152 is greater than any value it could have had before a crash.
153 This introduces apparent modifications every time the inode falls out of
154 the LRU inode cache, but this should only reduce the client caching performance
155 by a (hopefully) small margin.
156 .sh 2 "Crash Recovery and other Failure Scenarios"
157 .pp
158 The server must maintain the state of all the current leases held by clients.
159 The nice thing about short term leases is that maximum_lease_term seconds
160 after the server stops issuing leases, there are no current leases left.
161 As such, server crash recovery does not require any state recovery. After
162 rebooting, the server refuses to service any RPCs except for writes until
163 write_slack seconds after the last lease would have expired\**.
164 .(f
165 \** The last lease expiry time may be safely estimated as
166 "boottime+maximum_lease_term+clock_skew" for machines that cannot store
167 it in nonvolatile RAM.
168 .)f
169 By then, the server would not have any outstanding leases to recover the
170 state of and the clients have had at least write_slack seconds to push dirty
171 writes to the server and get the server sync'd up to date. After this, the
172 server simply services requests in a manner similar to NFS.
173 In an effort to minimize the effect of "recovery storms" [Baker91],
174 the server replies \fBtry_again_later\fR to the RPCs it is not
175 yet ready to service.
176 .pp
177 After a client crashes, the server may have to wait for a lease to timeout
178 before servicing a request if write sharing of a file with a cachable lease
179 on the client is about to occur.
180 As for the client, it simply starts up getting any leases it now needs. Any
181 outstanding leases for that client on the server prior to the crash will either be renewed or expire
182 via timeout.
183 .pp
184 Certain network partitioning failures are more problematic. If a client to
185 server network connection is severed just before a write caching lease expires,
186 the client cannot push the dirty writes to the server. After the lease expires
187 on the server, the server permits other clients to access the file with the
188 potential of getting stale data. Unfortunately I believe this failure scenario
189 is intrinsic in any delay write caching scheme unless the server is required to
190 wait \fBforever\fR for a client to regain contact\**.
191 .(f
192 \** Gray and Cheriton avoid this problem by using a \fBwrite through\fR policy.
193 .)f
194 Since the write caching lease has expired on the client,
195 it will sync up with the
196 server as soon as the network connection has been re-established.
197 .pp
198 There is another failure condition that can occur when the server is congested.
199 The worst case scenario would have the client pushing dirty writes to the server
200 but a large request queue on the server delays these writes for more than
201 \fBwrite_slack\fR seconds. It is hoped that a congestion control scheme using
202 the \fBtry_again_later\fR RPC reply after booting combined with
203 the following lease termination rule for write caching leases
204 can minimize the risk of this occurrence.
205 A write caching lease is only terminated on the server when there are have
206 been no writes to the file and the server has not been overloaded during
207 the previous write_slack seconds. The server has not been overloaded
208 is approximated by a test for sleeping nfsd(s) at the end of the write_slack
209 period.
210 .sh 2 "Server Disk Full"
211 .pp
212 There is a serious unresolved problem for delayed write caching with respect to
213 server disk space allocation.
214 When the disk on the file server is full, delayed write RPCs can fail
215 due to "out of space".
216 For NFS, this occurrence results in an error return from the close system
217 call on the file, since the dirty blocks are pushed on close.
218 Processes writing important files can check for this error return
219 to ensure that the file was written successfully.
220 For NQNFS, the dirty blocks are not pushed on close and as such the client
221 may not attempt the write RPC until after the process has done the close
222 which implies no error return from the close.
223 For the current prototype,
224 the only solution is to modify programs writing important
225 file(s) to call fsync and check for an error return from it instead of close.
226 .sh 2 "Protocol Details"
227 .pp
228 The protocol specification is identical to that of NFS [Sun89] except for
229 the following changes.
230 .ip \(bu
231 RPC Information
232 .(l
233         Program Number 300105
234         Version Number 1
235 .)l
236 .ip \(bu
237 Readdir_and_Lookup RPC
238 .(l
239         struct readdirlookargs {
240                 fhandle file;
241                 nfscookie cookie;
242                 unsigned count;
243                 unsigned duration;
244         };
246         struct entry {
247                 unsigned cachable;
248                 unsigned duration;
249                 modifyrev rev;
250                 fhandle entry_fh;
251                 nqnfs_fattr entry_attrib;
252                 unsigned fileid;
253                 filename name;
254                 nfscookie cookie;
255                 entry *nextentry;
256         };
258         union readdirlookres switch (stat status) {
259         case NFS_OK:
260                 struct {
261                         entry *entries;
262                         bool eof;
263                 } readdirlookok;
264         default:
265                 void;
266         };
268         readdirlookres
269         NQNFSPROC_READDIRLOOK(readdirlookargs) = 18;
270 .)l
271 Reads entries in a directory in a manner analogous to the NFSPROC_READDIR RPC
272 in NFS, but returns the file handle and attributes of each entry as well.
273 This allows the attribute and lookup caches to be primed.
274 .ip \(bu
275 Get Lease RPC
276 .(l
277         struct getleaseargs {
278                 fhandle file;
279                 cachetype readwrite;
280                 unsigned duration;
281         };
283         union getleaseres switch (stat status) {
284         case NFS_OK:
285                 bool cachable;
286                 unsigned duration;
287                 modifyrev rev;
288                 nqnfs_fattr attributes;
289         default:
290                 void;
291         };
293         getleaseres
294         NQNFSPROC_GETLEASE(getleaseargs) = 19;
295 .)l
296 Gets a lease for "file" valid for "duration" seconds from when the lease
297 was issued on the server\**.
298 .(f
299 \** To be safe, the client may only assume that the lease is valid
300 for ``duration'' seconds from when the RPC request was sent to the server.
301 .)f
302 The lease permits client caching if "cachable" is true.
303 The modify revision level and attributes for the file are also returned.
304 .ip \(bu
305 Eviction Message
306 .(l
307         void
308         NQNFSPROC_EVICTED (fhandle) = 21;
309 .)l
310 This message is sent from the server to the client. When the client receives
311 the message, it should flush data associated with the file represented by
312 "fhandle" from its caches and then send the \fBVacated Message\fR back to
313 the server. Flushing includes pushing any dirty writes via. write RPCs.
314 .ip \(bu
315 Vacated Message
316 .(l
317         void
318         NQNFSPROC_VACATED (fhandle) = 20;
319 .)l
320 This message is sent from the client to the server in response to the
321 \fBEviction Message\fR. See above.
322 .ip \(bu
323 Access RPC
324 .(l
325         struct accessargs {
326                 fhandle file;
327                 bool read_access;
328                 bool write_access;
329                 bool exec_access;
330         };
332         stat
333         NQNFSPROC_ACCESS(accessargs) = 22;
334 .)l
335 The access RPC does permission checking on the server for the given type
336 of access required by the client for the file.
337 Use of this RPC avoids accessibility problems caused by client->server uid
338 mapping.
339 .ip \(bu
340 Piggybacked Get Lease Request
341 .pp
342 The piggybacked get lease request is functionally equivalent to the Get Lease
343 RPC except that is attached to one of the other NQNFS RPC requests as follows.
344 A getleaserequest is prepended to all of the request arguments for NQNFS
345 and a getleaserequestres is inserted in all NFS result structures just after
346 the "stat" field only if "stat == NFS_OK".
347 .(l
348         union getleaserequest switch (cachetype type) {
349         case NQLREAD:
350         case NQLWRITE:
351                 unsigned duration;
352         default:
353                 void;
354         };
356         union getleaserequestres switch (cachetype type) {
357         case NQLREAD:
358         case NQLWRITE:
359                 bool cachable;
360                 unsigned duration;
361                 modifyrev rev;
362         default:
363                 void;
364         };
365 .)l
366 The get lease request applies to the file that the attached RPC operates on
367 and the file attributes remain in the same location as for the NFS RPC reply
368 structure.
369 .ip \(bu
370 Three additional "stat" values
371 .pp
372 Three additional values have been added to the enumerated type "stat".
373 .(l
374         NQNFS_EXPIRED=500
375         NQNFS_TRYLATER=501
376         NQNFS_AUTHERR=502
377 .)l
378 The "expired" value indicates that a lease has expired.
379 The "try later"
380 value is returned by the server when it wishes the client to retry the
381 RPC request after a short delay. It is used during crash recovery (Section 2)
382 and may also be useful for server congestion control.
383 The "authetication error" value is returned for kerberized mount points to
384 indicate that there is no cached authentication mapping and a Kerberos ticket
385 for the principal is required.
386 .sh 2 "Data Types"
387 .ip \(bu
388 cachetype
389 .(l
390         enum cachetype {
391                 NQLNONE = 0,
392                 NQLREAD = 1,
393                 NQLWRITE = 2
394         };
395 .)l
396 Type of lease requested. NQLNONE is used to indicate no piggybacked lease
397 request.
398 .ip \(bu
399 modifyrev
400 .(l
401         typedef unsigned hyper modifyrev;
402 .)l
403 The "modifyrev" is a unsigned quadword integer value that is never zero
404 and increases every time the corresponding file is modified on the server.
405 .ip \(bu
406 nqnfs_time
407 .(l
408         struct nqnfs_time {
409                 unsigned seconds;
410                 unsigned nano_seconds;
411         };
412 .)l
413 For NQNFS times are handled at nano second resolution instead of micro second
414 resolution for NFS.
415 .ip \(bu
416 nqnfs_fattr
417 .(l
418         struct nqnfs_fattr {
419                 ftype type;
420                 unsigned mode;
421                 unsigned nlink;
422                 unsigned uid;
423                 unsigned gid;
424                 unsigned hyper size;
425                 unsigned blocksize;
426                 unsigned rdev;
427                 unsigned hyper bytes;
428                 unsigned fsid;
429                 unsigned fileid;
430                 nqnfs_time atime;
431                 nqnfs_time mtime;
432                 nqnfs_time ctime;
433                 unsigned flags;
434                 unsigned generation;
435                 modifyrev rev;
436         };
437 .)l
438 The nqnfs_fattr structure is modified from the NFS fattr so that it stores
439 the file size as a 64bit quantity and the storage occupied as a 64bit number
440 of bytes. It also has fields added for the 4.4BSD va_flags and va_gen fields
441 as well as the file's modify rev level.
442 .ip \(bu
443 nqnfs_sattr
444 .(l
445         struct nqnfs_sattr {
446                 unsigned mode;
447                 unsigned uid;
448                 unsigned gid;
449                 unsigned hyper size;
450                 nqnfs_time atime;
451                 nqnfs_time mtime;
452                 unsigned flags;
453                 unsigned rdev;
454         };
455 .)l
456 The nqnfs_sattr structure is modified from the NFS sattr structure in the
457 same manner as fattr.
458 .lp
459 The arguments to several of the NFS RPCs have been modified as well. Mostly,
460 these are minor changes to use 64bit file offsets or similar. The modified
461 argument structures follow.
462 .ip \(bu
463 Lookup RPC
464 .(l
465         struct lookup_diropargs {
466                 unsigned duration;
467                 fhandle dir;
468                 filename name;
469         };
471         union lookup_diropres switch (stat status) {
472         case NFS_OK:
473                 struct {
474                         union getleaserequestres lookup_lease;
475                         fhandle file;
476                         nqnfs_fattr attributes;
477                 } lookup_diropok;
478         default:
479                 void;
480         };
482 .)l
483 The additional "duration" argument tells the server to get a lease for the
484 name being looked up if it is non-zero and the lease is specified
485 in "lookup_lease".
486 .ip \(bu
487 Read RPC
488 .(l
489         struct nqnfs_readargs {
490                 fhandle file;
491                 unsigned hyper offset;
492                 unsigned count;
493         };
494 .)l
495 .ip \(bu
496 Write RPC
497 .(l
498         struct nqnfs_writeargs {
499                 fhandle file;
500                 unsigned hyper offset;
501                 bool append;
502                 nfsdata data;
503         };
504 .)l
505 The "append" argument is true for apeend only write operations.
506 .ip \(bu
507 Get Filesystem Attributes RPC
508 .(l
509         union nqnfs_statfsres (stat status) {
510         case NFS_OK:
511                 struct {
512                         unsigned tsize;
513                         unsigned bsize;
514                         unsigned blocks;
515                         unsigned bfree;
516                         unsigned bavail;
517                         unsigned files;
518                         unsigned files_free;
519                 } info;
520         default:
521                 void;
522         };
523 .)l
524 The "files" field is the number of files in the file system and the "files_free"
525 is the number of additional files that can be created.
526 .sh 1 "Summary"
527 .pp
528 The configuration and tuning of an NFS environment tends to be a bit of a
529 mystic art, but hopefully this paper along with the man pages and other
530 reading will be helpful. Good Luck.