Whamcloud - gitweb
smash the HEAD with the contents of b_cmd. HEAD_PRE_CMD_SMASH and
[fs/lustre-release.git] / lustre / smfs / super.c
1 /*
2  *  snap_current
3  *
4  *  Copyright (C) 1998 Peter J. Braam
5  *  Copyright (C) 2000 Stelias Computing, Inc.
6  *  Copyright (C) 2000 Red Hat, Inc.
7  *  Copyright (C) 2000 Mountain View Data, Inc.
8  *
9  *  Author: Peter J. Braam <braam@mountainviewdata.com>
10  */
11 #define DEBUG_SUBSYSTEM S_SM
12
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/kmod.h>
16 #include <linux/init.h>
17 #include <linux/fs.h>
18 #include <linux/string.h>
19 #include <linux/mm.h>
20 #include <linux/utime.h>
21 #include <linux/file.h>
22 #include <linux/slab.h>
23 #include <linux/loop.h>
24 #include <linux/errno.h>
25 #include <linux/lustre_idl.h>
26 #include "smfs_internal.h" 
27
28 /* Find the options for the clone. These consist of a cache device
29    and an index in the snaptable associated with that device. 
30 */
31 static char *smfs_options(char *options, char **devstr, char **namestr, int *kml)
32 {
33         struct option *opt_value = NULL;
34         char *pos;
35         
36         while (!(get_opt(&opt_value, &pos))) {                  
37                 if (!strcmp(opt_value->opt, "dev")) {
38                         if (devstr != NULL)
39                                 *devstr = opt_value->value;
40                 } else if (!strcmp(opt_value->opt, "type")) {
41                         if (namestr != NULL)
42                                 *namestr = opt_value->value;
43                 } else if (!strcmp(opt_value->opt, "kml")) {
44                         *kml = 1;       
45                 } else {
46                         break;
47                 }
48         }
49         return pos;
50 }
51
52 static int set_loop_fd(char *dev_path, char *loop_dev)
53 {
54         struct loop_info loopinfo;
55         struct nameidata nd;
56         struct dentry *dentry;
57         struct block_device_operations *bd_ops;
58         struct file   *filp;
59         int    fd = 0, error = 0;
60         
61         fd = get_unused_fd();
62
63         if (!fd) RETURN(-EINVAL);
64         
65         filp = filp_open(dev_path, FMODE_WRITE, 0);
66         if (!filp || !S_ISREG(filp->f_dentry->d_inode->i_mode)) 
67                 RETURN(-EINVAL);
68         
69         fd_install(fd, filp);           
70
71         if (path_init(loop_dev, LOOKUP_FOLLOW, &nd)) {
72                 error = path_walk(loop_dev, &nd);
73                 if (error) {
74                         path_release(&nd);
75                         filp_close(filp, current->files); 
76                         RETURN(-EINVAL);
77                 }
78         } else {
79                 path_release(&nd);
80                 filp_close(filp, current->files); 
81                 RETURN(-EINVAL);
82         }                                                                                                                                                                    
83         dentry = nd.dentry;
84         bd_ops = get_blkfops(LOOP_MAJOR); 
85         
86         error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_FD,
87                               (unsigned long)fd);
88         if (error) {
89                 path_release(&nd);
90                 filp_close(filp, current->files); 
91                 RETURN(-EINVAL);
92         }
93         memset(&loopinfo, 0, sizeof(struct loop_info));
94
95         error = bd_ops->ioctl(dentry->d_inode, filp, LOOP_SET_STATUS,
96                               (unsigned long)(&loopinfo));
97         path_release(&nd);
98         RETURN(error);  
99 }
100
101 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
102 static char *find_unused_and_set_loop_device(char *dev_path)
103 {
104         char *loop_formats[] = { "/dev/loop/%d", "/dev/loop%d"};
105         struct loop_info loopinfo;
106         struct nameidata nd;
107         struct dentry *dentry;
108         char *dev = NULL;
109         int i, j, error;
110                                                                                                                                                                                              
111         for (j = 0; j < SIZE(loop_formats); j++) {
112                 SM_ALLOC(dev, strlen(loop_formats[i]) + 1);
113                 for(i = 0; i < 256; i++) {
114                         struct block_device_operations *bd_ops;
115
116                         sprintf(dev, loop_formats[j], i);
117                         
118                         if (path_init(dev, LOOKUP_FOLLOW, &nd)) {
119                                 error = path_walk(dev, &nd);
120                                 if (error && error != -ENOENT) {
121                                         path_release(&nd);
122                                         SM_FREE(dev, strlen(loop_formats[i]) + 1); 
123                                         RETURN(NULL);
124                                 }
125                         } else {
126                                 SM_FREE(dev, strlen(loop_formats[i]) + 1); 
127                                 RETURN(NULL);
128                         }      
129                         dentry = nd.dentry;
130                         bd_ops = get_blkfops(LOOP_MAJOR); 
131                         error = bd_ops->ioctl(dentry->d_inode, NULL, LOOP_GET_STATUS, 
132                                               (unsigned long)&loopinfo);
133                         path_release(&nd);
134                         
135                         if (error == -ENXIO) {
136                                 /*find unused loop and set dev_path to loopdev*/
137                                 error = set_loop_fd(dev_path, dev);
138                                 if (error) {
139                                         SM_FREE(dev, strlen(loop_formats[i]) + 1);
140                                         dev = NULL;             
141                                 }
142                                 return dev;/* probably free */
143                         }
144                 }
145                 SM_FREE(dev, strlen(loop_formats[i]) + 1);
146         }
147         RETURN(NULL);
148 }
149
150 #define MAX_LOOP_DEVICES        256
151 static char *parse_path2dev(struct super_block *sb, char *dev_path)
152 {
153         struct dentry *dentry;
154         struct nameidata nd;
155         char *name = NULL;
156         int  error = 0;
157
158         if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
159                 error = path_walk(dev_path, &nd);
160                 if (error) {
161                         path_release(&nd);
162                         RETURN(NULL);
163                 }
164         } else {
165                 RETURN(NULL);
166         }      
167         dentry = nd.dentry;
168
169         if (!dentry->d_inode || is_bad_inode(dentry->d_inode) || 
170             (!S_ISBLK(dentry->d_inode->i_mode) && 
171              !S_ISREG(dentry->d_inode->i_mode))){
172                 path_release(&nd);
173                 RETURN(NULL);
174         }
175                 
176         if (S_ISREG(dentry->d_inode->i_mode)) {
177                 name = find_unused_and_set_loop_device(dev_path);
178                 path_release(&nd);
179                 RETURN(name);                   
180         }
181         SM_ALLOC(name, strlen(dev_path) + 1);
182         memcpy(name, dev_path, strlen(dev_path) + 1);
183         RETURN(name);
184 }
185 void duplicate_sb(struct super_block *csb, 
186                          struct super_block *sb)
187 {
188         sb->s_blocksize = csb->s_blocksize;
189         sb->s_magic = csb->s_magic;
190         sb->s_blocksize_bits = csb->s_blocksize_bits;
191         sb->s_maxbytes = csb->s_maxbytes;
192 }
193 extern struct super_operations smfs_super_ops;
194
195 static int sm_mount_cache(struct super_block *sb, 
196                           char *devstr,
197                           char *typestr)
198 {
199         struct vfsmount *mnt;   
200         struct smfs_super_info *smb;
201         char *dev_name = NULL;
202         unsigned long page;
203         int     err = 0;
204         
205         dev_name = parse_path2dev(sb, devstr);
206         if (!dev_name) {
207                 GOTO(err_out, err = -ENOMEM);
208         }
209         if (!(page = __get_free_page(GFP_KERNEL))) {
210                 GOTO(err_out, err = -ENOMEM);
211         }                                                                                                                                                   
212         memset((void *)page, 0, PAGE_SIZE);
213         sprintf((char *)page, "iopen_nopriv");
214                                                                                                                                                                                                      
215         mnt = do_kern_mount(typestr, 0, dev_name, (void *)page);
216         free_page(page);
217         
218         if (IS_ERR(mnt)) {
219                 CERROR("do_kern_mount failed: rc = %ld\n", PTR_ERR(mnt));
220                 GOTO(err_out, err = PTR_ERR(mnt));
221         }
222         smb = S2SMI(sb); 
223         smb->smsi_sb = mnt->mnt_sb;
224         smb->smsi_mnt = mnt;
225         
226         duplicate_sb(mnt->mnt_sb, sb);
227         sm_set_sb_ops(mnt->mnt_sb, sb); 
228 err_out:
229         if (dev_name) 
230                 SM_FREE(dev_name, strlen(dev_name) + 2);
231                 
232         return err;     
233 }
234 static int sm_umount_cache(struct super_block *sb)
235 {
236         struct smfs_super_info *smb = S2SMI(sb);
237         
238         mntput(smb->smsi_mnt);
239         
240         return 0;
241 }
242 void smfs_put_super(struct super_block *sb)
243 {
244         if (sb)
245                 sm_umount_cache(sb);
246         return; 
247 }
248
249 struct super_block *
250 smfs_read_super(
251         struct super_block *sb,
252         void *data,
253         int silent)
254 {
255         struct inode *root_inode = NULL;
256         char *devstr = NULL, *typestr = NULL;
257         char *cache_data;
258         ino_t root_ino;
259         int err = 0, kml = 0;
260
261         ENTRY;
262
263         CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
264         
265         init_option(data);
266         /* read and validate options */
267         cache_data = smfs_options(data, &devstr, &typestr, &kml);
268         if (*cache_data) {
269                 CERROR("invalid mount option %s\n", (char*)data);
270                 GOTO(out_err, err=-EINVAL);
271         }
272         if (!typestr || !devstr) {
273                 CERROR("mount options name and dev mandatory\n");
274                 GOTO(out_err, err=-EINVAL);
275         }
276         
277         err = sm_mount_cache(sb, devstr, typestr);
278         if (err) {
279                 CERROR("Can not mount %s as %s\n", devstr, typestr);
280                 GOTO(out_err, 0);
281         }
282         
283         if (kml) smfs_kml_init(sb);     
284         
285         setup_sm_journal_ops(typestr);
286         
287         dget(S2CSB(sb)->s_root);
288         root_ino = S2CSB(sb)->s_root->d_inode->i_ino;
289         root_inode = iget(sb, root_ino);
290                 
291         CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
292                sb->s_op->read_inode, root_ino, root_inode);
293         
294         sb->s_root = d_alloc_root(root_inode);
295         
296         if (!sb->s_root) {
297                 GOTO(out_err, err=-EINVAL);
298         }
299         
300         CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
301                 (ulong) sb, (ulong) &sb->u.generic_sbp);
302         
303 out_err:
304         cleanup_option();
305         if (err)
306                 return NULL;
307         return sb;
308 }
309
310 static DECLARE_FSTYPE(smfs_type, "smfs", smfs_read_super, 0);
311
312 int init_smfs(void)
313 {
314         int err = 0;
315
316         err = register_filesystem(&smfs_type);
317         if (err) {
318                 CERROR("smfs: failed in register Storage Management filesystem!\n");
319         }
320         init_smfs_cache();              
321         return err;
322 }
323
324 int cleanup_smfs(void)
325 {
326         int err = 0;
327
328         ENTRY;
329         err = unregister_filesystem(&smfs_type);
330         if (err) {
331                 CERROR("smfs: failed to unregister Storage Management filesystem!\n");
332         }
333         cleanup_smfs_cache();           
334         return 0;
335 }