* directory or online at http://www.openafs.org/dl/license10.html
*/
-#ifndef lint
-#endif
/*
+
System: VICE-TWO
Module: partition.c
Institution: The Information Technology Center, Carnegie-Mellon University
*/
+#include <afsconfig.h>
#include <afs/param.h>
+
+RCSID("$Header$");
+
#include <ctype.h>
#ifdef AFS_NT40_ENV
#include <windows.h>
#include <winioctl.h>
#else
#include <sys/param.h>
-
+#include <sys/types.h>
+
#if AFS_HAVE_STATVFS
#include <sys/statvfs.h>
#endif /* AFS_HAVE_STATVFS */
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#include <sys/mount.h>
+#endif
#if !defined(AFS_SGI_ENV)
#ifdef AFS_OSF_ENV
#ifdef AFS_SUN5_ENV
#include <sys/fs/ufs_fs.h>
#else
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+#else
#include <ufs/fs.h>
#endif
+#endif
#else /* AFS_VFSINCL_ENV */
-#if !defined(AFS_AIX_ENV) && !defined(AFS_LINUX22_ENV)
+#if !defined(AFS_AIX_ENV) && !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
#include <sys/fs.h>
#endif
#endif /* AFS_VFSINCL_ENV */
#else
#ifdef AFS_LINUX22_ENV
#include <mntent.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
+#include <sys/statfs.h>
#else
#include <fstab.h>
#endif
#include "ntops.h"
#else
#include "namei_ops.h"
-#endif
+#include <dirent.h>
+#endif /* AFS_NT40_ENV */
#endif /* AFS_NAMEI_ENV */
#include "vnode.h"
#include "volume.h"
else
DiskPartitionList = dp;
dp->next = 0;
- strcpy(dp->name, path);
+ dp->name = (char *)malloc(strlen(path) + 1);
+ strncpy(dp->name, path, strlen(path) + 1);
#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);
strcpy(dp->devName, path);
+ strcat(dp->devName, "/");
+ strcat(dp->devName, "Lock");
+ mkdir(dp->devName, 0700);
+ strcat(dp->devName, path);
+ close(open(dp->devName, O_RDWR | O_CREAT, 0600));
dp->device = volutil_GetPartitionID(path);
#else
- strcpy(dp->devName, devname);
+ dp->devName = (char *)malloc(strlen(devname) + 1);
+ strncpy(dp->devName, devname, strlen(devname) + 1);
dp->device = dev;
#endif
dp->lock_fd = -1;
char *devname;
{
struct stat status;
+#if !defined(AFS_LINUX20_ENV) && !defined(AFS_NT40_ENV)
+ char AFSIDatPath[MAXPATHLEN];
+#endif
/* Only keep track of "/vicepx" partitions since it can get hairy
* when NFS mounts are involved.. */
}
#endif
+#if !defined(AFS_LINUX20_ENV) && !defined(AFS_NT40_ENV)
+ strcpy(AFSIDatPath, part);
+ strcat(AFSIDatPath, "/AFSIDat");
+#ifdef AFS_NAMEI_ENV
+ if (stat(AFSIDatPath, &status) < 0) {
+ DIR *dirp;
+ struct dirent *dp;
+
+ dirp = opendir(part);
+ assert(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);
+ return -1;
+ }
+ }
+ closedir(dirp);
+ }
+#else /* AFS_NAMEI_ENV */
+ if (stat(AFSIDatPath, &status) == 0) {
+ 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
-#ifdef AFS_DUX40_ENV
+#if defined(AFS_DUX40_ENV) && !defined(AFS_NAMEI_ENV)
if (status.st_ino != ROOTINO) {
Log("%s is not a mounted file system; ignored.\n", part);
return 0;
return 0;
}
+
+/* VIsAlwaysAttach() checks whether a /vicepX directory should always be
+ * attached (return value 1), or only attached when it is a separately
+ * mounted partition (return value 0). For non-NAMEI environments, it
+ * always returns 0.
+ */
+static int VIsAlwaysAttach(part)
+ char *part;
+{
+#ifdef AFS_NAMEI_ENV
+ struct stat st;
+ char checkfile[256];
+ int ret;
+
+ if (strncmp(part, VICE_PARTITION_PREFIX, VICE_PREFIX_SIZE))
+ return 0;
+
+ strncpy(checkfile, part, 100);
+ strcat(checkfile, "/");
+ strcat(checkfile, VICE_ALWAYSATTACH_FILE);
+
+ ret = stat(checkfile, &st);
+ return (ret < 0) ? 0 : 1;
+#else /* AFS_NAMEI_ENV */
+ return 0;
+#endif /* AFS_NAMEI_ENV */
+}
+
+/* VAttachPartitions2() looks for and attaches /vicepX partitions
+ * where a special file (VICE_ALWAYSATTACH_FILE) exists. This is
+ * used to attach /vicepX directories which aren't on dedicated
+ * partitions, in the NAMEI fileserver.
+ */
+void VAttachPartitions2() {
+#ifdef AFS_NAMEI_ENV
+ DIR *dirp;
+ struct dirent *de;
+ char pname[32];
+
+ dirp = opendir("/");
+ while (de = readdir(dirp)) {
+ strcpy(pname, "/");
+ strncat(pname, de->d_name, 20);
+ pname[sizeof(pname)-1] = '\0';
+
+ /* Only keep track of "/vicepx" partitions since automounter
+ may hose us */
+ if (VIsAlwaysAttach(pname))
+ VCheckPartition(pname, "");
+ }
+ closedir(dirp);
+#endif /* AFS_NAMEI_ENV */
+}
#endif /* AFS_NT40_ENV */
#ifdef AFS_SUN5_ENV
(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;
+
if (VCheckPartition(mnt.mnt_mountp, mnt.mnt_special) < 0 )
errors ++;
}
- (void) fclose(mntfile);
+ (void) fclose(mntfile);
+
+ /* Process the always-attach partitions, if any. */
+ VAttachPartitions2();
return errors ;
}
while (mntent = getmntent(mfd)) {
if (!hasmntopt(mntent, MNTOPT_RW)) continue;
+ /* If we're going to always attach this partition, do it later. */
+ if (VIsAlwaysAttach(mntent->mnt_dir))
+ continue;
+
if (VCheckPartition(mntent->mnt_dir, mntent->mnt_fsname) < 0 )
errors ++;
}
endmntent(mfd);
+ /* Process the always-attach partitions, if any. */
+ VAttachPartitions2();
+
return errors ;
}
#endif
continue; /* Ignore any "special" partitions */
#ifdef AFS_AIX42_ENV
+#ifndef AFS_NAMEI_ENV
{
struct superblock fs;
/* The Log statements are non-sequiters in the SalvageLog and don't
}
}
#endif
+#endif
+
+ /* If we're going to always attach this partition, do it later. */
+ if (VIsAlwaysAttach(part))
+ continue;
if (VCheckPartition(part, vmt2dataptr(vmountp, VMT_OBJECT)) < 0 )
errors ++;
}
- return errors ;
+ /* Process the always-attach partitions, if any. */
+ VAttachPartitions2();
+
+ return errors ;
}
#endif
-#ifdef AFS_DUX40_ENV
+#if defined(AFS_DUX40_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
int VAttachPartitions(void)
{
int errors = 0;
while (fsent = getfsent()) {
if (strcmp(fsent->fs_type, "rw") != 0) continue;
+ /* If we're going to always attach this partition, do it later. */
+ if (VIsAlwaysAttach(fsent->fs_file))
+ continue;
+
if (VCheckPartition(fsent->fs_file, fsent->fs_spec) < 0 )
errors ++;
}
endfsent();
+ /* Process the always-attach partitions, if any. */
+ VAttachPartitions2();
+
return errors ;
}
#endif
}
}
while (mntent = getmntent(mfd)) {
+ /* If we're going to always attach this partition, do it later. */
+ if (VIsAlwaysAttach(mntent->mnt_dir))
+ continue;
+
if (VCheckPartition(mntent->mnt_dir, mntent->mnt_fsname) < 0 )
errors ++;
}
endmntent(mfd);
+ /* Process the always-attach partitions, if any. */
+ VAttachPartitions2();
+
return errors ;
}
#endif /* AFS_LINUX22_ENV */
void VAdjustDiskUsage_r(Error *ec, Volume *vp, afs_int32 blocks, afs_int32 checkBlocks)
{
- afs_int32 rem, minavail;
*ec = 0;
/* why blocks instead of checkBlocks in the check below? Otherwise, any check
for less than BlocksSpare would skip the error-checking path, and we
blocks. */
if (blocks > 0) {
#ifdef AFS_AIX32_ENV
+ afs_int32 rem, minavail;
+
if ((rem = vp->partition->free - checkBlocks) <
(minavail = (vp->partition->totalUsable * aixlow_water) / 100))
#else
int VDiskUsage_r(Volume *vp, afs_int32 blocks)
{
- afs_int32 rem, minavail;
if (blocks > 0) {
#ifdef AFS_AIX32_ENV
+ afs_int32 rem, minavail;
+
if ((rem = vp->partition->free - blocks) <
(minavail = (vp->partition->totalUsable * aixlow_water) / 100))
#else
unsigned int *globalMask;
int globalMaskIndex;
#endif /* defined(AFS_HPUX_ENV) */
+#ifdef AFS_NAMEI_ENV
+#ifdef AFS_AIX42_ENV
+ char LockFileName[MAXPATHLEN + 1];
+
+ sprintf((char *)&LockFileName, "%s/AFSINODE_FSLock", name);
+ partitionName = (char *) &LockFileName;
+#endif
+#endif
if (!dp) return; /* no partition, will fail later */
if (dp->lock_fd != -1) return;
#if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV)
+#if !defined(AFS_AIX42_ENV) || !defined(AFS_NAMEI_ENV)
partitionName = dp->devName;
+#endif
code = O_RDWR;
#else
partitionName = dp->name;
for (retries=25; retries; retries--) {
dp->lock_fd = open(partitionName, code);
if (dp->lock_fd != -1) break;
+ if (errno == ENOENT)
+ code |= O_CREAT;
pausing.tv_sec = 0;
pausing.tv_usec = 500000;
select(0, NULL, NULL, NULL, &pausing);
assert (lockf(dp->lock_fd, F_LOCK, 0) != -1);
#else
assert (flock(dp->lock_fd, LOCK_EX) == 0);
-#endif /* defined(AFS_AIX_ENV) */
+#endif /* defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV) */
#endif
}