Skip to content

Commit

Permalink
libhammer - HAMMER filesystem library.
Browse files Browse the repository at this point in the history
Initial work to bring a library to help operating
HAMMER filesystems from userland.

It's barebones as of now, only "info" directive is
adapted, progressively the rest of the directives
will be migrated

Help-from: @swildner, @sjg
  • Loading branch information
tuxillo committed Oct 25, 2011
1 parent 754a8b0 commit cb7575e
Show file tree
Hide file tree
Showing 5 changed files with 646 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lib/libhammer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# DragonflyBSD Makefile

LIB= hammer
SRCS= crc32.c info.c misc.c
INCS= libhammer.h

SRCS+= crc32.c

MAN+= libhammer_get_volinfo.3

MLINKS+= libhammer_get_volinfo.3 libhammer_get_next_pfs.3
MLINKS+= libhammer_get_volinfo.3 libhammer_get_prev_pfs.3
MLINKS+= libhammer_get_volinfo.3 libhammer_get_first_pfs.3
MLINKS+= libhammer_get_volinfo.3 libhammer_get_last_pfs.3
MLINKS+= libhammer_get_volinfo.3 libhammer_free_volinfo.3

.PATH: ${.CURDIR}/../../sys/libkern
SHLIB_MAJOR= 0

.include <bsd.lib.mk>
210 changes: 210 additions & 0 deletions lib/libhammer/info.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* Copyright (c) 2011 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Antonio Huete <tuxillo@quantumachine.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>

#include <libhammer.h>

static u_int32_t count_snapshots(u_int32_t, char *, char *, int *);

libhammer_volinfo_t
libhammer_get_volinfo(const char *path)
{
struct hammer_ioc_pseudofs_rw pseudofs;
struct hammer_pseudofs_data *pfs_od;
struct hammer_ioc_info info;
libhammer_pfsinfo_t pfstmp;
libhammer_volinfo_t hvi;
int pfs_id;
int fd;

hvi = _libhammer_malloc(sizeof(*hvi));

TAILQ_INIT(&hvi->list_pseudo);

if ((fd = open(path, O_RDONLY)) < 0)
goto error1;

if ((ioctl(fd, HAMMERIOC_GET_INFO, &info)) < 0)
goto error1;

/* Fill volume information */
snprintf(hvi->vol_name, TXTLEN, "%s", info.vol_name);
hvi->vol_fsid = info.vol_fsid;
hvi->version = info.version;
hvi->nvolumes = info.nvolumes;
hvi->bigblocks = info.bigblocks;
hvi->rsvbigblocks = info.rsvbigblocks;

/*
* XXX - By now we iterate the whole range of +65000 possible
* pseudofs to discover the ones that are in use. Of course
* this is suboptimal. Best way would be to extract the
* pseudofs information from the control records in the
* B-Tree, that's in kernel land.
*/
pfs_od = _libhammer_malloc(sizeof(*pfs_od));

for(pfs_id = 0; pfs_id < HAMMER_MAX_PFS; pfs_id++) {
/* Clear the struct to be passed to the ioctl. */
bzero(&pseudofs, sizeof(pseudofs));

pfstmp = _libhammer_malloc(sizeof(*pfstmp));

pseudofs.pfs_id = pfs_id;
pseudofs.ondisk = pfs_od;
pseudofs.bytes = sizeof(struct hammer_pseudofs_data);
pseudofs.version = HAMMER_IOC_PSEUDOFS_VERSION;
if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pseudofs) != -1) {
/* XXX
* It may be completely wrong in the case that we pass a path
* that is in PFS 0 but isn't the mount path of it. There's no
* easy way to do this.
*/
pfstmp->ismaster = (pfs_od->mirror_flags & HAMMER_PFSD_SLAVE)
? 0 : 1;

if (pfs_id == 0)
pfstmp->mountedon = strdup(path);
else
pfstmp->mountedon = libhammer_find_pfs_mount(pfs_id,
hvi->vol_fsid, pfstmp->ismaster);
/*
* Fill in structs used in the library. We don't rely on
* HAMMER own struct but we do fill our own.
*/
pfstmp->version = pseudofs.version;
pfstmp->pfs_id = pseudofs.pfs_id;
pfstmp->mirror_flags = pfs_od->mirror_flags;
pfstmp->snapcount = count_snapshots(hvi->version,
pfstmp->snapshots, pfstmp->mountedon, &pfstmp->head.error);

TAILQ_INSERT_TAIL(&hvi->list_pseudo, pfstmp, entries);
}
}

goto end;

error1:
libhammer_free_volinfo(hvi);
if (fd != -1)
close(fd);

end:
return (hvi);
}

void
libhammer_free_volinfo(libhammer_volinfo_t volinfo)
{
struct libhammer_pfsinfo *pfstmp;

while(!TAILQ_EMPTY(&volinfo->list_pseudo)) {
pfstmp = TAILQ_FIRST(&volinfo->list_pseudo);
free(pfstmp->mountedon);
TAILQ_REMOVE(&volinfo->list_pseudo, pfstmp, entries);
free(pfstmp);
}
free(volinfo);
}

