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