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; 54431893caSAntonio 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; 58431893caSAntonio 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 82431893caSAntonio Huete Jimenez bzero(&pi, sizeof(pi)); 83431893caSAntonio Huete Jimenez pi.ondisk = _libhammer_malloc(sizeof(*pfs_od)); 84431893caSAntonio Huete Jimenez while(error == 0) { 85431893caSAntonio Huete Jimenez error = ioctl(fd, HAMMERIOC_PFS_ITERATE, &pi); 86431893caSAntonio Huete Jimenez if (error == 0 && 87431893caSAntonio 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)); 94431893caSAntonio 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 98cb7575e6SAntonio Huete Jimenez /* 99cb7575e6SAntonio Huete Jimenez * Fill in structs used in the library. We don't rely on 100cb7575e6SAntonio Huete Jimenez * HAMMER own struct but we do fill our own. 101cb7575e6SAntonio Huete Jimenez */ 102431893caSAntonio Huete Jimenez pfstmp->version = hvi->version; 103431893caSAntonio Huete Jimenez pfstmp->pfs_id = pi.pos; 104cb7575e6SAntonio Huete Jimenez pfstmp->mirror_flags = pfs_od->mirror_flags; 1054468f47bSAntonio Huete Jimenez pfstmp->beg_tid = pfs_od->sync_beg_tid; 1064468f47bSAntonio Huete Jimenez pfstmp->end_tid = pfs_od->sync_end_tid; 107*d428efb7SAntonio Huete Jimenez pfstmp->mountedon = 108*d428efb7SAntonio Huete Jimenez libhammer_find_pfs_mount(&pfs_od->unique_uuid); 109cb7575e6SAntonio Huete Jimenez pfstmp->snapcount = count_snapshots(hvi->version, 110c8fec8afSAntonio Huete Jimenez pfstmp->snapshots, pfstmp->mountedon, 111c8fec8afSAntonio Huete Jimenez &pfstmp->head.error); 112cb7575e6SAntonio Huete Jimenez 113cb7575e6SAntonio Huete Jimenez TAILQ_INSERT_TAIL(&hvi->list_pseudo, pfstmp, entries); 114cb7575e6SAntonio Huete Jimenez } 115431893caSAntonio Huete Jimenez pi.pos++; 116cb7575e6SAntonio Huete Jimenez } 117431893caSAntonio Huete Jimenez free(pi.ondisk); 118431893caSAntonio Huete Jimenez 119cb7575e6SAntonio Huete Jimenez close (fd); 120cb7575e6SAntonio Huete Jimenez 121cb7575e6SAntonio Huete Jimenez return (hvi); 122cb7575e6SAntonio Huete Jimenez } 123cb7575e6SAntonio Huete Jimenez 124cb7575e6SAntonio Huete Jimenez void 125cb7575e6SAntonio Huete Jimenez libhammer_free_volinfo(libhammer_volinfo_t volinfo) 126cb7575e6SAntonio Huete Jimenez { 127cb7575e6SAntonio Huete Jimenez struct libhammer_pfsinfo *pfstmp; 128cb7575e6SAntonio Huete Jimenez 129cb7575e6SAntonio Huete Jimenez while(!TAILQ_EMPTY(&volinfo->list_pseudo)) { 130cb7575e6SAntonio Huete Jimenez pfstmp = TAILQ_FIRST(&volinfo->list_pseudo); 131cb7575e6SAntonio Huete Jimenez free(pfstmp->mountedon); 132cb7575e6SAntonio Huete Jimenez TAILQ_REMOVE(&volinfo->list_pseudo, pfstmp, entries); 133cb7575e6SAntonio Huete Jimenez free(pfstmp); 134cb7575e6SAntonio Huete Jimenez } 135cb7575e6SAntonio Huete Jimenez free(volinfo); 136cb7575e6SAntonio Huete Jimenez } 137cb7575e6SAntonio Huete Jimenez 138cb7575e6SAntonio Huete Jimenez static u_int32_t 139c8fec8afSAntonio Huete Jimenez count_snapshots(u_int32_t version, char *pfs_snapshots, char *mountedon, 140c8fec8afSAntonio Huete Jimenez int *errorp) 141cb7575e6SAntonio Huete Jimenez { 142cb7575e6SAntonio Huete Jimenez struct hammer_ioc_snapshot snapinfo; 143cb7575e6SAntonio Huete Jimenez char *snapshots_path, *fpath; 144cb7575e6SAntonio Huete Jimenez struct dirent *den; 145cb7575e6SAntonio Huete Jimenez struct stat st; 146cb7575e6SAntonio Huete Jimenez DIR *dir; 147cb7575e6SAntonio Huete Jimenez u_int32_t snapshot_count; 148cb7575e6SAntonio Huete Jimenez int fd; 1491a9dc887SMatthew Dillon int spallocated; 150cb7575e6SAntonio Huete Jimenez 151cb7575e6SAntonio Huete Jimenez snapshot_count = 0; 152cb7575e6SAntonio Huete Jimenez 153cb7575e6SAntonio Huete Jimenez bzero(&snapinfo, sizeof(struct hammer_ioc_snapshot)); 154cb7575e6SAntonio Huete Jimenez 155cb7575e6SAntonio Huete Jimenez fd = open(mountedon, O_RDONLY); 156cb7575e6SAntonio Huete Jimenez if (fd < 0) { 157cb7575e6SAntonio Huete Jimenez *errorp = errno; 158cb7575e6SAntonio Huete Jimenez return 0; 159cb7575e6SAntonio Huete Jimenez } 160cb7575e6SAntonio Huete Jimenez 161cb7575e6SAntonio Huete Jimenez if (version < 3) { 162cb7575e6SAntonio Huete Jimenez /* 163cb7575e6SAntonio Huete Jimenez * old style: count the number of softlinks in the snapshots dir 164cb7575e6SAntonio Huete Jimenez */ 1651a9dc887SMatthew Dillon if (pfs_snapshots[0]) { 166cb7575e6SAntonio Huete Jimenez snapshots_path = pfs_snapshots; 1671a9dc887SMatthew Dillon spallocated = 0; 1681a9dc887SMatthew Dillon } else { 169cb7575e6SAntonio Huete Jimenez asprintf(&snapshots_path, "%s/snapshots", mountedon); 1701a9dc887SMatthew Dillon spallocated = 1; 1711a9dc887SMatthew Dillon } 172cb7575e6SAntonio Huete Jimenez if ((dir = opendir(snapshots_path)) != NULL) { 173cb7575e6SAntonio Huete Jimenez while ((den = readdir(dir)) != NULL) { 174cb7575e6SAntonio Huete Jimenez if (den->d_name[0] == '.') 175cb7575e6SAntonio Huete Jimenez continue; 176cb7575e6SAntonio Huete Jimenez asprintf(&fpath, "%s/%s", snapshots_path, 177cb7575e6SAntonio Huete Jimenez den->d_name); 178cb7575e6SAntonio Huete Jimenez if (lstat(fpath, &st) == 0 && 179cb7575e6SAntonio Huete Jimenez S_ISLNK(st.st_mode)) 180cb7575e6SAntonio Huete Jimenez snapshot_count++; 181cb7575e6SAntonio Huete Jimenez free(fpath); 182cb7575e6SAntonio Huete Jimenez } 183cb7575e6SAntonio Huete Jimenez closedir(dir); 184cb7575e6SAntonio Huete Jimenez } 1851a9dc887SMatthew Dillon if (spallocated) 1861a9dc887SMatthew Dillon free(snapshots_path); 187cb7575e6SAntonio Huete Jimenez } else { 188cb7575e6SAntonio Huete Jimenez /* 189cb7575e6SAntonio Huete Jimenez * new style: file system meta-data 190cb7575e6SAntonio Huete Jimenez */ 191cb7575e6SAntonio Huete Jimenez do { 192cb7575e6SAntonio Huete Jimenez if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snapinfo) < 0) { 193cb7575e6SAntonio Huete Jimenez *errorp = errno; 194cb7575e6SAntonio Huete Jimenez goto out; 195cb7575e6SAntonio Huete Jimenez } 196cb7575e6SAntonio Huete Jimenez 197cb7575e6SAntonio Huete Jimenez snapshot_count += snapinfo.count; 198cb7575e6SAntonio Huete Jimenez } while (snapinfo.head.error == 0 && snapinfo.count); 199cb7575e6SAntonio Huete Jimenez } 200cb7575e6SAntonio Huete Jimenez 201cb7575e6SAntonio Huete Jimenez out: 202cb7575e6SAntonio Huete Jimenez if (fd != -1) 203cb7575e6SAntonio Huete Jimenez close(fd); 204cb7575e6SAntonio Huete Jimenez return snapshot_count; 205cb7575e6SAntonio Huete Jimenez } 206