This commit was manufactured by cvs2svn to create tag
[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 #include <linux/module.h>
29 #include <linux/list.h>
30 #include <linux/fs.h>
31 #include <linux/namei.h>
32 #include <linux/namespace.h>
33 #include <linux/dcache.h>
34 #include <linux/seq_file.h>
35 #include <linux/pagemap.h>
36 #include <linux/highmem.h>
37 #include <linux/init.h>
38 #include <linux/string.h>
39 #include <linux/smp_lock.h>
40 #include <linux/backing-dev.h>
41 #include <linux/parser.h>
42 #include <asm/uaccess.h>
43
44 #include <linux/rcfs.h>
45
46 // Address of variable used as flag to indicate a magic file, 
47 // ; value unimportant 
48 int RCFS_IS_MAGIC;
49
50 struct inode *rcfs_get_inode(struct super_block *sb, int mode, dev_t dev)
51 {
52         struct inode *inode = new_inode(sb);
53
54         if (inode) {
55                 inode->i_mode = mode;
56                 inode->i_uid = current->fsuid;
57                 inode->i_gid = current->fsgid;
58                 inode->i_blksize = PAGE_CACHE_SIZE;
59                 inode->i_blocks = 0;
60                 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
61                 switch (mode & S_IFMT) {
62                 default:
63                         init_special_inode(inode, mode, dev);
64                         break;
65                 case S_IFREG:
66                         // Treat as default assignment */
67                         inode->i_op = &rcfs_file_inode_operations;
68                         // inode->i_fop = &rcfs_file_operations;
69                         break;
70                 case S_IFDIR:
71                         // inode->i_op = &rcfs_dir_inode_operations;
72                         inode->i_op = &rcfs_rootdir_inode_operations;
73                         inode->i_fop = &simple_dir_operations;
74
75                         // directory inodes start off with i_nlink == 2 
76                         //  (for "." entry)
77
78                         inode->i_nlink++;
79                         break;
80                 case S_IFLNK:
81                         inode->i_op = &page_symlink_inode_operations;
82                         break;
83                 }
84         }
85         return inode;
86 }
87
88 int _rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
89 {
90         struct inode *inode;
91         int error = -EPERM;
92
93         if (dentry->d_inode)
94                 return -EEXIST;
95
96         inode = rcfs_get_inode(dir->i_sb, mode, dev);
97         if (inode) {
98                 if (dir->i_mode & S_ISGID) {
99                         inode->i_gid = dir->i_gid;
100                         if (S_ISDIR(mode))
101                                 inode->i_mode |= S_ISGID;
102                 }
103                 d_instantiate(dentry, inode);
104                 dget(dentry);
105                 error = 0;
106         }
107
108         return error;
109 }
110
111 EXPORT_SYMBOL(_rcfs_mknod);
112
113 int rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
114 {
115         // User can only create directories, not files
116         if ((mode & S_IFMT) != S_IFDIR)
117                 return -EINVAL;
118
119         return dir->i_op->mkdir(dir, dentry, mode);
120 }
121
122 EXPORT_SYMBOL(rcfs_mknod);
123
124 struct dentry *rcfs_create_internal(struct dentry *parent,
125                                     struct rcfs_magf *magf, int magic)
126 {
127         struct qstr qstr;
128         struct dentry *mfdentry;
129
130         // Get new dentry for name  
131         qstr.name = magf->name;
132         qstr.len = strlen(magf->name);
133         qstr.hash = full_name_hash(magf->name, qstr.len);
134         mfdentry = lookup_hash(&qstr, parent);
135
136         if (!IS_ERR(mfdentry)) {
137                 int err;
138
139                 down(&parent->d_inode->i_sem);
140                 if (magic && (magf->mode & S_IFDIR))
141                         err = parent->d_inode->i_op->mkdir(parent->d_inode,
142                                                            mfdentry,
143                                                            magf->mode);
144                 else {
145                         err = _rcfs_mknod(parent->d_inode, mfdentry,
146                                           magf->mode, 0);
147                         // _rcfs_mknod doesn't increment parent's link count, 
148                         // i_op->mkdir does.
149                         parent->d_inode->i_nlink++;
150                 }
151                 up(&parent->d_inode->i_sem);
152
153                 if (err) {
154                         dput(mfdentry);
155                         return mfdentry;
156                 }
157         }
158         return mfdentry;
159 }
160
161 EXPORT_SYMBOL(rcfs_create_internal);
162
163 int rcfs_delete_internal(struct dentry *mfdentry)
164 {
165         struct dentry *parent;
166
167         if (!mfdentry || !mfdentry->d_parent)
168                 return -EINVAL;
169
170         parent = mfdentry->d_parent;
171
172         if (!mfdentry->d_inode) {
173                 return 0;
174         }
175         down(&mfdentry->d_inode->i_sem);
176         if (S_ISDIR(mfdentry->d_inode->i_mode))
177                 simple_rmdir(parent->d_inode, mfdentry);
178         else
179                 simple_unlink(parent->d_inode, mfdentry);
180         up(&mfdentry->d_inode->i_sem);
181
182         d_delete(mfdentry);
183
184         return 0;
185 }
186
187 EXPORT_SYMBOL(rcfs_delete_internal);
188
189 struct inode_operations rcfs_file_inode_operations = {
190         .getattr = simple_getattr,
191 };