Blame view
fs/hppfs/hppfs.c
16.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
1dd0dd111 hppfs pass vfsmou... |
2 |
* Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
1da177e4c Linux-2.6.12-rc2 |
3 4 |
* Licensed under the GPL */ |
1dd0dd111 hppfs pass vfsmou... |
5 6 |
#include <linux/ctype.h> #include <linux/dcache.h> |
3f580470b [PATCH] uml: rest... |
7 |
#include <linux/file.h> |
1dd0dd111 hppfs pass vfsmou... |
8 |
#include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
9 |
#include <linux/init.h> |
1da177e4c Linux-2.6.12-rc2 |
10 |
#include <linux/kernel.h> |
1dd0dd111 hppfs pass vfsmou... |
11 12 13 14 |
#include <linux/list.h> #include <linux/module.h> #include <linux/mount.h> #include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/statfs.h> |
1dd0dd111 hppfs pass vfsmou... |
16 |
#include <linux/types.h> |
918377b69 missing include i... |
17 |
#include <linux/pid_namespace.h> |
d6b722aa3 hppfs: missing in... |
18 |
#include <linux/namei.h> |
1da177e4c Linux-2.6.12-rc2 |
19 |
#include <asm/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
20 |
#include "os.h" |
f382d6e63 [PATCH] sanitize ... |
21 |
static struct inode *get_inode(struct super_block *, struct dentry *); |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
struct hppfs_data { struct list_head list; char contents[PAGE_SIZE - sizeof(struct list_head)]; }; struct hppfs_private { struct file *proc_file; int host_fd; loff_t len; struct hppfs_data *contents; }; struct hppfs_inode_info { |
a0612b1f0 uml: hppfs fixes |
36 |
struct dentry *proc_dentry; |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 40 41 |
struct inode vfs_inode; }; static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) { |
fd589e0b6 [PATCH] hppfs: fi... |
42 |
return container_of(inode, struct hppfs_inode_info, vfs_inode); |
1da177e4c Linux-2.6.12-rc2 |
43 44 45 |
} #define HPPFS_SUPER_MAGIC 0xb00000ee |
ee9b6d61a [PATCH] Mark stru... |
46 |
static const struct super_operations hppfs_sbops; |
1da177e4c Linux-2.6.12-rc2 |
47 48 49 50 51 52 53 |
static int is_pid(struct dentry *dentry) { struct super_block *sb; int i; sb = dentry->d_sb; |
a0612b1f0 uml: hppfs fixes |
54 |
if (dentry->d_parent != sb->s_root) |
1dd0dd111 hppfs pass vfsmou... |
55 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
56 |
|
1dd0dd111 hppfs pass vfsmou... |
57 58 59 |
for (i = 0; i < dentry->d_name.len; i++) { if (!isdigit(dentry->d_name.name[i])) return 0; |
1da177e4c Linux-2.6.12-rc2 |
60 |
} |
1dd0dd111 hppfs pass vfsmou... |
61 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
62 63 64 65 66 67 68 69 70 71 72 |
} static char *dentry_name(struct dentry *dentry, int extra) { struct dentry *parent; char *root, *name; const char *seg_name; int len, seg_len; len = 0; parent = dentry; |
1dd0dd111 hppfs pass vfsmou... |
73 74 |
while (parent->d_parent != parent) { if (is_pid(parent)) |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 78 79 80 81 82 |
len += strlen("pid") + 1; else len += parent->d_name.len + 1; parent = parent->d_parent; } root = "proc"; len += strlen(root); name = kmalloc(len + extra + 1, GFP_KERNEL); |
1dd0dd111 hppfs pass vfsmou... |
83 84 |
if (name == NULL) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
85 86 87 |
name[len] = '\0'; parent = dentry; |
1dd0dd111 hppfs pass vfsmou... |
88 89 |
while (parent->d_parent != parent) { if (is_pid(parent)) { |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
seg_name = "pid"; seg_len = strlen("pid"); } else { seg_name = parent->d_name.name; seg_len = parent->d_name.len; } len -= seg_len + 1; name[len] = '/'; strncpy(&name[len + 1], seg_name, seg_len); parent = parent->d_parent; } strncpy(name, root, strlen(root)); |
1dd0dd111 hppfs pass vfsmou... |
104 |
return name; |
1da177e4c Linux-2.6.12-rc2 |
105 |
} |
1da177e4c Linux-2.6.12-rc2 |
106 107 108 109 110 111 |
static int file_removed(struct dentry *dentry, const char *file) { char *host_file; int extra, fd; extra = 0; |
1dd0dd111 hppfs pass vfsmou... |
112 113 |
if (file != NULL) extra += strlen(file) + 1; |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
host_file = dentry_name(dentry, extra + strlen("/remove")); |
1dd0dd111 hppfs pass vfsmou... |
116 117 118 119 |
if (host_file == NULL) { printk(KERN_ERR "file_removed : allocation failed "); return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
120 |
} |
1dd0dd111 hppfs pass vfsmou... |
121 |
if (file != NULL) { |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 127 128 |
strcat(host_file, "/"); strcat(host_file, file); } strcat(host_file, "/remove"); fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); kfree(host_file); |
1dd0dd111 hppfs pass vfsmou... |
129 |
if (fd > 0) { |
1da177e4c Linux-2.6.12-rc2 |
130 |
os_close_file(fd); |
1dd0dd111 hppfs pass vfsmou... |
131 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
132 |
} |
1dd0dd111 hppfs pass vfsmou... |
133 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
134 |
} |
1da177e4c Linux-2.6.12-rc2 |
135 |
static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, |
a0612b1f0 uml: hppfs fixes |
136 |
struct nameidata *nd) |
1da177e4c Linux-2.6.12-rc2 |
137 |
{ |
0916a5e45 hppfs_lookup(): d... |
138 139 |
struct dentry *proc_dentry, *parent; struct qstr *name = &dentry->d_name; |
1da177e4c Linux-2.6.12-rc2 |
140 141 142 143 |
struct inode *inode; int err, deleted; deleted = file_removed(dentry, NULL); |
1dd0dd111 hppfs pass vfsmou... |
144 145 146 147 |
if (deleted < 0) return ERR_PTR(deleted); else if (deleted) return ERR_PTR(-ENOENT); |
1da177e4c Linux-2.6.12-rc2 |
148 |
|
1da177e4c Linux-2.6.12-rc2 |
149 |
parent = HPPFS_I(ino)->proc_dentry; |
1b1dcc1b5 [PATCH] mutex sub... |
150 |
mutex_lock(&parent->d_inode->i_mutex); |
0916a5e45 hppfs_lookup(): d... |
151 |
proc_dentry = lookup_one_len(name->name, parent, name->len); |
1b1dcc1b5 [PATCH] mutex sub... |
152 |
mutex_unlock(&parent->d_inode->i_mutex); |
1da177e4c Linux-2.6.12-rc2 |
153 |
|
1dd0dd111 hppfs pass vfsmou... |
154 155 |
if (IS_ERR(proc_dentry)) return proc_dentry; |
1da177e4c Linux-2.6.12-rc2 |
156 |
|
f382d6e63 [PATCH] sanitize ... |
157 158 159 |
err = -ENOMEM; inode = get_inode(ino->i_sb, proc_dentry); if (!inode) |
3cc0658e3 hppfs: fix dentry... |
160 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
161 162 |
d_add(dentry, inode); |
1dd0dd111 hppfs pass vfsmou... |
163 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
164 |
|
1da177e4c Linux-2.6.12-rc2 |
165 |
out: |
1dd0dd111 hppfs pass vfsmou... |
166 |
return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
167 |
} |
92e1d5be9 [PATCH] mark stru... |
168 |
static const struct inode_operations hppfs_file_iops = { |
1da177e4c Linux-2.6.12-rc2 |
169 |
}; |
347f217ce [PATCH] uml: __us... |
170 |
static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, |
1da177e4c Linux-2.6.12-rc2 |
171 172 |
loff_t *ppos, int is_user) { |
347f217ce [PATCH] uml: __us... |
173 |
ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); |
1da177e4c Linux-2.6.12-rc2 |
174 |
ssize_t n; |
471b17e7e [PATCH] struct pa... |
175 |
read = file->f_path.dentry->d_inode->i_fop->read; |
1da177e4c Linux-2.6.12-rc2 |
176 |
|
1dd0dd111 hppfs pass vfsmou... |
177 |
if (!is_user) |
1da177e4c Linux-2.6.12-rc2 |
178 179 180 |
set_fs(KERNEL_DS); n = (*read)(file, buf, count, &file->f_pos); |
1dd0dd111 hppfs pass vfsmou... |
181 |
if (!is_user) |
1da177e4c Linux-2.6.12-rc2 |
182 |
set_fs(USER_DS); |
1dd0dd111 hppfs pass vfsmou... |
183 184 |
if (ppos) *ppos = file->f_pos; |
8e0a21812 [PATCH] uml: fix ... |
185 |
return n; |
1da177e4c Linux-2.6.12-rc2 |
186 |
} |
347f217ce [PATCH] uml: __us... |
187 |
static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count) |
1da177e4c Linux-2.6.12-rc2 |
188 189 190 191 192 193 194 |
{ ssize_t n; int cur, err; char *new_buf; n = -ENOMEM; new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); |
1dd0dd111 hppfs pass vfsmou... |
195 196 197 |
if (new_buf == NULL) { printk(KERN_ERR "hppfs_read_file : kmalloc failed "); |
1da177e4c Linux-2.6.12-rc2 |
198 199 200 |
goto out; } n = 0; |
1dd0dd111 hppfs pass vfsmou... |
201 |
while (count > 0) { |
1da177e4c Linux-2.6.12-rc2 |
202 203 |
cur = min_t(ssize_t, count, PAGE_SIZE); err = os_read_file(fd, new_buf, cur); |
1dd0dd111 hppfs pass vfsmou... |
204 205 206 207 |
if (err < 0) { printk(KERN_ERR "hppfs_read : read failed, " "errno = %d ", err); |
1da177e4c Linux-2.6.12-rc2 |
208 209 |
n = err; goto out_free; |
1dd0dd111 hppfs pass vfsmou... |
210 |
} else if (err == 0) |
1da177e4c Linux-2.6.12-rc2 |
211 |
break; |
1dd0dd111 hppfs pass vfsmou... |
212 |
if (copy_to_user(buf, new_buf, err)) { |
1da177e4c Linux-2.6.12-rc2 |
213 214 215 216 217 218 219 220 221 |
n = -EFAULT; goto out_free; } n += err; count -= err; } out_free: kfree(new_buf); out: |
8e0a21812 [PATCH] uml: fix ... |
222 |
return n; |
1da177e4c Linux-2.6.12-rc2 |
223 |
} |
347f217ce [PATCH] uml: __us... |
224 |
static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 228 229 230 |
loff_t *ppos) { struct hppfs_private *hppfs = file->private_data; struct hppfs_data *data; loff_t off; int err; |
1dd0dd111 hppfs pass vfsmou... |
231 |
if (hppfs->contents != NULL) { |
a0612b1f0 uml: hppfs fixes |
232 |
int rem; |
1dd0dd111 hppfs pass vfsmou... |
233 234 |
if (*ppos >= hppfs->len) return 0; |
1da177e4c Linux-2.6.12-rc2 |
235 236 237 |
data = hppfs->contents; off = *ppos; |
1dd0dd111 hppfs pass vfsmou... |
238 |
while (off >= sizeof(data->contents)) { |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 242 |
data = list_entry(data->list.next, struct hppfs_data, list); off -= sizeof(data->contents); } |
1dd0dd111 hppfs pass vfsmou... |
243 |
if (off + count > hppfs->len) |
1da177e4c Linux-2.6.12-rc2 |
244 |
count = hppfs->len - off; |
a0612b1f0 uml: hppfs fixes |
245 246 247 248 |
rem = copy_to_user(buf, &data->contents[off], count); *ppos += count - rem; if (rem > 0) return -EFAULT; |
1dd0dd111 hppfs pass vfsmou... |
249 |
} else if (hppfs->host_fd != -1) { |
1da177e4c Linux-2.6.12-rc2 |
250 |
err = os_seek_file(hppfs->host_fd, *ppos); |
1dd0dd111 hppfs pass vfsmou... |
251 252 253 254 255 |
if (err) { printk(KERN_ERR "hppfs_read : seek failed, " "errno = %d ", err); return err; |
1da177e4c Linux-2.6.12-rc2 |
256 |
} |
880fe76ee hppfs: hppfs_read... |
257 258 259 260 261 262 263 |
err = hppfs_read_file(hppfs->host_fd, buf, count); if (err < 0) { printk(KERN_ERR "hppfs_read: read failed: %d ", err); return err; } count = err; |
1dd0dd111 hppfs pass vfsmou... |
264 |
if (count > 0) |
1da177e4c Linux-2.6.12-rc2 |
265 266 267 |
*ppos += count; } else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); |
1dd0dd111 hppfs pass vfsmou... |
268 |
return count; |
1da177e4c Linux-2.6.12-rc2 |
269 |
} |
a0612b1f0 uml: hppfs fixes |
270 271 |
static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 |
{ struct hppfs_private *data = file->private_data; struct file *proc_file = data->proc_file; |
347f217ce [PATCH] uml: __us... |
275 |
ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); |
1da177e4c Linux-2.6.12-rc2 |
276 |
|
471b17e7e [PATCH] struct pa... |
277 |
write = proc_file->f_path.dentry->d_inode->i_fop->write; |
a0612b1f0 uml: hppfs fixes |
278 |
return (*write)(proc_file, buf, len, ppos); |
1da177e4c Linux-2.6.12-rc2 |
279 280 281 282 283 284 285 286 287 288 289 |
} static int open_host_sock(char *host_file, int *filter_out) { char *end; int fd; end = &host_file[strlen(host_file)]; strcpy(end, "/rw"); *filter_out = 1; fd = os_connect_socket(host_file); |
1dd0dd111 hppfs pass vfsmou... |
290 291 |
if (fd > 0) return fd; |
1da177e4c Linux-2.6.12-rc2 |
292 293 294 295 |
strcpy(end, "/r"); *filter_out = 0; fd = os_connect_socket(host_file); |
1dd0dd111 hppfs pass vfsmou... |
296 |
return fd; |
1da177e4c Linux-2.6.12-rc2 |
297 298 299 300 301 302 |
} static void free_contents(struct hppfs_data *head) { struct hppfs_data *data; struct list_head *ele, *next; |
1dd0dd111 hppfs pass vfsmou... |
303 304 |
if (head == NULL) return; |
1da177e4c Linux-2.6.12-rc2 |
305 |
|
1dd0dd111 hppfs pass vfsmou... |
306 |
list_for_each_safe(ele, next, &head->list) { |
1da177e4c Linux-2.6.12-rc2 |
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
data = list_entry(ele, struct hppfs_data, list); kfree(data); } kfree(head); } static struct hppfs_data *hppfs_get_data(int fd, int filter, struct file *proc_file, struct file *hppfs_file, loff_t *size_out) { struct hppfs_data *data, *new, *head; int n, err; err = -ENOMEM; data = kmalloc(sizeof(*data), GFP_KERNEL); |
1dd0dd111 hppfs pass vfsmou... |
323 324 325 |
if (data == NULL) { printk(KERN_ERR "hppfs_get_data : head allocation failed "); |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 329 330 331 332 |
goto failed; } INIT_LIST_HEAD(&data->list); head = data; *size_out = 0; |
1dd0dd111 hppfs pass vfsmou... |
333 334 |
if (filter) { while ((n = read_proc(proc_file, data->contents, |
a0612b1f0 uml: hppfs fixes |
335 |
sizeof(data->contents), NULL, 0)) > 0) |
1da177e4c Linux-2.6.12-rc2 |
336 337 |
os_write_file(fd, data->contents, n); err = os_shutdown_socket(fd, 0, 1); |
1dd0dd111 hppfs pass vfsmou... |
338 339 |
if (err) { printk(KERN_ERR "hppfs_get_data : failed to shut down " |
1da177e4c Linux-2.6.12-rc2 |
340 341 342 343 344 |
"socket "); goto failed_free; } } |
1dd0dd111 hppfs pass vfsmou... |
345 |
while (1) { |
1da177e4c Linux-2.6.12-rc2 |
346 |
n = os_read_file(fd, data->contents, sizeof(data->contents)); |
1dd0dd111 hppfs pass vfsmou... |
347 |
if (n < 0) { |
1da177e4c Linux-2.6.12-rc2 |
348 |
err = n; |
1dd0dd111 hppfs pass vfsmou... |
349 350 351 |
printk(KERN_ERR "hppfs_get_data : read failed, " "errno = %d ", err); |
1da177e4c Linux-2.6.12-rc2 |
352 |
goto failed_free; |
1dd0dd111 hppfs pass vfsmou... |
353 |
} else if (n == 0) |
1da177e4c Linux-2.6.12-rc2 |
354 355 356 |
break; *size_out += n; |
1dd0dd111 hppfs pass vfsmou... |
357 |
if (n < sizeof(data->contents)) |
1da177e4c Linux-2.6.12-rc2 |
358 359 360 |
break; new = kmalloc(sizeof(*data), GFP_KERNEL); |
1dd0dd111 hppfs pass vfsmou... |
361 362 363 364 |
if (new == 0) { printk(KERN_ERR "hppfs_get_data : data allocation " "failed "); |
1da177e4c Linux-2.6.12-rc2 |
365 366 367 368 369 370 371 372 |
err = -ENOMEM; goto failed_free; } INIT_LIST_HEAD(&new->list); list_add(&new->list, &data->list); data = new; } |
1dd0dd111 hppfs pass vfsmou... |
373 |
return head; |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 377 |
failed_free: free_contents(head); failed: |
1dd0dd111 hppfs pass vfsmou... |
378 |
return ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
379 380 381 382 383 384 385 |
} static struct hppfs_private *hppfs_data(void) { struct hppfs_private *data; data = kmalloc(sizeof(*data), GFP_KERNEL); |
1dd0dd111 hppfs pass vfsmou... |
386 387 |
if (data == NULL) return data; |
1da177e4c Linux-2.6.12-rc2 |
388 389 390 391 |
*data = ((struct hppfs_private ) { .host_fd = -1, .len = -1, .contents = NULL } ); |
1dd0dd111 hppfs pass vfsmou... |
392 |
return data; |
1da177e4c Linux-2.6.12-rc2 |
393 394 395 396 |
} static int file_mode(int fmode) { |
1dd0dd111 hppfs pass vfsmou... |
397 398 399 400 401 402 403 |
if (fmode == (FMODE_READ | FMODE_WRITE)) return O_RDWR; if (fmode == FMODE_READ) return O_RDONLY; if (fmode == FMODE_WRITE) return O_WRONLY; return 0; |
1da177e4c Linux-2.6.12-rc2 |
404 405 406 407 |
} static int hppfs_open(struct inode *inode, struct file *file) { |
d76b0d9b2 CRED: Use creds i... |
408 |
const struct cred *cred = file->f_cred; |
1da177e4c Linux-2.6.12-rc2 |
409 |
struct hppfs_private *data; |
1dd0dd111 hppfs pass vfsmou... |
410 |
struct vfsmount *proc_mnt; |
a0612b1f0 uml: hppfs fixes |
411 |
struct dentry *proc_dentry; |
1da177e4c Linux-2.6.12-rc2 |
412 413 414 415 416 |
char *host_file; int err, fd, type, filter; err = -ENOMEM; data = hppfs_data(); |
1dd0dd111 hppfs pass vfsmou... |
417 |
if (data == NULL) |
1da177e4c Linux-2.6.12-rc2 |
418 |
goto out; |
471b17e7e [PATCH] struct pa... |
419 |
host_file = dentry_name(file->f_path.dentry, strlen("/rw")); |
1dd0dd111 hppfs pass vfsmou... |
420 |
if (host_file == NULL) |
1da177e4c Linux-2.6.12-rc2 |
421 422 423 |
goto out_free2; proc_dentry = HPPFS_I(inode)->proc_dentry; |
f382d6e63 [PATCH] sanitize ... |
424 |
proc_mnt = inode->i_sb->s_fs_info; |
1da177e4c Linux-2.6.12-rc2 |
425 426 |
/* XXX This isn't closed anywhere */ |
1dd0dd111 hppfs pass vfsmou... |
427 |
data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), |
745ca2475 CRED: Pass creden... |
428 |
file_mode(file->f_mode), cred); |
1da177e4c Linux-2.6.12-rc2 |
429 |
err = PTR_ERR(data->proc_file); |
1dd0dd111 hppfs pass vfsmou... |
430 |
if (IS_ERR(data->proc_file)) |
1da177e4c Linux-2.6.12-rc2 |
431 432 433 |
goto out_free1; type = os_file_type(host_file); |
1dd0dd111 hppfs pass vfsmou... |
434 |
if (type == OS_TYPE_FILE) { |
1da177e4c Linux-2.6.12-rc2 |
435 |
fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); |
1dd0dd111 hppfs pass vfsmou... |
436 |
if (fd >= 0) |
1da177e4c Linux-2.6.12-rc2 |
437 |
data->host_fd = fd; |
1dd0dd111 hppfs pass vfsmou... |
438 439 440 441 |
else printk(KERN_ERR "hppfs_open : failed to open '%s', " "errno = %d ", host_file, -fd); |
1da177e4c Linux-2.6.12-rc2 |
442 443 |
data->contents = NULL; |
1dd0dd111 hppfs pass vfsmou... |
444 |
} else if (type == OS_TYPE_DIR) { |
1da177e4c Linux-2.6.12-rc2 |
445 |
fd = open_host_sock(host_file, &filter); |
1dd0dd111 hppfs pass vfsmou... |
446 |
if (fd > 0) { |
1da177e4c Linux-2.6.12-rc2 |
447 |
data->contents = hppfs_get_data(fd, filter, |
3f580470b [PATCH] uml: rest... |
448 |
data->proc_file, |
1da177e4c Linux-2.6.12-rc2 |
449 |
file, &data->len); |
1dd0dd111 hppfs pass vfsmou... |
450 |
if (!IS_ERR(data->contents)) |
1da177e4c Linux-2.6.12-rc2 |
451 |
data->host_fd = fd; |
1dd0dd111 hppfs pass vfsmou... |
452 453 454 455 |
} else printk(KERN_ERR "hppfs_open : failed to open a socket " "in '%s', errno = %d ", host_file, -fd); |
1da177e4c Linux-2.6.12-rc2 |
456 457 458 459 |
} kfree(host_file); file->private_data = data; |
1dd0dd111 hppfs pass vfsmou... |
460 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
461 462 463 464 465 466 467 |
out_free1: kfree(host_file); out_free2: free_contents(data->contents); kfree(data); out: |
1dd0dd111 hppfs pass vfsmou... |
468 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
469 470 471 472 |
} static int hppfs_dir_open(struct inode *inode, struct file *file) { |
d76b0d9b2 CRED: Use creds i... |
473 |
const struct cred *cred = file->f_cred; |
1da177e4c Linux-2.6.12-rc2 |
474 |
struct hppfs_private *data; |
1dd0dd111 hppfs pass vfsmou... |
475 |
struct vfsmount *proc_mnt; |
a0612b1f0 uml: hppfs fixes |
476 |
struct dentry *proc_dentry; |
1da177e4c Linux-2.6.12-rc2 |
477 478 479 480 |
int err; err = -ENOMEM; data = hppfs_data(); |
1dd0dd111 hppfs pass vfsmou... |
481 |
if (data == NULL) |
1da177e4c Linux-2.6.12-rc2 |
482 483 484 |
goto out; proc_dentry = HPPFS_I(inode)->proc_dentry; |
f382d6e63 [PATCH] sanitize ... |
485 |
proc_mnt = inode->i_sb->s_fs_info; |
1dd0dd111 hppfs pass vfsmou... |
486 |
data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), |
745ca2475 CRED: Pass creden... |
487 |
file_mode(file->f_mode), cred); |
1da177e4c Linux-2.6.12-rc2 |
488 |
err = PTR_ERR(data->proc_file); |
1dd0dd111 hppfs pass vfsmou... |
489 |
if (IS_ERR(data->proc_file)) |
1da177e4c Linux-2.6.12-rc2 |
490 491 492 |
goto out_free; file->private_data = data; |
1dd0dd111 hppfs pass vfsmou... |
493 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
494 495 496 497 |
out_free: kfree(data); out: |
1dd0dd111 hppfs pass vfsmou... |
498 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
499 500 501 502 503 |
} static loff_t hppfs_llseek(struct file *file, loff_t off, int where) { struct hppfs_private *data = file->private_data; |
3f580470b [PATCH] uml: rest... |
504 |
struct file *proc_file = data->proc_file; |
1da177e4c Linux-2.6.12-rc2 |
505 506 |
loff_t (*llseek)(struct file *, loff_t, int); loff_t ret; |
471b17e7e [PATCH] struct pa... |
507 |
llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; |
1dd0dd111 hppfs pass vfsmou... |
508 |
if (llseek != NULL) { |
1da177e4c Linux-2.6.12-rc2 |
509 |
ret = (*llseek)(proc_file, off, where); |
1dd0dd111 hppfs pass vfsmou... |
510 511 |
if (ret < 0) return ret; |
1da177e4c Linux-2.6.12-rc2 |
512 |
} |
1dd0dd111 hppfs pass vfsmou... |
513 |
return default_llseek(file, off, where); |
1da177e4c Linux-2.6.12-rc2 |
514 |
} |
4b6f5d20b [PATCH] Make most... |
515 |
static const struct file_operations hppfs_file_fops = { |
1da177e4c Linux-2.6.12-rc2 |
516 517 518 519 520 521 522 523 524 525 526 527 528 529 |
.owner = NULL, .llseek = hppfs_llseek, .read = hppfs_read, .write = hppfs_write, .open = hppfs_open, }; struct hppfs_dirent { void *vfs_dirent; filldir_t filldir; struct dentry *dentry; }; static int hppfs_filldir(void *d, const char *name, int size, |
c8adf94a4 [PATCH] hppfs: re... |
530 |
loff_t offset, u64 inode, unsigned int type) |
1da177e4c Linux-2.6.12-rc2 |
531 532 |
{ struct hppfs_dirent *dirent = d; |
1dd0dd111 hppfs pass vfsmou... |
533 534 |
if (file_removed(dirent->dentry, name)) return 0; |
1da177e4c Linux-2.6.12-rc2 |
535 |
|
1dd0dd111 hppfs pass vfsmou... |
536 537 |
return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, inode, type); |
1da177e4c Linux-2.6.12-rc2 |
538 539 540 541 542 |
} static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) { struct hppfs_private *data = file->private_data; |
3f580470b [PATCH] uml: rest... |
543 |
struct file *proc_file = data->proc_file; |
1da177e4c Linux-2.6.12-rc2 |
544 545 546 547 |
int (*readdir)(struct file *, void *, filldir_t); struct hppfs_dirent dirent = ((struct hppfs_dirent) { .vfs_dirent = ent, .filldir = filldir, |
1dd0dd111 hppfs pass vfsmou... |
548 549 |
.dentry = file->f_path.dentry }); |
1da177e4c Linux-2.6.12-rc2 |
550 |
int err; |
471b17e7e [PATCH] struct pa... |
551 |
readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; |
1da177e4c Linux-2.6.12-rc2 |
552 553 554 555 |
proc_file->f_pos = file->f_pos; err = (*readdir)(proc_file, &dirent, hppfs_filldir); file->f_pos = proc_file->f_pos; |
1dd0dd111 hppfs pass vfsmou... |
556 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
557 |
} |
02c24a821 fs: push i_mutex ... |
558 559 |
static int hppfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
1da177e4c Linux-2.6.12-rc2 |
560 |
{ |
02c24a821 fs: push i_mutex ... |
561 |
return filemap_write_and_wait_range(file->f_mapping, start, end); |
1da177e4c Linux-2.6.12-rc2 |
562 |
} |
4b6f5d20b [PATCH] Make most... |
563 |
static const struct file_operations hppfs_dir_fops = { |
1da177e4c Linux-2.6.12-rc2 |
564 565 566 567 |
.owner = NULL, .readdir = hppfs_readdir, .open = hppfs_dir_open, .fsync = hppfs_fsync, |
6038f373a llseek: automatic... |
568 |
.llseek = default_llseek, |
1da177e4c Linux-2.6.12-rc2 |
569 |
}; |
726c33422 [PATCH] VFS: Perm... |
570 |
static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) |
1da177e4c Linux-2.6.12-rc2 |
571 572 573 574 575 576 577 |
{ sf->f_blocks = 0; sf->f_bfree = 0; sf->f_bavail = 0; sf->f_files = 0; sf->f_ffree = 0; sf->f_type = HPPFS_SUPER_MAGIC; |
1dd0dd111 hppfs pass vfsmou... |
578 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
579 580 581 582 583 584 585 |
} static struct inode *hppfs_alloc_inode(struct super_block *sb) { struct hppfs_inode_info *hi; hi = kmalloc(sizeof(*hi), GFP_KERNEL); |
1dd0dd111 hppfs pass vfsmou... |
586 587 |
if (!hi) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
588 |
|
1dd0dd111 hppfs pass vfsmou... |
589 |
hi->proc_dentry = NULL; |
1da177e4c Linux-2.6.12-rc2 |
590 |
inode_init_once(&hi->vfs_inode); |
1dd0dd111 hppfs pass vfsmou... |
591 |
return &hi->vfs_inode; |
1da177e4c Linux-2.6.12-rc2 |
592 |
} |
33b0daaa5 switch hppfs to -... |
593 |
void hppfs_evict_inode(struct inode *ino) |
1da177e4c Linux-2.6.12-rc2 |
594 |
{ |
33b0daaa5 switch hppfs to -... |
595 |
end_writeback(ino); |
a0612b1f0 uml: hppfs fixes |
596 597 |
dput(HPPFS_I(ino)->proc_dentry); mntput(ino->i_sb->s_fs_info); |
1da177e4c Linux-2.6.12-rc2 |
598 |
} |
fa0d7e3de fs: icache RCU fr... |
599 |
static void hppfs_i_callback(struct rcu_head *head) |
1da177e4c Linux-2.6.12-rc2 |
600 |
{ |
fa0d7e3de fs: icache RCU fr... |
601 |
struct inode *inode = container_of(head, struct inode, i_rcu); |
1da177e4c Linux-2.6.12-rc2 |
602 603 |
kfree(HPPFS_I(inode)); } |
fa0d7e3de fs: icache RCU fr... |
604 605 606 607 |
static void hppfs_destroy_inode(struct inode *inode) { call_rcu(&inode->i_rcu, hppfs_i_callback); } |
ee9b6d61a [PATCH] Mark stru... |
608 |
static const struct super_operations hppfs_sbops = { |
1da177e4c Linux-2.6.12-rc2 |
609 610 |
.alloc_inode = hppfs_alloc_inode, .destroy_inode = hppfs_destroy_inode, |
33b0daaa5 switch hppfs to -... |
611 |
.evict_inode = hppfs_evict_inode, |
1da177e4c Linux-2.6.12-rc2 |
612 613 |
.statfs = hppfs_statfs, }; |
1dd0dd111 hppfs pass vfsmou... |
614 615 |
static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
1da177e4c Linux-2.6.12-rc2 |
616 |
{ |
7b264fc2b hppfs: handle ->p... |
617 |
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; |
a0612b1f0 uml: hppfs fixes |
618 619 |
return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, buflen); |
1da177e4c Linux-2.6.12-rc2 |
620 |
} |
a0612b1f0 uml: hppfs fixes |
621 |
static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) |
1da177e4c Linux-2.6.12-rc2 |
622 |
{ |
7b264fc2b hppfs: handle ->p... |
623 |
struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; |
1da177e4c Linux-2.6.12-rc2 |
624 |
|
a0612b1f0 uml: hppfs fixes |
625 626 |
return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); } |
1da177e4c Linux-2.6.12-rc2 |
627 |
|
7b264fc2b hppfs: handle ->p... |
628 629 630 631 632 633 634 635 |
static void hppfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) { struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; if (proc_dentry->d_inode->i_op->put_link) proc_dentry->d_inode->i_op->put_link(proc_dentry, nd, cookie); } |
92e1d5be9 [PATCH] mark stru... |
636 |
static const struct inode_operations hppfs_dir_iops = { |
1da177e4c Linux-2.6.12-rc2 |
637 638 |
.lookup = hppfs_lookup, }; |
92e1d5be9 [PATCH] mark stru... |
639 |
static const struct inode_operations hppfs_link_iops = { |
1da177e4c Linux-2.6.12-rc2 |
640 641 |
.readlink = hppfs_readlink, .follow_link = hppfs_follow_link, |
7b264fc2b hppfs: handle ->p... |
642 |
.put_link = hppfs_put_link, |
1da177e4c Linux-2.6.12-rc2 |
643 |
}; |
f382d6e63 [PATCH] sanitize ... |
644 |
static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) |
1da177e4c Linux-2.6.12-rc2 |
645 |
{ |
f382d6e63 [PATCH] sanitize ... |
646 647 |
struct inode *proc_ino = dentry->d_inode; struct inode *inode = new_inode(sb); |
3cc0658e3 hppfs: fix dentry... |
648 649 |
if (!inode) { dput(dentry); |
f382d6e63 [PATCH] sanitize ... |
650 |
return ERR_PTR(-ENOMEM); |
3cc0658e3 hppfs: fix dentry... |
651 |
} |
f382d6e63 [PATCH] sanitize ... |
652 |
|
1dd0dd111 hppfs pass vfsmou... |
653 |
if (S_ISDIR(dentry->d_inode->i_mode)) { |
1da177e4c Linux-2.6.12-rc2 |
654 655 |
inode->i_op = &hppfs_dir_iops; inode->i_fop = &hppfs_dir_fops; |
1dd0dd111 hppfs pass vfsmou... |
656 |
} else if (S_ISLNK(dentry->d_inode->i_mode)) { |
1da177e4c Linux-2.6.12-rc2 |
657 658 |
inode->i_op = &hppfs_link_iops; inode->i_fop = &hppfs_file_fops; |
1dd0dd111 hppfs pass vfsmou... |
659 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
660 661 662 |
inode->i_op = &hppfs_file_iops; inode->i_fop = &hppfs_file_fops; } |
3cc0658e3 hppfs: fix dentry... |
663 |
HPPFS_I(inode)->proc_dentry = dentry; |
f382d6e63 [PATCH] sanitize ... |
664 665 666 667 668 669 670 671 |
inode->i_uid = proc_ino->i_uid; inode->i_gid = proc_ino->i_gid; inode->i_atime = proc_ino->i_atime; inode->i_mtime = proc_ino->i_mtime; inode->i_ctime = proc_ino->i_ctime; inode->i_ino = proc_ino->i_ino; inode->i_mode = proc_ino->i_mode; |
bfe868486 filesystems: add ... |
672 |
set_nlink(inode, proc_ino->i_nlink); |
f382d6e63 [PATCH] sanitize ... |
673 674 |
inode->i_size = proc_ino->i_size; inode->i_blocks = proc_ino->i_blocks; |
1da177e4c Linux-2.6.12-rc2 |
675 |
|
a0612b1f0 uml: hppfs fixes |
676 |
return inode; |
1da177e4c Linux-2.6.12-rc2 |
677 678 679 680 681 |
} static int hppfs_fill_super(struct super_block *sb, void *d, int silent) { struct inode *root_inode; |
1dd0dd111 hppfs pass vfsmou... |
682 |
struct vfsmount *proc_mnt; |
f382d6e63 [PATCH] sanitize ... |
683 |
int err = -ENOENT; |
1da177e4c Linux-2.6.12-rc2 |
684 |
|
0ceeca5a0 hppfs can use exi... |
685 |
proc_mnt = mntget(current->nsproxy->pid_ns->proc_mnt); |
1dd0dd111 hppfs pass vfsmou... |
686 |
if (IS_ERR(proc_mnt)) |
1da177e4c Linux-2.6.12-rc2 |
687 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
688 689 690 691 |
sb->s_blocksize = 1024; sb->s_blocksize_bits = 10; sb->s_magic = HPPFS_SUPER_MAGIC; sb->s_op = &hppfs_sbops; |
f382d6e63 [PATCH] sanitize ... |
692 |
sb->s_fs_info = proc_mnt; |
1da177e4c Linux-2.6.12-rc2 |
693 694 |
err = -ENOMEM; |
4c1d5a64f vfs: for usbfs, e... |
695 |
root_inode = get_inode(sb, dget(proc_mnt->mnt_root)); |
f382d6e63 [PATCH] sanitize ... |
696 697 |
if (!root_inode) goto out_mntput; |
1da177e4c Linux-2.6.12-rc2 |
698 |
sb->s_root = d_alloc_root(root_inode); |
1dd0dd111 hppfs pass vfsmou... |
699 700 |
if (!sb->s_root) goto out_iput; |
1da177e4c Linux-2.6.12-rc2 |
701 |
|
1dd0dd111 hppfs pass vfsmou... |
702 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
703 |
|
1dd0dd111 hppfs pass vfsmou... |
704 |
out_iput: |
1da177e4c Linux-2.6.12-rc2 |
705 |
iput(root_inode); |
1dd0dd111 hppfs pass vfsmou... |
706 707 |
out_mntput: mntput(proc_mnt); |
1da177e4c Linux-2.6.12-rc2 |
708 709 710 |
out: return(err); } |
3c26ff6e4 convert get_sb_no... |
711 |
static struct dentry *hppfs_read_super(struct file_system_type *type, |
454e2398b [PATCH] VFS: Perm... |
712 |
int flags, const char *dev_name, |
3c26ff6e4 convert get_sb_no... |
713 |
void *data) |
1da177e4c Linux-2.6.12-rc2 |
714 |
{ |
3c26ff6e4 convert get_sb_no... |
715 |
return mount_nodev(type, flags, data, hppfs_fill_super); |
1da177e4c Linux-2.6.12-rc2 |
716 717 718 719 720 |
} static struct file_system_type hppfs_type = { .owner = THIS_MODULE, .name = "hppfs", |
3c26ff6e4 convert get_sb_no... |
721 |
.mount = hppfs_read_super, |
1da177e4c Linux-2.6.12-rc2 |
722 723 724 725 726 727 |
.kill_sb = kill_anon_super, .fs_flags = 0, }; static int __init init_hppfs(void) { |
1dd0dd111 hppfs pass vfsmou... |
728 |
return register_filesystem(&hppfs_type); |
1da177e4c Linux-2.6.12-rc2 |
729 730 731 732 733 734 735 736 737 738 |
} static void __exit exit_hppfs(void) { unregister_filesystem(&hppfs_type); } module_init(init_hppfs) module_exit(exit_hppfs) MODULE_LICENSE("GPL"); |