f799b79b8f1d8c3478112d3858589cb36ad5e261
[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 int afs_root(struct super_block *afsp);
50 struct super_block *afs_read_super(struct super_block *sb, void *data, int silent);
51 int afs_fill_super(struct super_block *sb, void *data, int silent);
52 static struct super_block *afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data);
53
54 /* afs_file_system
55  * VFS entry for Linux - installed in init_module
56  * Linux mounts file systems by:
57  * 1) register_filesystem(&afs_file_system) - done in init_module
58  * 2) Mount call comes to us via do_mount -> read_super -> afs_read_super.
59  *    We are expected to setup the super_block. See afs_read_super.
60  */
61 #if defined(AFS_LINUX26_ENV)
62 struct backing_dev_info afs_backing_dev_info = {
63         .ra_pages       = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
64         .state          = 0,
65 };
66
67 struct file_system_type afs_fs_type = {
68     .owner = THIS_MODULE,
69     .name = "afs",
70     .get_sb = afs_get_sb,
71     .kill_sb = kill_anon_super,
72     .fs_flags = FS_BINARY_MOUNTDATA,
73 };
74 #elif defined(AFS_LINUX24_ENV)
75 DECLARE_FSTYPE(afs_fs_type, "afs", afs_read_super, 0);
76 #else
77 struct file_system_type afs_fs_type = {
78     "afs",                      /* name - used by mount operation. */
79     0,                          /* requires_dev - no for network filesystems. mount() will 
80                                  * pass us an "unnamed" device. */
81     afs_read_super,             /* wrapper to afs_mount */
82     NULL                        /* pointer to next file_system_type once registered. */
83 };
84 #endif
85
86 /* afs_read_super
87  * read the "super block" for AFS - roughly eguivalent to struct vfs.
88  * dev, covered, s_rd_only, s_dirt, and s_type will be set by read_super.
89  */
90 #if defined(AFS_LINUX26_ENV)
91 static struct super_block *
92 afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
93 {
94     return get_sb_nodev(fs_type, flags, data, afs_fill_super);
95 }
96
97 int
98 afs_fill_super(struct super_block *sb, void *data, int silent)
99 #else
100 struct super_block *
101 afs_read_super(struct super_block *sb, void *data, int silent)
102 #endif
103 {
104     int code = 0;
105
106     AFS_GLOCK();
107     if (afs_was_mounted) {
108         printf
109             ("You must reload the AFS kernel extensions before remounting AFS.\n");
110         AFS_GUNLOCK();
111 #if defined(AFS_LINUX26_ENV)
112         return -EINVAL;
113 #else
114         return NULL;
115 #endif
116     }
117     afs_was_mounted = 1;
118
119     /* Set basics of super_block */
120 #if !defined(AFS_LINUX24_ENV)
121     lock_super(sb);
122 #endif
123 #if defined(AFS_LINUX26_ENV)
124    __module_get(THIS_MODULE);
125 #else
126     MOD_INC_USE_COUNT;
127 #endif
128
129     afs_globalVFS = sb;
130     sb->s_blocksize = 1024;
131     sb->s_blocksize_bits = 10;
132     sb->s_magic = AFS_VFSMAGIC;
133     sb->s_op = &afs_sops;       /* Super block (vfs) ops */
134 #if defined(MAX_NON_LFS)
135     sb->s_maxbytes = MAX_NON_LFS;
136 #endif
137     code = afs_root(sb);
138     if (code) {
139         afs_globalVFS = NULL;
140 #if defined(AFS_LINUX26_ENV)
141         module_put(THIS_MODULE);
142 #else
143         MOD_DEC_USE_COUNT;
144 #endif
145     }
146
147 #if !defined(AFS_LINUX24_ENV)
148     unlock_super(sb);
149 #endif
150
151     AFS_GUNLOCK();
152 #if defined(AFS_LINUX26_ENV)
153     return code ? -EINVAL : 0;
154 #else
155     return code ? NULL : sb;
156 #endif
157 }
158
159
160 /* afs_root - stat the root of the file system. AFS global held on entry. */
161 static int
162 afs_root(struct super_block *afsp)
163 {
164     register afs_int32 code = 0;
165     struct vrequest treq;
166     register struct vcache *tvp = 0;
167
168     AFS_STATCNT(afs_root);
169     if (afs_globalVp && (afs_globalVp->states & CStatd)) {
170         tvp = afs_globalVp;
171     } else {
172         cred_t *credp = crref();
173
174         if (afs_globalVp) {
175             afs_PutVCache(afs_globalVp);
176             afs_globalVp = NULL;
177         }
178
179         if (!(code = afs_InitReq(&treq, credp)) && !(code = afs_CheckInit())) {
180             tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
181             if (tvp) {
182                 struct inode *ip = AFSTOV(tvp);
183                 struct vattr vattr;
184
185                 afs_getattr(tvp, &vattr, credp);
186                 afs_fill_inode(ip, &vattr);
187
188                 /* setup super_block and mount point inode. */
189                 afs_globalVp = tvp;
190 #if defined(AFS_LINUX24_ENV)
191                 afsp->s_root = d_alloc_root(ip);
192 #else
193                 afsp->s_root = d_alloc_root(ip, NULL);
194 #endif
195                 afsp->s_root->d_op = &afs_dentry_operations;
196             } else
197                 code = ENOENT;
198         }
199         crfree(credp);
200     }
201
202     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, afs_globalVp,
203                ICL_TYPE_INT32, code);
204     return code;
205 }
206
207 /* super_operations */
208
209 /* afs_notify_change
210  * Linux version of setattr call. What to change is in the iattr struct.
211  * We need to set bits in both the Linux inode as well as the vcache.
212  */
213 int
214 afs_notify_change(struct dentry *dp, struct iattr *iattrp)
215 {
216     struct vattr vattr;
217     cred_t *credp = crref();
218     struct inode *ip = dp->d_inode;
219     int code;
220
221     VATTR_NULL(&vattr);
222     iattr2vattr(&vattr, iattrp);        /* Convert for AFS vnodeops call. */
223
224 #if defined(AFS_LINUX26_ENV)
225     lock_kernel();
226 #endif
227     AFS_GLOCK();
228     code = afs_setattr(VTOAFS(ip), &vattr, credp);
229     if (!code) {
230         afs_getattr(VTOAFS(ip), &vattr, credp);
231         vattr2inode(ip, &vattr);
232     }
233     AFS_GUNLOCK();
234 #if defined(AFS_LINUX26_ENV)
235     unlock_kernel();
236 #endif
237     crfree(credp);
238     return -code;
239 }
240
241
242 #if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
243 static kmem_cache_t *afs_inode_cachep;
244
245 static struct inode *
246 afs_alloc_inode(struct super_block *sb)
247 {
248     struct vcache *vcp;
249
250     vcp = (struct vcache *) kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL);
251     if (!vcp)
252         return NULL;
253
254     return AFSTOV(vcp);
255 }
256
257 static void
258 afs_destroy_inode(struct inode *inode)
259 {
260     kmem_cache_free(afs_inode_cachep, inode);
261 }
262
263 static void
264 init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
265 {
266     struct vcache *vcp = (struct vcache *) foo;
267
268     if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
269         SLAB_CTOR_CONSTRUCTOR)
270         inode_init_once(AFSTOV(vcp));
271 }
272
273 int
274 afs_init_inodecache(void)
275 {
276 #ifndef SLAB_RECLAIM_ACCOUNT
277 #define SLAB_RECLAIM_ACCOUNT 0
278 #endif
279
280     afs_inode_cachep = kmem_cache_create("afs_inode_cache",
281                                          sizeof(struct vcache),
282                                          0, SLAB_HWCACHE_ALIGN | SLAB_RECLAIM_ACCOUNT,
283                                          init_once, NULL);
284     if (afs_inode_cachep == NULL)
285         return -ENOMEM;
286     return 0;
287 }
288
289 void
290 afs_destroy_inodecache(void)
291 {
292     if (kmem_cache_destroy(afs_inode_cachep))
293         printk(KERN_INFO "afs_inode_cache: not all structures were freed\n");
294 }
295 #else
296 int
297 afs_init_inodecache(void)
298 {
299     return 0;
300 }
301
302 void
303 afs_destroy_inodecache(void)
304 {
305     return;
306 }
307 #endif
308
309 static void
310 afs_clear_inode(struct inode *ip)
311 {
312     struct vcache *vcp = VTOAFS(ip);
313
314     if (vcp->vlruq.prev || vcp->vlruq.next)
315         osi_Panic("inode freed while on LRU");
316     if (vcp->hnext || vcp->vhnext)
317         osi_Panic("inode freed while still hashed");
318
319 #if !defined(STRUCT_SUPER_HAS_ALLOC_INODE)
320     afs_osi_Free(ip->u.generic_ip, sizeof(struct vcache));
321 #endif
322 }
323
324 /* afs_put_inode
325  * Linux version of inactive.  When refcount == 2, we are about to
326  * decrement to 1 and the only reference remaining should be for
327  * the VLRU
328  */
329
330 static void
331 afs_put_inode(struct inode *ip)
332 {
333     cred_t *credp = crref();
334     struct vcache *vcp = VTOAFS(ip);
335
336     AFS_GLOCK();
337     ObtainReadLock(&vcp->lock);
338     if (VREFCOUNT(vcp) == 2)
339         afs_InactiveVCache(vcp, credp);
340     ReleaseReadLock(&vcp->lock);
341     AFS_GUNLOCK();
342     crfree(credp);
343 }
344
345 /* afs_put_super
346  * Called from unmount to release super_block. */
347 static void
348 afs_put_super(struct super_block *sbp)
349 {
350     int code = 0;
351
352     AFS_GLOCK();
353     AFS_STATCNT(afs_unmount);
354
355 #if !defined(AFS_LINUX26_ENV)
356     if (!suser()) {
357         AFS_GUNLOCK();
358         return;
359     }
360 #endif
361
362     afs_globalVFS = 0;
363     afs_globalVp = 0;
364
365     osi_linux_free_inode_pages();       /* invalidate and release remaining AFS inodes. */
366     afs_shutdown();
367 #if defined(AFS_LINUX24_ENV)
368     mntput(afs_cacheMnt);
369 #endif
370
371     osi_linux_verify_alloced_memory();
372     AFS_GUNLOCK();
373
374     if (!code) {
375         sbp->s_dev = 0;
376 #if defined(AFS_LINUX26_ENV)
377         module_put(THIS_MODULE);
378 #else
379         MOD_DEC_USE_COUNT;
380 #endif
381     }
382 }
383
384
385 /* afs_statfs
386  * statp is in user space, so we need to cobble together a statfs, then
387  * copy it.
388  */
389 #if defined(AFS_LINUX26_ENV)
390 int
391 afs_statfs(struct super_block *sbp, struct kstatfs *statp)
392 #elif defined(AFS_LINUX24_ENV)
393 int
394 afs_statfs(struct super_block *sbp, struct statfs *statp)
395 #else
396 int
397 afs_statfs(struct super_block *sbp, struct statfs *__statp, int size)
398 #endif
399 {
400 #if !defined(AFS_LINUX24_ENV)
401     struct statfs stat, *statp;
402
403     if (size < sizeof(struct statfs))
404         return;
405
406     memset(&stat, 0, size);
407     statp = &stat;
408 #else
409     memset(statp, 0, sizeof(*statp));
410 #endif
411
412     AFS_STATCNT(afs_statfs);
413
414     statp->f_type = 0;          /* Can we get a real type sometime? */
415     statp->f_bsize = sbp->s_blocksize;
416     statp->f_blocks = statp->f_bfree = statp->f_bavail = statp->f_files =
417         statp->f_ffree = 9000000;
418     statp->f_fsid.val[0] = AFS_VFSMAGIC;
419     statp->f_fsid.val[1] = AFS_VFSFSID;
420     statp->f_namelen = 256;
421
422 #if !defined(AFS_LINUX24_ENV)
423     memcpy_tofs(__statp, &stat, size);
424 #endif
425     return 0;
426 }
427
428 void
429 afs_umount_begin(struct super_block *sbp)
430 {
431     afs_shuttingdown = 1;
432 }
433
434 struct super_operations afs_sops = {
435 #if defined(STRUCT_SUPER_HAS_ALLOC_INODE)
436   .alloc_inode =        afs_alloc_inode,
437   .destroy_inode =      afs_destroy_inode,
438 #endif
439   .clear_inode =        afs_clear_inode,
440   .put_inode =          afs_put_inode,
441   .put_super =          afs_put_super,
442   .statfs =             afs_statfs,
443   .umount_begin =       afs_umount_begin
444 #if !defined(AFS_LINUX24_ENV)
445   .notify_change =      afs_notify_change,
446 #endif
447 };
448
449 /************** Support routines ************************/
450
451 /* vattr_setattr
452  * Set iattr data into vattr. Assume vattr cleared before call.
453  */
454 static void
455 iattr2vattr(struct vattr *vattrp, struct iattr *iattrp)
456 {
457     vattrp->va_mask = iattrp->ia_valid;
458     if (iattrp->ia_valid & ATTR_MODE)
459         vattrp->va_mode = iattrp->ia_mode;
460     if (iattrp->ia_valid & ATTR_UID)
461         vattrp->va_uid = iattrp->ia_uid;
462     if (iattrp->ia_valid & ATTR_GID)
463         vattrp->va_gid = iattrp->ia_gid;
464     if (iattrp->ia_valid & ATTR_SIZE)
465         vattrp->va_size = iattrp->ia_size;
466     if (iattrp->ia_valid & ATTR_ATIME) {
467 #if defined(AFS_LINUX26_ENV)
468         vattrp->va_atime.tv_sec = iattrp->ia_atime.tv_sec;
469 #else
470         vattrp->va_atime.tv_sec = iattrp->ia_atime;
471 #endif
472         vattrp->va_atime.tv_usec = 0;
473     }
474     if (iattrp->ia_valid & ATTR_MTIME) {
475 #if defined(AFS_LINUX26_ENV)
476         vattrp->va_mtime.tv_sec = iattrp->ia_mtime.tv_sec;
477 #else
478         vattrp->va_mtime.tv_sec = iattrp->ia_mtime;
479 #endif
480         vattrp->va_mtime.tv_usec = 0;
481     }
482     if (iattrp->ia_valid & ATTR_CTIME) {
483 #if defined(AFS_LINUX26_ENV)
484         vattrp->va_ctime.tv_sec = iattrp->ia_ctime.tv_sec;
485 #else
486         vattrp->va_ctime.tv_sec = iattrp->ia_ctime;
487 #endif
488         vattrp->va_ctime.tv_usec = 0;
489     }
490 }
491
492 /* vattr2inode
493  * Rewrite the inode cache from the attr. Assumes all vattr fields are valid.
494  */
495 void
496 vattr2inode(struct inode *ip, struct vattr *vp)
497 {
498     ip->i_ino = vp->va_nodeid;
499     ip->i_nlink = vp->va_nlink;
500     ip->i_blocks = vp->va_blocks;
501     ip->i_blksize = vp->va_blocksize;
502     ip->i_rdev = vp->va_rdev;
503     ip->i_mode = vp->va_mode;
504     ip->i_uid = vp->va_uid;
505     ip->i_gid = vp->va_gid;
506     ip->i_size = vp->va_size;
507 #if defined(AFS_LINUX26_ENV)
508     ip->i_atime.tv_sec = vp->va_atime.tv_sec;
509     ip->i_mtime.tv_sec = vp->va_mtime.tv_sec;
510     ip->i_ctime.tv_sec = vp->va_ctime.tv_sec;
511 #else
512     ip->i_atime = vp->va_atime.tv_sec;
513     ip->i_mtime = vp->va_mtime.tv_sec;
514     ip->i_ctime = vp->va_ctime.tv_sec;
515 #endif
516 }