Beispiel #1
0
/*
 * Mount the file system.  Obtain the root inode and send back its details.
 */
int
fs_mount(dev_t __unused dev, unsigned int flags,
         struct fsdriver_node * root_node, unsigned int * res_flags)
{
    struct inode *root;

    /* VTreeFS must not be mounted as a root file system. */
    if (flags & REQ_ISROOT)
        return EINVAL;

    /* Get the root inode and increase its reference count. */
    root = get_root_inode();
    ref_inode(root);

    /* The system is now mounted.  Call the initialization hook. */
    if (vtreefs_hooks->init_hook != NULL)
        vtreefs_hooks->init_hook();

    /* Return the root inode's properties. */
    root_node->fn_ino_nr = get_inode_number(root);
    root_node->fn_mode = root->i_stat.mode;
    root_node->fn_size = root->i_stat.size;
    root_node->fn_uid = root->i_stat.uid;
    root_node->fn_gid = root->i_stat.gid;
    root_node->fn_dev = NO_DEV;

    *res_flags = RES_NOFLAGS;

    return OK;
}
Beispiel #2
0
/*
 * Return whether the given node is a PID directory.
 */
static int
dir_is_pid(struct inode *node)
{

	return (get_parent_inode(node) == get_root_inode() &&
	    get_inode_index(node) != NO_INDEX);
}
Beispiel #3
0
/* Returns the inode of the directory based on the date of RSS entry (pubDate). 
   If it does not have a pubDate atribute, it will return the inode of the directory with name "no_pubDate". */
struct inode *get_inode_by_date (char *pubDate) {
  struct inode *result;
  struct inode *temp;
  struct inode_stat dir_stat;
  char month[4];
  char year[5];

  // Setting the variables of the struct in order to create a new directory.
  dir_stat.mode = S_IFDIR;
  dir_stat.uid = 0;
  dir_stat.gid = 0;
  dir_stat.size = 0;
  dir_stat.dev = NO_DEV;

  if (strcmp (pubDate, "") == 0){
    // The RSS entry does not have an attribute called pubDate.
    result = get_inode_by_name(get_root_inode(), "no_pubDate");
    if (result == 0){
      result = add_inode(get_root_inode(), "no_pubDate", NO_INDEX, &dir_stat, 0, 0);
    }
  } else {
    // Extract the month from pubDate.
    strncpy(month, pubDate+8, 3);
    // Setting the end of the string.
    month[3] = 0;
    // Extract the year from pubDate.
    strncpy(year, pubDate+12, 4);
    year[4] = 0;

    temp = get_inode_by_name(get_root_inode(), year);

    if (temp == 0){
      // Make a new directory.
      temp = add_inode(get_root_inode(), year, NO_INDEX, &dir_stat, 0, 0);
      result = add_inode(temp, month, NO_INDEX, &dir_stat, 0, 0);
    } else {
      // The directory already exists.
      result = get_inode_by_name(temp, month);
      if (result == 0){
        // Make a new subdirectory.
        result = add_inode(temp, month, NO_INDEX, &dir_stat, 0, 0);
      }
    }
  }

  return result;
}
Beispiel #4
0
static int fuse_fill_super(struct super_block *sb, void *data, int silent)
{
	struct fuse_conn *fc;
	struct inode *root;
	struct fuse_mount_data d;
	struct file *file;
	int err;

	if (!parse_fuse_opt((char *) data, &d))
		return -EINVAL;

	sb->s_blocksize = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
	sb->s_magic = FUSE_SUPER_MAGIC;
	sb->s_op = &fuse_super_operations;
	sb->s_maxbytes = MAX_LFS_FILESIZE;
#ifndef FUSE_MAINLINE
#ifdef KERNEL_2_6
	sb->s_export_op = &fuse_export_operations;
#endif
#endif

	file = fget(d.fd);
	if (!file)
		return -EINVAL;

	fc = get_conn(file, sb);
	fput(file);
	if (IS_ERR(fc))
		return PTR_ERR(fc);

	fc->flags = d.flags;
	fc->user_id = d.user_id;
	fc->group_id = d.group_id;
	fc->max_read = d.max_read;
#ifdef KERNEL_2_6
	if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
		fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
#endif

	err = -ENOMEM;
	root = get_root_inode(sb, d.rootmode);
	if (root == NULL)
		goto err;

	sb->s_root = d_alloc_root(root);
	if (!sb->s_root) {
		iput(root);
		goto err;
	}
	fuse_send_init(fc);
	return 0;

 err:
	spin_lock(&fuse_lock);
	fuse_release_conn(fc);
	spin_unlock(&fuse_lock);
	return err;
}
Beispiel #5
0
/*===========================================================================*
 *				dir_is_pid				     *
 *===========================================================================*/
