File: [Development] / xfs-cmds / xfsdump / restore / dirattr.c (download)
Revision 1.15, Mon May 1 14:51:59 2006 UTC (11 years, 5 months ago) by wkendall
Branch: MAIN
Changes since 1.14: +0 -5
lines
Another approach to restoring the immutable flag at the correct
time. Also addresses some inefficiencies in restoring metadata
on files dumped in multiple extent groups and files with
extended attributes.
Back out changes for the previous attempt at restoring the immutable
flag.
|
/*
* 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 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. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Directory attributes are written on tape during the directory dump phase,
* which precedes the non-dir dump phase. The directory attributes cannot be
* restored, however, until all of the non-dir files have been restored
* (directory timestamps would be wrong, directory inherit flags would
* interfere, etc.) These routines allow the directory attributes to be stored
* on disk when they are read from the dump stream so that they can be applied
* at a later time.
*/
#include <xfs/libxfs.h>
#include <xfs/jdm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include "types.h"
#include "util.h"
#include "mlog.h"
#include "global.h"
#include "drive.h"
#include "media.h"
#include "content.h"
#include "content_inode.h"
#include "dirattr.h"
#include "openutil.h"
#include "mmap.h"
/* structure definitions used locally ****************************************/
#define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
/* node handle limits
*/
#ifdef DIRATTRCHK
/* macros for manipulating dirattr handles when handle consistency
* checking is enabled. the upper bits of a handle will be loaded
* with a handle checksum.
*/
#define HDLSUMCNT 4
#define HDLSUMSHIFT ( NBBY * sizeof ( dah_t ) - HDLSUMCNT )
#define HDLSUMLOMASK ( ( 1 << HDLSUMCNT ) - 1 )
#define HDLSUMMASK ( HDLSUMLOMASK << HDLSUMSHIFT )
#define HDLDIXCNT HDLSUMSHIFT
#define HDLDIXMASK ( ( 1 << HDLDIXCNT ) - 1 )
#define HDLGETSUM( h ) ( ( u_int16_t ) \
( ( ( int )h >> HDLSUMSHIFT ) \
& \
HDLSUMLOMASK ))
#define HDLGETDIX( h ) ( ( dix_t )( ( int )h & HDLDIXMASK ))
#define HDLMKHDL( s, d ) ( ( dah_t )( ( ( ( int )s << HDLSUMSHIFT )\
& \
HDLSUMMASK ) \
| \
( ( int )d & HDLDIXMASK )))
#define DIX_MAX ( ( off64_t )HDLDIXMASK )
/* each dirattr will hold two check fields: a handle checksum, and unique
* pattern, to differentiate a valid dirattr from random file contents.
*/
#define DIRATTRUNQ 0xa116
#else /* DIRATTRCHK */
#define DIX_MAX ( ( ( off64_t )1 \
<< \
( ( off64_t )NBBY \
* \
( off64_t )sizeof( dah_t ))) \
- \
( off64_t )2 ) /* 2 to avoid DAH_NULL */
#endif /* DIRATTRCHK */
/* dirattr definition
*/
struct dirattr {
#ifdef DIRATTRCHK
u_int16_t d_unq;
u_int16_t d_sum;
#endif /* DIRATTRCHK */
mode_t d_mode;
uid_t d_uid;
gid_t d_gid;
time32_t d_atime;
time32_t d_mtime;
time32_t d_ctime;
u_int32_t d_xflags;
u_int32_t d_extsize;
u_int32_t d_projid;
u_int32_t d_dmevmask;
u_int32_t d_dmstate;
off64_t d_extattroff;
};
typedef struct dirattr dirattr_t;
#define DIRATTR_EXTATTROFFNULL ( ( off64_t )OFF64MAX )
/* dirattr persistent context definition
*/
struct dirattr_pers {
off64_t dp_appendoff;
};
typedef struct dirattr_pers dirattr_pers_t;
#define DIRATTR_PERS_SZ pgsz
/* dirattr transient context definition
*/
#define DIRATTR_BUFSIZE 32768
struct dirattr_tran {
char *dt_pathname;
int dt_fd;
bool_t dt_at_endpr;
dah_t dt_cachedh;
dirattr_t dt_cached_dirattr;
size_t dt_off;
char dt_buf[DIRATTR_BUFSIZE];
char *dt_extattrpathname;
int dt_extattrfd;
bool_t dt_extattrfdbadpr;
};
typedef struct dirattr_tran dirattr_tran_t;
/* a dirattr is identified internally by its index into the backing store.
* this index is the offset of the dirattr (relative to the end of the dirattr
* persistent state hdr) into the backing store divided by the size of a
* dirattr. a special index is reserved to represent the null index. a type
* is defined for dirattr index (dix_t). it is a 64 bit signed for direct use
* in the lseek64 system call.
*/
typedef off64_t dix_t;
#define DIX2OFF( dix ) ( ( off64_t )( dix * ( off64_t )sizeof( dirattr_t ) \
+ \
( off64_t )DIRATTR_PERS_SZ ))
#define OFF2DIX( doff ) ( ( dix_t )( ( doff - ( off64_t )DIRATTR_PERS_SZ ) \
/ \
( off64_t )sizeof( dirattr_t )))
/* declarations of externally defined global symbols *************************/
extern size_t pgsz;
/* forward declarations of locally defined static functions ******************/
static void dirattr_get( dah_t );
static void dirattr_cacheflush( void );
#ifdef DIRATTRCHK
static u_int16_t calcdixcum( dix_t dix );
#endif /* DIRATTRCHK */
/* definition of locally defined global variables ****************************/
/* definition of locally defined static variables *****************************/
static char *dirattrfile = "dirattr";
static char *dirextattrfile = "dirextattr";
static dirattr_tran_t *dtp = 0;
static dirattr_pers_t *dpp = 0;
/* definition of locally defined global functions ****************************/
bool_t
dirattr_init( char *hkdir, bool_t resume, u_int64_t dircnt )
{
#ifdef SESSCPLT
if ( dtp ) {
return BOOL_TRUE;
}
#endif /* SESSCPLT */
/* sanity checks
*/
ASSERT( sizeof( dirattr_pers_t ) <= DIRATTR_PERS_SZ );
ASSERT( ! dtp );
ASSERT( ! dpp );
/* allocate and initialize context
*/
dtp = ( dirattr_tran_t * )calloc( 1, sizeof( dirattr_tran_t ));
ASSERT( dtp );
dtp->dt_cachedh = DAH_NULL;
dtp->dt_fd = -1;
dtp->dt_extattrfd = -1;
/* generate a string containing the pathname of the dirattr file
*/
dtp->dt_pathname = open_pathalloc( hkdir, dirattrfile, 0 );
/* open the dirattr file
*/
if ( resume ) {
/* open existing file
*/
dtp->dt_fd = open( dtp->dt_pathname, O_RDWR );
if ( dtp->dt_fd < 0 ) {
mlog( MLOG_NORMAL | MLOG_ERROR, _(
"could not find directory attributes file %s: "
"%s\n"),
dtp->dt_pathname,
strerror( errno ));
return BOOL_FALSE;
}
} else {
/* create the dirattr file, first unlinking any older version
* laying around
*/
( void )unlink( dtp->dt_pathname );
dtp->dt_fd = open( dtp->dt_pathname,
O_RDWR | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR );
if ( dtp->dt_fd < 0 ) {
mlog( MLOG_NORMAL | MLOG_ERROR, _(
"could not create directory attributes file %s: "
"%s\n"),
dtp->dt_pathname,
strerror( errno ));
return BOOL_FALSE;
}
/* reserve space for the backing store. try to use RESVSP64.
* if doesn't work, try ALLOCSP64. the former is faster, as
* it does not zero the space.
*/
{
bool_t successpr;
unsigned int ioctlcmd;
intgen_t loglevel;
size_t trycnt;
for ( trycnt = 0,
successpr = BOOL_FALSE,
ioctlcmd = XFS_IOC_RESVSP64,
loglevel = MLOG_VERBOSE
;
! successpr && trycnt < 2
;
trycnt++,
ioctlcmd = XFS_IOC_ALLOCSP64,
loglevel = max( MLOG_NORMAL, loglevel - 1 )) {
off64_t initsz;
struct flock64 flock64;
intgen_t rval;
if ( ! ioctlcmd ) {
continue;
}
initsz = ( off64_t )DIRATTR_PERS_SZ
+
( ( off64_t )dircnt * sizeof( dirattr_t ));
flock64.l_whence = 0;
flock64.l_start = 0;
flock64.l_len = initsz;
rval = ioctl( dtp->dt_fd, ioctlcmd, &flock64 );
if ( rval ) {
if ( errno != ENOTTY ) {
mlog( loglevel | MLOG_NOTE, _(
"attempt to reserve %lld bytes for %s "
"using %s "
"failed: %s (%d)\n"),
initsz,
dtp->dt_pathname,
ioctlcmd == XFS_IOC_RESVSP64
?
"XFS_IOC_RESVSP64"
:
"XFS_IOC_ALLOCSP64",
strerror( errno ),
errno );
}
} else {
successpr = BOOL_TRUE;
}
}
}
}
/* mmap the persistent descriptor
*/
ASSERT( ! ( DIRATTR_PERS_SZ % pgsz ));
dpp = ( dirattr_pers_t * )mmap_autogrow( DIRATTR_PERS_SZ,
dtp->dt_fd,
( off_t )0 );
ASSERT( dpp );
if ( dpp == ( dirattr_pers_t * )-1 ) {
mlog( MLOG_NORMAL | MLOG_ERROR, _(
"unable to map %s: %s\n"),
dtp->dt_pathname,
strerror( errno ));
return BOOL_FALSE;
}
/* initialize persistent state
*/
if ( ! resume ) {
dpp->dp_appendoff = ( off64_t )DIRATTR_PERS_SZ;
}
/* initialize transient state
*/
dtp->dt_at_endpr = BOOL_FALSE;
/* calculate the dir extattr pathname, and set the fd to -1.
* file will be created on demand.
*/
dtp->dt_extattrpathname = open_pathalloc( hkdir, dirextattrfile, 0 );
dtp->dt_extattrfd = -1;
dtp->dt_extattrfdbadpr = BOOL_FALSE;
if ( resume ) {
( void )unlink( dtp->dt_extattrpathname );
}
return BOOL_TRUE;
}
void
dirattr_cleanup( void )
{
/* REFERENCED */
intgen_t rval;
if ( ! dtp ) {
return;
}
if ( dpp ) {
rval = munmap( ( void * )dpp, DIRATTR_PERS_SZ );
ASSERT( ! rval );
dpp = 0;
}
if ( dtp->dt_fd >= 0 ) {
( void )close( dtp->dt_fd );
dtp->dt_fd = -1;
}
if ( dtp->dt_pathname ) {
( void )unlink( dtp->dt_pathname );
free( ( void * )dtp->dt_pathname );
}
if ( dtp->dt_extattrfd >= 0 ) {
( void )close( dtp->dt_extattrfd );
dtp->dt_extattrfd = -1;
}
if ( dtp->dt_extattrpathname ) {
( void )unlink( dtp->dt_extattrpathname );
free( ( void * )dtp->dt_extattrpathname );
}
free( ( void * )dtp );
dtp = 0;
}
dah_t
dirattr_add( filehdr_t *fhdrp )
{
dirattr_t dirattr;
off64_t oldoff;
dix_t dix;
#ifdef DIRATTRCHK
u_int16_t sum;
#endif /* DIRATTRCHK */
dah_t dah;
/* sanity checks
*/
ASSERT( dtp );
ASSERT( dpp );
/* make sure file pointer is positioned to write at end of file
*/
if ( ! dtp->dt_at_endpr ) {
off64_t newoff;
newoff = lseek64( dtp->dt_fd, dpp->dp_appendoff, SEEK_SET );
if ( newoff == ( off64_t )-1 ) {
mlog( MLOG_NORMAL | MLOG_ERROR, _(
"lseek of dirattr failed: %s\n"),
strerror( errno ));
return DAH_NULL;
}
ASSERT( dpp->dp_appendoff == newoff );
dtp->dt_at_endpr = BOOL_TRUE;
}
if (dtp->dt_off + sizeof(dirattr_t) > sizeof(dtp->dt_buf)) {
if (dirattr_flush() != RV_OK) {
return DAH_NULL;
}
}
/* calculate the index of this dirattr
*/
oldoff = dpp->dp_appendoff;
dix = OFF2DIX( oldoff );
ASSERT( dix <= DIX_MAX );
/* populate a dirattr
*/
dirattr.d_mode = ( mode_t )fhdrp->fh_stat.bs_mode;
dirattr.d_uid = ( uid_t )fhdrp->fh_stat.bs_uid;
dirattr.d_gid = ( gid_t )fhdrp->fh_stat.bs_gid;
dirattr.d_atime = ( time32_t )fhdrp->fh_stat.bs_atime.tv_sec;
dirattr.d_mtime = ( time32_t )fhdrp->fh_stat.bs_mtime.tv_sec;
dirattr.d_ctime = ( time32_t )fhdrp->fh_stat.bs_ctime.tv_sec;
dirattr.d_xflags = fhdrp->fh_stat.bs_xflags;
dirattr.d_extsize = ( u_int32_t )fhdrp->fh_stat.bs_extsize;
dirattr.d_projid = fhdrp->fh_stat.bs_projid;
dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask;
dirattr.d_dmstate = ( u_int32_t )fhdrp->fh_stat.bs_dmstate;
#ifdef DIRATTRCHK
dirattr.d_unq = DIRATTRUNQ;
sum = calcdixcum( dix );
dirattr.d_sum = sum;
#endif /* DIRATTRCHK */
dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL;
/* write the entry into our buffer
*/
memcpy(dtp->dt_buf + dtp->dt_off, (void *)&dirattr, sizeof(dirattr_t));
dtp->dt_off += sizeof(dirattr_t);
/* update the next write offset
*/
ASSERT( dpp->dp_appendoff <= OFF64MAX - ( off64_t )sizeof(dirattr_t) );
dpp->dp_appendoff += ( off64_t )sizeof(dirattr_t);
#ifdef DIRATTRCHK
dah = HDLMKHDL( sum, dix );
#else /* DIRATTRCHK */
dah = ( dah_t )dix;
#endif /* DIRATTRCHK */
return dah;
}
void
dirattr_addextattr( dah_t dah, extattrhdr_t *ahdrp )
{
off64_t oldoff;
off64_t off;
off64_t seekoff;
off64_t nulloff;
intgen_t nread;
intgen_t nwritten;
/* pull the selected dir attributes into the cache
*/
dirattr_get( dah );
/* open/create extended attributes file if not yet done
*/
if ( dtp->dt_extattrfd < 0 ) {
if ( dtp->dt_extattrfdbadpr ) {
return;
}
dtp->dt_extattrfd = open( dtp->dt_extattrpathname,
O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR );
if ( dtp->dt_extattrfd < 0 ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not open/create directory "
"extended attributes file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
}
/* seek to the end of the dir extattr list
*/
off = dtp->dt_cached_dirattr.d_extattroff;
oldoff = DIRATTR_EXTATTROFFNULL;
while ( off != DIRATTR_EXTATTROFFNULL ) {
seekoff = lseek64( dtp->dt_extattrfd, off, SEEK_SET );
if ( seekoff < 0 ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to into extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
ASSERT( seekoff == off );
oldoff = off;
nread = read( dtp->dt_extattrfd,
( void * )&off,
sizeof( off ));
if ( nread != ( intgen_t )sizeof( off )) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
}
/* append the extended attributes
*/
off = lseek64( dtp->dt_extattrfd, 0, SEEK_END );
if ( off < 0 ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to end of extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
nulloff = DIRATTR_EXTATTROFFNULL;
nwritten = write( dtp->dt_extattrfd,
( void * )&nulloff,
sizeof( nulloff ));
if ( nwritten != ( intgen_t )sizeof( nulloff )) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not write extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
nwritten = write( dtp->dt_extattrfd, ( void * )ahdrp, ahdrp->ah_sz );
if ( nwritten != ( intgen_t )( ahdrp->ah_sz )) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not write at end of extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
/* fill in the offset of the extended attributes into the
* linked list
*/
if ( oldoff == DIRATTR_EXTATTROFFNULL ) {
dtp->dt_cached_dirattr.d_extattroff = off;
dirattr_cacheflush( );
} else {
seekoff = lseek64( dtp->dt_extattrfd, oldoff, SEEK_SET );
if ( seekoff < 0 ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to into extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
ASSERT( seekoff == oldoff );
nwritten = write( dtp->dt_extattrfd,
( void * )&off,
sizeof( off ));
if ( nwritten != ( intgen_t )sizeof( off )) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not write extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return;
}
}
}
bool_t
dirattr_cb_extattr( dah_t dah,
bool_t ( * cbfunc )( extattrhdr_t *ahdrp,
void *ctxp ),
extattrhdr_t *ahdrp,
void *ctxp )
{
off64_t off;
/* pull the selected dir attributes into the cache
*/
dirattr_get( dah );
/* open/create extended attributes file if not yet done
*/
if ( dtp->dt_extattrfd < 0 ) {
if ( dtp->dt_extattrfdbadpr ) {
return BOOL_TRUE;
}
dtp->dt_extattrfd = open( dtp->dt_extattrpathname,
O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR );
if ( dtp->dt_extattrfd < 0 ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not open/create directory "
"extended attributes file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
}
/* walk through the dirattr list for this dah
*/
off = dtp->dt_cached_dirattr.d_extattroff;
while ( off != DIRATTR_EXTATTROFFNULL ) {
off64_t seekoff;
intgen_t nread;
off64_t nextoff;
size_t recsz;
bool_t ok;
/* seek to the extattr
*/
seekoff = lseek64( dtp->dt_extattrfd, off, SEEK_SET );
if ( seekoff < 0 ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not seek to into extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
ASSERT( seekoff == off );
/* peel off the next offset
*/
nread = read( dtp->dt_extattrfd,
( void * )&nextoff,
sizeof( nextoff ));
if ( nread != ( intgen_t )sizeof( nextoff )) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
/* read the extattr hdr
*/
nread = read( dtp->dt_extattrfd,
( void * )ahdrp,
EXTATTRHDR_SZ );
if ( nread != EXTATTRHDR_SZ ) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
/* read the remainder of the extattr
*/
recsz = ( size_t )ahdrp->ah_sz;
ASSERT( recsz >= EXTATTRHDR_SZ );
nread = read( dtp->dt_extattrfd,
( void * )&ahdrp[ 1 ],
recsz - EXTATTRHDR_SZ );
if ( nread != ( intgen_t )( recsz - EXTATTRHDR_SZ )) {
mlog( MLOG_NORMAL | MLOG_WARNING, _(
"could not read extended attributes "
"file %s: "
"%s (%d)\n"),
dtp->dt_extattrpathname,
strerror( errno ),
errno );
dtp->dt_extattrfdbadpr = BOOL_TRUE;
return BOOL_TRUE;
}
/* call the callback func
*/
ok = ( * cbfunc )( ahdrp, ctxp );
if ( ! ok ) {
return BOOL_FALSE;
}
/* go th the next one
*/
off = nextoff;
}
return BOOL_TRUE;
}
void
dirattr_update( dah_t dah, filehdr_t *fhdrp )
{
dix_t dix;
#ifdef DIRATTRCHK
u_int16_t sum;
#endif /* DIRATTRCHK */
off64_t argoff;
off64_t newoff;
dirattr_t dirattr;
intgen_t nwritten;
/* sanity checks
*/
ASSERT( dtp );
ASSERT( dpp );
ASSERT( dah != DAH_NULL );
#ifdef DIRATTRCHK
sum = HDLGETSUM( dah );
dix = HDLGETDIX( dah );
#else /* DIRATTRCHK */
dix = ( dix_t )dah;
#endif /* DIRATTRCHK */
ASSERT( dix >= 0 );
ASSERT( dix <= DIX_MAX );
argoff = DIX2OFF( dix );
ASSERT( argoff >= 0 );
ASSERT( argoff >= ( off64_t )DIRATTR_PERS_SZ );
ASSERT( argoff <= dpp->dp_appendoff - ( off64_t )sizeof( dirattr_t ));
#ifdef DIRATTRCHK
dirattr_get( dah );
ASSERT( dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ );
ASSERT( dtp->dt_cached_dirattr.d_sum == sum );
#endif /* DIRATTRCHK */
if ( dtp->dt_at_endpr && dtp->dt_off ) {
if (dirattr_flush() != RV_OK) {
assert( 0 );
return;
}
}
/* seek to the dirattr
*/
newoff = lseek64( dtp->dt_fd, argoff, SEEK_SET );
if ( newoff == ( off64_t )-1 ) {
mlog( MLOG_NORMAL, _(
"lseek of dirattr failed: %s\n"),
strerror( errno ));
ASSERT( 0 );
}
ASSERT( newoff == argoff );
/* populate a dirattr
*/
dirattr.d_mode = ( mode_t )fhdrp->fh_stat.bs_mode;
dirattr.d_uid = ( uid_t )fhdrp->fh_stat.bs_uid;
dirattr.d_gid = ( gid_t )fhdrp->fh_stat.bs_gid;
dirattr.d_atime = ( time32_t )fhdrp->fh_stat.bs_atime.tv_sec;
dirattr.d_mtime = ( time32_t )fhdrp->fh_stat.bs_mtime.tv_sec;
dirattr.d_ctime = ( time32_t )fhdrp->fh_stat.bs_ctime.tv_sec;
dirattr.d_xflags = fhdrp->fh_stat.bs_xflags;
dirattr.d_extsize = ( u_int32_t )fhdrp->fh_stat.bs_extsize;
dirattr.d_projid = fhdrp->fh_stat.bs_projid;
dirattr.d_dmevmask = fhdrp->fh_stat.bs_dmevmask;
dirattr.d_dmstate = ( u_int32_t )fhdrp->fh_stat.bs_dmstate;
dirattr.d_extattroff = DIRATTR_EXTATTROFFNULL;
/* write the dirattr
*/
nwritten = write( dtp->dt_fd, ( void * )&dirattr, sizeof( dirattr ));
if ( ( size_t )nwritten != sizeof( dirattr )) {
mlog( MLOG_NORMAL, _(
"update of dirattr failed: %s\n"),
strerror( errno ));
ASSERT( 0 );
}
dtp->dt_at_endpr = BOOL_FALSE;
dtp->dt_cachedh = dah;
}
/* ARGSUSED */
void
dirattr_del( dah_t dah )
{
}
mode_t
dirattr_get_mode( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_mode;
}
uid_t
dirattr_get_uid( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_uid;
}
uid_t
dirattr_get_gid( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_gid;
}
time32_t
dirattr_get_atime( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_atime;
}
time32_t
dirattr_get_mtime( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_mtime;
}
time32_t
dirattr_get_ctime( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_ctime;
}
u_int32_t
dirattr_get_xflags( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_xflags;
}
u_int32_t
dirattr_get_extsize( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_extsize;
}
u_int32_t
dirattr_get_projid( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_projid;
}
u_int32_t
dirattr_get_dmevmask( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_dmevmask;
}
u_int32_t
dirattr_get_dmstate( dah_t dah )
{
dirattr_get( dah );
return dtp->dt_cached_dirattr.d_dmstate;
}
rv_t
dirattr_flush()
{
ssize_t nwritten;
/* sanity checks
*/
assert ( dtp );
if (dtp->dt_off) {
/* write the accumulated dirattr entries
*/
nwritten = write( dtp->dt_fd, ( void * )dtp->dt_buf, dtp->dt_off);
if ( nwritten != dtp->dt_off ) {
if ( nwritten < 0 ) {
mlog( MLOG_NORMAL | MLOG_ERROR,
_("write of dirattr buffer failed: %s\n"),
strerror( errno ));
} else {
mlog( MLOG_NORMAL | MLOG_ERROR,
_("write of dirattr buffer failed: "
"expected to write %ld, actually "
"wrote %ld\n"), dtp->dt_off, nwritten);
}
assert( 0 );
return RV_UNKNOWN;
}
dtp->dt_off = 0;
}
return RV_OK;
}
/* definition of locally defined static functions ****************************/
static void
dirattr_get( dah_t dah )
{
dix_t dix;
off64_t argoff;
off64_t newoff;
intgen_t nread;
#ifdef DIRATTRCHK
u_int16_t sum;
#endif /* DIRATTRCHK */
/* sanity checks
*/
ASSERT( dtp );
ASSERT( dpp );
ASSERT( dah != DAH_NULL );
/* if we are already holding this dirattr in cache,
* just return
*/
if ( dtp->dt_cachedh == dah ) {
return;
}
#ifdef DIRATTRCHK
sum = HDLGETSUM( dah );
dix = HDLGETDIX( dah );
#else /* DIRATTRCHK */
dix = ( dix_t )dah;
#endif /* DIRATTRCHK */
ASSERT( dix >= 0 );
ASSERT( dix <= DIX_MAX );
argoff = DIX2OFF( dix );
ASSERT( argoff >= 0 );
ASSERT( argoff >= ( off64_t )DIRATTR_PERS_SZ );
ASSERT( argoff <= dpp->dp_appendoff - ( off64_t )sizeof( dirattr_t ));
if ( dtp->dt_at_endpr && dtp->dt_off ) {
if (dirattr_flush() != RV_OK) {
assert( 0 );
return;
}
}
/* seek to the dirattr
*/
newoff = lseek64( dtp->dt_fd, argoff, SEEK_SET );
if ( newoff == ( off64_t )-1 ) {
mlog( MLOG_NORMAL, _(
"lseek of dirattr failed: %s\n"),
strerror( errno ));
ASSERT( 0 );
}
ASSERT( newoff == argoff );
/* read the dirattr
*/
nread = read( dtp->dt_fd,
( void * )&dtp->dt_cached_dirattr,
sizeof( dtp->dt_cached_dirattr ));
if ( ( size_t )nread != sizeof( dtp->dt_cached_dirattr )) {
mlog( MLOG_NORMAL, _(
"read of dirattr failed: %s\n"),
strerror( errno ));
ASSERT( 0 );
}
#ifdef DIRATTRCHK
ASSERT( dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ );
ASSERT( dtp->dt_cached_dirattr.d_sum == sum );
#endif /* DIRATTRCHK */
dtp->dt_at_endpr = BOOL_FALSE;
dtp->dt_cachedh = dah;
}
static void
dirattr_cacheflush( void )
{
dah_t dah;
dix_t dix;
#ifdef DIRATTRCHK
u_int16_t sum;
#endif /* DIRATTRCHK */
off64_t argoff;
off64_t newoff;
intgen_t nwritten;
/* sanity checks
*/
ASSERT( dtp );
ASSERT( dpp );
/* if nothing in the cache, ignore
*/
dah = dtp->dt_cachedh;
ASSERT( dah != DAH_NULL );
if ( dah == DAH_NULL ) {
return;
}
#ifdef DIRATTRCHK
sum = HDLGETSUM( dah );
dix = HDLGETDIX( dah );
#else /* DIRATTRCHK */
dix = ( dix_t )dah;
#endif /* DIRATTRCHK */
#ifdef DIRATTRCHK
ASSERT( dtp->dt_cached_dirattr.d_unq == DIRATTRUNQ );
ASSERT( dtp->dt_cached_dirattr.d_sum == sum );
#endif /* DIRATTRCHK */
ASSERT( dix >= 0 );
ASSERT( dix <= DIX_MAX );
argoff = DIX2OFF( dix );
ASSERT( argoff >= 0 );
ASSERT( argoff >= ( off64_t )DIRATTR_PERS_SZ );
ASSERT( argoff <= dpp->dp_appendoff - ( off64_t )sizeof( dirattr_t ));
/* seek to the dirattr
*/
newoff = lseek64( dtp->dt_fd, argoff, SEEK_SET );
if ( newoff == ( off64_t )-1 ) {
mlog( MLOG_NORMAL, _(
"lseek of dirattr failed: %s\n"),
strerror( errno ));
ASSERT( 0 );
}
ASSERT( newoff == argoff );
/* write the dirattr
*/
nwritten = write( dtp->dt_fd,
( void * )&dtp->dt_cached_dirattr,
sizeof( dtp->dt_cached_dirattr ));
if ( ( size_t )nwritten != sizeof( dtp->dt_cached_dirattr )) {
mlog( MLOG_NORMAL, _(
"flush of dirattr failed: %s\n"),
strerror( errno ));
ASSERT( 0 );
}
dtp->dt_at_endpr = BOOL_FALSE;
}
#ifdef DIRATTRCHK
static u_int16_t
calcdixcum( dix_t dix )
{
u_int16_t sum;
ix_t nibcnt;
ix_t nibix;
ASSERT( ( sizeof( dah_t ) / HDLSUMCNT ) * HDLSUMCNT == sizeof( dah_t ));
nibcnt = ( sizeof( dah_t ) / HDLSUMCNT ) - 1;
sum = 0;
for ( nibix = 0 ; nibix < nibcnt ; nibix++ ) {
sum += ( u_int16_t )( dix & HDLSUMLOMASK );
dix >>= HDLSUMCNT;
}
sum = ( u_int16_t )( ( ~sum + 1 ) & HDLSUMLOMASK );
return sum;
}
#endif /* DIRATTRCHK */