This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / intermezzo / inode.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
5  *    Michael Callahan <callahan@maths.ox.ac.uk>
6  *  Copyright (C) 1999 Carnegie Mellon University
7  *    Rewritten for Linux 2.1.  Peter Braam <braam@cs.cmu.edu>
8  *
9  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
10  *
11  *   InterMezzo is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   InterMezzo is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with InterMezzo; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  * Super block/filesystem wide operations
25  */
26
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/mm.h>
30 #include <linux/string.h>
31 #include <linux/stat.h>
32 #include <linux/errno.h>
33 #include <linux/unistd.h>
34
35 #include <asm/system.h>
36 #include <asm/uaccess.h>
37
38 #include <linux/fs.h>
39 #include <linux/slab.h>
40 #include <linux/vmalloc.h>
41 #include <asm/segment.h>
42
43 #include "intermezzo_fs.h"
44 #include "intermezzo_psdev.h"
45
46 extern void presto_free_cache(struct presto_cache *);
47
48 void presto_set_ops(struct inode *inode, struct  filter_fs *filter)
49 {
50         ENTRY; 
51
52         if (!inode || is_bad_inode(inode))
53                 return;
54
55         if (S_ISREG(inode->i_mode)) {
56                 if ( !filter_c2cfiops(filter) ) {
57                        filter_setup_file_ops(filter, 
58                                              inode, &presto_file_iops,
59                                              &presto_file_fops);
60                 }
61                 inode->i_op = filter_c2ufiops(filter);
62                 inode->i_fop = filter_c2uffops(filter);
63                 CDEBUG(D_INODE, "set file methods for %ld to %p\n",
64                        inode->i_ino, inode->i_op);
65         } else if (S_ISDIR(inode->i_mode)) {
66                 inode->i_op = filter_c2udiops(filter);
67                 inode->i_fop = filter_c2udfops(filter);
68                 CDEBUG(D_INODE, "set dir methods for %ld to %p ioctl %p\n",
69                        inode->i_ino, inode->i_op, inode->i_fop->ioctl);
70         } else if (S_ISLNK(inode->i_mode)) {
71                 if ( !filter_c2csiops(filter)) {
72                         filter_setup_symlink_ops(filter, 
73                                                  inode,
74                                                  &presto_sym_iops, 
75                                                  &presto_sym_fops);
76                 }
77                 inode->i_op = filter_c2usiops(filter);
78                 inode->i_fop = filter_c2usfops(filter);
79                 CDEBUG(D_INODE, "set link methods for %ld to %p\n",
80                        inode->i_ino, inode->i_op);
81         }
82         EXIT;
83 }
84
85 void presto_read_inode(struct inode *inode)
86 {
87         struct presto_cache *cache;
88
89         cache = presto_get_cache(inode);
90         if ( !cache ) {
91                 CERROR("PRESTO: BAD, BAD: cannot find cache\n");
92                 make_bad_inode(inode);
93                 return ;
94         }
95
96         filter_c2csops(cache->cache_filter)->read_inode(inode);
97
98         CDEBUG(D_INODE, "presto_read_inode: ino %ld, gid %d\n", 
99                inode->i_ino, inode->i_gid);
100
101         presto_set_ops(inode, cache->cache_filter); 
102         /* XXX handle special inodes here or not - probably not? */
103 }
104
105 static void presto_put_super(struct super_block *sb)
106 {
107         struct presto_cache *cache;
108         struct upc_channel *channel;
109         struct super_operations *sops;
110         struct list_head *lh;
111         int err;
112
113         ENTRY;
114         cache = presto_cache_find(sb);
115         if (!cache) {
116                 EXIT;
117                 goto exit;
118         }
119         channel = &izo_channels[presto_c2m(cache)];
120         sops = filter_c2csops(cache->cache_filter);
121         err = izo_clear_all_fsetroots(cache); 
122         if (err) { 
123                 CERROR("%s: err %d\n", __FUNCTION__, err);
124         }
125         PRESTO_FREE(cache->cache_vfsmount, sizeof(struct vfsmount));
126
127         /* look at kill_super - fsync_super is not exported GRRR but 
128            probably not needed */ 
129         unlock_super(sb);
130         shrink_dcache_parent(cache->cache_root); 
131         dput(cache->cache_root); 
132         //fsync_super(sb); 
133         lock_super(sb);
134
135         if (sops->write_super)
136                 sops->write_super(sb); 
137
138         if (sops->put_super)
139                 sops->put_super(sb);
140
141         /* free any remaining async upcalls when the filesystem is unmounted */
142         spin_lock(&channel->uc_lock);
143         lh = channel->uc_pending.next;
144         while ( lh != &channel->uc_pending) {
145                 struct upc_req *req;
146                 req = list_entry(lh, struct upc_req, rq_chain);
147
148                 /* assignment must be here: we are about to free &lh */
149                 lh = lh->next;
150                 if ( ! (req->rq_flags & REQ_ASYNC) ) 
151                         continue;
152                 list_del(&(req->rq_chain));
153                 PRESTO_FREE(req->rq_data, req->rq_bufsize);
154                 PRESTO_FREE(req, sizeof(struct upc_req));
155         }
156         list_del(&cache->cache_channel_list); 
157         spin_unlock(&channel->uc_lock);
158
159         presto_free_cache(cache);
160
161 exit:
162         CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
163                presto_kmemory, presto_vmemory);
164         return ;
165 }
166
167 struct super_operations presto_super_ops = {
168         .read_inode    = presto_read_inode,
169         .put_super     = presto_put_super,
170 };
171
172
173 /* symlinks can be chowned */
174 struct inode_operations presto_sym_iops = {
175         .setattr       = presto_setattr
176 };
177
178 /* NULL for now */
179 struct file_operations presto_sym_fops;