1 #include <lunaix/mm/valloc.h>
2 #include <lunaix/mm/page.h>
5 #define blkpos(e_sb, fpos) ((fpos) / (e_sb)->block_size)
6 #define blkoff(e_sb, fpos) ((fpos) % (e_sb)->block_size)
9 ext2_open_inode(struct v_inode* inode, struct v_file* file)
12 struct ext2_file* e_file;
14 e_file = valloc(sizeof(*e_file));
18 if (check_directory_node(inode)) {
19 errno = ext2dr_open(inode, file);
23 // XXX anything for regular file?
36 ext2_close_inode(struct v_file* file)
38 ext2ino_update(file->inode);
40 if (check_directory_node(file->inode)) {
41 ext2dr_close(file->inode, file);
50 ext2_sync_inode(struct v_inode* inode)
53 // a modification to an inode may involves multiple
54 // blkbuf scattering among different groups.
55 // For now, we just sync everything, until we figure out
56 // a way to track each dirtied blkbuf w.r.t inode
57 ext2ino_resizing(inode, inode->fsize);
58 blkbuf_syncall(inode->sb->blks, false);
64 ext2_file_sync(struct v_file* file)
66 return ext2_sync_inode(file->inode);
70 ext2_seek_inode(struct v_file* file, size_t offset)
72 if (check_directory_node(file->inode)) {
73 return ext2dr_seek(file, offset);
76 // nothing to do, seek on file pos handled by vfs
81 ext2_inode_read(struct v_inode *inode,
82 void *buffer, size_t len, size_t fpos)
84 struct ext2_sbinfo* e_sb;
85 struct ext2_iterator iter;
86 struct ext2b_inode* b_ino;
87 struct ext2_inode* e_ino;
90 unsigned int sz = 0, blksz, movsz;
92 e_sb = EXT2_SB(inode->sb);
93 e_ino = EXT2_INO(inode);
95 blksz = e_sb->block_size;
98 ext2db_itbegin(&iter, inode, DBIT_MODE_ISIZE);
99 ext2db_itffw(&iter, fpos / blksz);
101 while (fpos < end && ext2db_itnext(&iter)) {
103 movsz = MIN(end - fpos, blksz - off);
105 memcpy(buffer, offset(iter.data, off), movsz);
107 buffer = offset(buffer, movsz);
113 return itstate_sel(&iter, MIN(sz, e_ino->isize));
117 ext2_inode_read_page(struct v_inode *inode, void *buffer, size_t fpos)
119 struct ext2_sbinfo* e_sb;
120 struct ext2_iterator iter;
121 struct ext2_inode* e_ino;
122 struct ext2b_inode* b_ino;
123 unsigned int blk_start, n,
124 transfer_sz, total_sz = 0;
126 assert(!va_offset(fpos));
128 e_sb = EXT2_SB(inode->sb);
129 e_ino = EXT2_INO(inode);
132 blk_start = fpos / e_sb->block_size;
133 n = PAGE_SIZE / e_sb->block_size;
134 transfer_sz = MIN(PAGE_SIZE, e_sb->block_size);
136 ext2db_itbegin(&iter, inode, DBIT_MODE_ISIZE);
137 ext2db_itffw(&iter, blk_start);
139 while (n-- && ext2db_itnext(&iter))
141 memcpy(buffer, iter.data, transfer_sz);
142 buffer = offset(buffer, transfer_sz);
143 total_sz += transfer_sz;
147 return itstate_sel(&iter, MIN(total_sz, e_ino->isize));
151 ext2_inode_write(struct v_inode *inode,
152 void *buffer, size_t len, size_t fpos)
155 unsigned int acc, blk_off, end, size;
156 struct ext2_sbinfo* e_sb;
159 e_sb = EXT2_SB(inode->sb);
164 errno = ext2db_acquire(inode, blkpos(e_sb, fpos), &buf);
169 blk_off = blkoff(e_sb, fpos);
170 size = e_sb->block_size - blk_off;
172 memcpy(offset(blkbuf_data(buf), blk_off), buffer, size);
173 buffer = offset(buffer, size);
186 ext2_inode_write_page(struct v_inode *inode, void *buffer, size_t fpos)
188 return ext2_inode_write(inode, buffer, PAGE_SIZE, fpos);
191 #define SYMLNK_INPLACE \
192 sizeof(((struct ext2b_inode*)0)->i_block_arr)
195 __readlink_symlink(struct v_inode *this, char* path)
201 struct ext2_inode* e_ino;
203 e_ino = EXT2_INO(this);
205 if (size <= SYMLNK_INPLACE) {
206 link = (char*) e_ino->ino->i_block_arr;
207 strncpy(path, link, size);
210 buf = ext2db_get(this, 0);
211 if (blkbuf_errbuf(buf)) {
215 link = blkbuf_data(buf);
216 strncpy(path, link, size);
225 ext2_get_symlink(struct v_inode *this, const char **path_out)
230 struct ext2_inode* e_ino;
232 e_ino = EXT2_INO(this);
239 if (!e_ino->symlink) {
240 symlink = valloc(size);
241 if ((errno = __readlink_symlink(this, symlink))) {
246 e_ino->symlink = symlink;
249 *path_out = e_ino->symlink;
255 ext2_set_symlink(struct v_inode *this, const char *target)
260 size_t size, new_len;
261 struct ext2_inode* e_ino;
263 e_ino = EXT2_INO(this);
265 new_len = strlen(target);
267 if (new_len > this->sb->blksize) {
271 if (size != new_len) {
272 vfree_safe(e_ino->symlink);
273 e_ino->symlink = valloc(new_len);
276 link = (char*) e_ino->ino->i_block_arr;
278 // if new size is shrinked to inplace range
279 if (size > SYMLNK_INPLACE && new_len <= SYMLNK_INPLACE)
281 ext2db_free_pos(this, 0);
284 // if new size is too big to fit inpalce
285 if (new_len > SYMLNK_INPLACE) {
287 // repurpose the i_block array back to normal
288 if (size <= SYMLNK_INPLACE) {
289 memset(link, 0, SYMLNK_INPLACE);
292 errno = ext2db_acquire(this, 0, &buf);
297 link = blkbuf_data(buf);
300 strncpy(e_ino->symlink, target, new_len);
301 strncpy(link, target, new_len);
303 ext2ino_update(this);
304 ext2ino_resizing(this, new_len);