/* * Add new remote entry */ static int hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data) { hammer2_ioc_remote_t *remote = data; hammer2_pfs_t *pmp = ip->pmp; hammer2_dev_t *hmp; int copyid = remote->copyid; int error = 0; hmp = pmp->pfs_hmps[0]; if (hmp == NULL) return (EINVAL); if (copyid >= HAMMER2_COPYID_COUNT) return (EINVAL); hammer2_voldata_lock(hmp); if (copyid < 0) { for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) { if (hmp->voldata.copyinfo[copyid].copyid == 0) break; } if (copyid == HAMMER2_COPYID_COUNT) { error = ENOSPC; goto failed; } } hammer2_voldata_modify(hmp); remote->copy1.copyid = copyid; hmp->voldata.copyinfo[copyid] = remote->copy1; hammer2_volconf_update(hmp, copyid); failed: hammer2_voldata_unlock(hmp); return (error); }
/* * Retrieve information about a remote */ static int hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data) { hammer2_dev_t *hmp; hammer2_ioc_remote_t *remote = data; int copyid = remote->copyid; hmp = ip->pmp->pfs_hmps[0]; if (hmp == NULL) return (EINVAL); if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) return (EINVAL); hammer2_voldata_lock(hmp); remote->copy1 = hmp->voldata.copyinfo[copyid]; hammer2_voldata_unlock(hmp); /* * Adjust nextid (GET only) */ while (++copyid < HAMMER2_COPYID_COUNT && hmp->voldata.copyinfo[copyid].copyid == 0) { ; } if (copyid == HAMMER2_COPYID_COUNT) remote->nextid = -1; else remote->nextid = copyid; return(0); }
/* * Set communications socket for connection */ static int hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data) { hammer2_ioc_remote_t *remote = data; hammer2_dev_t *hmp; int copyid = remote->copyid; hmp = ip->pmp->pfs_hmps[0]; if (hmp == NULL) return (EINVAL); if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) return (EINVAL); hammer2_voldata_lock(hmp); hammer2_voldata_unlock(hmp); return(0); }
/* * Replace existing remote entry */ static int hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data) { hammer2_ioc_remote_t *remote = data; hammer2_dev_t *hmp; int copyid = remote->copyid; hmp = ip->pmp->pfs_hmps[0]; if (hmp == NULL) return (EINVAL); if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT) return (EINVAL); hammer2_voldata_lock(hmp); hammer2_voldata_modify(hmp); /*hammer2_volconf_update(hmp, copyid);*/ hammer2_voldata_unlock(hmp); return(0); }
/* * Delete existing remote entry */ static int hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data) { hammer2_ioc_remote_t *remote = data; hammer2_pfs_t *pmp = ip->pmp; hammer2_dev_t *hmp; int copyid = remote->copyid; int error = 0; hmp = pmp->pfs_hmps[0]; if (hmp == NULL) return (EINVAL); if (copyid >= HAMMER2_COPYID_COUNT) return (EINVAL); remote->copy1.path[sizeof(remote->copy1.path) - 1] = 0; hammer2_voldata_lock(hmp); if (copyid < 0) { for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) { if (hmp->voldata.copyinfo[copyid].copyid == 0) continue; if (strcmp(remote->copy1.path, hmp->voldata.copyinfo[copyid].path) == 0) { break; } } if (copyid == HAMMER2_COPYID_COUNT) { error = ENOENT; goto failed; } } hammer2_voldata_modify(hmp); hmp->voldata.copyinfo[copyid].copyid = 0; hammer2_volconf_update(hmp, copyid); failed: hammer2_voldata_unlock(hmp); return (error); }
/* * Create a new inode in the specified directory using the vattr to * figure out the type of inode. * * 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_inode_t *dip, struct vattr *vap, struct ucred *cred, const uint8_t *name, size_t name_len, hammer2_inode_t **nipp) { hammer2_mount_t *hmp = dip->hmp; hammer2_chain_t *chain; hammer2_chain_t *parent; hammer2_inode_t *nip; hammer2_key_t lhc; int error; uid_t xuid; lhc = hammer2_dirhash(name, name_len); /* * Locate the inode or indirect block to create the new * entry in. At the same time check for key collisions * and iterate until we don't get one. */ parent = &dip->chain; hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS); error = 0; while (error == 0) { chain = hammer2_chain_lookup(hmp, &parent, lhc, lhc, 0); if (chain == NULL) break; if ((lhc & HAMMER2_DIRHASH_VISIBLE) == 0) error = ENOSPC; if ((lhc & HAMMER2_DIRHASH_LOMASK) == HAMMER2_DIRHASH_LOMASK) error = ENOSPC; hammer2_chain_unlock(hmp, chain); chain = NULL; ++lhc; } if (error == 0) { chain = hammer2_chain_create(hmp, parent, NULL, lhc, 0, HAMMER2_BREF_TYPE_INODE, HAMMER2_INODE_BYTES); if (chain == NULL) error = EIO; } hammer2_chain_unlock(hmp, parent); /* * Handle the error case */ if (error) { KKASSERT(chain == NULL); *nipp = NULL; return (error); } /* * Set up the new inode */ nip = chain->u.ip; *nipp = nip; hammer2_voldata_lock(hmp); 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; hammer2_update_time(&nip->ip_data.ctime); nip->ip_data.mtime = nip->ip_data.ctime; if (vap) nip->ip_data.mode = vap->va_mode; nip->ip_data.nlinks = 1; if (vap) { if (dip) { xuid = hammer2_to_unix_xid(&dip->ip_data.uid); xuid = vop_helper_create_uid(dip->pmp->mp, dip->ip_data.mode, xuid, cred, &vap->va_mode); } else { xuid = 0; } /* XXX if (vap->va_vaflags & VA_UID_UUID_VALID) nip->ip_data.uid = vap->va_uid_uuid; else if (vap->va_uid != (uid_t)VNOVAL) hammer2_guid_to_uuid(&nip->ip_data.uid, vap->va_uid); else */ hammer2_guid_to_uuid(&nip->ip_data.uid, xuid); /* XXX if (vap->va_vaflags & VA_GID_UUID_VALID) nip->ip_data.gid = vap->va_gid_uuid; else if (vap->va_gid != (gid_t)VNOVAL) hammer2_guid_to_uuid(&nip->ip_data.gid, vap->va_gid); else */ if (dip) nip->ip_data.gid = dip->ip_data.gid; } /* * Regular files and softlinks allow a small amount of data to be * directly embedded in the inode. This flag will be cleared if * the size is extended past the embedded limit. */ if (nip->ip_data.type == HAMMER2_OBJTYPE_REGFILE || nip->ip_data.type == HAMMER2_OBJTYPE_SOFTLINK) { nip->ip_data.op_flags |= HAMMER2_OPFLAG_DIRECTDATA; } KKASSERT(name_len < HAMMER2_INODE_MAXNAME); bcopy(name, nip->ip_data.filename, name_len); nip->ip_data.name_key = lhc; nip->ip_data.name_len = name_len; return (0); }
static void hammer2_autodmsg(kdmsg_msg_t *msg) { hammer2_dev_t *hmp = msg->state->iocom->handle; int copyid; switch(msg->tcmd) { case DMSG_LNK_CONN | DMSGF_CREATE: case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_DELETE: case DMSG_LNK_CONN | DMSGF_DELETE: /* * NOTE: kern_dmsg will automatically issue a result, * leaving the transaction open, for CREATEs, * and will automatically issue a terminating reply * for DELETEs. */ break; case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_REPLY: case DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_DELETE | DMSGF_REPLY: /* * Do a volume configuration dump when we receive a reply * to our auto-CONN (typically leaving the transaction open). */ if (msg->any.head.cmd & DMSGF_CREATE) { kprintf("HAMMER2: VOLDATA DUMP\n"); /* * Dump the configuration stored in the volume header. * This will typically be import/export access rights, * master encryption keys (encrypted), etc. */ hammer2_voldata_lock(hmp); copyid = 0; while (copyid < HAMMER2_COPYID_COUNT) { if (hmp->voldata.copyinfo[copyid].copyid) hammer2_volconf_update(hmp, copyid); ++copyid; } hammer2_voldata_unlock(hmp); kprintf("HAMMER2: INITIATE SPANs\n"); hammer2_update_spans(hmp, msg->state); } if ((msg->any.head.cmd & DMSGF_DELETE) && msg->state && (msg->state->txcmd & DMSGF_DELETE) == 0) { kprintf("HAMMER2: CONN WAS TERMINATED\n"); } break; case DMSG_LNK_SPAN | DMSGF_CREATE: /* * Monitor SPANs and issue a result, leaving the SPAN open * if it is something we can use now or in the future. */ if (msg->any.lnk_span.peer_type != DMSG_PEER_HAMMER2) { kdmsg_msg_reply(msg, 0); break; } if (msg->any.lnk_span.proto_version != DMSG_SPAN_PROTO_1) { kdmsg_msg_reply(msg, 0); break; } DMSG_TERMINATE_STRING(msg->any.lnk_span.peer_label); kprintf("H2 +RXSPAN cmd=%08x (%-20s) cl=", msg->any.head.cmd, msg->any.lnk_span.peer_label); printf_uuid(&msg->any.lnk_span.peer_id); kprintf(" fs="); printf_uuid(&msg->any.lnk_span.pfs_id); kprintf(" type=%d\n", msg->any.lnk_span.pfs_type); kdmsg_msg_result(msg, 0); break; case DMSG_LNK_SPAN | DMSGF_DELETE: /* * NOTE: kern_dmsg will automatically reply to DELETEs. */ kprintf("H2 -RXSPAN\n"); break; default: break; } }