4 * Copyright (C) Shailabh Nagar, IBM Corp. 2004
5 * Vivek Kashyap, IBM Corp. 2004
8 * Directory operations for rcfs
10 * Latest version, more details at http://ckrm.sf.net
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.
25 #include <linux/module.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>
39 #include <asm/uaccess.h>
41 #include <linux/rcfs.h>
43 #define rcfs_positive(dentry) ((dentry)->d_inode && !d_unhashed((dentry)))
45 int rcfs_empty(struct dentry *dentry)
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))
56 spin_unlock(&dcache_lock);
60 /* Directory inode operations */
63 rcfs_create(struct inode *dir, struct dentry *dentry, int mode,
66 return rcfs_mknod(dir, dentry, mode | S_IFREG, 0);
69 EXPORT_SYMBOL(rcfs_create);
71 /* Symlinks permitted ?? */
72 int rcfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
77 inode = rcfs_get_inode(dir->i_sb, S_IFLNK | S_IRWXUGO, 0);
79 int l = strlen(symname) + 1;
80 error = page_symlink(inode, symname, l);
82 if (dir->i_mode & S_ISGID)
83 inode->i_gid = dir->i_gid;
84 d_instantiate(dentry, inode);
92 EXPORT_SYMBOL(rcfs_symlink);
94 int rcfs_create_coredir(struct inode *dir, struct dentry *dentry)
97 struct rcfs_inode_info *ripar, *ridir;
101 ridir = RCFS_I(dentry->d_inode);
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);
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);
115 printk(KERN_ERR "rcfs_mkdir: Invalid parent core %p\n",
123 EXPORT_SYMBOL(rcfs_create_coredir);
125 int rcfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
129 ckrm_classtype_t *clstype;
132 struct dentry *pd = list_entry(dir->i_dentry.next, struct dentry,
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);
145 if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) {
146 printk(KERN_ERR "rcfs_mkdir: error in _rcfs_mknod\n");
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;
156 retval = rcfs_create_coredir(dir, dentry);
158 simple_rmdir(dir, dentry);
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 - 2);
174 EXPORT_SYMBOL(rcfs_mkdir);
176 int rcfs_rmdir(struct inode *dir, struct dentry *dentry)
178 struct rcfs_inode_info *ri = RCFS_I(dentry->d_inode);
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);
189 return simple_rmdir(dir, dentry);
191 } else if ((!strcmp(pd->d_name.name, "/") &&
192 !strcmp(dentry->d_name.name, "network"))) {
197 if (!rcfs_empty(dentry)) {
198 printk(KERN_ERR "rcfs_rmdir: directory not empty\n");
201 // Core class removal
203 if (ri->core == NULL) {
204 printk(KERN_ERR "rcfs_rmdir: core==NULL\n");
205 // likely a race condition
209 if ((*(ri->core->classtype->free)) (ri->core)) {
210 printk(KERN_ERR "rcfs_rmdir: ckrm_free_core_class failed\n");
213 ri->core = NULL; // just to be safe
215 // Clear magic files only after core successfully removed
216 rcfs_clear_magic(dentry);
218 return simple_rmdir(dir, dentry);
224 EXPORT_SYMBOL(rcfs_rmdir);
226 int rcfs_unlink(struct inode *dir, struct dentry *dentry)
228 // -ENOENT and not -ENOPERM to allow rm -rf to work despite
229 // magic files being present
233 EXPORT_SYMBOL(rcfs_unlink);
235 // rename is allowed on directories only
237 rcfs_rename(struct inode *old_dir, struct dentry *old_dentry,
238 struct inode *new_dir, struct dentry *new_dentry)
240 if (S_ISDIR(old_dentry->d_inode->i_mode))
241 return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
246 EXPORT_SYMBOL(rcfs_rename);
248 struct inode_operations rcfs_dir_inode_operations = {
249 .create = rcfs_create,
250 .lookup = simple_lookup,
252 .unlink = rcfs_unlink,
253 .symlink = rcfs_symlink,
257 .rename = rcfs_rename,
261 rcfs_root_create(struct inode *dir, struct dentry *dentry, int mode,
262 struct nameidata *nd)
268 rcfs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
273 int rcfs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
278 int rcfs_root_rmdir(struct inode *dir, struct dentry *dentry)
283 int rcfs_root_unlink(struct inode *dir, struct dentry *dentry)
289 rcfs_root_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
295 rcfs_root_rename(struct inode *old_dir, struct dentry *old_dentry,
296 struct inode *new_dir, struct dentry *new_dentry)
301 struct inode_operations rcfs_rootdir_inode_operations = {
302 .create = rcfs_root_create,
303 .lookup = simple_lookup,
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,