1 /* 2 * Copyright (c) 2015 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Antonio Huete <tuxillo@quantumachine.net> 6 * by Matthew Dillon <dillon@backplane.com> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 37 #include <assert.h> 38 #include <stdio.h> 39 #include <strings.h> 40 #include <string.h> 41 #include <stdlib.h> 42 #include <fcntl.h> 43 #include <errno.h> 44 #include <unistd.h> 45 46 #include "libhammer.h" 47 48 int 49 libhammer_pfs_get_snapshots(libhammer_fsinfo_t fip, libhammer_pfsinfo_t pip) 50 { 51 struct hammer_snapshot_data *snapdata = NULL; 52 struct hammer_ioc_snapshot snap; 53 libhammer_snapinfo_t sip; 54 libhammer_pfsinfo_t pfs0; 55 char *path = NULL; 56 int ret = 0; 57 int fd; 58 u_int i; 59 60 assert(pip != NULL); 61 assert(fip != NULL); 62 63 /* 64 * Still need a path to open so, when not mounted, try 65 * to figure out the PFS path access in order to open(2) 66 * Note that this will fail for slave PFS that were created 67 * with pfs-slave directive since they don't have any transaction 68 * recorded and nlookup can't find them. For those we simply 69 * return the error in the head structure of libhammer_pfsinfo_t 70 * for the caller to handle the situation. 71 */ 72 pfs0 = libhammer_get_first_pfs(fip); 73 if (pfs0 == NULL) 74 return -1; 75 76 if (pip->mountedon == NULL) 77 libhammer_pfs_canonical_path(pfs0->mountedon, pip, &path); 78 else 79 path = strdup(pip->mountedon); 80 81 if (path == NULL || (fd = open(path, O_RDONLY)) < 0) { 82 pip->head.error = errno; 83 ret = -1; 84 goto out; 85 } 86 87 bzero(&snap, sizeof(snap)); 88 89 /* 90 * Loop while there are snapshots returned from the ioctl(2) call. 91 * 92 * For more information on how the snapshots are returned 93 * to userland please check sys/vfs/hammer/hammer_ioctl.c 94 */ 95 do { 96 if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snap) < 0) { 97 pip->head.error = errno; 98 ret = -1; 99 close(fd); 100 goto out; 101 } 102 for (i = 0; i < snap.count; i++) { 103 snapdata = &snap.snaps[i]; 104 sip = _libhammer_malloc(sizeof(*sip)); 105 sip->tid = snapdata->tid; 106 sip->ts = snapdata->ts; 107 if (strlen(snapdata->label)) 108 sprintf(sip->label, "%s", snapdata->label); 109 else 110 sip->label[0] = '\0'; 111 TAILQ_INSERT_TAIL(&pip->list_snap, sip, entries); 112 pip->snapcount++; 113 } 114 } while (snap.head.error == 0 && snap.count); 115 close(fd); 116 117 out: 118 if (path) 119 free(path); 120 121 return (ret); 122 } 123 124 void 125 libhammer_pfs_free_snapshots(libhammer_pfsinfo_t pip) 126 { 127 struct libhammer_snapinfo *si; 128 129 while(!TAILQ_EMPTY(&pip->list_snap)) { 130 si = TAILQ_FIRST(&pip->list_snap); 131 TAILQ_REMOVE(&pip->list_snap, si, entries); 132 free(si); 133 } 134 } 135