Coverage Report

Created: 2026-10-17 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/fs/ramfs.c
Line
Count
Source
1
/*
2
 * ramfs.c - a malloc based filesystem
3
 *
4
 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License version 2
8
 * as published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 */
16
17
#include <common.h>
18
#include <driver.h>
19
#include <init.h>
20
#include <malloc.h>
21
#include <fs.h>
22
#include <command.h>
23
#include <errno.h>
24
#include <linux/stat.h>
25
#include <xfuncs.h>
26
#include <linux/sizes.h>
27
28
#define CHUNK_SIZE  (4096 * 2)
29
30
struct ramfs_chunk {
31
  unsigned long ofs;
32
  int size;
33
  struct list_head list;
34
  char data[];
35
};
36
37
struct ramfs_inode {
38
  struct inode inode;
39
  char *name;
40
  char *symlink;
41
  ulong mode;
42
43
  /* bytes used in this inode */
44
  unsigned long size;
45
  /* bytes currently allocated for this inode */
46
  unsigned long alloc_size;
47
48
  struct list_head data;
49
50
  struct ramfs_chunk *current_chunk;
51
};
52
53
static inline struct ramfs_inode *to_ramfs_inode(struct inode *inode)
54
70.0k
{
55
70.0k
  return container_of(inode, struct ramfs_inode, inode);
56
70.0k
}
57
58
/* ---------------------------------------------------------------*/
59
60
static const struct super_operations ramfs_ops;
61
static const struct inode_operations ramfs_dir_inode_operations;
62
static const struct inode_operations ramfs_file_inode_operations;
63
static const struct inode_operations ramfs_symlink_inode_operations;
64
static const struct file_operations ramfs_file_operations;
65
66
static struct inode *ramfs_get_inode(struct super_block *sb, const struct inode *dir,
67
             umode_t mode)
68
48.8k
{
69
48.8k
  struct inode *inode = new_inode(sb);
70
71
48.8k
  if (!inode)
72
0
    return NULL;
73
74
48.8k
  inode->i_ino = get_next_ino();
75
48.8k
  inode->i_mode = mode;
76
77
48.8k
  switch (mode & S_IFMT) {
78
0
  default:
79
0
    return NULL;
80
9.66k
  case S_IFREG:
81
9.66k
    inode->i_op = &ramfs_file_inode_operations;
82
9.66k
    inode->i_fop = &ramfs_file_operations;
83
9.66k
    break;
84
16.2k
  case S_IFDIR:
85
16.2k
    inode->i_op = &ramfs_dir_inode_operations;
86
16.2k
    inode->i_fop = &simple_dir_operations;
87
16.2k
    inc_nlink(inode);
88
16.2k
    break;
89
7.24k
  case S_IFLNK:
90
7.24k
    inode->i_op = &ramfs_symlink_inode_operations;
91
7.24k
    break;
92
0
  case S_IFBLK:
93
15.7k
  case S_IFCHR:
94
15.7k
    break;
95
48.8k
  }
96
97
48.8k
  return inode;
98
48.8k
}
99
100
12.3k
#define MIN_SIZE SZ_8K
101
102
static struct ramfs_chunk *ramfs_get_chunk(unsigned long size)
103
10.1k
{
104
10.1k
  struct ramfs_chunk *data;
105
106
10.1k
  if (size < MIN_SIZE)
107
2.17k
    size = MIN_SIZE;
108
109
10.1k
  data = calloc(struct_size(data, data, size), 1);
110
10.1k
  if (!data)
111
0
    return NULL;
112
113
10.1k
  data->size = size;
114
115
10.1k
  return data;
116
10.1k
}
117
118
static void ramfs_put_chunk(struct ramfs_chunk *data)
119
9.12k
{
120
9.12k
  free(data);
121
9.12k
}
122
123
/* ---------------------------------------------------------------*/
124
125
static int
126
ramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode)
127
33.5k
{
128
33.5k
  struct inode *inode = ramfs_get_inode(dir->i_sb, dir, mode);
129
130
33.5k
  if (!inode)
131
0
    return -ENOSPC;
132
133
33.5k
  d_instantiate(dentry, inode);
134
33.5k
  dget(dentry);   /* Extra count - pin the dentry in core */
135
136
33.5k
  return 0;
137
33.5k
}
138
139
static int ramfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
140
16.1k
{
141
16.1k
  int ret;
142
143
16.1k
  ret = ramfs_mknod(dir, dentry, mode | S_IFDIR);
144
16.1k
  if (!ret)
145
16.1k
    inc_nlink(dir);
146
147
16.1k
  return ret;
148
16.1k
}
149
150
static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode)
151
1.67k
{
152
1.67k
  return ramfs_mknod(dir, dentry, mode | S_IFREG);
153
1.67k
}
154
155
static int __ramfs_mknod(struct inode *dir,struct dentry *dentry, umode_t mode,
156
       const char *cdevname)
