-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinode.c
179 lines (146 loc) · 4.33 KB
/
inode.c
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
* Chunkfs inode routines
*
* (C) 2007-2008 Valerie Henson <[email protected]>
*/
#include <linux/module.h>
#include <linux/fs_stack.h>
#include "chunkfs.h"
#include "chunkfs_pool.h"
#include "chunkfs_dev.h"
#include "chunkfs_chunk.h"
#include "chunkfs_i.h"
static void
__copy_inode(struct inode *dst, struct inode *src)
{
/* Copy data from one inode to another */
fsstack_copy_attr_all(dst, src);
}
void
chunkfs_copy_up_inode(struct inode *inode, struct inode *client_inode)
{
struct inode *prev_inode = NULL;
struct inode *next_inode;
loff_t total_size = 0;
__copy_inode(inode, client_inode);
while (1) {
if (chunkfs_get_next_inode(inode, prev_inode, &next_inode))
break;
if (next_inode == NULL)
break;
/* XXX doesn't do holey files right */
chunkfs_debug("adding %llu\n", next_inode->i_size);
total_size += next_inode->i_size;
prev_inode = next_inode;
}
inode->i_size = total_size;
chunkfs_debug("ino %lu size %llu\n", inode->i_ino, inode->i_size);
mark_inode_dirty(inode);
}
static void
copy_down_inode(struct inode *inode, struct inode *client_inode)
{
__copy_inode(client_inode, inode);
}
static void
set_inode_ops(struct inode *inode, struct inode *client_inode)
{
/* Pick inode ops */
if (S_ISLNK(client_inode->i_mode))
inode->i_op = &chunkfs_symlink_iops;
else if (S_ISDIR(client_inode->i_mode))
inode->i_op = &chunkfs_dir_iops;
else if (S_ISREG(client_inode->i_mode))
inode->i_op = &chunkfs_file_iops;
else
inode->i_op = &chunkfs_special_iops;
/* Use different set of file ops for directories */
if (S_ISDIR(client_inode->i_mode))
inode->i_fop = &chunkfs_dir_fops;
else if (S_ISREG(client_inode->i_mode))
inode->i_fop = &chunkfs_file_fops;
/* properly initialize special inodes */
if (S_ISBLK(client_inode->i_mode) || S_ISCHR(client_inode->i_mode) ||
S_ISFIFO(client_inode->i_mode) || S_ISSOCK(client_inode->i_mode))
init_special_inode(inode, client_inode->i_mode,
client_inode->i_rdev);
}
/*
* Allocate a new inode and do any extra bits to it that aren't
* covered by the alloc_inode() op (currently none).
*/
int
chunkfs_new_inode(struct super_block *sb, struct inode **inodep)
{
*inodep = new_inode(sb);
if (is_bad_inode(*inodep))
/* XXX hate the inode error return conventions */
return -EIO;
return 0;
}
/*
* We've just read in a client inode. Fill in the chunkfs inode.
* Wait to fill in the continuation until the file is opened.
*/
void
chunkfs_start_inode(struct inode *inode, struct inode *client_inode,
u64 chunk_id)
{
struct chunkfs_inode_info *ii = CHUNKFS_I(inode);
BUG_ON(!client_inode);
ii->ii_client_inode = client_inode;
inode->i_ino = MAKE_UINO(chunk_id, client_inode->i_ino);
/* XXX i_mapping? */
/* XXX check inode checksum, etc. */
set_inode_ops(inode, client_inode);
chunkfs_copy_up_inode(inode, client_inode);
chunkfs_debug(" inode %p ino %0lx mode %0x client %p\n",
inode, inode->i_ino, inode->i_mode, ii->ii_client_inode);
}
/*
* Come in with the chunkfs inode. Fill it in and get the client
* inode too.
*/
struct inode *chunkfs_iget(struct super_block *sb, unsigned long ino)
{
struct chunkfs_chunk_info *ci;
struct inode *client_inode;
struct super_block *client_sb;
struct inode *inode;
u64 chunk_id;
unsigned long client_ino;
inode = iget_locked(sb, ino);
if (!inode)
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW))
return 0;
chunk_id = UINO_TO_CHUNK_ID(inode->i_ino);
client_ino = UINO_TO_INO(inode->i_ino);
chunkfs_debug("reading ino %0lx client ino %0lx chunk_id %0llx count %d\n",
inode->i_ino, client_ino, chunk_id, atomic_read(&inode->i_count));
/* XXX should be chunkfs_get_sb */
ci = chunkfs_find_chunk(sb->s_fs_info, chunk_id);
BUG_ON(ci == NULL); /* XXX */
client_sb = ci->ci_sb;
client_inode = iget_locked(client_sb, client_ino);
if (!(client_inode->i_state & I_NEW))
return 0;
if (is_bad_inode(client_inode)) {
/* XXX should do something here */
BUG();
return 0;
}
chunkfs_start_inode(inode, client_inode, chunk_id);
unlock_inode(inode);
unlock_inode(client_inode);
return 0;
}
int chunkfs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
struct inode *client_inode = get_client_inode(inode);
int err;
copy_down_inode(inode, client_inode);
/* XXX will client inodes be written when evicted? think so */
err = client_inode->i_sb->s_op->write_inode(client_inode, wbc);
return err;
}