1 /* 2 * Copyright (C) 2014 John Crispin <blogic@openwrt.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License version 2.1 6 * as published by the Free Software Foundation 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include <sys/types.h> 15 #include <sys/stat.h> 16 #include <sys/mount.h> 17 #include <sys/wait.h> 18 19 #include <errno.h> 20 #include <stdio.h> 21 #include <unistd.h> 22 #include <string.h> 23 24 #include "libfstools.h" 25 26 /* this is a raw syscall - man 2 pivot_root */ 27 extern int pivot_root(const char *new_root, const char *put_old); 28 29 /** 30 * mount_move - move mounted point to the new location 31 * 32 * @oldroot: directory that is current location of mount point 33 * @newroot: new directory for the mount point 34 */ 35 int 36 mount_move(const char *oldroot, const char *newroot, const char *dir) 37 { 38 #ifndef MS_MOVE 39 #define MS_MOVE (1 << 13) 40 #endif 41 struct stat s; 42 char olddir[64]; 43 char newdir[64]; 44 int ret; 45 46 snprintf(olddir, sizeof(olddir), "%s%s", oldroot, dir); 47 snprintf(newdir, sizeof(newdir), "%s%s", newroot, dir); 48 49 if (stat(olddir, &s) || !S_ISDIR(s.st_mode)) 50 return -1; 51 52 if (stat(newdir, &s) || !S_ISDIR(s.st_mode)) 53 return -1; 54 55 ret = mount(olddir, newdir, NULL, MS_NOATIME | MS_MOVE, NULL); 56 57 /* if (ret) 58 ULOG_ERR("failed %s %s: %m\n", olddir, newdir);*/ 59 60 return ret; 61 } 62 63 int 64 pivot(char *new, char *old) 65 { 66 char pivotdir[64]; 67 int ret; 68 69 if (mount_move("", new, "/proc")) 70 return -1; 71 72 snprintf(pivotdir, sizeof(pivotdir), "%s%s", new, old); 73 74 ret = pivot_root(new, pivotdir); 75 76 if (ret < 0) { 77 ULOG_ERR("pivot_root failed %s %s: %m\n", new, pivotdir); 78 return -1; 79 } 80 81 mount_move(old, "", "/dev"); 82 mount_move(old, "", "/tmp"); 83 mount_move(old, "", "/sys"); 84 mount_move(old, "", "/overlay"); 85 86 return 0; 87 } 88 89 /** 90 * fopivot - switch to overlay using passed dir as upper one 91 * 92 * @rw_root: writable directory that will be used as upper dir 93 * @ro_root: directory where old root will be put 94 */ 95 int 96 fopivot(char *rw_root, char *ro_root) 97 { 98 char overlay[64], mount_options[64], upperdir[64], workdir[64], upgrade[64], upgrade_dest[64]; 99 struct stat st; 100 101 if (find_filesystem("overlay")) { 102 ULOG_ERR("BUG: no suitable fs found\n"); 103 return -1; 104 } 105 106 snprintf(overlay, sizeof(overlay), "overlayfs:%s", rw_root); 107 snprintf(upperdir, sizeof(upperdir), "%s/upper", rw_root); 108 snprintf(workdir, sizeof(workdir), "%s/work", rw_root); 109 snprintf(upgrade, sizeof(upgrade), "%s/sysupgrade.tgz", rw_root); 110 snprintf(upgrade_dest, sizeof(upgrade_dest), "%s/sysupgrade.tgz", upperdir); 111 snprintf(mount_options, sizeof(mount_options), "lowerdir=/,upperdir=%s,workdir=%s", 112 upperdir, workdir); 113 114 /* 115 * Overlay FS v23 and later requires both a upper and 116 * a work directory, both on the same filesystem, but 117 * not part of the same subtree. 118 * We can't really deal with these constraints without 119 * creating two new subdirectories in /overlay. 120 */ 121 if (mkdir(upperdir, 0755) == -1 && errno != EEXIST) 122 return -1; 123 124 if (mkdir(workdir, 0755) == -1 && errno != EEXIST) 125 return -1; 126 127 if (stat(upgrade, &st) == 0) 128 rename(upgrade, upgrade_dest); 129 130 if (mount(overlay, "/mnt", "overlay", MS_NOATIME, mount_options)) { 131 ULOG_ERR("mount failed: %m, options %s\n", mount_options); 132 return -1; 133 } 134 135 return pivot("/mnt", ro_root); 136 } 137 138 /** 139 * ramoverlay - use RAM to store filesystem changes on top of RO root 140 */ 141 int 142 ramoverlay(void) 143 { 144 mkdir("/tmp/root", 0755); 145 mount("tmpfs", "/tmp/root", "tmpfs", MS_NOATIME, "mode=0755"); 146 147 return fopivot("/tmp/root", "/rom"); 148 } 149
This page was automatically generated by LXR 0.3.1. • OpenWrt