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