157
15.7k
{
158
15.7k
  int ret;
159
160
15.7k
  ret = ramfs_mknod(dir, dentry, mode);
161
15.7k
  if (ret)
162
0
    return ret;
163
164
15.7k
  init_special_inode(dentry->d_inode, mode, cdevname);
165
166
15.7k
  return 0;
167
15.7k
}
168
169
static int ramfs_symlink(struct inode *dir, struct dentry *dentry,
170
       const char *symname)
171
7.24k
{
172
7.24k
  struct inode *inode;
173
174
7.24k
  inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK | S_IRWXG);
175
7.24k
  if (!inode)
176
0
    return -ENOSPC;
177
178
7.24k
  inode->i_link = xstrdup(symname);
179
7.24k
  d_instantiate(dentry, inode);
180
181
7.24k
  return 0;
182
7.24k
}
183
184
static const char *ramfs_get_link(struct dentry *dentry, struct inode *inode)
185
0
{
186
0
  return inode->i_link;
187
0
}
188
189
static const struct inode_operations ramfs_symlink_inode_operations =
190
{
191
  .get_link = ramfs_get_link,
192
};
193
194
static int ramfs_tmpfile(struct inode *dir, struct file *file, umode_t mode)
195
7.99k
{
196
7.99k
  struct inode *inode;
197
198
7.99k
  inode = ramfs_get_inode(dir->i_sb, dir, mode);
199
7.99k
  if (!inode)
200
0
    return -ENOSPC;
201
202
7.99k
  d_tmpfile(file, inode);
203
204
7.99k
  return finish_open_simple(file, 0);
205
7.99k
}
206
207
static const struct inode_operations ramfs_dir_inode_operations =
208
{
209
  .lookup = simple_lookup,
210
  .symlink = ramfs_symlink,
211
  .mkdir = ramfs_mkdir,
212
  .rmdir = simple_rmdir,
213
  .unlink = simple_unlink,
214
  .create = ramfs_create,
215
  .tmpfile = ramfs_tmpfile,
216
  .mknod = __ramfs_mknod,
217
};
218
219
static struct ramfs_chunk *ramfs_find_chunk(struct ramfs_inode *node,
220
              unsigned long pos, int *ofs, int *len)