static int dir_is_pid(struct inode *node)
{
	/* Return whether the given node is a PID directory.
	 */

	return (get_parent_inode(node) == get_root_inode() &&
		get_inode_index(node) != NO_INDEX);
}
Beispiel #6
0
////分配一个未使用的任务结构
//返回:未使用的任务结构
struct TASK *task_alloc(void)
{
	int i;
	struct TASK *task = NULL;
	for (i = 0; i < MAX_TASKS; i++) {
		if (taskctl->tasks0[i].flags == 0) {
			task = &taskctl->tasks0[i];
			task->signal = 0;
			task->pid = get_new_pid();
			task->nr = i;
			debug("alloc pid = %d",task->pid);
			task->flags = 1; /* 正在使用的标志 */
			task->tss.eflags = 0x00000202; /* IF = 1; */
			task->tss.eax = 0; /* 这里先设置为0 */
			task->tss.ecx = 0;
			task->tss.edx = 0;
			task->tss.ebx = 0;
			task->tss.ebp = 0;
			task->tss.esi = 0;
			task->tss.edi = 0;
			task->tss.es = 0;
			task->tss.ds = 0;
			task->tss.fs = 0;
			task->tss.gs = 0;
			task->tss.cr3 =   PAGE_DIR_ADDR;
			task->tss.iomap = 0x40000000;
			task->tss.ss0 = 0;
			task->forked = 0; //重置是否是fork创建的标志
			task->exit_status = -1000;
			
			task->pwd = get_root_inode();
			task->root = get_root_inode();
			
			task->readKeyboard = 0;
			
			/* 打开标准文件:STDIN, STDOUT, STDERR */
			open_std_files(task);
			
			return task;
		}
	}
	return 0; /* 全部正在使用 */
}
Beispiel #7
0
/*
 * Unmount the file system.
 */
void
fs_unmount(void)
{
    struct inode *root;

    /* Decrease the count of the root inode. */
    root = get_root_inode();

    put_inode(root);

    /* The system is unmounted.  Call the cleanup hook. */
    if (vtreefs_hooks->cleanup_hook != NULL)
        vtreefs_hooks->cleanup_hook();
}
Beispiel #8
0
/*===========================================================================*
 *				init_hook				     *
 *===========================================================================*/
static void init_hook(void)
{
	/* Initialization hook. Generate the static part of the tree.
	 */
	static int first_time = 1;
	struct inode *root;

	if (first_time) {
		root = get_root_inode();

		construct_tree(root, root_files);

		first_time = 0;
	}
}
Beispiel #9
0
/*===========================================================================*
 *				getdents_hook				     *
 *===========================================================================*/
int getdents_hook(struct inode *node, cbdata_t UNUSED(cbdata))
{
	/* Directory entry retrieval hook, for potentially all files in a
	 * directory. Make sure that all files that are supposed to be
	 * returned, are actually part of the virtual tree.
	 */

	if (node == get_root_inode()) {
		update_tables();

		construct_pid_dirs();
	} else if (dir_is_pid(node)) {
		construct_pid_entries(node, NULL /*name*/);
	}

	return OK;
}
Beispiel #10
0
Datei: lfs.c Projekt: kitalda/lfs
/** Get file attributes.
 *
 * Gets file attributes and saves them in the stbuff
 * struct.
 */
