Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


hooking checkpoints into vmm execution
[palacios.git] / linux_module / iface-file.c
1 /* Palacios file interface 
2  * (c) Jack Lange, 2010
3  */
4
5
6 #include <linux/fs.h>
7 #include <linux/file.h>
8 #include <linux/spinlock.h>
9 #include <linux/uaccess.h>
10 #include <linux/module.h>
11
12 #include "palacios.h"
13 #include "linux-exts.h"
14
15 #include <interfaces/vmm_file.h>
16
17 static struct list_head global_files;
18
19
20 struct palacios_file {
21     struct file * filp;
22
23     char * path;
24     int mode;
25     
26     spinlock_t lock;
27
28     struct v3_guest * guest;
29     
30
31     struct list_head file_node;
32 };
33
34
35 // Currently this just holds the list of open files
36 struct vm_file_state {
37     struct list_head open_files;
38 };
39
40
41
42 static void * palacios_file_open(const char * path, int mode, void * private_data) {
43     struct v3_guest * guest = (struct v3_guest *)private_data;
44     struct palacios_file * pfile = NULL;        
45     struct vm_file_state * vm_state = NULL;
46
47     if (guest != NULL) {
48         vm_state = get_vm_ext_data(guest, "FILE_INTERFACE");
49         
50         if (vm_state == NULL) {
51             printk("ERROR: Could not locate vm file state for extension FILE_INTERFACE\n");
52             return NULL;
53         }
54     }
55     
56     pfile = kmalloc(sizeof(struct palacios_file), GFP_KERNEL);
57     memset(pfile, 0, sizeof(struct palacios_file));
58
59     if ((mode & FILE_OPEN_MODE_READ) && (mode & FILE_OPEN_MODE_WRITE)) { 
60         pfile->mode = O_RDWR;
61     } else if (mode & FILE_OPEN_MODE_READ) { 
62         pfile->mode = O_RDONLY;
63     } else if (mode & FILE_OPEN_MODE_WRITE) { 
64         pfile->mode = O_WRONLY;
65     } 
66     
67     if (mode & FILE_OPEN_MODE_CREATE) {
68         pfile->mode |= O_CREAT;
69     }
70
71
72     pfile->filp = filp_open(path, pfile->mode, 0);
73     
74     if (pfile->filp == NULL) {
75         printk("Cannot open file: %s\n", path);
76         return NULL;
77     }
78
79     pfile->path = kmalloc(strlen(path) + 1, GFP_KERNEL);
80     strncpy(pfile->path, path, strlen(path));
81     pfile->guest = guest;
82     
83     spin_lock_init(&(pfile->lock));
84
85     if (guest == NULL) {
86         list_add(&(pfile->file_node), &(global_files));
87     } else {
88         list_add(&(pfile->file_node), &(vm_state->open_files));
89     } 
90
91
92     return pfile;
93 }
94
95 static int palacios_file_close(void * file_ptr) {
96     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
97
98     filp_close(pfile->filp, NULL);
99     
100     list_del(&(pfile->file_node));
101
102     kfree(pfile->path);    
103     kfree(pfile);
104
105     return 0;
106 }
107
108 static long long palacios_file_size(void * file_ptr) {
109     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
110     struct file * filp = pfile->filp;
111     struct kstat s;
112     int ret;
113     
114     ret = vfs_getattr(filp->f_path.mnt, filp->f_path.dentry, &s);
115
116     if (ret != 0) {
117         printk("Failed to fstat file\n");
118         return -1;
119     }
120
121     return s.size;
122 }
123
124 static long long palacios_file_read(void * file_ptr, void * buffer, long long length, long long offset){
125     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
126     struct file * filp = pfile->filp;
127     ssize_t ret;
128     mm_segment_t old_fs;
129         
130     old_fs = get_fs();
131     set_fs(get_ds());
132         
133     ret = vfs_read(filp, buffer, length, &offset);
134         
135     set_fs(old_fs);
136         
137     if (ret <= 0) {
138         printk("sys_read of %p for %lld bytes failed\n", filp, length);         
139     }
140         
141     return ret;
142 }
143
144
145 static long long palacios_file_write(void * file_ptr, void * buffer, long long length, long long offset) {
146     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
147     struct file * filp = pfile->filp;
148     mm_segment_t old_fs;
149     ssize_t ret;
150
151     old_fs = get_fs();
152     set_fs(get_ds());
153
154     ret = vfs_write(filp, buffer, length, &offset);
155         
156     set_fs(old_fs);
157
158  
159     if (ret <= 0) {
160         printk("sys_write failed\n");           
161     }
162         
163     return ret;
164 }
165
166
167 static struct v3_file_hooks palacios_file_hooks = {
168         .open           = palacios_file_open,
169         .close          = palacios_file_close,
170         .read           = palacios_file_read,
171         .write          = palacios_file_write,
172         .size           = palacios_file_size,
173 };
174
175
176
177 static int file_init( void ) {
178     INIT_LIST_HEAD(&(global_files));
179
180     V3_Init_File(&palacios_file_hooks);
181
182     return 0;
183 }
184
185
186 static int file_deinit( void ) {
187     if (!list_empty(&(global_files))) {
188         printk("Error removing module with open files\n");
189     }
190
191     return 0;
192 }
193
194 static int guest_file_init(struct v3_guest * guest, void ** vm_data) {
195     struct vm_file_state * state = kmalloc(sizeof(struct vm_file_state), GFP_KERNEL);
196     
197     INIT_LIST_HEAD(&(state->open_files));
198
199     *vm_data = state;
200
201     return 0;
202 }
203
204
205 static int guest_file_deinit(struct v3_guest * guest, void * vm_data) {
206     
207     return 0;
208 }
209
210
211 static struct linux_ext file_ext = {
212     .name = "FILE_INTERFACE",
213     .init = file_init, 
214     .deinit = file_deinit,
215     .guest_init = guest_file_init,
216     .guest_deinit = guest_file_deinit
217 };
218
219
220 register_extension(&file_ext);