Пример #1
0
/*===========================================================================*
 *				sys_task				     *
 *===========================================================================*/
PUBLIC void sys_task()
{
/* Main entry point of sys_task.  Get the message and dispatch on type. */
/* 系统调用的主要入口点. 获取消息, 再根据类型分派. */
  static message m;
  register int result;
  register struct proc *caller_ptr;
  unsigned int call_nr;
  int s;

  /* Initialize the system task. */
  /* 初始化系统任务. */ // 初始化系统调用
  initialize();

  while (TRUE) {
      /* Get work. Block and wait until a request message arrives. */
	/* 开始工作. 阻塞, 直到一个请求消息到来. */
      receive(ANY, &m);			
      // 系统调用向量号
      call_nr = (unsigned) m.m_type - KERNEL_CALL;	
      // 请求系统调用的进程指针
      caller_ptr = proc_addr(m.m_source);	

      /* See if the caller made a valid request and try to handle it. */
      // 检查主调进程是否有能力请求该系统调用.
      if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {
	  kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
	  result = ECALLDENIED;			/* illegal message type */
      } else if (call_nr >= NR_SYS_CALLS) {		/* check call number */
	      // 检查系统调用向量号的合法性.
	  kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source);
	  result = EBADREQUEST;			/* illegal message type */
      } 
      else {
      // 执行系统调用.
          result = (*call_vec[call_nr])(&m);	/* handle the kernel call */
      }

      /* Send a reply, unless inhibited by a handler function. Use the kernel
       * function lock_send() to prevent a system call trap. The destination
       * is known to be blocked waiting for a message.
       */
      /*
       * 发送一个回复, 除非被系统调用处理函数禁止了. 使得系统函数
       * lock_send() 来禁止系统调用陷入. 已知目标进程因为等待一个消息而
       * 阻塞.
       */
      if (result != EDONTREPLY) {
	      // 将系统调用的执行结果发送给系统调用的主调进程.
  	  m.m_type = result;			/* report status of call */
          if (OK != (s=lock_send(m.m_source, &m))) {
              kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s);
          }
      }
  }
}
Пример #2
0
/*===========================================================================*
 *				sys_task				     *
 *===========================================================================*/
PUBLIC void sys_task()
{
/* Main entry point of sys_task.  Get the message and dispatch on type. */
  static message m;
  register int result;
  register struct proc *caller_ptr;
  unsigned int call_nr;
  int s;

  /* Initialize the system task. */
  initialize();

  while (TRUE) {
      /* Get work. Block and wait until a request message arrives. */
      receive(ANY, &m);
      call_nr = (unsigned) m.m_type - KERNEL_CALL;
      who_e = m.m_source;
      okendpt(who_e, &who_p);
      caller_ptr = proc_addr(who_p);

      /* See if the caller made a valid request and try to handle it. */
      if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {
#if DEBUG_ENABLE_IPC_WARNINGS
	  kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
#endif
	  result = ECALLDENIED;			/* illegal message type */
      } else if (call_nr >= NR_SYS_CALLS) {		/* check call number */
#if DEBUG_ENABLE_IPC_WARNINGS
	  kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source);
#endif
	  result = EBADREQUEST;			/* illegal message type */
      }
      else {
          result = (*call_vec[call_nr])(&m);	/* handle the system call */
      }

      /* Send a reply, unless inhibited by a handler function. Use the kernel
       * function lock_send() to prevent a system call trap. The destination
       * is known to be blocked waiting for a message.
       */
      if (result != EDONTREPLY) {
  	  m.m_type = result;			/* report status of call */
          if (OK != (s=lock_send(m.m_source, &m))) {
              kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s);
          }
      }
  }
}
Пример #3
0
static void reopen_file(struct tevent_context *ev, struct tevent_timer *te, 
				      struct timeval t, void *private_data)
{
	struct benchlock_state *state = (struct benchlock_state *)private_data;

	/* reestablish our open file */
	state->fnum = smbcli_open(state->tree, FNAME, O_RDWR|O_CREAT, DENY_NONE);
	if (state->fnum == -1) {
		printf("Failed to open %s on connection %d\n", FNAME, state->client_num);
		exit(1);
	}