int lfs_getattr(const char *path, struct stat *stbuf) {
	int res = 0;
	struct inode* node;
	printf("getattr: (path=%s)\n", path);

	memset(stbuf, 0, sizeof(struct stat));
	if (strncmp(path, "/.Trash", 7) == 0) {
		//TODO what to do here?
		return 0;
	}
	node = malloc(INODE_SIZE);
	if (!node) {
		perror("lfs_getattr, malloc");
		res = -ENOMEM;
	} else {
		if (strcmp(path, "/") == 0) {
			res = get_root_inode(log_system, node);
			if (!res) {
				stbuf->st_mode = S_IFDIR | 0755;
				stbuf->st_nlink = 2 + node->number_of_children;
			}
		} else {
			res = get_inode_from_path(log_system, path, node);
			if (res) {
				perror("lfs_getattr, get_inode_from_path");
				printf("getattr: get inode from path returned %d\n", res);
				res = -ENOENT;
			} else {
				if (node->is_dir) {
					stbuf->st_mode = S_IFDIR | 0755;
				} else {
					stbuf->st_mode = S_IFREG | 0777;
				}
				stbuf->st_nlink = 1;
			}
		}
		if (!res) {
			stbuf->st_size = node->file_size;
			stbuf->st_ino = node->inode_number;
			stbuf->st_blksize = BLOCK_SIZE;
		}
	}
	free(node);
	printf("get_attr done\n");
	return res;
}
Beispiel #11
0
static struct super_block *fuse_read_super(struct super_block *sb,
					   void *data, int silent)
{
	struct fuse_conn *fc;
	struct inode *root;
	struct fuse_mount_data *d = data;

        sb->s_blocksize = pageSize;
        sb->s_blocksize_bits = pageSizeBits;
        sb->s_magic = FUSE_SUPER_MAGIC;
        sb->s_op = &fuse_super_operations;

	root = get_root_inode(sb, d->rootmode);
	if(root == NULL) {
		printk("fuse_read_super: failed to get root inode\n");
		return NULL;
	}

	spin_lock(&fuse_lock);
	fc = get_conn(d);
	if(fc == NULL)
		goto err;

	if(fc->sb != NULL) {
		printk("fuse_read_super: connection already mounted\n");
		goto err;
	}

        sb->u.generic_sbp = fc;
	sb->s_root = d_alloc_root(root);
	if(!sb->s_root)
		goto err;

	fc->sb = sb;
	fc->flags = d->flags;
	fc->uid = d->uid;
	spin_unlock(&fuse_lock);

	return sb;

  err:
	spin_unlock(&fuse_lock);
	iput(root);
	return NULL;
}
Beispiel #12
0
/*===========================================================================*
 *				lookup_hook				     *
 *===========================================================================*/
int lookup_hook(struct inode *parent, char *name,
	cbdata_t UNUSED(cbdata))
{
	/* Path name resolution hook, for a specific parent and name pair.
	 * If needed, update our own view of the system first; after that,
	 * determine whether we need to (re)generate certain files.
	 */
	static clock_t last_update = 0;
	clock_t now;
	int r;

	/* Update lazily for lookups, as this gets too expensive otherwise.
	 * Alternative: pull in only PM's table?
	 */
	if ((r = getticks(&now)) != OK)
		panic(__FILE__, "unable to get uptime", r);

	if (last_update != now) {
		update_tables();

		last_update = now;
	}

	/* If the parent is the root directory, we must now reconstruct all
	 * entries, because some of them might have been garbage collected.
	 * We must update the entire tree at once; if we update individual
	 * entries, we risk name collisions.
	 */
	if (parent == get_root_inode()) {
		construct_pid_dirs();
	}
	/* If the parent is a process directory, we may need to (re)construct
	 * the entry being looked up.
	 */
	else if (dir_is_pid(parent)) {
		/* We might now have deleted our current containing directory;
		 * construct_pid_entries() will take care of this case.
		 */
		construct_pid_entries(parent, name);
	}

	return OK;
}
Beispiel #13
0
/*===========================================================================*
 *				fs_unmount				     *
 *===========================================================================*/
int fs_unmount(void)
{
	/* Unmount the file system.
	 */
	struct inode *root;

	/* Decrease the count of the root inode. */
	root = get_root_inode();

	put_inode(root);

	/* The system is unmounted. Call the cleanup hook. */
	if (vtreefs_hooks->cleanup_hook != NULL)
		vtreefs_hooks->cleanup_hook();

	/* We can now be shut down safely. */
	fs_mounted = FALSE;

	return OK;
}
Beispiel #14
0
/*===========================================================================*
 *				fs_readsuper				     *
 *===========================================================================*/
