Initial revision
[linux-2.6.git] / fs / rcfs / inode.c
1 /* 
2  * fs/rcfs/inode.c 
3  *
4  * Copyright (C) Shailabh Nagar,  IBM Corp. 2004
5  *               Vivek Kashyap,   IBM Corp. 2004
6  *           
7  * 
8  * Resource class filesystem (rcfs) forming the 
9  * user interface to Class-based Kernel Resource Management (CKRM).
10  *
11  * Latest version, more details at http://ckrm.sf.net
12  * 
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  */
19
20 /* Changes
21  *
22  * 05 Mar 2004
23  *        Created.
24  * 06 Mar 2004
25  *        Parsing for shares added
26  */
27
28
29 #include <linux/module.h>
30 #include <linux/list.h>
31 #include <linux/fs.h>
32 #include <linux/namei.h>
33 #include <asm/namei.h>
34 #include <linux/namespace.h>
35 #include <linux/dcache.h>
36 #include <linux/seq_file.h>
37 #include <linux/pagemap.h>
38 #include <linux/highmem.h>
39 #include <linux/init.h>
40 #include <linux/string.h>
41 #include <linux/smp_lock.h>
42 #include <linux/backing-dev.h>
43 #include <linux/parser.h>
44 #include <asm/uaccess.h>
45
46 #include <linux/rcfs.h>
47
48
49
50 // Address of variable used as flag to indicate a magic file, 
51 // ; value unimportant 
52 int RCFS_IS_MAGIC;
53
54
55 struct inode *rcfs_get_inode(struct super_block *sb, int mode, dev_t dev)
56 {
57         struct inode * inode = new_inode(sb);
58
59         if (inode) {
60                 inode->i_mode = mode;
61                 inode->i_uid = current->fsuid;
62                 inode->i_gid = current->fsgid;
63                 inode->i_blksize = PAGE_CACHE_SIZE;
64                 inode->i_blocks = 0;
65                 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
66                 switch (mode & S_IFMT) {
67                 default:
68                         init_special_inode(inode, mode, dev);
69                         break;
70                 case S_IFREG:
71                         // Treat as default assignment */
72                         inode->i_op = &rcfs_file_inode_operations;
73                         // inode->i_fop = &rcfs_file_operations;
74                         break;
75                 case S_IFDIR:
76                         // inode->i_op = &rcfs_dir_inode_operations;
77                         inode->i_op = &rcfs_rootdir_inode_operations;
78                         inode->i_fop = &simple_dir_operations;
79
80                         // directory inodes start off with i_nlink == 2 
81                         //  (for "." entry)
82  
83                         inode->i_nlink++;
84                         break;
85                 case S_IFLNK:
86                         inode->i_op = &page_symlink_inode_operations;
87                         break;
88                 }
89         }
90         return inode;
91 }
92
93
94
95 int
96 _rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
97 {
98         struct inode *inode;
99         int error = -EPERM;
100
101         if (dentry->d_inode)
102                 return -EEXIST;
103
104         inode = rcfs_get_inode(dir->i_sb, mode, dev);
105         if (inode) {
106                 if (dir->i_mode & S_ISGID) {
107                         inode->i_gid = dir->i_gid;
108                         if (S_ISDIR(mode))
109                                 inode->i_mode |= S_ISGID;
110                 }
111                 d_instantiate(dentry, inode);
112                 dget(dentry);   
113                 error = 0;
114         }
115
116         return error;
117 }
118 EXPORT_SYMBOL(_rcfs_mknod);
119
120
121 int
122 rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
123 {
124         // User can only create directories, not files
125         if ((mode & S_IFMT) != S_IFDIR)
126                 return -EINVAL;
127
128         return  dir->i_op->mkdir(dir, dentry, mode);
129 }
130 EXPORT_SYMBOL(rcfs_mknod);
131
132
133 struct dentry * 
134 rcfs_create_internal(struct dentry *parent, struct rcfs_magf *magf, int magic)
135 {
136         struct qstr qstr;
137         struct dentry *mfdentry ;
138
139         // Get new dentry for name  
140         qstr.name = magf->name;
141         qstr.len = strlen(magf->name);
142         qstr.hash = full_name_hash(magf->name,qstr.len);
143         mfdentry = lookup_hash(&qstr,parent);
144
145         if (!IS_ERR(mfdentry)) {
146                 int err; 
147
148                 down(&parent->d_inode->i_sem);
149                 if (magic && (magf->mode & S_IFDIR))
150                         err = parent->d_inode->i_op->mkdir(parent->d_inode,
151                                                    mfdentry, magf->mode);
152                 else {
153                         err =_rcfs_mknod(parent->d_inode,mfdentry,
154                                          magf->mode,0);
155                         // _rcfs_mknod doesn't increment parent's link count, 
156                         // i_op->mkdir does.
157                         parent->d_inode->i_nlink++;
158                 }
159                 up(&parent->d_inode->i_sem);
160
161                 if (err) {
162                         dput(mfdentry);
163                         return mfdentry;
164                 }
165         }
166         return mfdentry ;
167 }
168 EXPORT_SYMBOL(rcfs_create_internal);
169
170 int 
171 rcfs_delete_internal(struct dentry *mfdentry)
172 {
173         struct dentry *parent ;
174
175         if (!mfdentry || !mfdentry->d_parent)
176                 return -EINVAL;
177         
178         parent = mfdentry->d_parent;
179
180         if (!mfdentry->d_inode) {
181                 return 0;
182         }
183         down(&mfdentry->d_inode->i_sem);
184         if (S_ISDIR(mfdentry->d_inode->i_mode))
185                 simple_rmdir(parent->d_inode, mfdentry);
186         else
187                 simple_unlink(parent->d_inode, mfdentry);
188         up(&mfdentry->d_inode->i_sem);
189
190         d_delete(mfdentry);
191
192         return 0;
193 }
194 EXPORT_SYMBOL(rcfs_delete_internal);
195
196 struct inode_operations rcfs_file_inode_operations = {
197         .getattr        = simple_getattr,
198 };
199                 
200
201
202
203
204