vos: complain if no fields are passed
[openafs.git] / src / volser / vos.c
index 0010a1b..4e1a743 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <lock.h>
 #include <afs/stds.h>
+#include <rx/rx_queue.h>
 #include <rx/xdr.h>
 #include <rx/rx.h>
 #include <rx/rx_globals.h>
@@ -73,6 +74,7 @@ struct tqHead {
 
 #define COMMONPARMS     cmd_Seek(ts, 12);\
 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");\
+cmd_AddParmAlias(ts, 12, "-c");   /* original -cell option */ \
 cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "don't authenticate");\
 cmd_AddParm(ts, "-localauth",CMD_FLAG,CMD_OPTIONAL,"use server tickets");\
 cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose");\
@@ -104,7 +106,7 @@ qPut(struct tqHead *ahead, afs_uint32 volid)
 {
     struct tqElem *elem;
 
-    elem = (struct tqElem *)malloc(sizeof(struct tqElem));
+    elem = malloc(sizeof(struct tqElem));
     elem->next = ahead->next;
     elem->volid = volid;
     ahead->next = elem;
@@ -279,16 +281,15 @@ SendFile(usd_handle_t ufd, struct rx_call *call, long blksize)
 {
     char *buffer = (char *)0;
     afs_int32 error = 0;
-    int done = 0;
     afs_uint32 nbytes;
 
-    buffer = (char *)malloc(blksize);
+    buffer = malloc(blksize);
     if (!buffer) {
        fprintf(STDERR, "malloc failed\n");
        return -1;
     }
 
-    while (!error && !done) {
+    while (!error) {
 #ifndef AFS_NT40_ENV           /* NT csn't select on non-socket fd's */
        fd_set in;
        FD_ZERO(&in);
@@ -306,10 +307,10 @@ SendFile(usd_handle_t ufd, struct rx_call *call, long blksize)
                    afs_error_message(error));
            break;
        }
-       if (nbytes == 0) {
-           done = 1;
+
+       if (nbytes == 0)
            break;
-       }
+
        if (rx_Write(call, buffer, nbytes) != nbytes) {
            error = -1;
            break;
@@ -392,7 +393,7 @@ ReceiveFile(usd_handle_t ufd, struct rx_call *call, long blksize)
     afs_uint32 bytesleft, w;
     afs_int32 error = 0;
 
-    buffer = (char *)malloc(blksize);
+    buffer = malloc(blksize);
     if (!buffer) {
        fprintf(STDERR, "memory allocation failed\n");
        ERROR_EXIT(-1);
@@ -1713,6 +1714,7 @@ SetFields(struct cmd_syndesc *as, void *arock)
     afs_uint32 aserver;
     afs_int32 apart;
     int previdx = -1;
+    int have_field = 0;
 
     volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err);  /* -id */
     if (volid == 0) {
@@ -1746,6 +1748,7 @@ SetFields(struct cmd_syndesc *as, void *arock)
 
     if (as->parms[1].items) {
        /* -max <quota> */
+       have_field = 1;
        code = util_GetHumanInt32(as->parms[1].items->data, &info.maxquota);
        if (code) {
            fprintf(STDERR, "invalid quota value\n");
@@ -1754,12 +1757,18 @@ SetFields(struct cmd_syndesc *as, void *arock)
     }
     if (as->parms[2].items) {
        /* -clearuse */
+       have_field = 1;
        info.dayUse = 0;
     }
     if (as->parms[3].items) {
        /* -clearVolUpCounter */
+       have_field = 1;
        info.spare2 = 0;
     }
+    if (!have_field) {
+       fprintf(STDERR,"Nothing to set.\n");
+       return (1);
+    }
     code = UV_SetVolumeInfo(aserver, apart, volid, &info);
     if (code)
        fprintf(STDERR,
@@ -4476,7 +4485,6 @@ static int
 ListVLDB(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 apart;
-    afs_uint32 aserver;
     afs_int32 code;
     afs_int32 vcode;
     struct VldbListByAttributes attributes;
@@ -4490,7 +4498,6 @@ ListVLDB(struct cmd_syndesc *as, void *arock)
     int quiet, sort, lock;
     afs_int32 thisindex, nextindex;
 
-    aserver = 0;
     apart = 0;
 
     attributes.Mask = 0;
@@ -4517,6 +4524,8 @@ ListVLDB(struct cmd_syndesc *as, void *arock)
 
     /* Server specified */
     if (as->parms[1].items) {
+       afs_uint32 aserver;
+
        aserver = GetServer(as->parms[1].items->data);
        if (aserver == 0) {
            fprintf(STDERR, "vos: server '%s' not found in host table\n",
@@ -4604,9 +4613,7 @@ ListVLDB(struct cmd_syndesc *as, void *arock)
            } else {
                /* Grow the tarray to keep the extra entries */
                parraysize = (centries * sizeof(struct nvldbentry));
-               ttarray =
-                   (struct nvldbentry *)realloc(tarray,
-                                                tarraysize + parraysize);
+               ttarray = realloc(tarray, tarraysize + parraysize);
                if (!ttarray) {
                    fprintf(STDERR,
                            "Could not allocate enough space for  the VLDB entries\n");
@@ -5499,7 +5506,7 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
     afs_uint32 volid;
     afs_uint32 server;
     afs_int32 code, i, same;
-    struct nvldbentry entry, storeEntry;
+    struct nvldbentry entry, checkEntry, storeEntry;
     afs_int32 vcode;
     afs_int32 rwindex = 0;
     afs_uint32 rwserver = 0;
@@ -5544,6 +5551,7 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
     if (as->parms[3].items)
        force = 1;
 
+    memset(&entry, 0, sizeof(entry));
     vcode = VLDB_GetEntryByID(volid, -1, &entry);
     if (vcode) {
        fprintf(STDERR,
@@ -5554,7 +5562,6 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
     }
 
     /* use RO volid even if user specified RW or BK volid */
-
     if (volid != entry.volumeId[ROVOL])
        volid = entry.volumeId[ROVOL];
 
@@ -5564,8 +5571,9 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
            rwindex = i;
            rwserver = entry.serverNumber[i];
            rwpartition = entry.serverPartition[i];
-       }
-       if (entry.serverFlags[i] & ITSROVOL) {
+           if (roserver)
+               break;
+       } else if ((entry.serverFlags[i] & ITSROVOL) && !roserver) {
            same = VLDB_IsSameAddrs(server, entry.serverNumber[i], &code);
            if (code) {
                fprintf(STDERR,
@@ -5577,14 +5585,15 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
                roindex = i;
                roserver = entry.serverNumber[i];
                ropartition = entry.serverPartition[i];
-               break;
+               if (rwserver)
+                    break;
            }
        }
     }
     if (!roserver) {
        fprintf(STDERR, "Warning: RO volume didn't exist in vldb!\n");
     }
-    if (ropartition != partition) {
+    if (roserver && (ropartition != partition)) {
        fprintf(STDERR,
                "Warning: RO volume should be in partition %d instead of %d (vldb)\n",
                ropartition, partition);
@@ -5610,6 +5619,37 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
     vcode =
        ubik_VL_SetLock(cstruct, 0, entry.volumeId[RWVOL], RWVOL,
                  VLOP_MOVE);
+    if (vcode) {
+       fprintf(STDERR,
+               "Unable to lock volume %lu, code %d\n",
+               (unsigned long)entry.volumeId[RWVOL],vcode);
+       PrintError("", vcode);
+       return -1;
+    }
+
+    /* make sure the VLDB entry hasn't changed since we started */
+    memset(&checkEntry, 0, sizeof(checkEntry));
+    vcode = VLDB_GetEntryByID(volid, -1, &checkEntry);
+    if (vcode) {
+       fprintf(STDERR,
+                "Could not fetch the entry for volume %lu from VLDB\n",
+                (unsigned long)volid);
+       PrintError("convertROtoRW ", vcode);
+       code = vcode;
+       goto error_exit;
+    }
+
+    MapHostToNetwork(&checkEntry);
+    entry.flags &= ~VLOP_ALLOPERS;  /* clear any stale lock operation flags */
+    entry.flags |= VLOP_MOVE;        /* set to match SetLock operation above */
+    if (memcmp(&entry, &checkEntry, sizeof(entry)) != 0) {
+        fprintf(STDERR,
+                "VLDB entry for volume %lu has changed; please reissue the command.\n",
+                (unsigned long)volid);
+        code = -1;
+        goto error_exit;
+    }
+
     aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
     code = AFSVolConvertROtoRWvolume(aconn, partition, volid);
     if (code) {
@@ -5617,11 +5657,31 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
                "Converting RO volume %lu to RW volume failed with code %d\n",
                (unsigned long)volid, code);
        PrintError("convertROtoRW ", code);
-       return -1;
+       goto error_exit;
+    }
+    /* Update the VLDB to match what we did on disk as much as possible.  */
+    /* If the converted RO was in the VLDB, make it look like the new RW. */
+    if (roserver) {
+       entry.serverFlags[roindex] = ITSRWVOL;
+    } else {
+       /* Add a new site entry for the newly created RW.  It's possible
+        * (but unlikely) that we are already at MAXNSERVERS and that this
+        * new site will invalidate the whole VLDB entry;  however,
+        * VLDB_ReplaceEntry will detect this and return VL_BADSERVER,
+        * so we need no extra guard logic here.
+        */
+       afs_int32 newrwindex = entry.nServers;
+       (entry.nServers)++;
+       entry.serverNumber[newrwindex] = server;
+       entry.serverPartition[newrwindex] = partition;
+       entry.serverFlags[newrwindex] = ITSRWVOL;
     }
-    entry.serverFlags[roindex] = ITSRWVOL;
     entry.flags |= RW_EXISTS;
     entry.flags &= ~BACK_EXISTS;
+
+    /* if the old RW was in the VLDB, remove it by decrementing the number */
+    /* of servers, replacing the RW entry with the last entry, and zeroing */
+    /* out the last entry. */
     if (rwserver) {
        (entry.nServers)--;
        if (rwindex != entry.nServers) {
@@ -5651,9 +5711,14 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
                "Warning: volume converted, but vldb update failed with code %d!\n",
                code);
     }
+
+  error_exit:
     vcode = UV_LockRelease(entry.volumeId[RWVOL]);
     if (vcode) {
-       PrintDiagnostics("unlock", vcode);
+       fprintf(STDERR,
+               "Unable to unlock volume %lu, code %d\n",
+               (unsigned long)entry.volumeId[RWVOL],vcode);
+       PrintError("", vcode);
     }
     return code;
 }
@@ -6112,6 +6177,7 @@ main(int argc, char **argv)
                "machine readable format");
     COMMONPARMS;
     cmd_CreateAlias(ts, "volinfo");
+    cmd_CreateAlias(ts, "e");
 
     ts = cmd_CreateSyntax("setfields", SetFields, NULL,
                          "change volume info fields");