Exemplo n.º 1
0
int 
namei_release(struct file *filp,int force) {
  START(ftable,namei_rel);
#ifdef NAMEIDEBUG
  PRSHORTFILP("NAMEI_RELEASE:",filp,"");
  printf(" fr:%d\n",force);
#endif
#if 0
  if (filp == __current->root) {
    printf("Trying to release root filp\n");
    goto done;
  }
#endif
  /* ignore do not release for now */
  if (1 || !(filp->f_flags & O_DONOTRELEASE) || force) {
    if (CHECKOP(filp,release)) {
      DOOP(filp,release,(filp));
    }
  }
done:
  STOP(ftable,namei_rel);
  return 0;
}
Exemplo n.º 2
0
int 
namei_lookup(struct file *old_filp, char *name, struct file *new_filp) {
  struct file *filp = NULL;
  static int malloc_count = 0;
  static int mesg = 1;
  int error;

  START(namei,lookup);
  namei_lookup_count++;

  if (namei_cache_lookup(old_filp,name,&filp)) {
    *new_filp = *filp;
  } else {
    /* miss */
    error = DOOP(old_filp,lookup,(old_filp,name,new_filp));
    if (error) {
//      NAMEI_RELEASE(old_filp,&release);
#ifdef NAMEIDEBUG
      printf("LOOKUP old_filp %s failed errno: %s\n",next,strerror(errno));
#endif
      STOP(namei,lookup);
      return -1;
    }
    if (mesg) filp = (struct file *)__malloc(sizeof (struct file));
    if (filp == 0 && mesg) {
      kprintf("malloc failed (on try: %d\n",malloc_count);
      mesg = 0;
    } else {
      malloc_count++;
      *filp = *new_filp;
      namei_cache_add(old_filp,name,filp);
    }
  }
  STOP(namei,lookup);
  return 0;
}
Exemplo n.º 3
0
/* lookups of dots are passed down */
static int 
do_namei(struct file *cwd, 
	 const char *path, struct file *result_filp, char *result_name,
	 int *followlinks, int followlastlink)
{
    int error;
    char next[NAME_MAX +1];
    struct file old_space, new_space,tmp_traversal_space;
    struct file *old_filp = &old_space;
    struct file *new_filp = &new_space;
    struct file *tmp_traversal_filp = &tmp_traversal_space;
    struct file *tmp_swap_filp;
    struct shortfile release = {0,0};

    old_filp->flock_state = FLOCK_STATE_UNLOCKED;
    new_filp->flock_state = FLOCK_STATE_UNLOCKED;
    tmp_traversal_filp->flock_state = FLOCK_STATE_UNLOCKED;

    DPRINTF(SYSHELP_LEVEL,("do_namei: path: %s fl: %d fll: %d\n",path,*followlinks,followlastlink));

    nprintf("do_namei: path: \"%s\" fl: %d fll: %d\n",
	    path,*followlinks,followlastlink);

    /* If we have followed too many symlinks, error ELOOP */
    if (*followlinks > LINK_MAX) {
      errno = ELOOP;
      return -1;
    }

    ASSERTOP(cwd,lookup, directory with no lookup);

    *old_filp = *cwd;
    COUNT_COPY;
    ACQUIRE(old_filp);

    /* old_filp contains the directory we start at, and
     * new_filp will contain the name we just traversed.
     * when we return to top of loop, we copy new_filp into old_filp 
     * when we exit the loop, the resulting filp will be in new_filp */
    
    while(*path) {
      nprintf("path before : \"%s\" \n",path); 
      path = getNextComponent(path,next);

      nprintf("NEXT: \"%s\" path[0]: %d \n",next,*path);
      /* printf("path: \"%20s\"     next: \"%s\"\n",path,next); */
      
      if (EQDOTDOT(next)) {
	/* check traversal of /.. */
	if (FILPEQ(old_filp,__current->root)) {
	  next[1] = (char)0;	/* make it . */
	} 
	else 
	/* check traversal of /mnt/.. takes you back to / */
	  if (mounttraversalb(old_filp,&tmp_traversal_filp) == 0) {
	    RELEASE(old_filp);
	    COUNT_COPY;
	    *old_filp = *tmp_traversal_filp;
	    ACQUIRE(old_filp);
	    PRSHORTFILP("NEW POINT",old_filp,"\n");
	    /* fall through, old_filp points to /mnt, and next is ..
	     * so the later operations will handle the lookup of .. */
	  }
      }

      if (EQDOT(next)) {
	nprintf("in namei shortcircuiting . path: \"%s\"\n",path);
      	tmp_swap_filp = old_filp;
	old_filp = new_filp;
	new_filp = tmp_swap_filp;
	goto check_forward_mount;
      }

      if (!(S_ISDIR(old_filp->f_mode))) {
	nprintf("old_filp: ENOTDIR\n");
	errno = ENOTDIR;
	RELEASE(old_filp);
	return -1;
      }

      ASSERTOP(old_filp,lookup,no lookup operation in traversal of a path);
      
#ifdef CACHEDLOOKUP
      error = namei_lookup(old_filp, next, new_filp);
#else
      /* Do the actual lookup */
      nprintf("#OLD0: %s %d %08x\n",next,old_filp->f_ino, old_filp->f_mode);
      error = DOOP(old_filp,lookup,(old_filp,next,new_filp));
      nprintf("#OLD1: %s %d %08x\n",next,old_filp->f_ino, old_filp->f_mode);
#endif /* namei_lookup */

      if (error) {
	RELEASE(old_filp);
	nprintf("LOOKUP old_filp %s failed errno: %s\n",next,strerror(errno));
	return -1;
      }

      PRSHORTFILP("LOOKUP     ",old_filp," ");
      nprintf("#NAME: %p %s %d %08x\n",new_filp,next,new_filp->f_ino, new_filp->f_mode);
      nprintf("#OLD2: %p %s %d %08x\n",old_filp,next,old_filp->f_ino, old_filp->f_mode);
      PRSHORTFILP("  RETURNED:",new_filp,"\n");

      /* here you want to check if new_filp is a symbolic link, it is
	 you want to call readlink, then return namei on the new path we
	 got from readlink.  followlink will be an integer denoting how
	 many links we have followed. if 0 means we dont follow links. */
      
      if (S_ISLNK(new_filp->f_mode)) {
	char linkpath[PATH_MAX + 1];
	struct file *link_filp;
	nprintf("%d) SYMLINK new_filp %d is symlink remaining path: \"%s\" fll %d\n",
	       *followlinks,new_filp->f_ino,path,followlastlink);
	/* if this is the last path element, and we dont followlastlink */
	if (*path == 0 && followlastlink == 0) {
	  RELEASE(old_filp);
	  break;
	}

	ASSERTOP(new_filp,readlink,no readlink on a symlink filp);
	
	nprintf("3#NAME: %p %s %d %08x\n",new_filp,next,new_filp->f_ino, new_filp->f_mode);
	if ((error = DOOP(new_filp,readlink,(new_filp,linkpath,PATH_MAX))) == -1) {
	  RELEASE(old_filp);
	  RELEASE(new_filp);
	  return -1;
	}
	if (error >= 0) linkpath[error] = 0;

	nprintf("5#NAME: %p %s %d %08x\n",new_filp,next,new_filp->f_ino, new_filp->f_mode);
	RELEASE(new_filp);
	nprintf("6#NAME: %p %s %d %08x\n",new_filp,next,new_filp->f_ino, new_filp->f_mode);

	nprintf("%d) following symlink path: %s\n",*followlinks,linkpath);

	/* since new_filp is a symlink it could only have come from
	   a lookup */
	(*followlinks)++;

	if (linkpath[0] == '/') link_filp = (__current->root); 
	else link_filp = old_filp;


	error = do_namei(link_filp,
			 linkpath,
			 new_filp, 
			 result_name,
			 followlinks,
			 followlastlink);
	
	RELEASE(old_filp);

	nprintf("%d) error: %d PATH LEFT: %s, from %d, %x\n",
		*followlinks,error,path,new_filp->f_ino, new_filp->f_mode);
	if (error) {
	  nprintf("DO_NAMEI failed errno: %s\n",strerror(errno));
	  return -1;
	}


	goto next;
	//return error;
      } 

      RELEASE(old_filp);
    check_forward_mount:
      if (mounttraversalf(new_filp,&tmp_traversal_filp) == 0) {
	nprintf("traversing mount point ->, remaining: \"%s\"\n",path);
	RELEASE(new_filp);
	COUNT_COPY;
	*new_filp = *tmp_traversal_filp;
	ACQUIRE(new_filp);
#ifdef NAMEIDEBUG
	PRSHORTFILP("NEW POINT",new_filp,"\n");
#endif
	next[0] = '.'; next[1] = 0;
      }
    next:
      if (*path) {
	/* efficient way of doing: *old_filp = *new_filp, */
	tmp_swap_filp = old_filp;
	old_filp = new_filp;
	new_filp = tmp_swap_filp;
      }
    }
    
#ifdef NAMEIDEBUG
    nprintf("#LAST NAME: %s %d %08x\n",next,new_filp->f_ino, new_filp->f_mode);
#endif
    COUNT_COPY;
    *result_filp = *new_filp;
    if (result_name) {
      strcpy(result_name,next);
    }
    return 0;
}
Exemplo n.º 4
0
int
select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
	   struct timeval *timeout)
{
  unsigned int wait_ticks = 0;  
  int fd;
#define WK_SELECT_SZ 1024
  struct wk_term t[WK_SELECT_SZ];  
  int next;
  int total = 0;
  fd_set newreadfds, newwritefds, newexceptfds;
#define DID_FDREADY 1		
#define DID_TIMEOUT 2
#define DID_SIGNAL 3
  struct file *filp;
  int had_prev_term;