int fs_readsuper(void)
{
	/* This function gets the root inode and sends back its details.
	 */
	struct inode *root;

	/* Get the device number, for stat requests. */
	fs_dev = fs_m_in.REQ_DEV;

	/* The VTreeFS must not be mounted as a root file system. */
	if (fs_m_in.REQ_FLAGS & REQ_ISROOT)
		return EINVAL;

	/* Get the root inode and increase its reference count. */
	root = get_root_inode();
	ref_inode(root);

	/* The system is now mounted. Call the initialization hook. */
	if (vtreefs_hooks->init_hook != NULL)
		vtreefs_hooks->init_hook();

	/* Return the root inode's properties. */
	fs_m_out.RES_INODE_NR = get_inode_number(root);
	fs_m_out.RES_MODE = root->i_stat.mode;
	fs_m_out.RES_FILE_SIZE_HI = 0;
	fs_m_out.RES_FILE_SIZE_LO = root->i_stat.size;
	fs_m_out.RES_UID = root->i_stat.uid;
	fs_m_out.RES_GID = root->i_stat.gid;
	fs_m_out.RES_DEV = NO_DEV;

	fs_m_out.RES_CONREQS = 1;/* We can handle only 1 request at a time */

	fs_mounted = TRUE;

	return OK;
}
Beispiel #15
0
static int fuse_fill_super(struct super_block *sb, void *data, int silent)
{
	struct fuse_conn *fc;
	struct inode *root;
	struct fuse_mount_data d;
	struct file *file;
	struct dentry *root_dentry;
	struct fuse_req *init_req;
	int err;
	int is_bdev = sb->s_bdev != NULL;

	if (sb->s_flags & MS_MANDLOCK)
		return -EINVAL;

	if (!parse_fuse_opt((char *) data, &d, is_bdev))
		return -EINVAL;

	if (is_bdev) {
#ifdef CONFIG_BLOCK
		if (!sb_set_blocksize(sb, d.blksize))
			return -EINVAL;
#endif
	} else {
		sb->s_blocksize = PAGE_CACHE_SIZE;
		sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
	}
	sb->s_magic = FUSE_SUPER_MAGIC;
	sb->s_op = &fuse_super_operations;
	sb->s_maxbytes = MAX_LFS_FILESIZE;
	sb->s_export_op = &fuse_export_operations;

	file = fget(d.fd);
	if (!file)
		return -EINVAL;

	if (file->f_op != &fuse_dev_operations)
		return -EINVAL;

	fc = new_conn(sb);
	if (!fc)
		return -ENOMEM;

	fc->flags = d.flags;
	fc->user_id = d.user_id;
	fc->group_id = d.group_id;
	fc->max_read = max_t(unsigned, 4096, d.max_read);

	/* Used by get_root_inode() */
	sb->s_fs_info = fc;

	err = -ENOMEM;
	root = get_root_inode(sb, d.rootmode);
	if (!root)
		goto err;

	root_dentry = d_alloc_root(root);
	if (!root_dentry) {
		iput(root);
		goto err;
	}

	init_req = fuse_request_alloc();
	if (!init_req)
		goto err_put_root;

	if (is_bdev) {
		fc->destroy_req = fuse_request_alloc();
		if (!fc->destroy_req)
			goto err_free_init_req;
	}

	mutex_lock(&fuse_mutex);
	err = -EINVAL;
	if (file->private_data)
		goto err_unlock;

	err = fuse_ctl_add_conn(fc);
	if (err)
		goto err_unlock;

	list_add_tail(&fc->entry, &fuse_conn_list);
	sb->s_root = root_dentry;
	fc->connected = 1;
	file->private_data = fuse_conn_get(fc);
	mutex_unlock(&fuse_mutex);
	/*
	 * atomic_dec_and_test() in fput() provides the necessary
	 * memory barrier for file->private_data to be visible on all
	 * CPUs after this
	 */
	fput(file);

	fuse_send_init(fc, init_req);

	return 0;

 err_unlock:
	mutex_unlock(&fuse_mutex);
 err_free_init_req:
	fuse_request_free(init_req);
 err_put_root:
	dput(root_dentry);
 err:
	fput(file);
	fuse_conn_put(fc);
	return err;
}
Beispiel #16
0
Datei: lfs.c Projekt: kitalda/lfs
int lfs_mkdir(const char *path, mode_t mode) {
	int res = 0;
	struct inode* node;
	struct inode* parent;
	char* name;

	printf("%s\n", "lfs_mkdir");

	node = malloc(INODE_SIZE);
	if (!node) {
		res = -ENOMEM;
	} else {
		if (get_inode_from_path(log_system, path, node) == 0) {
			free(node);
			printf("mkdir: dir exists\n");
			return -EEXIST;
		}
		name = malloc(FILE_NAME_LENGTH_MAX);
		if (!name) {
			res = -ENOMEM;
		} else {
			//printf("mkdir: 1\n");
			res = get_filename(path, name);
			if (!res) {
				//printf("mkdir: 2\n");
				parent = malloc(INODE_SIZE);
				if (!parent) {
					res = -ENOMEM;
				} else {
					//printf("mkdir: 3\n");
					res = get_root_inode(log_system, parent);
					if (!res) {
						//printf("mkdir: 4\n");
						char* temp = malloc(strlen(path));
						if (!temp) {
							res = -ENOMEM;
						} else {
							//printf("mkdir: 5\n");
							strcpy(temp, path);
							while ((strcmp(temp, name) != 0) && (strcmp(temp + 1, name) != 0)
									&& !res) {
								//printf("mkdir: temp now = %s\n", temp);
								res = traverse_path(log_system, temp, parent, node, temp);
								if (!res) {
									parent = node;
								}
							}
							if (!res) {
								printf("mkdir: 6\n");
								printf("mkdir: parent is %s\n", parent->file_name);
								node->inode_number = log_system->number_of_inodes
										+ INODE_NUMBERS_MIN;
								node->is_dir = 1;
								memcpy(node->file_name, name, strlen(name));
								node->number_of_blocks = 0;
								//printf("mkdir: child is %s\n", node->file_name);
								node->number_of_children = 0;
								node->file_size = strlen(name);
								memset(node->block_placements, 0, BLOCKS_PR_INODE);
								memset(node->blocks_changed, 0, BLOCKS_PR_INODE);
								//printf("mkdir: 9\n");
								res = add_child_to_dir(log_system, parent, node);
								//printf("mkdir: parent has %d children\n", parent->number_of_children);

							}
							free(temp);
						}
					}
				}
			}
			free(name);
		}
	}
	//printf("mkdir: returning %d\n", res);
	return res;
}
Beispiel #17
0
Datei: lfs.c Projekt: kitalda/lfs
/**
 * Helper function. Get folder or file at start of path.
 */
