This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / intermezzo / kml.c
1 #include <linux/errno.h>
2 #include <linux/slab.h>
3 #include <linux/vmalloc.h>
4 #include <linux/module.h>
5 #include <asm/uaccess.h>
6
7 #include "intermezzo_fs.h"
8 #include "intermezzo_upcall.h"
9 #include "intermezzo_psdev.h"
10 #include "intermezzo_kml.h"
11
12 static struct presto_file_set * kml_getfset (char *path)
13 {
14         return presto_path2fileset(path);
15 }
16
17 /* Send the KML buffer and related volume info into kernel */
18 int begin_kml_reint (struct file *file, unsigned long arg)
19 {
20         struct {
21                 char *volname;
22                 int   namelen;  
23                 char *recbuf;
24                 int   reclen;     /* int   newpos; */
25         } input;
26         struct kml_fsdata *kml_fsdata = NULL;
27         struct presto_file_set *fset = NULL;
28         char   *path;
29         int    error;
30
31         ENTRY;
32         /* allocate buffer & copy it to kernel space */
33         if (copy_from_user(&input, (char *)arg, sizeof(input))) {
34                 EXIT;
35                 return -EFAULT;
36         }
37
38         if (input.reclen > kml_fsdata->kml_maxsize)
39                 return -ENOMEM; /* we'll find solution to this in the future */
40
41         PRESTO_ALLOC(path, char *, input.namelen + 1);
42         if ( !path ) {
43                 EXIT;
44                 return -ENOMEM;
45         }
46         if (copy_from_user(path, input.volname, input.namelen)) {
47                 PRESTO_FREE(path, input.namelen + 1);
48                 EXIT;
49                 return -EFAULT;
50         }
51         path[input.namelen] = '\0';
52         fset = kml_getfset (path);
53         PRESTO_FREE(path, input.namelen + 1);
54
55         kml_fsdata = FSET_GET_KMLDATA(fset);
56         /* read the buf from user memory here */
57         if (copy_from_user(kml_fsdata->kml_buf, input.recbuf, input.reclen)) {
58                 EXIT;
59                 return -EFAULT;
60         }
61         kml_fsdata->kml_len = input.reclen;
62
63         decode_kmlrec (&kml_fsdata->kml_reint_cache,
64                         kml_fsdata->kml_buf, kml_fsdata->kml_len);
65
66         kml_fsdata->kml_reint_current = kml_fsdata->kml_reint_cache.next;
67         kml_fsdata->kml_reintpos = 0;
68         kml_fsdata->kml_count = 0;
69         return 0;
70 }
71
72 /* DO_KML_REINT  */
73 int do_kml_reint (struct file *file, unsigned long arg)
74 {
75         struct {
76                 char *volname;
77                 int   namelen;  
78                 char *path;
79                 int pathlen;
80                 int recno;
81                 int offset;
82                 int len;
83                 int generation;
84                 __u64 ino;
85         } input;
86         int error;
87         char   *path;
88         struct kml_rec *close_rec;
89         struct kml_fsdata *kml_fsdata;
90         struct presto_file_set *fset;
91
92         ENTRY;
93         if (copy_from_user(&input, (char *)arg, sizeof(input))) {
94                 EXIT;
95                 return -EFAULT;
96         }
97         PRESTO_ALLOC(path, char *, input.namelen + 1);
98         if ( !path ) {
99                 EXIT;
100                 return -ENOMEM;
101         }
102         if (copy_from_user(path, input.volname, input.namelen)) {
103                 PRESTO_FREE(path, input.namelen + 1);
104                 EXIT;
105                 return -EFAULT;
106         }
107         path[input.namelen] = '\0';
108         fset = kml_getfset (path);
109         PRESTO_FREE(path, input.namelen + 1);
110
111         kml_fsdata = FSET_GET_KMLDATA(fset);
112
113         error = kml_reintbuf(kml_fsdata, 
114                 fset->fset_mtpt->d_name.name, 
115                 &close_rec);
116
117         if (error == KML_CLOSE_BACKFETCH && close_rec != NULL) {
118                 struct kml_close *close = &close_rec->rec_kml.close;
119                 input.ino = close->ino;
120                 input.generation = close->generation;
121                 if (strlen (close->path) + 1 < input.pathlen) {
122                         strcpy (input.path, close->path);
123                         input.pathlen = strlen (close->path) + 1;
124                         input.recno = close_rec->rec_tail.recno;
125                         input.offset = close_rec->rec_kml_offset;
126                         input.len = close_rec->rec_size;
127                         input.generation = close->generation;
128                         input.ino = close->ino;
129                 }
130                 else {
131                         CDEBUG(D_KML, "KML_DO_REINT::no space to save:%d < %d",
132                                 strlen (close->path) + 1, input.pathlen);
133                         error = -ENOMEM;
134                 }
135                 if (copy_to_user((char *)arg, &input, sizeof (input)))
136                         return -EFAULT;
137         }
138         return error;
139 }
140
141 /* END_KML_REINT */
142 int end_kml_reint (struct file *file, unsigned long arg)
143 {
144         /* Free KML buffer and related volume info */
145         struct {
146                 char *volname;
147                 int   namelen;  
148 #if 0
149                 int   count; 
150                 int   newpos; 
151 #endif
152         } input;
153         struct presto_file_set *fset = NULL;
154         struct kml_fsdata *kml_fsdata = NULL;
155         int error;
156         char *path;
157
158         ENTRY;
159         if (copy_from_user(&input, (char *)arg, sizeof(input))) { 
160                EXIT;
161                return -EFAULT;
162         }
163
164         PRESTO_ALLOC(path, char *, input.namelen + 1);
165         if ( !path ) {
166                 EXIT;
167                 return -ENOMEM;
168         }
169         if (copy_from_user(path, input.volname, input.namelen)) {
170         if ( error ) {
171                 PRESTO_FREE(path, input.namelen + 1);
172                 EXIT;
173                 return -EFAULT;
174         }
175         path[input.namelen] = '\0';
176         fset = kml_getfset (path);
177         PRESTO_FREE(path, input.namelen + 1);
178
179         kml_fsdata = FSET_GET_KMLDATA(fset);
180         delete_kmlrec (&kml_fsdata->kml_reint_cache);
181
182         /* kml reint support */
183         kml_fsdata->kml_reint_current = NULL;
184         kml_fsdata->kml_len = 0;
185         kml_fsdata->kml_reintpos = 0;
186         kml_fsdata->kml_count = 0;
187 #if 0
188         input.newpos = kml_upc->newpos;
189         input.count = kml_upc->count;
190         if (copy_to_user((char *)arg, &input, sizeof (input)))
191                 return -EFAULT;
192 #endif
193         return error;
194 }