  OSCALLENTER(OSCALL_select);
  width = MIN (width+1, NR_OPEN);

  /* make sure that all fd's set to be polled are valid fd's */

  for (fd = 0; fd < width; fd++) {
    if ((readfds && FD_ISSET (fd, readfds)) || 
	(writefds && FD_ISSET (fd, writefds)) ||
	(exceptfds && FD_ISSET (fd, exceptfds))) {
      CHECKFD(fd, OSCALL_select);
      assert (CHECKOP (__current->fd[fd], select));
      assert (CHECKOP (__current->fd[fd], select_pred));
    }
  }

  FD_ZERO(&newreadfds);
  FD_ZERO(&newwritefds);
  FD_ZERO(&newexceptfds);

  /* Our basic algorithm is poll the fd's once. If any fd's are found
     ready return. Otherwise sleep until one of them might be ready
     and repeat the process. In practice we don't expect to go
     through this loop more than once, but theoretically we could
     wakeup for some reason other than haveing fd's ready. Am I just
     being paranoid? */

  /* Note: we can _definitely_ go thru this loop more than once, because
     in some cases (e.g., TCP), we can only sleep on an "indication" that
     select might pass (e.g., a packet arrived).  We have to then call
     select to find out if it does in fact make the socket ready, and rebuild
     the sleep predicate otherwise. */