int get_inode_from_path(struct file_system* lfs, const char *path,
		struct inode* inode) {
	int res = 0;
	int found;
	char* curr_path;
	struct inode* node;
	char* file_name;

	printf("get_inode_from_path: path = %s\n", path);

	if (!inode) {
		inode = malloc(INODE_SIZE);
	}
	if (!inode) {
		return -ENOMEM;
	}
//printf("1\n");
	if (strcmp(path, "/") == 0) {
		res = get_root_inode(lfs, inode);
	} else {
		//printf("2\n");
		file_name = malloc(FILE_NAME_LENGTH_MAX);
		if (!file_name) {
			res = -ENOMEM;
		} else {
			printf("3\n");
			res = get_filename(path, file_name);
			if (!res) {
				//printf("get_inode_..: path = %s\n", path);
				//printf("get_inode_from path: file_name = %s\n", file_name);
				node = malloc(INODE_SIZE);
				if (!node) {
					res = -ENOMEM;
				} else {
					printf("4\n");
					res = get_root_inode(lfs, node);
					if (!res) {
						printf("5\n");
						curr_path = malloc(FILE_NAME_LENGTH_MAX * INODES_PR_LOG);
						if (!curr_path) {
							res = -ENOMEM;
						} else {
							printf("6\n");
							found = 0;
							memcpy(curr_path, path, strlen(path));
							printf("7\n");
							res = get_root_inode(lfs, node);
							printf("get_inode_from_path: root inode has %d children\n",
									node->number_of_children);
							while (!res && !found) {
								if (strcmp(node->file_name, file_name) == 0) {
									found = 1;
								} else {
									printf("curr_path = %s, path  = %s\n", curr_path, path);
									res = traverse_path(lfs, curr_path, node, node, curr_path);
									if (res == -ENOENT) {
										printf("get_inode_from_path: no node with path: %s\n",
												path);
									}
								}
							}
							if (found) {
								inode = node;
								res = 0;
							} else {
								res = -ENOENT;
							}
							free(curr_path);
						}
					}
					free(node);
				}
			}
			free(file_name);
		}
	}
//printf("get_inode_from_path: returns %d, inode number was: %d\n", res, node->inode_number);
	return res;
}
Beispiel #18
0
Datei: lfs.c Projekt: kitalda/lfs
/** Reads a directory */
int lfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
		off_t offset, struct fuse_file_info *fi) {
	struct inode* node;
	struct inode* child;
	unsigned int* block;
	int res = 0;
	//printf("readdir: (path=%s)\n", path);

	node = malloc(INODE_SIZE);
	if (!node) {
		res = -ENOMEM;
	} else {
		if (strcmp(path, "/") == 0) {
			res = get_root_inode(log_system, node);
			if (!res) {
				struct stat* stbuf = malloc(sizeof(struct stat));
				if (!stbuf) {
					res = -ENOMEM;
				} else {
					stbuf->st_ino = node->inode_number;
					stbuf->st_mode = S_IFDIR | 755;
					filler(buf, ".", stbuf, 0);
					filler(buf, "..", NULL, 0);
					free(stbuf);
				}
			}
		} else {
			res = get_inode_from_path(log_system, path, node);
			if (res) {
				return -ENOENT;
			} else {
				if (!node->is_dir) {
					////printf("Well, that explains it\n");
					res = -ENOTDIR;
				} else {
					////printf("readdir: 1\n");
					block = malloc(BLOCK_SIZE);
					if (!block) {
						res = -ENOMEM;
					} else {
						struct stat* stbuf = malloc(sizeof(struct stat));
						if (!stbuf) {
							res = -ENOMEM;
						} else {
							int i;
							////printf("readdir: 3\n");
							stbuf->st_ino = node->inode_number;
							stbuf->st_mode = S_IFDIR;
							filler(buf, ".", NULL, 0);
							filler(buf, "..", NULL, 0);
							for (i = 0; (i < node->number_of_children) && !res; i++) {
								////printf("readdir: 4,%d\n", i);
								child = malloc(INODE_SIZE);
								if (!child) {
									res = -ENOMEM;
								} else {
									res = read_inode(log_system, node->block_placements[i],
											child);
									stbuf->st_ino = child->inode_number;
									if (child->is_dir) {
										stbuf->st_mode = S_IFDIR | 755;
									} else {
										stbuf->st_mode = S_IFREG | 755;
									}
									filler(buf, child->file_name, stbuf, 0);
									free(child);
								}

							}
							free(stbuf);
						}

						free(block);
					}
				}
			}
		}
		free(node);
	}
	return res;
}
Beispiel #19
0
/*
 * Regenerate the set of PID directories in the root directory of the file
 * system.  Add new directories and delete old directories as appropriate;
 * leave unchanged those that should remain the same.
 */
