version 1.37, 2007/02/22 06:37:00 |
version 1.37.4.6, 2007/10/08 20:19:29 |
Line 231 tmpfs_lookup(void *v) |
|
Line 231 tmpfs_lookup(void *v) |
|
cnp->cn_lwp); |
cnp->cn_lwp); |
if (error != 0) |
if (error != 0) |
goto out; |
goto out; |
tnode->tn_lookup_dirent = de; |
} else |
} |
de = NULL; |
|
|
/* Allocate a new vnode on the matching entry. */ |
/* Allocate a new vnode on the matching entry. */ |
error = tmpfs_alloc_vp(dvp->v_mount, tnode, vpp); |
error = tmpfs_alloc_vp(dvp->v_mount, tnode, vpp); |
|
tnode->tn_lookup_dirent = de; |
} |
} |
} |
} |
|
|
|
|
else |
else |
vput(dvp); |
vput(dvp); |
|
|
KASSERT(!VOP_ISLOCKED(dvp)); |
|
|
|
return error; |
return error; |
} |
} |
|
|
Line 718 tmpfs_link(void *v) |
|
Line 717 tmpfs_link(void *v) |
|
struct tmpfs_node *node; |
struct tmpfs_node *node; |
|
|
KASSERT(VOP_ISLOCKED(dvp)); |
KASSERT(VOP_ISLOCKED(dvp)); |
KASSERT(!VOP_ISLOCKED(vp)); |
|
KASSERT(cnp->cn_flags & HASBUF); |
KASSERT(cnp->cn_flags & HASBUF); |
KASSERT(dvp != vp); /* XXX When can this be false? */ |
KASSERT(dvp != vp); /* XXX When can this be false? */ |
|
|
Line 729 tmpfs_link(void *v) |
|
Line 727 tmpfs_link(void *v) |
|
* needs the vnode to be locked. */ |
* needs the vnode to be locked. */ |
error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
if (error != 0) |
if (error != 0) |
goto out; |
goto out1; |
|
|
/* XXX: Why aren't the following two tests done by the caller? */ |
/* XXX: Why aren't the following two tests done by the caller? */ |
|
|
Line 775 tmpfs_link(void *v) |
|
Line 773 tmpfs_link(void *v) |
|
error = 0; |
error = 0; |
|
|
out: |
out: |
if (VOP_ISLOCKED(vp)) |
VOP_UNLOCK(vp, 0); |
VOP_UNLOCK(vp, 0); |
out1: |
|
|
PNBUF_PUT(cnp->cn_pnbuf); |
PNBUF_PUT(cnp->cn_pnbuf); |
|
|
vput(dvp); |
vput(dvp); |
|
|
/* XXX Locking status of dvp does not match manual page. */ |
|
KASSERT(!VOP_ISLOCKED(dvp)); |
|
KASSERT(!VOP_ISLOCKED(vp)); |
|
|
|
return error; |
return error; |
} |
} |
|
|
Line 807 tmpfs_rename(void *v) |
|
Line 800 tmpfs_rename(void *v) |
|
struct tmpfs_mount *tmp; |
struct tmpfs_mount *tmp; |
struct tmpfs_node *fdnode; |
struct tmpfs_node *fdnode; |
struct tmpfs_node *fnode; |
struct tmpfs_node *fnode; |
|
struct tmpfs_node *tnode; |
struct tmpfs_node *tdnode; |
struct tmpfs_node *tdnode; |
|
|
KASSERT(VOP_ISLOCKED(tdvp)); |
KASSERT(VOP_ISLOCKED(tdvp)); |
KASSERT(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp))); |
KASSERT(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp) == LK_EXCLUSIVE)); |
KASSERT(fcnp->cn_flags & HASBUF); |
KASSERT(fcnp->cn_flags & HASBUF); |
KASSERT(tcnp->cn_flags & HASBUF); |
KASSERT(tcnp->cn_flags & HASBUF); |
|
|
fdnode = VP_TO_TMPFS_DIR(fdvp); |
fdnode = VP_TO_TMPFS_DIR(fdvp); |
fnode = VP_TO_TMPFS_NODE(fvp); |
fnode = VP_TO_TMPFS_NODE(fvp); |
|
tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp); |
de = fnode->tn_lookup_dirent; |
de = fnode->tn_lookup_dirent; |
|
|
/* Disallow cross-device renames. |
/* Disallow cross-device renames. |
Line 843 tmpfs_rename(void *v) |
|
Line 838 tmpfs_rename(void *v) |
|
} |
} |
KASSERT(de->td_node == fnode); |
KASSERT(de->td_node == fnode); |
|
|
|
/* If replacing an existing entry, ensure we can do the operation. */ |
|
if (tvp != NULL) { |
|
KASSERT(tnode != NULL); |
|
if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) { |
|
if (tnode->tn_size > 0) { |
|
error = ENOTEMPTY; |
|
goto out; |
|
} |
|
} else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) { |
|
error = ENOTDIR; |
|
goto out; |
|
} else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) { |
|
error = EISDIR; |
|
goto out; |
|
} else { |
|
KASSERT(fnode->tn_type != VDIR && |
|
tnode->tn_type != VDIR); |
|
} |
|
} |
|
|
/* If we need to move the directory between entries, lock the |
/* If we need to move the directory between entries, lock the |
* source so that we can safely operate on it. */ |
* source so that we can safely operate on it. */ |
if (fdnode != tdnode) { |
if (fdnode != tdnode) { |
Line 925 tmpfs_rename(void *v) |
|
Line 940 tmpfs_rename(void *v) |
|
/* If we are overwriting an entry, we have to remove the old one |
/* If we are overwriting an entry, we have to remove the old one |
* from the target directory. */ |
* from the target directory. */ |
if (tvp != NULL) { |
if (tvp != NULL) { |
struct tmpfs_node *tnode; |
KASSERT(tnode != NULL); |
|
|
tnode = VP_TO_TMPFS_NODE(tvp); |
|
|
|
/* The source node cannot be a directory in this case. */ |
|
KASSERT(fnode->tn_type != VDIR); |
|
|
|
/* Remove the old entry from the target directory. */ |
/* Remove the old entry from the target directory. */ |
de = tnode->tn_lookup_dirent; |
de = tnode->tn_lookup_dirent; |
Line 1007 tmpfs_rmdir(void *v) |
|
Line 1017 tmpfs_rmdir(void *v) |
|
tmp = VFS_TO_TMPFS(dvp->v_mount); |
tmp = VFS_TO_TMPFS(dvp->v_mount); |
dnode = VP_TO_TMPFS_DIR(dvp); |
dnode = VP_TO_TMPFS_DIR(dvp); |
node = VP_TO_TMPFS_DIR(vp); |
node = VP_TO_TMPFS_DIR(vp); |
|
error = 0; |
|
|
/* Directories with more than two entries ('.' and '..') cannot be |
/* Directories with more than two entries ('.' and '..') cannot be |
* removed. */ |
* removed. */ |
Line 1014 tmpfs_rmdir(void *v) |
|
Line 1025 tmpfs_rmdir(void *v) |
|
error = ENOTEMPTY; |
error = ENOTEMPTY; |
goto out; |
goto out; |
} |
} |
|
KASSERT(node->tn_links == 1); |
|
|
/* This invariant holds only if we are not trying to remove "..". |
/* This invariant holds only if we are not trying to remove "..". |
* We checked for that above so this is safe now. */ |
* We checked for that above so this is safe now. */ |
Line 1044 tmpfs_rmdir(void *v) |
|
Line 1056 tmpfs_rmdir(void *v) |
|
|
|
/* Release the parent. */ |
/* Release the parent. */ |
cache_purge(dvp); /* XXX Is this needed? */ |
cache_purge(dvp); /* XXX Is this needed? */ |
vput(dvp); |
|
|
|
/* Free the directory entry we just deleted. Note that the node |
/* Free the directory entry we just deleted. Note that the node |
* referred by it will not be removed until the vnode is really |
* referred by it will not be removed until the vnode is really |
* reclaimed. */ |
* reclaimed. */ |
tmpfs_free_dirent(tmp, de, true); |
tmpfs_free_dirent(tmp, de, true); |
|
|
/* Release the deleted vnode (will destroy the node, notify |
out: |
* interested parties and clean it from the cache). */ |
/* Release the nodes. */ |
|
vput(dvp); |
vput(vp); |
vput(vp); |
|
|
error = 0; |
|
|
|
out: |
|
if (error != 0) { |
|
vput(dvp); |
|
vput(vp); |
|
} |
|
|
|
return error; |
return error; |
} |
} |
|
|
|
|
tmpfs_inactive(void *v) |
tmpfs_inactive(void *v) |
{ |
{ |
struct vnode *vp = ((struct vop_inactive_args *)v)->a_vp; |
struct vnode *vp = ((struct vop_inactive_args *)v)->a_vp; |
struct lwp *l = ((struct vop_inactive_args *)v)->a_l; |
bool *recycle = ((struct vop_inactive_args *)v)->a_recycle; |
|
nlink_t links; |
|
|
struct tmpfs_node *node; |
struct tmpfs_node *node; |
|
|
KASSERT(VOP_ISLOCKED(vp)); |
KASSERT(VOP_ISLOCKED(vp)); |
|
|
node = VP_TO_TMPFS_NODE(vp); |
node = VP_TO_TMPFS_NODE(vp); |
|
links = node->tn_links; |
|
|
VOP_UNLOCK(vp, 0); |
VOP_UNLOCK(vp, 0); |
|
|
if (node->tn_links == 0) |
*recycle = (links == 0); |
vrecycle(vp, NULL, l); |
|
|
|
return 0; |
return 0; |
} |
} |
Line 1246 tmpfs_reclaim(void *v) |
|
Line 1251 tmpfs_reclaim(void *v) |
|
struct tmpfs_mount *tmp; |
struct tmpfs_mount *tmp; |
struct tmpfs_node *node; |
struct tmpfs_node *node; |
|
|
KASSERT(!VOP_ISLOCKED(vp)); |
|
|
|
node = VP_TO_TMPFS_NODE(vp); |
node = VP_TO_TMPFS_NODE(vp); |
tmp = VFS_TO_TMPFS(vp->v_mount); |
tmp = VFS_TO_TMPFS(vp->v_mount); |
|
|
Line 1260 tmpfs_reclaim(void *v) |
|
Line 1263 tmpfs_reclaim(void *v) |
|
if (node->tn_links == 0) |
if (node->tn_links == 0) |
tmpfs_free_node(tmp, node); |
tmpfs_free_node(tmp, node); |
|
|
KASSERT(!VOP_ISLOCKED(vp)); |
|
KASSERT(vp->v_data == NULL); |
KASSERT(vp->v_data == NULL); |
|
|
return 0; |
return 0; |
Line 1380 tmpfs_getpages(void *v) |
|
Line 1382 tmpfs_getpages(void *v) |
|
int npages = *count; |
int npages = *count; |
|
|
KASSERT(vp->v_type == VREG); |
KASSERT(vp->v_type == VREG); |
LOCK_ASSERT(simple_lock_held(&vp->v_interlock)); |
KASSERT(mutex_owned(&vp->v_interlock)); |
|
|
node = VP_TO_TMPFS_NODE(vp); |
node = VP_TO_TMPFS_NODE(vp); |
uobj = node->tn_spec.tn_reg.tn_aobj; |
uobj = node->tn_spec.tn_reg.tn_aobj; |
Line 1389 tmpfs_getpages(void *v) |
|
Line 1391 tmpfs_getpages(void *v) |
|
|
|
if (vp->v_size <= offset + (centeridx << PAGE_SHIFT)) { |
if (vp->v_size <= offset + (centeridx << PAGE_SHIFT)) { |
if ((flags & PGO_LOCKED) == 0) |
if ((flags & PGO_LOCKED) == 0) |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
return EINVAL; |
return EINVAL; |
} |
} |
|
|
Line 1408 tmpfs_getpages(void *v) |
|
Line 1410 tmpfs_getpages(void *v) |
|
node->tn_status |= TMPFS_NODE_MODIFIED; |
node->tn_status |= TMPFS_NODE_MODIFIED; |
} |
} |
|
|
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
|
|
/* |
/* |
* Make sure that the array on which we will store the |
* Make sure that the array on which we will store the |
Line 1423 tmpfs_getpages(void *v) |
|
Line 1425 tmpfs_getpages(void *v) |
|
if (m != NULL) |
if (m != NULL) |
for (i = 0; i < npages; i++) |
for (i = 0; i < npages; i++) |
m[i] = NULL; |
m[i] = NULL; |
simple_lock(&uobj->vmobjlock); |
mutex_enter(&uobj->vmobjlock); |
error = (*uobj->pgops->pgo_get)(uobj, offset, m, &npages, centeridx, |
error = (*uobj->pgops->pgo_get)(uobj, offset, m, &npages, centeridx, |
access_type, advice, flags | PGO_ALLPAGES); |
access_type, advice, flags | PGO_ALLPAGES); |
#if defined(DEBUG) |
#if defined(DEBUG) |
Line 1453 tmpfs_putpages(void *v) |
|
Line 1455 tmpfs_putpages(void *v) |
|
struct tmpfs_node *node; |
struct tmpfs_node *node; |
struct uvm_object *uobj; |
struct uvm_object *uobj; |
|
|
LOCK_ASSERT(simple_lock_held(&vp->v_interlock)); |
KASSERT(mutex_owned(&vp->v_interlock)); |
|
|
node = VP_TO_TMPFS_NODE(vp); |
node = VP_TO_TMPFS_NODE(vp); |
|
|
if (vp->v_type != VREG) { |
if (vp->v_type != VREG) { |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
return 0; |
return 0; |
} |
} |
|
|
uobj = node->tn_spec.tn_reg.tn_aobj; |
uobj = node->tn_spec.tn_reg.tn_aobj; |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
|
|
simple_lock(&uobj->vmobjlock); |
mutex_enter(&uobj->vmobjlock); |
error = (*uobj->pgops->pgo_put)(uobj, offlo, offhi, flags); |
error = (*uobj->pgops->pgo_put)(uobj, offlo, offhi, flags); |
|
|
/* XXX mtime */ |
/* XXX mtime */ |