	num_connected++;

	DEBUG(0,("reconnect to %s finished (%u connected)\n", state->dest_host,
		 num_connected));

	state->stage = LOCK_INITIAL;
	lock_send(state);
}
Пример #4
0
/*
  called when a lock completes
*/
static void lock_completion(struct smbcli_request *req)
{
	struct benchlock_state *state = (struct benchlock_state *)req->async.private_data;
	NTSTATUS status = smbcli_request_simple_recv(req);
	state->req = NULL;
	if (!NT_STATUS_IS_OK(status)) {
		if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) ||
		    NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) ||
		    NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
			talloc_free(state->tree);
			state->tree = NULL;
			num_connected--;	
			DEBUG(0,("reopening connection to %s\n", state->dest_host));
			talloc_free(state->te);
			state->te = event_add_timed(state->ev, state->mem_ctx, 
						    timeval_current_ofs(1,0), 
						    reopen_connection, state);
		} else {
			DEBUG(0,("Lock failed - %s\n", nt_errstr(status)));
			lock_failed++;
		}
		return;
	}

	switch (state->stage) {
	case LOCK_INITIAL:
		state->stage = LOCK_LOCK;
		break;
	case LOCK_LOCK:
		state->stage = LOCK_UNLOCK;
		break;
	case LOCK_UNLOCK:
		state->stage = LOCK_LOCK;
		break;
	}

	state->count++;
	lock_send(state);
}
Пример #5
0
/*===========================================================================*
 *				sys_task				     *
 *===========================================================================*/
