#include #include #include #include #include #include #include #include static char probe_path[MAXPATHLEN]; static int probe_result = -1; static int probe_run(SYSCTL_HANDLER_ARGS) { struct nameidata nd; struct vattr attributes; struct vnode *vnode; int error, operation; operation = 0; error = sysctl_handle_int(oidp, &operation, 0, req); if (error != 0 || req->newptr == NULL) return (error); if (operation < 1 || operation > 5 || probe_path[0] == '\0') return (EINVAL); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, probe_path); error = namei(&nd); if (error != 0) { probe_result = error; return (0); } vnode = nd.ni_vp; NDFREE_PNBUF(&nd); VATTR_NULL(&attributes); attributes.va_size = 0; if (operation == 2 || operation == 5) attributes.va_mode = 0600; if (operation == 3 || operation == 5) { attributes.va_uid = 1; attributes.va_gid = 1; } if (operation == 4 || operation == 5) { attributes.va_atime.tv_sec = 1; attributes.va_atime.tv_nsec = 0; attributes.va_mtime.tv_sec = 1; attributes.va_mtime.tv_nsec = 0; } probe_result = VOP_SETATTR(vnode, &attributes, curthread->td_ucred); vput(vnode); return (0); } static int probe_modevent(module_t module, int event, void *arg) { (void)module; (void)arg; switch (event) { case MOD_LOAD: case MOD_UNLOAD: return (0); default: return (EOPNOTSUPP); } } SYSCTL_NODE(_debug, OID_AUTO, erofs_setattr_probe, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "EROFS setattr regression probe"); SYSCTL_STRING(_debug_erofs_setattr_probe, OID_AUTO, path, CTLFLAG_RW, probe_path, sizeof(probe_path), "Target vnode path"); SYSCTL_PROC(_debug_erofs_setattr_probe, OID_AUTO, run, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0, probe_run, "I", "1=size; 2=size+mode; 3=size+owner; 4=size+times; 5=all"); SYSCTL_INT(_debug_erofs_setattr_probe, OID_AUTO, result, CTLFLAG_RD, &probe_result, 0, "Last VOP_SETATTR errno"); static moduledata_t probe_module = { "erofs_setattr_probe", probe_modevent, NULL, }; DECLARE_MODULE(erofs_setattr_probe, probe_module, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_VERSION(erofs_setattr_probe, 1);