embox

Форк
0
/
ramfs_ops.c 
322 строки · 6.3 Кб
1
#include <errno.h>
2
#include <string.h>
3
#include <sys/stat.h>
4
#include <stdint.h>
5

6
#include <drivers/block_dev.h>
7

8
#include <fs/file_desc.h>
9
#include <fs/inode.h>
10
#include <fs/inode_operation.h>
11
#include <fs/mount.h>
12
#include <fs/super_block.h>
13
#include <fs/dir_context.h>
14

15
#include <mem/misc/pool.h>
16
#include <mem/page.h>
17

18
#include <lib/libds/indexator.h>
19
#include <util/math.h>
20

21
#include "ramfs.h"
22

23
struct ramfs_file_info ramfs_files[RAMFS_FILES];
24

25
INDEX_DEF(ramfs_file_idx, 0, RAMFS_FILES);
26

27
static char sector_buff[RAMFS_BUFFER_SIZE];
28

29
static size_t ramfs_read(struct file_desc *desc, void *buf, size_t size) {
30
	struct ramfs_file_info *fi;
31
	struct ramfs_fs_info *fsi;
32
	struct block_dev *bdev;
33
	void *pbuf, *ebuf;
34
	off_t pos;
35

36
	assert(desc);
37

38
	fi = file_get_inode_data(desc);
39
	assert(fi);
40

41
	fsi = fi->fsi;
42
	assert(fsi);
43

44
	bdev = fsi->bdev;
45
	assert(bdev);
46

47
	pos = file_get_pos(desc);
48

49
	pbuf = buf;
50
	ebuf = buf + min(file_get_size(desc) - pos, size);
51
	while (pbuf < ebuf) {
52
		blkno_t blk = pos / fsi->block_size;
53
		int offset = pos % fsi->block_size;
54
		int read_n;
55

56
		assert (blk < fsi->block_per_file);
57
		assert (blk < fsi->numblocks);
58

59
		blk += fi->index * fsi->block_per_file;
60

61
		assert(sizeof(sector_buff) >= fsi->block_size);
62
		if (0 > block_dev_read(bdev, sector_buff,
63
					fsi->block_size, blk)) {
64
			break;
65
		}
66

67
		read_n = min(fsi->block_size - offset, ebuf - pbuf);
68
		memcpy (pbuf, sector_buff + offset, read_n);
69

70
		pos += read_n;
71
		pbuf += read_n;
72
	}
73

74
	return pbuf - buf;
75
}
76

77
static size_t ramfs_write(struct file_desc *desc, void *buf, size_t size) {
78
	struct ramfs_file_info *fi;
79
	size_t len;
80
	size_t current, cnt;
81
	uint32_t end_pos;
82
	blkno_t blk;
83
	uint32_t bytecount;
84
	uint32_t start_block;
85
	struct ramfs_fs_info *fsi;
86
	struct block_dev *bdev;
87
	off_t pos;
88

89
	fi = file_get_inode_data(desc);
90
	fsi = fi->fsi;
91
	bdev = fsi->bdev;
92

93
	pos = file_get_pos(desc);
94

95
	bytecount = 0;
96

97
	len = size;
98
	end_pos = pos + len;
99
	start_block = fi->index * fsi->block_per_file;
100

101
	while(1) {
102
		if (0 == fsi->block_size) {
103
			break;
104
		}
105

106
		blk = pos / fsi->block_size;
107
		/* check if block over the file */
108
		if(blk >= fsi->block_per_file) {
109
			bytecount = 0;
110
			break;
111
		} else {
112
			blk += start_block;
113
		}
114
		/* calculate pointer in scratch buffer */
115
		current = pos % fsi->block_size;
116

117
		/* set the counter how many bytes written in block */
118
		if(end_pos - pos > fsi->block_size) {
119
			if(current) {
120
				cnt = fsi->block_size - current;
121
			} else {
122
				cnt = fsi->block_size;
123
			}
124
		} else {
125
			cnt = end_pos - pos;
126
			/* over the block ? */
127
			if((current + cnt) > fsi->block_size) {
128
				cnt -= (current + cnt) % fsi->block_size;
129
			}
130
		}
131

132
		/* one block read operation */
133
		if(0 > block_dev_read(bdev, sector_buff, fsi->block_size, blk)) {
134
			bytecount = 0;
135
			break;
136
		}
137
		/* set new data in block */
138
		memcpy (sector_buff + current, buf, cnt);
139

140
		/* write one block to device */
141
		if(0 > block_dev_write(bdev, sector_buff, fsi->block_size, blk)) {
142
			bytecount = 0;
143
			break;
144
		}
145
		bytecount += cnt;
146
		buf = (void*) (((uint8_t*) buf) + cnt);
147
		/* shift the pointer */
148
		pos += cnt;
149
		if (end_pos <= pos) {
150
			break;
151
		}
152
	}
153
	/* if we write over the last EOF, set new filelen */
154
	if (file_get_size(desc) < pos) {
155
		file_set_size(desc, pos);
156
	}
157

158
	fi->length = file_get_size(desc);
159

160
	return bytecount;
161
}
162