  do {

    had_prev_term = 0;

    /* do a poll on the fd's. We want to make sure that we do this
       before sleeping so on the first time through the do loop we
       avoid descheduling and having to wait till we're re-scheduled
       before noticing that there're fd's ready. */

    for (fd = 0; fd < width; fd++) {
      if (readfds && FD_ISSET (fd, readfds))
	if (DOOP (__current->fd[fd], select, (__current->fd[fd], SELECT_READ))) {
	  total++;
	  FD_SET (fd, &newreadfds);
	}
      if (writefds && FD_ISSET (fd, writefds))
	if (DOOP (__current->fd[fd], select, (__current->fd[fd], SELECT_WRITE))) {
	  total++;
	  FD_SET (fd, &newwritefds);
	}	
      if (SELECT_EXCEPT_CONDITIONS && exceptfds && FD_ISSET (fd, exceptfds))
	if (DOOP (__current->fd[fd], select, (__current->fd[fd], SELECT_EXCEPT))) {
	  total++;
	  FD_SET (fd, &newexceptfds);
	}	
    }

    /* ok, we found some fd's that we need to report. Replace the
       fdsets the user passed in with fdsets containing which
       fd's are ready and return the total number of fd's ready. */

    if (total) {
      if (readfds)
	copyfds (readfds, &newreadfds, width);
      if (writefds)
	copyfds (writefds, &newwritefds, width);
      if (exceptfds)
	copyfds (exceptfds, &newexceptfds, width);
      /* XXX */
      OSCALLEXIT(OSCALL_select);
      return total;
    }

    /* if the user is just polling, handle that now before going through
       all the work to construct a predicate */

    if (timeout) {
      wait_ticks = ((1000000/RATE) * timeout->tv_sec) +
	(timeout->tv_usec + RATE - 1)/RATE;
      if (!wait_ticks)
	{
	  if (readfds) FD_ZERO(readfds);
	  if (writefds) FD_ZERO(writefds);
	  if (exceptfds) FD_ZERO(exceptfds);
	  OSCALLEXIT(OSCALL_select);
	  return 0;
	}
    }

    /* now construct a wakeup-predicate that will wake us when something
       interesting happens on these fd's. We call each fd's select_pred
       operation which returns a clause of the final predicate. All
       clauses are combined into one large predicate that we'll sleep on. */

    next = 0;
    had_prev_term = 0;
    next = wk_mktag (next, t, DID_FDREADY);
    for (fd = 0; fd < width; fd++) {
      filp = __current->fd[fd];
      if (readfds && FD_ISSET (fd, readfds)) {
	if (had_prev_term)
	  next = wk_mkop (next, t, WK_OR);	
	next += DOOP (filp,select_pred,(filp,SELECT_READ,&t[next]));
	had_prev_term = 1;
      }
	  
      if (writefds && FD_ISSET (fd, writefds)) {
	if (had_prev_term)
	  next = wk_mkop (next, t, WK_OR);	
	next += DOOP (filp,select_pred,(filp,SELECT_WRITE,&t[next]));	
	had_prev_term = 1;
      }

      if (SELECT_EXCEPT_CONDITIONS && exceptfds && FD_ISSET (fd, exceptfds)) {
	if (had_prev_term)
	  next = wk_mkop (next, t, WK_OR);	
	next += DOOP (filp,select_pred,(filp,SELECT_EXCEPT,&t[next]));	
	had_prev_term = 1;
      }
    }
    /* slap on a final term to wake us when the timeout occurrs, if there
       is one */

    if (timeout) {
      if (had_prev_term)
	next = wk_mkop (next, t, WK_OR);
      next = wk_mktag (next, t, DID_TIMEOUT);
      next += wk_mksleep_pred (&t[next], wait_ticks + __sysinfo.si_system_ticks);
      had_prev_term = 1;
    }

    /* we need to wakeup if a signal comes in */
    if (had_prev_term) {
       next = wk_mkop (next, t, WK_OR);
    }
    next = wk_mktag (next, t, DID_SIGNAL);
    next += wk_mksig_pred (&t[next]);
    had_prev_term = 1;
    
    /* wait for predicate to evaluate to true */
    wk_waitfor_pred (t, next);

    /* u_pred_tag is set to the piece of the predicate that caused
       us to wake up */

    if (UAREA.u_pred_tag == DID_TIMEOUT) {
      if (readfds) FD_ZERO(readfds);
      if (writefds) FD_ZERO(writefds);
      if (exceptfds) FD_ZERO(exceptfds);
      OSCALLEXIT(OSCALL_select);
      return 0;
    }
    if (UAREA.u_pred_tag == DID_SIGNAL) {
      //kprintf("%d select interrupted by signal\n",getpid());
      errno = EINTR;
      OSCALLEXIT(OSCALL_select);
      return -1;
    }
  
  } while (1);
}
Exemplo n.º 5
0
int 
old_select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
       struct timeval *timeout)
{
  int fd;
  fd_set newreadfds, newwritefds, newexceptfds;
  unsigned int wait_ticks = 0;
  unsigned int t,s;
  int total = 0;
  struct file *filp;
  int error;
  int traversed = 0;
  DPRINTF(SYS_LEVEL,("select: entering, timeout %d\n",
		     (timeout != NULL) ? (int) timeout->tv_sec : 0));

