L4Re - L4 Runtime Environment
vfs_impl.h
1 /*
2  * (c) 2008-2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  * Alexander Warg <warg@os.inf.tu-dresden.de>,
4  * Björn Döbel <doebel@os.inf.tu-dresden.de>
5  * economic rights: Technische Universität Dresden (Germany)
6  *
7  * This file is part of TUD:OS and distributed under the terms of the
8  * GNU General Public License 2.
9  * Please see the COPYING-GPL-2 file for details.
10  *
11  * As a special exception, you may use this file as part of a free software
12  * library without restriction. Specifically, if other files instantiate
13  * templates or use macros or inline functions from this file, or you compile
14  * this file and link it with other files to produce an executable, this
15  * file does not by itself cause the resulting executable to be covered by
16  * the GNU General Public License. This exception does not however
17  * invalidate any other reasons why the executable file might be covered by
18  * the GNU General Public License.
19  */
20 
21 #include "ds_util.h"
22 #include "fd_store.h"
23 #include "vcon_stream.h"
24 #include "ns_fs.h"
25 #include "vfs_api.h"
26 
27 #include <l4/re/env>
28 #include <l4/re/rm>
29 #include <l4/re/dataspace>
30 #include <l4/cxx/hlist>
31 #include <l4/cxx/std_alloc>
32 
33 #include <l4/l4re_vfs/backend>
34 
35 #include <unistd.h>
36 #include <cstdarg>
37 #include <errno.h>
38 #include <sys/uio.h>
39 
40 #if 0
41 #include <l4/sys/kdebug.h>
42 static int debug_mmap = 1;
43 #define DEBUG_LOG(level, dbg...) do { if (level) dbg } while (0)
44 #else
45 #define DEBUG_LOG(level, dbg...) do { } while (0)
46 #endif
47 
53 #define USE_BIG_ANON_DS
54 
55 using L4Re::Rm;
56 
57 namespace {
58 
59 using cxx::Ref_ptr;
60 
61 class Fd_store : public L4Re::Core::Fd_store
62 {
63 public:
64  Fd_store() throw();
65 };
66 
67 // for internal Vcon_streams we want to have a placement new operator, so
68 // inherit and add one
69 class Std_stream : public L4Re::Core::Vcon_stream
70 {
71 public:
72  Std_stream(L4::Cap<L4::Vcon> c) : L4Re::Core::Vcon_stream(c) {}
73 };
74 
75 Fd_store::Fd_store() throw()
76 {
77  // use this strange way to prevent deletion of the stdio object
78  // this depends on Fd_store to being a singleton !!!
79  static char m[sizeof(Std_stream)] __attribute__((aligned(sizeof(long))));
80  Std_stream *s = new (m) Std_stream(L4Re::Env::env()->log());
81  // make sure that we never delete the static io stream thing
82  s->add_ref();
83  set(0, cxx::ref_ptr(s)); // stdin
84  set(1, cxx::ref_ptr(s)); // stdout
85  set(2, cxx::ref_ptr(s)); // stderr
86 }
87 
88 class Root_mount_tree : public L4Re::Vfs::Mount_tree
89 {
90 public:
91  Root_mount_tree() : L4Re::Vfs::Mount_tree(0) {}
92  void operator delete (void *) {}
93 };
94 
95 class Vfs : public L4Re::Vfs::Ops
96 {
97 private:
98  bool _early_oom;
99 
100 public:
101  Vfs()
102  : _early_oom(true), _root_mount(), _root(L4Re::Env::env())
103  {
104  _root_mount.add_ref();
105  _root.add_ref();
106  _root_mount.mount(cxx::ref_ptr(&_root));
107  _cwd = cxx::ref_ptr(&_root);
108 
109 #if 0
110  Ref_ptr<L4Re::Vfs::File> rom;
111  _root.openat("rom", 0, 0, &rom);
112 
113  _root_mount.create_tree("lib/foo", rom);
114 
115  _root.openat("lib", 0, 0, &_cwd);
116 
117 #endif
118  }
119 
120  int alloc_fd(Ref_ptr<L4Re::Vfs::File> const &f) throw();
121  Ref_ptr<L4Re::Vfs::File> free_fd(int fd) throw();
122  Ref_ptr<L4Re::Vfs::File> get_root() throw();
123  Ref_ptr<L4Re::Vfs::File> get_cwd() throw();
124  void set_cwd(Ref_ptr<L4Re::Vfs::File> const &dir) throw();
125  Ref_ptr<L4Re::Vfs::File> get_file(int fd) throw();
126  Ref_ptr<L4Re::Vfs::File> set_fd(int fd, Ref_ptr<L4Re::Vfs::File> const &f = Ref_ptr<>::Nil) throw();
127  L4Re::Cap_alloc *cap_alloc() throw();
128 
129  int mmap2(void *start, size_t len, int prot, int flags, int fd,
130  off_t offset, void **ptr) throw();
131 
132  int munmap(void *start, size_t len) throw();
133  int mremap(void *old, size_t old_sz, size_t new_sz, int flags,
134  void **new_addr) throw();
135  int mprotect(const void *a, size_t sz, int prot) throw();
136  int msync(void *addr, size_t len, int flags) throw();
137  int madvise(void *addr, size_t len, int advice) throw();
138 
139  int register_file_system(L4Re::Vfs::File_system *f) throw();
140  int unregister_file_system(L4Re::Vfs::File_system *f) throw();
141  L4Re::Vfs::File_system *get_file_system(char const *fstype) throw();
142 
143  int register_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) throw();
144  int unregister_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) throw();
145  Ref_ptr<L4Re::Vfs::File_factory> get_file_factory(int proto) throw();
146  Ref_ptr<L4Re::Vfs::File_factory> get_file_factory(char const *proto_name) throw();
147 
148  void operator delete (void *) {}
149 
150  void *malloc(size_t size) noexcept { return Vfs_config::malloc(size); }
151  void free(void *m) noexcept { Vfs_config::free(m); }
152 
153 private:
154  Root_mount_tree _root_mount;
155  L4Re::Core::Env_dir _root;
156  Ref_ptr<L4Re::Vfs::File> _cwd;
157  Fd_store fds;
158 
159  L4Re::Vfs::File_system *_fs_registry;
160 
161  struct File_factory_item : cxx::H_list_item_t<File_factory_item>
162  {
164  explicit File_factory_item(cxx::Ref_ptr<L4Re::Vfs::File_factory> const &f)
165  : f(f) {};
166 
167  File_factory_item() = default;
168  File_factory_item(File_factory_item const &) = delete;
169  File_factory_item &operator = (File_factory_item const &) = delete;
170  };
171 
172  cxx::H_list_t<File_factory_item> _file_factories;
173 
174  l4_addr_t _anon_offset;
175  L4::Cap<L4Re::Dataspace> _anon_ds;
176 
177  int alloc_ds(unsigned long size, L4::Cap<L4Re::Dataspace> *ds);
178  int alloc_anon_mem(l4_umword_t size, L4::Cap<L4Re::Dataspace> *ds,
179  l4_addr_t *offset);
180 };
181 
182 static inline bool strequal(char const *a, char const *b)
183 {
184  for (;*a && *a == *b; ++a, ++b)
185  ;
186  return *a == *b;
187 }
188 
189 int
190 Vfs::register_file_system(L4Re::Vfs::File_system *f) throw()
191 {
193 
194  if (!f)
195  return -EINVAL;
196 
197  for (File_system *c = _fs_registry; c; c = c->next())
198  if (strequal(c->type(), f->type()))
199  return -EEXIST;
200 
201  f->next(_fs_registry);
202  _fs_registry = f;
203 
204  return 0;
205 }
206 
207 int
208 Vfs::unregister_file_system(L4Re::Vfs::File_system *f) throw()
209 {
211 
212  if (!f)
213  return -EINVAL;
214 
215  File_system **p = &_fs_registry;
216 
217  for (; *p; p = &(*p)->next())
218  if (*p == f)
219  {
220  *p = f->next();
221  f->next() = 0;
222  return 0;
223  }
224 
225  return -ENOENT;
226 }
227 
229 Vfs::get_file_system(char const *fstype) throw()
230 {
231  bool try_dynamic = true;
232  for (;;)
233  {
235  for (File_system *c = _fs_registry; c; c = c->next())
236  if (strequal(c->type(), fstype))
237  return c;
238 
239  if (!try_dynamic)
240  return 0;
241 
242  // try to load a file system module dynamically
243  int res = Vfs_config::load_module(fstype);
244 
245  if (res < 0)
246  return 0;
247 
248  try_dynamic = false;
249  }
250 }
251 
252 int
253 Vfs::register_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) throw()
254 {
255  if (!f)
256  return -EINVAL;
257 
258  void *x = this->malloc(sizeof(File_factory_item));
259  if (!x)
260  return -ENOMEM;
261 
262  auto ff = new (x, cxx::Nothrow()) File_factory_item(f);
263  _file_factories.push_front(ff);
264  return 0;
265 }
266 
267 int
268 Vfs::unregister_file_factory(cxx::Ref_ptr<L4Re::Vfs::File_factory> f) throw()
269 {
270  for (auto p: _file_factories)
271  {
272  if (p->f == f)
273  {
274  _file_factories.remove(p);
275  p->~File_factory_item();
276  this->free(p);
277  return 0;
278  }
279  }
280  return -ENOENT;
281 }
282 
283 Ref_ptr<L4Re::Vfs::File_factory>
284 Vfs::get_file_factory(int proto) throw()
285 {
286  for (auto p: _file_factories)
287  if (p->f->proto() == proto)
288  return p->f;
289 
290  return Ref_ptr<L4Re::Vfs::File_factory>();
291 }
292 
293 Ref_ptr<L4Re::Vfs::File_factory>
294 Vfs::get_file_factory(char const * /*proto_name*/) throw()
295 {
296 #if 0 // strcmp not available in ldso so disable this for now
297  for (auto p: _file_factories)
298  {
299  auto n = p->f->proto_name();
300  if (n && __builtin_strcmp(n, proto_name) == 0)
301  return p->f;
302  }
303 #endif
304  return Ref_ptr<L4Re::Vfs::File_factory>();
305 }
306 
307 int
308 Vfs::alloc_fd(Ref_ptr<L4Re::Vfs::File> const &f) throw()
309 {
310  int fd = fds.alloc();
311  if (fd < 0)
312  return -EMFILE;
313 
314  if (f)
315  fds.set(fd, f);
316 
317  return fd;
318 }
319 
320 Ref_ptr<L4Re::Vfs::File>
321 Vfs::free_fd(int fd) throw()
322 {
323  Ref_ptr<L4Re::Vfs::File> f = fds.get(fd);
324 
325  if (!f)
326  return Ref_ptr<>::Nil;
327 
328  fds.free(fd);
329  return f;
330 }
331 
332 
333 Ref_ptr<L4Re::Vfs::File>
334 Vfs::get_root() throw()
335 {
336  return cxx::ref_ptr(&_root);
337 }
338 
339 Ref_ptr<L4Re::Vfs::File>
340 Vfs::get_cwd() throw()
341 {
342  return _cwd;
343 }
344 
345 void
346 Vfs::set_cwd(Ref_ptr<L4Re::Vfs::File> const &dir) throw()
347 {
348  // FIXME: check for is dir
349  if (dir)
350  _cwd = dir;
351 }
352 
353 Ref_ptr<L4Re::Vfs::File>
354 Vfs::get_file(int fd) throw()
355 {
356  return fds.get(fd);
357 }
358 
359 Ref_ptr<L4Re::Vfs::File>
360 Vfs::set_fd(int fd, Ref_ptr<L4Re::Vfs::File> const &f) throw()
361 {
362  Ref_ptr<L4Re::Vfs::File> old = fds.get(fd);
363  fds.set(fd, f);
364  return old;
365 }
366 
368 Vfs::cap_alloc() throw()
369 {
370  return L4Re::Core::cap_alloc();
371 }
372 
373 
374 
375 #define GET_FILE_DBG(fd, err) \
376  Ref_ptr<L4Re::Vfs::File> fi = fds.get(fd); \
377  if (!fi) \
378  { \
379  return -err; \
380  }
381 
382 #define GET_FILE(fd, err) \
383  Ref_ptr<L4Re::Vfs::File> fi = fds.get(fd); \
384  if (!fi) \
385  return -err;
386 
387 
388 int
389 Vfs::munmap(void *start, size_t len) L4_NOTHROW
390 {
391  using namespace L4;
392  using namespace L4Re;
393 
394  int err;
395  Cap<Dataspace> ds;
396  Cap<Rm> r = Env::env()->rm();
397 
398  while (1)
399  {
400  DEBUG_LOG(debug_mmap, {
401  outstring("DETACH: ");
402  outhex32(l4_addr_t(start));
403  outstring(" ");
404  outhex32(len);
405  outstring("\n");
406  });
407  err = r->detach(l4_addr_t(start), len, &ds, This_task);
408  if (err < 0)
409  return err;
410 
411  switch (err & Rm::Detach_result_mask)
412  {
413  case Rm::Split_ds:
414  return 0;
415  case Rm::Detached_ds:
416  if (ds.is_valid())
417  L4Re::Core::release_ds(ds);
418  break;
419  default:
420  break;
421  }
422 
423  if (!(err & Rm::Detach_again))
424  return 0;
425  }
426 }
427 
428 int
429 Vfs::alloc_ds(unsigned long size, L4::Cap<L4Re::Dataspace> *ds)
430 {
432 
433  if (!ds->is_valid())
434  return -ENOMEM;
435 
436  int err;
437  if ((err = Vfs_config::allocator()->alloc(size, *ds)) < 0)
438  return err;
439 
440  DEBUG_LOG(debug_mmap, {
441  outstring("ANON DS ALLOCATED: size=");
442  outhex32(size);
443  outstring(" cap=");
444  outhex32(ds->cap());
445  outstring("\n");
446  });
447 
448  return 0;
449 }
450 
451 int
452 Vfs::alloc_anon_mem(l4_umword_t size, L4::Cap<L4Re::Dataspace> *ds,
453  l4_addr_t *offset)
454 {
455 #ifdef USE_BIG_ANON_DS
456  enum
457  {
458  ANON_MEM_DS_POOL_SIZE = 256UL << 20, // size of a pool dataspace used for anon memory
459  ANON_MEM_MAX_SIZE = 32UL << 20, // chunk size that will be allocate a dataspace
460  };
461 #else
462  enum
463  {
464  ANON_MEM_DS_POOL_SIZE = 256UL << 20, // size of a pool dataspace used for anon memory
465  ANON_MEM_MAX_SIZE = 0UL << 20, // chunk size that will be allocate a dataspace
466  };
467 #endif
468 
469  if (size >= ANON_MEM_MAX_SIZE)
470  {
471  int err;
472  if ((err = alloc_ds(size, ds)) < 0)
473  return err;
474 
475  *offset = 0;
476 
477  if (!_early_oom)
478  return err;
479 
480  return (*ds)->allocate(0, size);
481  }
482 
483  if (!_anon_ds.is_valid() || _anon_offset + size >= ANON_MEM_DS_POOL_SIZE)
484  {
485  if (_anon_ds.is_valid())
486  L4Re::Core::release_ds(_anon_ds);
487 
488  int err;
489  if ((err = alloc_ds(ANON_MEM_DS_POOL_SIZE, ds)) < 0)
490  return err;
491 
492  _anon_offset = 0;
493  _anon_ds = *ds;
494  }
495  else
496  *ds = _anon_ds;
497 
498  if (_early_oom)
499  {
500  if (int err = (*ds)->allocate(_anon_offset, size))
501  return err;
502  }
503 
504  *offset = _anon_offset;
505  _anon_offset += size;
506  return 0;
507 }
508 
509 int
510 Vfs::mmap2(void *start, size_t len, int prot, int flags, int fd, off_t _offset,
511  void **resptr) L4_NOTHROW
512 {
513  using namespace L4Re;
514  off64_t offset = l4_trunc_page(_offset << 12);
515 
516  start = (void*)l4_trunc_page(l4_addr_t(start));
517  len = l4_round_page(len);
518  l4_umword_t size = (len + L4_PAGESIZE-1) & ~(L4_PAGESIZE-1);
519 
520  // special code to just reserve an area of the virtual address space
521  if (flags & 0x1000000)
522  {
523  int err;
524  L4::Cap<Rm> r = Env::env()->rm();
525  l4_addr_t area = (l4_addr_t)start;
526  err = r->reserve_area(&area, size, L4Re::Rm::Search_addr);
527  if (err < 0)
528  return err;
529  *resptr = (void*)area;
530  DEBUG_LOG(debug_mmap, {
531  outstring("MMAP reserved area: ");
532  outhex32(area);
533  outstring(" size=");
534  outhex32(size);
535  outstring("\n");
536  });
537  return 0;
538  }
539 
541  l4_addr_t anon_offset = 0;
542  unsigned rm_flags = 0;
543 
544  if (flags & (MAP_ANONYMOUS | MAP_PRIVATE))
545  {
546  rm_flags |= L4Re::Rm::Detach_free;
547 
548  int err = alloc_anon_mem(size, &ds, &anon_offset);
549  if (err)
550  return err;
551 
552  DEBUG_LOG(debug_mmap, {
553  outstring("USE ANON MEM: ");
554  outhex32(ds.cap());
555  outstring(" offs=");
556  outhex32(anon_offset);
557  outstring("\n");
558  });
559  }
560 
561  if (!(flags & MAP_ANONYMOUS))
562  {
563  Ref_ptr<L4Re::Vfs::File> fi = fds.get(fd);
564  if (!fi)
565  {
566  return -EBADF;
567  }
568 
569  L4::Cap<L4Re::Dataspace> fds = fi->data_space();
570 
571  if (!fds.is_valid())
572  {
573  return -EINVAL;
574  }
575 
576  if (size + offset > l4_round_page(fds->size()))
577  {
578  return -EINVAL;
579  }
580 
581  if (flags & MAP_PRIVATE)
582  {
583  DEBUG_LOG(debug_mmap, outstring("COW\n"););
584  ds->copy_in(anon_offset, fds, l4_trunc_page(offset), l4_round_page(size));
585  offset = anon_offset;
586  }
587  else
588  {
589  ds = fds;
590  }
591  }
592  else
593  offset = anon_offset;
594 
595 
596  if (!(flags & MAP_FIXED) && start == 0)
597  start = (void*)L4_PAGESIZE;
598 
599  int err;
600  char *data = (char *)start;
601  L4::Cap<Rm> r = Env::env()->rm();
602  l4_addr_t overmap_area = L4_INVALID_ADDR;
603 
604  if (flags & MAP_FIXED)
605  {
606  overmap_area = l4_addr_t(start);
607 
608  err = r->reserve_area(&overmap_area, size);
609  if (err < 0)
610  overmap_area = L4_INVALID_ADDR;
611 
612  rm_flags |= Rm::In_area;
613 
614  err = munmap(start, len);
615  if (err && err != -ENOENT)
616  return err;
617  }
618 
619  if (!(flags & MAP_FIXED)) rm_flags |= Rm::Search_addr;
620  if (!(prot & PROT_WRITE)) rm_flags |= Rm::Read_only;
621 
622  err = r->attach(&data, size, rm_flags,
623  L4::Ipc::make_cap(ds, (prot & PROT_WRITE)
625  : L4_CAP_FPAGE_RO),
626  offset);
627 
628  DEBUG_LOG(debug_mmap, {
629  outstring(" MAPPED: ");
630  outhex32(ds.cap());
631  outstring(" addr: ");
632  outhex32(l4_addr_t(data));
633  outstring(" bytes: ");
634  outhex32(size);
635  outstring(" offset: ");
636  outhex32(offset);
637  outstring(" err=");
638  outdec(err);
639  outstring("\n");
640  });
641 
642 
643  if (overmap_area != L4_INVALID_ADDR)
644  r->free_area(overmap_area);
645 
646  if (err < 0)
647  return err;
648 
649 
650  if (start && !data)
651  return -EINVAL;
652 
653  *resptr = data;
654 
655  return 0;
656 }
657 
658 namespace {
659  class Auto_area
660  {
661  public:
663  l4_addr_t a;
664 
665  explicit Auto_area(L4::Cap<L4Re::Rm> r, l4_addr_t a = L4_INVALID_ADDR)
666  : r(r), a(a) {}
667 
668  int reserve(l4_addr_t _a, l4_size_t sz, unsigned flags)
669  {
670  a = _a;
671  int e = r->reserve_area(&a, sz, flags);
672  if (e)
673  a = L4_INVALID_ADDR;
674  return e;
675  }
676 
677  void free()
678  {
679  if (a != L4_INVALID_ADDR)
680  {
681  r->free_area(a);
682  a = L4_INVALID_ADDR;
683  }
684  }
685 
686  ~Auto_area() { free(); }
687  };
688 }
689 
690 int
691 Vfs::mremap(void *old_addr, size_t old_size, size_t new_size, int flags,
692  void **new_addr) L4_NOTHROW
693 {
694  using namespace L4Re;
695 
696  DEBUG_LOG(debug_mmap, {
697  outstring("Mremap: addr=");
698  outhex32((l4_umword_t)old_addr);
699  outstring(" old_size=");
700  outhex32(old_size);
701  outstring(" new_size=");
702  outhex32(new_size);
703  outstring("\n");
704  });
705 
706  if (flags & MREMAP_FIXED && !(flags & MREMAP_MAYMOVE))
707  return -EINVAL;
708 
709  L4::Cap<Rm> r = Env::env()->rm();
710 
711  // sanitize input parameters to multiples of pages
712  l4_addr_t oa = l4_trunc_page((l4_addr_t)old_addr);
713  old_size = l4_round_page(old_size);
714  new_size = l4_round_page(new_size);
715 
716  l4_addr_t na;
717 
718  if (new_size < old_size)
719  {
720  *new_addr = old_addr;
721  return munmap((void*)(oa + new_size), old_size - new_size);
722  }
723 
724  if (new_size == old_size)
725  {
726  *new_addr = old_addr;
727  return 0;
728  }
729 
730  Auto_area area(r);
731 
732  if (!(flags & MREMAP_FIXED))
733  na = oa;
734  else
735  na = l4_trunc_page((l4_addr_t)new_addr);
736 
737  int err;
738 
739  // check if the current virtual memory area can be expanded
740  err = area.reserve(oa, new_size, 0);
741  if (err)
742  return err;
743 
744  l4_addr_t ta = oa + old_size;
745  unsigned long ts = new_size - old_size;
746  l4_addr_t toffs;
747  unsigned tflags;
749 
750  err = r->find(&ta, &ts, &toffs, &tflags, &tds);
751 
752  // there is enough space to expand the mapping in place
753  if (!(err == -ENOENT || (err == 0 && (tflags & Rm::In_area))))
754  {
755  if ((flags & (MREMAP_FIXED | MREMAP_MAYMOVE)) != MREMAP_MAYMOVE)
756  return -EINVAL;
757 
758  // free our old reserved area, used for blocking the old memory region
759  area.free();
760 
761  // move
762  err = area.reserve(0, new_size, Rm::Search_addr);
763  if (err)
764  return err;
765 
766  na = area.a;
767 
768  // move all the old regions to the new place ...
769  Auto_area block_area(r);
770  err = block_area.reserve(oa, old_size, 0);
771  if (err)
772  return err;
773 
774  while (1)
775  {
776  ta = oa;
777  ts = old_size;
778 
779  err = r->find(&ta, &ts, &toffs, &tflags, &tds);
780  if (err == -ENOENT || (err == 0 && (tflags & Rm::In_area)))
781  break;
782 
783  if (err)
784  return err;
785 
786  if (ta < oa)
787  {
788  toffs += oa - ta;
789  ts -= oa - ta;
790  ta = oa;
791  }
792 
793  l4_addr_t n = na + (ta - oa);
794  unsigned long max_s = old_size - (ta - oa);
795 
796  if (ts > max_s)
797  ts = max_s;
798 
799  err = r->attach(&n, ts, tflags | Rm::In_area,
800  L4::Ipc::make_cap(tds, (tflags & Rm::Read_only)
801  ? L4_CAP_FPAGE_RO
802  : L4_CAP_FPAGE_RW),
803  toffs);
804  if (err)
805  return err;
806 
807  err = r->detach(ta, ts, &tds, This_task, Rm::Detach_exact | Rm::Detach_keep);
808  if (err < 0)
809  return err;
810 
811  switch (err & Rm::Detach_result_mask)
812  {
813  case Rm::Split_ds:
814  break;
815  case Rm::Detached_ds:
816  if (tds.is_valid())
817  L4Re::Core::release_ds(tds);
818  break;
819  default:
820  break;
821  }
822  }
823  }
824 
825  err = alloc_anon_mem(new_size - old_size, &tds, &toffs);
826  if (err)
827  return err;
828 
829  *new_addr = (void *)na;
830  na = na + old_size;
831  err = r->attach(&na, new_size - old_size, Rm::In_area | Rm::Detach_free,
832  L4::Ipc::make_cap(tds, (tflags & Rm::Read_only)
833  ? L4_CAP_FPAGE_RO
834  : L4_CAP_FPAGE_RW),
835  toffs);
836 
837  return err;
838 }
839 
840 int
841 Vfs::mprotect(const void *a, size_t sz, int prot) L4_NOTHROW
842 {
843  (void)a;
844  (void)sz;
845  return (prot & PROT_WRITE) ? -1 : 0;
846 }
847 
848 int
849 Vfs::msync(void *, size_t, int) L4_NOTHROW
850 { return 0; }
851 
852 int
853 Vfs::madvise(void *, size_t, int) L4_NOTHROW
854 { return 0; }
855 
856 }
857 
858 void *__rtld_l4re_env_posix_vfs_ops;
859 extern void *l4re_env_posix_vfs_ops __attribute__((alias("__rtld_l4re_env_posix_vfs_ops"), visibility("default")));
860 
861 
862 #undef DEBUG_LOG
863 #undef GET_FILE_DBG
864 #undef GET_FILE
865 
L4::Cap< Log > log() const
Object-capability to the logging service.
Definition: env:130
unsigned int l4_size_t
Unsigned size type.
Definition: l4int.h:35
Read and interface specific &#39;W&#39; right for capability flex-pages.
Definition: __l4_fpage.h:176
Our C++ library.
Definition: arith:22
long reserve_area(l4_addr_t *start, unsigned long size, unsigned flags=0, unsigned char align=L4_PAGESHIFT) const
Reserve the given area in the region map.
Definition: rm:239
unsigned long size() const
Get size of a dataspace.
A reference-counting pointer with automatic cleanup.
Definition: ref_ptr:80
Interface for the POSIX backends for an application.
Definition: vfs.h:1063
long free_area(l4_addr_t addr)
Free an area from the region map.
Double-linked list of typed H_list_item_t elements.
Definition: hlist:256
Helper type to distinguish the oeprator new version that does not throw exceptions.
Definition: std_alloc:30
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition: consts.h:359
Capability allocator interface.
Definition: cap_alloc:40
L4 low-level kernel interface.
Cap< T > make_cap(L4::Cap< T > cap, unsigned rights)
Make an L4::Ipc::Cap<T> for the given capability and rights.
Definition: ipc_types:621
l4_addr_t l4_trunc_page(l4_addr_t address) L4_NOTHROW
Round an address down to the next lower page boundary.
Definition: consts.h:334
L4Re C++ Interfaces.
Definition: cmd_control:15
Search for a suitable address range.
Definition: rm:113
long copy_in(l4_addr_t dst_offs, L4::Ipc::Cap< Dataspace > src, l4_addr_t src_offs, unsigned long size)
Copy contents from another dataspace.
Environment interface.
Read right for capability flex-pages.
Definition: __l4_fpage.h:160
Interface for memory-like objects.
Definition: dataspace:59
#define L4_PAGESIZE
Minimal page size (in bytes).
Definition: consts.h:277
Region mapper interface.
static Env const * env()
Returns the initial environment for the current task.
Definition: env:100
int detach(l4_addr_t addr, L4::Cap< Dataspace > *mem, L4::Cap< L4::Task > const &task=This_task) const
Detach a region from the address space.
Definition: rm:497
l4_cap_idx_t cap() const
Return capability selector.
Definition: capability.h:51
_Cap_alloc & cap_alloc
Capability allocator.
Basic element type for a double-linked H_list.
Definition: hlist:33
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:52
Free the portion of the data space after detach.
Definition: rm:90
Invalid address.
Definition: consts.h:379
L4::Cap< void > alloc()
Allocated a new capability.
l4_cap_idx_t cap() const
Return capability selector.
Definition: kobject:79
Region map.
Definition: rm:69
bool is_valid() const
Test whether the capability is a valid capability index (i.e., not L4_INVALID_CAP).
Definition: capability.h:59
int find(l4_addr_t *addr, unsigned long *size, l4_addr_t *offset, unsigned *flags, L4::Cap< Dataspace > *m)
Find a region given an address and size.
Definition: rm:461
Dataspace interface.
unsigned long l4_addr_t
Address type.
Definition: l4int.h:45
long attach(l4_addr_t *start, unsigned long size, unsigned long flags, L4::Ipc::Cap< Dataspace > mem, l4_addr_t offs=0, unsigned char align=L4_PAGESHIFT) const
Attach a data space to a region.
Definition: rm_impl.h:43
Basic interface for an L4Re::Vfs file system.
Definition: vfs.h:867
#define L4_NOTHROW
Mark a function declaration and definition as never throwing an exception.
Definition: compiler.h:185