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