Now
MAIN commitmail json YAML
src/sys/kern/vfs_vnode.c@1.141
/
diff
/
nxr@1.141
src/sys/miscfs/specfs/spec_vnops.c@1.209 / diff / nxr@1.209
src/sys/miscfs/specfs/spec_vnops.c@1.209 / diff / nxr@1.209
specfs: Remove specnode from hash table in spec_node_revoke.
Previously, it was possible for spec_node_lookup_by_dev to handle a
speconde that a concurrent spec_node_destroy is about to remove from
the hash table and then free, as soon as spec_node_lookup_by_dev
releases device_lock.
Now, the ordering is:
1. Remove specnode from hash table in spec_node_revoke. At this
point, no _new_ vnode references are possible (other than possibly
one acquired by vcache_vget under v_interlock), but there may be
existing ones.
2. Mark vnode reclaimed so vcache_vget will fail.
3. The last vrele (or equivalent logic in vcache_vget) will then free
the specnode in spec_node_destroy.
This way, _if_ a thread in spec_node_lookup_by_dev finds a specnode
in the hash table under device_lock/v_interlock, _then_ it will not
be freed until the thread completes vcache_vget.
This change requires calling spec_node_revoke unconditionally for
device special nodes, not just for active ones. Might introduce
slightly more contention on device_lock but not much because we
already have to take it in this path anyway a little later in
spec_node_destroy.
Previously, it was possible for spec_node_lookup_by_dev to handle a
speconde that a concurrent spec_node_destroy is about to remove from
the hash table and then free, as soon as spec_node_lookup_by_dev
releases device_lock.
Now, the ordering is:
1. Remove specnode from hash table in spec_node_revoke. At this
point, no _new_ vnode references are possible (other than possibly
one acquired by vcache_vget under v_interlock), but there may be
existing ones.
2. Mark vnode reclaimed so vcache_vget will fail.
3. The last vrele (or equivalent logic in vcache_vget) will then free
the specnode in spec_node_destroy.
This way, _if_ a thread in spec_node_lookup_by_dev finds a specnode
in the hash table under device_lock/v_interlock, _then_ it will not
be freed until the thread completes vcache_vget.
This change requires calling spec_node_revoke unconditionally for
device special nodes, not just for active ones. Might introduce
slightly more contention on device_lock but not much because we
already have to take it in this path anyway a little later in
spec_node_destroy.