* directory or online at http://www.openafs.org/dl/license10.html
*
* Portions Copyright (c) 2003 Apple Computer, Inc.
+ * Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
#include <ctype.h>
+#include <string.h>
#ifdef AFS_NT40_ENV
#include <windows.h>
#include <winbase.h>
#else
#include <sys/param.h>
#include <sys/types.h>
+#include <unistd.h>
#if AFS_HAVE_STATVFS || AFS_HAVE_STATVFS64
#include <sys/statvfs.h>
#include <mntent.h>
#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
#include <rx/xdr.h>
#include <afs/afsint.h>
#include "nfs.h"
/*@printflike@*/ extern void Log(const char *format, ...);
int aixlow_water = 8; /* default 8% */
-struct DiskPartition *DiskPartitionList;
+struct DiskPartition64 *DiskPartitionList;
+
+#ifdef AFS_DEMAND_ATTACH_FS
+static struct DiskPartition64 *DiskPartitionTable[VOLMAXPARTS+1];
+
+static struct DiskPartition64 * VLookupPartition_r(char * path);
+static void AddPartitionToTable_r(struct DiskPartition64 *);
+#endif /* AFS_DEMAND_ATTACH_FS */
#ifdef AFS_SGI_XFS_IOPS_ENV
/* Verify that the on disk XFS inodes on the partition are large enough to
}
return code;
}
-#endif
+#endif /* AFS_SGI_XFS_IOPS_ENV */
+int
+VInitPartitionPackage(void)
+{
+#ifdef AFS_DEMAND_ATTACH_ENV
+ memset(&DiskPartitionTable, 0, sizeof(DiskPartitionTable));
+#endif /* AFS_DEMAND_ATTACH_ENV */
+ return 0;
+}
static void
VInitPartition_r(char *path, char *devname, Device dev)
{
- struct DiskPartition *dp, *op;
- dp = (struct DiskPartition *)malloc(sizeof(struct DiskPartition));
+ struct DiskPartition64 *dp, *op;
+ dp = (struct DiskPartition64 *)malloc(sizeof(struct DiskPartition64));
/* Add it to the end, to preserve order when we print statistics */
for (op = DiskPartitionList; op; op = op->next) {
if (!op->next)
dp->next = 0;
dp->name = (char *)malloc(strlen(path) + 1);
strncpy(dp->name, path, strlen(path) + 1);
+ dp->index = volutil_GetPartitionID(path);
#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
/* Create a lockfile for the partition, of the form /vicepa/Lock/vicepa */
dp->devName = (char *)malloc(2 * strlen(path) + 6);
mkdir(dp->devName, 0700);
strcat(dp->devName, path);
close(afs_open(dp->devName, O_RDWR | O_CREAT, 0600));
- dp->device = volutil_GetPartitionID(path);
+ dp->device = dp->index;
#else
dp->devName = (char *)malloc(strlen(devname) + 1);
strncpy(dp->devName, devname, strlen(devname) + 1);
dp->device = dev;
#endif
- dp->lock_fd = -1;
+ dp->lock_fd = INVALID_FD;
dp->flags = 0;
dp->f_files = 1; /* just a default value */
#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
(void)namei_ViceREADME(VPartitionPath(dp));
#endif
VSetPartitionDiskUsage_r(dp);
+#ifdef AFS_DEMAND_ATTACH_FS
+ AddPartitionToTable_r(dp);
+ queue_Init(&dp->vol_list.head);
+ assert(pthread_cond_init(&dp->vol_list.cv, NULL) == 0);
+ dp->vol_list.len = 0;
+ dp->vol_list.busy = 0;
+#endif /* AFS_DEMAND_ATTACH_FS */
}
static void
VInitPartition(char *path, char *devname, Device dev)
{
- VOL_LOCK VInitPartition_r(path, devname, dev);
-VOL_UNLOCK}
+ VOL_LOCK;
+ VInitPartition_r(path, devname, dev);
+ VOL_UNLOCK;
+}
#ifndef AFS_NT40_ENV
/* VAttachPartitions() finds the vice partitions on this server. Calls
dirp = opendir(part);
assert(dirp);
- while (dp = readdir(dirp)) {
+ while ((dp = readdir(dirp))) {
if (dp->d_name[0] == 'V') {
Log("This program is compiled with AFS_NAMEI_ENV, but partition %s seems to contain volumes which don't use the namei-interface; aborting\n", part);
closedir(dirp);
Log("This program is compiled without AFS_NAMEI_ENV, but partition %s seems to contain volumes which use the namei-interface; aborting\n", part);
return -1;
}
-#endif /* AFS_NAMEI_ENV */
-#endif
#ifdef AFS_SGI_XFS_IOPS_ENV
if (VerifyXFSInodeSize(part, status.st_fstype) < 0)
return -1;
#endif
+#endif /* AFS_NAMEI_ENV */
+#endif /* !AFS_LINUX20_ENV && !AFS_NT40_ENV */
#if defined(AFS_DUX40_ENV) && !defined(AFS_NAMEI_ENV)
- if (afs_status.st_ino != ROOTINO) {
+ if (status.st_ino != ROOTINO) {
Log("%s is not a mounted file system; ignored.\n", part);
return 0;
}
* partitions, in the NAMEI fileserver.
*/
void
-VAttachPartitions2()
+VAttachPartitions2(void)
{
#ifdef AFS_NAMEI_ENV
DIR *dirp;
}
while (!getmntent(mntfile, &mnt)) {
/* Ignore non ufs or non read/write partitions */
- if ((strcmp(mnt.mnt_fstype, "ufs") != 0)
+ /* but allow zfs too if we're in the NAMEI environment */
+ if (
+#ifdef AFS_NAMEI_ENV
+ (((strcmp(mnt.mnt_fstype, "ufs") &&
+ strcmp(mnt.mnt_fstype, "zfs"))))
+#else
+ (strcmp(mnt.mnt_fstype, "ufs") != 0)
+#endif
|| (strncmp(mnt.mnt_mntopts, "ro,ignore", 9) == 0))
continue;
-
+
/* If we're going to always attach this partition, do it later. */
if (VIsAlwaysAttach(mnt.mnt_mountp))
continue;
+#ifndef AFS_NAMEI_ENV
+ if (hasmntopt(&mnt, "logging") != NULL) {
+ Log("This program is compiled without AFS_NAMEI_ENV, and "
+ "partition %s is mounted with the 'logging' option. "
+ "Using the inode fileserver backend with 'logging' UFS "
+ "partitions causes volume corruption, so please either "
+ "mount the partition without logging, or use the namei "
+ "fileserver backend. Aborting...\n", mnt.mnt_mountp);
+ errors++;
+ }
+#endif /* !AFS_NAMEI_ENV */
+
if (VCheckPartition(mnt.mnt_mountp, mnt.mnt_special) < 0)
errors++;
}
exit(-1);
}
- while (fsent = getfsent()) {
+ while ((fsent = getfsent())) {
if (strcmp(fsent->fs_type, "rw") != 0)
continue;
int
VAttachPartitions(void)
{
- struct DiskPartition *partP, *prevP, *nextP;
+ struct DiskPartition64 *partP, *prevP, *nextP;
struct vpt_iter iter;
struct vptab entry;
* is required. The canonical name is still in part->name.
*/
char *
-VPartitionPath(struct DiskPartition *part)
+VPartitionPath(struct DiskPartition64 *part)
{
#ifdef AFS_NT40_ENV
return part->devName;
}
/* get partition structure, abortp tells us if we should abort on failure */
-struct DiskPartition *
+struct DiskPartition64 *
VGetPartition_r(char *name, int abortp)
{
- register struct DiskPartition *dp;
+ register struct DiskPartition64 *dp;
+#ifdef AFS_DEMAND_ATTACH_FS
+ dp = VLookupPartition_r(name);
+#else /* AFS_DEMAND_ATTACH_FS */
for (dp = DiskPartitionList; dp; dp = dp->next) {
if (strcmp(dp->name, name) == 0)
break;
}
+#endif /* AFS_DEMAND_ATTACH_FS */
if (abortp)
assert(dp != NULL);
return dp;
}
-struct DiskPartition *
+struct DiskPartition64 *
VGetPartition(char *name, int abortp)
{
- struct DiskPartition *retVal;
- VOL_LOCK retVal = VGetPartition_r(name, abortp);
- VOL_UNLOCK return retVal;
+ struct DiskPartition64 *retVal;
+ VOL_LOCK;
+ retVal = VGetPartition_r(name, abortp);
+ VOL_UNLOCK;
+ return retVal;
}
#ifdef AFS_NT40_ENV
void
-VSetPartitionDiskUsage_r(register struct DiskPartition *dp)
+VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
{
ULARGE_INTEGER free_user, total, free_total;
int ufree, tot, tfree;
#else
void
-VSetPartitionDiskUsage_r(register struct DiskPartition *dp)
+VSetPartitionDiskUsage_r(register struct DiskPartition64 *dp)
{
- int fd, totalblks, free, used, availblks, bsize, code;
+ int bsize, code;
+ afs_int64 totalblks, free, used, availblks;
int reserved;
#ifdef afs_statvfs
struct afs_statvfs statbuf;
#endif /* AFS_NT40_ENV */
void
-VSetPartitionDiskUsage(register struct DiskPartition *dp)
+VSetPartitionDiskUsage(register struct DiskPartition64 *dp)
{
- VOL_LOCK VSetPartitionDiskUsage_r(dp);
-VOL_UNLOCK}
+ VOL_LOCK;
+ VSetPartitionDiskUsage_r(dp);
+ VOL_UNLOCK;
+}
void
VResetDiskUsage_r(void)
{
- struct DiskPartition *dp;
+ struct DiskPartition64 *dp;
for (dp = DiskPartitionList; dp; dp = dp->next) {
VSetPartitionDiskUsage_r(dp);
#ifndef AFS_PTHREAD_ENV
void
VResetDiskUsage(void)
{
- VOL_LOCK VResetDiskUsage_r();
-VOL_UNLOCK}
+ VOL_LOCK;
+ VResetDiskUsage_r();
+ VOL_UNLOCK;
+}
void
VAdjustDiskUsage_r(Error * ec, Volume * vp, afs_sfsize_t blocks,
VAdjustDiskUsage(Error * ec, Volume * vp, afs_sfsize_t blocks,
afs_sfsize_t checkBlocks)
{
- VOL_LOCK VAdjustDiskUsage_r(ec, vp, blocks, checkBlocks);
-VOL_UNLOCK}
+ VOL_LOCK;
+ VAdjustDiskUsage_r(ec, vp, blocks, checkBlocks);
+ VOL_UNLOCK;
+}
int
VDiskUsage_r(Volume * vp, afs_sfsize_t blocks)
VDiskUsage(Volume * vp, afs_sfsize_t blocks)
{
int retVal;
- VOL_LOCK retVal = VDiskUsage_r(vp, blocks);
- VOL_UNLOCK return retVal;
+ VOL_LOCK;
+ retVal = VDiskUsage_r(vp, blocks);
+ VOL_UNLOCK;
+ return retVal;
}
void
VPrintDiskStats_r(void)
{
- struct DiskPartition *dp;
+ struct DiskPartition64 *dp;
for (dp = DiskPartitionList; dp; dp = dp->next) {
Log("Partition %s: %d available 1K blocks (minfree=%d), ", dp->name,
dp->totalUsable, dp->minFree);
void
VPrintDiskStats(void)
{
- VOL_LOCK VPrintDiskStats_r();
-VOL_UNLOCK}
+ VOL_LOCK;
+ VPrintDiskStats_r();
+ VOL_UNLOCK;
+}
#ifdef AFS_NT40_ENV
/* Need a separate lock file on NT, since NT only has mandatory file locks. */
void
VLockPartition_r(char *name)
{
- struct DiskPartition *dp = VGetPartition_r(name, 0);
+ struct DiskPartition64 *dp = VGetPartition_r(name, 0);
OVERLAPPED lap;
if (!dp)
return;
- if (dp->lock_fd == -1) {
+ if (dp->lock_fd == INVALID_FD) {
char path[64];
int rc;
(void)sprintf(path, "%s\\%s", VPartitionPath(dp), LOCKFILE);
dp->lock_fd =
- (int)CreateFile(path, GENERIC_WRITE,
+ (FD_t)CreateFile(path, GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
- assert(dp->lock_fd != (int)INVALID_HANDLE_VALUE);
+ assert(dp->lock_fd != INVALID_FD);
- memset((char *)&lap, 0, sizeof(lap));
+ memset(&lap, 0, sizeof(lap));
rc = LockFileEx((HANDLE) dp->lock_fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1,
0, &lap);
assert(rc);
void
VUnlockPartition_r(char *name)
{
- register struct DiskPartition *dp = VGetPartition_r(name, 0);
+ register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
OVERLAPPED lap;
if (!dp)
return; /* no partition, will fail later */
- memset((char *)&lap, 0, sizeof(lap));
+ memset(&lap, 0, sizeof(lap));
UnlockFileEx((HANDLE) dp->lock_fd, 0, 1, 0, &lap);
CloseHandle((HANDLE) dp->lock_fd);
- dp->lock_fd = -1;
+ dp->lock_fd = INVALID_FD;
}
#else /* AFS_NT40_ENV */
void
VLockPartition_r(char *name)
{
- register struct DiskPartition *dp = VGetPartition_r(name, 0);
+ register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
char *partitionName;
int retries, code;
struct timeval pausing;
void
VUnlockPartition_r(char *name)
{
- register struct DiskPartition *dp = VGetPartition_r(name, 0);
+ register struct DiskPartition64 *dp = VGetPartition_r(name, 0);
if (!dp)
return; /* no partition, will fail later */
close(dp->lock_fd);
void
VLockPartition(char *name)
{
- VOL_LOCK VLockPartition_r(name);
-VOL_UNLOCK}
+ VOL_LOCK;
+ VLockPartition_r(name);
+ VOL_UNLOCK;
+}
void
VUnlockPartition(char *name)
{
- VOL_LOCK VUnlockPartition_r(name);
-VOL_UNLOCK}
+ VOL_LOCK;
+ VUnlockPartition_r(name);
+ VOL_UNLOCK;
+}
+
+#ifdef AFS_DEMAND_ATTACH_FS
+
+/* XXX not sure this will work on AFS_NT40_ENV
+ * needs to be tested!
+ */
+
+/**
+ * lookup a disk partition object by its index number.
+ *
+ * @param[in] id partition index number
+ * @param[in] abortp see abortp usage note below
+ *
+ * @return disk partition object
+ * @retval NULL no such disk partition
+ *
+ * @note when abortp is non-zero, lookups which would return
+ * NULL will result in an assertion failure
+ *
+ * @pre VOL_LOCK must be held
+ *
+ * @internal volume package internal use only
+ */
+
+struct DiskPartition64 *
+VGetPartitionById_r(afs_int32 id, int abortp)
+{
+ struct DiskPartition64 *dp = NULL;
+
+ if ((id >= 0) && (id <= VOLMAXPARTS)) {
+ dp = DiskPartitionTable[id];
+ }
+
+ if (abortp) {
+ assert(dp != NULL);
+ }
+ return dp;
+}
+
+/**
+ * lookup a disk partition object by its index number.
+ *
+ * @param[in] id partition index number
+ * @param[in] abortp see abortp usage note below
+ *
+ * @return disk partition object
+ * @retval NULL no such disk partition
+ *
+ * @note when abortp is non-zero, lookups which would return
+ * NULL will result in an assertion failure
+ */
+
+struct DiskPartition64 *
+VGetPartitionById(afs_int32 id, int abortp)
+{
+ struct DiskPartition64 * dp;
+
+ VOL_LOCK;
+ dp = VGetPartitionById_r(id, abortp);
+ VOL_UNLOCK;
+
+ return dp;
+}
+
+static struct DiskPartition64 *
+VLookupPartition_r(char * path)
+{
+ afs_int32 id = volutil_GetPartitionID(path);
+
+ if (id < 0 || id > VOLMAXPARTS)
+ return NULL;
+
+ return DiskPartitionTable[id];
+}
+
+static void
+AddPartitionToTable_r(struct DiskPartition64 *dp)
+{
+ assert(dp->index >= 0 && dp->index <= VOLMAXPARTS);
+ DiskPartitionTable[dp->index] = dp;
+}
+
+#if 0
+static void
+DeletePartitionFromTable_r(struct DiskPartition64 *dp)
+{
+ assert(dp->index >= 0 && dp->index <= VOLMAXPARTS);
+ DiskPartitionTable[dp->index] = NULL;
+}
+#endif
+#endif /* AFS_DEMAND_ATTACH_FS */