> > > void fsnotify_put_mark(struct fsnotify_mark *mark) > > > @@ -275,6 +317,9 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) > > > free_conn = true; > > > } else { > > > __fsnotify_recalc_mask(conn); > > > + /* Unpin inode on last mark that wants inode refcount held */ > > > + if (mark->flags & FSNOTIFY_MARK_FLAG_HAS_IREF) > > > + objp = fsnotify_drop_iref(conn, &type); > > > } > > > > This is going to be interesting. What if the connector got detached from > > the inode before fsnotify_put_mark() was called? Then iref_proxy would be > > already 0 and we would barf? I think > > fsnotify_detach_connector_from_object() needs to drop inode reference but > > leave iref_proxy alone for this to work. fsnotify_drop_iref() would then > > drop inode reference only if iref_proxy reaches 0 and conn->objp != NULL... > > > > Good catch! but solution I think the is way simpler: > > + /* Unpin inode on last mark that wants inode refcount held */ > + if (conn->type == FSNOTIFY_OBJ_TYPE_INODE && > + mark->flags & FSNOTIFY_MARK_FLAG_HAS_IREF) > + objp = fsnotify_drop_iref(conn, &type); > > (iref_proxy > 0) always infers a single i_count reference, so it makes > fsnotify_detach_connector_from_object() sets iref_proxy = 0 and > conn->type = FSNOTIFY_OBJ_TYPE_DETACHED, so we should be good here. > FWIW, I completely changed the proxy iref tracking in v2 (branch fan_evictable). There is no iref_proxy, only FSNOTIFY_CONN_FLAG_HAS_IREF flag on the connector which is aligned with elevated inode reference. The "virtual iref_proxy" is recalculated in __fsnotify_recalc_mask() which allows for the "upgrade to pinned inode" logic, but iput() is only called on detach of mark or detach of object, if connector had FSNOTIFY_CONN_FLAG_HAS_IREF and the "virtual iref_proxy" dropped to 0. Thanks, Amir.