163
/* ramfs filesystem description pool */
164
POOL_DEF(ramfs_fs_pool, struct ramfs_fs_info, RAMFS_DESCRIPTORS);
165

166
extern struct inode_operations ramfs_iops;
167
extern struct super_block_operations ramfs_sbops;
168

169
int ramfs_iterate(struct inode *next, char *name, struct inode *parent, struct dir_ctx *ctx) {
170
	struct ramfs_fs_info *fsi;
171
	int cur_id;
172

173
	assert(ctx);
174
	assert(next);
175
	assert(parent);
176
	assert(parent->i_sb);
177

178
	cur_id = (int) (uintptr_t)ctx->fs_ctx;
179
	fsi = parent->i_sb->sb_data;
180

181
	while (cur_id < RAMFS_FILES) {
182
		if (ramfs_files[cur_id].fsi != fsi) {
183
			cur_id++;
184
			continue;
185
		}
186

187
		inode_priv_set(next, &ramfs_files[cur_id]);
188
		next->i_no = cur_id;
189
		next->i_size = ramfs_files[cur_id].length;
190
		next->i_mode = ramfs_files[cur_id].mode & (S_IFMT | S_IRWXA);
191

192
		ctx->fs_ctx = (void *) (uintptr_t)(cur_id + 1);
193
		strncpy(name, (char *) ramfs_files[cur_id].name, NAME_MAX);
194

195
		return 0;
196
	}
197

198
	ctx->fs_ctx = NULL;
199
	return -1;
200
}
201

202
int ramfs_fill_sb(struct super_block *sb, const char *source) {
203
	struct ramfs_fs_info *fsi;
204
	struct block_dev *bdev;
205

206
	assert(sb);
207

208
	bdev = bdev_by_path(source);
209
	if (NULL == bdev) {
210
		return -ENODEV;
211
	}
212

213
	if (NULL == (fsi = pool_alloc(&ramfs_fs_pool))) {
214
		return -ENOMEM;
215
	}
216

217
	assert(bdev->block_size <= sizeof(sector_buff));
218

219
	memset(fsi, 0, sizeof(struct ramfs_fs_info));
220
	fsi->block_per_file = MAX_FILE_SIZE / bdev->block_size;
221
	fsi->block_size = bdev->block_size;
222
	fsi->numblocks = bdev->size / bdev->block_size;
223
	fsi->bdev = bdev;
224

225
	sb->sb_data = fsi;
226
	sb->sb_iops = &ramfs_iops;
227
	sb->sb_fops = &ramfs_fops;
228
	sb->sb_ops  = &ramfs_sbops;
229
	sb->bdev    = bdev;
230

231
	return 0;
232
}
233

234
struct file_operations ramfs_fops = {
235
	.write = ramfs_write,
236
	.read = ramfs_read,
237
};
238

239
int ramfs_format(struct block_dev *bdev, void *priv) {
240
	if (NULL == bdev) {
241
		return -ENODEV;
242
	}
243

244
	if (MAX_FILE_SIZE > bdev->size) {
245
		return -ENOSPC;
246
	}
247

248
	return 0;
249
}
250

251
struct ramfs_file_info *ramfs_file_alloc(struct inode *node) {
252
	struct ramfs_file_info *fi;
253
	size_t fi_index;
254

255
	fi_index = index_alloc(&ramfs_file_idx, INDEX_MIN);
256
	if (fi_index == INDEX_NONE) {
257
		return NULL;
258
	}
259

260
	fi = &ramfs_files[fi_index];
261
	memset(fi, 0, sizeof(*fi));
262

263
	fi->index = fi_index;
264
	fi->fsi   = node->i_sb->sb_data;
265
	fi->inode = node;
266

267
	inode_size_set(node, 0);
268
	inode_priv_set(node, fi);
269

270
	return fi;
271
}
272

273
static int ramfs_file_free(struct ramfs_file_info *fi) {
274
	index_free(&ramfs_file_idx, fi->index);
275
	memset(fi, 0, sizeof(*fi));
276

277
	return 0;
278
}
279

280
int ramfs_delete(struct inode *dir, struct inode *node) {
281
	struct ramfs_file_info *fi;
282

283
	fi = inode_priv(node);
284

285
	return ramfs_file_free(fi);
286
}
287

288
int ramfs_truncate(struct inode *node, off_t length) {
289
	assert(node);
290

291
	if (length > MAX_FILE_SIZE) {
292
		return -EFBIG;
293
	}
294

295
	inode_size_set(node, length);
296

297
	return 0;
298
}
299

300
int ramfs_create(struct inode *i_new, struct inode *i_dir, int mode) {
301
	struct ramfs_file_info *fi;
302

303
	if (S_ISREG(i_new->i_mode)) {
304
		assert(i_new);
305

306
		fi = ramfs_file_alloc(i_new);
307
		if (NULL == fi) {
308
			return -ENOMEM;
309
		}
310
		fi->mode = i_new->i_mode;
311
		strncpy(fi->name, inode_name(i_new), sizeof(fi->name) - 1);
312

313
		i_new->i_no = fi->index;
314
	}
315

316
	return 0;
317
}
318

319
int ramfs_destroy_inode(struct inode *inode) {
320
	assert(inode);
321
	return 0;
322
}
323

324

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.