static void
construct_pid_dirs(void)
{
	/*
	 * We have to make two passes.  Otherwise, we would trigger a vtreefs
	 * assert when we add an entry for a PID before deleting the previous
	 * entry for that PID.  While rare, such rapid PID reuse does occur in
	 * practice.
	 */
	struct inode *root, *node;
	struct inode_stat stat;
	char name[PNAME_MAX+1];
	pid_t pid;
	int i;

	root = get_root_inode();

	/* First pass: delete old entries. */
	for (i = 0; i < NR_PROCS + NR_TASKS; i++) {
		/* Do we already have an inode associated with this slot? */
		node = get_inode_by_index(root, i);
		if (node == NULL)
			continue;

		/*
		 * If the process slot is not in use, delete the associated
		 * inode.
		 */
		if (!slot_in_use(i)) {
			delete_inode(node);

			continue;
		}

		/* Otherwise, get the process ID. */
		if (i < NR_TASKS)
			pid = (pid_t)(i - NR_TASKS);
		else
			pid = mproc[i - NR_TASKS].mp_pid;

		/*
		 * If there is an old entry, see if the pid matches the current
		 * entry, and the owner is still the same.  Otherwise, delete
		 * the old entry first.  We reconstruct the entire subtree even
		 * if only the owner changed, for security reasons: if a
		 * process could keep open a file or directory across the owner
		 * change, it might be able to access information it shouldn't.
		 */
		if (pid != (pid_t)get_inode_cbdata(node) ||
		    !check_owner(node, i))
			delete_inode(node);
	}

	/* Second pass: add new entries. */
	for (i = 0; i < NR_PROCS + NR_TASKS; i++) {
		/* If the process slot is not in use, skip this slot. */
		if (!slot_in_use(i))
			continue;

		/*
		 * If we have an inode associated with this slot, we have
		 * already checked it to be up-to-date above.
		 */
		if (get_inode_by_index(root, i) != NULL)
			continue;

		/* Get the process ID. */
		if (i < NR_TASKS)
			pid = (pid_t)(i - NR_TASKS);
		else
			pid = mproc[i - NR_TASKS].mp_pid;

		/* Add the entry for the process slot. */
		snprintf(name, PNAME_MAX + 1, "%d", pid);

		make_stat(&stat, i, NO_INDEX);

		node = add_inode(root, name, i, &stat, nr_pid_entries,
		    (cbdata_t)pid);

		if (node == NULL)
			out_of_inodes();
	}
}