Example #1
0
/* Return an identifier for an shared memory segment of at least size
   SIZE which is associated with KEY.  */
int
__shmget (key_t key, size_t size, int shmflags)
{
  error_t err;
  int fd;

  if (key == IPC_PRIVATE || shmflags & IPC_EXCL)
    /* An exclusive shared memory segment must be created.  */
    err = get_exclusive (shmflags, size, &key, &fd);
  else
    err = get_shared (shmflags, size, key, &fd);

  if (err)
    {
      errno = err;
      return -1;
    }

  /* From here, we can't fail.  That's important, as otherwise we
     would need to unlink the file if we created it (in that case, the
     code above would have to be changed to pass a "created" flag down
     to the caller).  */

  __close (fd);

  return key;
}
Example #2
0
static
int little_lock(sqlite3_file *file, int lock) {
  int res;
  little_file *self = (little_file*)file;

  trace("LOCK UP %s...\n", locktypeName(lock));
  fflush(stdout);
  switch (lock) {
    case SQLITE_LOCK_SHARED:
      res = get_shared(self->name);
      if (res < 0) trace ("Optimistic locking! forge ahead\n");
      else self->shared_lock_number = res;

      // don't worry if we don't get the lock, we have versioning
      res = get_version(self->name, &(self->version), &(self->nextfreeblock));
      if (errno == ENOENT) res = 0;
      break;

    case SQLITE_LOCK_RESERVED:
      res = get_reserved(self->name);
      break;

    case SQLITE_LOCK_EXCLUSIVE:
      res = get_exclusive(self->name, self->shared_lock_number);
      self->shared_lock_number = -1;
      ++(self->version);
      break;

    default: return SQLITE_ERROR;
  }
  if (res == -EAGAIN) return SQLITE_BUSY;
  if (res < 0) return SQLITE_ERROR;
  trace("LOCK UP %s OK\n", locktypeName(lock));
  return SQLITE_OK;
}
Example #3
0
/* Open the shared memory segment KEY (creating it if it doesn't yet
   exist) and return a file descriptor to it in R_FD.  */
static error_t
get_shared (int shmflags, size_t size, key_t key, int *r_fd)
{
  error_t err = 0;
  char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
  int fd = -1;
  int create_flag;

  create_flag = (shmflags & IPC_CREAT) ? O_CREAT : 0;
  sprintf (filename, SHM_DIR SHM_NAMEPRI, key);

  do
    {
      fd = __open (filename, O_NORW | create_flag, shmflags & 0777);

      if (fd < 0 && errno != ENOENT)
	/* We give up.  */
	return errno;
      else if (fd >= 0)
	{
	  int res;
	  struct stat statbuf;

	  /* Check the size (we only need to do this if we did not
	     create the shared memory segment file ourselves).  */
	  res = __fstat (fd, &statbuf);
	  if (res < 0)
	    {
	      err = errno;
	      __close (fd);
	      return err;
	    }

	  if (statbuf.st_size < size)
	    {
	      __close (fd);
	      return EINVAL;
	    }
	}	  
      else
	{
	  /* The memory segment doesn't exist.  */
	  if (create_flag)
	    {
	      /* Try to create it exclusively.  */
	      err = get_exclusive (shmflags, size, &key, &fd);
	      if (err == EEXIST)
		/* If somebody created it in the meanwhile, just try again.  */
		err = 0;
	    }
	  else
	    err = ENOENT;
	}
    }
  while (fd < 0 && !err);

  if (!err)
    *r_fd = fd;
  else
    *r_fd = -1;

  return err;
}
Example #4
0
static int vol_cdev_ioctl(struct inode *inode, struct file *file,
			  unsigned int cmd, unsigned long arg)
{
	int err = 0;
	struct ubi_volume_desc *desc = file->private_data;
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;
	void __user *argp = (void __user *)arg;

	switch (cmd) {
	/* Volume update command */
	case UBI_IOCVOLUP:
	{
		int64_t bytes, rsvd_bytes;

		if (!capable(CAP_SYS_RESOURCE)) {
			err = -EPERM;
			break;
		}

		err = copy_from_user(&bytes, argp, sizeof(int64_t));
		if (err) {
			err = -EFAULT;
			break;
		}

		if (desc->mode == UBI_READONLY) {
			err = -EROFS;
			break;
		}

		rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad);
		if (bytes < 0 || bytes > rsvd_bytes) {
			err = -EINVAL;
			break;
		}

		err = get_exclusive(desc);
		if (err < 0)
			break;

		err = ubi_start_update(ubi, vol, bytes);
		if (bytes == 0)
			revoke_exclusive(desc, UBI_READWRITE);
		break;
	}

	/* Atomic logical eraseblock change command */
	case UBI_IOCEBCH:
	{
		struct ubi_leb_change_req req;

		err = copy_from_user(&req, argp,
				     sizeof(struct ubi_leb_change_req));
		if (err) {
			err = -EFAULT;
			break;
		}

		if (desc->mode == UBI_READONLY ||
		    vol->vol_type == UBI_STATIC_VOLUME) {
			err = -EROFS;
			break;
		}

		/* Validate the request */
		err = -EINVAL;
		if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
		    req.bytes < 0 || req.lnum >= vol->usable_leb_size)
			break;
		if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
		    req.dtype != UBI_UNKNOWN)
			break;

		err = get_exclusive(desc);
		if (err < 0)
			break;

		err = ubi_start_leb_change(ubi, vol, &req);
		if (req.bytes == 0)
			revoke_exclusive(desc, UBI_READWRITE);
		break;
	}

