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));
15 e_file->b_ino = EXT2_INO(inode);
19 if (check_directory_node(inode)) {
20 errno = ext2dr_open(inode, file);
24 // XXX anything for regular file?
37 ext2_close_inode(struct v_file* file)
39 ext2ino_update(file->inode);
41 if (check_directory_node(file->inode)) {
42 ext2dr_close(file->inode, file);
51 ext2_sync_inode(struct v_inode* inode)
54 // a modification to an inode may involves multiple
55 // blkbuf scattering among different groups.
56 // For now, we just sync everything, until we figure out
57 // a way to track each dirtied blkbuf w.r.t inode
58 ext2ino_resizing(inode, inode->fsize);
59 blkbuf_syncall(inode->sb->blks, false);
65 ext2_file_sync(struct v_file* file)
67 return ext2_sync_inode(file->inode);
71 ext2_seek_inode(struct v_file* file, size_t offset)
73 if (check_directory_node(file->inode)) {
74 return ext2dr_seek(file, offset);
77 // nothing to do, seek on file pos handled by vfs
82 ext2_inode_read(struct v_inode *inode,
83 void *buffer, size_t len, size_t fpos)
85 struct ext2_sbinfo* e_sb;
86 struct ext2_iterator iter;
87 struct ext2b_inode* b_ino;
88 struct ext2_inode* e_ino;
91 unsigned int sz = 0, blksz, movsz;
93 e_sb = EXT2_SB(inode->sb);
94 e_ino = EXT2_INO(inode);
96 blksz = e_sb->block_size;
99 ext2db_itbegin(&iter, inode);
100 ext2db_itffw(&iter, fpos / blksz);
102 while (fpos < end && ext2db_itnext(&iter)) {
104 movsz = MIN(end - fpos, blksz - off);
106 memcpy(buffer, offset(iter.data, off), movsz);
108 buffer = offset(buffer, movsz);
114 return itstate_sel(&iter, MIN(sz, e_ino->isize));
118 ext2_inode_read_page(struct v_inode *inode, void *buffer, size_t fpos)
120 struct ext2_sbinfo* e_sb;
121 struct ext2_iterator iter;
122 struct ext2_inode* e_ino;
123 struct ext2b_inode* b_ino;
124 unsigned int blk_start, n,
125 transfer_sz, total_sz = 0;
127 assert(!va_offset(fpos));
129 e_sb = EXT2_SB(inode->sb);
130 e_ino = EXT2_INO(inode);
133 blk_start = fpos / e_sb->block_size;
134 n = PAGE_SIZE / e_sb->block_size;
135 transfer_sz = MIN(PAGE_SIZE, e_sb->block_size);
137 ext2db_itbegin(&iter, inode);
138 ext2db_itffw(&iter, blk_start);
140 while (n-- && ext2db_itnext(&iter))
142 memcpy(buffer, iter.data, transfer_sz);
143 buffer = offset(buffer, transfer_sz);
144 total_sz += transfer_sz;
148 return itstate_sel(&iter, MIN(total_sz, e_ino->isize));
152 ext2_inode_write(struct v_inode *inode,
153 void *buffer, size_t len, size_t fpos)
156 unsigned int acc, blk_off, end, size;
157 struct ext2_sbinfo* e_sb;
160 e_sb = EXT2_SB(inode->sb);
165 errno = ext2db_acquire(inode, blkpos(e_sb, fpos), &buf);
170 blk_off = blkoff(e_sb, fpos);
171 size = e_sb->block_size - blk_off;
173 memcpy(offset(blkbuf_data(buf), blk_off), buffer, size);
174 buffer = offset(buffer, size);
187 ext2_inode_write_page(struct v_inode *inode, void *buffer, size_t fpos)
189 return ext2_inode_write(inode, buffer, PAGE_SIZE, fpos);
192 #define SYMLNK_INPLACE \
193 sizeof(((struct ext2b_inode*)0)->i_block_arr)
196 __readlink_symlink(struct v_inode *this, char* path)
202 struct ext2_inode* e_ino;
204 e_ino = EXT2_INO(this);
206 if (size <= SYMLNK_INPLACE) {
207 link = (char*) e_ino->ino->i_block_arr;
208 strncpy(path, link, size);
211 buf = ext2db_get(this, 0);
212 if (blkbuf_errbuf(buf)) {
216 link = blkbuf_data(buf);
217 strncpy(path, link, size);
226 ext2_get_symlink(struct v_inode *this, const char **path_out)
231 struct ext2_inode* e_ino;
233 e_ino = EXT2_INO(this);
240 if (!e_ino->symlink) {
241 symlink = valloc(size);
242 if ((errno = __readlink_symlink(this, symlink))) {
247 e_ino->symlink = symlink;
250 *path_out = e_ino->symlink;
256 ext2_set_symlink(struct v_inode *this, const char *target)
261 size_t size, new_len;
262 struct ext2_inode* e_ino;
264 e_ino = EXT2_INO(this);
266 new_len = strlen(target);
268 if (new_len > this->sb->blksize) {
272 if (size != new_len) {
273 vfree_safe(e_ino->symlink);
274 e_ino->symlink = valloc(new_len);
277 link = (char*) e_ino->ino->i_block_arr;
279 // if new size is shrinked to inplace range
280 if (size > SYMLNK_INPLACE && new_len <= SYMLNK_INPLACE)
282 ext2db_free_pos(this, 0);
285 // if new size is too big to fit inpalce
286 if (new_len > SYMLNK_INPLACE) {
288 // repurpose the i_block array back to normal
289 if (size <= SYMLNK_INPLACE) {
290 memset(link, 0, SYMLNK_INPLACE);
293 errno = ext2db_acquire(this, 0, &buf);
298 link = blkbuf_data(buf);
301 strncpy(e_ino->symlink, target, new_len);
302 strncpy(link, target, new_len);
304 ext2ino_update(this);
305 ext2ino_resizing(this, new_len);