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