Module Name:    src
Committed By:   rmind
Date:           Tue May 24 01:09:48 UTC 2011

Modified Files:
        src/sys/fs/tmpfs: tmpfs_mem.c tmpfs_subr.c tmpfs_vfsops.c

Log Message:
- tmpfs_alloc_node/tmpfs_free_node: move inode limiting into tmpfs_node_get()
  and tmpfs_node_put(), update outdated/wrong comments and move/add asserts.
- tmpfs_mount: check for the version of arguments a bit earlier.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/fs/tmpfs/tmpfs_mem.c
cvs rdiff -u -r1.64 -r1.65 src/sys/fs/tmpfs/tmpfs_subr.c
cvs rdiff -u -r1.48 -r1.49 src/sys/fs/tmpfs/tmpfs_vfsops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/tmpfs/tmpfs_mem.c
diff -u src/sys/fs/tmpfs/tmpfs_mem.c:1.3 src/sys/fs/tmpfs/tmpfs_mem.c:1.4
--- src/sys/fs/tmpfs/tmpfs_mem.c:1.3	Thu May 19 03:21:23 2011
+++ src/sys/fs/tmpfs/tmpfs_mem.c	Tue May 24 01:09:47 2011
@@ -1,9 +1,12 @@
-/*	$NetBSD: tmpfs_mem.c,v 1.3 2011/05/19 03:21:23 rmind Exp $	*/
+/*	$NetBSD: tmpfs_mem.c,v 1.4 2011/05/24 01:09:47 rmind Exp $	*/
 
 /*
- * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Mindaugas Rasiukevicius.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -32,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_mem.c,v 1.3 2011/05/19 03:21:23 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_mem.c,v 1.4 2011/05/24 01:09:47 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -161,6 +164,10 @@
 tmpfs_node_get(struct tmpfs_mount *mp)
 {
 
+	if (atomic_inc_uint_nv(&mp->tm_nodes_cnt) >= mp->tm_nodes_max) {
+		atomic_dec_uint(&mp->tm_nodes_cnt);
+		return NULL;
+	}
 	if (!tmpfs_mem_incr(mp, sizeof(struct tmpfs_node))) {
 		return NULL;
 	}
@@ -171,6 +178,7 @@
 tmpfs_node_put(struct tmpfs_mount *mp, struct tmpfs_node *tn)
 {
 
+	atomic_dec_uint(&mp->tm_nodes_cnt);
 	tmpfs_mem_decr(mp, sizeof(struct tmpfs_node));
 	pool_put(&tmpfs_node_pool, tn);
 }

Index: src/sys/fs/tmpfs/tmpfs_subr.c
diff -u src/sys/fs/tmpfs/tmpfs_subr.c:1.64 src/sys/fs/tmpfs/tmpfs_subr.c:1.65
--- src/sys/fs/tmpfs/tmpfs_subr.c:1.64	Sun May 22 04:20:50 2011
+++ src/sys/fs/tmpfs/tmpfs_subr.c	Tue May 24 01:09:47 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_subr.c,v 1.64 2011/05/22 04:20:50 rmind Exp $	*/
+/*	$NetBSD: tmpfs_subr.c,v 1.65 2011/05/24 01:09:47 rmind Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.64 2011/05/22 04:20:50 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.65 2011/05/24 01:09:47 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -61,29 +61,9 @@
 #include <fs/tmpfs/tmpfs_specops.h>
 #include <fs/tmpfs/tmpfs_vnops.h>
 
-/* --------------------------------------------------------------------- */
-
 /*
- * Allocates a new node of type 'type' inside the 'tmp' mount point, with
- * its owner set to 'uid', its group to 'gid' and its mode set to 'mode',
- * using the credentials of the process 'p'.
- *
- * If the node type is set to 'VDIR', then the parent parameter must point
- * to the parent directory of the node being created.  It may only be NULL
- * while allocating the root node.
- *
- * If the node type is set to 'VBLK' or 'VCHR', then the rdev parameter
- * specifies the device the node represents.
- *
- * If the node type is set to 'VLNK', then the parameter target specifies
- * the file name of the target file for the symbolic link that is being
- * created.
- *
- * Note that new nodes are retrieved from the available list if it has
- * items or, if it is empty, from the node pool as long as there is enough
- * space to create them.
- *
- * Returns zero on success or an appropriate error code on failure.
+ * tmpfs_alloc_node: allocate a new inode of a specified type and
+ * insert it into the list of specified mount point.
  */
 int
 tmpfs_alloc_node(struct tmpfs_mount *tmp, enum vtype type,
@@ -92,24 +72,8 @@
 {
 	struct tmpfs_node *nnode;
 
-	/* If the root directory of the 'tmp' file system is not yet
-	 * allocated, this must be the request to do it. */
-	KASSERT(IMPLIES(tmp->tm_root == NULL, parent == NULL && type == VDIR));
-
-	KASSERT(IFF(type == VLNK, target != NULL));
-	KASSERT(IFF(type == VBLK || type == VCHR, rdev != VNOVAL));
-
-	KASSERT(uid != VNOVAL && gid != VNOVAL && mode != VNOVAL);
-
-	nnode = NULL;
-	if (atomic_inc_uint_nv(&tmp->tm_nodes_cnt) >= tmp->tm_nodes_max) {
-		atomic_dec_uint(&tmp->tm_nodes_cnt);
-		return ENOSPC;
-	}
-
 	nnode = tmpfs_node_get(tmp);
 	if (nnode == NULL) {
-		atomic_dec_uint(&tmp->tm_nodes_cnt);
 		return ENOSPC;
 	}
 
@@ -127,26 +91,35 @@
 	nnode->tn_status = 0;
 	nnode->tn_flags = 0;
 	nnode->tn_links = 0;
+	nnode->tn_lockf = NULL;
+	nnode->tn_vnode = NULL;
 
 	vfs_timestamp(&nnode->tn_atime);
 	nnode->tn_birthtime = nnode->tn_atime;
 	nnode->tn_ctime = nnode->tn_atime;
 	nnode->tn_mtime = nnode->tn_atime;
 
+	KASSERT(uid != VNOVAL && gid != VNOVAL && mode != VNOVAL);
 	nnode->tn_uid = uid;
 	nnode->tn_gid = gid;
 	nnode->tn_mode = mode;
-	nnode->tn_lockf = NULL;
-	nnode->tn_vnode = NULL;
 
 	/* Type-specific initialization. */
 	switch (nnode->tn_type) {
 	case VBLK:
 	case VCHR:
+		/* Character/block special device. */
+		KASSERT(rdev != VNOVAL);
 		nnode->tn_spec.tn_dev.tn_rdev = rdev;
 		break;
-
 	case VDIR:
+		/*
+		 * Directory.  Parent must be specified, unless allocating
+		 * the root inode.
+		 */
+		KASSERT(parent || tmp->tm_root == NULL);
+		KASSERT(parent != nnode);
+
 		TAILQ_INIT(&nnode->tn_spec.tn_dir.tn_dir);
 		nnode->tn_spec.tn_dir.tn_parent =
 		    (parent == NULL) ? nnode : parent;
@@ -154,14 +127,13 @@
 		nnode->tn_spec.tn_dir.tn_readdir_lastp = NULL;
 		nnode->tn_links++;
 		break;
-
 	case VFIFO:
-		/* FALLTHROUGH */
 	case VSOCK:
 		break;
-
 	case VLNK:
-		KASSERT(strlen(target) < MAXPATHLEN);
+		/* Symbolic link.  Target specifies the file name. */
+		KASSERT(target && strlen(target) < MAXPATHLEN);
+
 		nnode->tn_size = strlen(target);
 		if (nnode->tn_size == 0) {
 			nnode->tn_spec.tn_lnk.tn_link = NULL;
@@ -170,21 +142,19 @@
 		nnode->tn_spec.tn_lnk.tn_link =
 		    tmpfs_strname_alloc(tmp, nnode->tn_size);
 		if (nnode->tn_spec.tn_lnk.tn_link == NULL) {
-			atomic_dec_uint(&tmp->tm_nodes_cnt);
 			tmpfs_node_put(tmp, nnode);
 			return ENOSPC;
 		}
 		memcpy(nnode->tn_spec.tn_lnk.tn_link, target, nnode->tn_size);
 		break;
-
 	case VREG:
+		/* Regular file.  Create an underlying UVM object. */
 		nnode->tn_spec.tn_reg.tn_aobj =
 		    uao_create(INT32_MAX - PAGE_SIZE, 0);
 		nnode->tn_spec.tn_reg.tn_aobj_pages = 0;
 		break;
-
 	default:
-		KASSERT(0);
+		KASSERT(false);
 	}
 
 	mutex_init(&nnode->tn_vlock, MUTEX_DEFAULT, IPL_NONE);
@@ -197,24 +167,9 @@
 	return 0;
 }
 
-/* --------------------------------------------------------------------- */
-
 /*
- * Destroys the node pointed to by node from the file system 'tmp'.
- * If the node does not belong to the given mount point, the results are
- * unpredicted.
- *
- * If the node references a directory; no entries are allowed because
- * their removal could need a recursive algorithm, something forbidden in
- * kernel space.  Furthermore, there is not need to provide such
- * functionality (recursive removal) because the only primitives offered
- * to the user are the removal of empty directories and the deletion of
- * individual files.
- *
- * Note that nodes are not really deleted; in fact, when a node has been
- * allocated, it cannot be deleted during the whole life of the file
- * system.  Instead, they are moved to the available list and remain there
- * until reused.
+ * tmpfs_free_node: remove the inode from a list in the mount point and
+ * destroy the inode structures.
  */
 void
 tmpfs_free_node(struct tmpfs_mount *tmp, struct tmpfs_node *node)
@@ -224,18 +179,18 @@
 	mutex_enter(&tmp->tm_lock);
 	LIST_REMOVE(node, tn_entries);
 	mutex_exit(&tmp->tm_lock);
-	atomic_dec_uint(&tmp->tm_nodes_cnt);
 
 	switch (node->tn_type) {
 	case VLNK:
-		if (node->tn_size > 0)
+		if (node->tn_size > 0) {
 			tmpfs_strname_free(tmp, node->tn_spec.tn_lnk.tn_link,
 			    node->tn_size);
+		}
 		break;
 	case VREG:
 		/*
-		 * Calculate the size of node data, decrease the used-memory
-		 * counter, and destroy the memory object (if any).
+		 * Calculate the size of inode data, decrease the used-memory
+		 * counter, and destroy the unerlying UVM object (if any).
 		 */
 		objsz = PAGE_SIZE * node->tn_spec.tn_reg.tn_aobj_pages;
 		if (objsz != 0) {
@@ -245,6 +200,10 @@
 			uao_detach(node->tn_spec.tn_reg.tn_aobj);
 		}
 		break;
+	case VDIR:
+		KASSERT(TAILQ_EMPTY(&node->tn_spec.tn_dir.tn_dir));
+		KASSERT(node->tn_spec.tn_dir.tn_parent || node == tmp->tm_root);
+		break;
 	default:
 		break;
 	}
@@ -253,8 +212,6 @@
 	tmpfs_node_put(tmp, node);
 }
 
-/* --------------------------------------------------------------------- */
-
 /*
  * Allocates a new directory entry for the node node with a name of name.
  * The new directory entry is returned in *de.

Index: src/sys/fs/tmpfs/tmpfs_vfsops.c
diff -u src/sys/fs/tmpfs/tmpfs_vfsops.c:1.48 src/sys/fs/tmpfs/tmpfs_vfsops.c:1.49
--- src/sys/fs/tmpfs/tmpfs_vfsops.c:1.48	Thu May 19 03:21:23 2011
+++ src/sys/fs/tmpfs/tmpfs_vfsops.c	Tue May 24 01:09:47 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vfsops.c,v 1.48 2011/05/19 03:21:23 rmind Exp $	*/
+/*	$NetBSD: tmpfs_vfsops.c,v 1.49 2011/05/24 01:09:47 rmind Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.48 2011/05/19 03:21:23 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vfsops.c,v 1.49 2011/05/24 01:09:47 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -105,7 +105,9 @@
 	ino_t nodes;
 	int error;
 
-	if (*data_len < sizeof *args)
+	/* Validate the version. */
+	if (*data_len < sizeof(*args) ||
+	    args->ta_version != TMPFS_ARGS_VERSION)
 		return EINVAL;
 
 	/* Handle retrieval of mount point arguments. */
@@ -128,17 +130,11 @@
 	}
 
 	if (mp->mnt_flag & MNT_UPDATE) {
-		/* XXX: There is no support yet to update file system
-		 * settings.  Should be added. */
-
+		/* TODO */
 		return EOPNOTSUPP;
 	}
 
-	if (args->ta_version != TMPFS_ARGS_VERSION)
-		return EINVAL;
-
-	/* Do not allow mounts if we do not have enough memory to preserve
-	 * the minimum reserved pages. */
+	/* Prohibit mounts if there is not enough memory. */
 	if (tmpfs_mem_info(true) < TMPFS_PAGES_RESERVED)
 		return EINVAL;
 
@@ -159,7 +155,7 @@
 	KASSERT(nodes >= 3);
 
 	/* Allocate the tmpfs mount structure and fill it. */
-	tmp = kmem_alloc(sizeof(struct tmpfs_mount), KM_SLEEP);
+	tmp = kmem_zalloc(sizeof(struct tmpfs_mount), KM_SLEEP);
 	if (tmp == NULL)
 		return ENOMEM;
 
@@ -194,8 +190,6 @@
 	return error;
 }
 
-/* --------------------------------------------------------------------- */
-
 static int
 tmpfs_start(struct mount *mp, int flags)
 {

Reply via email to