- PL2545 WAR: disable CKRM numtasks controller
[linux-2.6.git] / fs / rcfs / dir.c
1 /* 
2  * fs/rcfs/dir.c 
3  *
4  * Copyright (C) Shailabh Nagar,  IBM Corp. 2004
5  *               Vivek Kashyap,   IBM Corp. 2004
6  *           
7  * 
8  * Directory operations for rcfs
9  *
10  * Latest version, more details at http://ckrm.sf.net
11  * 
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  */
18
19 /* Changes
20  *
21  * 08 Mar 2004
22  *        Created.
23  */
24
25
26 #include <linux/module.h>
27 #include <linux/fs.h>
28 #include <linux/namei.h>
29 #include <asm/namei.h>
30 #include <linux/namespace.h>
31 #include <linux/dcache.h>
32 #include <linux/seq_file.h>
33 #include <linux/pagemap.h>
34 #include <linux/highmem.h>
35 #include <linux/init.h>
36 #include <linux/string.h>
37 #include <linux/smp_lock.h>
38 #include <linux/backing-dev.h>
39 #include <linux/parser.h>
40
41 #include <asm/uaccess.h>
42
43 #include <linux/rcfs.h>
44
45
46
47 #define rcfs_positive(dentry)  ((dentry)->d_inode && !d_unhashed((dentry)))
48
49 int rcfs_empty(struct dentry *dentry)
50 {
51         struct dentry *child;
52         int ret = 0;
53                                                                                                
54         spin_lock(&dcache_lock);
55         list_for_each_entry(child, &dentry->d_subdirs, d_child)
56                 if (!rcfs_is_magic(child) && rcfs_positive(child))
57                         goto out;
58         ret = 1;
59 out:
60         spin_unlock(&dcache_lock);
61         return ret;
62 }
63
64                                                                                                
65
66
67 /* Directory inode operations */
68
69
70 int 
71 rcfs_create(struct inode *dir, struct dentry *dentry, int mode, 
72             struct nameidata *nd)
73 {
74         return rcfs_mknod(dir, dentry, mode | S_IFREG, 0);
75 }
76 EXPORT_SYMBOL(rcfs_create);
77
78
79 /* Symlinks permitted ?? */
80 int  
81 rcfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
82 {
83         struct inode *inode;
84         int error = -ENOSPC;
85
86         inode = rcfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
87         if (inode) {
88                 int l = strlen(symname)+1;
89                 error = page_symlink(inode, symname, l);
90                 if (!error) {
91                         if (dir->i_mode & S_ISGID)
92                                 inode->i_gid = dir->i_gid;
93                         d_instantiate(dentry, inode);
94                         dget(dentry);
95                 } else
96                         iput(inode);
97         }
98         return error;
99 }
100 EXPORT_SYMBOL(rcfs_symlink);
101
102 int
103 rcfs_create_coredir(struct inode *dir, struct dentry *dentry)
104 {
105
106         struct rcfs_inode_info *ripar, *ridir;
107         int sz;
108
109         ripar = RCFS_I(dir);
110         ridir = RCFS_I(dentry->d_inode);
111
112         // Inform RC's - do Core operations 
113         if (ckrm_is_core_valid(ripar->core)) {
114                 sz = strlen(ripar->name) + strlen(dentry->d_name.name) + 2 ;
115                 ridir->name = kmalloc(sz, GFP_KERNEL);
116                 if (!ridir->name) {
117                         return -ENOMEM;
118                 }
119                 snprintf(ridir->name, sz,"%s/%s", ripar->name, 
120                          dentry->d_name.name);
121                 ridir->core = (*(ripar->core->classtype->alloc))
122                         (ripar->core,ridir->name);
123         }
124         else {
125                 printk(KERN_ERR "rcfs_mkdir: Invalid parent core %p\n",
126                        ripar->core);
127                 return -EINVAL;
128         }
129
130         return 0;
131 }
132 EXPORT_SYMBOL(rcfs_create_coredir);
133
134
135 int
136 rcfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
137 {
138
139         int retval = 0;
140         ckrm_classtype_t *clstype;
141
142 #if 0
143         struct dentry *pd = list_entry(dir->i_dentry.next, struct dentry, 
144                                                         d_alias);
145         if ((!strcmp(pd->d_name.name, "/") &&
146              !strcmp(dentry->d_name.name, "ce"))) {
147                 // Call CE's mkdir if it has registered, else fail.
148                 if (rcfs_eng_callbacks.mkdir) {
149                         return (*rcfs_eng_callbacks.mkdir)(dir, dentry, mode);
150                 } else {
151                         return -EINVAL;
152                 }
153         }
154 #endif
155
156         if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) {
157                 printk(KERN_ERR "rcfs_mkdir: error in _rcfs_mknod\n");
158                 return retval;
159         }
160
161         dir->i_nlink++;
162
163         // Inherit parent's ops since _rcfs_mknod assigns noperm ops
164         dentry->d_inode->i_op = dir->i_op;
165         dentry->d_inode->i_fop = dir->i_fop;
166
167
168         retval = rcfs_create_coredir(dir, dentry);
169         if (retval) {
170                 simple_rmdir(dir,dentry);
171                 return retval;
172                 // goto mkdir_err;
173         }
174  
175         // create the default set of magic files 
176         clstype = (RCFS_I(dentry->d_inode))->core->classtype;
177         rcfs_create_magic(dentry, &(((struct rcfs_magf*)clstype->mfdesc)[1]), 
178                           clstype->mfcount-1);
179
180         return retval;
181
182 //mkdir_err:
183         dir->i_nlink--;
184         return retval;
185 }
186 EXPORT_SYMBOL(rcfs_mkdir);
187
188
189 int 
190 rcfs_rmdir(struct inode * dir, struct dentry * dentry)
191 {
192         struct rcfs_inode_info *ri = RCFS_I(dentry->d_inode);
193
194 #if 0
195         struct dentry *pd = list_entry(dir->i_dentry.next, 
196                                        struct dentry, d_alias);
197         if ((!strcmp(pd->d_name.name, "/") &&
198              !strcmp(dentry->d_name.name, "ce"))) {
199                 // Call CE's mkdir if it has registered, else fail.
200                 if (rcfs_eng_callbacks.rmdir) {
201                         return (*rcfs_eng_callbacks.rmdir)(dir, dentry);
202                 } else {
203                         return simple_rmdir(dir, dentry);
204                 }
205         }
206         else if ((!strcmp(pd->d_name.name, "/") &&
207                   !strcmp(dentry->d_name.name, "network"))) {
208                 return -EPERM;
209         }
210 #endif
211         
212         if (!rcfs_empty(dentry)) {
213                 printk(KERN_ERR "rcfs_rmdir: directory not empty\n");
214                 goto out;
215         }
216
217         // Core class removal 
218
219         if (ri->core == NULL) {
220                 printk(KERN_ERR "rcfs_rmdir: core==NULL\n");
221                 // likely a race condition
222                 return 0;
223         }
224
225         if ((*(ri->core->classtype->free))(ri->core)) {
226                 printk(KERN_ERR "rcfs_rmdir: ckrm_free_core_class failed\n");
227                 goto out;
228         }
229         ri->core = NULL ; // just to be safe 
230
231         // Clear magic files only after core successfully removed 
232         rcfs_clear_magic(dentry);
233
234         return simple_rmdir(dir, dentry);
235
236 out:
237         return -EBUSY;
238 }
239 EXPORT_SYMBOL(rcfs_rmdir);
240
241
242 int
243 rcfs_unlink(struct inode *dir, struct dentry *dentry)
244 {
245         // -ENOENT and not -ENOPERM to allow rm -rf to work despite 
246         // magic files being present
247         return -ENOENT;
248 }
249 EXPORT_SYMBOL(rcfs_unlink);
250         
251 // rename is allowed on directories only
252 int
253 rcfs_rename(struct inode *old_dir, struct dentry *old_dentry,
254                 struct inode *new_dir, struct dentry *new_dentry)
255 {
256         if (S_ISDIR(old_dentry->d_inode->i_mode)) 
257                 return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
258         else
259                 return -EINVAL;
260 }
261 EXPORT_SYMBOL(rcfs_rename);
262
263
264 struct inode_operations rcfs_dir_inode_operations = {
265         .create         = rcfs_create,
266         .lookup         = simple_lookup,
267         .link           = simple_link,
268         .unlink         = rcfs_unlink,
269         .symlink        = rcfs_symlink,
270         .mkdir          = rcfs_mkdir,
271         .rmdir          = rcfs_rmdir,
272         .mknod          = rcfs_mknod,
273         .rename         = rcfs_rename,
274 };
275
276
277
278
279
280 int 
281 rcfs_root_create(struct inode *dir, struct dentry *dentry, int mode, 
282                  struct nameidata *nd)
283 {
284         return -EPERM;
285 }
286
287
288 int  
289 rcfs_root_symlink(struct inode * dir, struct dentry *dentry, 
290                   const char * symname)
291 {
292         return -EPERM;
293 }
294
295 int 
296 rcfs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
297 {
298         return -EPERM;
299 }
300
301 int 
302 rcfs_root_rmdir(struct inode * dir, struct dentry * dentry)
303 {
304         return -EPERM;
305 }
306
307 int
308 rcfs_root_unlink(struct inode *dir, struct dentry *dentry)
309 {
310         return -EPERM;
311 }
312
313 int
314 rcfs_root_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
315 {
316         return -EPERM;
317 }
318         
319 int
320 rcfs_root_rename(struct inode *old_dir, struct dentry *old_dentry,
321                 struct inode *new_dir, struct dentry *new_dentry)
322 {
323         return -EPERM;
324 }
325
326 struct inode_operations rcfs_rootdir_inode_operations = {
327         .create         = rcfs_root_create,
328         .lookup         = simple_lookup,
329         .link           = simple_link,
330         .unlink         = rcfs_root_unlink,
331         .symlink        = rcfs_root_symlink,
332         .mkdir          = rcfs_root_mkdir,
333         .rmdir          = rcfs_root_rmdir,
334         .mknod          = rcfs_root_mknod,
335         .rename         = rcfs_root_rename,
336 };