func: static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
  
  {
  
      BDRVSheepdogState *s = bs->opaque;
  
      int ret, fd;
  
      uint32_t new_vid;
  
      SheepdogInode *inode;
  
      unsigned int datalen;
  
  
  
      dprintf("sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " "
  
              "is_snapshot %d\n", sn_info->name, sn_info->id_str,
  
              s->name, sn_info->vm_state_size, s->is_snapshot);
  
  
  
      if (s->is_snapshot) {
  
          error_report("You can't create a snapshot of a snapshot VDI, "
  
                       "%s (%" PRIu32 ").", s->name, s->inode.vdi_id);
  
  
  
          return -EINVAL;
  
      }
  
  
  
      dprintf("%s %s\n", sn_info->name, sn_info->id_str);
  
  
  
      s->inode.vm_state_size = sn_info->vm_state_size;
  
      s->inode.vm_clock_nsec = sn_info->vm_clock_nsec;
  
      /* It appears that inode.tag does not require a NUL terminator,
  
       * which means this use of strncpy is ok.
  
       */
  
      strncpy(s->inode.tag, sn_info->name, sizeof(s->inode.tag));
  
      /* we don't need to update entire object */
  
      datalen = SD_INODE_SIZE - sizeof(s->inode.data_vdi_id);
  
  
  
      /* refresh inode. */
  
      fd = connect_to_sdog(s->addr, s->port);
  
      if (fd < 0) {
  
          ret = fd;
  
          goto cleanup;
  
      }
  
  
  
      ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
  
                         s->inode.nr_copies, datalen, 0, false, s->cache_enabled);
  
      if (ret < 0) {
  
          error_report("failed to write snapshot's inode.");
  
          goto cleanup;
  
      }
  
  
  
      ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid, 1,
  
                         s->addr, s->port);
  
      if (ret < 0) {
  
          error_report("failed to create inode for snapshot. %s",
  
                       strerror(errno));
  
          goto cleanup;
  
      }
  
  
  
      inode = (SheepdogInode *)g_malloc(datalen);
  
  
  
      ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
  
                        s->inode.nr_copies, datalen, 0, s->cache_enabled);
  
  
  
      if (ret < 0) {
  
          error_report("failed to read new inode info. %s", strerror(errno));
  
          goto cleanup;
  
      }
  
  
  
      memcpy(&s->inode, inode, datalen);
  
      dprintf("s->inode: name %s snap_id %x oid %x\n",
  
              s->inode.name, s->inode.snap_id, s->inode.vdi_id);
  
  
  
  cleanup:
  
      closesocket(fd);
  
      return ret;
  
  }
  