Add code for locking individual volumes on disk
[openafs.git] / src / vol / partition.c
index 8542410..b874a21 100644 (file)
@@ -183,11 +183,14 @@ int aixlow_water = 8;             /* default 8% */
 struct DiskPartition64 *DiskPartitionList;
 
 #ifdef AFS_DEMAND_ATTACH_FS
+/* file to lock to conceptually "lock" the vol headers on a partition */
+#define AFS_PARTLOCK_FILE ".volheaders.lock"
+#define AFS_VOLUMELOCK_FILE ".volume.lock"
+
 static struct DiskPartition64 *DiskPartitionTable[VOLMAXPARTS+1];
 
 static struct DiskPartition64 * VLookupPartition_r(char * path);
 static void AddPartitionToTable_r(struct DiskPartition64 *);
-static void DeletePartitionFromTable_r(struct DiskPartition64 *);
 #endif /* AFS_DEMAND_ATTACH_FS */
 
 #ifdef AFS_SGI_XFS_IOPS_ENV
@@ -241,6 +244,7 @@ static void
 VInitPartition_r(char *path, char *devname, Device dev)
 {
     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) {
@@ -284,6 +288,17 @@ VInitPartition_r(char *path, char *devname, Device dev)
     assert(pthread_cond_init(&dp->vol_list.cv, NULL) == 0);
     dp->vol_list.len = 0;
     dp->vol_list.busy = 0;
+    {
+       char lockpath[MAXPATHLEN+1];
+       afs_snprintf(lockpath, MAXPATHLEN, "%s/" AFS_PARTLOCK_FILE, dp->name);
+       lockpath[MAXPATHLEN] = '\0';
+       VLockFileInit(&dp->headerLockFile, lockpath);
+
+       afs_snprintf(lockpath, MAXPATHLEN, "%s/" AFS_VOLUMELOCK_FILE, dp->name);
+       lockpath[MAXPATHLEN] = '\0';
+       VLockFileInit(&dp->volLockFile, lockpath);
+    }
+    VDiskLockInit(&dp->headerLock, &dp->headerLockFile, 1);
 #endif /* AFS_DEMAND_ATTACH_FS */
 }
 
@@ -469,6 +484,18 @@ VAttachPartitions(void)
        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++;
     }
@@ -1103,7 +1130,7 @@ VLockPartition_r(char *name)
                            CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
        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);
@@ -1118,7 +1145,7 @@ VUnlockPartition_r(char *name)
 
     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);
@@ -1266,6 +1293,47 @@ VUnlockPartition(char *name)
 
 #ifdef AFS_DEMAND_ATTACH_FS
 
+/* new-style partition locks; these are only to have some mutual exclusion
+ * between the VGC scanner and volume utilies creating/altering vol headers
+ */
+
+/**
+ * lock a partition's vol headers.
+ *
+ * @param[in] dp       the partition to lock
+ * @param[in] locktype READ_LOCK or WRITE_LOCK
+ *
+ * @return operation status
+ *  @retval 0 success
+ */
+int
+VPartHeaderLock(struct DiskPartition64 *dp, int locktype)
+{
+    int code;
+
+    /* block on acquiring the lock */
+    int nonblock = 0;
+
+    code = VGetDiskLock(&dp->headerLock, locktype, nonblock);
+    if (code) {
+       Log("VPartHeaderLock: error %d locking partititon %s\n", code,
+           VPartitionPath(dp));
+    }
+    return code;
+}
+
+/**
+ * unlock a partition's vol headers.
+ *
+ * @param[in] dp       the partition to unlock
+ * @param[in] locktype READ_LOCK or WRITE_LOCK
+ */
+void
+VPartHeaderUnlock(struct DiskPartition64 *dp, int locktype)
+{
+    VReleaseDiskLock(&dp->headerLock, locktype);
+}
+
 /* XXX not sure this will work on AFS_NT40_ENV
  * needs to be tested!
  */
@@ -1318,7 +1386,7 @@ VGetPartitionById_r(afs_int32 id, int abortp)
 struct DiskPartition64 *
 VGetPartitionById(afs_int32 id, int abortp)
 {
-    struct Diskpartition64 * dp;
+    struct DiskPartition64 * dp;
 
     VOL_LOCK;
     dp = VGetPartitionById_r(id, abortp);
@@ -1345,10 +1413,12 @@ AddPartitionToTable_r(struct DiskPartition64 *dp)
     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 */