This commit was manufactured by cvs2svn to create branch
[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 #include <linux/rcfs.h>
26 #include <net/tcp.h>
27
28 extern int rcfs_create(struct inode *, struct dentry *, int,
29                        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 int sock_create_noperm(struct inode *, struct dentry *, int,
43                        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, shares_fileops, stats_fileops, target_fileops;
53
54 struct inode_operations my_iops = {
55         .create = rcfs_create,
56         .lookup = simple_lookup,
57         .link = simple_link,
58         .unlink = rcfs_unlink,
59         .symlink = rcfs_symlink,
60         .mkdir = sock_mkdir,
61         .rmdir = sock_rmdir,
62         .mknod = rcfs_mknod,
63         .rename = rcfs_rename,
64 };
65
66 struct inode_operations class_iops = {
67         .create = sock_create_noperm,
68         .lookup = simple_lookup,
69         .link = simple_link,
70         .unlink = sock_unlink_noperm,
71         .symlink = rcfs_symlink,
72         .mkdir = sock_mkdir_noperm,
73         .rmdir = sock_rmdir_noperm,
74         .mknod = sock_mknod_noperm,
75         .rename = rcfs_rename,
76 };
77
78 struct inode_operations sub_iops = {
79         .create = sock_create_noperm,
80         .lookup = simple_lookup,
81         .link = simple_link,
82         .unlink = sock_unlink_noperm,
83         .symlink = rcfs_symlink,
84         .mkdir = sock_mkdir_noperm,
85         .rmdir = sock_rmdir_noperm,
86         .mknod = sock_mknod_noperm,
87         .rename = rcfs_rename,
88 };
89
90 struct rcfs_magf def_magf = {
91         .mode = RCFS_DEFAULT_DIR_MODE,
92         .i_op = &sub_iops,
93         .i_fop = NULL,
94 };
95
96 struct rcfs_magf sock_rootdesc[] = {
97         {
98          //      .name = should not be set, copy from classtype name,
99          .mode = RCFS_DEFAULT_DIR_MODE,
100          .i_op = &my_iops,
101          //.i_fop   = &simple_dir_operations,
102          .i_fop = NULL,
103          },
104         {
105          .name = "members",
106          .mode = RCFS_DEFAULT_FILE_MODE,
107          .i_op = &my_iops,
108          .i_fop = &members_fileops,
109          },
110         {
111          .name = "target",
112          .mode = RCFS_DEFAULT_FILE_MODE,
113          .i_op = &my_iops,
114          .i_fop = &target_fileops,
115          },
116         {
117          .name = "reclassify",
118          .mode = RCFS_DEFAULT_FILE_MODE,
119          .i_op = &my_iops,
120          .i_fop = &reclassify_fileops,
121          },
122 };
123
124 struct rcfs_magf sock_magf[] = {
125         {
126          .name = "config",
127          .mode = RCFS_DEFAULT_FILE_MODE,
128          .i_op = &my_iops,
129          .i_fop = &config_fileops,
130          },
131         {
132          .name = "members",
133          .mode = RCFS_DEFAULT_FILE_MODE,
134          .i_op = &my_iops,
135          .i_fop = &members_fileops,
136          },
137         {
138          .name = "shares",
139          .mode = RCFS_DEFAULT_FILE_MODE,
140          .i_op = &my_iops,
141          .i_fop = &shares_fileops,
142          },
143         {
144          .name = "stats",
145          .mode = RCFS_DEFAULT_FILE_MODE,
146          .i_op = &my_iops,
147          .i_fop = &stats_fileops,
148          },
149         {
150          .name = "target",
151          .mode = RCFS_DEFAULT_FILE_MODE,
152          .i_op = &my_iops,
153          .i_fop = &target_fileops,
154          },
155 };
156
157 struct rcfs_magf sub_magf[] = {
158         {
159          .name = "config",
160          .mode = RCFS_DEFAULT_FILE_MODE,
161          .i_op = &my_iops,
162          .i_fop = &config_fileops,
163          },
164         {
165          .name = "shares",
166          .mode = RCFS_DEFAULT_FILE_MODE,
167          .i_op = &my_iops,
168          .i_fop = &shares_fileops,
169          },
170         {
171          .name = "stats",
172          .mode = RCFS_DEFAULT_FILE_MODE,
173          .i_op = &my_iops,
174          .i_fop = &stats_fileops,
175          },
176 };
177
178 struct rcfs_mfdesc sock_mfdesc = {
179         .rootmf = sock_rootdesc,
180         .rootmflen = (sizeof(sock_rootdesc) / sizeof(struct rcfs_magf)),
181 };
182
183 #define SOCK_MAX_MAGF (sizeof(sock_magf)/sizeof(struct rcfs_magf))
184 #define LAQ_MAX_SUBMAGF (sizeof(sub_magf)/sizeof(struct rcfs_magf))
185
186 int sock_rmdir(struct inode *p, struct dentry *me)
187 {
188         struct dentry *mftmp, *mfdentry;
189         int ret = 0;
190
191         // delete all magic sub directories
192         list_for_each_entry_safe(mfdentry, mftmp, &me->d_subdirs, d_child) {
193                 if (S_ISDIR(mfdentry->d_inode->i_mode)) {
194                         ret = rcfs_rmdir(me->d_inode, mfdentry);
195                         if (ret)
196                                 return ret;
197                 }
198         }
199         // delete ourselves
200         ret = rcfs_rmdir(p, me);
201
202         return ret;
203 }
204
205 #ifdef NUM_ACCEPT_QUEUES
206 #define LAQ_NUM_ACCEPT_QUEUES NUM_ACCEPT_QUEUES
207 #else
208 #define LAQ_NUM_ACCEPT_QUEUES 0
209 #endif
210
211 int sock_mkdir(struct inode *dir, struct dentry *dentry, int mode)
212 {
213         int retval = 0;
214         int i, j;
215         struct dentry *pentry, *mfdentry;
216
217         if (_rcfs_mknod(dir, dentry, mode | S_IFDIR, 0)) {
218                 printk(KERN_ERR "rcfs_mkdir: error reaching parent\n");
219                 return retval;
220         }
221         // Needed if only _rcfs_mknod is used instead of i_op->mkdir
222         dir->i_nlink++;
223
224         retval = rcfs_create_coredir(dir, dentry);
225         if (retval)
226                 goto mkdir_err;
227
228         /* create the default set of magic files */
229         for (i = 0; i < SOCK_MAX_MAGF; i++) {
230                 mfdentry = rcfs_create_internal(dentry, &sock_magf[i], 0);
231                 mfdentry->d_fsdata = &RCFS_IS_MAGIC;
232                 RCFS_I(mfdentry->d_inode)->core = RCFS_I(dentry->d_inode)->core;
233                 if (sock_magf[i].i_fop)
234                         mfdentry->d_inode->i_fop = sock_magf[i].i_fop;
235                 if (sock_magf[i].i_op)
236                         mfdentry->d_inode->i_op = sock_magf[i].i_op;
237         }
238
239         for (i = 1; i < LAQ_NUM_ACCEPT_QUEUES; i++) {
240                 j = sprintf(def_magf.name, "%d", i);
241                 def_magf.name[j] = '\0';
242
243                 pentry = rcfs_create_internal(dentry, &def_magf, 0);
244                 retval = rcfs_create_coredir(dentry->d_inode, pentry);
245                 if (retval)
246                         goto mkdir_err;
247                 pentry->d_fsdata = &RCFS_IS_MAGIC;
248                 for (j = 0; j < LAQ_MAX_SUBMAGF; j++) {
249                         mfdentry =
250                             rcfs_create_internal(pentry, &sub_magf[j], 0);
251                         mfdentry->d_fsdata = &RCFS_IS_MAGIC;
252                         RCFS_I(mfdentry->d_inode)->core =
253                             RCFS_I(pentry->d_inode)->core;
254                         if (sub_magf[j].i_fop)
255                                 mfdentry->d_inode->i_fop = sub_magf[j].i_fop;
256                         if (sub_magf[j].i_op)
257                                 mfdentry->d_inode->i_op = sub_magf[j].i_op;
258                 }
259                 pentry->d_inode->i_op = &sub_iops;
260         }
261         dentry->d_inode->i_op = &class_iops;
262         return 0;
263
264       mkdir_err:
265         // Needed
266         dir->i_nlink--;
267         return retval;
268 }
269
270 #ifndef NUM_ACCEPT_QUEUES
271 #define NUM_ACCEPT_QUEUES 0
272 #endif
273
274 char *sock_get_name(struct ckrm_core_class *c)
275 {
276         char *p = (char *)c->name;
277
278         while (*p)
279                 p++;
280         while (*p != '/' && p != c->name)
281                 p--;
282
283         return ++p;
284 }
285
286 int
287 sock_create_noperm(struct inode *dir, struct dentry *dentry, int mode,
288                    struct nameidata *nd)
289 {
290         return -EPERM;
291 }
292
293 int sock_unlink_noperm(struct inode *dir, struct dentry *dentry)
294 {
295         return -EPERM;
296 }
297
298 int sock_mkdir_noperm(struct inode *dir, struct dentry *dentry, int mode)
299 {
300         return -EPERM;
301 }
302
303 int sock_rmdir_noperm(struct inode *dir, struct dentry *dentry)
304 {
305         return -EPERM;
306 }
307
308 int
309 sock_mknod_noperm(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
310 {
311         return -EPERM;
312 }
313
314 #if 0
315 void 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 = RCFS_I(pentry->d_inode)->core;
325                 dentry = rcfs_create_internal(pentry, &my_dir_magf[2], 0);
326                 if (my_dir_magf[2].i_fop)
327                         dentry->d_inode->i_fop = my_dir_magf[2].i_fop;
328                 RCFS_I(dentry->d_inode)->core = RCFS_I(pentry->d_inode)->core;
329         } else {
330                 printk(KERN_ERR "Could not create /rcfs/listen_aq\n"
331                        "Perhaps /rcfs needs to be mounted\n");
332         }
333 }
334 #endif