This commit was manufactured by cvs2svn to create branch
[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  * Resource class filesystem (rcfs) forming the 
8  * user interface to Class-based Kernel Resource Management (CKRM).
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  * 05 Mar 2004
22  *        Created.
23  * 06 Mar 2004
24  *        Parsing for shares added
25  */
26
27 #include <linux/module.h>
28 #include <linux/list.h>
29 #include <linux/fs.h>
30 #include <linux/namei.h>
31 #include <linux/namespace.h>
32 #include <linux/dcache.h>
33 #include <linux/seq_file.h>
34 #include <linux/pagemap.h>
35 #include <linux/highmem.h>
36 #include <linux/init.h>
37 #include <linux/string.h>
38 #include <linux/smp_lock.h>
39 #include <linux/backing-dev.h>
40 #include <linux/parser.h>
41 #include <asm/uaccess.h>
42
43 #include <linux/rcfs.h>
44
45 /*
46  * Address of variable used as flag to indicate a magic file, 
47  * value unimportant
48  */ 
49 int RCFS_IS_MAGIC;
50
51 struct inode *rcfs_get_inode(struct super_block *sb, int mode, dev_t dev)
52 {
53         struct inode *inode = new_inode(sb);
54
55         if (inode) {
56                 inode->i_mode = mode;
57                 inode->i_uid = current->fsuid;
58                 inode->i_gid = current->fsgid;
59                 inode->i_blksize = PAGE_CACHE_SIZE;
60                 inode->i_blocks = 0;
61                 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
62                 switch (mode & S_IFMT) {
63                 default:
64                         init_special_inode(inode, mode, dev);
65                         break;
66                 case S_IFREG:
67                         /* Treat as default assignment */
68                         inode->i_op = &rcfs_file_inode_operations;
69                         /* inode->i_fop = &rcfs_file_operations; */
70                         break;
71                 case S_IFDIR:
72                         /* inode->i_op = &rcfs_dir_inode_operations; */
73                         inode->i_op = &rcfs_rootdir_inode_operations;
74                         inode->i_fop = &simple_dir_operations;
75
76                         /*
77                          * directory inodes start off with i_nlink == 2 
78                          *  (for "." entry)
79                          */
80                         inode->i_nlink++;
81                         break;
82                 case S_IFLNK:
83                         inode->i_op = &page_symlink_inode_operations;
84                         break;
85                 }
86         }
87         return inode;
88 }
89
90 int _rcfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
91 {
92         struct inode *inode;
93         int error = -EPERM;
94
95         if (dentry->d_inode)
96                 return -EEXIST;
97         inode = rcfs_get_inode(dir->i_sb, mode, dev);
98         if (inode) {
99                 if (dir->i_mode & S_ISGID) {
100                         inode->i_gid = dir->i_gid;
101                         if (S_ISDIR(mode))
102                                 inode->i_mode |= S_ISGID;
103                 }
104                 d_instantiate(dentry, inode);
105                 dget(dentry);
106                 error = 0;
107         }
108         return error;
109 }
110
111 EXPORT_SYMBOL_GPL(_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_GPL(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                         /*
148                          * _rcfs_mknod doesn't increment parent's link count, 
149                          * i_op->mkdir does.
150                          */
151                         parent->d_inode->i_nlink++;
152                 }
153                 up(&parent->d_inode->i_sem);
154                 if (err) {
155                         dput(mfdentry);
156                         return mfdentry;
157                 }
158         }
159         return mfdentry;
160 }
161
162 EXPORT_SYMBOL_GPL(rcfs_create_internal);
163
164 int rcfs_delete_internal(struct dentry *mfdentry)
165 {
166         struct dentry *parent;
167
168         if (!mfdentry || !mfdentry->d_parent)
169                 return -EINVAL;
170         parent = mfdentry->d_parent;
171         if (!mfdentry->d_inode) {
172                 return 0;
173         }
174         down(&mfdentry->d_inode->i_sem);
175         if (S_ISDIR(mfdentry->d_inode->i_mode))
176                 simple_rmdir(parent->d_inode, mfdentry);
177         else
178                 simple_unlink(parent->d_inode, mfdentry);
179         up(&mfdentry->d_inode->i_sem);
180         d_delete(mfdentry);
181
182         return 0;
183 }
184
185 EXPORT_SYMBOL_GPL(rcfs_delete_internal);
186
187 struct inode_operations rcfs_file_inode_operations = {
188         .getattr = simple_getattr,
189 };