forked from DragonFlyBSD/DragonFlyBSD
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libhammer - HAMMER filesystem library.
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
Showing
5 changed files
with
646 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.