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) {