volinfo-dont-bomb-on-attach-failure-20050310
[openafs.git] / src / afs / LINUX / osi_vfsops.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  * VFS operations for Linux
12  *
13  * super_block operations should return negated errno to Linux.
14  */
15 #include <afsconfig.h>
16 #include "afs/param.h"
17
18 RCSID
19     ("$Header$");
20
21 #define __NO_VERSION__          /* don't define kernel_version in module.h */
22 #include <linux/module.h> /* early to avoid printf->printk mapping */
23 #include "afs/sysincludes.h"
24 #include "afsincludes.h"
25 #include "afs/afs_stats.h"
26 #if !defined(AFS_LINUX26_ENV)
27 #include "h/locks.h"
28 #endif
29 #if defined(AFS_LINUX24_ENV)
30 #include "h/smp_lock.h"
31 #endif
32
33
34 struct vcache *afs_globalVp = 0;
35 struct vfs *afs_globalVFS = 0;
36 #if defined(AFS_LINUX24_ENV)
37 struct vfsmount *afs_cacheMnt;
38 #endif
39 int afs_was_mounted = 0;        /* Used to force reload if mount/unmount/mount */
40
41 extern struct super_operations afs_sops;
42 extern afs_rwlock_t afs_xvcache;
43 extern struct afs_q VLRU;
44
45 extern struct dentry_operations afs_dentry_operations;
46
47 /* Forward declarations */
48 static void iattr2vattr(struct vattr *vattrp, struct iattr *iattrp);
49 static void update_inode_cache(struct inode *ip, struct vattr *vp);
50 static int afs_root(struct super_block *afsp);
51 struct super_block *afs_read_super(struct super_block *sb, void *data, int silent);
52 int afs_fill_super(struct super_block *sb, void *data, int silent);
53 static struct super_block *afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data);
54
55 /* afs_file_system
56  * VFS entry for Linux - installed in init_module
57  * Linux mounts file systems by:
58  * 1) register_filesystem(&afs_file_system) - done in init_module
59  * 2) Mount call comes to us via do_mount -> read_super -> afs_read_super.
60  *    We are expected to setup the super_block. See afs_read_super.
61  */
62 #if defined(AFS_LINUX26_ENV)
63 struct backing_dev_info afs_backing_dev_info = {
64         .ra_pages       = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
65         .state          = 0,
66 };
67
68 struct file_system_type afs_fs_type = {
69     .owner = THIS_MODULE,
70     .name = "afs",
71     .get_sb = afs_get_sb,
72     .kill_sb = kill_anon_super,
73     .fs_flags = FS_BINARY_MOUNTDATA,
74 };
75 #elif defined(AFS_LINUX24_ENV)
76 DECLARE_FSTYPE(afs_fs_type, "afs", afs_read_super, 0);
77 #else
78 struct file_system_type afs_fs_type = {
79     "afs",                      /* name - used by mount operation. */
80     0,                          /* requires_dev - no for network filesystems. mount() will 
81                                  * pass us an "unnamed" device. */
82     afs_read_super,             /* wrapper to afs_mount */
83     NULL                        /* pointer to next file_system_type once registered. */
84 };
85 #endif
86
87 /* afs_read_super
88  * read the "super block" for AFS - roughly eguivalent to struct vfs.
89  * dev, covered, s_rd_only, s_dirt, and s_type will be set by read_super.
90  */
91 #if defined(AFS_LINUX26_ENV)
92 static struct super_block *
93 afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
94 {
95     return get_sb_nodev(fs_type, flags, data, afs_fill_super);
96 }
97
98 int
99 afs_fill_super(struct super_block *sb, void *data, int silent)
100 #else
101 struct super_block *
102 afs_read_super(struct super_block *sb, void *data, int silent)
103 #endif
104 {
105     int code = 0;
106
107     AFS_GLOCK();
108     if (afs_was_mounted) {
109         printf
110             ("You must reload the AFS kernel extensions before remounting AFS.\n");
111         AFS_GUNLOCK();
112 #if defined(AFS_LINUX26_ENV)
113         return -EINVAL;
114 #else
115         return NULL;
116 #endif
117     }
118     afs_was_mounted = 1;
119
120     /* Set basics of super_block */
121 #if !defined(AFS_LINUX24_ENV)
122     lock_super(sb);
123 #endif
124 #if defined(AFS_LINUX26_ENV)
125    __module_get(THIS_MODULE);
126 #else
127     MOD_INC_USE_COUNT;
128 #endif
129
130     afs_globalVFS = sb;
131     sb->s_blocksize = 1024;
132     sb->s_blocksize_bits = 10;
133     sb->s_magic = AFS_VFSMAGIC;
134     sb->s_op = &afs_sops;       /* Super block (vfs) ops */
135 #if defined(MAX_NON_LFS)
136     sb->s_maxbytes = MAX_NON_LFS;
137 #endif
138     code = afs_root(sb);
139     if (code) {
140         afs_globalVFS = NULL;
141 #if defined(AFS_LINUX26_ENV)
142         module_put(THIS_MODULE);
143 #else
144         MOD_DEC_USE_COUNT;
145 #endif
146     }
147
148 #if !defined(AFS_LINUX24_ENV)
149     unlock_super(sb);
150 #endif
151
152     AFS_GUNLOCK();
153 #if defined(AFS_LINUX26_ENV)
154     return code ? -EINVAL : 0;
155 #else
156     return code ? NULL : sb;
157 #endif
158 }
159
160
161 /* afs_root - stat the root of the file system. AFS global held on entry. */
162 static int
163 afs_root(struct super_block *afsp)
164 {
165     register afs_int32 code = 0;
166     struct vrequest treq;
167     register struct vcache *tvp = 0;
168
169     AFS_STATCNT(afs_root);
170     if (afs_globalVp && (afs_globalVp->states & CStatd)) {
171         tvp = afs_globalVp;
172     } else {
173         cred_t *credp = crref();
174
175         if (afs_globalVp) {
176             afs_PutVCache(afs_globalVp);
177             afs_globalVp = NULL;
178         }
179
180         if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) {
181             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
182             if (tvp) {
183                 extern struct inode_operations afs_dir_iops;
184 #if defined(AFS_LINUX24_ENV)
185                 extern struct file_operations afs_dir_fops;
186 #endif
187
188                 /* "/afs" is a directory, reset inode ops accordingly. */
189                 AFSTOV(tvp)->v_op = &afs_dir_iops;
190 #if defined(AFS_LINUX24_ENV)
191                 AFSTOV(tvp)->v_fop = &afs_dir_fops;
192 #endif
193
194                 /* setup super_block and mount point inode. */
195                 afs_globalVp = tvp;
196 #if defined(AFS_LINUX24_ENV)
197                 afsp->s_root = d_alloc_root(AFSTOI(tvp));
198 #else
199                 afsp->s_root = d_alloc_root(AFSTOI(tvp), NULL);
200 #endif
201                 afsp->s_root->d_op = &afs_dentry_operations;
202             } else
203                 code = ENOENT;
204         }
205         crfree(credp);
206     }
207
208     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, afs_globalVp,
209                ICL_TYPE_INT32, code);
210     return code;
211 }
212
213 /* super_operations */
214
215 /* afs_notify_change
216  * Linux version of setattr call. What to change is in the iattr struct.
217  * We need to set bits in both the Linux inode as well as the vcache.
218  */
219 int
220 afs_notify_change(struct dentry *dp, struct iattr *iattrp)
221 {
222     struct vattr vattr;
223     int code;
224     cred_t *credp = crref();
225     struct inode *ip = dp->d_inode;
226
227     AFS_GLOCK();
228 #if defined(AFS_LINUX26_ENV)
229     lock_kernel();
230 #endif
231     VATTR_NULL(&vattr);
232     iattr2vattr(&vattr, iattrp);        /* Convert for AFS vnodeops call. */
233     update_inode_cache(ip, &vattr);
234     code = afs_setattr(ITOAFS(ip), &vattr, credp);
235     afs_CopyOutAttrs(ITOAFS(ip), &vattr);
236     /* Note that the inode may still not have all the correct info. But at
237      * least we've got the newest version of what was supposed to be set.
238      */
239
240 #if defined(AFS_LINUX26_ENV)
241     unlock_kernel();
242 #endif
243     AFS_GUNLOCK();
244     crfree(credp);
245     return -code;
246 }
247
248
249 /* This list is simply used to initialize the i_list member of the
250  * linux inode. This stops linux inode syncing code from choking on our
251  * inodes.
252  */
253 static LIST_HEAD(dummy_inode_list);
254
255
256 /* This is included for documentation only. */
257 /* afs_write_inode
258  * Used to flush in core inode to disk. We don't need to do this. Top level
259  * write_inode() routine will clear i_dirt. If this routine is in the table,
260  * it's expected to do the cleaning and clear i_dirt.
261  * 
262  * 9/24/99: This is what we thought until we discovered msync() does end up calling
263  * this function to sync a single inode to disk. msync() only flushes selective
264  * pages to disk. So it needs an inode syncing function to update metadata when it
265  * has synced some pages of a file to disk.
266  */
267 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
268 #ifdef WRITE_INODE_NOT_VOID
269 static int
270 #else
271 static void
272 #endif
273 afs_write_inode(struct inode *ip, int unused)
274 #else
275 static void
276 afs_write_inode(struct inode *ip)
277 #endif
278 {
279     list_del(&ip->i_list);
280     /* and put it back on our dummy list. */
281     put_inode_on_dummy_list(ip);
282
283     /* for now we don't actually update the metadata during msync. This
284      * is just to keep linux happy.  */
285 #ifdef WRITE_INODE_NOT_VOID
286     return 0;
287 #endif
288 }
289
290
291 static void
292 afs_destroy_inode(struct inode *ip)
293 {
294     ip->i_state = 0;
295 }
296
297
298 /* afs_put_inode
299  * called from iput when count goes to zero. Linux version of inactive.
300  * For Linux 2.2, this funcionality has moved to the delete inode super op.
301  * If we use the common inode pool, we'll need to set i_nlink to 0 here.
302  * That will trigger the call to delete routine.
303  */
304
305 static void
306 afs_delete_inode(struct inode *ip)
307 {
308 #ifdef AFS_LINUX26_ENV
309     put_inode_on_dummy_list(ip);
310 #endif
311
312     AFS_GLOCK();
313     osi_clear_inode(ip);
314     AFS_GUNLOCK();
315 }
316
317
318 /* afs_put_super
319  * Called from unmount to release super_block. */
320 static void
321 afs_put_super(struct super_block *sbp)
322 {
323     int code = 0;
324
325     AFS_GLOCK();
326     AFS_STATCNT(afs_unmount);
327
328 #if !defined(AFS_LINUX26_ENV)
329     if (!suser()) {
330         AFS_GUNLOCK();
331         return;
332     }
333 #endif
334
335     afs_globalVFS = 0;
336     afs_globalVp = 0;
337     afs_shutdown();
338 #if defined(AFS_LINUX24_ENV)
339     mntput(afs_cacheMnt);
340 #endif
341
342     osi_linux_verify_alloced_memory();
343     AFS_GUNLOCK();
344
345     if (!code) {
346         sbp->s_dev = 0;
347 #if defined(AFS_LINUX26_ENV)
348         module_put(THIS_MODULE);
349 #else
350         MOD_DEC_USE_COUNT;
351 #endif
352     }
353 }
354
355
356 /* afs_statfs
357  * statp is in user space, so we need to cobble together a statfs, then
358  * copy it.
359  */
360 #if defined(AFS_LINUX26_ENV)
361 int
362 afs_statfs(struct super_block *sbp, struct kstatfs *statp)
363 #elif defined(AFS_LINUX24_ENV)
364 int
365 afs_statfs(struct super_block *sbp, struct statfs *statp)
366 #else
367 int
368 afs_statfs(struct super_block *sbp, struct statfs *__statp, int size)
369 #endif
370 {
371 #if !defined(AFS_LINUX24_ENV)
372     struct statfs stat;
373
374     if (size < sizeof(struct statfs))
375         return;
376
377     memset(&stat, 0, size);
378     statp = &stat;
379 #else
380     memset(statp, 0, sizeof(*statp));
381 #endif
382
383     AFS_STATCNT(afs_statfs);
384
385     statp->f_type = 0;          /* Can we get a real type sometime? */
386     statp->f_bsize = sbp->s_blocksize;
387     statp->f_blocks = statp->f_bfree = statp->f_bavail = statp->f_files =
388         statp->f_ffree = 9000000;
389     statp->f_fsid.val[0] = AFS_VFSMAGIC;
390     statp->f_fsid.val[1] = AFS_VFSFSID;
391     statp->f_namelen = 256;
392
393 #if !defined(AFS_LINUX24_ENV)
394     memcpy_tofs(__statp, &stat, size);
395 #endif
396     return 0;
397 }
398
399 void
400 afs_umount_begin(struct super_block *sbp)
401 {
402     afs_shuttingdown = 1;
403 }
404
405 struct super_operations afs_sops = {
406 #if defined(AFS_LINUX26_ENV)
407   .drop_inode =         generic_delete_inode,
408   .destroy_inode =      afs_destroy_inode,
409 #endif
410   .delete_inode =       afs_delete_inode,
411   .write_inode =        afs_write_inode,
412   .put_super =          afs_put_super,
413   .statfs =             afs_statfs,
414   .umount_begin =       afs_umount_begin
415 #if !defined(AFS_LINUX24_ENV)
416   .notify_change =      afs_notify_change,
417 #endif
418 };
419
420 /************** Support routines ************************/
421
422 /* vattr_setattr
423  * Set iattr data into vattr. Assume vattr cleared before call.
424  */
425 static void
426 iattr2vattr(struct vattr *vattrp, struct iattr *iattrp)
427 {
428     vattrp->va_mask = iattrp->ia_valid;
429     if (iattrp->ia_valid & ATTR_MODE)
430         vattrp->va_mode = iattrp->ia_mode;
431     if (iattrp->ia_valid & ATTR_UID)
432         vattrp->va_uid = iattrp->ia_uid;
433     if (iattrp->ia_valid & ATTR_GID)
434         vattrp->va_gid = iattrp->ia_gid;
435     if (iattrp->ia_valid & ATTR_SIZE)
436         vattrp->va_size = iattrp->ia_size;
437     if (iattrp->ia_valid & ATTR_ATIME) {
438 #if defined(AFS_LINUX26_ENV)
439         vattrp->va_atime.tv_sec = iattrp->ia_atime.tv_sec;
440 #else
441         vattrp->va_atime.tv_sec = iattrp->ia_atime;
442 #endif
443         vattrp->va_atime.tv_usec = 0;
444     }
445     if (iattrp->ia_valid & ATTR_MTIME) {
446 #if defined(AFS_LINUX26_ENV)
447         vattrp->va_mtime.tv_sec = iattrp->ia_mtime.tv_sec;
448 #else
449         vattrp->va_mtime.tv_sec = iattrp->ia_mtime;
450 #endif
451         vattrp->va_mtime.tv_usec = 0;
452     }
453     if (iattrp->ia_valid & ATTR_CTIME) {
454 #if defined(AFS_LINUX26_ENV)
455         vattrp->va_ctime.tv_sec = iattrp->ia_ctime.tv_sec;
456 #else
457         vattrp->va_ctime.tv_sec = iattrp->ia_ctime;
458 #endif
459         vattrp->va_ctime.tv_usec = 0;
460     }
461 }
462
463 /* update_inode_cache
464  * Update inode with info from vattr struct. Use va_mask to determine what
465  * to update.
466  */
467 static void
468 update_inode_cache(struct inode *ip, struct vattr *vp)
469 {
470     if (vp->va_mask & ATTR_MODE)
471         ip->i_mode = vp->va_mode;
472     if (vp->va_mask & ATTR_UID)
473         ip->i_uid = vp->va_uid;
474     if (vp->va_mask & ATTR_GID)
475         ip->i_gid = vp->va_gid;
476     if (vp->va_mask & ATTR_SIZE)
477         ip->i_size = vp->va_size;
478     if (vp->va_mask & ATTR_ATIME)
479 #if defined(AFS_LINUX26_ENV)
480         ip->i_atime.tv_sec = vp->va_atime.tv_sec;
481 #else
482         ip->i_atime = vp->va_atime.tv_sec;
483 #endif
484     if (vp->va_mask & ATTR_MTIME)
485 #if defined(AFS_LINUX26_ENV)
486         ip->i_mtime.tv_sec = vp->va_mtime.tv_sec;
487 #else
488         ip->i_mtime = vp->va_mtime.tv_sec;
489 #endif
490     if (vp->va_mask & ATTR_CTIME)
491 #if defined(AFS_LINUX26_ENV)
492         ip->i_ctime.tv_sec = vp->va_ctime.tv_sec;
493 #else
494         ip->i_ctime = vp->va_ctime.tv_sec;
495 #endif
496 }
497
498 /* vattr2inode
499  * Rewrite the inode cache from the attr. Assumes all vattr fields are valid.
500  */
501 void
502 vattr2inode(struct inode *ip, struct vattr *vp)
503 {
504     ip->i_ino = vp->va_nodeid;
505     ip->i_nlink = vp->va_nlink;
506     ip->i_blocks = vp->va_blocks;
507     ip->i_blksize = vp->va_blocksize;
508     ip->i_rdev = vp->va_rdev;
509     ip->i_mode = vp->va_mode;
510     ip->i_uid = vp->va_uid;
511     ip->i_gid = vp->va_gid;
512     ip->i_size = vp->va_size;
513 #if defined(AFS_LINUX26_ENV)
514     ip->i_atime.tv_sec = vp->va_atime.tv_sec;
515     ip->i_mtime.tv_sec = vp->va_mtime.tv_sec;
516     ip->i_ctime.tv_sec = vp->va_ctime.tv_sec;
517 #else
518     ip->i_atime = vp->va_atime.tv_sec;
519     ip->i_mtime = vp->va_mtime.tv_sec;
520     ip->i_ctime = vp->va_ctime.tv_sec;
521 #endif
522 }
523
524 /* Put this afs inode on our own dummy list. Linux expects to see inodes
525  * nicely strung up in lists. Linux inode syncing code chokes on our inodes if
526  * they're not on any lists.
527  */
528 void
529 put_inode_on_dummy_list(struct inode *ip)
530 {
531     /* Initialize list. See explanation above. */
532     list_add(&ip->i_list, &dummy_inode_list);
533 }
534
535 /* And yet another routine to update the inode cache - called from ProcessFS */
536 void
537 vcache2inode(struct vcache *avc)
538 {
539     struct vattr vattr;
540
541     VATTR_NULL(&vattr);
542     afs_CopyOutAttrs(avc, &vattr);      /* calls vattr2inode */
543 }
544
545 /* Yet another one for fakestat'ed mountpoints */
546 void
547 vcache2fakeinode(struct vcache *rootvp, struct vcache *mpvp)
548 {
549     struct vattr vattr;
550
551     VATTR_NULL(&vattr);
552     afs_CopyOutAttrs(rootvp, &vattr);
553     vattr2inode(AFSTOI(mpvp), &vattr);
554 }