  if (timeout != NULL) {
	DPRINTF(SYS_LEVEL,
		("setting waiting time: sec: %d, usec: %d\n",
		 (int) timeout->tv_sec, (int)timeout->tv_usec));
	wait_ticks = ((1000000/RATE) * timeout->tv_sec)
	  + timeout->tv_usec/RATE;
  }
  
  FD_ZERO(&newreadfds);
  FD_ZERO(&newwritefds);
  FD_ZERO(&newexceptfds);

  t = TICKS;
  width = MIN(width,NR_OPEN);
  do {
    DPRINTF(SYS_LEVEL,("polling: %d ticks\n",wait_ticks));
    for (fd = 0; fd <= width; fd++) {
      /* maybe should be using min(width,fdtable_max) */
      /*	DPRINTF(SYS_LEVEL,("testing fd.%d\n",fd));*/
      
      if ((readfds  && FD_ISSET(fd,readfds))) {
	if (!traversed) {
	  CHECKFD(fd);
	}
	filp = __current->fd[fd];
	error = CHECKOP(filp,select);
	assert(error);
	error = DOOP(filp,select,(filp,SELECT_READ));
	if (error) {FD_SET(fd,&newreadfds); total++;}
      }
      if ((writefds  && FD_ISSET(fd,writefds))) {
	if (!traversed) {
	  CHECKFD(fd);
	}
	filp = __current->fd[fd];
	error = CHECKOP(filp,select);
	assert(error);
	error = DOOP(filp,select,(filp,SELECT_WRITE));
	if (error) {FD_SET(fd,&newwritefds); total++;}
      }
    }
    traversed++;

    s = TICKS;
    
    if (total > 0) {
      if (readfds) copyfds(readfds,&newreadfds,width);
      if (writefds) copyfds(writefds,&newwritefds,width);
      return(total);
    }

    usleep(100000);
    
  } while(s < t + wait_ticks || timeout == NULL);
  return(total);
}
Exemplo n.º 6
0
/* read select for a single filp with timeout.  More efficient than
   using general select */
