-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathfile.c
More file actions
94 lines (78 loc) · 2.54 KB
/
file.c
File metadata and controls
94 lines (78 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "khellofs.h"
ssize_t hellofs_read(struct file *filp, char __user *buf, size_t len,
loff_t *ppos) {
struct super_block *sb;
struct inode *inode;
struct hellofs_inode *hellofs_inode;
struct buffer_head *bh;
char *buffer;
int nbytes;
inode = filp->f_path.dentry->d_inode;
sb = inode->i_sb;
hellofs_inode = HELLOFS_INODE(inode);
if (*ppos >= hellofs_inode->file_size) {
return 0;
}
bh = sb_bread(sb, hellofs_inode->data_block_no);
if (!bh) {
printk(KERN_ERR "Failed to read data block %llu\n",
hellofs_inode->data_block_no);
return 0;
}
buffer = (char *)bh->b_data + *ppos;
nbytes = min((size_t)(hellofs_inode->file_size - *ppos), len);
if (copy_to_user(buf, buffer, nbytes)) {
brelse(bh);
printk(KERN_ERR
"Error copying file content to userspace buffer\n");
return -EFAULT;
}
brelse(bh);
*ppos += nbytes;
return nbytes;
}
/* TODO We didn't use address_space/pagecache here.
If we hook file_operations.write = do_sync_write,
and file_operations.aio_write = generic_file_aio_write,
we will use write to pagecache instead. */
ssize_t hellofs_write(struct file *filp, const char __user *buf, size_t len,
loff_t *ppos) {
struct super_block *sb;
struct inode *inode;
struct hellofs_inode *hellofs_inode;
struct buffer_head *bh;
struct hellofs_superblock *hellofs_sb;
char *buffer;
int ret;
inode = filp->f_path.dentry->d_inode;
sb = inode->i_sb;
hellofs_inode = HELLOFS_INODE(inode);
hellofs_sb = HELLOFS_SB(sb);
ret = generic_write_checks(filp, ppos, &len, 0);
if (ret) {
return ret;
}
bh = sb_bread(sb, hellofs_inode->data_block_no);
if (!bh) {
printk(KERN_ERR "Failed to read data block %llu\n",
hellofs_inode->data_block_no);
return 0;
}
buffer = (char *)bh->b_data + *ppos;
if (copy_from_user(buffer, buf, len)) {
brelse(bh);
printk(KERN_ERR
"Error copying file content from userspace buffer "
"to kernel space\n");
return -EFAULT;
}
*ppos += len;
mark_buffer_dirty(bh);
sync_dirty_buffer(bh);
brelse(bh);
hellofs_inode->file_size = max((size_t)(hellofs_inode->file_size),
(size_t)(*ppos));
hellofs_save_hellofs_inode(sb, hellofs_inode);
/* TODO We didn't update file size here. To be frank I don't know how. */
return len;
}