PUBLIC void sys_task()
{
/* Main entry point of sys_task.  Get the message and dispatch on type. */
  static message m;
  register int result;
  register struct proc *caller_ptr;
  int s;
  int call_nr;
  int n = 0;

  /* Initialize the system task. */
  initialize();


  while (TRUE) {
      struct proc *restarting;

      restarting = vmrestart_check(&m);

      if(!restarting) {
        int r;
	/* Get work. Block and wait until a request message arrives. */
	if((r=receive(ANY, &m)) != OK)
		minix_panic("receive() failed", r);
      } 

      sys_call_code = (unsigned) m.m_type;
      call_nr = sys_call_code - KERNEL_CALL;	
      who_e = m.m_source;
      okendpt(who_e, &who_p);
      caller_ptr = proc_addr(who_p);

      /* See if the caller made a valid request and try to handle it. */
      if (call_nr < 0 || call_nr >= NR_SYS_CALLS) {	/* check call number */
	  kprintf("SYSTEM: illegal request %d from %d.\n",
		call_nr,m.m_source);
	  result = EBADREQUEST;			/* illegal message type */
      } 
      else if (!GET_BIT(priv(caller_ptr)->s_k_call_mask, call_nr)) {
	  result = ECALLDENIED;			/* illegal message type */
      }
      else {
          result = (*call_vec[call_nr])(&m); /* handle the system call */
      }

      if(result == VMSUSPEND) {
	/* Special case: message has to be saved for handling
	 * until VM tells us it's allowed. VM has been notified
	 * and we must wait for its reply to restart the call.
	 */
        vmassert(RTS_ISSET(caller_ptr, VMREQUEST));
	vmassert(caller_ptr->p_vmrequest.type == VMSTYPE_KERNELCALL);
	memcpy(&caller_ptr->p_vmrequest.saved.reqmsg, &m, sizeof(m));
      } else if (result != EDONTREPLY) {
	/* Send a reply, unless inhibited by a handler function.
	 * Use the kernel function lock_send() to prevent a system
	 * call trap.
	 */
		if(restarting) {
        		vmassert(!RTS_ISSET(restarting, VMREQUEST));
#if 0
        		vmassert(!RTS_ISSET(restarting, VMREQTARGET));
#endif
		}
		m.m_type = result;		/* report status of call */
		if(WILLRECEIVE(caller_ptr, SYSTEM)) {
		  if (OK != (s=lock_send(m.m_source, &m))) {
			kprintf("SYSTEM, reply to %d failed: %d\n",
			m.m_source, s);
		  }
		} else {
			kprintf("SYSTEM: not replying to %d; not ready\n", 
				caller_ptr->p_endpoint);
		}
	}
  }
}
Пример #6
0
/* 
   benchmark locking calls
*/
bool torture_bench_lock(struct torture_context *torture)
{
	bool ret = true;
	TALLOC_CTX *mem_ctx = talloc_new(torture);
	int i, j;
	int timelimit = torture_setting_int(torture, "timelimit", 10);
	struct timeval tv;
	struct benchlock_state *state;
	int total = 0, minops=0;
	struct smbcli_state *cli;
	bool progress;
	off_t offset;
	int initial_locks = torture_setting_int(torture, "initial_locks", 0);

	progress = torture_setting_bool(torture, "progress", true);

	nprocs = torture_setting_int(torture, "nprocs", 4);

	state = talloc_zero_array(mem_ctx, struct benchlock_state, nprocs);

	printf("Opening %d connections\n", nprocs);
	for (i=0;i<nprocs;i++) {
		state[i].tctx = torture;
		state[i].mem_ctx = talloc_new(state);
		state[i].client_num = i;
		state[i].ev = torture->ev;
		if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) {
			return false;
		}
		talloc_steal(mem_ctx, state);
		state[i].tree = cli->tree;
		state[i].dest_host = talloc_strdup(state[i].mem_ctx, 
						   cli->tree->session->transport->socket->hostname);
		state[i].dest_ports = talloc_array(state[i].mem_ctx, 
						   const char *, 2);
		state[i].dest_ports[0] = talloc_asprintf(state[i].dest_ports, 
							 "%u", 
							 cli->tree->session->transport->socket->port);
		state[i].dest_ports[1] = NULL;
		state[i].called_name  = talloc_strdup(state[i].mem_ctx,
						      cli->tree->session->transport->called.name);
		state[i].service_type = talloc_strdup(state[i].mem_ctx,
						      cli->tree->device);
	}

	num_connected = i;

	if (!torture_setup_dir(cli, BASEDIR)) {
		goto failed;
	}

	for (i=0;i<nprocs;i++) {
		state[i].fnum = smbcli_open(state[i].tree, 
					    FNAME, 
					    O_RDWR|O_CREAT, DENY_NONE);
		if (state[i].fnum == -1) {
			printf("Failed to open %s on connection %d\n", FNAME, i);
			goto failed;
		}

		/* Optionally, lock initial_locks for each proc beforehand. */
		if (i == 0 && initial_locks > 0) {
			printf("Initializing %d locks on each proc.\n",
			    initial_locks);
		}

		for (j = 0; j < initial_locks; j++) {
			offset = (0xFFFFFED8LLU * (i+2)) + j;
			if (!NT_STATUS_IS_OK(smbcli_lock64(state[i].tree,
			    state[i].fnum, offset, 1, 0, WRITE_LOCK))) {
				printf("Failed initializing, lock=%d\n", j);
				goto failed;
			}
		}

		state[i].stage = LOCK_INITIAL;
		lock_send(&state[i]);
	}

	tv = timeval_current();	

	if (progress) {
		event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state);
	}

	printf("Running for %d seconds\n", timelimit);
	while (timeval_elapsed(&tv) < timelimit) {
		event_loop_once(torture->ev);

		if (lock_failed) {
			DEBUG(0,("locking failed\n"));
			goto failed;
		}
	}

	printf("%.2f ops/second\n", total/timeval_elapsed(&tv));
	minops = state[0].count;
	for (i=0;i<nprocs;i++) {
		printf("[%d] %u ops\n", i, state[i].count);
		if (state[i].count < minops) minops = state[i].count;
	}
	if (minops < 0.5*total/nprocs) {
		printf("Failed: unbalanced locking\n");
		goto failed;
	}

	for (i=0;i<nprocs;i++) {
		talloc_free(state[i].req);
		smb_raw_exit(state[i].tree->session);
	}

	smbcli_deltree(state[0].tree, BASEDIR);
	talloc_free(mem_ctx);
	printf("\n");
	return ret;

failed:
	smbcli_deltree(state[0].tree, BASEDIR);
	talloc_free(mem_ctx);
	return false;
}