Tidy up uio_t meaning
[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         code = afs_dir_GetBlob(tdc, dirpos, &entry);
304         if (code)
305             break;
306         de = (struct DirEntry *)entry.data;
307
308         ino = afs_calc_inum (avc->f.fid.Fid.Volume, 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 /* Validate a dentry. Return 1 if unchanged, 0 if VFS layer should re-evaluate.
891  * In kernels 2.2.10 and above, we are passed an additional flags var which
892  * may have either the LOOKUP_FOLLOW OR LOOKUP_DIRECTORY set in which case
893  * we are advised to follow the entry if it is a link or to make sure that 
894  * it is a directory. But since the kernel itself checks these possibilities
895  * later on, we shouldn't have to do it until later. Perhaps in the future..
896  */
897 static int
898 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
899 #ifdef DOP_REVALIDATE_TAKES_NAMEIDATA
900 afs_linux_dentry_revalidate(struct dentry *dp, struct nameidata *nd)
901 #else
902 afs_linux_dentry_revalidate(struct dentry *dp, int flags)
903 #endif
904 #else
905 afs_linux_dentry_revalidate(struct dentry *dp)
906 #endif
907 {
908     struct vattr vattr;
909     cred_t *credp = NULL;
910     struct vcache *vcp, *pvcp, *tvc = NULL;
911     int valid;
912     struct afs_fakestat_state fakestate;
913
914 #ifdef AFS_LINUX24_ENV
915     maybe_lock_kernel();
916 #endif
917     AFS_GLOCK();
918     afs_InitFakeStat(&fakestate);
919
920     if (dp->d_inode) {
921
922         vcp = VTOAFS(dp->d_inode);
923         pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
924
925         if (vcp == afs_globalVp)
926             goto good_dentry;
927
928         if (vcp->mvstat == 1) {         /* mount point */
929             if (vcp->mvid && (vcp->f.states & CMValid)) {
930                 int tryEvalOnly = 0;
931                 int code = 0;
932                 struct vrequest treq;
933
934                 credp = crref();
935                 code = afs_InitReq(&treq, credp);
936                 if (
937 #ifdef AFS_DARWIN_ENV
938                     (strcmp(dp->d_name.name, ".DS_Store") == 0) ||
939                     (strcmp(dp->d_name.name, "Contents") == 0) ||
940 #endif
941                     (strcmp(dp->d_name.name, ".directory") == 0)) {
942                     tryEvalOnly = 1;
943                 }
944                 if (tryEvalOnly)
945                     code = afs_TryEvalFakeStat(&vcp, &fakestate, &treq);
946                 else
947                     code = afs_EvalFakeStat(&vcp, &fakestate, &treq);
948                 if ((tryEvalOnly && vcp->mvstat == 1) || code) {
949                     /* a mount point, not yet replaced by its directory */
950                     goto bad_dentry;
951                 }
952             }
953         } else
954             if (*dp->d_name.name != '/' && vcp->mvstat == 2) /* root vnode */
955                 check_bad_parent(dp);   /* check and correct mvid */
956
957 #ifdef notdef
958         /* If the last looker changes, we should make sure the current
959          * looker still has permission to examine this file.  This would
960          * always require a crref() which would be "slow".
961          */
962         if (vcp->last_looker != treq.uid) {
963             if (!afs_AccessOK(vcp, (vType(vcp) == VREG) ? PRSFS_READ : PRSFS_LOOKUP, &treq, CHECK_MODE_BITS))
964                 goto bad_dentry;
965
966             vcp->last_looker = treq.uid;
967         }
968 #endif
969
970         /* If the parent's DataVersion has changed or the vnode
971          * is longer valid, we need to do a full lookup.  VerifyVCache
972          * isn't enough since the vnode may have been renamed.
973          */
974
975         if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time || !(vcp->f.states & CStatd)) {
976
977             credp = crref();
978             afs_lookup(pvcp, (char *)dp->d_name.name, &tvc, credp);
979             if (!tvc || tvc != vcp)
980                 goto bad_dentry;
981
982             if (afs_getattr(vcp, &vattr, credp))
983                 goto bad_dentry;
984
985             vattr2inode(AFSTOV(vcp), &vattr);
986             dp->d_time = hgetlo(pvcp->f.m.DataVersion);
987         }
988
989         /* should we always update the attributes at this point? */
990         /* unlikely--the vcache entry hasn't changed */
991
992     } else {
993 #ifdef notyet
994         pvcp = VTOAFS(dp->d_parent->d_inode);           /* dget_parent()? */
995         if (hgetlo(pvcp->f.m.DataVersion) > dp->d_time)
996             goto bad_dentry;
997 #endif
998
999         /* No change in parent's DataVersion so this negative
1000          * lookup is still valid.  BUT, if a server is down a
1001          * negative lookup can result so there should be a
1002          * liftime as well.  For now, always expire.
1003          */
1004
1005         goto bad_dentry;
1006     }
1007
1008   good_dentry:
1009     valid = 1;
1010
1011   done:
1012     /* Clean up */
1013     if (tvc)
1014         afs_PutVCache(tvc);
1015     afs_PutFakeStat(&fakestate);
1016     AFS_GUNLOCK();
1017     if (credp)
1018         crfree(credp);
1019
1020     if (!valid) {
1021         shrink_dcache_parent(dp);
1022         d_drop(dp);
1023     }
1024 #ifdef AFS_LINUX24_ENV
1025     maybe_unlock_kernel();
1026 #endif
1027     return valid;
1028
1029   bad_dentry:
1030     if (have_submounts(dp))
1031         valid = 1;
1032     else 
1033         valid = 0;
1034     goto done;
1035 }
1036
1037 static void
1038 afs_dentry_iput(struct dentry *dp, struct inode *ip)
1039 {
1040     struct vcache *vcp = VTOAFS(ip);
1041
1042     AFS_GLOCK();
1043     if (!AFS_IS_DISCONNECTED || (vcp->f.states & CUnlinked)) {
1044         (void) afs_InactiveVCache(vcp, NULL);
1045     }
1046     AFS_GUNLOCK();
1047 #ifdef DCACHE_NFSFS_RENAMED
1048     dp->d_flags &= ~DCACHE_NFSFS_RENAMED;   
1049 #endif
1050
1051     iput(ip);
1052 }
1053
1054 static int
1055 afs_dentry_delete(struct dentry *dp)
1056 {
1057     if (dp->d_inode && (VTOAFS(dp->d_inode)->f.states & CUnlinked))
1058         return 1;               /* bad inode? */
1059
1060     return 0;
1061 }
1062
1063 struct dentry_operations afs_dentry_operations = {
1064   .d_revalidate =       afs_linux_dentry_revalidate,
1065   .d_delete =           afs_dentry_delete,
1066   .d_iput =             afs_dentry_iput,
1067 };
1068
1069 /**********************************************************************
1070  * AFS Linux inode operations
1071  **********************************************************************/
1072
1073 /* afs_linux_create
1074  *
1075  * Merely need to set enough of vattr to get us through the create. Note
1076  * that the higher level code (open_namei) will take care of any tuncation
1077  * explicitly. Exclusive open is also taken care of in open_namei.
1078  *
1079  * name is in kernel space at this point.
1080  */
1081 static int
1082 #ifdef IOP_CREATE_TAKES_NAMEIDATA
1083 afs_linux_create(struct inode *dip, struct dentry *dp, int mode,
1084                  struct nameidata *nd)
1085 #else
1086 afs_linux_create(struct inode *dip, struct dentry *dp, int mode)
1087 #endif
1088 {
1089     struct vattr vattr;
1090     cred_t *credp = crref();
1091     const char *name = dp->d_name.name;
1092     struct vcache *vcp;
1093     int code;
1094
1095     VATTR_NULL(&vattr);
1096     vattr.va_mode = mode;
1097     vattr.va_type = mode & S_IFMT;
1098
1099     AFS_GLOCK();
1100     code = afs_create(VTOAFS(dip), (char *)name, &vattr, NONEXCL, mode,
1101                       &vcp, credp);
1102
1103     if (!code) {
1104         struct inode *ip = AFSTOV(vcp);
1105
1106         afs_getattr(vcp, &vattr, credp);
1107         afs_fill_inode(ip, &vattr);
1108         insert_inode_hash(ip);
1109         dp->d_op = &afs_dentry_operations;
1110         dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1111         d_instantiate(dp, ip);
1112     }
1113     AFS_GUNLOCK();
1114
1115     crfree(credp);
1116     return afs_convert_code(code);
1117 }
1118
1119 /* afs_linux_lookup */
1120 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
1121 static struct dentry *
1122 #ifdef IOP_LOOKUP_TAKES_NAMEIDATA
1123 afs_linux_lookup(struct inode *dip, struct dentry *dp,
1124                  struct nameidata *nd)
1125 #else
1126 afs_linux_lookup(struct inode *dip, struct dentry *dp)
1127 #endif
1128 #else
1129 static int
1130 afs_linux_lookup(struct inode *dip, struct dentry *dp)
1131 #endif
1132 {
1133     cred_t *credp = crref();
1134     struct vcache *vcp = NULL;
1135     const char *comp = dp->d_name.name;
1136     struct inode *ip = NULL;
1137     int code;
1138
1139     AFS_GLOCK();
1140     code = afs_lookup(VTOAFS(dip), (char *)comp, &vcp, credp);
1141     
1142     if (vcp) {
1143         struct vattr vattr;
1144
1145         ip = AFSTOV(vcp);
1146         afs_getattr(vcp, &vattr, credp);
1147         afs_fill_inode(ip, &vattr);
1148         if (
1149 #ifdef HAVE_LINUX_HLIST_UNHASHED
1150             hlist_unhashed(&ip->i_hash)
1151 #else
1152             ip->i_hash.prev == NULL
1153 #endif
1154             )
1155             insert_inode_hash(ip);
1156     }
1157     dp->d_op = &afs_dentry_operations;
1158     dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1159     AFS_GUNLOCK();
1160
1161 #if defined(AFS_LINUX24_ENV)
1162     if (ip && S_ISDIR(ip->i_mode)) {
1163         struct dentry *alias;
1164
1165         /* Try to invalidate an existing alias in favor of our new one */
1166         alias = d_find_alias(ip);
1167         if (alias) {
1168             if (d_invalidate(alias) == 0) {
1169                 dput(alias);
1170             } else {
1171                 iput(ip);
1172                 crfree(credp);
1173                 return alias;
1174             }
1175         }
1176     }
1177 #endif
1178     d_add(dp, ip);
1179
1180     crfree(credp);
1181
1182     /* It's ok for the file to not be found. That's noted by the caller by
1183      * seeing that the dp->d_inode field is NULL.
1184      */
1185 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
1186     if (code == ENOENT)
1187         return ERR_PTR(0);
1188     else 
1189         return ERR_PTR(afs_convert_code(code));
1190 #else
1191     if (code == ENOENT)
1192         code = 0;
1193     return afs_convert_code(code);
1194 #endif
1195 }
1196
1197 static int
1198 afs_linux_link(struct dentry *olddp, struct inode *dip, struct dentry *newdp)
1199 {
1200     int code;
1201     cred_t *credp = crref();
1202     const char *name = newdp->d_name.name;
1203     struct inode *oldip = olddp->d_inode;
1204
1205     /* If afs_link returned the vnode, we could instantiate the
1206      * dentry. Since it's not, we drop this one and do a new lookup.
1207      */
1208     d_drop(newdp);
1209
1210     AFS_GLOCK();
1211     code = afs_link(VTOAFS(oldip), VTOAFS(dip), (char *)name, credp);
1212
1213     AFS_GUNLOCK();
1214     crfree(credp);
1215     return afs_convert_code(code);
1216 }
1217
1218 static int
1219 afs_linux_unlink(struct inode *dip, struct dentry *dp)
1220 {
1221     int code = EBUSY;
1222     cred_t *credp = crref();
1223     const char *name = dp->d_name.name;
1224     struct vcache *tvc = VTOAFS(dp->d_inode);
1225
1226     if (VREFCOUNT(tvc) > 1 && tvc->opens > 0
1227                                 && !(tvc->f.states & CUnlinked)) {
1228         struct dentry *__dp;
1229         char *__name;
1230
1231         __dp = NULL;
1232         __name = NULL;
1233         do {
1234             dput(__dp);
1235
1236             AFS_GLOCK();
1237             if (__name)
1238                 osi_FreeSmallSpace(__name);
1239             __name = afs_newname();
1240             AFS_GUNLOCK();
1241
1242             __dp = lookup_one_len(__name, dp->d_parent, strlen(__name));
1243                 
1244             if (IS_ERR(__dp))
1245                 goto out;
1246         } while (__dp->d_inode != NULL);
1247
1248         AFS_GLOCK();
1249         code = afs_rename(VTOAFS(dip), (char *)dp->d_name.name, VTOAFS(dip), (char *)__dp->d_name.name, credp);
1250         if (!code) {
1251             tvc->mvid = (void *) __name;
1252             crhold(credp);
1253             if (tvc->uncred) {
1254                 crfree(tvc->uncred);
1255             }
1256             tvc->uncred = credp;
1257             tvc->f.states |= CUnlinked;
1258 #ifdef DCACHE_NFSFS_RENAMED
1259             dp->d_flags |= DCACHE_NFSFS_RENAMED;   
1260 #endif
1261         } else {
1262             osi_FreeSmallSpace(__name); 
1263         }
1264         AFS_GUNLOCK();
1265
1266         if (!code) {
1267             __dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1268             d_move(dp, __dp);
1269         }
1270         dput(__dp);
1271
1272         goto out;
1273     }
1274
1275     AFS_GLOCK();
1276     code = afs_remove(VTOAFS(dip), (char *)name, credp);
1277     AFS_GUNLOCK();
1278     if (!code)
1279         d_drop(dp);
1280 out:
1281     crfree(credp);
1282     return afs_convert_code(code);
1283 }
1284
1285
1286 static int
1287 afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target)
1288 {
1289     int code;
1290     cred_t *credp = crref();
1291     struct vattr vattr;
1292     const char *name = dp->d_name.name;
1293
1294     /* If afs_symlink returned the vnode, we could instantiate the
1295      * dentry. Since it's not, we drop this one and do a new lookup.
1296      */
1297     d_drop(dp);
1298
1299     VATTR_NULL(&vattr);
1300     AFS_GLOCK();
1301     code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp);
1302     AFS_GUNLOCK();
1303     crfree(credp);
1304     return afs_convert_code(code);
1305 }
1306
1307 static int
1308 afs_linux_mkdir(struct inode *dip, struct dentry *dp, int mode)
1309 {
1310     int code;
1311     cred_t *credp = crref();
1312     struct vcache *tvcp = NULL;
1313     struct vattr vattr;
1314     const char *name = dp->d_name.name;
1315
1316     VATTR_NULL(&vattr);
1317     vattr.va_mask = ATTR_MODE;
1318     vattr.va_mode = mode;
1319     AFS_GLOCK();
1320     code = afs_mkdir(VTOAFS(dip), (char *)name, &vattr, &tvcp, credp);
1321
1322     if (tvcp) {
1323         struct inode *ip = AFSTOV(tvcp);
1324
1325         afs_getattr(tvcp, &vattr, credp);
1326         afs_fill_inode(ip, &vattr);
1327
1328         dp->d_op = &afs_dentry_operations;
1329         dp->d_time = hgetlo(VTOAFS(dip)->f.m.DataVersion);
1330         d_instantiate(dp, ip);
1331     }
1332     AFS_GUNLOCK();
1333
1334     crfree(credp);
1335     return afs_convert_code(code);
1336 }
1337
1338 static int
1339 afs_linux_rmdir(struct inode *dip, struct dentry *dp)
1340 {
1341     int code;
1342     cred_t *credp = crref();
1343     const char *name = dp->d_name.name;
1344
1345     /* locking kernel conflicts with glock? */
1346
1347     AFS_GLOCK();
1348     code = afs_rmdir(VTOAFS(dip), (char *)name, credp);
1349     AFS_GUNLOCK();
1350
1351     /* Linux likes to see ENOTEMPTY returned from an rmdir() syscall
1352      * that failed because a directory is not empty. So, we map
1353      * EEXIST to ENOTEMPTY on linux.
1354      */
1355     if (code == EEXIST) {
1356         code = ENOTEMPTY;
1357     }
1358
1359     if (!code) {
1360         d_drop(dp);
1361     }
1362
1363     crfree(credp);
1364     return afs_convert_code(code);
1365 }
1366
1367
1368 static int
1369 afs_linux_rename(struct inode *oldip, struct dentry *olddp,
1370                  struct inode *newip, struct dentry *newdp)
1371 {
1372     int code;
1373     cred_t *credp = crref();
1374     const char *oldname = olddp->d_name.name;
1375     const char *newname = newdp->d_name.name;
1376     struct dentry *rehash = NULL;
1377
1378     if (!list_empty(&newdp->d_hash)) {
1379         d_drop(newdp);
1380         rehash = newdp;
1381     }
1382
1383 #if defined(AFS_LINUX24_ENV)
1384     if (atomic_read(&olddp->d_count) > 1)
1385         shrink_dcache_parent(olddp);
1386 #endif
1387
1388     AFS_GLOCK();
1389     code = afs_rename(VTOAFS(oldip), (char *)oldname, VTOAFS(newip), (char *)newname, credp);
1390     AFS_GUNLOCK();
1391
1392     if (!code)
1393         olddp->d_time = 0;      /* force to revalidate */
1394
1395     if (rehash)
1396         d_rehash(rehash);
1397
1398     crfree(credp);
1399     return afs_convert_code(code);
1400 }
1401
1402
1403 /* afs_linux_ireadlink 
1404  * Internal readlink which can return link contents to user or kernel space.
1405  * Note that the buffer is NOT supposed to be null-terminated.
1406  */
1407 static int
1408 afs_linux_ireadlink(struct inode *ip, char *target, int maxlen, uio_seg_t seg)
1409 {
1410     int code;
1411     cred_t *credp = crref();
1412     struct uio tuio;
1413     struct iovec iov;
1414
1415     setup_uio(&tuio, &iov, target, (afs_offs_t) 0, maxlen, UIO_READ, seg);
1416     code = afs_readlink(VTOAFS(ip), &tuio, credp);
1417     crfree(credp);
1418
1419     if (!code)
1420         return maxlen - tuio.uio_resid;
1421     else
1422         return afs_convert_code(code);
1423 }
1424
1425 #if !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
1426 /* afs_linux_readlink 
1427  * Fill target (which is in user space) with contents of symlink.
1428  */
1429 static int
1430 afs_linux_readlink(struct dentry *dp, char *target, int maxlen)
1431 {
1432     int code;
1433     struct inode *ip = dp->d_inode;
1434
1435     AFS_GLOCK();
1436     code = afs_linux_ireadlink(ip, target, maxlen, AFS_UIOUSER);
1437     AFS_GUNLOCK();
1438     return code;
1439 }
1440
1441
1442 /* afs_linux_follow_link
1443  * a file system dependent link following routine.
1444  */
1445 #if defined(AFS_LINUX24_ENV)
1446 static int afs_linux_follow_link(struct dentry *dentry, struct nameidata *nd)
1447 {
1448     int code;
1449     char *name;
1450
1451     name = osi_Alloc(PATH_MAX);
1452     if (!name) {
1453         return -EIO;
1454     }
1455
1456     AFS_GLOCK();
1457     code = afs_linux_ireadlink(dentry->d_inode, name, PATH_MAX - 1, AFS_UIOSYS);
1458     AFS_GUNLOCK();
1459
1460     if (code < 0) {
1461         goto out;
1462     }
1463
1464     name[code] = '\0';
1465     code = vfs_follow_link(nd, name);
1466
1467 out:
1468     osi_Free(name, PATH_MAX);
1469
1470     return code;
1471 }
1472
1473 #else /* !defined(AFS_LINUX24_ENV) */
1474
1475 static struct dentry *
1476 afs_linux_follow_link(struct dentry *dp, struct dentry *basep,
1477                       unsigned int follow)
1478 {
1479     int code = 0;
1480     char *name;
1481     struct dentry *res;
1482
1483
1484     AFS_GLOCK();
1485     name = osi_Alloc(PATH_MAX + 1);
1486     if (!name) {
1487         AFS_GUNLOCK();
1488         dput(basep);
1489         return ERR_PTR(-EIO);
1490     }
1491
1492     code = afs_linux_ireadlink(dp->d_inode, name, PATH_MAX, AFS_UIOSYS);
1493     AFS_GUNLOCK();
1494
1495     if (code < 0) {
1496         dput(basep);
1497         if (code < -MAX_ERRNO)
1498             res = ERR_PTR(-EIO);
1499         else
1500             res = ERR_PTR(code);
1501     } else {
1502         name[code] = '\0';
1503         res = lookup_dentry(name, basep, follow);
1504     }
1505
1506     AFS_GLOCK();
1507     osi_Free(name, PATH_MAX + 1);
1508     AFS_GUNLOCK();
1509     return res;
1510 }
1511 #endif /* AFS_LINUX24_ENV */
1512 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
1513
1514 static inline int
1515 afs_linux_can_bypass(struct inode *ip) {
1516     switch(cache_bypass_strategy) {
1517         case NEVER_BYPASS_CACHE:
1518             return 0;
1519         case ALWAYS_BYPASS_CACHE:
1520             return 1;
1521         case LARGE_FILES_BYPASS_CACHE:
1522             if(i_size_read(ip) > cache_bypass_threshold)
1523                 return 1;
1524         default:
1525             return 0;
1526      }
1527 }
1528
1529 /* afs_linux_readpage
1530  * all reads come through here. A strategy-like read call.
1531  */
1532 static int
1533 afs_linux_readpage(struct file *fp, struct page *pp)
1534 {
1535     afs_int32 code;
1536 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1537     char *address;
1538     afs_offs_t offset = ((loff_t) pp->index) << PAGE_CACHE_SHIFT;
1539 #else
1540     ulong address = afs_linux_page_address(pp);
1541     afs_offs_t offset = pageoff(pp);
1542 #endif
1543     afs_int32 bypasscache = 0; /* bypass for this read */
1544     struct nocache_read_request *ancr;
1545 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1546     afs_int32 isize;
1547 #endif
1548     struct uio *auio;
1549     struct iovec *iovecp;
1550     struct inode *ip = FILE_INODE(fp);
1551     afs_int32 cnt = page_count(pp);
1552     struct vcache *avc = VTOAFS(ip);
1553     cred_t *credp;
1554
1555     credp = crref();
1556 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1557     address = kmap(pp);
1558     ClearPageError(pp);
1559 #else
1560     atomic_add(1, &pp->count);
1561     set_bit(PG_locked, &pp->flags);     /* other bits? See mm.h */
1562     clear_bit(PG_error, &pp->flags);
1563 #endif
1564     /* if bypasscache, receiver frees, else we do */
1565     auio = osi_Alloc(sizeof(struct uio));
1566     iovecp = osi_Alloc(sizeof(struct iovec));
1567
1568     setup_uio(auio, iovecp, (char *)address, offset, PAGE_SIZE, UIO_READ,
1569               AFS_UIOSYS);
1570
1571     bypasscache = afs_linux_can_bypass(ip);
1572
1573     /* In the new incarnation of selective caching, a file's caching policy
1574      * can change, eg because file size exceeds threshold, etc. */
1575     trydo_cache_transition(avc, credp, bypasscache);
1576         
1577     if(bypasscache) {
1578         if(address)
1579             kunmap(pp);
1580         /* save the page for background map */
1581         auio->uio_iov->iov_base = (void*) pp;
1582         /* the background thread will free this */
1583         ancr = osi_Alloc(sizeof(struct nocache_read_request));
1584         ancr->auio = auio;
1585         ancr->offset = offset;
1586         ancr->length = PAGE_SIZE;
1587
1588         maybe_lock_kernel();
1589         code = afs_ReadNoCache(avc, ancr, credp);
1590         maybe_unlock_kernel();
1591
1592         goto done; /* skips release page, doing it in bg thread */
1593     }
1594                   
1595 #ifdef AFS_LINUX24_ENV
1596     maybe_lock_kernel();
1597 #endif
1598     AFS_GLOCK();
1599     AFS_DISCON_LOCK();
1600     afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
1601                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
1602                99999);  /* not a possible code value */
1603
1604     code = afs_rdwr(avc, auio, UIO_READ, 0, credp);
1605         
1606     afs_Trace4(afs_iclSetp, CM_TRACE_READPAGE, ICL_TYPE_POINTER, ip,
1607                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, cnt, ICL_TYPE_INT32,
1608                code);
1609     AFS_DISCON_UNLOCK();
1610     AFS_GUNLOCK();
1611 #ifdef AFS_LINUX24_ENV
1612     maybe_unlock_kernel();
1613 #endif
1614     if (!code) {
1615         /* XXX valid for no-cache also?  Check last bits of files... :)
1616          * Cognate code goes in afs_NoCacheFetchProc.  */
1617         if (auio->uio_resid)    /* zero remainder of page */
1618              memset((void *)(address + (PAGE_SIZE - auio->uio_resid)), 0,
1619                     auio->uio_resid);
1620
1621 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1622         flush_dcache_page(pp);
1623         SetPageUptodate(pp);
1624 #else
1625         set_bit(PG_uptodate, &pp->flags);
1626 #endif
1627     } /* !code */
1628
1629 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
1630     kunmap(pp);
1631     UnlockPage(pp);
1632 #else
1633     clear_bit(PG_locked, &pp->flags);
1634     wake_up(&pp->wait);
1635     free_page(address);
1636 #endif
1637
1638     /* do not call afs_GetDCache if cache is bypassed */
1639     if(bypasscache)
1640         goto done;
1641
1642     /* free if not bypassing cache */
1643     osi_Free(auio, sizeof(struct uio));
1644     osi_Free(iovecp, sizeof(struct iovec));
1645
1646     if (!code && AFS_CHUNKOFFSET(offset) == 0) {
1647         struct dcache *tdc;
1648         struct vrequest treq;
1649
1650         AFS_GLOCK();
1651         code = afs_InitReq(&treq, credp);
1652         if (!code && !NBObtainWriteLock(&avc->lock, 534)) {
1653             tdc = afs_FindDCache(avc, offset);
1654             if (tdc) {
1655                 if (!(tdc->mflags & DFNextStarted))
1656                     afs_PrefetchChunk(avc, tdc, credp, &treq);
1657                     afs_PutDCache(tdc);
1658             }
1659             ReleaseWriteLock(&avc->lock);
1660         }
1661         AFS_GUNLOCK();
1662     }
1663
1664 done:
1665     crfree(credp);
1666     return afs_convert_code(code);
1667 }
1668
1669 #if defined(AFS_LINUX24_ENV)
1670 static int
1671 afs_linux_writepage_sync(struct inode *ip, struct page *pp,
1672                          unsigned long offset, unsigned int count)
1673 {
1674     struct vcache *vcp = VTOAFS(ip);
1675     char *buffer;
1676     afs_offs_t base;
1677     int code = 0;
1678     cred_t *credp;
1679     struct uio tuio;
1680     struct iovec iovec;
1681     int f_flags = 0;
1682
1683     buffer = kmap(pp) + offset;
1684     base = (((loff_t) pp->index) << PAGE_CACHE_SHIFT)  + offset;
1685
1686     credp = crref();
1687     maybe_lock_kernel();
1688     AFS_GLOCK();
1689     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1690                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1691                ICL_TYPE_INT32, 99999);
1692
1693     ObtainWriteLock(&vcp->lock, 532);
1694     if (vcp->f.states & CPageWrite) {
1695         ReleaseWriteLock(&vcp->lock);
1696         AFS_GUNLOCK();
1697         maybe_unlock_kernel();
1698         crfree(credp);
1699         kunmap(pp);
1700         /* should mark it dirty? */
1701         return(0); 
1702     }
1703     vcp->f.states |= CPageWrite;
1704     ReleaseWriteLock(&vcp->lock);
1705
1706     setup_uio(&tuio, &iovec, buffer, base, count, UIO_WRITE, AFS_UIOSYS);
1707
1708     code = afs_write(vcp, &tuio, f_flags, credp, 0);
1709
1710     i_size_write(ip, vcp->f.m.Length);
1711     ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
1712
1713     ObtainWriteLock(&vcp->lock, 533);
1714     if (!code) {
1715         struct vrequest treq;
1716
1717         if (!afs_InitReq(&treq, credp))
1718             code = afs_DoPartialWrite(vcp, &treq);
1719     }
1720     code = code ? afs_convert_code(code) : count - tuio.uio_resid;
1721
1722     vcp->f.states &= ~CPageWrite;
1723     ReleaseWriteLock(&vcp->lock);
1724
1725     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1726                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1727                ICL_TYPE_INT32, code);
1728
1729     AFS_GUNLOCK();
1730     maybe_unlock_kernel();
1731     crfree(credp);
1732     kunmap(pp);
1733
1734     return code;
1735 }
1736
1737
1738 static int
1739 #ifdef AOP_WRITEPAGE_TAKES_WRITEBACK_CONTROL
1740 afs_linux_writepage(struct page *pp, struct writeback_control *wbc)
1741 #else
1742 afs_linux_writepage(struct page *pp)
1743 #endif
1744 {
1745     struct address_space *mapping = pp->mapping;
1746     struct inode *inode;
1747     unsigned long end_index;
1748     unsigned offset = PAGE_CACHE_SIZE;
1749     long status;
1750
1751     if (PageLaunder(pp)) {
1752         return(fail_writepage(pp));
1753     }
1754
1755     inode = (struct inode *)mapping->host;
1756     end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
1757
1758     /* easy case */
1759     if (pp->index < end_index)
1760         goto do_it;
1761     /* things got complicated... */
1762     offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1);
1763     /* OK, are we completely out? */
1764     if (pp->index >= end_index + 1 || !offset)
1765         return -EIO;
1766   do_it:
1767     status = afs_linux_writepage_sync(inode, pp, 0, offset);
1768     SetPageUptodate(pp);
1769     UnlockPage(pp);
1770     if (status == offset)
1771         return 0;
1772     else
1773         return status;
1774 }
1775 #else
1776 /* afs_linux_updatepage
1777  * What one would have thought was writepage - write dirty page to file.
1778  * Called from generic_file_write. buffer is still in user space. pagep
1779  * has been filled in with old data if we're updating less than a page.
1780  */
1781 static int
1782 afs_linux_updatepage(struct file *fp, struct page *pp, unsigned long offset,
1783                      unsigned int count, int sync)
1784 {
1785     struct vcache *vcp = VTOAFS(FILE_INODE(fp));
1786     u8 *page_addr = (u8 *) afs_linux_page_address(pp);
1787     int code = 0;
1788     cred_t *credp;
1789     struct uio tuio;
1790     struct iovec iovec;
1791
1792     set_bit(PG_locked, &pp->flags);
1793
1794     credp = crref();
1795     AFS_GLOCK();
1796     AFS_DISCON_LOCK();
1797     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1798                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1799                ICL_TYPE_INT32, 99999);
1800     setup_uio(&tuio, &iovec, page_addr + offset,
1801               (afs_offs_t) (pageoff(pp) + offset), count, UIO_WRITE,
1802               AFS_UIOSYS);
1803
1804     code = afs_write(vcp, &tuio, fp->f_flags, credp, 0);
1805
1806     i_size_write(ip, vcp->f.m.Length);
1807     ip->i_blocks = ((vcp->f.m.Length + 1023) >> 10) << 1;
1808
1809     if (!code) {
1810         struct vrequest treq;
1811
1812         ObtainWriteLock(&vcp->lock, 533);
1813         vcp->f.m.Date = osi_Time();   /* set modification time */
1814         if (!afs_InitReq(&treq, credp))
1815             code = afs_DoPartialWrite(vcp, &treq);
1816         ReleaseWriteLock(&vcp->lock);
1817     }
1818
1819     code = code ? afs_convert_code(code) : count - tuio.uio_resid;
1820     afs_Trace4(afs_iclSetp, CM_TRACE_UPDATEPAGE, ICL_TYPE_POINTER, vcp,
1821                ICL_TYPE_POINTER, pp, ICL_TYPE_INT32, page_count(pp),
1822                ICL_TYPE_INT32, code);
1823
1824     AFS_DISCON_UNLOCK();
1825     AFS_GUNLOCK();
1826     crfree(credp);
1827
1828     clear_bit(PG_locked, &pp->flags);
1829     return code;
1830 }
1831 #endif
1832
1833 /* afs_linux_permission
1834  * Check access rights - returns error if can't check or permission denied.
1835  */
1836 static int
1837 #ifdef IOP_PERMISSION_TAKES_NAMEIDATA
1838 afs_linux_permission(struct inode *ip, int mode, struct nameidata *nd)
1839 #else
1840 afs_linux_permission(struct inode *ip, int mode)
1841 #endif
1842 {
1843     int code;
1844     cred_t *credp = crref();
1845     int tmp = 0;
1846
1847     AFS_GLOCK();
1848     if (mode & MAY_EXEC)
1849         tmp |= VEXEC;
1850     if (mode & MAY_READ)
1851         tmp |= VREAD;
1852     if (mode & MAY_WRITE)
1853         tmp |= VWRITE;
1854     code = afs_access(VTOAFS(ip), tmp, credp);
1855
1856     AFS_GUNLOCK();
1857     crfree(credp);
1858     return afs_convert_code(code);
1859 }
1860
1861 #if defined(AFS_LINUX24_ENV) && !defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
1862 static int
1863 afs_linux_commit_write(struct file *file, struct page *page, unsigned offset,
1864                        unsigned to)
1865 {
1866     int code;
1867
1868     code = afs_linux_writepage_sync(file->f_dentry->d_inode, page,
1869                                     offset, to - offset);
1870     kunmap(page);
1871
1872     return code;
1873 }
1874
1875 static int
1876 afs_linux_prepare_write(struct file *file, struct page *page, unsigned from,
1877                         unsigned to)
1878 {
1879 /* sometime between 2.4.0 and 2.4.19, the callers of prepare_write began to
1880    call kmap directly instead of relying on us to do it */
1881     kmap(page);
1882     return 0;
1883 }
1884 #endif
1885
1886 #if defined(STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
1887 static int
1888 afs_linux_write_end(struct file *file, struct address_space *mapping,
1889                                 loff_t pos, unsigned len, unsigned copied,
1890                                 struct page *page, void *fsdata)
1891 {
1892     int code;
1893     unsigned from = pos & (PAGE_CACHE_SIZE - 1);
1894
1895     code = afs_linux_writepage_sync(file->f_dentry->d_inode, page,
1896                                     from, copied);
1897     unlock_page(page);
1898     page_cache_release(page);
1899     return code;
1900 }
1901
1902 static int
1903 afs_linux_write_begin(struct file *file, struct address_space *mapping,
1904                                 loff_t pos, unsigned len, unsigned flags,
1905                                 struct page **pagep, void **fsdata)
1906 {
1907     struct page *page;
1908     pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1909 #if defined(HAVE_LINUX_GRAB_CACHE_PAGE_WRITE_BEGIN)
1910     page = grab_cache_page_write_begin(mapping, index, flags);
1911 #else
1912     page = __grab_cache_page(mapping, index);
1913 #endif
1914     *pagep = page;
1915
1916     return 0;
1917 }
1918 #endif
1919
1920
1921 static struct inode_operations afs_file_iops = {
1922 #if defined(AFS_LINUX24_ENV)
1923   .permission =         afs_linux_permission,
1924   .revalidate =         afs_linux_revalidate,
1925   .setattr =            afs_notify_change,
1926 #else
1927   .default_file_ops =   &afs_file_fops,
1928   .readpage =           afs_linux_readpage,  
1929   .revalidate =         afs_linux_revalidate,
1930   .updatepage =         afs_linux_updatepage,
1931 #endif
1932 };
1933
1934 #if defined(AFS_LINUX24_ENV)
1935 static struct address_space_operations afs_file_aops = {
1936   .readpage =           afs_linux_readpage,
1937   .writepage =          afs_linux_writepage,
1938 #if defined (STRUCT_ADDRESS_SPACE_OPERATIONS_HAS_WRITE_BEGIN)
1939   .write_begin =        afs_linux_write_begin,
1940   .write_end =          afs_linux_write_end,
1941 #else
1942   .commit_write =       afs_linux_commit_write,
1943   .prepare_write =      afs_linux_prepare_write,
1944 #endif
1945 };
1946 #endif
1947
1948
1949 /* Separate ops vector for directories. Linux 2.2 tests type of inode
1950  * by what sort of operation is allowed.....
1951  */
1952
1953 static struct inode_operations afs_dir_iops = {
1954 #if !defined(AFS_LINUX24_ENV)
1955   .default_file_ops =   &afs_dir_fops,
1956 #else
1957   .setattr =            afs_notify_change,
1958 #endif
1959   .create =             afs_linux_create,
1960   .lookup =             afs_linux_lookup,
1961   .link =               afs_linux_link,
1962   .unlink =             afs_linux_unlink,
1963   .symlink =            afs_linux_symlink,
1964   .mkdir =              afs_linux_mkdir,
1965   .rmdir =              afs_linux_rmdir,
1966   .rename =             afs_linux_rename,
1967   .revalidate =         afs_linux_revalidate,
1968   .permission =         afs_linux_permission,
1969 };
1970
1971 /* We really need a separate symlink set of ops, since do_follow_link()
1972  * determines if it _is_ a link by checking if the follow_link op is set.
1973  */
1974 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
1975 static int
1976 afs_symlink_filler(struct file *file, struct page *page)
1977 {
1978     struct inode *ip = (struct inode *)page->mapping->host;
1979     char *p = (char *)kmap(page);
1980     int code;
1981
1982     maybe_lock_kernel();
1983     AFS_GLOCK();
1984     code = afs_linux_ireadlink(ip, p, PAGE_SIZE, AFS_UIOSYS);
1985     AFS_GUNLOCK();
1986
1987     if (code < 0)
1988         goto fail;
1989     p[code] = '\0';             /* null terminate? */
1990     maybe_unlock_kernel();
1991
1992     SetPageUptodate(page);
1993     kunmap(page);
1994     UnlockPage(page);
1995     return 0;
1996
1997   fail:
1998     maybe_unlock_kernel();
1999
2000     SetPageError(page);
2001     kunmap(page);
2002     UnlockPage(page);
2003     return code;
2004 }
2005
2006 static struct address_space_operations afs_symlink_aops = {
2007   .readpage =   afs_symlink_filler
2008 };
2009 #endif  /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
2010
2011 static struct inode_operations afs_symlink_iops = {
2012 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
2013   .readlink =           page_readlink,
2014 #if defined(HAVE_KERNEL_PAGE_FOLLOW_LINK)
2015   .follow_link =        page_follow_link,
2016 #else
2017   .follow_link =        page_follow_link_light,
2018   .put_link =           page_put_link,
2019 #endif
2020 #else /* !defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE) */
2021   .readlink =           afs_linux_readlink,
2022   .follow_link =        afs_linux_follow_link,
2023 #if !defined(AFS_LINUX24_ENV)
2024   .permission =         afs_linux_permission,
2025   .revalidate =         afs_linux_revalidate,
2026 #endif
2027 #endif /* USABLE_KERNEL_PAGE_SYMLINK_CACHE */
2028 #if defined(AFS_LINUX24_ENV)
2029   .setattr =            afs_notify_change,
2030 #endif
2031 };
2032
2033 void
2034 afs_fill_inode(struct inode *ip, struct vattr *vattr)
2035 {
2036         
2037     if (vattr)
2038         vattr2inode(ip, vattr);
2039
2040 /* Reset ops if symlink or directory. */
2041     if (S_ISREG(ip->i_mode)) {
2042         ip->i_op = &afs_file_iops;
2043 #if defined(AFS_LINUX24_ENV)
2044         ip->i_fop = &afs_file_fops;
2045         ip->i_data.a_ops = &afs_file_aops;
2046 #endif
2047
2048     } else if (S_ISDIR(ip->i_mode)) {
2049         ip->i_op = &afs_dir_iops;
2050 #if defined(AFS_LINUX24_ENV)
2051         ip->i_fop = &afs_dir_fops;
2052 #endif
2053
2054     } else if (S_ISLNK(ip->i_mode)) {
2055         ip->i_op = &afs_symlink_iops;
2056 #if defined(USABLE_KERNEL_PAGE_SYMLINK_CACHE)
2057         ip->i_data.a_ops = &afs_symlink_aops;
2058         ip->i_mapping = &ip->i_data;
2059 #endif
2060     }
2061
2062 }