This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / rcfs / socket_fs.c
1 /* ckrm_socketaq.c 
2  *
3  * Copyright (C) Vivek Kashyap,      IBM Corp. 2004
4  * 
5  * Latest version, more details at http://ckrm.sf.net
6  * 
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  */
13
14 /* Changes
15  * Initial version
16  */
17
18 /*******************************************************************************
19  *  Socket class type
20  *   
21  * Defines the root structure for socket based classes. Currently only inbound
22  * connection control is supported based on prioritized accept queues. 
23  ******************************************************************************/
24
25
26 #include <linux/rcfs.h>
27 #include <net/tcp.h>
28
29 extern int rcfs_create(struct inode *,struct dentry *, int, struct nameidata *);
30 extern int rcfs_unlink(struct inode *, struct dentry *);
31 extern int  rcfs_symlink(struct inode *, struct dentry *, const char *);
32 extern int rcfs_mknod(struct inode *, struct dentry *, int mode, dev_t);
33 extern int rcfs_mkdir(struct inode *, struct dentry *, int);
34 extern int rcfs_rmdir(struct inode *, struct dentry *);
35 extern int rcfs_rename(struct inode *, struct dentry *, struct inode *, 
36                 struct dentry *);
37
38 extern int rcfs_create_coredir(struct inode *, struct dentry *);
39 int sock_mkdir(struct inode *, struct dentry *, int mode);
40 int sock_rmdir(struct inode *, struct dentry *);
41
42
43 int sock_create_noperm(struct inode *, struct dentry *,int, struct nameidata *);
44 int sock_unlink_noperm(struct inode *,struct dentry *);
45 int sock_mkdir_noperm(struct inode *,struct dentry *,int);
46 int sock_rmdir_noperm(struct inode *,struct dentry *);
47 int sock_mknod_noperm(struct inode *,struct dentry *,int, dev_t);
48
49 void sock_set_directory(void);
50
51 extern struct file_operations config_fileops,
52                         members_fileops,
53                         shares_fileops,
54                         stats_fileops,
55                         target_fileops;
56
57
58 struct inode_operations my_iops = {
59                 .create         = rcfs_create,
60                 .lookup         = simple_lookup,
61                 .link           = simple_link,
62                 .unlink         = rcfs_unlink,
63                 .symlink        = rcfs_symlink,
64                 .mkdir          = sock_mkdir,
65                 .rmdir          = sock_rmdir,
66                 .mknod          = rcfs_mknod,
67                 .rename         = rcfs_rename,
68 };
69
70 struct inode_operations class_iops = {
71                 .create         = sock_create_noperm,
72                 .lookup         = simple_lookup,
73                 .link           = simple_link,
74                 .unlink         = sock_unlink_noperm,
75                 .symlink        = rcfs_symlink,
76                 .mkdir          = sock_mkdir_noperm,
77                 .rmdir          = sock_rmdir_noperm,
78                 .mknod          = sock_mknod_noperm,
79                 .rename         = rcfs_rename,
80 };
81
82 struct inode_operations sub_iops = {
83                 .create         = sock_create_noperm,
84                 .lookup         = simple_lookup,
85                 .link           = simple_link,
86                 .unlink         = sock_unlink_noperm,
87                 .symlink        = rcfs_symlink,
88                 .mkdir          = sock_mkdir_noperm,
89                 .rmdir          = sock_rmdir_noperm,
90                 .mknod          = sock_mknod_noperm,
91                 .rename         = rcfs_rename,
92 };
93
94 struct rcfs_magf def_magf = {
95         .mode = RCFS_DEFAULT_DIR_MODE,
96         .i_op = &sub_iops,
97         .i_fop = NULL,
98 };
99
100 struct rcfs_magf sock_rootdesc[] = {
101         {
102         //      .name = should not be set, copy from classtype name,
103                 .mode = RCFS_DEFAULT_DIR_MODE,
104                 .i_op = &my_iops,
105                 //.i_fop   = &simple_dir_operations,
106                 .i_fop = NULL,
107         },
108         {
109                 .name = "members",
110                 .mode = RCFS_DEFAULT_FILE_MODE,
111                 .i_op = &my_iops,
112                 .i_fop = &members_fileops,
113         },
114         {
115                 .name = "target",
116                 .mode = RCFS_DEFAULT_FILE_MODE,
117                 .i_op = &my_iops,
118                 .i_fop = &target_fileops,
119         },
120 };
121
122 struct rcfs_magf sock_magf[] = {
123         {
124                 .name = "config",
125                 .mode = RCFS_DEFAULT_FILE_MODE,
126                 .i_op = &my_iops,
127                 .i_fop = &config_fileops,
128         },
129         {
130                 .name = "members",
131                 .mode = RCFS_DEFAULT_FILE_MODE,
132                 .i_op = &my_iops,
133                 .i_fop =&members_fileops,
134         },
135         {
136                 .name = "shares",
137                 .mode = RCFS_DEFAULT_FILE_MODE,
138                 .i_op = &my_iops,
139                 .i_fop = &shares_fileops,
140         },
141         {
142                 .name = "stats",
143                 .mode = RCFS_DEFAULT_FILE_MODE,
144                 .i_op = &my_iops,
145                 .i_fop = &stats_fileops,
146         },
147         {
148                 .name = "target",
149                 .mode = RCFS_DEFAULT_FILE_MODE,
150                 .i_op = &my_iops,
151                 .i_fop = &target_fileops,
152         },
153 };
154
155 struct rcfs_magf sub_magf[] = {
156         {
157                 .name = "config",
158                 .mode = RCFS_DEFAULT_FILE_MODE,
159                 .i_op = &my_iops,
160                 .i_fop = &config_fileops,
161         },
162         {
163                 .name = "shares",
164                 .mode = RCFS_DEFAULT_FILE_MODE,
165                 .i_op = &my_iops,
166                 .i_fop = &shares_fileops,
167         },
168         {
169                 .name = "stats",
170                 .mode = RCFS_DEFAULT_FILE_MODE,
171                 .i_op = &my_iops,
172                 .i_fop = &stats_fileops,
173         },
174 };
175
176 struct rcfs_mfdesc sock_mfdesc = {
177         .rootmf         = sock_rootdesc,
178         .rootmflen      = (sizeof(sock_rootdesc)/sizeof(struct rcfs_magf)),
179 };
180
181
182 #define SOCK_MAX_MAGF (sizeof(sock_magf)/sizeof(struct rcfs_magf))
183 #define LAQ_MAX_SUBMAGF (sizeof(sub_magf)/sizeof(struct rcfs_magf))
184
185 int 
186 sock_rmdir(struct inode *p, struct dentry *me)
187 {
188         struct dentry *mftmp, *mfdentry ;
189
190         // delete all magic sub directories
191         list_for_each_entry_safe(mfdentry, mftmp, &me->d_subdirs, d_child) {
192                 if (S_ISDIR(mfdentry->d_inode->i_mode))
193                         rcfs_rmdir(me->d_inode, mfdentry);
194         }
195         // delete ourselves
196         rcfs_rmdir(p,me);
197
198         return 0;
199 }
200
201 #ifdef NUM_ACCEPT_QUEUES
202 #define LAQ_NUM_ACCEPT_QUEUES NUM_ACCEPT_QUEUES
203 #else
204 #define LAQ_NUM_ACCEPT_QUEUES 0
205 #endif
206
207 int
208 sock_mkdir(struct inode *dir, struct dentry *dentry, int mode)
209 {
210         int retval = 0;
211         int i,j;
212         struct dentry *pentry, *mfdentry;
213
214         if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) {
215                 printk(KERN_ERR "rcfs_mkdir: error reaching parent\n");
216                 return retval;
217         }
218         
219         // Needed if only _rcfs_mknod is used instead of i_op->mkdir
220         dir->i_nlink++;
221
222         retval = rcfs_create_coredir(dir, dentry);
223         if (retval) 
224                 goto mkdir_err;
225
226         /* create the default set of magic files */
227         for (i =0; i < SOCK_MAX_MAGF; i++) {
228                 mfdentry = rcfs_create_internal(dentry, &sock_magf[i],0);
229                 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
230                 RCFS_I(mfdentry->d_inode)->core = 
231                                 RCFS_I(dentry->d_inode)->core;
232                 if (sock_magf[i].i_fop)
233                         mfdentry->d_inode->i_fop = sock_magf[i].i_fop;
234                 if (sock_magf[i].i_op)
235                         mfdentry->d_inode->i_op = sock_magf[i].i_op;
236         }
237         
238         for (i=1; i < LAQ_NUM_ACCEPT_QUEUES; i++) {
239                 j = sprintf(def_magf.name, "%d",i);
240                 def_magf.name[j] = '\0';
241
242                 pentry = rcfs_create_internal(dentry, &def_magf,0);
243                 retval = rcfs_create_coredir(dentry->d_inode, pentry);
244                 if (retval)
245                         goto mkdir_err;
246                 for (j=0; j < LAQ_MAX_SUBMAGF; j++) {
247                         mfdentry = rcfs_create_internal(pentry, &sub_magf[j],0);
248                         mfdentry->d_fsdata = &RCFS_IS_MAGIC;
249                         RCFS_I(mfdentry->d_inode)->core = 
250                                         RCFS_I(pentry->d_inode)->core;
251                         if (sub_magf[j].i_fop)
252                                 mfdentry->d_inode->i_fop = sub_magf[j].i_fop;
253                         if (sub_magf[j].i_op)
254                                 mfdentry->d_inode->i_op = sub_magf[j].i_op;
255                 }
256                 pentry->d_inode->i_op = &sub_iops;
257         }
258         dentry->d_inode->i_op = &class_iops;
259         return 0;
260
261 mkdir_err:
262         // Needed
263         dir->i_nlink--;
264         return retval;
265 }
266 #ifndef NUM_ACCEPT_QUEUES
267 #define NUM_ACCEPT_QUEUES 0
268 #endif
269
270 char *
271 sock_get_name(struct ckrm_core_class *c)
272 {
273         char *p = (char *)c->name;
274         
275         while(*p)
276                 p++;
277         while( *p != '/' && p != c->name)
278                 p--;
279
280         return ++p;
281 }
282
283 int 
284 sock_create_noperm(struct inode *dir,struct dentry *dentry,int mode, struct nameidata *nd)
285 {
286         return -EPERM;
287 }
288
289 int 
290 sock_unlink_noperm(struct inode *dir,struct dentry *dentry)
291 {
292         return -EPERM;
293 }
294
295 int 
296 sock_mkdir_noperm(struct inode *dir,struct dentry *dentry, int mode)
297 {
298         return -EPERM;
299 }
300
301 int 
302 sock_rmdir_noperm(struct inode *dir,struct dentry *dentry)
303 {
304         return -EPERM;
305 }
306
307 int 
308 sock_mknod_noperm(struct inode *dir,struct dentry *dentry,int mode, dev_t dev)
309 {
310         return -EPERM;
311 }
312
313 #if 0
314 void
315 sock_set_directory()
316 {
317         struct dentry *pentry, *dentry;
318
319         pentry = rcfs_set_magf_byname("listen_aq", (void *)&my_dir_magf[0]);
320         if (pentry) {
321                 dentry = rcfs_create_internal(pentry, &my_dir_magf[1],0);
322                 if (my_dir_magf[1].i_fop)
323                         dentry->d_inode->i_fop = my_dir_magf[1].i_fop;
324                 RCFS_I(dentry->d_inode)->core = 
325                                 RCFS_I(pentry->d_inode)->core;
326                 dentry = rcfs_create_internal(pentry, &my_dir_magf[2],0);
327                 if (my_dir_magf[2].i_fop)
328                         dentry->d_inode->i_fop = my_dir_magf[2].i_fop;
329                 RCFS_I(dentry->d_inode)->core = 
330                                 RCFS_I(pentry->d_inode)->core;
331         }
332         else  {
333                 printk(KERN_ERR "Could not create /rcfs/listen_aq\n"
334                                 "Perhaps /rcfs needs to be mounted\n");
335         }
336 }
337 #endif
338