File: [Development] / xfs-cmds / xfsdump / inventory / inv_oref.c (download)
Revision 1.6, Tue Apr 29 01:52:34 2003 UTC (14 years, 5 months ago) by nathans
Branch: MAIN
CVS Tags: XFS-1_3_0pre1 Changes since 1.5: +2 -2
lines
Fix includes to not be relative to paths provided by -I directives, for
the xfsprogs and xfsdump builds. At this stage still provide these gcc
options in the build but later that can be removed too now that headers
are clean.
|
/**************************************************************************
* *
* Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
* *
**************************************************************************/
#include <xfs/libxfs.h>
#include <xfs/jdm.h>
#include "inv_priv.h"
#include "inv_oref.h"
/*
* Resolve a stobj, invidx or fstab
*/
intgen_t
oref_resolve_(
invt_oref_t *obj,
invt_objtype_t type)
{
intgen_t rval;
type &= INVT_OTYPE_MASK;
ASSERT(type);
ASSERT(! OREF_ISRESOLVED(obj, INVT_OTYPE_MASK));
switch (type) {
case INVT_OTYPE_INVIDX:
rval = oref_resolve_invidx(obj);
break;
case INVT_OTYPE_STOBJ:
rval = oref_resolve_stobj(obj);
break;
case INVT_OTYPE_FSTAB:
rval = oref_resolve_fstab(obj);
break;
default:
ASSERT(0);
break;
}
return rval;
}
/*
* Resolve an object reference upto a specified point
*/
intgen_t
oref_resolve_upto(
invt_oref_t *obj,
invt_objtype_t type)
{
intgen_t rval = INV_OK;
ASSERT (OREF_ISRESOLVED(obj, INVT_OTYPE_MASK));
ASSERT (OREF_ISLOCKED(obj));
/* we arent interested in anything else */
type &= INVT_RES_MASK;
ASSERT(type);
if (type >= INVT_RES_COUNTERS) {
rval = oref_resolve_counters(obj);
}
if (type >= INVT_RES_ENTRIES && rval != INV_ERR) {
rval = oref_resolve_entries(obj);
}
if (type >= INVT_RES_HDRS && rval != INV_ERR) {
rval = oref_resolve_hdrs(obj);
}
if (type >= INVT_RES_SESSIONS && rval != INV_ERR) {
rval = oref_resolve_sessions(obj);
}
if (type >= INVT_RES_STRMS && rval != INV_ERR) {
rval = oref_resolve_strms(obj);
}
if (type >= INVT_RES_MFILES && rval != INV_ERR) {
rval = oref_resolve_mfiles(obj);
}
return rval;
}
intgen_t
oref_resolve_entries(
invt_oref_t *obj)
{
if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES))
return INV_OK;
ASSERT(! OREF_ISRESOLVED(INVT_OTYPE_STOBJ));
if (OREF_ISRESOLVED(INVT_OTYPE_INVIDX)) {
invt_entry_t *ent;
ASSERT(OREF_CNT_CURNUM(obj));
if (GET_ENTRIES(obj->fd, &ent, OREF_CNT_CURNUM(obj),
sizeof(invt_entry_t)) < 0){
return INV_ERR;
}
obj->eu_ent = ent;
}
else {
invt_fstab_t *ent;
ASSERT(OREF_CNT_CURNUM(obj));
if (GET_ENTRIES(obj->fd, &ent, OREF_CNT_CURNUM(obj),
sizeof(invt_fstab_t)) < 0){
return INV_ERR;
}
obj->eu_fstabent = ent;
}
OREF_SET_TYPE(obj, INVT_RES_COUNTERS);
return INV_OK;
}
intgen_t
oref_resolve_counters(
invt_oref_t *obj)
{
if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS))
return INV_OK;
if (OREF_ISRESOLVED(INVT_OTYPE_STOBJ)) {
invt_sescounter_t *sescnt;
sescnt = calloc(1, sizeof(invt_sescounter_t));
if (GET_SESCOUNTERS(obj->fd, sescnt) < 0){
free(sescnt);
return INV_ERR;
}
obj->cu_sescnt = sescnt;
}
else {
invt_counter_t *cnt;
cnt = calloc(1, sizeof(invt_counter_t));
if (GET_COUNTERS(obj->fd, cnt) < 0){
free(cnt);
return INV_ERR;
}
obj->cu_cnt = cnt;
}
OREF_SET_TYPE(obj, INVT_RES_COUNTERS);
return INV_OK;
}
intgen_t
oref_sync(
invt_oref_t *obj,
invt_objtype_t type)
{
intgen_t rval;
type &= INVT_RES_MASK;
ASSERT(type);
ASSERT(OREF_ISRESOLVED(obj, INVT_OTYPE_MASK));
ASSERT(OREF_ISRESOLVED(obj, type));
ASSERT(OREF_ISLOCKED(obj));
switch (type) {
case INVT_RES_COUNTERS:
rval = PUT_REC_NOLOCK(obj->fd,
OREF_CNT(obj),
sizeof(*OREF_CNT(obj)),
(off64_t) 0);
break;
case INVT_RES_ENTRIES:
ASSERT(! OREF_ISRESOLVED(obj, INVT_OTYPE_STOBJ));
rval = PUT_REC_NOLOCK(obj->fd,
OREF_ENTRIES(obj),
sizeof(*OREF_ENTRIES(obj)),
(off64_t) sizeof(*OREF_CNT(obj)));
break;
default:
ASSERT(0);
break;
}
return rval;
}
intgen_t
oref_sync_append(
invt_oref_t *obj,
invt_objtype_t type,
void *entry,
size_t entsz)
{
intgen_t rval;
type &= INVT_RES_MASK;
ASSERT(type);
ASSERT(OREF_ISRESOLVED(obj, INVT_OTYPE_MASK));
ASSERT(OREF_ISLOCKED(obj));
switch (type) {
case INVT_RES_ENTRIES:
ASSERT(! OREF_ISRESOLVED(obj, INVT_OTYPE_STOBJ));
rval = PUT_REC_NOLOCK(obj->fd,
entry,
entsz,
IDX_HDR_OFFSET(OREF_CNT_CURNUM(obj) - 1));
if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES))
free((oref)->eu_ent);
OREF_UNSET_TYPE(obj, INVT_RES_ENTRIES);
break;
default:
ASSERT(0);
break;
}
return rval;
}
void
_oref_free(
invt_oref_t *obj,
bool_t freethis)
{
/*
* Unlock the object *if* it is locked.
* We dont want to actually close the fd because,
* the tokens still need it.
*/
OREF_UNLOCK(obj);
if (OREF_ISRESOLVED(obj, INVT_OTYPE_STOBJ) ){
if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS))
free((oref)->cu_sescnt);
if (OREF_ISRESOLVED(obj, INVT_RES_HDRS))
free((oref)->eu_hdr);
if (OREF_ISRESOLVED(obj, INVT_RES_SESSIONS))
free((oref)->eu_ses);
if (OREF_ISRESOLVED(obj, INVT_RES_STRMS))
free((oref)->eu_strm);
if (OREF_ISRESOLVED(obj, INVT_RES_MFILES))
free((oref)->eu_mfile);
}
else if (OREF_ISRESOLVED(obj, INVT_OTYPE_INVIDX)) {
if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS))
free((oref)->cu_cnt);
if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES))
free((oref)->eu_ent);
}
else if (OREF_ISRESOLVED(obj, INVT_OTYPE_FSTAB)) {
if (OREF_ISRESOLVED(obj, INVT_RES_COUNTERS))
free((oref)->cu_cnt);
if (OREF_ISRESOLVED(obj, INVT_RES_ENTRIES))
free((oref)->eu_fstabent);
}
OREF_INIT(obj);
if (freethis)
free(obj);
}
/*
* Resolve the invidx and a suitable stobj.
* Also resolves an idb_token as a side effect.
*/
intgen_t
oref_resolve(
invt_oref_t *invidx,
inv_predicate_t bywhat,
void *pred)
{
char fname[ INV_STRLEN ];
char uuname[ INV_STRLEN ];
int fd;
invt_oref_t *stobj;
int index;
ASSERT(! OREF_ISRESOLVED(invidx, INVT_OTYPE_MASK));
OREF_SET_TYPE(invidx, INVT_OTYPE_INVIDX);
/* come up with the unique file suffix that refers to this
filesystem */
if (fstab_get_fname(pred, uuname, bywhat) < 0) {
return INV_ERR;
}
(void) strcpy(fname, uuname);
strcat(fname, INV_INVINDEX_PREFIX);
/* first check if the inv_index file exists: if not create it */
if ((fd = open(fname, O_RDWR)) == -1) {
if (errno != ENOENT) {
INV_PERROR (fname);
return INV_ERR;
}
/* create the invidx */
return oref_resolve_new_invidx(invidx, fname);
}
invidx->fd = fd;
OREF_LOCK(invidx, LOCK_EX);
if (oref_resolve_child(invidx, &index) == INV_ERR) {
OREF_UNLOCK(invidx);
return INV_ERR;
}
stobj = OREF_CHILD(invidx);
/* Now we need to make sure that this has enough space */
OREF_LOCK(stobj, LOCK_SH);
if (oref_resolve_upto(stobj, INVT_RES_COUNTERS) == INV_ERR) {
OREF_UNLOCK(stobj);
OREF_UNLOCK(invidx);
return INV_ERR;
}
/* create another storage object ( and, an inv_index entry for it
too ) if we've filled this one up */
if (OREF_CNT_CURNUM(stobj) >= OREF_CNT_MAXNUM(stobj)) {
intgen_t rval;
#ifdef INVT_DEBUG
mlog( MLOG_DEBUG | MLOG_INV, "$ INV: creating a new storage obj & "
"index entry. \n" );
#endif
/* Close(), Destroy() and mark unresolved */
OREF_UNRESOLVE_CHILD(invidx);
rval = oref_resolve_new_stobj(invidx, BOOL_FALSE);
/* rval = oref_idx_create_entry(invidx, BOOL_FALSE); */
OREF_UNLOCK(invidx);
return rval;
}
OREF_UNLOCK(stobj);
OREF_UNLOCK(invidx);
tok = get_token(invidx->fd, stobj->fd);
tok->d_invindex_off = IDX_HDR_OFFSET(index - 1);
OREF_SET_TOKEN(tok);
return INV_OK;
}
/*
* Resolve the invidx entirely, and open the StObj.
* Invidx is kept locked by caller
*/
intgen_t
oref_resolve_child(
invt_oref_t *invidx,
int *index)
{
invt_entry_t *ent;
ASSERT(OREF_IS_LOCKED(invidx));
if (oref_resolve_upto(invidx, INVT_RES_ENTRIES) == INV_ERR)
return INV_ERR;
ent = OREF_ENTRIES(invidx);
/* at this point we know that there should be at least one invindex
entry present */
ASSERT ( ent != NULL );
ASSERT ( ent->ie_filename );
fd = open( ent->ie_filename, O_RDWR );
if ( fd < 0 ) {
INV_PERROR( ent->ie_filename );
return INV_ERR;
}
stobj = calloc(1, sizeof(invt_oref_t));
OREF_SET_CHILD(invidx, stobj);
stobj->fd = fd;
return INV_OK;
}
/* used to be idx_create */
intgen_t
oref_resolve_new_invidx(
invt_oref_t *invidx,
char *fname)
{
int stobjfd, fd;
inv_idbtoken_t tok;
if ((fd = open ( fname , O_RDWR | O_CREAT ) ) < 0 ) {
INV_PERROR ( fname );
return INV_ERR;
}
invidx->fd = fd;
OREF_LOCK(invidx, LOCK_EX);
fchmod(fd, INV_PERMS);
#ifdef INVT_DEBUG
mlog( MLOG_NITTY | MLOG_INV, "creating InvIndex %s\n", fname);
#endif
/* create the new stobj as its first entry */
rval = oref_resolve_new_stobj(invidx, IS_EMPTY);
OREF_UNLOCK(invidx);
return rval;
}
/* formerly idx_create_entry() */
intgen_t
oref_resolve_new_stobj(
invt_oref_t *invidx,
bool_t firstentry)
{
invt_entry_t ent;
int fd;
off64_t hoff;
invt_oref_t *stobj;
inv_idbtoken_t tok;
ASSERT(OREF_ISLOCKED(invidx));
memset ( &ent, 0, sizeof( ent ) );
stobj = calloc(1, sizeof(invt_oref_t));
OREF_SET_CHILD(invidx, stobj);
/* initialize the start and end times to be the same */
ent.ie_timeperiod.tp_start = ent.ie_timeperiod.tp_end = (time32_t)0;
stobj_makefname( ent.ie_filename );
if ( firstentry ) {
invt_counter_t *cnt;
cnt = malloc(sizeof(invt_counter_t));
cnt->ic_maxnum = INVT_MAX_INVINDICES;
cnt->ic_curnum = 1;
cnt->ic_vernum = INV_VERSION;
fd = stobj_create( ent.ie_filename );
if ( fd < 0 ) {
free(cnt);
return INV_ERR;
}
stobj->fd = fd;
OREF_SET_COUNTERS(invidx, cnt);
OREF_SET_ENTRIES(invidx, &ent);
if ((oref_sync(invidx, INVT_RES_COUNTERS) == INV_ERR)
||
(oref_sync(invidx, INVT_RES_ENTRIES) == INV_ERR))
return INV_ERR;
}
else {
if (oref_resolve_upto(invidx, INVT_RES_COUNTERS) == INV_ERR)
return INV_ERR;
/* create the new storage object */
fd = stobj_create( ent.ie_filename );
if ( fd < 0 ) {
return -1;
}
stobj->fd = fd;
OREF_CNT_CURNUM(invidx)++;
if ((oref_sync(invidx, INVT_RES_COUNTERS) == INV_ERR)
||
(oref_sync_append(invidx, INVT_RES_ENTRIES,
&ent, sizeof(ent)) == INV_ERR))
return INV_ERR;
}
tok = get_token( invfd, fd );
tok->d_invindex_off = IDX_HDR_OFFSET(OREF_CNT_CURNUM(invidx) - 1);
tok->d_update_flag |= NEW_INVINDEX;
OREF_SET_TOKEN(invidx, tok);
return INV_OK;
}