1cb7575e6SAntonio Huete Jimenez /* 2cb7575e6SAntonio Huete Jimenez * Copyright (c) 2011 The DragonFly Project. All rights reserved. 3cb7575e6SAntonio Huete Jimenez * 4cb7575e6SAntonio Huete Jimenez * This code is derived from software contributed to The DragonFly Project 5cb7575e6SAntonio Huete Jimenez * by Antonio Huete <tuxillo@quantumachine.net> 6cb7575e6SAntonio Huete Jimenez * 7cb7575e6SAntonio Huete Jimenez * Redistribution and use in source and binary forms, with or without 8cb7575e6SAntonio Huete Jimenez * modification, are permitted provided that the following conditions 9cb7575e6SAntonio Huete Jimenez * are met: 10cb7575e6SAntonio Huete Jimenez * 11cb7575e6SAntonio Huete Jimenez * 1. Redistributions of source code must retain the above copyright 12cb7575e6SAntonio Huete Jimenez * notice, this list of conditions and the following disclaimer. 13cb7575e6SAntonio Huete Jimenez * 2. Redistributions in binary form must reproduce the above copyright 14cb7575e6SAntonio Huete Jimenez * notice, this list of conditions and the following disclaimer in 15cb7575e6SAntonio Huete Jimenez * the documentation and/or other materials provided with the 16cb7575e6SAntonio Huete Jimenez * distribution. 17cb7575e6SAntonio Huete Jimenez * 3. Neither the name of The DragonFly Project nor the names of its 18cb7575e6SAntonio Huete Jimenez * contributors may be used to endorse or promote products derived 19cb7575e6SAntonio Huete Jimenez * from this software without specific, prior written permission. 20cb7575e6SAntonio Huete Jimenez * 21cb7575e6SAntonio Huete Jimenez * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22cb7575e6SAntonio Huete Jimenez * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23cb7575e6SAntonio Huete Jimenez * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24cb7575e6SAntonio Huete Jimenez * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25cb7575e6SAntonio Huete Jimenez * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26cb7575e6SAntonio Huete Jimenez * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27cb7575e6SAntonio Huete Jimenez * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28cb7575e6SAntonio Huete Jimenez * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29cb7575e6SAntonio Huete Jimenez * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30cb7575e6SAntonio Huete Jimenez * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31cb7575e6SAntonio Huete Jimenez * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32cb7575e6SAntonio Huete Jimenez * SUCH DAMAGE. 33cb7575e6SAntonio Huete Jimenez */ 34c8fec8afSAntonio Huete Jimenez 35cb7575e6SAntonio Huete Jimenez #include <dirent.h> 36cb7575e6SAntonio Huete Jimenez #include <err.h> 37cb7575e6SAntonio Huete Jimenez #include <errno.h> 38cb7575e6SAntonio Huete Jimenez #include <fcntl.h> 39cb7575e6SAntonio Huete Jimenez #include <stdio.h> 40cb7575e6SAntonio Huete Jimenez #include <stdlib.h> 41cb7575e6SAntonio Huete Jimenez #include <string.h> 42cb7575e6SAntonio Huete Jimenez #include <sys/param.h> 43cb7575e6SAntonio Huete Jimenez #include <sys/stat.h> 44cb7575e6SAntonio Huete Jimenez #include <unistd.h> 45cb7575e6SAntonio Huete Jimenez 463729b417SAntonio Huete Jimenez #include "libhammer.h" 47cb7575e6SAntonio Huete Jimenez 48cb7575e6SAntonio Huete Jimenez static u_int32_t count_snapshots(u_int32_t, char *, char *, int *); 49cb7575e6SAntonio Huete Jimenez 50cb7575e6SAntonio Huete Jimenez libhammer_volinfo_t 51cb7575e6SAntonio Huete Jimenez libhammer_get_volinfo(const char *path) 52cb7575e6SAntonio Huete Jimenez { 53cb7575e6SAntonio Huete Jimenez struct hammer_pseudofs_data *pfs_od; 54*431893caSAntonio Huete Jimenez struct hammer_ioc_pfs_iterate pi; 55cb7575e6SAntonio Huete Jimenez struct hammer_ioc_info info; 56cb7575e6SAntonio Huete Jimenez libhammer_pfsinfo_t pfstmp; 57cb7575e6SAntonio Huete Jimenez libhammer_volinfo_t hvi; 58*431893caSAntonio Huete Jimenez int error = 0; 59cb7575e6SAntonio Huete Jimenez int fd; 60cb7575e6SAntonio Huete Jimenez 61cb7575e6SAntonio Huete Jimenez if ((fd = open(path, O_RDONLY)) < 0) 62c8fec8afSAntonio Huete Jimenez return NULL; 63cb7575e6SAntonio Huete Jimenez 64c8fec8afSAntonio Huete Jimenez hvi = _libhammer_malloc(sizeof(*hvi)); 65c8fec8afSAntonio Huete Jimenez TAILQ_INIT(&hvi->list_pseudo); 66c8fec8afSAntonio Huete Jimenez if ((ioctl(fd, HAMMERIOC_GET_INFO, &info)) < 0) { 67c8fec8afSAntonio Huete Jimenez libhammer_free_volinfo(hvi); 68c8fec8afSAntonio Huete Jimenez close(fd); 69c8fec8afSAntonio Huete Jimenez return NULL; 70c8fec8afSAntonio Huete Jimenez } 71cb7575e6SAntonio Huete Jimenez 72cb7575e6SAntonio Huete Jimenez /* Fill volume information */ 73cb7575e6SAntonio Huete Jimenez snprintf(hvi->vol_name, TXTLEN, "%s", info.vol_name); 74cb7575e6SAntonio Huete Jimenez hvi->vol_fsid = info.vol_fsid; 75cb7575e6SAntonio Huete Jimenez hvi->version = info.version; 76cb7575e6SAntonio Huete Jimenez hvi->nvolumes = info.nvolumes; 77925016b9SAntonio Huete Jimenez hvi->inodes = info.inodes; 78cb7575e6SAntonio Huete Jimenez hvi->bigblocks = info.bigblocks; 79e2fb4261SAntonio Huete Jimenez hvi->freebigblocks = info.freebigblocks; 80cb7575e6SAntonio Huete Jimenez hvi->rsvbigblocks = info.rsvbigblocks; 81cb7575e6SAntonio Huete Jimenez 82*431893caSAntonio Huete Jimenez bzero(&pi, sizeof(pi)); 83*431893caSAntonio Huete Jimenez pi.ondisk = _libhammer_malloc(sizeof(*pfs_od)); 84*431893caSAntonio Huete Jimenez while(error == 0) { 85*431893caSAntonio Huete Jimenez error = ioctl(fd, HAMMERIOC_PFS_ITERATE, &pi); 86*431893caSAntonio Huete Jimenez if (error == 0 && 87*431893caSAntonio Huete Jimenez ((pi.head.flags & HAMMER_PFSD_DELETED) == 0)) { 88c8fec8afSAntonio Huete Jimenez /* 89c8fec8afSAntonio Huete Jimenez * XXX - In the case the path passed is on PFS#0 but it 90c8fec8afSAntonio Huete Jimenez * is not the mountpoint itself, it could produce a 91c8fec8afSAntonio Huete Jimenez * wrong type of PFS. 92cb7575e6SAntonio Huete Jimenez */ 93c8fec8afSAntonio Huete Jimenez pfstmp = _libhammer_malloc(sizeof(*pfstmp)); 94*431893caSAntonio Huete Jimenez pfs_od = pi.ondisk; 95c8fec8afSAntonio Huete Jimenez pfstmp->ismaster = 96c8fec8afSAntonio Huete Jimenez (pfs_od->mirror_flags & HAMMER_PFSD_SLAVE) ? 0 : 1; 97cb7575e6SAntonio Huete Jimenez 98*431893caSAntonio Huete Jimenez if (pi.pos == 0) 99cb7575e6SAntonio Huete Jimenez pfstmp->mountedon = strdup(path); 100cb7575e6SAntonio Huete Jimenez else 101c8fec8afSAntonio Huete Jimenez pfstmp->mountedon = 102*431893caSAntonio Huete Jimenez libhammer_find_pfs_mount(pi.pos, 103cb7575e6SAntonio Huete Jimenez hvi->vol_fsid, pfstmp->ismaster); 104cb7575e6SAntonio Huete Jimenez /* 105cb7575e6SAntonio Huete Jimenez * Fill in structs used in the library. We don't rely on 106cb7575e6SAntonio Huete Jimenez * HAMMER own struct but we do fill our own. 107cb7575e6SAntonio Huete Jimenez */ 108*431893caSAntonio Huete Jimenez pfstmp->version = hvi->version; 109*431893caSAntonio Huete Jimenez pfstmp->pfs_id = pi.pos; 110cb7575e6SAntonio Huete Jimenez pfstmp->mirror_flags = pfs_od->mirror_flags; 111cb7575e6SAntonio Huete Jimenez pfstmp->snapcount = count_snapshots(hvi->version, 112c8fec8afSAntonio Huete Jimenez pfstmp->snapshots, pfstmp->mountedon, 113c8fec8afSAntonio Huete Jimenez &pfstmp->head.error); 114cb7575e6SAntonio Huete Jimenez 115cb7575e6SAntonio Huete Jimenez TAILQ_INSERT_TAIL(&hvi->list_pseudo, pfstmp, entries); 116cb7575e6SAntonio Huete Jimenez } 117*431893caSAntonio Huete Jimenez pi.pos++; 118cb7575e6SAntonio Huete Jimenez } 119*431893caSAntonio Huete Jimenez free(pi.ondisk); 120*431893caSAntonio Huete Jimenez 121cb7575e6SAntonio Huete Jimenez close (fd); 122cb7575e6SAntonio Huete Jimenez 123cb7575e6SAntonio Huete Jimenez return (hvi); 124cb7575e6SAntonio Huete Jimenez } 125cb7575e6SAntonio Huete Jimenez 126cb7575e6SAntonio Huete Jimenez void 127cb7575e6SAntonio Huete Jimenez libhammer_free_volinfo(libhammer_volinfo_t volinfo) 128cb7575e6SAntonio Huete Jimenez { 129cb7575e6SAntonio Huete Jimenez struct libhammer_pfsinfo *pfstmp; 130cb7575e6SAntonio Huete Jimenez 131cb7575e6SAntonio Huete Jimenez while(!TAILQ_EMPTY(&volinfo->list_pseudo)) { 132cb7575e6SAntonio Huete Jimenez pfstmp = TAILQ_FIRST(&volinfo->list_pseudo); 133cb7575e6SAntonio Huete Jimenez free(pfstmp->mountedon); 134cb7575e6SAntonio Huete Jimenez TAILQ_REMOVE(&volinfo->list_pseudo, pfstmp, entries); 135cb7575e6SAntonio Huete Jimenez free(pfstmp); 136cb7575e6SAntonio Huete Jimenez } 137cb7575e6SAntonio Huete Jimenez free(volinfo); 138cb7575e6SAntonio Huete Jimenez } 139cb7575e6SAntonio Huete Jimenez 140cb7575e6SAntonio Huete Jimenez static u_int32_t 141c8fec8afSAntonio Huete Jimenez count_snapshots(u_int32_t version, char *pfs_snapshots, char *mountedon, 142c8fec8afSAntonio Huete Jimenez int *errorp) 143cb7575e6SAntonio Huete Jimenez { 144cb7575e6SAntonio Huete Jimenez struct hammer_ioc_snapshot snapinfo; 145cb7575e6SAntonio Huete Jimenez char *snapshots_path, *fpath; 146cb7575e6SAntonio Huete Jimenez struct dirent *den; 147cb7575e6SAntonio Huete Jimenez struct stat st; 148cb7575e6SAntonio Huete Jimenez DIR *dir; 149cb7575e6SAntonio Huete Jimenez u_int32_t snapshot_count; 150cb7575e6SAntonio Huete Jimenez int fd; 151cb7575e6SAntonio Huete Jimenez 152cb7575e6SAntonio Huete Jimenez snapshot_count = 0; 153cb7575e6SAntonio Huete Jimenez 154cb7575e6SAntonio Huete Jimenez bzero(&snapinfo, sizeof(struct hammer_ioc_snapshot)); 155cb7575e6SAntonio Huete Jimenez 156cb7575e6SAntonio Huete Jimenez fd = open(mountedon, O_RDONLY); 157cb7575e6SAntonio Huete Jimenez if (fd < 0) { 158cb7575e6SAntonio Huete Jimenez *errorp = errno; 159cb7575e6SAntonio Huete Jimenez return 0; 160cb7575e6SAntonio Huete Jimenez } 161cb7575e6SAntonio Huete Jimenez 162cb7575e6SAntonio Huete Jimenez if (version < 3) { 163cb7575e6SAntonio Huete Jimenez /* 164cb7575e6SAntonio Huete Jimenez * old style: count the number of softlinks in the snapshots dir 165cb7575e6SAntonio Huete Jimenez */ 166cb7575e6SAntonio Huete Jimenez if (pfs_snapshots[0]) 167cb7575e6SAntonio Huete Jimenez snapshots_path = pfs_snapshots; 168cb7575e6SAntonio Huete Jimenez else 169cb7575e6SAntonio Huete Jimenez asprintf(&snapshots_path, "%s/snapshots", mountedon); 170cb7575e6SAntonio Huete Jimenez if ((dir = opendir(snapshots_path)) != NULL) { 171cb7575e6SAntonio Huete Jimenez while ((den = readdir(dir)) != NULL) { 172cb7575e6SAntonio Huete Jimenez if (den->d_name[0] == '.') 173cb7575e6SAntonio Huete Jimenez continue; 174cb7575e6SAntonio Huete Jimenez asprintf(&fpath, "%s/%s", snapshots_path, 175cb7575e6SAntonio Huete Jimenez den->d_name); 176cb7575e6SAntonio Huete Jimenez if (lstat(fpath, &st) == 0 && 177cb7575e6SAntonio Huete Jimenez S_ISLNK(st.st_mode)) 178cb7575e6SAntonio Huete Jimenez snapshot_count++; 179cb7575e6SAntonio Huete Jimenez free(fpath); 180cb7575e6SAntonio Huete Jimenez } 181cb7575e6SAntonio Huete Jimenez closedir(dir); 182cb7575e6SAntonio Huete Jimenez } 183cb7575e6SAntonio Huete Jimenez } else { 184cb7575e6SAntonio Huete Jimenez /* 185cb7575e6SAntonio Huete Jimenez * new style: file system meta-data 186cb7575e6SAntonio Huete Jimenez */ 187cb7575e6SAntonio Huete Jimenez do { 188cb7575e6SAntonio Huete Jimenez if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snapinfo) < 0) { 189cb7575e6SAntonio Huete Jimenez *errorp = errno; 190cb7575e6SAntonio Huete Jimenez goto out; 191cb7575e6SAntonio Huete Jimenez } 192cb7575e6SAntonio Huete Jimenez 193cb7575e6SAntonio Huete Jimenez snapshot_count += snapinfo.count; 194cb7575e6SAntonio Huete Jimenez } while (snapinfo.head.error == 0 && snapinfo.count); 195cb7575e6SAntonio Huete Jimenez } 196cb7575e6SAntonio Huete Jimenez 197cb7575e6SAntonio Huete Jimenez out: 198afc801daSAntonio Huete Jimenez if (!pfs_snapshots[0]) 199afc801daSAntonio Huete Jimenez free(snapshots_path); 200cb7575e6SAntonio Huete Jimenez if (fd != -1) 201cb7575e6SAntonio Huete Jimenez close(fd); 202cb7575e6SAntonio Huete Jimenez return snapshot_count; 203cb7575e6SAntonio Huete Jimenez } 204