void tmpfs_free_vp(struct vnode *);
int tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
struct namecache *, struct ucred *, char *);
-void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
-void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
+void tmpfs_dir_attach(struct tmpfs_node *, struct tmpfs_dirent *);
+void tmpfs_dir_detach(struct tmpfs_node *, struct tmpfs_dirent *);
struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node,
struct tmpfs_node *f,
struct namecache *ncp);
int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *);
-int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *);
+int tmpfs_dir_getdotdotdent(struct tmpfs_mount *,
+ struct tmpfs_node *, struct uio *);
struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t);
int tmpfs_dir_getdents(struct tmpfs_node *, struct uio *, off_t *);
int tmpfs_reg_resize(struct vnode *, off_t, int);
case VSOCK:
break;
case VREG:
- vinitvmio(vp, node->tn_size);
+ vinitvmio(vp, (node->tn_size + BMASK) & ~(off_t)BMASK);
break;
case VLNK:
- if (node->tn_size >= vp->v_mount->mnt_maxsymlinklen)
- vinitvmio(vp, node->tn_size);
break;
case VFIFO:
vp->v_ops = &mp->mnt_vn_fifo_ops;
break;
case VDIR:
- vinitvmio(vp, node->tn_size);
break;
default:
/* Now that all required items are allocated, we can proceed to
* insert the new node into the directory, an operation that
* cannot fail. */
- tmpfs_dir_attach(dvp, de);
+ tmpfs_dir_attach(dnode, de);
TMPFS_NODE_UNLOCK(node);
return error;
* the directory entry, as this is done by tmpfs_alloc_dirent.
*/
void
-tmpfs_dir_attach(struct vnode *vp, struct tmpfs_dirent *de)
+tmpfs_dir_attach(struct tmpfs_node *dnode, struct tmpfs_dirent *de)
{
- struct tmpfs_node *dnode;
-
- dnode = VP_TO_TMPFS_DIR(vp);
-
+ TMPFS_NODE_LOCK(dnode);
TAILQ_INSERT_TAIL(&dnode->tn_dir.tn_dirhead, de, td_entries);
- TMPFS_NODE_LOCK(dnode);
TMPFS_ASSERT_ELOCKED(dnode);
dnode->tn_size += sizeof(struct tmpfs_dirent);
- dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
- TMPFS_NODE_MODIFIED;
+ dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED |
+ TMPFS_NODE_MODIFIED;
TMPFS_NODE_UNLOCK(dnode);
}
* the directory entry, as this is done by tmpfs_free_dirent.
*/
void
-tmpfs_dir_detach(struct vnode *vp, struct tmpfs_dirent *de)
+tmpfs_dir_detach(struct tmpfs_node *dnode, struct tmpfs_dirent *de)
{
- struct tmpfs_node *dnode;
-
- dnode = VP_TO_TMPFS_DIR(vp);
-
-
+ TMPFS_NODE_LOCK(dnode);
if (dnode->tn_dir.tn_readdir_lastp == de) {
dnode->tn_dir.tn_readdir_lastn = 0;
dnode->tn_dir.tn_readdir_lastp = NULL;
}
TAILQ_REMOVE(&dnode->tn_dir.tn_dirhead, de, td_entries);
- TMPFS_NODE_LOCK(dnode);
TMPFS_ASSERT_ELOCKED(dnode);
dnode->tn_size -= sizeof(struct tmpfs_dirent);
- dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
- TMPFS_NODE_MODIFIED;
+ dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED |
+ TMPFS_NODE_MODIFIED;
TMPFS_NODE_UNLOCK(dnode);
}
* error happens.
*/
int
-tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio)
+tmpfs_dir_getdotdotdent(struct tmpfs_mount *tmp, struct tmpfs_node *node,
+ struct uio *uio)
{
int error;
struct dirent dent;
TMPFS_VALIDATE_DIR(node);
KKASSERT(uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT);
- /*
- * Return ENOENT if the current node is already removed.
- */
- if (node->tn_dir.tn_parent == NULL) {
- return (ENOENT);
+ if (node->tn_dir.tn_parent) {
+ TMPFS_NODE_LOCK(node->tn_dir.tn_parent);
+ dent.d_ino = node->tn_dir.tn_parent->tn_id;
+ TMPFS_NODE_UNLOCK(node->tn_dir.tn_parent);
+ } else {
+ dent.d_ino = tmp->tm_root->tn_id;
}
- TMPFS_NODE_LOCK(node->tn_dir.tn_parent);
- dent.d_ino = node->tn_dir.tn_parent->tn_id;
- TMPFS_NODE_UNLOCK(node->tn_dir.tn_parent);
-
dent.d_type = DT_DIR;
dent.d_namlen = 2;
dent.d_name[0] = '.';
* When adjusting the vnode filesize and its VM object we must
* also adjust our backing VM object (aobj). The blocksize
* used must match the block sized we use for the buffer cache.
+ *
+ * The backing VM object contains no VM pages, only swap
+ * assignments.
*/
if (newsize < oldsize) {
vm_pindex_t osize;
+ vm_pindex_t nsize;
vm_object_t aobj;
error = nvtruncbuf(vp, newsize, BSIZE, -1);
aobj = node->tn_reg.tn_aobj;
if (aobj) {
osize = aobj->size;
- if (osize > vp->v_object->size) {
+ nsize = vp->v_object->size;
+ if (nsize < osize) {
aobj->size = osize;
- vm_object_page_remove(aobj, vp->v_object->size,
- osize, FALSE);
+ swap_pager_freespace(aobj, nsize,
+ osize - nsize);
}
}
} else {
while (!TAILQ_EMPTY(&node->tn_dir.tn_dirhead)) {
de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
+ tmpfs_dir_detach(node, de);
tmpfs_free_dirent(tmp, de);
node->tn_size -= sizeof(struct tmpfs_dirent);
}
/* Remove the entry from the directory; as it is a file, we do not
* have to change the number of hard links of the directory. */
- tmpfs_dir_detach(dvp, de);
+ tmpfs_dir_detach(dnode, de);
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
struct vnode *dvp = v->a_dvp;
struct vnode *vp = v->a_vp;
struct namecache *ncp = v->a_nch->ncp;
-
- int error;
struct tmpfs_dirent *de;
struct tmpfs_node *node;
+ struct tmpfs_node *dnode;
+ int error;
KKASSERT(dvp != vp); /* XXX When can this be false? */
node = VP_TO_TMPFS_NODE(vp);
+ dnode = VP_TO_TMPFS_NODE(dvp);
/* XXX: Why aren't the following two tests done by the caller? */
goto out;
/* Insert the new directory entry into the appropriate directory. */
- tmpfs_dir_attach(dvp, de);
+ tmpfs_dir_attach(dnode, de);
/* vp link count has changed, so update node times. */
struct vnode *tdvp = v->a_tdvp;
struct namecache *tncp = v->a_tnch->ncp;
struct vnode *tvp = tncp->nc_vp;
-
- char *newname;
- int error;
struct tmpfs_dirent *de;
struct tmpfs_mount *tmp;
struct tmpfs_node *fdnode;
struct tmpfs_node *fnode;
struct tmpfs_node *tnode;
struct tmpfs_node *tdnode;
+ char *newname;
+ int error;
tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
/* Do the move: just remove the entry from the source directory
* and insert it into the target one. */
- tmpfs_dir_detach(fdvp, de);
- tmpfs_dir_attach(tdvp, de);
+ tmpfs_dir_detach(fdnode, de);
+ tmpfs_dir_attach(tdnode, de);
}
/* If the name has changed, we need to make it effective by changing
if (tvp != NULL) {
/* Remove the old entry from the target directory. */
de = tmpfs_dir_lookup(tdnode, tnode, tncp);
- tmpfs_dir_detach(tdvp, de);
+ tmpfs_dir_detach(tdnode, de);
/* Free the directory entry we just deleted. Note that the
* node referred by it will not be removed until the vnode is
/* Detach the directory entry from the directory (dnode). */
- tmpfs_dir_detach(dvp, de);
+ tmpfs_dir_detach(dnode, de);
/* No vnode should be allocated for this entry from this point */
TMPFS_NODE_LOCK(node);
int *eofflag = v->a_eofflag;
off_t **cookies = v->a_cookies;
int *ncookies = v->a_ncookies;
-
+ struct tmpfs_mount *tmp;
int error;
off_t startoff;
off_t cnt = 0;
if (vp->v_type != VDIR)
return ENOTDIR;
+ tmp = VFS_TO_TMPFS(vp->v_mount);
node = VP_TO_TMPFS_DIR(vp);
startoff = uio->uio_offset;
}
if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) {
- error = tmpfs_dir_getdotdotdent(node, uio);
+ error = tmpfs_dir_getdotdotdent(tmp, node, uio);
if (error != 0)
goto outok;
cnt++;