LINUX: Use afs_convert_code in afs_notify_change
[openafs.git] / src / afs / LINUX24 / osi_vnodeops.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux specific vnodeops. Also includes the glue routines required to call
12  * AFS vnodeops.
13  *
14  * So far the only truly scary part is that Linux relies on the inode cache
15  * to be up to date. Don't you dare break a callback and expect an fstat
16  * to give you meaningful information. This appears to be fixed in the 2.1
17  * development kernels. As it is we can fix this now by intercepting the 
18  * stat calls.
19  */
20
21 #include <afsconfig.h>
22 #include "afs/param.h"
23
24
25 #include "afs/sysincludes.h"
26 #include "afsincludes.h"
27 #include "afs/afs_stats.h"
28 #include "h/mm.h"
29 #ifdef HAVE_MM_INLINE_H
30 #include "h/mm_inline.h"
31 #endif
32 #include "h/pagemap.h"
33 #if defined(AFS_LINUX24_ENV)
34 #include "h/smp_lock.h"
35 #endif
36 #include "afs/lock.h"
37 #include "afs/afs_bypasscache.h"
38
39 #ifdef pgoff2loff
40 #define pageoff(pp) pgoff2loff((pp)->index)
41 #else
42 #define pageoff(pp) pp->offset
43 #endif
44
45 #ifndef MAX_ERRNO
46 #define MAX_ERRNO 1000L
47 #endif
48
49 extern struct vcache *afs_globalVp;
50 #if defined(AFS_LINUX24_ENV)
51 /* Some uses of BKL are perhaps not needed for bypass or memcache--
52  * why don't we try it out? */
53 extern struct afs_cacheOps afs_UfsCacheOps;
54 #define maybe_lock_kernel()                     \
55     do {                                               \
56         if(afs_cacheType == &afs_UfsCacheOps)          \
57             lock_kernel();                             \
58     } while(0);
59
60
61 #define maybe_unlock_kernel()                   \
62     do {                                               \
63         if(afs_cacheType == &afs_UfsCacheOps)          \
64             unlock_kernel();                           \
65     } while(0);
66 #endif /* AFS_LINUX24_ENV */
67
68
69 /* This function converts a positive error code from AFS into a negative
70  * code suitable for passing into the Linux VFS layer. It checks that the
71  * error code is within the permissable bounds for the ERR_PTR mechanism.
72  *
73  * _All_ error codes which come from the AFS layer should be passed through
74  * this function before being returned to the kernel.
75  */
76
77 static inline int afs_convert_code(int code) {
78     if ((code >= 0) && (code <= MAX_ERRNO))
79         return -code;
80     else
81         return -EIO;
82 }
83
84 /* Linux doesn't require a credp for many functions, and crref is an expensive
85  * operation. This helper function avoids obtaining it for VerifyVCache calls
86  */
87
88 static inline int afs_linux_VerifyVCache(struct vcache *avc, cred_t **retcred) {
89     cred_t *credp = NULL;
90     struct vrequest treq;
91     int code;
92
93     if (avc->f.states & CStatd) {
94         if (retcred)
95             *retcred = NULL;
96         return 0;
97     }
98
99     credp = crref();
100
101     code = afs_InitReq(&treq, credp);
102     if (code == 0)
103         code = afs_VerifyVCache2(avc, &treq);
104
105     if (retcred != NULL)
106         *retcred = credp;
107     else
108         crfree(credp);
109
110     return afs_convert_code(code);
111 }
112
113 static ssize_t
114 afs_linux_read(struct file *fp, char *buf, size_t count, loff_t * offp)
115 {
116     ssize_t code = 0;
117     struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
118 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
119     afs_size_t isize, offindex;
120 #endif
121
122     AFS_GLOCK();
123     afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
124                ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
125                99999);
126     code = afs_linux_VerifyVCache(vcp, NULL);
127
128     if (code == 0) {
129 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
130         isize = (i_size_read(fp->f_mapping->host) - 1) >> PAGE_CACHE_SHIFT;
131         offindex = *offp >> PAGE_CACHE_SHIFT;
132         if(offindex > isize) {
133             code=0;
134             goto done;
135         }
136 #endif
137         /* Linux's FlushPages implementation doesn't ever use credp,
138          * so we optimise by not using it */
139         osi_FlushPages(vcp, NULL);      /* ensure stale pages are gone */
140         AFS_GUNLOCK();
141 #ifdef HAVE_LINUX_DO_SYNC_READ
142         code = do_sync_read(fp, buf, count, offp);
143 #else
144         code = generic_file_read(fp, buf, count, offp);
145 #endif
146         AFS_GLOCK();
147     }
148
149     afs_Trace4(afs_iclSetp, CM_TRACE_READOP, ICL_TYPE_POINTER, vcp,
150                ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
151                code);
152 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
153 done:
154 #endif
155     AFS_GUNLOCK();
156     return code;
157 }
158
159
160 /* Now we have integrated VM for writes as well as reads. generic_file_write
161  * also takes care of re-positioning the pointer if file is open in append
162  * mode. Call fake open/close to ensure we do writes of core dumps.
163  */
164 static ssize_t
165 afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
166 {
167     ssize_t code = 0;
168     struct vcache *vcp = VTOAFS(fp->f_dentry->d_inode);
169     cred_t *credp;
170
171     AFS_GLOCK();
172
173     afs_Trace4(afs_iclSetp, CM_TRACE_WRITEOP, ICL_TYPE_POINTER, vcp,
174                ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
175                (fp->f_flags & O_APPEND) ? 99998 : 99999);
176
177     code = afs_linux_VerifyVCache(vcp, &credp);
178
179     ObtainWriteLock(&vcp->lock, 529);
180     afs_FakeOpen(vcp);
181     ReleaseWriteLock(&vcp->lock);
182     if (code == 0) {
183             AFS_GUNLOCK();
184 #ifdef DO_SYNC_READ
185             code = do_sync_write(fp, buf, count, offp);
186 #else
187             code = generic_file_write(fp, buf, count, offp);
188 #endif
189             AFS_GLOCK();
190     }
191
192     ObtainWriteLock(&vcp->lock, 530);
193
194     if (vcp->execsOrWriters == 1 && !credp)
195       credp = crref();
196
197     afs_FakeClose(vcp, credp);
198     ReleaseWriteLock(&vcp->lock);
199
200     afs_Trace4(afs_iclSetp, CM_TRACE_WRITEOP, ICL_TYPE_POINTER, vcp,
201                ICL_TYPE_OFFSET, offp, ICL_TYPE_INT32, count, ICL_TYPE_INT32,
202                code);
203
204     if (credp)
205       crfree(credp);
206     AFS_GUNLOCK();
207     return code;
208 }
209
210 extern int BlobScan(struct dcache * afile, afs_int32 ablob);
211
212 /* This is a complete rewrite of afs_readdir, since we can make use of
213  * filldir instead of afs_readdir_move. Note that changes to vcache/dcache
214  * handling and use of bulkstats will need to be reflected here as well.
215  */
216 static int
217 afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
218 {
219     struct vcache *avc = VTOAFS(FILE_INODE(fp));
220     struct vrequest treq;
221     struct dcache *tdc;
222     int code;
223     int offset;
224     int dirpos;
225     struct DirEntry *de;
226     ino_t ino;
227     int len;
228     afs_size_t origOffset, tlen;
229     cred_t *credp = crref();
230     struct afs_fakestat_state fakestat;
231
232     AFS_GLOCK();
233     AFS_STATCNT(afs_readdir);
234
235     code = afs_convert_code(afs_InitReq(&treq, credp));
236     crfree(credp);
237     if (code)
238         goto out1;
239
240     afs_InitFakeStat(&fakestat);
241     code = afs_convert_code(afs_EvalFakeStat(&avc, &fakestat, &treq));
242     if (code)
243         goto out;
244
245     /* update the cache entry */
246   tagain:
247     code = afs_convert_code(afs_VerifyVCache2(avc, &treq));
248     if (code)
249         goto out;
250
251     /* get a reference to the entire directory */
252     tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
253     len = tlen;
254     if (!tdc) {
255         code = -ENOENT;
256         goto out;
257     }
258     ObtainSharedLock(&avc->lock, 810);
259     UpgradeSToWLock(&avc->lock, 811);
260     ObtainReadLock(&tdc->lock);
261     /*
262      * Make sure that the data in the cache is current. There are two
263      * cases we need to worry about:
264      * 1. The cache data is being fetched by another process.
265      * 2. The cache data is no longer valid
266      */
267     while ((avc->f.states & CStatd)
268            && (tdc->dflags & DFFetching)
269            && hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
270         ReleaseReadLock(&tdc->lock);
271         ReleaseSharedLock(&avc->lock);
272         afs_osi_Sleep(&tdc->validPos);
273         ObtainSharedLock(&avc->lock, 812);
274         ObtainReadLock(&tdc->lock);
275     }
276     if (!(avc->f.states & CStatd)
277         || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
278         ReleaseReadLock(&tdc->lock);
279         ReleaseSharedLock(&avc->lock);
280         afs_PutDCache(tdc);
281         goto tagain;
282     }
283
284     /* Set the readdir-in-progress flag, and downgrade the lock
285      * to shared so others will be able to acquire a read lock.
286      */
287     avc->f.states |= CReadDir;
288     avc->dcreaddir = tdc;
289     avc->readdir_pid = MyPidxx2Pid(MyPidxx);
290     ConvertWToSLock(&avc->lock);
291
292     /* Fill in until we get an error or we're done. This implementation
293      * takes an offset in units of blobs, rather than bytes.
294      */
295     code = 0;
296     offset = (int) fp->f_pos;
297     while (1) {
298         dirpos = BlobScan(tdc, offset);
299         if (!dirpos)
300             break;
301
302         code = afs_dir_GetBlob(tdc, dirpos, &entry);
303         if (code)
304             break;
305         de = (struct DirEntry *)entry.data;
306
307         ino = afs_calc_inum(avc->f.fid.Cell, avc->f.fid.Fid.Volume,
308                             ntohl(de->fid.vnode));
309
310         if (de->name)
311             len = strlen(de->name);
312         else {
313             printf("afs_linux_readdir: afs_dir_GetBlob failed, null name (inode %lx, dirpos %d)\n", 
314                    (unsigned long)&tdc->f.inode, dirpos);
315             DRelease(de, 0);
316             ReleaseSharedLock(&avc->lock);
317             afs_PutDCache(tdc);
318             code = -ENOENT;
319             goto out;
320         }
321
322         /* filldir returns -EINVAL when the buffer is full. */
323 #if (defined(AFS_LINUX24_ENV) || defined(pgoff2loff)) && defined(DECLARE_FSTYPE)
324         {
325             unsigned int type = DT_UNKNOWN;
326             struct VenusFid afid;
327             struct vcache *tvc;
328             int vtype;
329             afid.Cell = avc->f.fid.Cell;
330             afid.Fid.Volume = avc->f.fid.Fid.Volume;
331             afid.Fid.Vnode = ntohl(de->fid.vnode);
332             afid.Fid.Unique = ntohl(de->fid.vunique);
333             if ((avc->f.states & CForeign) == 0 && (ntohl(de->fid.vnode) & 1)) {
334                 type = DT_DIR;
335             } else if ((tvc = afs_FindVCache(&afid, 0, 0))) {
336                 if (tvc->mvstat) {
337                     type = DT_DIR;
338                 } else if (((tvc->f.states) & (CStatd | CTruth))) {
339                     /* CTruth will be set if the object has
340                      *ever* been statd */
341                     vtype = vType(tvc);
342                     if (vtype == VDIR)
343                         type = DT_DIR;
344                     else if (vtype == VREG)
345                         type = DT_REG;
346                     /* Don't do this until we're sure it can't be a mtpt */
347                     /* else if (vtype == VLNK)
348                      * type=DT_LNK; */
349                     /* what other types does AFS support? */
350                 }
351                 /* clean up from afs_FindVCache */
352                 afs_PutVCache(tvc);
353             }
354             /* 
355              * If this is NFS readdirplus, then the filler is going to
356              * call getattr on this inode, which will deadlock if we're
357              * holding the GLOCK.
358              */
359             AFS_GUNLOCK();
360             code = (*filldir) (dirbuf, de->name, len, offset, ino, type);
361             AFS_GLOCK();
362         }
363 #else
364         code = (*filldir) (dirbuf, de->name, len, offset, ino);
365 #endif
366         DRelease(de, 0);
367         if (code)
368             break;
369         offset = dirpos + 1 + ((len + 16) >> 5);
370     }
371     /* If filldir didn't fill in the last one this is still pointing to that
372      * last attempt.
373      */
374     fp->f_pos = (loff_t) offset;
375
376     ReleaseReadLock(&tdc->lock);
377     afs_PutDCache(tdc);
378     UpgradeSToWLock(&avc->lock, 813);
379     avc->f.states &= ~CReadDir;
380     avc->dcreaddir = 0;
381     avc->readdir_pid = 0;
382     ReleaseSharedLock(&avc->lock);
383     code = 0;
384
385 out:
386     afs_PutFakeStat(&fakestat);
387 out1:
388     AFS_GUNLOCK();
389     return code;
390 }
391
392
393 /* in afs_pioctl.c */
394 extern int afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
395                       unsigned long arg);
396
397 #if defined(HAVE_UNLOCKED_IOCTL) || defined(HAVE_COMPAT_IOCTL)
398 static long afs_unlocked_xioctl(struct file *fp, unsigned int com,
399                                unsigned long arg) {
400     return afs_xioctl(FILE_INODE(fp), fp, com, arg);
401
402 }
403 #endif
404
405
406 static int
407 afs_linux_mmap(struct file *fp, struct vm_area_struct *vmap)
408 {
409     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
410     int code;
411
412     AFS_GLOCK();
413 #if defined(AFS_LINUX24_ENV)
414     afs_Trace3(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vcp,
415                ICL_TYPE_POINTER, vmap->vm_start, ICL_TYPE_INT32,
416                vmap->vm_end - vmap->vm_start);
417 #else
418     afs_Trace4(afs_iclSetp, CM_TRACE_GMAP, ICL_TYPE_POINTER, vcp,
419                ICL_TYPE_POINTER, vmap->vm_start, ICL_TYPE_INT32,
420                vmap->vm_end - vmap->vm_start, ICL_TYPE_INT32,
421                vmap->vm_offset);
422 #endif
423
424     /* get a validated vcache entry */
425     code = afs_linux_VerifyVCache(vcp, NULL);
426
427     /* Linux's Flushpage implementation doesn't use credp, so optimise
428      * our code to not need to crref() it */
429     osi_FlushPages(vcp, NULL); /* ensure stale pages are gone */
430     AFS_GUNLOCK();
431     code = generic_file_mmap(fp, vmap);
432     AFS_GLOCK();
433     if (!code)
434         vcp->f.states |= CMAPPED;
435
436     AFS_GUNLOCK();
437     return code;
438 }
439
440 static int
441 afs_linux_open(struct inode *ip, struct file *fp)
442 {
443     struct vcache *vcp = VTOAFS(ip);
444     cred_t *credp = crref();
445     int code;
446
447 #ifdef AFS_LINUX24_ENV
448     maybe_lock_kernel();
449 #endif
450     AFS_GLOCK();
451     code = afs_open(&vcp, fp->f_flags, credp);
452     AFS_GUNLOCK();
453 #ifdef AFS_LINUX24_ENV
454     maybe_unlock_kernel();
455 #endif
456
457     crfree(credp);
458     return afs_convert_code(code);
459 }
460
461 static int
462 afs_linux_release(struct inode *ip, struct file *fp)
463 {
464     struct vcache *vcp = VTOAFS(ip);
465     cred_t *credp = crref();
466     int code = 0;
467
468 #ifdef AFS_LINUX24_ENV
469     maybe_lock_kernel();
470 #endif
471     AFS_GLOCK();
472     code = afs_close(vcp, fp->f_flags, credp);
473     AFS_GUNLOCK();
474 #ifdef AFS_LINUX24_ENV
475     maybe_unlock_kernel();
476 #endif
477
478     crfree(credp);
479     return afs_convert_code(code);
480 }
481
482 static int
483 #if defined(AFS_LINUX24_ENV)
484 afs_linux_fsync(struct file *fp, struct dentry *dp, int datasync)
485 #else
486 afs_linux_fsync(struct file *fp, struct dentry *dp)
487 #endif
488 {
489     int code;
490     struct inode *ip = FILE_INODE(fp);
491     cred_t *credp = crref();
492
493 #ifdef AFS_LINUX24_ENV
494     maybe_lock_kernel();
495 #endif
496     AFS_GLOCK();
497     code = afs_fsync(VTOAFS(ip), credp);
498     AFS_GUNLOCK();
499 #ifdef AFS_LINUX24_ENV
500     maybe_unlock_kernel();
501 #endif
502     crfree(credp);
503     return afs_convert_code(code);
504
505 }
506
507
508 static int
509 afs_linux_lock(struct file *fp, int cmd, struct file_lock *flp)
510 {
511     int code = 0;
512     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
513     cred_t *credp = crref();
514     struct AFS_FLOCK flock;
515 #if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
516     struct file_lock conflict;
517 #elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
518     struct file_lock *conflict;
519 #endif
520     
521     /* Convert to a lock format afs_lockctl understands. */
522     memset(&flock, 0, sizeof(flock));
523     flock.l_type = flp->fl_type;
524     flock.l_pid = flp->fl_pid;
525     flock.l_whence = 0;
526     flock.l_start = flp->fl_start;
527     if (flp->fl_end == OFFSET_MAX)
528         flock.l_len = 0; /* Lock to end of file */
529     else
530         flock.l_len = flp->fl_end - flp->fl_start + 1;
531
532     /* Safe because there are no large files, yet */
533 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
534     if (cmd == F_GETLK64)
535         cmd = F_GETLK;
536     else if (cmd == F_SETLK64)
537         cmd = F_SETLK;
538     else if (cmd == F_SETLKW64)
539         cmd = F_SETLKW;
540 #endif /* F_GETLK64 && F_GETLK != F_GETLK64 */
541
542     AFS_GLOCK();
543     code = afs_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
544     AFS_GUNLOCK();
545
546 #ifdef AFS_LINUX24_ENV
547     if ((code == 0 || flp->fl_type == F_UNLCK) && 
548         (cmd == F_SETLK || cmd == F_SETLKW)) {
549 # ifdef POSIX_LOCK_FILE_WAIT_ARG
550         code = posix_lock_file(fp, flp, 0);
551 # else
552         flp->fl_flags &=~ FL_SLEEP;
553         code = posix_lock_file(fp, flp);
554 # endif 
555         if (code && flp->fl_type != F_UNLCK) {
556             struct AFS_FLOCK flock2;
557             flock2 = flock;
558             flock2.l_type = F_UNLCK;
559             AFS_GLOCK();
560             afs_lockctl(vcp, &flock2, F_SETLK, credp);
561             AFS_GUNLOCK();
562         }
563     }
564     /* If lockctl says there are no conflicting locks, then also check with the
565      * kernel, as lockctl knows nothing about byte range locks
566      */
567     if (code == 0 && cmd == F_GETLK && flock.l_type == F_UNLCK) {
568 # if defined(POSIX_TEST_LOCK_CONFLICT_ARG)
569         if (posix_test_lock(fp, flp, &conflict)) {
570             locks_copy_lock(flp, &conflict);
571             flp->fl_type = F_UNLCK;
572             crfree(credp);
573             return 0;
574         }
575 # elif defined(POSIX_TEST_LOCK_RETURNS_CONFLICT)
576         if ((conflict = posix_test_lock(fp, flp))) {
577             locks_copy_lock(flp, conflict);
578             flp->fl_type = F_UNLCK;
579             crfree(credp);
580             return 0;
581         }
582 # else
583         posix_test_lock(fp, flp);
584         /* If we found a lock in the kernel's structure, return it */
585         if (flp->fl_type != F_UNLCK) {
586             crfree(credp);
587             return 0;
588         }
589 # endif
590     }
591     
592 #endif
593     /* Convert flock back to Linux's file_lock */
594     flp->fl_type = flock.l_type;
595     flp->fl_pid = flock.l_pid;
596     flp->fl_start = flock.l_start;
597     if (flock.l_len == 0)
598         flp->fl_end = OFFSET_MAX; /* Lock to end of file */
599     else
600         flp->fl_end = flock.l_start + flock.l_len - 1;
601
602     crfree(credp);
603     return code;
604 }
605
606 #ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
607 static int
608 afs_linux_flock(struct file *fp, int cmd, struct file_lock *flp) {
609     int code = 0;
610     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
611     cred_t *credp = crref();
612     struct AFS_FLOCK flock;
613     /* Convert to a lock format afs_lockctl understands. */
614     memset(&flock, 0, sizeof(flock));
615     flock.l_type = flp->fl_type;
616     flock.l_pid = flp->fl_pid;
617     flock.l_whence = 0;
618     flock.l_start = 0;
619     flock.l_len = 0;
620
621     /* Safe because there are no large files, yet */
622 #if defined(F_GETLK64) && (F_GETLK != F_GETLK64)
623     if (cmd == F_GETLK64)
624         cmd = F_GETLK;
625     else if (cmd == F_SETLK64)
626         cmd = F_SETLK;
627     else if (cmd == F_SETLKW64)
628         cmd = F_SETLKW;
629 #endif /* F_GETLK64 && F_GETLK != F_GETLK64 */
630
631     AFS_GLOCK();
632     code = afs_convert_code(afs_lockctl(vcp, &flock, cmd, credp));
633     AFS_GUNLOCK();
634
635     if ((code == 0 || flp->fl_type == F_UNLCK) && 
636         (cmd == F_SETLK || cmd == F_SETLKW)) {
637         flp->fl_flags &=~ FL_SLEEP;
638         code = flock_lock_file_wait(fp, flp);
639         if (code && flp->fl_type != F_UNLCK) {
640             struct AFS_FLOCK flock2;
641             flock2 = flock;
642             flock2.l_type = F_UNLCK;
643             AFS_GLOCK();
644             afs_lockctl(vcp, &flock2, F_SETLK, credp);
645             AFS_GUNLOCK();
646         }
647     }
648     /* Convert flock back to Linux's file_lock */
649     flp->fl_type = flock.l_type;
650     flp->fl_pid = flock.l_pid;
651
652     crfree(credp);
653     return code;
654 }
655 #endif
656
657 /* afs_linux_flush
658  * essentially the same as afs_fsync() but we need to get the return
659  * code for the sys_close() here, not afs_linux_release(), so call
660  * afs_StoreAllSegments() with AFS_LASTSTORE
661  */
662 static int
663 #if defined(FOP_FLUSH_TAKES_FL_OWNER_T)
664 afs_linux_flush(struct file *fp, fl_owner_t id)
665 #else
666 afs_linux_flush(struct file *fp)
667 #endif
668 {
669     struct vrequest treq;
670     struct vcache *vcp;
671     cred_t *credp;
672     int code;
673     int bypasscache;
674
675     AFS_GLOCK();
676
677     if ((fp->f_flags & O_ACCMODE) == O_RDONLY) { /* readers dont flush */
678         AFS_GUNLOCK();
679         return 0;
680     }
681
682     AFS_DISCON_LOCK();
683
684     credp = crref();
685     vcp = VTOAFS(FILE_INODE(fp));
686
687     code = afs_InitReq(&treq, credp);
688     if (code)
689         goto out;
690         /* If caching is bypassed for this file, or globally, just return 0 */
691         if(cache_bypass_strategy == ALWAYS_BYPASS_CACHE)
692                 bypasscache = 1;
693         else {
694                 ObtainReadLock(&vcp->lock);
695                 if(vcp->cachingStates & FCSBypass)
696                         bypasscache = 1;
697                 ReleaseReadLock(&vcp->lock);
698         }
699         if(bypasscache) {
700             /* future proof: don't rely on 0 return from afs_InitReq */
701             code = 0; goto out;
702         }
703
704     ObtainSharedLock(&vcp->lock, 535);
705     if ((vcp->execsOrWriters > 0) && (file_count(fp) == 1)) {
706         UpgradeSToWLock(&vcp->lock, 536);
707         if (!AFS_IS_DISCONNECTED) {
708                 code = afs_StoreAllSegments(vcp,
709                                 &treq,
710                                 AFS_SYNC | AFS_LASTSTORE);
711         } else {
712                 afs_DisconAddDirty(vcp, VDisconWriteOsiFlush, 1);
713         }
714         ConvertWToSLock(&vcp->lock);
715     }
716     code = afs_CheckCode(code, &treq, 54);
717     ReleaseSharedLock(&vcp->lock);
718
719 out:
720     AFS_DISCON_UNLOCK();
721     AFS_GUNLOCK();
722
723     crfree(credp);
724     return afs_convert_code(code);
725 }
726
727 #if !defined(AFS_LINUX24_ENV)
728 /* Not allowed to directly read a directory. */
729 ssize_t
730 afs_linux_dir_read(struct file * fp, char *buf, size_t count, loff_t * ppos)
731 {
732     return -EISDIR;
733 }
734 #endif
735
736
737
738 struct file_operations afs_dir_fops = {
739 #if !defined(AFS_LINUX24_ENV)
740   .read =       afs_linux_dir_read,
741   .lock =       afs_linux_lock,
742   .fsync =      afs_linux_fsync,
743 #else
744   .read =       generic_read_dir,
745 #endif
746   .readdir =    afs_linux_readdir,
747 #ifdef HAVE_UNLOCKED_IOCTL
748   .unlocked_ioctl = afs_unlocked_xioctl,
749 #else
750   .ioctl =      afs_xioctl,
751 #endif
752 #ifdef HAVE_COMPAT_IOCTL
753   .compat_ioctl = afs_unlocked_xioctl,
754 #endif
755   .open =       afs_linux_open,
756   .release =    afs_linux_release,
757 };
758
759 struct file_operations afs_file_fops = {
760   .read =       afs_linux_read,
761   .write =      afs_linux_write,
762 #ifdef HAVE_LINUX_GENERIC_FILE_AIO_READ
763   .aio_read =   generic_file_aio_read,
764   .aio_write =  generic_file_aio_write,
765 #endif
766 #ifdef HAVE_UNLOCKED_IOCTL
767   .unlocked_ioctl = afs_unlocked_xioctl,
768 #else
769   .ioctl =      afs_xioctl,
770 #endif
771 #ifdef HAVE_COMPAT_IOCTL
772   .compat_ioctl = afs_unlocked_xioctl,
773 #endif
774   .mmap =       afs_linux_mmap,
775   .open =       afs_linux_open,
776   .flush =      afs_linux_flush,
777   .release =    afs_linux_release,
778   .fsync =      afs_linux_fsync,
779   .lock =       afs_linux_lock,
780 #ifdef STRUCT_FILE_OPERATIONS_HAS_FLOCK
781   .flock =      afs_linux_flock,
782 #endif
783 };
784
785
786 /**********************************************************************
787  * AFS Linux dentry operations
788  **********************************************************************/
789
790 /* check_bad_parent() : Checks if this dentry's vcache is a root vcache
791  * that has its mvid (parent dir's fid) pointer set to the wrong directory
792  * due to being mounted in multiple points at once. If so, check_bad_parent()
793  * calls afs_lookup() to correct the vcache's mvid, as well as the volume's
794  * dotdotfid and mtpoint fid members.
795  * Parameters:
796  *   dp - dentry to be checked.
797  * Return Values:
798  *   None.
799  * Sideeffects:
800  *   This dentry's vcache's mvid will be set to the correct parent directory's
801  *   fid.
802  *   This root vnode's volume will have its dotdotfid and mtpoint fids set
803  *   to the correct parent and mountpoint fids.
804  */
805
806 static inline void
807 check_bad_parent(struct dentry *dp)
808 {
809     cred_t *credp;
810     struct vcache *vcp = VTOAFS(dp->d_inode), *avc = NULL;
811     struct vcache *pvc = VTOAFS(dp->d_parent->d_inode);
812
813     if (vcp->mvid->Fid.Volume != pvc->f.fid.Fid.Volume) {       /* bad parent */
814         credp = crref();
815
816         /* force a lookup, so vcp->mvid is fixed up */
817         afs_lookup(pvc, (char *)dp->d_name.name, &avc, credp);
818         if (!avc || vcp != avc) {       /* bad, very bad.. */
819             afs_Trace4(afs_iclSetp, CM_TRACE_TMP_1S3L, ICL_TYPE_STRING,
820                        "check_bad_parent: bad pointer returned from afs_lookup origvc newvc dentry",
821                        ICL_TYPE_POINTER, vcp, ICL_TYPE_POINTER, avc,
822                        ICL_TYPE_POINTER, dp);
823         }
824         if (avc)
825             AFS_RELE(AFSTOV(avc));
826         crfree(credp);
827     }
828
829     return;
830 }
831
832 /* afs_linux_revalidate
833  * Ensure vcache is stat'd before use. Return 0 if entry is valid.
834  */
835 static int
836 afs_linux_revalidate(struct dentry *dp)
837 {
838     struct vattr vattr;
839     struct vcache *vcp = VTOAFS(dp->d_inode);
840     cred_t *credp;
841     int code;
842
843     if (afs_shuttingdown)
844         return EIO;
845
846 #ifdef AFS_LINUX24_ENV
847     maybe_lock_kernel();
848 #endif
849     AFS_GLOCK();
850
851 #ifdef notyet
852     /* Make this a fast path (no crref), since it's called so often. */
853     if (vcp->f.states & CStatd) {
854
855         if (*dp->d_name.name != '/' && vcp->mvstat == 2)        /* root vnode */
856             check_bad_parent(dp);       /* check and correct mvid */
857
858         AFS_GUNLOCK();
859 #ifdef AFS_LINUX24_ENV
860         unlock_kernel();
861 #endif
862         return 0;
863     }
864 #endif
865
866     /* This avoids the crref when we don't have to do it. Watch for
867      * changes in afs_getattr that don't get replicated here!
868      */
869     if (vcp->f.states & CStatd &&
870         (!afs_fakestat_enable || vcp->mvstat != 1) &&
871         !afs_nfsexporter &&
872         (vType(vcp) == VDIR || vType(vcp) == VLNK)) {
873         code = afs_CopyOutAttrs(vcp, &vattr);
874     } else {
875         credp = crref();
876         code = afs_getattr(vcp, &vattr, credp);
877         crfree(credp);
878     }
879     if (!code)
880         afs_fill_inode(AFSTOV(vcp), &vattr);
881
882     AFS_GUNLOCK();
883 #ifdef AFS_LINUX24_ENV
884     maybe_unlock_kernel();
885 #endif
886
887     return afs_convert_code(code);
888 }
889
890 /* vattr_setattr
891  * Set iattr data into vattr. Assume vattr cleared before call.
892  */
893 static void
894 iattr2vattr(struct vattr *vattrp, struct iattr *iattrp)
895 {
896     vattrp->va_mask = iattrp->ia_valid;
897     if (iattrp->ia_valid & ATTR_MODE)
898         vattrp->va_mode = iattrp->ia_mode;
899     if (iattrp->ia_valid & ATTR_UID)
900         vattrp->va_uid = iattrp->ia_uid;
901     if (iattrp->ia_valid & ATTR_GID)
902         vattrp->va_gid = iattrp->ia_gid;
903     if (iattrp->ia_valid & ATTR_SIZE)
904         vattrp->va_size = iattrp->ia_size;
905     if (iattrp->ia_valid & ATTR_ATIME) {
906         vattrp->va_atime.tv_sec = iattrp->ia_atime;
907         vattrp->va_atime.tv_usec = 0;
908     }
909     if (iattrp->ia_valid & ATTR_MTIME) {
910         vattrp->va_mtime.tv_sec = iattrp->ia_mtime;
911         vattrp->va_mtime.tv_usec = 0;
912     }
913     if (iattrp->ia_valid & ATTR_CTIME) {
914         vattrp->va_ctime.tv_sec = iattrp->ia_ctime;
915         vattrp->va_ctime.tv_usec = 0;
916     }
917 }
918
919 /* vattr2inode
920  * Rewrite the inode cache from the attr. Assumes all vattr fields are valid.
921  */
922 void
923 vattr2inode(struct inode *ip, struct vattr *vp)
924 {
925     ip->i_ino = vp->va_nodeid;
926     ip->i_nlink = vp->va_nlink;
927     ip->i_blocks = vp->va_blocks;
928 #ifdef STRUCT_INODE_HAS_I_BLKBITS
929     ip->i_blkbits = AFS_BLKBITS;
930 #endif
931 #ifdef STRUCT_INODE_HAS_I_BLKSIZE
932     ip->i_blksize = vp->va_blocksize;
933 #endif
934     ip->i_rdev = vp->va_rdev;
935     ip->i_mode = vp->va_mode;
936     ip->i_uid = vp->va_uid;
937     ip->i_gid = vp->va_gid;
938     i_size_write(ip, vp->va_size);
939     ip->i_atime = vp->va_atime.tv_sec;
940     ip->i_mtime = vp->va_mtime.tv_sec;
941     ip->i_ctime = vp->va_ctime.tv_sec;
942 }
943
944 /* afs_notify_change
945  * Linux version of setattr call. What to change is in the iattr struct.
946  * We need to set bits in both the Linux inode as well as the vcache.
947  */
948 int
949 afs_notify_change(struct dentry *dp, struct iattr *iattrp)
950 {
951     struct vattr vattr;
952     cred_t *credp = crref();
953     struct inode *ip = dp->d_inode;
954     int code;
955
956     VATTR_NULL(&vattr);
957     iattr2vattr(&vattr, iattrp);        /* Convert for AFS vnodeops call. */
958
959     AFS_GLOCK();
960     code = afs_setattr(VTOAFS(ip), &vattr, credp);
961     if (!code) {
962         afs_getattr(VTOAFS(ip), &vattr, credp);
963         vattr2inode(ip, &vattr);
964     }
965     AFS_GUNLOCK();
966     crfree(credp);
967     return afs_convert_code(code);
968 }
969
970 /* Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
971  * In kernels 2.2.10 and above, we are passed an additional flags var which
972  * may have either the LOOKUP_FOLLOW OR LOOKUP_DIRECTORY set in which case
973  * we are advised to follow the entry if it is a link or to make sure that 
974  * it is a directory. But since the kernel itself checks these possibilities
975  * later on, we shouldn't have to do it until later. Perhaps in the future..
976  */
977 static int
978 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
979 #ifdef DOP_REVALIDATE_TAKES_NAMEIDATA
980 afs_linux_dentry_revalidate(struct dentry *dp, struct nameidata *nd)
981 #else
982 afs_linux_dentry_revalidate(struct dentry *dp, int flags)
983 #endif
984 #else
985 afs_linux_dentry_revalidate(struct dentry *dp)
986 #endif
987 {
988     struct vattr vattr;
989     cred_t *credp = NULL;
990     struct vcache *vcp, *pvcp, *tvc = NULL;
991     int valid;
992     struct afs_fakestat_state fakestate;
993
994 #ifdef AFS_LINUX24_ENV
995     maybe_lock_kernel();
996 #endif
997     AFS_GLOCK();
998     afs_InitFakeStat(&fakestate);
999
1000     if (dp->d_inode) {
1001
1002         vcp = VTOAFS(dp->d_inode);
1003         pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
1004
1005         if (vcp == afs_globalVp)
1006             goto good_dentry;
1007
1008         if (vcp->mvstat == 1) {         /* mount point */
1009             if (vcp->mvid && (vcp->f.states & CMValid)) {
1010                 int tryEvalOnly = 0;
1011                 int code = 0;
1012                 struct vrequest treq;
1013
1014                 credp = crref();
1015                 code = afs_InitReq(&treq, credp);
1016                 if (
1017 #ifdef AFS_DARWIN_ENV
1018                     (strcmp(dp->d_name.name, ".DS_Store") == 0) ||
1019                     (strcmp(dp->d_name.name, "Contents") == 0) ||
1020 #endif
1021                     (strcmp(dp->d_name.name, ".directory") == 0)) {
1022                     tryEvalOnly = 1;
1023                 }
1024                 if (tryEvalOnly)
1025                     code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
1026                 else
1027                     code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
1028                 if ((tryEvalOnly && vcp->mvstat == 1) || code) {
1029                     /* a mount point, not yet replaced by its directory */
1030                     goto bad_dentry;
1031                 }
1032             }
1033         } else
1034             if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
1035                 check_bad_parent(dp);   /* check and correct mvid */
1036
1037 #ifdef notdef
1038         /* If the last looker changes, we should make sure the current
1039          * looker still has permission to examine this file.  This would
1040          * always require a crref() which would be "slow".
1041          */
1042         if (vcp->last_looker != treq.uid) {
1043             if (!afs_AccessOK(vcp, (vType(vcp) == VREG) ? PRSFS_READ : PRSFS_LOOKUP, &treq, CHECK_MODE_BITS))
1044                 goto bad_dentry;
1045
1046             vcp->last_looker = treq.uid;
1047         }
1048 #endif
1049
1050         /* If the parent's DataVersion has changed or the vnode
1051          * is longer valid, we need to do a full lookup.  VerifyVCache
1052          * isn't enough since the vnode may have been renamed.
1053          */
1054
1055         if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd)) {
1056
1057             credp = crref();
1058             afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
1059             if (!tvc || tvc != vcp)
1060                 goto bad_dentry;
1061
1062             if (afs_getattr(vcp, &vattr, credp))
1063                 goto bad_dentry;
1064
1065             vattr2inode(AFSTOV(vcp), &vattr);
1066             dp->d_time = hgetlo(pvcp->f.m.DataVersion);
1067         }
1068
1069         /* should we always update the attributes at this point? */
1070         /* unlikely--the vcache entry hasn't changed */
1071
1072     } else {
1073 #ifdef notyet
1074         pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
1075         if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time)
1076             goto bad_dentry;
1077 #endif
1078
1079         /* No change in parent's DataVersion so this negative
1080          * lookup is still valid.  BUT, if a server is down a
1081          * negative lookup can result so there should be a
1082          * liftime as well.  For now, always expire.
1083          */
1084
1085         goto bad_dentry;
1086     }
1087
1088   good_dentry:
1089     valid = 1;
1090
1091   done:
1092     /* Clean up */
1093     if (tvc)
1094         afs_PutVCache(tvc);
1095     afs_PutFakeStat(&fakestate);
1096     AFS_GUNLOCK();
1097     if (credp)
1098         crfree(credp);
1099
1100     if (!valid) {
1101         shrink_dcache_parent(dp);
1102         d_drop(dp);
1103     }
1104 #ifdef AFS_LINUX24_ENV
1105     maybe_unlock_kernel();
1106 #endif
1107     return valid;
1108
1109   bad_dentry:
1110     if (have_submounts(dp))
1111         valid = 1;
1112     else 
1113         valid = 0;
1114     goto done;
1115 }
1116
1117 static void
1118 afs_dentry_iput(struct dentry *dp, struct inode *ip)
1119 {
1120     struct vcache *vcp = VTOAFS(ip);
1121
1122     AFS_GLOCK();
1123     if (!AFS_IS_DISCONNECTED || (vcp->f.states & CUnlinked)) {
1124         (void) afs_InactiveVCache(vcp, NULL);
1125     }
1126     AFS_GUNLOCK();
1127 #ifdef DCACHE_NFSFS_RENAMED
1128     dp->d_flags &= ~DCACHE_NFSFS_RENAMED;   
1129 #endif
1130
1131     iput(ip);
1132 }
1133
1134 static int
1135 afs_dentry_delete(struct dentry *dp)
1136 {
1137     if (dp->d_inode && (VTOAFS(dp->d_inode)->f.states & CUnlinked))
1138         return 1;               /* bad inode? */
1139
1140     return 0;
1141 }
1142
1143 struct dentry_operations afs_dentry_operations = {
1144   .d_revalidate =       afs_linux_dentry_revalidate,
1145   .d_delete =           afs_dentry_delete,
1146   .d_iput =             afs_dentry_iput,
1147 };
1148
1149 /**********************************************************************
1150  * AFS Linux inode operations
1151  **********************************************************************/
1152
1153 /* afs_linux_create
1154  *
1155  * Merely need to set enough of vattr to get us through the create. Note
1156  * that the higher level code (open_namei) will take care of any tuncation
1157  * explicitly. Exclusive open is also taken care of in open_namei.
1158  *
1159  * name is in kernel space at this point.
1160  */
1161 static int
1162 #ifdef IOP_CREATE_TAKES_NAMEIDATA
1163 afs_linux_create(struct inode *dip, struct dentry *dp, int mode,
1164                  struct nameidata *nd)
1165 #else
1166 afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
1167 #endif
1168 {
1169     struct vattr vattr;
1170     cred_t *credp = crref();
1171     const char *name = dp->d_name.name;
1172     struct vcache *vcp;
1173     int code;
1174
1175     VATTR_NULL(&vattr);
1176     vattr.va_mode = mode;
1177     vattr.va_type = mode & S_IFMT;
1178
1179     AFS_GLOCK();
1180     code = afs_create(VTOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
1181                       &vcp, credp);
1182
1183     if (!code) {
1184         struct inode *ip = AFSTOV(vcp);
1185
1186         afs_getattr(vcp, &vattr, credp);
1187         afs_fill_inode(ip, &vattr);
1188         insert_inode_hash(ip);
1189         dp->d_op = &afs_dentry_operations;
1190         dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1191         d_instantiate(dp, ip);
1192     }
1193     AFS_GUNLOCK();
1194
1195     crfree(credp);
1196     return afs_convert_code(code);
1197 }
1198
1199 /* afs_linux_lookup */
1200 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
1201 static struct dentry *
1202 #ifdef IOP_LOOKUP_TAKES_NAMEIDATA
1203 afs_linux_lookup(struct inode *dip, struct dentry *dp,
1204                  struct nameidata *nd)
1205 #else
1206 afs_linux_lookup(struct inode *dip, struct dentry *dp)
1207 #endif
1208 #else
1209 static int
1210 afs_linux_lookup(struct inode *dip, struct dentry *dp)
1211 #endif
1212 {
1213     cred_t *credp = crref();
1214     struct vcache *vcp = NULL;
1215     const char *comp = dp->d_name.name;
1216     struct inode *ip = NULL;
1217     int code;
1218
1219     AFS_GLOCK();
1220     code = afs_lookup(VTOAFS(dip), (char *)comp, &vcp, credp);
1221     
1222     if (vcp) {
1223         struct vattr vattr;
1224
1225         ip = AFSTOV(vcp);
1226         afs_getattr(vcp, &vattr, credp);
1227         afs_fill_inode(ip, &vattr);
1228         if (
1229 #ifdef HAVE_LINUX_HLIST_UNHASHED
1230             hlist_unhashed(&ip->i_hash)
1231 #else
1232             ip->i_hash.prev == NULL
1233 #endif
1234             )
1235             insert_inode_hash(ip);
1236     }
1237     dp->d_op = &afs_dentry_operations;
1238     dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1239     AFS_GUNLOCK();
1240
1241 #if defined(AFS_LINUX24_ENV)
1242     if (ip && S_ISDIR(ip->i_mode)) {
1243         struct dentry *alias;
1244
1245         /* Try to invalidate an existing alias in favor of our new one */
1246         alias = d_find_alias(ip);
1247         if (alias) {
1248             if (d_invalidate(alias) == 0) {
1249                 dput(alias);
1250             } else {
1251                 iput(ip);
1252                 crfree(credp);
1253                 return alias;
1254             }
1255         }
1256     }
1257 #endif
1258     d_add(dp, ip);
1259
1260     crfree(credp);
1261
1262     /* It's ok for the file to not be found. That's noted by the caller by
1263      * seeing that the dp->d_inode field is NULL.
1264      */
1265 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
1266     if (code == ENOENT)
1267         return ERR_PTR(0);
1268     else 
1269         return ERR_PTR(afs_convert_code(code));
1270 #else
1271     if (code == ENOENT)
1272         code = 0;
1273     return afs_convert_code(code);
1274 #endif
1275 }
1276
1277 static int
1278 afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
1279 {
1280     int code;
1281     cred_t *credp = crref();
1282     const char *name = newdp->d_name.name;
1283     struct inode *oldip = olddp->d_inode;
1284
1285     /* If afs_link returned the vnode, we could instantiate the
1286      * dentry. Since it's not, we drop this one and do a new lookup.
1287      */
1288     d_drop(newdp);
1289
1290     AFS_GLOCK();
1291     code = afs_link(VTOAFS(oldip), VTOAFS(dip), (char *)name, credp);
1292
1293     AFS_GUNLOCK();
1294     crfree(credp);
1295     return afs_convert_code(code);
1296 }
1297
1298 static int
1299 afs_linux_unlink(struct inode *dip, struct dentry *dp)
1300 {
1301     int code = EBUSY;
1302     cred_t *credp = crref();
1303     const char *name = dp->d_name.name;
1304     struct vcache *tvc = VTOAFS(dp->d_inode);
1305
1306     if (VREFCOUNT(tvc) > 1 && tvc->opens > 0
1307                                 && !(tvc->f.states & CUnlinked)) {
1308         struct dentry *__dp;
1309         char *__name;
1310
1311         __dp = NULL;
1312         __name = NULL;
1313         do {
1314             dput(__dp);
1315
1316             AFS_GLOCK();
1317             if (__name)
1318                 osi_FreeSmallSpace(__name);
1319             __name = afs_newname();
1320             AFS_GUNLOCK();
1321
1322             __dp = lookup_one_len(__name, dp->d_parent, strlen(__name));
1323                 
1324             if (IS_ERR(__dp))
1325                 goto out;
1326         } while (__dp->d_inode != NULL);
1327
1328         AFS_GLOCK();
1329         code = afs_rename(VTOAFS(dip), (char *)dp->d_name.name, VTOAFS(dip), (char *)__dp->d_name.name, credp);
1330         if (!code) {
1331             tvc->mvid = (void *) __name;
1332             crhold(credp);
1333             if (tvc->uncred) {
1334                 crfree(tvc->uncred);
1335             }
1336             tvc->uncred = credp;
1337             tvc->f.states |= CUnlinked;
1338 #ifdef DCACHE_NFSFS_RENAMED
1339             dp->d_flags |= DCACHE_NFSFS_RENAMED;   
1340 #endif
1341         } else {
1342             osi_FreeSmallSpace(__name); 
1343         }
1344         AFS_GUNLOCK();
1345
1346         if (!code) {
1347             __dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1348             d_move(dp, __dp);
1349         }
1350         dput(__dp);
1351
1352         goto out;
1353     }
1354
1355     AFS_GLOCK();
1356     code = afs_remove(VTOAFS(dip), (char *)name, credp);
1357     AFS_GUNLOCK();
1358     if (!code)
1359         d_drop(dp);
1360 out:
1361     crfree(credp);
1362     return afs_convert_code(code);
1363 }
1364
1365
1366 static int
1367 afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
1368 {
1369     int code;
1370     cred_t *credp = crref();
1371     struct vattr vattr;
1372     const char *name = dp->d_name.name;
1373
1374     /* If afs_symlink returned the vnode, we could instantiate the
1375      * dentry. Since it's not, we drop this one and do a new lookup.
1376      */
1377     d_drop(dp);
1378
1379     VATTR_NULL(&vattr);
1380     AFS_GLOCK();
1381     code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp);
1382     AFS_GUNLOCK();
1383     crfree(credp);
1384     return afs_convert_code(code);
1385 }
1386
1387 static int
1388 afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
1389 {
1390     int code;
1391     cred_t *credp = crref();
1392     struct vcache *tvcp = NULL;
1393     struct vattr vattr;
1394     const char *name = dp->d_name.name;
1395
1396     VATTR_NULL(&vattr);
1397     vattr.va_mask = ATTR_MODE;
1398     vattr.va_mode = mode;
1399     AFS_GLOCK();
1400     code = afs_mkdir(VTOAFS(dip), (char *)name, &vattr, &tvcp, credp);
1401
1402     if (tvcp) {
1403         struct inode *ip = AFSTOV(tvcp);
1404
1405         afs_getattr(tvcp, &vattr, credp);
1406         afs_fill_inode(ip, &vattr);
1407
1408         dp->d_op = &afs_dentry_operations;
1409         dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1410         d_instantiate(dp, ip);
1411     }
1412     AFS_GUNLOCK();
1413
1414     crfree(credp);
1415     return afs_convert_code(code);
1416 }
1417
1418 static int
1419 afs_linux_rmdir(struct inode *dip, struct dentry *dp)
1420 {
1421     int code;
1422     cred_t *credp = crref();
1423     const char *name = dp->d_name.name;
1424
1425     /* locking kernel conflicts with glock? */
1426
1427     AFS_GLOCK();
1428     code = afs_rmdir(VTOAFS(dip), (char *)name, credp);
1429     AFS_GUNLOCK();
1430
1431     /* Linux likes to see ENOTEMPTY returned from an rmdir() syscall
1432      * that failed because a directory is not empty. So, we map
1433      * EEXIST to ENOTEMPTY on linux.
1434      */
1435     if (code == EEXIST) {
1436         code = ENOTEMPTY;
1437     }
1438
1439     if (!code) {
1440         d_drop(dp);
1441     }
1442
1443     crfree(credp);
1444     return afs_convert_code(code);
1445 }
1446
1447
1448 static int
1449 afs_linux_rename(struct inode *oldip, struct dentry *olddp,
1450                  struct inode *newip, struct dentry *newdp)
1451 {
1452     int code;
1453     cred_t *credp = crref();
1454     const char *oldname = olddp->d_name.name;
1455     const char *newname = newdp->d_name.name;
1456     struct dentry *rehash = NULL;
1457
1458     if (!list_empty(&newdp->d_hash)) {
1459         d_drop(newdp);
1460         rehash = newdp;
1461     }
1462
1463 #if defined(AFS_LINUX24_ENV)
1464     if (atomic_read(&olddp->d_count) > 1)
1465         shrink_dcache_parent(olddp);
1466 #endif
1467
1468     AFS_GLOCK();
1469     code = afs_rename(VTOAFS(oldip), (char *)oldname, VTOAFS(newip), (char *)newname, credp);
1470     AFS_GUNLOCK();
1471
1472     if (!code)
1473         olddp->d_time = 0;      /* force to revalidate */
1474
1475     if (rehash)
1476         d_rehash(rehash);
1477
1478     crfree(credp);
1479     return afs_convert_code(code);
1480 }
1481
1482
1483 /* afs_linux_ireadlink 
1484  * Internal readlink which can return link contents to user or kernel space.
1485  * Note that the buffer is NOT supposed to be null-terminated.
1486  */
1487 static int
1488 afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
1489 {
1490     int code;
1491     cred_t *credp = crref();
1492     struct uio tuio;
1493     struct iovec iov;
1494
1495     setup_uio(&tuio, &iov, target, (afs_offs_t) 0, maxlen, UIO_READ, seg);
1496     code = afs_readlink(VTOAFS(ip), &tuio, credp);
1497     crfree(credp);
1498
1499     if (!code)
1500         return maxlen - tuio.uio_resid;
1501     else
1502         return afs_convert_code(code);
1503 }
1504
1505 #if !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
1506 /* afs_linux_readlink 
1507  * Fill target (which is in user space) with contents of symlink.
1508  */
1509 static int
1510 afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
1511 {
1512     int code;
1513     struct inode *ip = dp->d_inode;
1514
1515     AFS_GLOCK();
1516     code = afs_linux_ireadlink(ip, target, maxlen, AFS_UIOUSER);
1517     AFS_GUNLOCK();
1518     return code;
1519 }
1520
1521
1522 /* afs_linux_follow_link
1523  * a file system dependent link following routine.
1524  */
1525 #if defined(AFS_LINUX24_ENV)
1526 static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
1527 {
1528     int code;
1529     char *name;
1530
1531     name = osi_Alloc(PATH_MAX);
1532     if (!name) {
1533         return -EIO;
1534     }
1535
1536     AFS_GLOCK();
1537     code = afs_linux_ireadlink(dentry->d_inode, name, PATH_MAX - 1, AFS_UIOSYS);
1538     AFS_GUNLOCK();
1539
1540     if (code < 0) {
1541         goto out;
1542     }
1543
1544     name[code] = '\0';
1545     code = vfs_follow_link(nd, name);
1546
1547 out:
1548     osi_Free(name, PATH_MAX);
1549
1550     return code;
1551 }
1552
1553 #else /* !defined(AFS_LINUX24_ENV) */
1554
1555 static struct dentry *
1556 afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
1557                       unsigned int follow)
1558 {
1559     int code = 0;
1560     char *name;
1561     struct dentry *res;
1562
1563
1564     AFS_GLOCK();
1565     name = osi_Alloc(PATH_MAX + 1);
1566     if (!name) {
1567         AFS_GUNLOCK();
1568         dput(basep);
1569         return ERR_PTR(-EIO);
1570     }
1571
1572     code = afs_linux_ireadlink(dp->d_inode, name, PATH_MAX, AFS_UIOSYS);
1573     AFS_GUNLOCK();
1574
1575     if (code < 0) {
1576         dput(basep);
1577         if (code < -MAX_ERRNO)
1578             res = ERR_PTR(-EIO);
1579         else
1580             res = ERR_PTR(code);
1581     } else {
1582         name[code] = '\0';
1583         res = lookup_dentry(name, basep, follow);
1584     }
1585
1586     AFS_GLOCK();
1587     osi_Free(name, PATH_MAX + 1);
1588     AFS_GUNLOCK();
1589     return res;
1590 }
1591 #endif /* AFS_LINUX24_ENV */
1592 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
1593
1594 static inline int
1595 afs_linux_can_bypass(struct inode *ip) {
1596     switch(cache_bypass_strategy) {
1597         case NEVER_BYPASS_CACHE:
1598             return 0;
1599         case ALWAYS_BYPASS_CACHE:
1600             return 1;
1601         case LARGE_FILES_BYPASS_CACHE:
1602             if(i_size_read(ip) > cache_bypass_threshold)
1603                 return 1;
1604         default:
1605             return 0;
1606      }
1607 }
1608
1609 /* afs_linux_readpage
1610  * all reads come through here. A strategy-like read call.
1611  */
1612 static int
1613 afs_linux_readpage(struct file *fp, struct page *pp)
1614 {
1615     afs_int32 code;
1616 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1617     char *address;
1618     afs_offs_t offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
1619 #else
1620     ulong address = afs_linux_page_address(pp);
1621     afs_offs_t offset = pageoff(pp);
1622 #endif
1623     afs_int32 bypasscache = 0; /* bypass for this read */
1624     struct nocache_read_request *ancr;
1625 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1626     afs_int32 isize;
1627 #endif
1628     struct uio *auio;
1629     struct iovec *iovecp;
1630     struct inode *ip = FILE_INODE(fp);
1631     afs_int32 cnt = page_count(pp);
1632     struct vcache *avc = VTOAFS(ip);
1633     cred_t *credp;
1634
1635     credp = crref();
1636 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1637     address = kmap(pp);
1638     ClearPageError(pp);
1639 #else
1640     atomic_add(1, &pp->count);
1641     set_bit(PG_locked, &pp->flags);     /* other bits? See mm.h */
1642     clear_bit(PG_error, &pp->flags);
1643 #endif
1644     /* if bypasscache, receiver frees, else we do */
1645     auio = osi_Alloc(sizeof(struct uio));
1646     iovecp = osi_Alloc(sizeof(struct iovec));
1647
1648     setup_uio(auio, iovecp, (char *)address, offset, PAGE_SIZE, UIO_READ,
1649               AFS_UIOSYS);
1650
1651     bypasscache = afs_linux_can_bypass(ip);
1652
1653     /* In the new incarnation of selective caching, a file's caching policy
1654      * can change, eg because file size exceeds threshold, etc. */
1655     trydo_cache_transition(avc, credp, bypasscache);
1656         
1657     if(bypasscache) {
1658         if(address)
1659             kunmap(pp);
1660         /* save the page for background map */
1661         auio->uio_iov->iov_base = (void*) pp;
1662         /* the background thread will free this */
1663         ancr = osi_Alloc(sizeof(struct nocache_read_request));
1664         ancr->auio = auio;
1665         ancr->offset = offset;
1666         ancr->length = PAGE_SIZE;
1667
1668         maybe_lock_kernel();
1669         code = afs_ReadNoCache(avc, ancr, credp);
1670         maybe_unlock_kernel();
1671
1672         goto done; /* skips release page, doing it in bg thread */
1673     }
1674                   
1675 #ifdef AFS_LINUX24_ENV
1676     maybe_lock_kernel();
1677 #endif
1678     AFS_GLOCK();
1679     AFS_DISCON_LOCK();
1680     afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
1681                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
1682                99999);  /* not a possible code value */
1683
1684     code = afs_rdwr(avc, auio, UIO_READ, 0, credp);
1685         
1686     afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
1687                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
1688                code);
1689     AFS_DISCON_UNLOCK();
1690     AFS_GUNLOCK();
1691 #ifdef AFS_LINUX24_ENV
1692     maybe_unlock_kernel();
1693 #endif
1694     if (!code) {
1695         /* XXX valid for no-cache also?  Check last bits of files... :)
1696          * Cognate code goes in afs_NoCacheFetchProc.  */
1697         if (auio->uio_resid)    /* zero remainder of page */
1698              memset((void *)(address + (PAGE_SIZE - auio->uio_resid)), 0,
1699                     auio->uio_resid);
1700
1701 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1702         flush_dcache_page(pp);
1703         SetPageUptodate(pp);
1704 #else
1705         set_bit(PG_uptodate, &pp->flags);
1706 #endif
1707     } /* !code */
1708
1709 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1710     kunmap(pp);
1711     UnlockPage(pp);
1712 #else
1713     clear_bit(PG_locked, &pp->flags);
1714     wake_up(&pp->wait);
1715     free_page(address);
1716 #endif
1717
1718     /* do not call afs_GetDCache if cache is bypassed */
1719     if(bypasscache)
1720         goto done;
1721
1722     /* free if not bypassing cache */
1723     osi_Free(auio, sizeof(struct uio));
1724     osi_Free(iovecp, sizeof(struct iovec));
1725
1726     if (!code && AFS_CHUNKOFFSET(offset) == 0) {
1727         struct dcache *tdc;
1728         struct vrequest treq;
1729
1730         AFS_GLOCK();
1731         code = afs_InitReq(&treq, credp);
1732         if (!code && !NBObtainWriteLock(&avc->lock, 534)) {
1733             tdc = afs_FindDCache(avc, offset);
1734             if (tdc) {
1735                 if (!(tdc->mflags & DFNextStarted))
1736                     afs_PrefetchChunk(avc, tdc, credp, &treq);
1737                     afs_PutDCache(tdc);
1738             }
1739             ReleaseWriteLock(&avc->lock);
1740         }
1741         AFS_GUNLOCK();
1742     }
1743
1744 done:
1745     crfree(credp);
1746     return afs_convert_code(code);
1747 }
1748
1749 #if defined(AFS_LINUX24_ENV)
1750 static int
1751 afs_linux_writepage_sync(struct inode *ip, struct page *pp,
1752                          unsigned long offset, unsigned int count)
1753 {
1754     struct vcache *vcp = VTOAFS(ip);
1755     char *buffer;
1756     afs_offs_t base;
1757     int code = 0;
1758     cred_t *credp;
1759     struct uio tuio;
1760     struct iovec iovec;
1761     int f_flags = 0;
1762
1763     buffer = kmap(pp) + offset;
1764     base = (((loff_t) pp->index) << PAGE_CACHE_SHIFT)  + offset;
1765
1766     credp = crref();
1767     maybe_lock_kernel();
1768     AFS_GLOCK();
1769     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1770                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1771                ICL_TYPE_INT32, 99999);
1772
1773     ObtainWriteLock(&vcp->lock, 532);
1774     if (vcp->f.states & CPageWrite) {
1775         ReleaseWriteLock(&vcp->lock);
1776         AFS_GUNLOCK();
1777         maybe_unlock_kernel();
1778         crfree(credp);
1779         kunmap(pp);
1780         /* should mark it dirty? */
1781         return(0); 
1782     }
1783     vcp->f.states |= CPageWrite;
1784     ReleaseWriteLock(&vcp->lock);
1785
1786     setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
1787
1788     code = afs_write(vcp, &tuio, f_flags, credp, 0);
1789
1790     i_size_write(ip, vcp->f.m.Length);
1791     ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
1792
1793     ObtainWriteLock(&vcp->lock, 533);
1794     if (!code) {
1795         struct vrequest treq;
1796
1797         if (!afs_InitReq(&treq, credp))
1798             code = afs_DoPartialWrite(vcp, &treq);
1799     }
1800     code = code ? afs_convert_code(code) : count - tuio.uio_resid;
1801
1802     vcp->f.states &= ~CPageWrite;
1803     ReleaseWriteLock(&vcp->lock);
1804
1805     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1806                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1807                ICL_TYPE_INT32, code);
1808
1809     AFS_GUNLOCK();
1810     maybe_unlock_kernel();
1811     crfree(credp);
1812     kunmap(pp);
1813
1814     return code;
1815 }
1816
1817
1818 static int
1819 #ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
1820 afs_linux_writepage(struct page *pp, struct writeback_control *wbc)
1821 #else
1822 afs_linux_writepage(struct page *pp)
1823 #endif
1824 {
1825     struct address_space *mapping = pp->mapping;
1826     struct inode *inode;
1827     unsigned long end_index;
1828     unsigned offset = PAGE_CACHE_SIZE;
1829     long status;
1830
1831     if (PageLaunder(pp)) {
1832         return(fail_writepage(pp));
1833     }
1834
1835     inode = (struct inode *)mapping->host;
1836     end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
1837
1838     /* easy case */
1839     if (pp->index < end_index)
1840         goto do_it;
1841     /* things got complicated... */
1842     offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1);
1843     /* OK, are we completely out? */
1844     if (pp->index >= end_index + 1 || !offset)
1845         return -EIO;
1846   do_it:
1847     status = afs_linux_writepage_sync(inode, pp, 0, offset);
1848     SetPageUptodate(pp);
1849     UnlockPage(pp);
1850     if (status == offset)
1851         return 0;
1852     else
1853         return status;
1854 }
1855 #else
1856 /* afs_linux_updatepage
1857  * What one would have thought was writepage - write dirty page to file.
1858  * Called from generic_file_write. buffer is still in user space. pagep
1859  * has been filled in with old data if we're updating less than a page.
1860  */
1861 static int
1862 afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
1863                      unsigned int count, int sync)
1864 {
1865     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
1866     u8 *page_addr = (u8 *) afs_linux_page_address(pp);
1867     int code = 0;
1868     cred_t *credp;
1869     struct uio tuio;
1870     struct iovec iovec;
1871
1872     set_bit(PG_locked, &pp->flags);
1873
1874     credp = crref();
1875     AFS_GLOCK();
1876     AFS_DISCON_LOCK();
1877     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1878                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1879                ICL_TYPE_INT32, 99999);
1880     setup_uio(&tuio, &iovec, page_addr + offset,
1881               (afs_offs_t) (pageoff(pp) + offset), count, UIO_WRITE,
1882               AFS_UIOSYS);
1883
1884     code = afs_write(vcp, &tuio, fp->f_flags, credp, 0);
1885
1886     i_size_write(ip, vcp->f.m.Length);
1887     ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
1888
1889     if (!code) {
1890         struct vrequest treq;
1891
1892         ObtainWriteLock(&vcp->lock, 533);
1893         vcp->f.m.Date = osi_Time();   /* set modification time */
1894         if (!afs_InitReq(&treq, credp))
1895             code = afs_DoPartialWrite(vcp, &treq);
1896         ReleaseWriteLock(&vcp->lock);
1897     }
1898
1899     code = code ? afs_convert_code(code) : count - tuio.uio_resid;
1900     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1901                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1902                ICL_TYPE_INT32, code);
1903
1904     AFS_DISCON_UNLOCK();
1905     AFS_GUNLOCK();
1906     crfree(credp);
1907
1908     clear_bit(PG_locked, &pp->flags);
1909     return code;
1910 }
1911 #endif
1912
1913 /* afs_linux_permission
1914  * Check access rights - returns error if can't check or permission denied.
1915  */
1916 static int
1917 #ifdef IOP_PERMISSION_TAKES_NAMEIDATA
1918 afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd)
1919 #else
1920 afs_linux_permission(struct inode *ip, int mode)
1921 #endif
1922 {
1923     int code;
1924     cred_t *credp = crref();
1925     int tmp = 0;
1926
1927     AFS_GLOCK();
1928     if (mode & MAY_EXEC)
1929         tmp |= VEXEC;
1930     if (mode & MAY_READ)
1931         tmp |= VREAD;
1932     if (mode & MAY_WRITE)
1933         tmp |= VWRITE;
1934     code = afs_access(VTOAFS(ip), tmp, credp);
1935
1936     AFS_GUNLOCK();
1937     crfree(credp);
1938     return afs_convert_code(code);
1939 }
1940
1941 #if defined(AFS_LINUX24_ENV) && !defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
1942 static int
1943 afs_linux_commit_write(struct file *file, struct page *page, unsigned offset,
1944                        unsigned to)
1945 {
1946     int code;
1947
1948     code = afs_linux_writepage_sync(file->f_dentry->d_inode, page,
1949                                     offset, to - offset);
1950     kunmap(page);
1951
1952     return code;
1953 }
1954
1955 static int
1956 afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
1957                         unsigned to)
1958 {
1959 /* sometime between 2.4.0 and 2.4.19, the callers of prepare_write began to
1960    call kmap directly instead of relying on us to do it */
1961     kmap(page);
1962     return 0;
1963 }
1964 #endif
1965
1966 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
1967 static int
1968 afs_linux_write_end(struct file *file, struct address_space *mapping,
1969                                 loff_t pos, unsigned len, unsigned copied,
1970                                 struct page *page, void *fsdata)
1971 {
1972     int code;
1973     unsigned from = pos & (PAGE_CACHE_SIZE - 1);
1974
1975     code = afs_linux_writepage_sync(file->f_dentry->d_inode, page,
1976                                     from, copied);
1977     unlock_page(page);
1978     page_cache_release(page);
1979     return code;
1980 }
1981
1982 static int
1983 afs_linux_write_begin(struct file *file, struct address_space *mapping,
1984                                 loff_t pos, unsigned len, unsigned flags,
1985                                 struct page **pagep, void **fsdata)
1986 {
1987     struct page *page;
1988     pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1989 #if defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN)
1990     page = grab_cache_page_write_begin(mapping, index, flags);
1991 #else
1992     page = __grab_cache_page(mapping, index);
1993 #endif
1994     *pagep = page;
1995
1996     return 0;
1997 }
1998 #endif
1999
2000
2001 static struct inode_operations afs_file_iops = {
2002 #if defined(AFS_LINUX24_ENV)
2003   .permission =         afs_linux_permission,
2004   .revalidate =         afs_linux_revalidate,
2005   .setattr =            afs_notify_change,
2006 #else
2007   .default_file_ops =   &afs_file_fops,
2008   .readpage =           afs_linux_readpage,  
2009   .revalidate =         afs_linux_revalidate,
2010   .updatepage =         afs_linux_updatepage,
2011 #endif
2012 };
2013
2014 #if defined(AFS_LINUX24_ENV)
2015 static struct address_space_operations afs_file_aops = {
2016   .readpage =           afs_linux_readpage,
2017   .writepage =          afs_linux_writepage,
2018 #if defined (STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
2019   .write_begin =        afs_linux_write_begin,
2020   .write_end =          afs_linux_write_end,
2021 #else
2022   .commit_write =       afs_linux_commit_write,
2023   .prepare_write =      afs_linux_prepare_write,
2024 #endif
2025 };
2026 #endif
2027
2028
2029 /* Separate ops vector for directories. Linux 2.2 tests type of inode
2030  * by what sort of operation is allowed.....
2031  */
2032
2033 static struct inode_operations afs_dir_iops = {
2034 #if !defined(AFS_LINUX24_ENV)
2035   .default_file_ops =   &afs_dir_fops,
2036 #else
2037   .setattr =            afs_notify_change,
2038 #endif
2039   .create =             afs_linux_create,
2040   .lookup =             afs_linux_lookup,
2041   .link =               afs_linux_link,
2042   .unlink =             afs_linux_unlink,
2043   .symlink =            afs_linux_symlink,
2044   .mkdir =              afs_linux_mkdir,
2045   .rmdir =              afs_linux_rmdir,
2046   .rename =             afs_linux_rename,
2047   .revalidate =         afs_linux_revalidate,
2048   .permission =         afs_linux_permission,
2049 };
2050
2051 /* We really need a separate symlink set of ops, since do_follow_link()
2052  * determines if it _is_ a link by checking if the follow_link op is set.
2053  */
2054 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
2055 static int
2056 afs_symlink_filler(struct file *file, struct page *page)
2057 {
2058     struct inode *ip = (struct inode *)page->mapping->host;
2059     char *p = (char *)kmap(page);
2060     int code;
2061
2062     maybe_lock_kernel();
2063     AFS_GLOCK();
2064     code = afs_linux_ireadlink(ip, p, PAGE_SIZE, AFS_UIOSYS);
2065     AFS_GUNLOCK();
2066
2067     if (code < 0)
2068         goto fail;
2069     p[code] = '\0';             /* null terminate? */
2070     maybe_unlock_kernel();
2071
2072     SetPageUptodate(page);
2073     kunmap(page);
2074     UnlockPage(page);
2075     return 0;
2076
2077   fail:
2078     maybe_unlock_kernel();
2079
2080     SetPageError(page);
2081     kunmap(page);
2082     UnlockPage(page);
2083     return code;
2084 }
2085
2086 static struct address_space_operations afs_symlink_aops = {
2087   .readpage =   afs_symlink_filler
2088 };
2089 #endif  /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
2090
2091 static struct inode_operations afs_symlink_iops = {
2092 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
2093   .readlink =           page_readlink,
2094 #if defined(HAVE_KERNEL_PAGE_FOLLOW_LINK)
2095   .follow_link =        page_follow_link,
2096 #else
2097   .follow_link =        page_follow_link_light,
2098   .put_link =           page_put_link,
2099 #endif
2100 #else /* !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE) */
2101   .readlink =           afs_linux_readlink,
2102   .follow_link =        afs_linux_follow_link,
2103 #if !defined(AFS_LINUX24_ENV)
2104   .permission =         afs_linux_permission,
2105   .revalidate =         afs_linux_revalidate,
2106 #endif
2107 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
2108 #if defined(AFS_LINUX24_ENV)
2109   .setattr =            afs_notify_change,
2110 #endif
2111 };
2112
2113 void
2114 afs_fill_inode(struct inode *ip, struct vattr *vattr)
2115 {
2116         
2117     if (vattr)
2118         vattr2inode(ip, vattr);
2119
2120 /* Reset ops if symlink or directory. */
2121     if (S_ISREG(ip->i_mode)) {
2122         ip->i_op = &afs_file_iops;
2123 #if defined(AFS_LINUX24_ENV)
2124         ip->i_fop = &afs_file_fops;
2125         ip->i_data.a_ops = &afs_file_aops;
2126 #endif
2127
2128     } else if (S_ISDIR(ip->i_mode)) {
2129         ip->i_op = &afs_dir_iops;
2130 #if defined(AFS_LINUX24_ENV)
2131         ip->i_fop = &afs_dir_fops;
2132 #endif
2133
2134     } else if (S_ISLNK(ip->i_mode)) {
2135         ip->i_op = &afs_symlink_iops;
2136 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
2137         ip->i_data.a_ops = &afs_symlink_aops;
2138         ip->i_mapping = &ip->i_data;
2139 #endif
2140     }
2141
2142 }