static u_int32_t
count_snapshots(u_int32_t version, char *pfs_snapshots, char *mountedon, int *errorp)
{
struct hammer_ioc_snapshot snapinfo;
char *snapshots_path, *fpath;
struct dirent *den;
struct stat st;
DIR *dir;
u_int32_t snapshot_count;
int fd;

snapshot_count = 0;

bzero(&snapinfo, sizeof(struct hammer_ioc_snapshot));

fd = open(mountedon, O_RDONLY);
if (fd < 0) {
*errorp = errno;
return 0;
}

if (version < 3) {
/*
* old style: count the number of softlinks in the snapshots dir
*/
if (pfs_snapshots[0])
snapshots_path = pfs_snapshots;
else
asprintf(&snapshots_path, "%s/snapshots", mountedon);
if ((dir = opendir(snapshots_path)) != NULL) {
while ((den = readdir(dir)) != NULL) {
if (den->d_name[0] == '.')
continue;
asprintf(&fpath, "%s/%s", snapshots_path,
den->d_name);
if (lstat(fpath, &st) == 0 &&
S_ISLNK(st.st_mode))
snapshot_count++;
free(fpath);
}
closedir(dir);
}
} else {
/*
* new style: file system meta-data
*/
do {
if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snapinfo) < 0) {
*errorp = errno;
goto out;
}

snapshot_count += snapinfo.count;
} while (snapinfo.head.error == 0 && snapinfo.count);
}

out:
if (fd != -1)
close(fd);
return snapshot_count;
}
150 changes: 150 additions & 0 deletions lib/libhammer/libhammer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright (c) 2011 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Antonio Huete <tuxillo@quantumachine.net>
* by Matthew Dillon <dillon@backplane.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#ifndef _LIBHAMMER_H_
#define _LIBHAMMER_H_

#include <sys/queue.h>
#include <sys/param.h>

#include <vfs/hammer/hammer_disk.h>
#include <vfs/hammer/hammer_ioctl.h>

#define TXTLEN 64

#define HAMMER_BUFLISTS 64
#define HAMMER_BUFLISTMASK (HAMMER_BUFLISTS - 1)
#define COLLECT_HSIZE 1024
#define COLLECT_HMASK (COLLECT_HSIZE - 1)
#define HAMMER_BUFINFO_READAHEAD 0x0001
/*
* WARNING: Do not make the SNAPSHOTS_BASE "/var/snapshots" because
* it will interfere with the older HAMMER VERS < 3 snapshots directory
* for the /var PFS.
*/
#define SNAPSHOTS_BASE "/var/hammer" /* HAMMER VERS >= 3 */
#define WS " \t\r\n"

#define SERIALBUF_SIZE (512 * 1024)
#define RD_HSIZE 32768
#define RD_HMASK (RD_HSIZE - 1)

#define DICTF_MADEDIR 0x01
#define DICTF_MADEFILE 0x02
#define DICTF_PARENT 0x04 /* parent attached for real */
#define DICTF_TRAVERSED 0x80
#define FLAG_TOOFARLEFT 0x0001
#define FLAG_TOOFARRIGHT 0x0002
#define FLAG_BADTYPE 0x0004
#define FLAG_BADCHILDPARENT 0x0008
#define FLAG_BADMIRRORTID 0x0010

/*
* Hammer information system structures
*/
struct libhammer_head {
int32_t error;
int32_t flags;
int32_t rsv[2];
};

typedef struct libhammer_pfsinfo {
struct libhammer_head head; /* Additional error and flags */

uint32_t snapcount; /* Snapshot count */
u_int32_t version; /* HAMMER version */
char *mountedon; /* Mount path of the PFS */
int ismaster; /* Is a PFS master */
int pfs_id; /* PFS ID number */
int mirror_flags; /* Misc flags */
char snapshots[64]; /* softlink dir for pruning */
uuid_t unique_uuid; /* unique uuid of this master/slave */
TAILQ_ENTRY(libhammer_pfsinfo) entries;
} *libhammer_pfsinfo_t;

typedef struct libhammer_volinfo {
struct libhammer_head head; /* Additional error and flags */

char vol_name[TXTLEN]; /* Volume name */
uuid_t vol_fsid; /* Filesystem UUID */
int version; /* HAMMER version */
int nvolumes; /* Number of volumes */
int64_t bigblocks; /* Total big blocks */
int64_t rsvbigblocks; /* Reserved big blocks */
int32_t rsv[8];
TAILQ_HEAD(pfslist, libhammer_pfsinfo) list_pseudo;
} *libhammer_volinfo_t;

/*
* INFO directive prototypes
*/
__BEGIN_DECLS
libhammer_volinfo_t libhammer_get_volinfo(const char *);
void libhammer_free_volinfo(libhammer_volinfo_t);
__END_DECLS

static __inline libhammer_pfsinfo_t
libhammer_get_next_pfs(libhammer_pfsinfo_t pfsinfo)
{
return TAILQ_NEXT(pfsinfo, entries);
}

static __inline libhammer_pfsinfo_t
libhammer_get_prev_pfs(libhammer_pfsinfo_t pfsinfo)
{
return TAILQ_PREV(pfsinfo, pfslist, entries);
}

static __inline libhammer_pfsinfo_t
libhammer_get_first_pfs(libhammer_volinfo_t volinfo)
{
return TAILQ_FIRST(&volinfo->list_pseudo);
}

static __inline libhammer_pfsinfo_t
libhammer_get_last_pfs(libhammer_volinfo_t volinfo)
{
return TAILQ_LAST(&volinfo->list_pseudo, pfslist);
}

#endif

/*
* MISC directive prototypes
*/
__BEGIN_DECLS
char *libhammer_find_pfs_mount(int, uuid_t, int);
void *_libhammer_malloc(size_t);
__END_DECLS
Loading

0 comments on commit cb7575e

Please sign in to comment.