With VNOP_MONITOR() still unavailable I thought I'd explore other alternatives.
Passing VFS_TBLNOMACLABEL into vfs_fsadd() has revealed that the issue was with the vnode being NULL when accessing directories that were removed on other client machines.
Further debugging has confirmed that the vnode was being set to NULL via a call to cache_enter() with cn_flags set to MAKEENTRY in vnop_lookup() on receiving a response from the server saying that the directory was no longer there.
Dtrace(1)'ing vnode's mac labels showed that for my filesystem they were set to NULL at all times whether or not VFS_TBLNOMACLABEL was set.
My filesystem being distributed, I have the benefit of querying the server about the presence of files or directories in my vnop_lookup().
What I attempted next is modify my lookup algorithm to remove the local vnode that represents a file or directory that the server reports as no longer existing, i.e. removed by another client machine.
Below is a pseudocode for the part of my lookup algorithm that deals with negative server responses.
ret = query_server(item);
if(ret==ENOENT){
if(ISSET(cnp->cn_flags, ISLASTCN)){
err = cache_lookup(cnp);
if(err==CACHE_HIT){ /*item rm'd elsewhere, remove local vnode*/
vn_revoke(vp);
cache_purge(dvp);
vnode_update_identity(VNODE_UPDATE_PURGE);
}
else if(err==ENOENT)
cache_purge_negatives(dvp);
else if(cnp->cn_nameiop==CREATE||cnp->cn_nameiop==RENAME)
ret = EJUSTRETURN;
else if(ISSET(cnp->cn_flags, MAKEENTRY))
cache_enter(dvp, NULLVP, cnp);
}
}
vn_revoke() ends up calling vnop_reclaim(), which in turn does the following:
remove_np_from_hashtable();
vnode_removefsref(vp);
vnode_clearfsnode(vp);
cache_purge(vp);
The above does prevent kernel panics from happening when clicking on files or directories that were removed elsewhere in Finder.
On stepping back to the parent directory, the removed item is no longer displayed.
However, it's still showing in the terminal when queried with ls(1) or stat(1).
I've instrumented relevant parts of code with debugging print statements, but I still don't understand why this is happening.
Any pointers on what I'm missing would be greatly appreciated.