#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
	/* Logical eraseblock erasure command */
	case UBI_IOCEBER:
	{
		int32_t lnum;

		err = get_user(lnum, (__user int32_t *)argp);
		if (err) {
			err = -EFAULT;
			break;
		}

		if (desc->mode == UBI_READONLY ||
		    vol->vol_type == UBI_STATIC_VOLUME) {
			err = -EROFS;
			break;
		}

		if (lnum < 0 || lnum >= vol->reserved_pebs) {
			err = -EINVAL;
			break;
		}

		dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
		err = ubi_eba_unmap_leb(ubi, vol, lnum);
		if (err)
			break;

		err = ubi_wl_flush(ubi);
		break;
	}
#endif

	default:
		err = -ENOTTY;
		break;
	}

	return err;
}
Example #5
0
static int vol_cdev_ioctl(struct inode *inode, struct file *file,
			  unsigned int cmd, unsigned long arg)
{
	int err = 0;
	struct ubi_volume_desc *desc = file->private_data;
	struct ubi_volume *vol = desc->vol;
	struct ubi_device *ubi = vol->ubi;
	void __user *argp = (void __user *)arg;

	if (_IOC_NR(cmd) > VOL_CDEV_IOC_MAX_SEQ ||
	    _IOC_TYPE(cmd) != UBI_VOL_IOC_MAGIC)
		return -ENOTTY;

	if (_IOC_DIR(cmd) && _IOC_READ)
		err = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
	else if (_IOC_DIR(cmd) && _IOC_WRITE)
		err = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
	if (err)
		return -EFAULT;

	switch (cmd) {

	/* Volume update command */
	case UBI_IOCVOLUP:
	{
		int64_t bytes, rsvd_bytes;

		if (!capable(CAP_SYS_RESOURCE)) {
			err = -EPERM;
			break;
		}

		err = copy_from_user(&bytes, argp, sizeof(int64_t));
		if (err) {
			err = -EFAULT;
			break;
		}

		if (desc->mode == UBI_READONLY) {
			err = -EROFS;
			break;
		}

		rsvd_bytes = vol->reserved_pebs * (ubi->leb_size-vol->data_pad);
		if (bytes < 0 || bytes > rsvd_bytes) {
			err = -EINVAL;
			break;
		}

		err = get_exclusive(desc);
		if (err < 0)
			break;

		err = ubi_start_update(ubi, vol->vol_id, bytes);
		if (bytes == 0)
			revoke_exclusive(desc, UBI_READWRITE);

		file->f_pos = 0;
		break;
	}

#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
	/* Logical eraseblock erasure command */
	case UBI_IOCEBER:
	{
		int32_t lnum;

		err = __get_user(lnum, (__user int32_t *)argp);
		if (err) {
			err = -EFAULT;
			break;
		}

		if (desc->mode == UBI_READONLY) {
			err = -EROFS;
			break;
		}

		if (lnum < 0 || lnum >= vol->reserved_pebs) {
			err = -EINVAL;
			break;
		}

		if (vol->vol_type != UBI_DYNAMIC_VOLUME) {
			err = -EROFS;
			break;
		}

		dbg_msg("erase LEB %d:%d", vol->vol_id, lnum);
		err = ubi_eba_unmap_leb(ubi, vol->vol_id, lnum);
		if (err)
			break;

		err = ubi_wl_flush(ubi);
		break;
	}
#endif

	default:
		err = -ENOTTY;
		break;
	}

	return err;
}