221
13.7k
{
222
13.7k
  struct ramfs_chunk *data, *cur = node->current_chunk;
223
224
13.7k
  if (cur && pos >= cur->ofs)
225
11.3k
    data = cur;
226
2.45k
  else
227
2.45k
    data = list_first_entry(&node->data, struct ramfs_chunk, list);
228
229
23.8k
  list_for_each_entry_from(data, &node->data, list) {
230
23.8k
    if (data->ofs + data->size > pos) {
231
13.7k
      *ofs = pos - data->ofs;
232
13.7k
      *len = data->size - *ofs;
233
234
13.7k
      node->current_chunk = data;
235
236
13.7k
      return data;
237
13.7k
    }
238
23.8k
  }
239
240
0
  pr_err("%s: no chunk for pos %ld found\n", __func__, pos);
241
242
0
  return NULL;
243
13.7k
}
244
245
static int ramfs_read(struct file *f, void *buf, size_t insize)
246
1.24k
{
247
1.24k
  struct inode *inode = f->f_inode;
248
1.24k
  struct ramfs_inode *node = to_ramfs_inode(inode);
249
1.24k
  struct ramfs_chunk *data;
250
1.24k
  int ofs, len, now;
251
1.24k
  unsigned long pos = f->f_pos;
252
1.24k
  int size = insize;
253
254
1.24k
  pr_vdebug("%s: %p %zu @ %lld\n", __func__, node, insize, f->f_pos);
255
256
4.84k
  while (size) {
257
3.59k
    data = ramfs_find_chunk(node, pos, &ofs, &len);
258
3.59k
    if (!data)
259
0
      return -EINVAL;
260
261
3.59k
    pr_vdebug("%s: pos: %lu ofs: %d len: %d\n", __func__, pos, ofs, len);
262
263
3.59k
    now = min(size, len);
264
265
3.59k
    memcpy(buf, data->data + ofs, now);
266
267
3.59k
    size -= now;
268
3.59k
    buf += now;
269
3.59k
    pos += now;
270
3.59k
  }
271
272
1.24k
  return insize;
273
1.24k
}
274
275
static int ramfs_write(struct file *f, const void *buf, size_t insize)
276
10.1k
{
277
10.1k
  struct inode *inode = f->f_inode;
278
10.1k
  struct ramfs_inode *node = to_ramfs_inode(inode);
279
10.1k
  struct ramfs_chunk *data;
280
10.1k
  int ofs, len, now;
281
10.1k
  unsigned long pos = f->f_pos;
282
10.1k
  int size = insize;
283
284
10.1k
  pr_vdebug("%s: %p %zu @ %lld\n", __func__, node, insize, f->f_pos);
285
286
20.3k
  while (size) {
287
10.1k
    data = ramfs_find_chunk(node, pos, &ofs, &len);
288
10.1k
    if (!data)
289
0
      return -EINVAL;
290
291
10.1k
    pr_vdebug("%s: pos: %lu ofs: %d len: %d\n", __func__, pos, ofs, len);
292
293
10.1k
    now = min(size, len);
294
295
10.1k
    memcpy(data->data + ofs, buf, now);
296
297
10.1k
    size -= now;
298
10.1k
    buf += now;
299
10.1k
    pos += now;
300
10.1k
  }
301
302
10.1k
  return insize;
303
10.1k
}
304
305
static void ramfs_truncate_down(struct ramfs_inode *node, unsigned long size)
306
46.7k
{
307
46.7k
  struct ramfs_chunk *data, *tmp;
308
309
46.7k
  list_for_each_entry_safe(data, tmp, &node->data, list) {
310
9.12k
    if (data->ofs >= size) {
311
9.12k
      list_del(&data->list);
312
9.12k
      node->alloc_size -= data->size;
313
9.12k
      ramfs_put_chunk(data);
314
9.12k
    }
315
9.12k
  }
316
317
46.7k
  node->current_chunk = NULL;
318
46.7k
}
319
320
static int ramfs_truncate_up(struct ramfs_inode *node, unsigned long size)
321
10.1k
{
322
10.1k
  struct ramfs_chunk *data, *tmp;
323
10.1k
  LIST_HEAD(list);
324
10.1k
  unsigned long add = size - node->alloc_size;
325
10.1k
  unsigned long chunksize = add;
326
10.1k
  unsigned long alloc_size = 0;
327
328
10.1k
  if (node->alloc_size >= size)
329
0
    return 0;
330
331
  /*
332
   * We first try to allocate all space we need in a single chunk.
333
   * This may fail because of fragmented memory, so in case we cannot
334
   * allocate memory we successively decrease the chunk size until
335
   * we have enough allocations made.
336
   */
337
10.1k
  while (1) {
338
10.1k
    unsigned long now = min(chunksize, add);
339
340
10.1k
    data = ramfs_get_chunk(now);
341
10.1k
    if (!data) {
342
      /* No luck, try with smaller chunk size */
343
0
      chunksize >>= 1;
344
345
      /* If we do not have even 128KiB then go out */
346
0
      if (chunksize < SZ_128K)
347
0
        goto out;
348
349
0
      continue;
350
0
    }
351
352
10.1k
    data->ofs = node->alloc_size + alloc_size;
353
354
10.1k
    alloc_size += data->size;
355
356
10.1k
    list_add_tail(&data->list, &list);
357
358
10.1k
    if (add <= data->size)
359
10.1k
      break;
360
361
0
    add -= data->size;
362
0
  }
363
364
10.1k
  list_splice_tail(&list, &node->data);
365
366
10.1k
  node->alloc_size += alloc_size;
367
368
10.1k
  return 0;
369
370
0
out:
371
0
  list_for_each_entry_safe(data, tmp, &list, list) {
372
0
    list_del(&data->list);
373
0
    ramfs_put_chunk(data);
374
0
  }
375
376
0
  return -ENOSPC;
377
10.1k
}
378
379
static int ramfs_truncate(struct file *f, loff_t size)
380
11.8k
{
381
11.8k
  struct inode *inode = f->f_inode;
382
11.8k
  struct ramfs_inode *node = to_ramfs_inode(inode);
383
11.8k
  int ret;
384
385
  /*
386
   * This is a malloc based filesystem, no need to support more
387
   * memory than fits into unsigned long.
388
   */
389
11.8k
  if (size > ULONG_MAX)
390
0
    return -ENOSPC;
391
392
11.8k
  pr_vdebug("%s: %p cur: %ld new: %lld alloc: %ld\n", __func__, node,
393
11.8k
         node->size, size, node->alloc_size);
394
395
11.8k
  if (size == node->size)
396
1.67k
    return 0;
397
398
10.2k
  if (size < node->size) {
399
52
    ramfs_truncate_down(node, size);
400
10.1k
  } else {
401
10.1k
    ret = ramfs_truncate_up(node, size);
402
10.1k
    if (ret)
403
0
      return ret;
404
10.1k
  }
405
406
10.2k
  node->size = size;
407
408
10.2k
  return 0;
409
10.2k
}
410
411
static int ramfs_memmap(struct file *f, void **map, int flags)
412
0
{
413
0
  struct inode *inode = f->f_inode;
414
0
  struct ramfs_inode *node = to_ramfs_inode(inode);
415
0
  struct ramfs_chunk *data;
416
417
0
  if (list_empty(&node->data))
418
0
    return -EINVAL;
419
420
0
  if (!list_is_singular(&node->data))
421
0
    return -EINVAL;
422
423
0
  data = list_first_entry(&node->data, struct ramfs_chunk, list);
424
425
0
  *map = data->data;
426
427
0
  return 0;
428
0
}
429
430
static const struct file_operations ramfs_file_operations = {
431
  .read      = ramfs_read,
432
  .write     = ramfs_write,
433
  .memmap    = ramfs_memmap,
434
  .truncate  = ramfs_truncate,
435
};
436
437
static struct inode *ramfs_alloc_inode(struct super_block *sb)
438
48.8k
{
439
48.8k
  struct ramfs_inode *node;
440
441
48.8k
  node = xzalloc(sizeof(*node));
442
443
48.8k
  INIT_LIST_HEAD(&node->data);
444
445
48.8k
  return &node->inode;
446
48.8k
}
447
448
static void ramfs_destroy_inode(struct inode *inode)
449
46.7k
{
450
46.7k
  struct ramfs_inode *node = to_ramfs_inode(inode);
451
452
46.7k
  ramfs_truncate_down(node, 0);
453
454
46.7k
  free(node);
455
46.7k
}
456
457
static const struct super_operations ramfs_ops = {
458
  .alloc_inode = ramfs_alloc_inode,
459
  .destroy_inode = ramfs_destroy_inode,
460
};
461
462
static int ramfs_probe(struct device *dev)
463
26
{
464
26
  struct inode *inode;
465
26
  struct fs_device *fsdev = dev_to_fs_device(dev);
466
26
  struct super_block *sb = &fsdev->sb;
467
468
26
  sb->s_op = &ramfs_ops;
469
470
26
  inode = ramfs_get_inode(sb, NULL, S_IFDIR);
471
26
  sb->s_root = d_make_root(inode);
472
473
26
  return 0;
474
26
}
475
476
static struct fs_driver ramfs_driver = {
477
  .drv = {
478
    .probe  = ramfs_probe,
479
    .name = "ramfs",
480
  }
481
};
482
483
static int ramfs_init(void)
484
26
{
485
26
  return register_fs_driver(&ramfs_driver);
486
26
}
487
488
coredevice_initcall(ramfs_init);