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.


396183bb98bb5749faba30b54182f0de6b90f73d
[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     pfile->filp = filp_open(path, pfile->mode, 0);
68     
69     if (pfile->filp == NULL) {
70         printk("Cannot open file: %s\n", path);
71         return NULL;
72     }
73
74     pfile->path = kmalloc(strlen(path) + 1, GFP_KERNEL);
75     strncpy(pfile->path, path, strlen(path));
76     pfile->guest = guest;
77     
78     spin_lock_init(&(pfile->lock));
79
80     if (guest == NULL) {
81         list_add(&(pfile->file_node), &(global_files));
82     } else {
83         list_add(&(pfile->file_node), &(vm_state->open_files));
84     } 
85
86
87     return pfile;
88 }
89
90 static int palacios_file_close(void * file_ptr) {
91     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
92
93     filp_close(pfile->filp, NULL);
94     
95     list_del(&(pfile->file_node));
96
97     kfree(pfile->path);    
98     kfree(pfile);
99
100     return 0;
101 }
102
103 static long long palacios_file_size(void * file_ptr) {
104     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
105     struct file * filp = pfile->filp;
106     struct kstat s;
107     int ret;
108     
109     ret = vfs_getattr(filp->f_path.mnt, filp->f_path.dentry, &s);
110
111     if (ret != 0) {
112         printk("Failed to fstat file\n");
113         return -1;
114     }
115
116     return s.size;
117 }
118
119 static long long palacios_file_read(void * file_ptr, void * buffer, long long length, long long offset){
120     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
121     struct file * filp = pfile->filp;
122     ssize_t ret;
123     mm_segment_t old_fs;
124         
125     old_fs = get_fs();
126     set_fs(get_ds());
127         
128     ret = vfs_read(filp, buffer, length, &offset);
129         
130     set_fs(old_fs);
131         
132     if (ret <= 0) {
133         printk("sys_read of %p for %lld bytes failed\n", filp, length);         
134     }
135         
136     return ret;
137 }
138
139
140 static long long palacios_file_write(void * file_ptr, void * buffer, long long length, long long offset) {
141     struct palacios_file * pfile = (struct palacios_file *)file_ptr;
142     struct file * filp = pfile->filp;
143     mm_segment_t old_fs;
144     ssize_t ret;
145
146     old_fs = get_fs();
147     set_fs(get_ds());
148
149     ret = vfs_write(filp, buffer, length, &offset);
150         
151     set_fs(old_fs);
152
153  
154     if (ret <= 0) {
155         printk("sys_write failed\n");           
156     }
157         
158     return ret;
159 }
160
161
162 static struct v3_file_hooks palacios_file_hooks = {
163         .open           = palacios_file_open,
164         .close          = palacios_file_close,
165         .read           = palacios_file_read,
166         .write          = palacios_file_write,
167         .size           = palacios_file_size,
168 };
169
170
171
172 static int file_init( void ) {
173     INIT_LIST_HEAD(&(global_files));
174
175     V3_Init_File(&palacios_file_hooks);
176
177     return 0;
178 }
179
180
181 static int file_deinit( void ) {
182     if (!list_empty(&(global_files))) {
183         printk("Error removing module with open files\n");
184     }
185
186     return 0;
187 }
188
189 static int guest_file_init(struct v3_guest * guest, void ** vm_data) {
190     struct vm_file_state * state = kmalloc(sizeof(struct vm_file_state), GFP_KERNEL);
191     
192     INIT_LIST_HEAD(&(state->open_files));
193
194     *vm_data = state;
195
196     return 0;
197 }
198
199
200 static int guest_file_deinit(struct v3_guest * guest, void * vm_data) {
201     
202     return 0;
203 }
204
205
206 static struct linux_ext file_ext = {
207     .name = "FILE_INTERFACE",
208     .init = file_init, 
209     .deinit = file_deinit,
210     .guest_init = guest_file_init,
211     .guest_deinit = guest_file_deinit
212 };
213
214
215 register_extension(&file_ext);