hammer2 - Add pfs_list, pfs_create, pfs_delete
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 6 Apr 2012 05:04:42 +0000 (22:04 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 6 Apr 2012 05:04:42 +0000 (22:04 -0700)
* Add functions to manage PFSs created under the super-root.

13 files changed:
sbin/hammer2/Makefile
sbin/hammer2/cmd_pfs.c [copied from sbin/hammer2/cmd_remote.c with 50% similarity]
sbin/hammer2/cmd_remote.c
sbin/hammer2/hammer2.h
sbin/hammer2/main.c
sbin/hammer2/subs.c
sbin/newfs_hammer2/newfs_hammer2.c
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_disk.h
sys/vfs/hammer2/hammer2_inode.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_ioctl.h
sys/vfs/hammer2/hammer2_vnops.c

index 332ae01..742a93c 100644 (file)
@@ -1,6 +1,6 @@
 PROG=  hammer2
 SRCS=  main.c subs.c
-SRCS+= cmd_remote.c cmd_snapshot.c cmd_helper.c
+SRCS+= cmd_remote.c cmd_snapshot.c cmd_pfs.c cmd_helper.c
 #MAN=  hammer2.8
 NOMAN= TRUE
 
similarity index 50%
copy from sbin/hammer2/cmd_remote.c
copy to sbin/hammer2/cmd_pfs.c
index 4f723f7..c830bfa 100644 (file)
 #include "hammer2.h"
 
 int
-cmd_remote_connect(const char *sel_path, const char *url)
+cmd_pfs_list(const char *sel_path)
 {
-       hammer2_ioc_remote_t remote;
+       hammer2_ioc_pfs_t pfs;
        int ecode = 0;
+       int count = 0;
        int fd;
+       uint32_t status;
+       char *pfs_id_str = NULL;
 
        if ((fd = hammer2_ioctl_handle(sel_path)) < 0)
                return(1);
-       bzero(&remote, sizeof(remote));
-       remote.copyid = -1;
-       remote.fd = -1;
-       if (strlen(url) >= sizeof(remote.copy1.path)) {
-               fprintf(stderr, "hammer2: connect: Path too long\n");
-               close(fd);
-               return(1);
-       }
-       snprintf(remote.copy1.path, sizeof(remote.copy1.path), "%s", url);
-       if (ioctl(fd, HAMMER2IOC_ADD_REMOTE, &remote) < 0) {
-               perror("ioctl");
-               ecode = 1;
+       bzero(&pfs, sizeof(pfs));
+
+       while ((pfs.name_key = pfs.name_next) != (hammer2_key_t)-1) {
+               if (ioctl(fd, HAMMER2IOC_PFS_GET, &pfs) < 0) {
+                       perror("ioctl");
+                       ecode = 1;
+                       break;
+               }
+               if (count == 0) {
+                       printf("Type        "
+                              "Pfs_id                               "
+                              "Label\n");
+               }
+               switch(pfs.pfs_type) {
+               case HAMMER2_PFSTYPE_NONE:
+                       printf("NONE        ");
+                       break;
+               case HAMMER2_PFSTYPE_ADMIN:
+                       printf("ADMIN       ");
+                       break;
+               case HAMMER2_PFSTYPE_CACHE:
+                       printf("CACHE       ");
+                       break;
+               case HAMMER2_PFSTYPE_COPY:
+                       printf("COPY        ");
+                       break;
+               case HAMMER2_PFSTYPE_SLAVE:
+                       printf("SLAVE       ");
+                       break;
+               case HAMMER2_PFSTYPE_SOFT_SLAVE:
+                       printf("SOFT_SLAVE  ");
+                       break;
+               case HAMMER2_PFSTYPE_SOFT_MASTER:
+                       printf("SOFT_MASTER ");
+                       break;
+               case HAMMER2_PFSTYPE_MASTER:
+                       printf("MASTER      ");
+                       break;
+               default:
+                       printf("%02x          ", pfs.pfs_type);
+                       break;
+               }
+               uuid_to_string(&pfs.pfs_id, &pfs_id_str, &status);
+               printf("%s ", pfs_id_str);
+               free(pfs_id_str);
+               pfs_id_str = NULL;
+               printf("%s\n", pfs.name);
+               ++count;
        }
        close(fd);
-       return 0;;
+
+       return (ecode);
 }
 
 int
-cmd_remote_disconnect(const char *sel_path, const char *url)
+cmd_pfs_create(const char *sel_path, const char *name,
+              uint8_t pfs_type, const char *uuid_str)
 {
-       hammer2_ioc_remote_t remote;
+       hammer2_ioc_pfs_t pfs;
        int ecode = 0;
        int fd;
+       uint32_t status;
 
-       if ((fd = hammer2_ioctl_handle(sel_path)) < 0)
+       if (pfs_type == HAMMER2_PFSTYPE_NONE) {
+               fprintf(stderr, "hammer2: pfs_create: requires -t pfs_type\n");
                return(1);
-       bzero(&remote, sizeof(remote));
-       remote.copyid = -1;
-       remote.fd = -1;
-       if (strlen(url) >= sizeof(remote.copy1.path)) {
-               fprintf(stderr, "hammer2: disconnect: Path too long\n");
-               close(fd);
+       }
+
+       if ((fd = hammer2_ioctl_handle(sel_path)) < 0)
                return(1);
+       bzero(&pfs, sizeof(pfs));
+       snprintf(pfs.name, sizeof(pfs.name), "%s", name);
+       pfs.pfs_type = pfs_type;
+       if (uuid_str) {
+               uuid_from_string(uuid_str, &pfs.pfs_id, &status);
+       } else {
+               uuid_create(&pfs.pfs_id, &status);
        }
-       snprintf(remote.copy1.path, sizeof(remote.copy1.path), "%s", url);
-       if (ioctl(fd, HAMMER2IOC_DEL_REMOTE, &remote) < 0) {
-               perror("ioctl");
+       if (status == uuid_s_ok)
+               uuid_create(&pfs.pfs_fsid, &status);
+       if (status == uuid_s_ok) {
+               if (ioctl(fd, HAMMER2IOC_PFS_CREATE, &pfs) < 0) {
+                       perror("ioctl");
+                       ecode = 1;
+               }
+       } else {
+               fprintf(stderr, "hammer2: pfs_create: badly formed uuid\n");
                ecode = 1;
        }
        close(fd);
-       return 0;;
+       return (ecode);
 }
 
 int
-cmd_remote_status(const char *sel_path, int all_opt __unused)
+cmd_pfs_delete(const char *sel_path, const char *name)
 {
-       hammer2_ioc_remote_t remote;
+       hammer2_ioc_pfs_t pfs;
        int ecode = 0;
-       int count = 0;
        int fd;
 
        if ((fd = hammer2_ioctl_handle(sel_path)) < 0)
                return(1);
-       bzero(&remote, sizeof(remote));
+       bzero(&pfs, sizeof(pfs));
+       snprintf(pfs.name, sizeof(pfs.name), "%s", name);
 
-       while ((remote.copyid = remote.nextid) >= 0) {
-               if (ioctl(fd, HAMMER2IOC_GET_REMOTE, &remote) < 0) {
-                       perror("ioctl");
-                       ecode = 1;
-                       break;
-               }
-               if (remote.copy1.copyid == 0)
-                       continue;
-               if (count == 0)
-                       printf("CPYID LABEL           STATUS PATH\n");
-               printf("%5d %-15s %c%c%c.%02x %s\n",
-                       remote.copy1.copyid,
-                       remote.copy1.label,
-                       '-', '-', '-',
-                       remote.copy1.priority,
-                       remote.copy1.path);
-               ++count;
+       if (ioctl(fd, HAMMER2IOC_PFS_CREATE, &pfs) < 0) {
+               fprintf(stderr, "hammer2: pfs_delete(%s): %s\n",
+                       name, strerror(errno));
+               ecode = 1;
        }
-       if (count == 0)
-               printf("No linkages found\n");
+       close(fd);
+
        return (ecode);
 }
index 4f723f7..8300e09 100644 (file)
@@ -53,7 +53,7 @@ cmd_remote_connect(const char *sel_path, const char *url)
                return(1);
        }
        snprintf(remote.copy1.path, sizeof(remote.copy1.path), "%s", url);
-       if (ioctl(fd, HAMMER2IOC_ADD_REMOTE, &remote) < 0) {
+       if (ioctl(fd, HAMMER2IOC_REMOTE_ADD, &remote) < 0) {
                perror("ioctl");
                ecode = 1;
        }
@@ -79,7 +79,7 @@ cmd_remote_disconnect(const char *sel_path, const char *url)
                return(1);
        }
        snprintf(remote.copy1.path, sizeof(remote.copy1.path), "%s", url);
-       if (ioctl(fd, HAMMER2IOC_DEL_REMOTE, &remote) < 0) {
+       if (ioctl(fd, HAMMER2IOC_REMOTE_DEL, &remote) < 0) {
                perror("ioctl");
                ecode = 1;
        }
@@ -100,7 +100,7 @@ cmd_remote_status(const char *sel_path, int all_opt __unused)
        bzero(&remote, sizeof(remote));
 
        while ((remote.copyid = remote.nextid) >= 0) {
-               if (ioctl(fd, HAMMER2IOC_GET_REMOTE, &remote) < 0) {
+               if (ioctl(fd, HAMMER2IOC_REMOTE_GET, &remote) < 0) {
                        perror("ioctl");
                        ecode = 1;
                        break;
index 5de0b75..7f451e5 100644 (file)
@@ -65,6 +65,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <uuid.h>
 
 extern int DebugOpt;
 extern int NormalExit;
@@ -75,4 +76,10 @@ void hammer2_disconnect(void *(*func)(void *), void *arg);
 int cmd_remote_connect(const char *sel_path, const char *url);
 int cmd_remote_disconnect(const char *sel_path, const char *url);
 int cmd_remote_status(const char *sel_path, int all_opt);
+
+int cmd_pfs_list(const char *sel_path);
+int cmd_pfs_create(const char *sel_path, const char *name,
+                       uint8_t pfs_type, const char *uuid_str);
+int cmd_pfs_delete(const char *sel_path, const char *name);
+
 int cmd_helper(const char *sel_path);
index c7b7afc..81ef955 100644 (file)
@@ -144,10 +144,29 @@ main(int ac, char **av)
                 * Get status of PFS and its connections (-a for all PFSs)
                 */
                ecode = cmd_remote_status(sel_path, all_opt);
-       } else if (strcmp(av[0], "mkpfs") == 0) {
+       } else if (strcmp(av[0], "pfs_list") == 0) {
+               /*
+                * List all PFSs
+                */
+               ecode = cmd_pfs_list(sel_path);
+       } else if (strcmp(av[0], "pfs_create") == 0) {
                /*
                 * Create new PFS using pfs_type
                 */
+               if (ac < 2) {
+                       fprintf(stderr, "pfs_create: requires name\n");
+                       usage(1);
+               }
+               ecode = cmd_pfs_create(sel_path, av[1], pfs_type, uuid_str);
+       } else if (strcmp(av[0], "pfs_delete") == 0) {
+               /*
+                * Delete a PFS by name
+                */
+               if (ac < 2) {
+                       fprintf(stderr, "pfs_delete: requires name\n");
+                       usage(1);
+               }
+               ecode = cmd_pfs_delete(sel_path, av[1]);
        } else if (strcmp(av[0], "snapshot") == 0) {
                /*
                 * Create snapshot with optional pfs_type and optional
index 51f2694..751bf8a 100644 (file)
@@ -53,7 +53,7 @@ hammer2_ioctl_handle(const char *sel_path)
                        sel_path, strerror(errno));
                return(-1);
        }
-       if (ioctl(fd, HAMMER2IOC_GET_VERSION, &info) < 0) {
+       if (ioctl(fd, HAMMER2IOC_VERSION_GET, &info) < 0) {
                fprintf(stderr, "hammer2: '%s' is not a hammer2 filesystem\n",
                        sel_path);
                close(fd);
index f4cc5da..1be34e6 100644 (file)
@@ -68,7 +68,8 @@ static int Hammer2Version = -1;
 static int ForceOpt = 0;
 static uuid_t Hammer2_FSType;  /* static filesystem type id for HAMMER2 */
 static uuid_t Hammer2_FSId;    /* unique filesystem id in volu header */
-static uuid_t Hammer2_PFSId;   /* PFS id in super-root inode */
+static uuid_t Hammer2_SPFSId;  /* PFS id in super-root inode */
+static uuid_t Hammer2_RPFSId;  /* PFS id in root inode */
 static const char *Label = "ROOT";
 static hammer2_off_t BootAreaSize;
 static hammer2_off_t AuxAreaSize;
@@ -85,7 +86,8 @@ main(int ac, char **av)
        int ch;
        int fd = -1;
        char *fsidstr;
-       char *pfsidstr;
+       char *spfsidstr;
+       char *rpfsidstr;
 
        /*
         * Sanity check basic filesystem structures.  No cookies for us
@@ -94,15 +96,14 @@ main(int ac, char **av)
        assert(sizeof(hammer2_volume_data_t) == HAMMER2_VOLUME_BYTES);
        assert(sizeof(hammer2_inode_data_t) == HAMMER2_INODE_BYTES);
        assert(sizeof(hammer2_blockref_t) == HAMMER2_BLOCKREF_BYTES);
-       assert((HAMMER2_PBUFSIZE / sizeof(hammer2_blockref_t)) ==
-              HAMMER2_IND_COUNT);
 
        /*
         * Generate a filesystem id and lookup the filesystem type
         */
        srandomdev();
        uuidgen(&Hammer2_FSId, 1);
-       uuidgen(&Hammer2_PFSId, 1);
+       uuidgen(&Hammer2_SPFSId, 1);
+       uuidgen(&Hammer2_RPFSId, 1);
        uuid_from_string(HAMMER2_UUID_STRING, &Hammer2_FSType, &status);
        /*uuid_name_lookup(&Hammer2_FSType, "DragonFly HAMMER2", &status);*/
        if (status != uuid_s_ok) {
@@ -228,7 +229,8 @@ main(int ac, char **av)
         * We'll need to stuff this in the volume header soon.
         */
        uuid_to_string(&Hammer2_FSId, &fsidstr, &status);
-       uuid_to_string(&Hammer2_PFSId, &pfsidstr, &status);
+       uuid_to_string(&Hammer2_SPFSId, &spfsidstr, &status);
+       uuid_to_string(&Hammer2_RPFSId, &rpfsidstr, &status);
 
        /*
         * Calculate the amount of reserved space.  HAMMER2_RESERVE_SEG (4MB)
@@ -260,7 +262,8 @@ main(int ac, char **av)
        printf("topo-reserved:    %s\n", sizetostr(reserved_space));
        printf("free-space:       %s\n", sizetostr(free_space));
        printf("fsid:             %s\n", fsidstr);
-       printf("pfsid:            %s\n", pfsidstr);
+       printf("supr-pfsid:       %s\n", spfsidstr);
+       printf("root-pfsid:       %s\n", rpfsidstr);
        printf("\n");
 
        return(0);
@@ -512,9 +515,10 @@ format_hammer2(int fd, hammer2_off_t total_space, hammer2_off_t free_space)
         * Compression mode and supported copyids.
         */
        rawip->comp_algo = HAMMER2_COMP_AUTOZERO;
-       rawip->copyids[0] = HAMMER2_COPYID_LOCAL;       /* local disk */
 
-       /* rawip->pfsid is left empty */
+       rawip->pfs_id = Hammer2_RPFSId;
+       rawip->pfs_type = HAMMER2_PFSTYPE_MASTER;
+       rawip->op_flags |= HAMMER2_OPFLAG_PFSROOT;
 
        /* rawip->u.blockset is left empty */
 
@@ -559,7 +563,6 @@ format_hammer2(int fd, hammer2_off_t total_space, hammer2_off_t free_space)
        rawip->name_key = 0;
 
        rawip->comp_algo = HAMMER2_COMP_AUTOZERO;
-       rawip->copyids[0] = HAMMER2_COPYID_LOCAL;       /* local disk */
 
        /*
         * The super-root is flagged as a PFS and typically given its own
@@ -567,7 +570,8 @@ format_hammer2(int fd, hammer2_off_t total_space, hammer2_off_t free_space)
         * snapshots and all if desired.  PFS ids are used to match up
         * mirror sources and targets and cluster copy sources and targets.
         */
-       rawip->pfsid = Hammer2_PFSId;
+       rawip->pfs_id = Hammer2_SPFSId;
+       rawip->pfs_type = HAMMER2_PFSTYPE_MASTER;
        rawip->op_flags |= HAMMER2_OPFLAG_PFSROOT;
 
        /*
index dc7d648..06e9fc9 100644 (file)
@@ -335,6 +335,7 @@ int hammer2_calc_logical(hammer2_inode_t *ip, hammer2_off_t uoff,
  * hammer2_inode.c
  */
 struct vnode *hammer2_igetv(hammer2_inode_t *ip, int *errorp);
+
 hammer2_inode_t *hammer2_inode_alloc(hammer2_mount_t *hmp, void *data);
 void hammer2_inode_free(hammer2_inode_t *ip);
 void hammer2_inode_ref(hammer2_inode_t *ip);
@@ -353,6 +354,10 @@ int hammer2_inode_connect(hammer2_inode_t *dip, hammer2_inode_t *nip,
 int hammer2_hardlink_create(hammer2_inode_t *ip, hammer2_inode_t *dip,
                        const uint8_t *name, size_t name_len);
 
+int hammer2_unlink_file(hammer2_inode_t *dip,
+                       const uint8_t *name, size_t name_len,
+                       int isdir, int adjlinks);
+
 /*
  * hammer2_chain.c
  */
index 0b13055..c3f5f98 100644 (file)
@@ -410,6 +410,10 @@ typedef struct hammer2_indblock_data hammer2_indblock_data_t;
 struct hammer2_inode_data {
        uint16_t        version;        /* 0000 inode data version */
        uint16_t        reserved02;     /* 0002 */
+
+       /*
+        * core inode attributes, inode type, misc flags
+        */
        uint32_t        uflags;         /* 0004 chflags */
        uint32_t        rmajor;         /* 0008 available for device nodes */
        uint32_t        rminor;         /* 000C available for device nodes */
@@ -425,24 +429,43 @@ struct hammer2_inode_data {
        uint16_t        cap_flags;      /* 0052 capability flags */
        uint32_t        mode;           /* 0054 unix modes (typ low 16 bits) */
 
+       /*
+        * inode size, identification, localized recursive configuration
+        * for compression and backup copies.
+        */
        hammer2_tid_t   inum;           /* 0058 inode number */
        hammer2_off_t   size;           /* 0060 size of file */
        uint64_t        nlinks;         /* 0068 hard links (typ only dirs) */
        hammer2_tid_t   iparent;        /* 0070 parent inum (recovery only) */
-       uint8_t         copies[8];      /* 0078 request copies to (up to 8) */
-       hammer2_off_t   data_quota;     /* 0080 subtree quota in bytes */
-       hammer2_off_t   data_count;     /* 0088 subtree byte count */
-       hammer2_off_t   inode_quota;    /* 0090 subtree quota inode count */
-       hammer2_off_t   inode_count;    /* 0098 subtree inode count */
-       uint16_t        name_len;       /* 00A0 filename length */
-       uint8_t         comp_algo;      /* 00A2 compression request & algo */
-       uint8_t         reservedA3;     /* 00A3 */
-       uint32_t        reservedA4;     /* 00A4 */
-       hammer2_key_t   name_key;       /* 00A8 full filename key */
-       uint8_t         reservedB0[7];  /* 00B0 */
-       uint8_t         pfs_type;       /* 00B7 (if PFSROOT) node type */
-       uuid_t          pfs_id;         /* 00B8 (if PFSROOT) pfs uuid */
-       uint64_t        pfs_inum;       /* 00C8 (if PFSROOT) inum allocator */
+       hammer2_key_t   name_key;       /* 0078 full filename key */
+       uint16_t        name_len;       /* 0080 filename length */
+       uint8_t         ncopies;        /* 0082 ncopies to local media */
+       uint8_t         comp_algo;      /* 0083 compression request & algo */
+
+       /*
+        * These fields are currently only applicable to PFSROOTs.
+        *
+        * NOTE: We can't use {volume_data->fsid, pfs_id} to uniquely
+        *       identify an instance of a PFS in the cluster because
+        *       a mount may contain more than one copy of the PFS as
+        *       a separate node.  {pfs_fsid, pfs_id} must be used for
+        *       registration in the cluster.
+        */
+       uint8_t         reserved84;     /* 0084 */
+       uint8_t         reserved85;     /* 0085 */
+       uint8_t         reserved86;     /* 0086 */
+       uint8_t         pfs_type;       /* 0087 (if PFSROOT) node type */
+       uint64_t        pfs_inum;       /* 0088 (if PFSROOT) inum allocator */
+       uuid_t          pfs_id;         /* 0090 (if PFSROOT) pfs uuid */
+       uuid_t          pfs_fsid;       /* 00A0 (if PFSROOT) unique pfs uuid */
+
+       /*
+        * Quotas and cumulative sub-tree counters.
+        */
+       hammer2_off_t   data_quota;     /* 00B0 subtree quota in bytes */
+       hammer2_off_t   data_count;     /* 00B8 subtree byte count */
+       hammer2_off_t   inode_quota;    /* 00C0 subtree quota inode count */
+       hammer2_off_t   inode_count;    /* 00C8 subtree inode count */
        hammer2_tid_t   attr_tid;       /* 00D0 attributes changed */
        hammer2_tid_t   dirent_tid;     /* 00D8 directory/attr changed */
        uint64_t        reservedE0;     /* 00E0 */
@@ -597,9 +620,9 @@ struct hammer2_copy_data {
        uint16_t flags;         /* 04-05 flags field */
        uint8_t error;          /* 06    last operational error */
        uint8_t priority;       /* 07    priority and round-robin flag */
-       uint8_t remote_pfs_type;/* 08    probed direct remote PFS type */
+       uint8_t remote_pfstype; /* 08    probed direct remote PFS type */
        uint8_t reserved08[23]; /* 09-1F */
-       uuid_t  pfsid;          /* 20-2F copy target must match this uuid */
+       uuid_t  pfs_id;         /* 20-2F copy target must match this uuid */
        uint8_t label[16];      /* 30-3F import/export label */
        uint8_t path[64];       /* 40-7F target specification string or key */
 };
index 3bf6c37..d8fd256 100644 (file)
@@ -195,6 +195,10 @@ hammer2_igetv(hammer2_inode_t *ip, int *errorp)
  *
  * If no error occurs the new inode with its chain locked is returned in
  * *nipp, otherwise an error is returned and *nipp is set to NULL.
+ *
+ * If vap and/or cred are NULL the related fields are not set and the
+ * inode type defaults to a directory.  This is used when creating PFSs
+ * under the super-root, so the inode number is set to 1 in this case.
  */
 int
 hammer2_inode_create(hammer2_mount_t *hmp,
@@ -254,14 +258,21 @@ hammer2_inode_create(hammer2_mount_t *hmp,
        nip = chain->u.ip;
        *nipp = nip;
 
-       nip->ip_data.type = hammer2_get_obj_type(vap->va_type);
        hammer2_voldata_lock(hmp);
-       nip->ip_data.inum = hmp->voldata.alloc_tid++;   /* XXX modify/lock */
+       if (vap) {
+               nip->ip_data.type = hammer2_get_obj_type(vap->va_type);
+               nip->ip_data.inum = hmp->voldata.alloc_tid++;
+               /* XXX modify/lock */
+       } else {
+               nip->ip_data.type = HAMMER2_OBJTYPE_DIRECTORY;
+               nip->ip_data.inum = 1;
+       }
        hammer2_voldata_unlock(hmp);
        nip->ip_data.version = HAMMER2_INODE_VERSION_ONE;
        nip->ip_data.ctime = 0;
        nip->ip_data.mtime = 0;
-       nip->ip_data.mode = vap->va_mode;
+       if (vap)
+               nip->ip_data.mode = vap->va_mode;
        nip->ip_data.nlinks = 1;
        /* uid, gid, etc */
 
@@ -417,6 +428,151 @@ hammer2_hardlink_create(hammer2_inode_t *ip, hammer2_inode_t *dip,
 }
 
 /*
+ * Unlink the file from the specified directory inode.  The directory inode
+ * does not need to be locked.
+ *
+ * isdir determines whether a directory/non-directory check should be made.
+ * No check is made if isdir is set to -1.
+ *
+ * adjlinks tells unlink that we want to adjust the nlinks count of the
+ * inode.  When removing the last link for a NON forwarding entry we can
+ * just ignore the link count... no point updating the inode that we are
+ * about to dereference, it would just result in a lot of wasted I/O.
+ *
+ * However, if the entry is a forwarding entry (aka a hardlink), and adjlinks
+ * is non-zero, we have to locate the hardlink and adjust its nlinks field.
+ */
+int
+hammer2_unlink_file(hammer2_inode_t *dip, const uint8_t *name, size_t name_len,
+                   int isdir, int adjlinks)
+{
+       hammer2_mount_t *hmp;
+       hammer2_chain_t *parent;
+       hammer2_chain_t *chain;
+       hammer2_chain_t *dparent;
+       hammer2_chain_t *dchain;
+       hammer2_key_t lhc;
+       int error;
+
+       error = 0;
+
+       hmp = dip->hmp;
+       lhc = hammer2_dirhash(name, name_len);
+
+       /*
+        * Search for the filename in the directory
+        */
+       parent = &dip->chain;
+       hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
+       chain = hammer2_chain_lookup(hmp, &parent,
+                                    lhc, lhc + HAMMER2_DIRHASH_LOMASK,
+                                    0);
+       while (chain) {
+               if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
+                   chain->u.ip &&
+                   name_len == chain->data->ipdata.name_len &&
+                   bcmp(name, chain->data->ipdata.filename, name_len) == 0) {
+                       break;
+               }
+               chain = hammer2_chain_next(hmp, &parent, chain,
+                                          lhc, lhc + HAMMER2_DIRHASH_LOMASK,
+                                          0);
+       }
+
+       /*
+        * Not found or wrong type (isdir < 0 disables the type check).
+        */
+       if (chain == NULL) {
+               hammer2_chain_unlock(hmp, parent);
+               return ENOENT;
+       }
+       if (chain->data->ipdata.type == HAMMER2_OBJTYPE_DIRECTORY &&
+           isdir == 0) {
+               error = ENOTDIR;
+               goto done;
+       }
+       if (chain->data->ipdata.type != HAMMER2_OBJTYPE_DIRECTORY &&
+           isdir == 1) {
+               error = EISDIR;
+               goto done;
+       }
+
+       /*
+        * If this is a directory the directory must be empty.  However, if
+        * isdir < 0 we are doing a rename and the directory does not have
+        * to be empty.
+        */
+       if (chain->data->ipdata.type == HAMMER2_OBJTYPE_DIRECTORY &&
+           isdir >= 0) {
+               dparent = chain;
+               hammer2_chain_lock(hmp, dparent, HAMMER2_RESOLVE_ALWAYS);
+               dchain = hammer2_chain_lookup(hmp, &dparent,
+                                             0, (hammer2_key_t)-1,
+                                             HAMMER2_LOOKUP_NODATA);
+               if (dchain) {
+                       hammer2_chain_unlock(hmp, dchain);
+                       hammer2_chain_unlock(hmp, dparent);
+                       error = ENOTEMPTY;
+                       goto done;
+               }
+               hammer2_chain_unlock(hmp, dparent);
+               dparent = NULL;
+               /* dchain NULL */
+       }
+
+#if 0
+       /*
+        * If adjlinks is non-zero this is a real deletion (otherwise it is
+        * probably a rename).  XXX
+        */
+       if (adjlinks) {
+               if (chain->data->ipdata.type == HAMMER2_OBJTYPE_HARDLINK) {
+                       /*hammer2_adjust_hardlink(chain->u.ip, -1);*/
+                       /* error handling */
+               } else {
+                       waslastlink = 1;
+               }
+       } else {
+               waslastlink = 0;
+       }
+#endif
+
+       /*
+        * Found, the chain represents the inode.  Remove the parent reference
+        * to the chain.  The chain itself is no longer referenced and will
+        * be marked unmodified by hammer2_chain_delete(), avoiding unnecessary
+        * I/O.
+        */
+       hammer2_chain_delete(hmp, parent, chain);
+       /* XXX nlinks (hardlink special case) */
+       /* XXX nlinks (parent directory) */
+
+#if 0
+       /*
+        * Destroy any associated vnode, but only if this was the last
+        * link.  XXX this might not be needed.
+        */
+       if (chain->u.ip->vp) {
+               struct vnode *vp;
+               vp = hammer2_igetv(chain->u.ip, &error);
+               if (error == 0) {
+                       vn_unlock(vp);
+                       /* hammer2_knote(vp, NOTE_DELETE); */
+                       cache_inval_vp(vp, CINV_DESTROY);
+                       vrele(vp);
+               }
+       }
+#endif
+       error = 0;
+
+done:
+       hammer2_chain_unlock(hmp, chain);
+       hammer2_chain_unlock(hmp, parent);
+
+       return error;
+}
+
+/*
  * Calculate the allocation size for the file fragment straddling EOF
  */
 int
index b83a776..f0606d0 100644 (file)
 
 #include "hammer2.h"
 
-static int hammer2_ioctl_get_version(hammer2_inode_t *ip, void *data);
-static int hammer2_ioctl_get_remote(hammer2_inode_t *ip, void *data);
-static int hammer2_ioctl_add_remote(hammer2_inode_t *ip, void *data);
-static int hammer2_ioctl_del_remote(hammer2_inode_t *ip, void *data);
-static int hammer2_ioctl_rep_remote(hammer2_inode_t *ip, void *data);
-static int hammer2_ioctl_get_socket(hammer2_inode_t *ip, void *data);
-static int hammer2_ioctl_set_socket(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_remote_get(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data);
+static int hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data);
 
 int
 hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
@@ -63,53 +66,44 @@ hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
        error = priv_check_cred(cred, PRIV_HAMMER_IOCTL, 0);
 
        switch(com) {
-       case HAMMER2IOC_GET_VERSION:
-               /*
-                * Retrieve version and basic status
-                */
-               error = hammer2_ioctl_get_version(ip, data);
+       case HAMMER2IOC_VERSION_GET:
+               error = hammer2_ioctl_version_get(ip, data);
                break;
-       case HAMMER2IOC_GET_REMOTE:
-               /*
-                * Retrieve information about a remote
-                */
+       case HAMMER2IOC_REMOTE_GET:
                if (error == 0)
-                       error = hammer2_ioctl_get_remote(ip, data);
+                       error = hammer2_ioctl_remote_get(ip, data);
                break;
-       case HAMMER2IOC_ADD_REMOTE:
-               /*
-                * Add new remote entry.
-                */
+       case HAMMER2IOC_REMOTE_ADD:
                if (error == 0)
-                       error = hammer2_ioctl_add_remote(ip, data);
+                       error = hammer2_ioctl_remote_add(ip, data);
                break;
-       case HAMMER2IOC_DEL_REMOTE:
-               /*
-                * Delete existing remote entry
-                */
+       case HAMMER2IOC_REMOTE_DEL:
                if (error == 0)
-                       error = hammer2_ioctl_del_remote(ip, data);
+                       error = hammer2_ioctl_remote_del(ip, data);
                break;
-       case HAMMER2IOC_REP_REMOTE:
-               /*
-                * Replace existing remote entry
-                */
+       case HAMMER2IOC_REMOTE_REP:
                if (error == 0)
-                       error = hammer2_ioctl_rep_remote(ip, data);
+                       error = hammer2_ioctl_remote_rep(ip, data);
                break;
-       case HAMMER2IOC_GET_SOCKET:
-               /*
-                * Retrieve communications socket
-                */
+       case HAMMER2IOC_SOCKET_GET:
                if (error == 0)
-                       error = hammer2_ioctl_get_socket(ip, data);
+                       error = hammer2_ioctl_socket_get(ip, data);
                break;
-       case HAMMER2IOC_SET_SOCKET:
-               /*
-                * Set communications socket for connection
-                */
+       case HAMMER2IOC_SOCKET_SET:
+               if (error == 0)
+                       error = hammer2_ioctl_socket_set(ip, data);
+               break;
+       case HAMMER2IOC_PFS_GET:
                if (error == 0)
-                       error = hammer2_ioctl_set_socket(ip, data);
+                       error = hammer2_ioctl_pfs_get(ip, data);
+               break;
+       case HAMMER2IOC_PFS_CREATE:
+               if (error == 0)
+                       error = hammer2_ioctl_pfs_create(ip, data);
+               break;
+       case HAMMER2IOC_PFS_DELETE:
+               if (error == 0)
+                       error = hammer2_ioctl_pfs_delete(ip, data);
                break;
        default:
                error = EOPNOTSUPP;
@@ -122,7 +116,7 @@ hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
  * Retrieve version and basic info
  */
 static int
-hammer2_ioctl_get_version(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data)
 {
        hammer2_mount_t *hmp = ip->hmp;
        hammer2_ioc_version_t *version = data;
@@ -135,7 +129,7 @@ hammer2_ioctl_get_version(hammer2_inode_t *ip, void *data)
  * Retrieve information about a remote
  */
 static int
-hammer2_ioctl_get_remote(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_remote_get(hammer2_inode_t *ip, void *data)
 {
        hammer2_mount_t *hmp = ip->hmp;
        hammer2_ioc_remote_t *remote = data;
@@ -167,7 +161,7 @@ hammer2_ioctl_get_remote(hammer2_inode_t *ip, void *data)
  * Add new remote entry
  */
 static int
-hammer2_ioctl_add_remote(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data)
 {
        hammer2_mount_t *hmp = ip->hmp;
        hammer2_ioc_remote_t *remote = data;
@@ -201,7 +195,7 @@ failed:
  * Delete existing remote entry
  */
 static int
-hammer2_ioctl_del_remote(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data)
 {
        hammer2_mount_t *hmp = ip->hmp;
        hammer2_ioc_remote_t *remote = data;
@@ -237,7 +231,7 @@ failed:
  * Replace existing remote entry
  */
 static int
-hammer2_ioctl_rep_remote(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data)
 {
        hammer2_mount_t *hmp = ip->hmp;
        hammer2_ioc_remote_t *remote = data;
@@ -256,7 +250,7 @@ hammer2_ioctl_rep_remote(hammer2_inode_t *ip, void *data)
  * Retrieve communications socket
  */
 static int
-hammer2_ioctl_get_socket(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data)
 {
        return (EOPNOTSUPP);
 }
@@ -265,7 +259,7 @@ hammer2_ioctl_get_socket(hammer2_inode_t *ip, void *data)
  * Set communications socket for connection
  */
 static int
-hammer2_ioctl_set_socket(hammer2_inode_t *ip, void *data)
+hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data)
 {
        hammer2_mount_t *hmp = ip->hmp;
        hammer2_ioc_remote_t *remote = data;
@@ -279,3 +273,113 @@ hammer2_ioctl_set_socket(hammer2_inode_t *ip, void *data)
 
        return(0);
 }
+
+/*
+ * Used to scan PFSs, which are directories under the super-root.
+ */
+static int
+hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data)
+{
+       hammer2_mount_t *hmp = ip->hmp;
+       hammer2_ioc_pfs_t *pfs = data;
+       hammer2_chain_t *parent;
+       hammer2_chain_t *chain;
+       hammer2_inode_t *xip;
+       int error = 0;
+
+       parent = hmp->schain;
+       error = hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
+       if (error)
+               goto done;
+
+       /*
+        * Search for the first key or specific key.  Remember that keys
+        * can be returned in any order.
+        */
+       if (pfs->name_key == 0) {
+               chain = hammer2_chain_lookup(hmp, &parent,
+                                            0, (hammer2_key_t)-1, 0);
+       } else {
+               chain = hammer2_chain_lookup(hmp, &parent,
+                                            pfs->name_key, pfs->name_key, 0);
+       }
+       while (chain && chain->bref.type != HAMMER2_BREF_TYPE_INODE) {
+               chain = hammer2_chain_next(hmp, &parent, chain,
+                                    0, (hammer2_key_t)-1, 0);
+       }
+       if (chain) {
+               /*
+                * Load the data being returned by the ioctl.
+                */
+               xip = chain->u.ip;
+               pfs->name_key = xip->ip_data.name_key;
+               pfs->pfs_type = xip->ip_data.pfs_type;
+               pfs->pfs_id = xip->ip_data.pfs_id;
+               pfs->pfs_fsid = xip->ip_data.pfs_fsid;
+               KKASSERT(xip->ip_data.name_len < sizeof(pfs->name));
+               bcopy(xip->ip_data.filename, pfs->name,
+                     xip->ip_data.name_len);
+               pfs->name[xip->ip_data.name_len] = 0;
+
+               /*
+                * Calculate the next field
+                */
+               do {
+                       chain = hammer2_chain_next(hmp, &parent, chain,
+                                            0, (hammer2_key_t)-1, 0);
+               } while (chain && chain->bref.type != HAMMER2_BREF_TYPE_INODE);
+               if (chain) {
+                       pfs->name_next = chain->u.ip->ip_data.name_key;
+                       hammer2_chain_unlock(hmp, chain);
+               } else {
+                       pfs->name_next = (hammer2_key_t)-1;
+               }
+       } else {
+               pfs->name_next = (hammer2_key_t)-1;
+               error = ENOENT;
+       }
+done:
+       hammer2_chain_unlock(hmp, parent);
+       return (error);
+}
+
+/*
+ * Create a new PFS under the super-root
+ */
+static int
+hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
+{
+       hammer2_mount_t *hmp = ip->hmp;
+       hammer2_ioc_pfs_t *pfs = data;
+       hammer2_inode_t *nip = NULL;
+       int error;
+
+       pfs->name[sizeof(pfs->name) - 1] = 0;   /* ensure 0-termination */
+       error = hammer2_inode_create(hmp, NULL, NULL, hmp->schain->u.ip,
+                                    pfs->name, strlen(pfs->name),
+                                    &nip);
+       if (error == 0) {
+               hammer2_chain_modify(hmp, &nip->chain, 0);
+               nip->ip_data.pfs_type = pfs->pfs_type;
+               nip->ip_data.pfs_id = pfs->pfs_id;
+               /* nip->ip_data.pfsfsid = XXX */
+               hammer2_chain_unlock(hmp, &nip->chain);
+       }
+       return (error);
+}
+
+/*
+ * Destroy an existing PFS under the super-root
+ */
+static int
+hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data)
+{
+       hammer2_mount_t *hmp = ip->hmp;
+       hammer2_ioc_pfs_t *pfs = data;
+       int error;
+
+       error = hammer2_unlink_file(hmp->schain->u.ip,
+                                   pfs->name, strlen(pfs->name),
+                                   0, 1);
+       return (error);
+}
index 5ec7228..ffa49ad 100644 (file)
@@ -71,14 +71,41 @@ struct hammer2_ioc_remote {
 
 typedef struct hammer2_ioc_remote hammer2_ioc_remote_t;
 
-#define HAMMER2IOC_GET_VERSION _IOWR('h', 64, struct hammer2_ioc_version)
+/*
+ * Ioctls to manage PFSs
+ *
+ * PFSs can be clustered by matching their pfs_id, and the PFSs making up
+ * a cluster can be uniquely identified by combining the vol_id with
+ * the pfs_id.
+ */
+struct hammer2_ioc_pfs {
+       hammer2_key_t           name_key;       /* super-root directory scan */
+       hammer2_key_t           name_next;      /* (GET only) */
+       uint8_t                 pfs_type;       /* e.g. MASTER, SLAVE, ... */
+       uint8_t                 reserved0011;
+       uint8_t                 reserved0012;
+       uint8_t                 reserved0013;
+       uint32_t                reserved0014;
+       uint64_t                reserved0018;
+       uuid_t                  pfs_fsid;       /* identifies PFS instance */
+       uuid_t                  pfs_id;         /* identifies PFS cluster */
+       char                    name[NAME_MAX+1]; /* device@name mtpt */
+};
+
+typedef struct hammer2_ioc_pfs hammer2_ioc_pfs_t;
+
+#define HAMMER2IOC_VERSION_GET _IOWR('h', 64, struct hammer2_ioc_version)
+
+#define HAMMER2IOC_REMOTE_GET  _IOWR('h', 68, struct hammer2_ioc_remote)
+#define HAMMER2IOC_REMOTE_ADD  _IOWR('h', 69, struct hammer2_ioc_remote)
+#define HAMMER2IOC_REMOTE_DEL  _IOWR('h', 70, struct hammer2_ioc_remote)
+#define HAMMER2IOC_REMOTE_REP  _IOWR('h', 71, struct hammer2_ioc_remote)
 
-#define HAMMER2IOC_GET_REMOTE  _IOWR('h', 68, struct hammer2_ioc_remote)
-#define HAMMER2IOC_ADD_REMOTE  _IOWR('h', 69, struct hammer2_ioc_remote)
-#define HAMMER2IOC_DEL_REMOTE  _IOWR('h', 70, struct hammer2_ioc_remote)
-#define HAMMER2IOC_REP_REMOTE  _IOWR('h', 71, struct hammer2_ioc_remote)
+#define HAMMER2IOC_SOCKET_GET  _IOWR('h', 76, struct hammer2_ioc_remote)
+#define HAMMER2IOC_SOCKET_SET  _IOWR('h', 77, struct hammer2_ioc_remote)
 
-#define HAMMER2IOC_GET_SOCKET  _IOWR('h', 76, struct hammer2_ioc_remote)
-#define HAMMER2IOC_SET_SOCKET  _IOWR('h', 77, struct hammer2_ioc_remote)
+#define HAMMER2IOC_PFS_GET     _IOWR('h', 80, struct hammer2_ioc_pfs)
+#define HAMMER2IOC_PFS_CREATE  _IOWR('h', 81, struct hammer2_ioc_pfs)
+#define HAMMER2IOC_PFS_DELETE  _IOWR('h', 82, struct hammer2_ioc_pfs)
 
 #endif
index 7dfe551..9b4409e 100644 (file)
@@ -57,9 +57,6 @@ static hammer2_off_t hammer2_assign_physical(hammer2_inode_t *ip,
                                hammer2_key_t lbase, int lblksize, int *errorp);
 static void hammer2_extend_file(hammer2_inode_t *ip, hammer2_key_t nsize);
 static void hammer2_truncate_file(hammer2_inode_t *ip, hammer2_key_t nsize);
-static int hammer2_unlink_file(hammer2_inode_t *dip,
-                               const uint8_t *name, size_t name_len,
-                               int isdir, int adjlinks);
 
 /*
  * Last reference to a vnode is going away but it is still cached.
@@ -1777,153 +1774,6 @@ done:
        return (error);
 }
 
-/*
- * Unlink the file from the specified directory inode.  The directory inode
- * does not need to be locked.
- *
- * isdir determines whether a directory/non-directory check should be made.
- * No check is made if isdir is set to -1.
- *
- * adjlinks tells unlink that we want to adjust the nlinks count of the
- * inode.  When removing the last link for a NON forwarding entry we can
- * just ignore the link count... no point updating the inode that we are
- * about to dereference, it would just result in a lot of wasted I/O.
- *
- * However, if the entry is a forwarding entry (aka a hardlink), and adjlinks
- * is non-zero, we have to locate the hardlink and adjust its nlinks field.
- */
-static
-int
-hammer2_unlink_file(hammer2_inode_t *dip, const uint8_t *name, size_t name_len,
-                   int isdir, int adjlinks)
-{
-       hammer2_mount_t *hmp;
-       hammer2_chain_t *parent;
-       hammer2_chain_t *chain;
-       hammer2_chain_t *dparent;
-       hammer2_chain_t *dchain;
-       hammer2_key_t lhc;
-       int error;
-
-       error = 0;
-
-       hmp = dip->hmp;
-       lhc = hammer2_dirhash(name, name_len);
-
-       /*
-        * Search for the filename in the directory
-        */
-       parent = &dip->chain;
-       hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
-       chain = hammer2_chain_lookup(hmp, &parent,
-                                    lhc, lhc + HAMMER2_DIRHASH_LOMASK,
-                                    0);
-       while (chain) {
-               if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
-                   chain->u.ip &&
-                   name_len == chain->data->ipdata.name_len &&
-                   bcmp(name, chain->data->ipdata.filename, name_len) == 0) {
-                       break;
-               }
-               chain = hammer2_chain_next(hmp, &parent, chain,
-                                          lhc, lhc + HAMMER2_DIRHASH_LOMASK,
-                                          0);
-       }
-
-       /*
-        * Not found or wrong type (isdir < 0 disables the type check).
-        */
-       if (chain == NULL) {
-               hammer2_chain_unlock(hmp, parent);
-               return ENOENT;
-       }
-       if (chain->data->ipdata.type == HAMMER2_OBJTYPE_DIRECTORY &&
-           isdir == 0) {
-               error = ENOTDIR;
-               goto done;
-       }
-       if (chain->data->ipdata.type != HAMMER2_OBJTYPE_DIRECTORY &&
-           isdir == 1) {
-               error = EISDIR;
-               goto done;
-       }
-
-       /*
-        * If this is a directory the directory must be empty.  However, if
-        * isdir < 0 we are doing a rename and the directory does not have
-        * to be empty.
-        */
-       if (chain->data->ipdata.type == HAMMER2_OBJTYPE_DIRECTORY &&
-           isdir >= 0) {
-               dparent = chain;
-               hammer2_chain_lock(hmp, dparent, HAMMER2_RESOLVE_ALWAYS);
-               dchain = hammer2_chain_lookup(hmp, &dparent,
-                                             0, (hammer2_key_t)-1,
-                                             HAMMER2_LOOKUP_NODATA);
-               if (dchain) {
-                       hammer2_chain_unlock(hmp, dchain);
-                       hammer2_chain_unlock(hmp, dparent);
-                       error = ENOTEMPTY;
-                       goto done;
-               }
-               hammer2_chain_unlock(hmp, dparent);
-               dparent = NULL;
-               /* dchain NULL */
-       }
-
-#if 0
-       /*
-        * If adjlinks is non-zero this is a real deletion (otherwise it is
-        * probably a rename).  XXX
-        */
-       if (adjlinks) {
-               if (chain->data->ipdata.type == HAMMER2_OBJTYPE_HARDLINK) {
-                       /*hammer2_adjust_hardlink(chain->u.ip, -1);*/
-                       /* error handling */
-               } else {
-                       waslastlink = 1;
-               }
-       } else {
-               waslastlink = 0;
-       }
-#endif
-
-       /*
-        * Found, the chain represents the inode.  Remove the parent reference
-        * to the chain.  The chain itself is no longer referenced and will
-        * be marked unmodified by hammer2_chain_delete(), avoiding unnecessary
-        * I/O.
-        */
-       hammer2_chain_delete(hmp, parent, chain);
-       /* XXX nlinks (hardlink special case) */
-       /* XXX nlinks (parent directory) */
-
-#if 0
-       /*
-        * Destroy any associated vnode, but only if this was the last
-        * link.  XXX this might not be needed.
-        */
-       if (chain->u.ip->vp) {
-               struct vnode *vp;
-               vp = hammer2_igetv(chain->u.ip, &error);
-               if (error == 0) {
-                       vn_unlock(vp);
-                       /* hammer2_knote(vp, NOTE_DELETE); */
-                       cache_inval_vp(vp, CINV_DESTROY);
-                       vrele(vp);
-               }
-       }
-#endif
-       error = 0;
-
-done:
-       hammer2_chain_unlock(hmp, chain);
-       hammer2_chain_unlock(hmp, parent);
-
-       return error;
-}
-
-
 static int hammer2_strategy_read(struct vop_strategy_args *ap);
 static int hammer2_strategy_write(struct vop_strategy_args *ap);