cow_user.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. #include <stddef.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. /* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines
  5. * that.
  6. */
  7. #include <unistd.h>
  8. #include <byteswap.h>
  9. #include <sys/time.h>
  10. #include <sys/param.h>
  11. #include <sys/user.h>
  12. #include "os.h"
  13. #include "cow.h"
  14. #include "cow_sys.h"
  15. #define PATH_LEN_V1 256
  16. typedef __u32 time32_t;
  17. struct cow_header_v1 {
  18. __s32 magic;
  19. __s32 version;
  20. char backing_file[PATH_LEN_V1];
  21. time32_t mtime;
  22. __u64 size;
  23. __s32 sectorsize;
  24. } __attribute__((packed));
  25. /* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
  26. * case other systems have different values for MAXPATHLEN.
  27. *
  28. * The same must hold for V2 - we want file format compatibility, not anything
  29. * else.
  30. */
  31. #define PATH_LEN_V3 4096
  32. #define PATH_LEN_V2 PATH_LEN_V3
  33. struct cow_header_v2 {
  34. __u32 magic;
  35. __u32 version;
  36. char backing_file[PATH_LEN_V2];
  37. time32_t mtime;
  38. __u64 size;
  39. __s32 sectorsize;
  40. } __attribute__((packed));
  41. /* Changes from V2 -
  42. * PATH_LEN_V3 as described above
  43. * Explicitly specify field bit lengths for systems with different
  44. * lengths for the usual C types. Not sure whether char or
  45. * time_t should be changed, this can be changed later without
  46. * breaking compatibility
  47. * Add alignment field so that different alignments can be used for the
  48. * bitmap and data
  49. * Add cow_format field to allow for the possibility of different ways
  50. * of specifying the COW blocks. For now, the only value is 0,
  51. * for the traditional COW bitmap.
  52. * Move the backing_file field to the end of the header. This allows
  53. * for the possibility of expanding it into the padding required
  54. * by the bitmap alignment.
  55. * The bitmap and data portions of the file will be aligned as specified
  56. * by the alignment field. This is to allow COW files to be
  57. * put on devices with restrictions on access alignments, such as
  58. * /dev/raw, with a 512 byte alignment restriction. This also
  59. * allows the data to be more aligned more strictly than on
  60. * sector boundaries. This is needed for ubd-mmap, which needs
  61. * the data to be page aligned.
  62. * Fixed (finally!) the rounding bug
  63. */
  64. /* Until Dec2005, __attribute__((packed)) was left out from the below
  65. * definition, leading on 64-bit systems to 4 bytes of padding after mtime, to
  66. * align size to 8-byte alignment. This shifted all fields above (no padding
  67. * was present on 32-bit, no other padding was added).
  68. *
  69. * However, this _can be detected_: it means that cow_format (always 0 until
  70. * now) is shifted onto the first 4 bytes of backing_file, where it is otherwise
  71. * impossible to find 4 zeros. -bb */
  72. struct cow_header_v3 {
  73. __u32 magic;
  74. __u32 version;
  75. __u32 mtime;
  76. __u64 size;
  77. __u32 sectorsize;
  78. __u32 alignment;
  79. __u32 cow_format;
  80. char backing_file[PATH_LEN_V3];
  81. } __attribute__((packed));
  82. /* This is the broken layout used by some 64-bit binaries. */
  83. struct cow_header_v3_broken {
  84. __u32 magic;
  85. __u32 version;
  86. __s64 mtime;
  87. __u64 size;
  88. __u32 sectorsize;
  89. __u32 alignment;
  90. __u32 cow_format;
  91. char backing_file[PATH_LEN_V3];
  92. } __attribute__((packed));
  93. /* COW format definitions - for now, we have only the usual COW bitmap */
  94. #define COW_BITMAP 0
  95. union cow_header {
  96. struct cow_header_v1 v1;
  97. struct cow_header_v2 v2;
  98. struct cow_header_v3 v3;
  99. struct cow_header_v3_broken v3_b;
  100. };
  101. #define COW_MAGIC 0x4f4f4f4d /* MOOO */
  102. #define COW_VERSION 3
  103. #define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
  104. #define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
  105. void cow_sizes(int version, __u64 size, int sectorsize, int align,
  106. int bitmap_offset, unsigned long *bitmap_len_out,
  107. int *data_offset_out)
  108. {
  109. if(version < 3){
  110. *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
  111. *data_offset_out = bitmap_offset + *bitmap_len_out;
  112. *data_offset_out = (*data_offset_out + sectorsize - 1) /
  113. sectorsize;
  114. *data_offset_out *= sectorsize;
  115. }
  116. else {
  117. *bitmap_len_out = DIV_ROUND(size, sectorsize);
  118. *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8);
  119. *data_offset_out = bitmap_offset + *bitmap_len_out;
  120. *data_offset_out = ROUND_UP(*data_offset_out, align);
  121. }
  122. }
  123. static int absolutize(char *to, int size, char *from)
  124. {
  125. char save_cwd[256], *slash;
  126. int remaining;
  127. if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
  128. cow_printf("absolutize : unable to get cwd - errno = %d\n",
  129. errno);
  130. return(-1);
  131. }
  132. slash = strrchr(from, '/');
  133. if(slash != NULL){
  134. *slash = '\0';
  135. if(chdir(from)){
  136. *slash = '/';
  137. cow_printf("absolutize : Can't cd to '%s' - "
  138. "errno = %d\n", from, errno);
  139. return(-1);
  140. }
  141. *slash = '/';
  142. if(getcwd(to, size) == NULL){
  143. cow_printf("absolutize : unable to get cwd of '%s' - "
  144. "errno = %d\n", from, errno);
  145. return(-1);
  146. }
  147. remaining = size - strlen(to);
  148. if(strlen(slash) + 1 > remaining){
  149. cow_printf("absolutize : unable to fit '%s' into %d "
  150. "chars\n", from, size);
  151. return(-1);
  152. }
  153. strcat(to, slash);
  154. }
  155. else {
  156. if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
  157. cow_printf("absolutize : unable to fit '%s' into %d "
  158. "chars\n", from, size);
  159. return(-1);
  160. }
  161. strcpy(to, save_cwd);
  162. strcat(to, "/");
  163. strcat(to, from);
  164. }
  165. chdir(save_cwd);
  166. return(0);
  167. }
  168. int write_cow_header(char *cow_file, int fd, char *backing_file,
  169. int sectorsize, int alignment, unsigned long long *size)
  170. {
  171. struct cow_header_v3 *header;
  172. unsigned long modtime;
  173. int err;
  174. err = cow_seek_file(fd, 0);
  175. if(err < 0){
  176. cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
  177. goto out;
  178. }
  179. err = -ENOMEM;
  180. header = cow_malloc(sizeof(*header));
  181. if(header == NULL){
  182. cow_printf("write_cow_header - failed to allocate COW V3 header\n");
  183. goto out;
  184. }
  185. header->magic = htonl(COW_MAGIC);
  186. header->version = htonl(COW_VERSION);
  187. err = -EINVAL;
  188. if(strlen(backing_file) > sizeof(header->backing_file) - 1){
  189. /* Below, %zd is for a size_t value */
  190. cow_printf("Backing file name \"%s\" is too long - names are "
  191. "limited to %zd characters\n", backing_file,
  192. sizeof(header->backing_file) - 1);
  193. goto out_free;
  194. }
  195. if(absolutize(header->backing_file, sizeof(header->backing_file),
  196. backing_file))
  197. goto out_free;
  198. err = os_file_modtime(header->backing_file, &modtime);
  199. if(err < 0){
  200. cow_printf("write_cow_header - backing file '%s' mtime "
  201. "request failed, err = %d\n", header->backing_file,
  202. -err);
  203. goto out_free;
  204. }
  205. err = cow_file_size(header->backing_file, size);
  206. if(err < 0){
  207. cow_printf("write_cow_header - couldn't get size of "
  208. "backing file '%s', err = %d\n",
  209. header->backing_file, -err);
  210. goto out_free;
  211. }
  212. header->mtime = htonl(modtime);
  213. header->size = htonll(*size);
  214. header->sectorsize = htonl(sectorsize);
  215. header->alignment = htonl(alignment);
  216. header->cow_format = COW_BITMAP;
  217. err = cow_write_file(fd, header, sizeof(*header));
  218. if(err != sizeof(*header)){
  219. cow_printf("write_cow_header - write of header to "
  220. "new COW file '%s' failed, err = %d\n", cow_file,
  221. -err);
  222. goto out_free;
  223. }
  224. err = 0;
  225. out_free:
  226. cow_free(header);
  227. out:
  228. return(err);
  229. }
  230. int file_reader(__u64 offset, char *buf, int len, void *arg)
  231. {
  232. int fd = *((int *) arg);
  233. return(pread(fd, buf, len, offset));
  234. }
  235. /* XXX Need to sanity-check the values read from the header */
  236. int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
  237. __u32 *version_out, char **backing_file_out,
  238. time_t *mtime_out, unsigned long long *size_out,
  239. int *sectorsize_out, __u32 *align_out,
  240. int *bitmap_offset_out)
  241. {
  242. union cow_header *header;
  243. char *file;
  244. int err, n;
  245. unsigned long version, magic;
  246. header = cow_malloc(sizeof(*header));
  247. if(header == NULL){
  248. cow_printf("read_cow_header - Failed to allocate header\n");
  249. return(-ENOMEM);
  250. }
  251. err = -EINVAL;
  252. n = (*reader)(0, (char *) header, sizeof(*header), arg);
  253. if(n < offsetof(typeof(header->v1), backing_file)){
  254. cow_printf("read_cow_header - short header\n");
  255. goto out;
  256. }
  257. magic = header->v1.magic;
  258. if(magic == COW_MAGIC) {
  259. version = header->v1.version;
  260. }
  261. else if(magic == ntohl(COW_MAGIC)){
  262. version = ntohl(header->v1.version);
  263. }
  264. /* No error printed because the non-COW case comes through here */
  265. else goto out;
  266. *version_out = version;
  267. if(version == 1){
  268. if(n < sizeof(header->v1)){
  269. cow_printf("read_cow_header - failed to read V1 "
  270. "header\n");
  271. goto out;
  272. }
  273. *mtime_out = header->v1.mtime;
  274. *size_out = header->v1.size;
  275. *sectorsize_out = header->v1.sectorsize;
  276. *bitmap_offset_out = sizeof(header->v1);
  277. *align_out = *sectorsize_out;
  278. file = header->v1.backing_file;
  279. }
  280. else if(version == 2){
  281. if(n < sizeof(header->v2)){
  282. cow_printf("read_cow_header - failed to read V2 "
  283. "header\n");
  284. goto out;
  285. }
  286. *mtime_out = ntohl(header->v2.mtime);
  287. *size_out = ntohll(header->v2.size);
  288. *sectorsize_out = ntohl(header->v2.sectorsize);
  289. *bitmap_offset_out = sizeof(header->v2);
  290. *align_out = *sectorsize_out;
  291. file = header->v2.backing_file;
  292. }
  293. /* This is very subtle - see above at union cow_header definition */
  294. else if(version == 3 && (*((int*)header->v3.backing_file) != 0)){
  295. if(n < sizeof(header->v3)){
  296. cow_printf("read_cow_header - failed to read V3 "
  297. "header\n");
  298. goto out;
  299. }
  300. *mtime_out = ntohl(header->v3.mtime);
  301. *size_out = ntohll(header->v3.size);
  302. *sectorsize_out = ntohl(header->v3.sectorsize);
  303. *align_out = ntohl(header->v3.alignment);
  304. if (*align_out == 0) {
  305. cow_printf("read_cow_header - invalid COW header, "
  306. "align == 0\n");
  307. }
  308. *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
  309. file = header->v3.backing_file;
  310. }
  311. else if(version == 3){
  312. cow_printf("read_cow_header - broken V3 file with"
  313. " 64-bit layout - recovering content.\n");
  314. if(n < sizeof(header->v3_b)){
  315. cow_printf("read_cow_header - failed to read V3 "
  316. "header\n");
  317. goto out;
  318. }
  319. /* this was used until Dec2005 - 64bits are needed to represent
  320. * 2038+. I.e. we can safely do this truncating cast.
  321. *
  322. * Additionally, we must use ntohl() instead of ntohll(), since
  323. * the program used to use the former (tested - I got mtime
  324. * mismatch "0 vs whatever").
  325. *
  326. * Ever heard about bug-to-bug-compatibility ? ;-) */
  327. *mtime_out = (time32_t) ntohl(header->v3_b.mtime);
  328. *size_out = ntohll(header->v3_b.size);
  329. *sectorsize_out = ntohl(header->v3_b.sectorsize);
  330. *align_out = ntohl(header->v3_b.alignment);
  331. if (*align_out == 0) {
  332. cow_printf("read_cow_header - invalid COW header, "
  333. "align == 0\n");
  334. }
  335. *bitmap_offset_out = ROUND_UP(sizeof(header->v3_b), *align_out);
  336. file = header->v3_b.backing_file;
  337. }
  338. else {
  339. cow_printf("read_cow_header - invalid COW version\n");
  340. goto out;
  341. }
  342. err = -ENOMEM;
  343. *backing_file_out = cow_strdup(file);
  344. if(*backing_file_out == NULL){
  345. cow_printf("read_cow_header - failed to allocate backing "
  346. "file\n");
  347. goto out;
  348. }
  349. err = 0;
  350. out:
  351. cow_free(header);
  352. return(err);
  353. }
  354. int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
  355. int alignment, int *bitmap_offset_out,
  356. unsigned long *bitmap_len_out, int *data_offset_out)
  357. {
  358. unsigned long long size, offset;
  359. char zero = 0;
  360. int err;
  361. err = write_cow_header(cow_file, fd, backing_file, sectorsize,
  362. alignment, &size);
  363. if(err)
  364. goto out;
  365. *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
  366. cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
  367. bitmap_len_out, data_offset_out);
  368. offset = *data_offset_out + size - sizeof(zero);
  369. err = cow_seek_file(fd, offset);
  370. if(err < 0){
  371. cow_printf("cow bitmap lseek failed : err = %d\n", -err);
  372. goto out;
  373. }
  374. /* does not really matter how much we write it is just to set EOF
  375. * this also sets the entire COW bitmap
  376. * to zero without having to allocate it
  377. */
  378. err = cow_write_file(fd, &zero, sizeof(zero));
  379. if(err != sizeof(zero)){
  380. cow_printf("Write of bitmap to new COW file '%s' failed, "
  381. "err = %d\n", cow_file, -err);
  382. if (err >= 0)
  383. err = -EINVAL;
  384. goto out;
  385. }
  386. return(0);
  387. out:
  388. return(err);
  389. }
  390. /*
  391. * ---------------------------------------------------------------------------
  392. * Local variables:
  393. * c-file-style: "linux"
  394. * End:
  395. */