int
__select_single_filp(struct file *filp, struct timeval *timeout)
{
  unsigned long long wait_ticks = 0;  
  unsigned long long wait_until = 0;  
  unsigned int begin_ticks = 0;  

#define WK_SELECT_SZ 1024
  struct wk_term t[WK_SELECT_SZ];  
  int next;
#define DID_FDREADY 1		
#define DID_TIMEOUT 2
#define DID_SIGNAL 3
  assert(RATE);
  assert(filp->op_type == UDP_SOCKET_TYPE);
  /* Our basic algorithm is poll the fd's once. If any fd's are found
     ready return. Otherwise sleep until one of them might be ready
     and repeat the process. In practice we don't expect to go
     through this loop more than once, but theoretically we could
     wakeup for some reason other than haveing fd's ready. Am I just
     being paranoid? */

  /* Note: we can _definitely_ go thru this loop more than once, because
     in some cases (e.g., TCP), we can only sleep on an "indication" that
     select might pass (e.g., a packet arrived).  We have to then call
     select to find out if it does in fact make the socket ready, and rebuild
     the sleep predicate otherwise. */

    /* do a poll on the fd's. We want to make sure that we do this
       before sleeping so on the first time through the do loop we
       avoid descheduling and having to wait till we're re-scheduled
       before noticing that there're fd's ready. */

  for(;;) {
    if (DOOP (filp, select, (filp, SELECT_READ))) {
      //kprintf("& %d",(int)__sysinfo.si_system_ticks);
      return 1;
    }
    
    /* if the user is just polling, handle that now before going through
     all the work to construct a predicate */
    
    if (timeout) {
      wait_ticks = ((1000000/RATE) * timeout->tv_sec) + timeout->tv_usec/RATE;
      if (!wait_ticks) {
//	kprintf("%");

	return 0;
      }
    }
    
    /* now construct a wakeup-predicate that will wake us when something
       interesting happens on these fd's. We call each fd's select_pred
       operation which returns a clause of the final predicate. All
       clauses are combined into one large predicate that we'll sleep on. */
    
    next = 0;
    next = wk_mktag (next, t, DID_FDREADY);
    
    next += DOOP (filp,select_pred,(filp,SELECT_READ,&t[next]));
    
    /* slap on a final term to wake us when the timeout occurrs, if there
       is one */

    begin_ticks = (int)__sysinfo.si_system_ticks;
    wait_until = wait_ticks + __sysinfo.si_system_ticks;
    if (timeout) {
      next = wk_mkop (next, t, WK_OR);
      next = wk_mktag (next, t, DID_TIMEOUT);
      next += wk_mksleep_pred (&t[next], wait_until);
    }

	/* we need to wakup if a signal comes in */
    next = wk_mkop (next, t, WK_OR);
    next = wk_mktag (next, t, DID_SIGNAL);
    next += wk_mksig_pred (&t[next]);

	/* wait for predicate to evaluate to true */
    wk_waitfor_pred (t, next);
    
    /* u_pred_tag is set to the piece of the predicate that caused
       us to wake up */
    
    if (UAREA.u_pred_tag == DID_TIMEOUT) {
//#if 0
      kprintf("timeout wt %d rate %d\n",
	      (int)wait_ticks,(unsigned int)(RATE));
      kprintf("Timeout sec: %ld usec: %ld\n",timeout->tv_sec,timeout->tv_usec);
      kprintf("begin ticks: %d sleep until ticks: %d si_system_ticks: %d\n",
	      begin_ticks,(int)wait_until,(int)__sysinfo.si_system_ticks);
//#endif
      return 0;
    }

  } 
}