Whamcloud - gitweb
eddd0c8df38a65d1855543b71380fb00ff5c9ed1
[fs/lustre-release.git] / lustre / obdfs / super.c
1 /*
2  * OBDFS Super operations
3  *
4  * Copryright (C) 1996 Peter J. Braam <braam@stelias.com>
5  * Copryright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
6  * Copryright (C) 1999 Seagate Technology Inc.
7  *
8  */
9
10 #define EXPORT_SYMTAB
11
12 #include <linux/config.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/mm.h>
16 #include <linux/string.h>
17 #include <linux/stat.h>
18 #include <linux/errno.h>
19 #include <linux/locks.h>
20 #include <linux/unistd.h>
21
22 #include <asm/system.h>
23 #include <asm/uaccess.h>
24
25 #include <linux/fs.h>
26 #include <linux/stat.h>
27 #include <asm/uaccess.h>
28 #include <linux/vmalloc.h>
29 #include <asm/segment.h>
30
31 #include <linux/obd_support.h>
32 #include <linux/obd_class.h>
33 #include <linux/obd_sim.h>  /* XXX for development/debugging only */
34 #include <obdfs.h>
35
36 /* VFS super_block ops */
37 static struct super_block *obdfs_read_super(struct super_block *, void *, int);
38 static void obdfs_read_inode(struct inode *);
39 static int  obdfs_notify_change(struct dentry *dentry, struct iattr *attr);
40 static void obdfs_write_inode(struct inode *);
41 static void obdfs_delete_inode(struct inode *);
42 static void obdfs_put_super(struct super_block *);
43 static int obdfs_statfs(struct super_block *sb, struct statfs *buf, 
44                        int bufsiz);
45
46 /* exported operations */
47 struct super_operations obdfs_super_operations =
48 {
49         obdfs_read_inode,       /* read_inode */
50         obdfs_write_inode,      /* write_inode */
51         NULL,                   /* put_inode */
52         obdfs_delete_inode,     /* delete_inode */
53         obdfs_notify_change,    /* notify_change */
54         obdfs_put_super,        /* put_super */
55         NULL,                   /* write_super */
56         obdfs_statfs,           /* statfs */
57         NULL                    /* remount_fs */
58 };
59
60 struct obdfs_sb_info obdfs_super_info;
61 int obd_minor = 0;
62 int obd_root_ino = 2;
63
64 static struct super_block * obdfs_read_super(struct super_block *sb, 
65                                             void *data, int silent)
66 {
67         struct inode *root = 0; 
68         struct obdfs_sb_info *sbi = NULL;
69         struct obd_device *obddev;
70         int error = 0;
71         unsigned long blocksize;
72         unsigned long blocksize_bits;
73         unsigned long root_ino;
74         int scratch;
75         
76
77         ENTRY;
78         MOD_INC_USE_COUNT; 
79
80         sbi = &obdfs_super_info;
81
82         if ( sbi->osi_super ) {
83                 printk("Already mounted\n");
84                 MOD_DEC_USE_COUNT;
85                 return NULL;
86         }
87         
88         obddev = &obd_dev[obd_minor];
89
90         if ( ! (obddev->obd_flags & OBD_ATTACHED) || 
91              ! (obddev->obd_flags & OBD_SET_UP) )
92                 return NULL;
93
94         sbi->osi_obd = obddev;
95         sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops;
96         
97         error  = sbi->osi_ops->o_connect(sbi->osi_obd, &sbi->osi_conn_info);
98         if ( error ) {
99                 printk("OBDFS: cannot connect to 0x%x.\n", obd_minor);
100                 goto error;
101         }
102
103         sbi->osi_super = sb;
104
105         error = sbi->osi_ops->o_get_info(sbi->osi_conn_info.conn_id, 
106                                          strlen("blocksize"), 
107                                          "blocksize", 
108                                          &scratch, (void *)&blocksize);
109         if ( error ) {
110                 printk("Getinfo call to drive failed (blocksize)\n");
111                 goto error;
112         }
113
114         error = sbi->osi_ops->o_get_info(sbi->osi_conn_info.conn_id, 
115                                          strlen("blocksize_bits"), 
116                                          "blocksize_bits", 
117                                          &scratch, (void *)&blocksize_bits);
118         if ( error ) {
119                 printk("Getinfo call to drive failed (blocksize_bits)\n");
120                 goto error;
121         }
122
123         error = sbi->osi_ops->o_get_info(sbi->osi_conn_info.conn_id, 
124                                          strlen("root_ino"), 
125                                          "root_ino", 
126                                          &scratch, (void *)&root_ino);
127         if ( error ) {
128                 printk("Getinfo call to drive failed (root_ino)\n");
129                 goto error;
130         }
131         
132
133         lock_super(sb);
134         sb->u.generic_sbp = sbi;
135         
136         sb->s_blocksize = blocksize;
137         sb->s_blocksize_bits = (unsigned char)blocksize_bits;
138         sb->s_magic = OBDFS_SUPER_MAGIC;
139         sb->s_op = &obdfs_super_operations;
140
141         /* make root inode */
142         root = iget(sb, root_ino);
143         if (!root || is_bad_inode(root)) {
144             printk("OBDFS: bad iget for root\n");
145             sb->s_dev = 0;
146             error = ENOENT;
147             unlock_super(sb);
148             goto error;
149         } 
150
151         printk("obdfs_read_super: rootinode is %ld dev %d\n", 
152                root->i_ino, root->i_dev);
153         sb->s_root = d_alloc_root(root);
154         unlock_super(sb);
155         EXIT;  
156         return sb;
157
158  error:
159         EXIT;  
160         MOD_DEC_USE_COUNT;
161         if (sbi) {
162                 sbi->osi_super = NULL;
163         }
164         if (root) {
165                 iput(root);
166         }
167         sb->s_dev = 0;
168         return NULL;
169 }
170
171 static void obdfs_put_super(struct super_block *sb)
172 {
173         struct obdfs_sb_info *sbi;
174
175         ENTRY;
176
177
178         sb->s_dev = 0;
179         
180         /* XXX flush stuff */
181         sbi = sb->u.generic_sbp;
182         sb->u.generic_sbp = NULL;
183         sbi->osi_ops->o_disconnect(sbi->osi_conn_info.conn_id);
184         sbi->osi_super = NULL;
185
186         
187         printk("OBDFS: Bye bye.\n");
188         memset(sbi, 0, sizeof(* sbi));
189
190         MOD_DEC_USE_COUNT;
191         EXIT;
192 }
193
194 extern struct inode_operations obdfs_inode_ops;
195
196 /* all filling in of inodes postponed until lookup */
197 static void obdfs_read_inode(struct inode *inode)
198 {
199         int error;
200         struct obdfs_sb_info *sbi = inode->i_sb->u.generic_sbp;
201         ENTRY;
202
203         error = sbi->osi_ops->o_getattr(sbi->osi_conn_info.conn_id, 
204                                         inode->i_ino, inode);
205         if (error) {
206                 printk("obdfs_read_inode: ibd_getattr fails (%d)\n", error);
207                 return;
208         }
209
210         inode->i_op = &obdfs_inode_ops;
211         return;
212 }
213
214 static void obdfs_write_inode(struct inode *inode) 
215 {
216         struct obdfs_sb_info *sbi;
217         int error;
218         
219         sbi = inode->i_sb->u.generic_sbp;
220         error = sbi->osi_ops->o_setattr(sbi->osi_conn_info.conn_id, 
221                                         inode->i_ino, inode);
222         if (error) {
223                 printk("obdfs_write_inode: ibd_setattr fails (%d)\n", error);
224                 return;
225         }
226
227         return;
228 }
229
230 static void obdfs_delete_inode(struct inode *inode)
231 {
232         struct obdfs_sb_info *sbi;
233         int error;
234         ENTRY;
235
236         sbi = inode->i_sb->u.generic_sbp;
237         error = sbi->osi_ops->o_destroy(sbi->osi_conn_info.conn_id, 
238                                         inode->i_ino);
239         if (error) {
240                 printk("obdfs_delete_node: ibd_destroy fails (%d)\n", error);
241                 return;
242         }
243
244         EXIT;
245 }
246
247 static int  obdfs_notify_change(struct dentry *de, struct iattr *iattr)
248 {
249         struct inode *inode = de->d_inode;
250         struct iattr saved_copy;
251         struct obdfs_sb_info * sbi;
252         int error;
253
254         ENTRY;
255         inode_to_iattr(inode, &saved_copy);
256
257         sbi = inode->i_sb->u.generic_sbp;
258         inode_setattr(inode, iattr);
259         error = sbi->osi_ops->o_setattr(sbi->osi_conn_info.conn_id, 
260                                         inode->i_ino, inode);
261         if ( error ) {
262                 inode_setattr(inode, &saved_copy);
263                 printk("obdfs_notify_change: obd_setattr fails (%d)\n", error);
264                 return error;
265         }
266         EXIT;
267         return error;
268 }
269
270
271 static int obdfs_statfs(struct super_block *sb, struct statfs *buf, 
272                        int bufsize)
273 {
274         struct statfs tmp;
275         struct obdfs_sb_info * sbi;
276         int error;
277
278         ENTRY;
279
280         sbi = sb->u.generic_sbp;
281         error = sbi->osi_ops->o_statfs(sbi->osi_conn_info.conn_id, &tmp);
282         if ( error ) { 
283                 printk("obdfs_notify_change: obd_statfs fails (%d)\n", error);
284                 return error;
285         }
286         copy_to_user(buf, &tmp, (bufsize<sizeof(tmp)) ? bufsize : sizeof(tmp));
287
288         EXIT;
289
290         return error; 
291 }
292
293 struct file_system_type obdfs_fs_type = {
294    "obdfs", 0, obdfs_read_super, NULL
295 };
296
297 int init_obdfs(void)
298 {
299         printk(KERN_INFO "OBDFS v0.1, braam@stelias.com\n");
300
301         obdfs_sysctl_init();
302
303         obd_sbi = &obdfs_super_info;
304         obd_fso = &obdfs_file_ops;
305
306         return register_filesystem(&obdfs_fs_type);
307 }
308
309
310 #ifdef MODULE
311 int init_module(void)
312 {
313         return init_obdfs();
314 }
315
316 void cleanup_module(void)
317 {
318         ENTRY;
319
320         obdfs_sysctl_clean();
321         unregister_filesystem(&obdfs_fs_type);
322 }
323 void obdfs_psdev_dec_use_count(void)
324 {
325         MOD_DEC_USE_COUNT;
326 }
327
328 EXPORT_SYMBOL(obdfs_psdev_dec_use_count);
329
330 #endif