Пример #1
0
/* Remove a command from the file hash table. */
void
file_command_remove (struct command* command, int status)
{
  DBG("FILE REMOVE COMMAND: CMD %p  status %d\n", command, status);
  FILE_LOCK;
  struct redir *redirs = ct_extract_redirs (command->cmdtree);

  /* For each file. */
  while (redirs)
    {
      DBG("FILE REMOVE COMMAND: file: %s\n", redirs->file);

      /* Find the file being accessed. */
      struct file *file = *file_find (file_hash (redirs->file), redirs->file);
      if (!file)
        DBG("FILE REMOVE COMMAND: error: file not hashed\n");

      /* Remove command as an accessor to the file. */
      file_file_remove_accessor (file, command);

      redirs = redirs->next;
    }
  command->status = status;
  ct_free (command);

  FILE_UNLOCK;
}
Пример #2
0
/* Add a command's file accesses to the hash table. */
static void
file_command_add (struct command *new_command)
{
  FILE_LOCK;
  /* Check dependencies. */
  struct redir *redirs = ct_extract_redirs (new_command->cmdtree);

  /* For each file. */
  while (redirs)
    {
      DBG("FILE ADD COMMAND: file: %s\n", redirs->file);

      /* Find the file being accessed. If not yet hashed, hash it. */
      struct file *file = *file_find (file_hash (redirs->file), redirs->file);
      if (!file)
        file = *file_file_add (redirs->file);

      /* Add command as an accessor. */
      if (file_file_add_accessor (redirs, new_command, file))
        new_command->dependencies++;

      /* Also add file to command's file-accessed list. */
      file_command_list_add (file, &new_command->files);

      redirs = redirs->next;
    }

  DBG("FILE ADD COMMAND: dependencies: %d\n", new_command->dependencies);

  /* Add to frontier if no dependencies. */
  if (new_command->dependencies == 0)
    frontier_add (new_command);
  FILE_UNLOCK;
}
Пример #3
0
/*
 * Lookup file info. If it doesn't exist, create a file info struct
 * and open a (VFS) file for the given inode.
 *
 * FIXME:
 * Note that we open the file O_RDONLY even when creating write locks.
 * This is not quite right, but for now, we assume the client performs
 * the proper R/W checking.
 */
__be32
nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
					struct nfs_fh *f)
{
	struct hlist_node *pos;
	struct nlm_file	*file;
	unsigned int	hash;
	__be32		nfserr;

	nlm_debug_print_fh("nlm_lookup_file", f);

	hash = file_hash(f);

	/* Lock file table */
	mutex_lock(&nlm_file_mutex);

	hlist_for_each_entry(file, pos, &nlm_files[hash], f_list)
		if (!nfs_compare_fh(&file->f_handle, f))
			goto found;

	nlm_debug_print_fh("creating file for", f);

	nfserr = nlm_lck_denied_nolocks;
	file = kzalloc(sizeof(*file), GFP_KERNEL);
	if (!file)
		goto out_unlock;

	memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
	mutex_init(&file->f_mutex);
	INIT_HLIST_NODE(&file->f_list);
	INIT_LIST_HEAD(&file->f_blocks);

	/* Open the file. Note that this must not sleep for too long, else
	 * we would lock up lockd:-) So no NFS re-exports, folks.
	 *
	 * We have to make sure we have the right credential to open
	 * the file.
	 */
	if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) {
		dprintk("lockd: open failed (error %d)\n", nfserr);
		goto out_free;
	}

	hlist_add_head(&file->f_list, &nlm_files[hash]);

found:
	dprintk("lockd: found file %p (count %d)\n", file, file->f_count);
	*result = file;
	file->f_count++;
	nfserr = 0;

out_unlock:
	mutex_unlock(&nlm_file_mutex);
	return nfserr;

out_free:
	kfree(file);
	goto out_unlock;
}
Пример #4
0
/* Insert a command into file hash table. For each file the command accesses,
   the command will be inserted after the currently runnable commands, but
   before every other command.
   Note that if the currently runnable commands have read access, and the
   inserted command also has read access, the inserted command will become
   runnable. */
static void
file_command_insert (struct command *command)
{
  FILE_LOCK;
  struct redir *redirs = ct_extract_redirs (command->cmdtree);
  bool blocked = false;

  /* For each file. */
  while (redirs)
    {
      DBG("FILE INSERT COMMAND: file: %s\n", redirs->file);

      /* Find the file to be accessed. */
      struct file *file = *file_find (file_hash (redirs->file), redirs->file);
      if (!file)
        DBG("FILE INSERT COMMAND: error: file not hashed\n");

      /* Command is blocked if file's current running command is a write, or
         the command we're inserting is a write (the converse is they're all
         reads, meaning they can run simultaneously. */
      if (file->accessors &&
          (file->accessors->access == WRITE_ACCESS ||
           redirs->type == FILE_OUT || redirs->type == FILE_CLOBBER ||
           redirs->type == FILE_APPEND))
        blocked = true;

      if (!file->accessors ||
          (redirs->type == FILE_IN && file->accessors->access == READ_ACCESS))
        frontier_add (command);

      /* Skip through runnable commands.
         1. Read access: iterate until end.
         2. Write access: insert after first accessor.
         3. No accessor: just set as accessor. */
      struct file_acc *acc = file->accessors;
      struct file_acc **accp = &file->accessors;
      while (acc)
        {
          /* Iterate through accessors until write access is found. */
          accp = &acc->next;
          if (acc->access != READ_ACCESS)
            {
              /* If writer is first accessor, skip over it. Otherwise,
                 insert before it. */
              if (acc == file->accessors)
                acc = acc->next;
              break;
            }
          acc = acc->next;
        }

      /* Create accessor for command and insert into accessor list. */
      struct file_acc *new_acc = malloc (sizeof *new_acc);
      if (redirs->type == FILE_IN)
        new_acc->access = READ_ACCESS;
      else if (redirs->type == FILE_OUT && redirs->type == FILE_CLOBBER
               && redirs->type == FILE_APPEND)
        new_acc->access = WRITE_ACCESS;
      new_acc->cmd = command;
      new_acc->next = acc;
      *accp = new_acc;

      redirs = redirs->next;
    }

  /* If the command is not blocked, put into frontier. */
  if (!blocked)
    frontier_add (command);

  FILE_UNLOCK;
}