#include <roken.h>
-#define MAXINT (~(1<<((sizeof(int)*8)-1)))
+#include <limits.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <afs/afs_assert.h>
-
-#include <rx/xdr.h>
+#include <afs/opr.h>
+#ifdef AFS_PTHREAD_ENV
+#include <opr/lock.h>
+#endif
#include "rx/rx_queue.h"
#include <afs/afsint.h>
#include "nfs.h"
#include "partition.h"
#include "salvsync.h"
#include "common.h"
-#if defined(AFS_SGI_ENV)
-#include "sys/types.h"
-#include "fcntl.h"
-#undef min
-#undef max
-#include "stdlib.h"
-#endif
#ifdef AFS_NT40_ENV
-#include <fcntl.h>
#include "ntops.h"
-#else
-#include <sys/file.h>
-#ifdef AFS_SUN5_ENV
-#include <sys/fcntl.h>
-#endif
-#include <unistd.h>
-#endif /* AFS_NT40_ENV */
-#include <sys/stat.h>
-
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
#endif
struct VnodeClassInfo VnodeClassInfo[nVNODECLASSES];
vcp->cacheSize = nVnodes;
switch (class) {
case vSmall:
- osi_Assert(CHECKSIZE_SMALLVNODE);
+ opr_Assert(CHECKSIZE_SMALLVNODE);
vcp->lruHead = NULL;
vcp->residentSize = SIZEOF_SMALLVNODE;
vcp->diskSize = SIZEOF_SMALLDISKVNODE;
return 0;
va = (byte *) calloc(nVnodes, vcp->residentSize);
- osi_Assert(va != NULL);
+ opr_Assert(va != NULL);
while (nVnodes--) {
Vnode *vnp = (Vnode *) va;
Vn_refcount(vnp) = 0; /* no context switches */
* allocate an unused vnode from the lru chain.
*
* @param[in] vcp vnode class info object pointer
+ * @param[in] vp volume pointer
+ * @param[in] vnodeNumber new vnode number that the vnode will be used for
*
* @pre VOL_LOCK is held
*
- * @post vnode object is removed from lru, and vnode hash table.
- * vnode is disassociated from volume object.
+ * @post vnode object is removed from lru
+ * vnode is disassociated with its old volume, and associated with its
+ * new volume
+ * vnode is removed from its old vnode hash table, and for DAFS, it is
+ * added to its new hash table
* state is set to VN_STATE_INVALID.
* inode handle is released.
+ * a reservation is held on the vnode object
*
* @note we traverse backwards along the lru circlist. It shouldn't
* be necessary to specify that nUsers == 0 since if it is in the list,
*
* @warning DAFS: VOL_LOCK is dropped while doing inode handle release
*
+ * @warning for non-DAFS, the vnode is _not_ hashed on the vnode hash table;
+ * non-DAFS must hash the vnode itself after loading data
+ *
* @return vnode object pointer
*/
Vnode *
-VGetFreeVnode_r(struct VnodeClassInfo * vcp)
+VGetFreeVnode_r(struct VnodeClassInfo * vcp, struct Volume *vp,
+ VnodeId vnodeNumber)
{
Vnode *vnp;
DeleteFromVVnList(vnp);
}
+ /* we must re-hash the vnp _before_ we drop the glock again; otherwise,
+ * someone else might try to grab the same vnode id, and we'll both alloc
+ * a vnode object for the same vn id, bypassing vnode locking */
+ Vn_id(vnp) = vnodeNumber;
+ VnCreateReservation_r(vnp);
+ AddToVVnList(vp, vnp);
+#ifdef AFS_DEMAND_ATTACH_FS
+ AddToVnHash(vnp);
+#endif
+
/* drop the file descriptor */
if (vnp->handle) {
#ifdef AFS_DEMAND_ATTACH_FS
Vnode *
-VAllocVnode(Error * ec, Volume * vp, VnodeType type)
+VAllocVnode(Error * ec, Volume * vp, VnodeType type, VnodeId in_vnode, Unique in_unique)
{
Vnode *retVal;
VOL_LOCK;
- retVal = VAllocVnode_r(ec, vp, type);
+ retVal = VAllocVnode_r(ec, vp, type, in_vnode, in_unique);
VOL_UNLOCK;
return retVal;
}
* @param[out] ec error code return
* @param[in] vp volume object pointer
* @param[in] type desired vnode type
+ * @param[in] type desired vnode ID (optional)
+ * @param[in] type desired vnode Unique (optional)
*
* @return vnode object pointer
*
* @post vnode allocated and returned
*/
Vnode *
-VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
+VAllocVnode_r(Error * ec, Volume * vp, VnodeType type, VnodeId in_vnode, Unique in_unique)
{
Vnode *vnp;
VnodeId vnodeNumber;
struct VnodeClassInfo *vcp;
VnodeClass class;
Unique unique;
+ struct vnodeIndex *index;
+ unsigned int offset;
+
#ifdef AFS_DEMAND_ATTACH_FS
VolState vol_state_save;
#endif
return NULL;
}
- unique = vp->nextVnodeUnique++;
- if (!unique)
- unique = vp->nextVnodeUnique++;
-
if (vp->nextVnodeUnique > V_uniquifier(vp)) {
VUpdateVolume_r(ec, vp, 0);
if (*ec)
return NULL;
}
- /* Find a slot in the bit map */
- bitNumber = VAllocBitmapEntry_r(ec, vp, &vp->vnodeIndex[class],
- VOL_ALLOC_BITMAP_WAIT);
- if (*ec)
- return NULL;
- vnodeNumber = bitNumberToVnodeNumber(bitNumber, class);
+ /*
+ * If in_vnode and in_unique are specified, we are asked to
+ * allocate a specifc vnode slot. Used by RW replication to
+ * keep vnode IDs consistent with the master.
+ */
+
+ if (!in_vnode) {
+ int rollover = 0;
+
+ unique = vp->nextVnodeUnique++;
+ if (unique == 0) {
+ rollover = 1; /* nextVnodeUnique rolled over */
+ vp->nextVnodeUnique = 2; /* 1 is reserved for the root vnode */
+ unique = vp->nextVnodeUnique++;
+ }
+
+ if (vp->nextVnodeUnique > V_uniquifier(vp) || rollover) {
+ VUpdateVolume_r(ec, vp, 0);
+ if (*ec)
+ return NULL;
+ }
+
+ /* Find a slot in the bit map */
+ bitNumber = VAllocBitmapEntry_r(ec, vp, &vp->vnodeIndex[class],
+ VOL_ALLOC_BITMAP_WAIT);
+
+ if (*ec)
+ return NULL;
+ vnodeNumber = bitNumberToVnodeNumber(bitNumber, class);
+ } else {
+ index = &vp->vnodeIndex[class];
+ if (!in_unique) {
+ *ec = VNOVNODE;
+ return NULL;
+ }
+ /* Catch us up to where the master is */
+ if (in_unique > vp->nextVnodeUnique)
+ vp->nextVnodeUnique = in_unique+1;
+
+ if (vp->nextVnodeUnique > V_uniquifier(vp)) {
+ VUpdateVolume_r(ec, vp, 0);
+ if (*ec)
+ return NULL;
+ }
+
+ unique = in_unique;
+ bitNumber = vnodeIdToBitNumber(in_vnode);
+ offset = bitNumber >> 3;
+
+ /* Mark vnode in use. Grow bitmap if needed. */
+ if ((offset >= index->bitmapSize)
+ || ((*(index->bitmap + offset) & (1 << (bitNumber & 0x7))) == 0))
+ VGrowBitmap(index);
+ /* Should not happen */
+ if (*(index->bitmap + offset) & (1 << (bitNumber & 0x7))) {
+ *ec = VNOVNODE;
+ return NULL;
+ }
+
+ *(index->bitmap + offset) |= (1 << (bitNumber & 0x7));
+ vnodeNumber = in_vnode;
+ }
/*
* DAFS:
}
}
+ /* sanity check: vnode should be blank if it was deleted. If it's
+ * not blank, it is still in use somewhere; but the bitmap told us
+ * this vnode number was free, so something is wrong. */
+ if (vnp->disk.type != vNull) {
+ Error tmp;
+ Log("VAllocVnode: addled bitmap or vnode object! (vol %" AFS_VOLID_FMT ", "
+ "vnode %p, number %ld, type %ld)\n", afs_printable_VolumeId_lu(vp->hashid), vnp,
+ (long)Vn_id(vnp), (long)vnp->disk.type);
+ *ec = EIO;
+ VFreeBitMapEntry_r(&tmp, vp, &vp->vnodeIndex[class], bitNumber,
+ VOL_FREE_BITMAP_WAIT);
+ VInvalidateVnode_r(vnp);
+ VnUnlock(vnp, WRITE_LOCK);
+ VnCancelReservation_r(vnp);
+#ifdef AFS_DEMAND_ATTACH_FS
+ VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
+#else
+ VForceOffline_r(vp, 0);
+#endif
+ return NULL;
+ }
+
} else {
/* no such vnode in the cache */
- vnp = VGetFreeVnode_r(vcp);
-
- /* Initialize the header fields so noone allocates another
- * vnode with the same number */
- Vn_id(vnp) = vnodeNumber;
- VnCreateReservation_r(vnp);
- AddToVVnList(vp, vnp);
-#ifdef AFS_DEMAND_ATTACH_FS
- AddToVnHash(vnp);
-#endif
+ vnp = VGetFreeVnode_r(vcp, vp, vnodeNumber);
/* This will never block (guaranteed by check in VGetFreeVnode_r() */
VnLock(vnp, WRITE_LOCK, VOL_LOCK_HELD, WILL_NOT_DEADLOCK);
}
} else {
/* growing file - grow in a reasonable increment */
- char *buf = (char *)malloc(16 * 1024);
+ char *buf = malloc(16 * 1024);
if (!buf) {
Log("VAllocVnode: can't grow vnode index: out of memory\n");
*ec = ENOMEM;
vnp->disk.uniquifier = unique;
vnp->handle = NULL;
vcp->allocs++;
- vp->header->diskstuff.filecount++;
+ V_filecount(vp)++;
#ifdef AFS_DEMAND_ATTACH_FS
VnChangeState_r(vnp, VN_STATE_EXCLUSIVE);
#endif
dosalv = 0;
} else if (nBytes == -1 && errno == EIO) {
/* disk error; salvage */
- Log("VnLoad: Couldn't read vnode %u, volume %u (%s); volume needs salvage\n", Vn_id(vnp), V_id(vp), V_name(vp));
+ Log("VnLoad: Couldn't read vnode %u, volume %" AFS_VOLID_FMT " (%s); volume needs salvage\n", Vn_id(vnp), afs_printable_VolumeId_lu(V_id(vp)), V_name(vp));
} else {
/* vnode is not allocated */
if (LogLevel >= 5)
- Log("VnLoad: Couldn't read vnode %u, volume %u (%s); read %d bytes, errno %d\n",
- Vn_id(vnp), V_id(vp), V_name(vp), (int)nBytes, errno);
- *ec = VIO;
+ Log("VnLoad: Couldn't read vnode %u, volume %" AFS_VOLID_FMT " (%s); read %d bytes, errno %d\n",
+ Vn_id(vnp), afs_printable_VolumeId_lu(V_id(vp)), V_name(vp), (int)nBytes, errno);
+ *ec = VNOVNODE;
dosalv = 0;
}
goto error_encountered_nolock;
if ((offset >= index->bitmapSize)
|| ((*(index->bitmap + offset) & (1 << (bitNumber & 0x7)))
== 0)) {
- Log("VnLoad: Request for unallocated vnode %u, volume %u (%s) denied.\n", Vn_id(vnp), V_id(vp), V_name(vp));
+ Log("VnLoad: Request for unallocated vnode %u, volume %" AFS_VOLID_FMT " (%s) denied.\n", Vn_id(vnp), afs_printable_VolumeId_lu(V_id(vp)), V_name(vp));
*ec = VNOVNODE;
dosalv = 0;
} else {
- Log("VnLoad: Bad magic number, vnode %u, volume %u (%s); volume needs salvage\n", Vn_id(vnp), V_id(vp), V_name(vp));
+ Log("VnLoad: Bad magic number, vnode %u, volume %" AFS_VOLID_FMT " (%s); volume needs salvage\n", Vn_id(vnp), afs_printable_VolumeId_lu(V_id(vp)), V_name(vp));
}
}
goto error_encountered;
}
- IH_INIT(vnp->handle, V_device(vp), V_parentId(vp), VN_GET_INO(vnp));
+ IH_INIT(vnp->handle, V_device(vp), afs_printable_VolumeId_lu(V_parentId(vp)), VN_GET_INO(vnp));
VnUnlock(vnp, WRITE_LOCK);
#ifdef AFS_DEMAND_ATTACH_FS
VnChangeState_r(vnp, VN_STATE_ONLINE);
VnChangeState_r(vnp, VN_STATE_ERROR);
#endif
} else {
- Log("VnStore: Couldn't write vnode %u, volume %u (%s) (error %d)\n", Vn_id(vnp), V_id(Vn_volume(vnp)), V_name(Vn_volume(vnp)), (int)nBytes);
+ Log("VnStore: Couldn't write vnode %u, volume %" AFS_VOLID_FMT " (%s) (error %d)\n", Vn_id(vnp), afs_printable_VolumeId_lu(V_id(Vn_volume(vnp))), V_name(Vn_volume(vnp)), (int)nBytes);
#ifdef AFS_DEMAND_ATTACH_FS
goto error_encountered;
#else
VnChangeState_r(vnp, VN_STATE_ERROR);
VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
#else
- osi_Assert(1 == 2);
+ opr_abort();
#endif
}
/* Not in cache; tentatively grab most distantly used one from the LRU
* chain */
vcp->reads++;
- vnp = VGetFreeVnode_r(vcp);
+ vnp = VGetFreeVnode_r(vcp, vp, vnodeNumber);
/* Initialize */
vnp->changed_newTime = vnp->changed_oldTime = 0;
vnp->delete = 0;
- Vn_id(vnp) = vnodeNumber;
- VnCreateReservation_r(vnp);
- AddToVVnList(vp, vnp);
-#ifdef AFS_DEMAND_ATTACH_FS
- AddToVnHash(vnp);
-#endif
/*
* XXX for non-DAFS, there is a serious
struct VnodeClassInfo *vcp;
*ec = 0;
- osi_Assert(Vn_refcount(vnp) != 0);
+ opr_Assert(Vn_refcount(vnp) != 0);
class = vnodeIdToClass(Vn_id(vnp));
vcp = &VnodeClassInfo[class];
- osi_Assert(vnp->disk.vnodeMagic == vcp->magic);
+ opr_Assert(vnp->disk.vnodeMagic == vcp->magic);
VNLog(200, 2, Vn_id(vnp), (intptr_t) vnp, 0, 0);
#ifdef AFS_DEMAND_ATTACH_FS
if (vnp->changed_oldTime || vnp->changed_newTime || vnp->delete) {
Volume *vp = Vn_volume(vnp);
afs_uint32 now = FT_ApproxTime();
- osi_Assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
+ opr_Assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
if (vnp->delete) {
/* No longer any directory entries for this vnode. Free the Vnode */
if (vnp->changed_newTime)
{
V_updateDate(vp) = vp->updateTime = now;
- if(V_volUpCounter(vp)<MAXINT)
- V_volUpCounter(vp)++;
+ if(V_volUpdateCounter(vp)< UINT_MAX)
+ V_volUpdateCounter(vp)++;
}
/* The vnode has been changed. Write it out to disk */
#ifdef AFS_DEMAND_ATTACH_FS
VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
#else
- osi_Assert(V_needsSalvaged(vp));
+ opr_Assert(V_needsSalvaged(vp));
*ec = VSALVAGE;
#endif
} else {
* (doing so could cause a "addled bitmap" message).
*/
if (vnp->delete && !*ec) {
- if (Vn_volume(vnp)->header->diskstuff.filecount-- < 1)
- Vn_volume(vnp)->header->diskstuff.filecount = 0;
+ if (V_filecount(Vn_volume(vnp))-- < 1)
+ V_filecount(Vn_volume(vnp)) = 0;
VFreeBitMapEntry_r(ec, vp, &vp->vnodeIndex[class],
vnodeIdToBitNumber(Vn_id(vnp)),
VOL_FREE_BITMAP_WAIT);
#endif /* AFS_PTHREAD_ENV */
*ec = 0;
- osi_Assert(Vn_refcount(vnp) != 0);
+ opr_Assert(Vn_refcount(vnp) != 0);
class = vnodeIdToClass(Vn_id(vnp));
vcp = &VnodeClassInfo[class];
- osi_Assert(vnp->disk.vnodeMagic == vcp->magic);
+ opr_Assert(vnp->disk.vnodeMagic == vcp->magic);
VNLog(300, 2, Vn_id(vnp), (intptr_t) vnp, 0, 0);
#ifdef AFS_DEMAND_ATTACH_FS
if (vnp->changed_oldTime || vnp->changed_newTime) {
Volume *vp = Vn_volume(vnp);
afs_uint32 now = FT_ApproxTime();
- osi_Assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
+ opr_Assert(Vn_cacheCheck(vnp) == vp->cacheCheck);
if (vnp->changed_newTime)
vnp->disk.serverModifyTime = now;
if (vnp->changed_newTime)
#ifdef AFS_DEMAND_ATTACH_FS
VRequestSalvage_r(ec, vp, SALVSYNC_ERROR, 0);
#else
- osi_Assert(V_needsSalvaged(vp));
+ opr_Assert(V_needsSalvaged(vp));
*ec = VSALVAGE;
#endif
} else {
#endif /* AFS_DEMAND_ATTACH_FS */
/* XXX need better error handling here */
- osi_Assert(VInvalidateVnodesByVolume_r(vp,
- &ih_vec,
- &vec_len) == 0);
+ opr_Verify(VInvalidateVnodesByVolume_r(vp, &ih_vec,
+ &vec_len) == 0);
/*
* DAFS:
for (i = 0; i < vec_len; i++) {
IH_REALLYCLOSE(ih_vec[i]);
+ IH_RELEASE(ih_vec[i]);
}
free(ih_vec);
#endif /* AFS_DEMAND_ATTACH_FS */
/* XXX need better error handling here */
- osi_Assert(VInvalidateVnodesByVolume_r(vp,
- &ih_vec,
- &vec_len) == 0);
+ opr_Verify(VInvalidateVnodesByVolume_r(vp, &ih_vec,
+ &vec_len) == 0);
/*
* DAFS: