* Walk up the mount stack (if any). * * Correctness is provided in the following ways: * - all vnodes are protected from freeing with SMR * - struct mount objects are type stable making them always safe to access * - stability of the particular mount is provided by busying it * - relationship between the vnode which is mounted on and the mount is * verified with the vnode sequence counter
| 5063 | * indeed present at least at some point which matches the regular lookup. |
| 5064 | */ |
| 5065 | static int __noinline |
| 5066 | cache_fplookup_climb_mount(struct cache_fpl *fpl) |
| 5067 | { |
| 5068 | struct mount *mp, *prev_mp; |
| 5069 | struct mount_pcpu *mpcpu, *prev_mpcpu; |
| 5070 | struct vnode *vp; |
| 5071 | seqc_t vp_seqc; |
| 5072 | |
| 5073 | vp = fpl->tvp; |
| 5074 | vp_seqc = fpl->tvp_seqc; |
| 5075 | |
| 5076 | VNPASS(vp->v_type == VDIR || vp->v_type == VBAD, vp); |
| 5077 | mp = atomic_load_ptr(&vp->v_mountedhere); |
| 5078 | if (__predict_false(mp == NULL)) { |
| 5079 | return (0); |
| 5080 | } |
| 5081 | |
| 5082 | prev_mp = NULL; |
| 5083 | for (;;) { |
| 5084 | if (!vfs_op_thread_enter_crit(mp, mpcpu)) { |
| 5085 | if (prev_mp != NULL) |
| 5086 | vfs_op_thread_exit_crit(prev_mp, prev_mpcpu); |
| 5087 | return (cache_fpl_partial(fpl)); |
| 5088 | } |
| 5089 | if (prev_mp != NULL) |
| 5090 | vfs_op_thread_exit_crit(prev_mp, prev_mpcpu); |
| 5091 | if (!vn_seqc_consistent(vp, vp_seqc)) { |
| 5092 | vfs_op_thread_exit_crit(mp, mpcpu); |
| 5093 | return (cache_fpl_partial(fpl)); |
| 5094 | } |
| 5095 | if (!cache_fplookup_mp_supported(mp)) { |
| 5096 | vfs_op_thread_exit_crit(mp, mpcpu); |
| 5097 | return (cache_fpl_partial(fpl)); |
| 5098 | } |
| 5099 | vp = atomic_load_ptr(&mp->mnt_rootvnode); |
| 5100 | if (vp == NULL) { |
| 5101 | vfs_op_thread_exit_crit(mp, mpcpu); |
| 5102 | return (cache_fpl_partial(fpl)); |
| 5103 | } |
| 5104 | vp_seqc = vn_seqc_read_any(vp); |
| 5105 | if (seqc_in_modify(vp_seqc)) { |
| 5106 | vfs_op_thread_exit_crit(mp, mpcpu); |
| 5107 | return (cache_fpl_partial(fpl)); |
| 5108 | } |
| 5109 | prev_mp = mp; |
| 5110 | prev_mpcpu = mpcpu; |
| 5111 | mp = atomic_load_ptr(&vp->v_mountedhere); |
| 5112 | if (mp == NULL) |
| 5113 | break; |
| 5114 | } |
| 5115 | |
| 5116 | vfs_op_thread_exit_crit(prev_mp, prev_mpcpu); |
| 5117 | fpl->tvp = vp; |
| 5118 | fpl->tvp_seqc = vp_seqc; |
| 5119 | return (0); |
| 5120 | } |
| 5121 | |
| 5122 | static int __noinline |
no test coverage detected