Repository: koordinator-sh/koordinator

Issue:
[BUG] Pod creation fails with "invalid argument" when hyperThreadEnabledRatio > 1.0 in CPU Normalization
**What happened**:

When setting `hyperThreadEnabledRatio` to a value greater than 1.0 (e.g., 1.2) in the CPU Normalization configuration, Pod creation fails with the following error:
```
Warning Failed 4m3s (x4 over 4m50s) kubelet Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting cgroup config for procHooks process: failed to write "200000": write /sys/fs/cgroup/cpu,cpuacct/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podxxx.slice/cri-xxx.scope/cpu.cfs_quota_us: invalid argument: unknown
```

**What you expected to happen**:

Pods should be created successfully with adjusted CFS quota values according to the `hyperThreadEnabledRatio` setting.

**How to reproduce it (as minimally and precisely as possible)**:

1. Configure slo with CPU Normalization enabled and `hyperThreadEnabledRatio > 1.0`:
spec:
  cpuNormalizationStrategy:
    enable: true
    ratioModel:
      "Intel(R) Xeon(R) Silver 4116 CPU @ 2.10GHz":
        baseRatio: 1
        hyperThreadEnabledRatio: 1.2
2. Create a Pod with QoS `Burstable` and CPU limits (e.g., `cpu: 2`) and have init container
```
  - name: test
  initContainers:
  - command:
    - sh
    - -c
    - xxx
  ```

3. Observe that the Pod fails to start with "invalid argument" error

4. Change `hyperThreadEnabledRatio` to 1.0, and the Pod starts successfully

**Root Cause Analysis**:

The issue occurs due to Linux cgroup hierarchy constraints where parent cgroup's `cpu.cfs_quota_us` must be ≥ sum of children's quotas.

Current execution flow when `ratio = 1.2`:
1. **PreRunPodSandbox hook**: Pod quota is adjusted from 400000 to 333334 (400000 / 1.2)
2. **PreCreateContainer hook**: Container quota is NOT adjusted (remains 400000) because `Request.Resources == nil` in proxy mode
3. **Container creation**: Runtime tries to create container with quota 400000, but parent pod quota is 333334
4. **Result**: ❌ Constraint violation (400000 > 333334) → "invalid argument" error

**Proposed Solution**:

Add Pod Phase check to skip CFS quota adjustment during Pod creation phase, and only perform adjustment when Pod is Running (via reconciler):

func (p *Plugin) AdjustPodCFSQuota(proto protocol.HooksProtocol) error {
    // ... existing checks ...
    
    // Only adjust Pod CFS quota when Pod is Running
    if podCtx.Request.PodPhase != corev1.PodRunning {
        return nil
    }
    
    return p.adjustPodCFSQuota(podCtx)
}
This approach:
- Avoids cgroup constraint violations during Pod creation
- Leverages the reconciler mechanism to adjust quotas after Pod is Running
- Maintains backward compatibility
- Requires minimal code changes

**Anything else we need to know**:

- The issue only occurs when `hyperThreadEnabledRatio > 1.0` (quota needs to be reduced)
- When `hyperThreadEnabledRatio = 1.0`, no adjustment is needed, so Pod creation succeeds
- The bug affects all Pods with CPU limits when CPU Normalization is enabled with ratio > 1.0
- Related code: `pkg/koordlet/runtimehooks/hooks/cpunormalization/cpu_normalization.go`

**Environment**:
- Koordinator version: 1.7.0
- Kubernetes version: v1.28+
- Container runtime: containerd
- OS: Linux
- Kernel version: 5.x+
- Cgroup driver: systemd (cgroup v1)


Hints from issue comments:
@clay-wangzhi: /label area/koordlet@koordinator-bot: @clay-wangzhi: The label(s) `/label area/koordlet` cannot be applied. These labels are supported: ``

<details>

In response to [this](https://github.com/koordinator-sh/koordinator/issues/2693#issuecomment-3521225022):

>/label area/koordlet


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>

Solution patch:
diff --git a/.gitignore b/.gitignore
index 384f8c2c..ee973dee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,5 @@ vendor
 dist/
 
 README-contributing.md
+
+libpfm-*/
\ No newline at end of file
diff --git a/apis/extension/qos_utils.go b/apis/extension/qos_utils.go
index 63ae5621..ad62f655 100644
--- a/apis/extension/qos_utils.go
+++ b/apis/extension/qos_utils.go
@@ -18,7 +18,7 @@ package extension
 
 import (
 	corev1 "k8s.io/api/core/v1"
-	v1qos "k8s.io/kubernetes/pkg/apis/core/v1/helper/qos"
+	"k8s.io/kubectl/pkg/util/qos"
 )
 
 // NOTE: functions in this file can be overwritten for extension
@@ -74,5 +74,5 @@ func GetKubeQosClass(pod *corev1.Pod) corev1.PodQOSClass {
 	if len(qosClass) > 0 {
 		return qosClass
 	}
-	return v1qos.GetPodQOS(pod)
+	return qos.GetPodQOS(pod)
 }
diff --git a/apis/extension/reservation.go b/apis/extension/reservation.go
index b69e2633..c43fadb5 100644
--- a/apis/extension/reservation.go
+++ b/apis/extension/reservation.go
@@ -60,6 +60,20 @@ type ReservationAllocated struct {
 	UID  types.UID `json:"uid,omitempty"`
 }
 
+func (r *ReservationAllocated) GetName() string {
+	if r == nil {
+		return ""
+	}
+	return r.Name
+}
+
+func (r *ReservationAllocated) GetUID() types.UID {
+	if r == nil {
+		return ""
+	}
+	return r.UID
+}
+
 // ReservationAffinity represents the constraints of Pod selection Reservation
 type ReservationAffinity struct {
 	// Specifies the reservation name directly, other reservation affinity fields will be ignored.
diff --git a/apis/extension/resource.go b/apis/extension/resource.go
index 263f0c22..16eff056 100644
--- a/apis/extension/resource.go
+++ b/apis/extension/resource.go
@@ -18,6 +18,7 @@ package extension
 
 import (
 	"encoding/json"
+	"strings"
 
 	corev1 "k8s.io/api/core/v1"
 )
@@ -34,6 +35,11 @@ const (
 	// It annotates the requests/limits of extended resources and can be used by runtime proxy and koordlet that
 	// cannot get the original pod spec in CRI requests.
 	AnnotationExtendedResourceSpec = NodeDomainPrefix + "/extended-resource-spec"
+
+	// AnnotationPodReplaceResources is used to replace or erase the resource name in pod spec.
+	// This annotation allows the scheduler and webhook processing flow to update specified resources before evaluation.
+	// NOTE: The usage scenarios must ensure that the resources on the node are not oversold by itself.
+	AnnotationPodReplaceResources = PodDomainPrefix + "/replace-resources"
 )
 
 var (
@@ -97,3 +103,27 @@ func SetExtendedResourceSpec(pod *corev1.Pod, spec *ExtendedResourceSpec) error
 	pod.Annotations[AnnotationExtendedResourceSpec] = string(data)
 	return nil
 }
+
+// GetPodReplaceResourcesConfig parses replace and erase resource names from pod annotations.
+// Annotation format: "resourceA:resourceB,resourceC:resourceD,resourceE:"
+// means replace resourceA with resourceB, replace resourceC with resourceD, erase resourceE
+func GetPodReplaceResourcesConfig(pod *corev1.Pod) (eraseNames []corev1.ResourceName,
+	replaceMappings map[corev1.ResourceName]corev1.ResourceName) {
+	if v, ok := pod.Annotations[AnnotationPodReplaceResources]; ok && v != "" {
+		mappings := strings.Split(v, ",")
+		replaceMappings = make(map[corev1.ResourceName]corev1.ResourceName)
+		for _, mapping := range mappings {
+			parts := strings.Split(mapping, ":")
+			if len(parts) != 2 {
+				continue
+			}
+			from, to := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
+			if to == "" {
+				eraseNames = append(eraseNames, corev1.ResourceName(from))
+			} else {
+				replaceMappings[corev1.ResourceName(from)] = corev1.ResourceName(to)
+			}
+		}
+	}
+	return
+}
diff --git a/go.mod b/go.mod
index e12add3c..e7b0febe 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
 	github.com/google/renameio v0.1.0
 	github.com/google/uuid v1.3.0
 	github.com/hodgesds/perf-utils v0.7.0
-	github.com/jaypipes/ghw v0.12.0
+	github.com/jaypipes/ghw v0.20.0
 	github.com/jedib0t/go-pretty/v6 v6.4.0
 	github.com/k8stopologyawareschedwg/noderesourcetopology-api v0.1.1
 	github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb
@@ -38,8 +38,8 @@ require (
 	github.com/prometheus/client_golang v1.16.0
 	github.com/prometheus/client_model v0.4.0
 	github.com/prometheus/prometheus v0.0.0-00010101000000-000000000000
-	github.com/spf13/cobra v1.7.0
-	github.com/spf13/pflag v1.0.5
+	github.com/spf13/cobra v1.9.1
+	github.com/spf13/pflag v1.0.6
 	github.com/stretchr/testify v1.8.4
 	github.com/urfave/cli/v2 v2.27.7
 	github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
@@ -60,6 +60,7 @@ require (
 	k8s.io/component-base v0.28.7
 	k8s.io/component-helpers v0.28.7
 	k8s.io/cri-api v0.28.7
+	k8s.io/gengo v0.0.0-20220902162205-c0856e24416d
 	k8s.io/klog/v2 v2.100.1
 	k8s.io/kube-scheduler v0.28.7
 	k8s.io/kubectl v0.28.7
@@ -92,7 +93,6 @@ require (
 	github.com/Microsoft/go-winio v0.6.0 // indirect
 	github.com/Microsoft/hcsshim v0.9.4 // indirect
 	github.com/NYTimes/gziphandler v1.1.1 // indirect
-	github.com/StackExchange/wmi v1.2.1 // indirect
 	github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
 	github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
 	github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e // indirect
@@ -125,7 +125,6 @@ require (
 	github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect
 	github.com/evanphx/json-patch/v5 v5.6.0 // indirect
 	github.com/felixge/httpsnoop v1.0.3 // indirect
-	github.com/ghodss/yaml v1.0.0 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
 	github.com/go-logfmt/logfmt v0.5.1 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
@@ -154,7 +153,7 @@ require (
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect
 	github.com/imdario/mergo v0.3.12 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
-	github.com/jaypipes/pcidb v1.0.0 // indirect
+	github.com/jaypipes/pcidb v1.1.1 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/jpillora/backoff v1.0.0 // indirect
@@ -169,7 +168,6 @@ require (
 	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
 	github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible // indirect
-	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/moby/ipvs v1.1.0 // indirect
 	github.com/moby/spdystream v0.2.0 // indirect
 	github.com/moby/sys/mountinfo v0.6.2 // indirect
@@ -205,6 +203,7 @@ require (
 	github.com/vishvananda/netns v0.0.4 // indirect
 	github.com/vmware/govmomi v0.30.6 // indirect
 	github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
+	github.com/yusufpapurcu/wmi v1.2.4 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.9 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
 	go.etcd.io/etcd/client/v3 v3.5.9 // indirect
@@ -241,13 +240,12 @@ require (
 	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
 	gopkg.in/warnings.v0 v0.1.2 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	howett.net/plist v1.0.0 // indirect
+	howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 // indirect
 	k8s.io/apiextensions-apiserver v0.28.3 // indirect
 	k8s.io/cloud-provider v0.28.7 // indirect
 	k8s.io/controller-manager v0.28.7 // indirect
 	k8s.io/csi-translation-lib v0.28.7 // indirect
 	k8s.io/dynamic-resource-allocation v0.28.7 // indirect
-	k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect
 	k8s.io/kms v0.28.7 // indirect
 	k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
 	k8s.io/legacy-cloud-providers v0.0.0 // indirect
diff --git a/go.sum b/go.sum
index 84644871..8c1cf6be 100644
--- a/go.sum
+++ b/go.sum
@@ -266,8 +266,6 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq
 github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
-github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
-github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
 github.com/a8m/tree v0.0.0-20210115125333-10a5fd5b637d/go.mod h1:FSdwKX97koS5efgm8WevNf7XS3PqtyFkKDDXrz778cg=
 github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
 github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
@@ -501,6 +499,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
 github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
 github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -598,7 +597,6 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS
 github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
 github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
 github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
-github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
@@ -634,7 +632,6 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
 github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
 github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo=
 github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA=
-github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
 github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -889,10 +886,10 @@ github.com/ionos-cloud/sdk-go/v6 v6.1.3 h1:vb6yqdpiqaytvreM0bsn2pXw+1YDvEk2RKSmB
 github.com/ionos-cloud/sdk-go/v6 v6.1.3/go.mod h1:Ox3W0iiEz0GHnfY9e5LmAxwklsxguuNFEUSu0gVRTME=
 github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8=
 github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
-github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho=
-github.com/jaypipes/ghw v0.12.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g=
-github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
-github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
+github.com/jaypipes/ghw v0.20.0 h1:8efvHHtyrj0P4qVZ9KE43iW9tMThKoh6dEOo38f3a4w=
+github.com/jaypipes/ghw v0.20.0/go.mod h1:GPrvwbtPoxYUenr74+nAnWbardIZq600vJDD5HnPsPE=
+github.com/jaypipes/pcidb v1.1.1 h1:QmPhpsbmmnCwZmHeYAATxEaoRuiMAJusKYkUncMC0ro=
+github.com/jaypipes/pcidb v1.1.1/go.mod h1:x27LT2krrUgjf875KxQXKB0Ha/YXLdZRVmw6hH0G7g8=
 github.com/jedib0t/go-pretty/v6 v6.4.0 h1:YlI/2zYDrweA4MThiYMKtGRfT+2qZOO65ulej8GTcVI=
 github.com/jedib0t/go-pretty/v6 v6.4.0/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@@ -1281,13 +1278,15 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3
 github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
 github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
 github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
 github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
@@ -1371,6 +1370,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
+github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
 github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
 github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
 github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
@@ -1923,7 +1924,6 @@ gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
-gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1948,8 +1948,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
-howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
-howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
+howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 h1:eeH1AIcPvSc0Z25ThsYF+Xoqbn0CI/YnXVYoTLFdGQw=
+howett.net/plist v1.0.2-0.20250314012144-ee69052608d9/go.mod h1:fyFX5Hj5tP1Mpk8obqA9MZgXT416Q5711SDT7dQLTLk=
 k8s.io/api v0.28.7 h1:YKIhBxjXKaxuxWJnwohV0aGjRA5l4IU0Eywf/q19AVI=
 k8s.io/api v0.28.7/go.mod h1:y4RbcjCCMff1930SG/TcP3AUKNfaJUgIeUp58e/2vyY=
 k8s.io/apiextensions-apiserver v0.28.7 h1:NQlzP/vmvIO9Qt7wQTdMe9sGWGkozQZMPk9suehAvR8=
diff --git a/pkg/device-daemon/resource/mlu.go b/pkg/device-daemon/resource/mlu.go
index e71888c7..0d734698 100644
--- a/pkg/device-daemon/resource/mlu.go
+++ b/pkg/device-daemon/resource/mlu.go
@@ -53,7 +53,7 @@ func (manager *mluManager) GetDevices() ([]Device, error) {
 	if err != nil {
 		return nil, fmt.Errorf("getMLUDevice(): new PCI instance error, %v", err)
 	}
-	devices := pci.ListDevices()
+	devices := pci.Devices
 	if len(devices) == 0 {
 		klog.Info("getMLUDevice(): no pci devices")
 		return nil, nil
diff --git a/pkg/device-daemon/resource/npu.go b/pkg/device-daemon/resource/npu.go
index c0262884..7e4e9cda 100644
--- a/pkg/device-daemon/resource/npu.go
+++ b/pkg/device-daemon/resource/npu.go
@@ -51,7 +51,7 @@ func (manager *npuManager) GetDevices() ([]Device, error) {
 	if err != nil {
 		return nil, fmt.Errorf("getXPUDevice(): new PCI instance error, %v", err)
 	}
-	devices := pci.ListDevices()
+	devices := pci.Devices
 	if len(devices) == 0 {
 		klog.Info("getNPUDevice(): no pci devices")
 		return nil, nil
diff --git a/pkg/device-daemon/resource/xpu.go b/pkg/device-daemon/resource/xpu.go
index afb00d69..eab46e92 100644
--- a/pkg/device-daemon/resource/xpu.go
+++ b/pkg/device-daemon/resource/xpu.go
@@ -51,7 +51,7 @@ func (manager *xpuManager) GetDevices() ([]Device, error) {
 	if err != nil {
 		return nil, fmt.Errorf("getXPUDevice(): new PCI instance error, %v", err)
 	}
-	devices := pci.ListDevices()
+	devices := pci.Devices
 	if len(devices) == 0 {
 		klog.Info("getXPUDevice(): no pci devices")
 		return nil, nil
diff --git a/pkg/features/features.go b/pkg/features/features.go
index ad054afd..56689990 100644
--- a/pkg/features/features.go
+++ b/pkg/features/features.go
@@ -51,6 +51,9 @@ const (
 	// ColocationProfileSkipMutatingResources config whether to update resourceName according to priority by default
 	ColocationProfileSkipMutatingResources featuregate.Feature = "ColocationProfileSkipMutatingResources"
 
+	// ColocationProfileSkipValidatingPriority config whether to validate label priority
+	ColocationProfileSkipValidatingPriority featuregate.Feature = "ColocationProfileSkipValidatingPriority"
+
 	// WebhookFramework enables webhook framework, global feature-gate for webhook
 	WebhookFramework featuregate.Feature = "WebhookFramework"
 
@@ -76,6 +79,9 @@ const (
 	// when add resource type: from parent to child
 	ElasticQuotaEnableUpdateResourceKey featuregate.Feature = "ElasticQuotaEnableUpdateResourceKey"
 
+	// ElasticQuotaEvaluationTransformPod enables transforming pod before evaluating quota
+	ElasticQuotaEvaluationTransformPod featuregate.Feature = "ElasticQuotaEvaluationTransformPod"
+
 	// DisableDefaultQuota disable default quota.
 	DisableDefaultQuota featuregate.Feature = "DisableDefaultQuota"
 
@@ -99,27 +105,29 @@ const (
 )
 
 var defaultFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
-	PodMutatingWebhook:                     {Default: true, PreRelease: featuregate.Beta},
-	PodValidatingWebhook:                   {Default: true, PreRelease: featuregate.Beta},
-	ElasticQuotaMutatingWebhook:            {Default: true, PreRelease: featuregate.Beta},
-	ElasticQuotaValidatingWebhook:          {Default: true, PreRelease: featuregate.Beta},
-	NodeMutatingWebhook:                    {Default: false, PreRelease: featuregate.Alpha},
-	NodeValidatingWebhook:                  {Default: false, PreRelease: featuregate.Alpha},
-	ConfigMapValidatingWebhook:             {Default: false, PreRelease: featuregate.Alpha},
-	ReservationMutatingWebhook:             {Default: false, PreRelease: featuregate.Alpha},
-	WebhookFramework:                       {Default: true, PreRelease: featuregate.Beta},
-	ColocationProfileSkipMutatingResources: {Default: false, PreRelease: featuregate.Alpha},
-	MultiQuotaTree:                         {Default: false, PreRelease: featuregate.Alpha},
-	ElasticQuotaIgnorePodOverhead:          {Default: false, PreRelease: featuregate.Alpha},
-	ElasticQuotaGuaranteeUsage:             {Default: false, PreRelease: featuregate.Alpha},
-	ElasticQuotaEnableUpdateResourceKey:    {Default: false, PreRelease: featuregate.Alpha},
-	DisableDefaultQuota:                    {Default: false, PreRelease: featuregate.Alpha},
-	SupportParentQuotaSubmitPod:            {Default: false, PreRelease: featuregate.Alpha},
-	EnableQuotaAdmission:                   {Default: false, PreRelease: featuregate.Alpha},
-	EnableSyncGPUSharedResource:            {Default: false, PreRelease: featuregate.Alpha},
-	ColocationProfileController:            {Default: false, PreRelease: featuregate.Alpha},
-	ValidatePodDeviceResource:              {Default: false, PreRelease: featuregate.Alpha},
-	EnablePodEnhancedValidator:             {Default: false, PreRelease: featuregate.Alpha},
+	PodMutatingWebhook:                      {Default: true, PreRelease: featuregate.Beta},
+	PodValidatingWebhook:                    {Default: true, PreRelease: featuregate.Beta},
+	ElasticQuotaMutatingWebhook:             {Default: true, PreRelease: featuregate.Beta},
+	ElasticQuotaValidatingWebhook:           {Default: true, PreRelease: featuregate.Beta},
+	NodeMutatingWebhook:                     {Default: false, PreRelease: featuregate.Alpha},
+	NodeValidatingWebhook:                   {Default: false, PreRelease: featuregate.Alpha},
+	ConfigMapValidatingWebhook:              {Default: false, PreRelease: featuregate.Alpha},
+	ReservationMutatingWebhook:              {Default: false, PreRelease: featuregate.Alpha},
+	WebhookFramework:                        {Default: true, PreRelease: featuregate.Beta},
+	ColocationProfileSkipMutatingResources:  {Default: false, PreRelease: featuregate.Alpha},
+	ColocationProfileSkipValidatingPriority: {Default: false, PreRelease: featuregate.Alpha},
+	MultiQuotaTree:                          {Default: false, PreRelease: featuregate.Alpha},
+	ElasticQuotaIgnorePodOverhead:           {Default: false, PreRelease: featuregate.Alpha},
+	ElasticQuotaGuaranteeUsage:              {Default: false, PreRelease: featuregate.Alpha},
+	ElasticQuotaEnableUpdateResourceKey:     {Default: false, PreRelease: featuregate.Alpha},
+	ElasticQuotaEvaluationTransformPod:      {Default: false, PreRelease: featuregate.Alpha},
+	DisableDefaultQuota:                     {Default: false, PreRelease: featuregate.Alpha},
+	SupportParentQuotaSubmitPod:             {Default: false, PreRelease: featuregate.Alpha},
+	EnableQuotaAdmission:                    {Default: false, PreRelease: featuregate.Alpha},
+	EnableSyncGPUSharedResource:             {Default: false, PreRelease: featuregate.Alpha},
+	ColocationProfileController:             {Default: false, PreRelease: featuregate.Alpha},
+	ValidatePodDeviceResource:               {Default: false, PreRelease: featuregate.Alpha},
+	EnablePodEnhancedValidator:              {Default: false, PreRelease: featuregate.Alpha},
 }
 
 const (
@@ -137,11 +145,15 @@ const (
 	// PreemptionPolicyTransformer is used to take over the pod preemption policy with the specified label.
 	// If a pod does not set a preemptionPolicy, it will be mapped to the DefaultPreemptionPolicy.
 	PreemptionPolicyTransformer featuregate.Feature = "PreemptionPolicyTransformer"
+	// ReplaceResourcesTransformer is used to replace resource or erase specified resource names.
+	// Note: The usage scenarios must ensure that the resources on the node are not oversold by itself.
+	ReplaceResourcesTransformer featuregate.Feature = "ReplaceResourcesTransformer"
 )
 
 var transformerFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
 	PriorityTransformer:         {Default: false, PreRelease: featuregate.Alpha},
 	PreemptionPolicyTransformer: {Default: false, PreRelease: featuregate.Alpha},
+	ReplaceResourcesTransformer: {Default: false, PreRelease: featuregate.Alpha},
 }
 
 func init() {
diff --git a/pkg/koordlet/metricsadvisor/devices/gpu/collector_gpu_linux.go b/pkg/koordlet/metricsadvisor/devices/gpu/collector_gpu_linux.go
index 063bab3a..7013a2f0 100644
--- a/pkg/koordlet/metricsadvisor/devices/gpu/collector_gpu_linux.go
+++ b/pkg/koordlet/metricsadvisor/devices/gpu/collector_gpu_linux.go
@@ -20,7 +20,6 @@ import (
 	"errors"
 	"fmt"
 	"sort"
-	"strings"
 	"sync"
 	"time"
 
@@ -33,6 +32,7 @@ import (
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/metriccache"
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/metricsadvisor/devices/helper"
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/util"
+	"github.com/koordinator-sh/koordinator/pkg/koordlet/util/system"
 )
 
 type gpuDeviceManager struct {
@@ -91,18 +91,16 @@ func (g *gpuDeviceManager) shutdown() error {
 }
 
 func (g *gpuDeviceManager) initGPUData() error {
-	count, ret := nvml.DeviceGetCount()
-	if ret != nvml.SUCCESS {
-		return fmt.Errorf("unable to get device count: %v", nvml.ErrorString(ret))
-	}
+	pciBusIDs := system.GetGPUDevicePCIBusIDs()
+	count := len(pciBusIDs)
 	if count == 0 {
 		return errors.New("no gpu device found")
 	}
 	devices := make([]*device, count)
-	for deviceIndex := 0; deviceIndex < count; deviceIndex++ {
-		gpudevice, ret := nvml.DeviceGetHandleByIndex(deviceIndex)
+	for _, busID := range pciBusIDs {
+		gpudevice, ret := nvml.DeviceGetHandleByPciBusId(busID)
 		if ret != nvml.SUCCESS {
-			return fmt.Errorf("unable to get device at index %d: %v", deviceIndex, nvml.ErrorString(ret))
+			return fmt.Errorf("unable to get device at pciBusID %s: %v", busID, nvml.ErrorString(ret))
 		}
 
 		uuid, ret := gpudevice.GetUUID()
@@ -119,17 +117,12 @@ func (g *gpuDeviceManager) initGPUData() error {
 		if ret != nvml.SUCCESS {
 			return fmt.Errorf("unable to get device memory info: %v", nvml.ErrorString(ret))
 		}
-		pciInfo, ret := gpudevice.GetPciInfo()
+
+		deviceIndex, ret := gpudevice.GetIndex()
 		if ret != nvml.SUCCESS {
-			return fmt.Errorf("unable to get pci info: %v", nvml.ErrorString(ret))
+			return fmt.Errorf("unable to get device index: %v", nvml.ErrorString(ret))
 		}
-		busIDBuilder := &strings.Builder{}
-		for _, v := range pciInfo.BusIdLegacy {
-			if v != 0 {
-				busIDBuilder.WriteByte(byte(v))
-			}
-		}
-		busID := strings.ToLower(busIDBuilder.String())
+
 		nodeID, pcie, busID, err := helper.ParsePCIInfo(busID)
 		if err != nil {
 			return err
diff --git a/pkg/koordlet/metricsadvisor/devices/rdma/collector_rdma_linux.go b/pkg/koordlet/metricsadvisor/devices/rdma/collector_rdma_linux.go
index 47f8667b..cc1f4303 100644
--- a/pkg/koordlet/metricsadvisor/devices/rdma/collector_rdma_linux.go
+++ b/pkg/koordlet/metricsadvisor/devices/rdma/collector_rdma_linux.go
@@ -36,7 +36,7 @@ func GetNetDevice() (metriccache.Devices, error) {
 	if err != nil {
 		return nil, fmt.Errorf("getNetDevice(): new PCI instance error, %v", err)
 	}
-	devices := pci.ListDevices()
+	devices := pci.Devices
 	if len(devices) == 0 {
 		klog.Warningf("getNetDevice(): no pci devices")
 		return nil, nil
diff --git a/pkg/koordlet/qosmanager/plugins/cpuevict/cpu_evict.go b/pkg/koordlet/qosmanager/plugins/cpuevict/cpu_evict.go
index c8778a88..38f9488d 100644
--- a/pkg/koordlet/qosmanager/plugins/cpuevict/cpu_evict.go
+++ b/pkg/koordlet/qosmanager/plugins/cpuevict/cpu_evict.go
@@ -427,7 +427,7 @@ func (c *cpuEvictor) getPodEvictInfoAndSortByPriority(thresholdConfig *slov1alph
 			continue
 		}
 		// 3. sort :  koordinator.sh/priority
-		podPriority := qosmanagerUtil.GetPodPriorityLabel(pod)
+		podPriority := qosmanagerUtil.GetPodPriorityLabel(pod, int64(podInfo.Priority))
 		podInfo.LabelPriority = podPriority
 		// 4. filter no metrics
 		queryMeta, err := metriccache.PodCPUUsageMetric.BuildQueryMeta(metriccache.MetricPropertiesFunc.Pod(string(pod.UID)))
diff --git a/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress.go b/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress.go
index bb5d0e1d..16a978ee 100644
--- a/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress.go
+++ b/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress.go
@@ -54,6 +54,7 @@ const (
 	beMinCPUSetCores        = 2
 	beMinQuota              = 2000
 	beMaxIncreaseCPUPercent = 0.1 // scale up slow
+	beUnsetQuota            = -1
 )
 
 type suppressPolicyStatus string
@@ -417,7 +418,7 @@ func (r *CPUSuppress) adjustByCPUSet(cpusetQuantity *resource.Quantity, nodeCPUI
 	// - for a enlargement of BE cpuset, it is welcome and costless for BE processes.
 	err = r.applyBESuppressCPUSet(beCPUSet, oldCPUSet)
 	if err != nil {
-		klog.Warningf("suppressBECPU failed to apply be cpu suppress policy, err: %s", err)
+		klog.Warningf("suppressBECPU failed to apply be cpu suppress policy, target cpuset %v, err: %s", beCPUSet, err)
 		return
 	}
 	klog.Infof("suppressBECPU finished, suppress be cpu successfully: current cpuset %v", beCPUSet)
@@ -614,19 +615,19 @@ func (r *CPUSuppress) adjustByCfsQuota(cpuQuantity *resource.Quantity, node *cor
 	}
 
 	beMaxIncreaseCPUQuota := float64(node.Status.Capacity.Cpu().Value()) * float64(system.DefaultCPUCFSPeriod) * beMaxIncreaseCPUPercent
-	if float64(newBeQuota)-float64(currentBeQuota) > beMaxIncreaseCPUQuota {
+	if float64(newBeQuota)-float64(currentBeQuota) > beMaxIncreaseCPUQuota && currentBeQuota != beUnsetQuota { // scale with steps after quota has set
 		newBeQuota = currentBeQuota + int64(beMaxIncreaseCPUQuota)
 	}
 
 	eventHelper := audit.V(3).Node().Reason(resourceexecutor.AdjustBEByNodeCPUUsage).Message("update BE group to cfs_quota: %v", newBeQuota)
 	updater, err := resourceexecutor.DefaultCgroupUpdaterFactory.New(system.CPUCFSQuotaName, beCgroupPath, strconv.FormatInt(newBeQuota, 10), eventHelper)
 	if err != nil {
-		klog.V(4).Infof("failed to get be cfs quota updater, err: %v", err)
+		klog.V(4).Infof("failed to get be cfs quota updater, target quota: %d, err: %v", newBeQuota, err)
 		return
 	}
 	isUpdated, err := r.executor.Update(false, updater)
 	if err != nil {
-		klog.Errorf("suppressBECPU: failed to write cfs_quota_us for be pods, error: %v", err)
+		klog.Errorf("suppressBECPU: failed to write cfs_quota_us for be pods, target quota: %d, error: %v", newBeQuota, err)
 		return
 	}
 	metrics.RecordBESuppressCores(string(slov1alpha1.CPUCfsQuotaPolicy), float64(newBeQuota)/float64(system.DefaultCPUCFSPeriod))
diff --git a/pkg/koordlet/qosmanager/plugins/memoryevict/memory_evict.go b/pkg/koordlet/qosmanager/plugins/memoryevict/memory_evict.go
index 24ad7577..5f0e02d5 100644
--- a/pkg/koordlet/qosmanager/plugins/memoryevict/memory_evict.go
+++ b/pkg/koordlet/qosmanager/plugins/memoryevict/memory_evict.go
@@ -304,7 +304,7 @@ func (m *memoryEvictor) getPodEvictInfoAndSortByPriority(thresholdConfig *slov1a
 			continue
 		}
 		// 3. sort :  koordinator.sh/priority
-		podPriority := qosmanagerUtil.GetPodPriorityLabel(pod)
+		podPriority := qosmanagerUtil.GetPodPriorityLabel(pod, int64(podInfo.Priority))
 		podInfo.LabelPriority = podPriority
 		// 4. filter no metrics
 		queryMeta, err := metriccache.PodMemUsageMetric.BuildQueryMeta(metriccache.MetricPropertiesFunc.Pod(string(pod.UID)))
diff --git a/pkg/koordlet/qosmanager/plugins/util/evict.go b/pkg/koordlet/qosmanager/plugins/util/evict.go
index df2cff17..c761d043 100644
--- a/pkg/koordlet/qosmanager/plugins/util/evict.go
+++ b/pkg/koordlet/qosmanager/plugins/util/evict.go
@@ -36,9 +36,7 @@ type ReleaseList map[ReleaseTargetType]corev1.ResourceList
 const (
 	ReleaseTargetTypeBatchResourceRequest ReleaseTargetType = "podBatchResourceRequest"
 	ReleaseTargetTypeResourceUsed         ReleaseTargetType = "podUsed"
-
-	DefaultEvictPriority = 9999
-	EvictedStr           = "evicted"
+	EvictedStr                                              = "evicted"
 )
 
 type PodEvictInfo struct {
@@ -259,16 +257,16 @@ func addReleased(a, b ReleaseList) {
 	}
 }
 
-func GetPodPriorityLabel(pod *corev1.Pod) int64 {
+func GetPodPriorityLabel(pod *corev1.Pod, defaultPriority int64) int64 {
 	if pod == nil || pod.Labels == nil {
-		return DefaultEvictPriority
+		return defaultPriority
 	}
 	if fractionStr, ok := pod.Labels[apiext.LabelPodPriority]; !ok {
-		return DefaultEvictPriority
+		return defaultPriority
 	} else {
 		num, err := strconv.Atoi(fractionStr)
 		if err != nil {
-			return DefaultEvictPriority
+			return defaultPriority
 		}
 		return int64(num)
 	}
diff --git a/pkg/koordlet/runtimehooks/protocol/container_context.go b/pkg/koordlet/runtimehooks/protocol/container_context.go
index 91e082b3..c0707cd2 100644
--- a/pkg/koordlet/runtimehooks/protocol/container_context.go
+++ b/pkg/koordlet/runtimehooks/protocol/container_context.go
@@ -61,7 +61,7 @@ type ContainerRequest struct {
 	PodAnnotations    map[string]string
 	CgroupParent      string
 	ContainerEnvs     map[string]string
-	Resources         *Resources // TODO: support proxy & nri mode
+	Resources         *Resources // supports proxy, reconciler & nri mode
 	ExtendedResources *apiext.ExtendedResourceContainerSpec
 }
 
@@ -92,6 +92,14 @@ func (c *ContainerRequest) FromNri(pod *api.PodSandbox, container *api.Container
 	}
 	c.ContainerEnvs = envs
 
+	// extract Resources from NRI container
+	if linux := container.GetLinux(); linux != nil {
+		if containerResources := linux.GetResources(); containerResources != nil {
+			c.Resources = &Resources{}
+			c.Resources.FromNriLinuxResources(containerResources)
+		}
+	}
+
 	spec, err := apiext.GetExtendedResourceSpec(pod.GetAnnotations())
 	if err != nil {
 		klog.V(4).Infof("failed to get ExtendedResourceSpec from nri via annotation, container %s/%s, name: %s, err: %s",
@@ -111,6 +119,11 @@ func (c *ContainerRequest) FromProxy(req *runtimeapi.ContainerResourceHookReques
 	c.PodAnnotations = req.GetPodAnnotations()
 	c.CgroupParent, _ = koordletutil.GetContainerCgroupParentDirByID(req.GetPodCgroupParent(), c.ContainerMeta.ID)
 	c.ContainerEnvs = req.GetContainerEnvs()
+	// extract Resources from proxy request
+	if req.GetContainerResources() != nil {
+		c.Resources = &Resources{}
+		c.Resources.FromLinuxContainerResources(req.GetContainerResources())
+	}
 	// retrieve ExtendedResources from pod annotations
 	spec, err := apiext.GetExtendedResourceSpec(req.GetPodAnnotations())
 	if err != nil {
diff --git a/pkg/koordlet/runtimehooks/protocol/protocol.go b/pkg/koordlet/runtimehooks/protocol/protocol.go
index 845a6ebc..2524f5a1 100644
--- a/pkg/koordlet/runtimehooks/protocol/protocol.go
+++ b/pkg/koordlet/runtimehooks/protocol/protocol.go
@@ -19,10 +19,12 @@ package protocol
 import (
 	"strconv"
 
+	"github.com/containerd/nri/pkg/api"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/client-go/tools/record"
 	"k8s.io/kubernetes/pkg/api/v1/resource"
 
+	runtimeapi "github.com/koordinator-sh/koordinator/apis/runtime/v1alpha1"
 	slov1alpha1 "github.com/koordinator-sh/koordinator/apis/slo/v1alpha1"
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/audit"
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/resourceexecutor"
@@ -135,6 +137,64 @@ func (r *Resources) FromContainer(container *corev1.Container) {
 	}
 }
 
+// FromLinuxContainerResources extracts resource information from LinuxContainerResources
+func (r *Resources) FromLinuxContainerResources(resources *runtimeapi.LinuxContainerResources) {
+	if resources == nil {
+		return
+	}
+	if resources.CpuShares != 0 {
+		cpuShares := resources.CpuShares
+		r.CPUShares = &cpuShares
+	}
+	if resources.CpuQuota != 0 {
+		cfsQuota := resources.CpuQuota
+		r.CFSQuota = &cfsQuota
+	}
+	// MemoryLimitInBytes: 0 means not specified, negative values mean unlimited (-1)
+	if resources.MemoryLimitInBytes != 0 {
+		memoryLimit := resources.MemoryLimitInBytes
+		if memoryLimit < 0 {
+			memoryLimit = -1
+		}
+		r.MemoryLimit = &memoryLimit
+	}
+	if resources.CpusetCpus != "" {
+		cpusetCpus := resources.CpusetCpus
+		r.CPUSet = &cpusetCpus
+	}
+}
+
+// FromNriLinuxResources extracts resource information from NRI's LinuxResources
+func (r *Resources) FromNriLinuxResources(resources *api.LinuxResources) {
+	if resources == nil {
+		return
+	}
+	// Extract CPU resources
+	if cpu := resources.GetCpu(); cpu != nil {
+		if shares := cpu.GetShares(); shares != nil && shares.Value != 0 {
+			cpuShares := int64(shares.Value)
+			r.CPUShares = &cpuShares
+		}
+		if quota := cpu.GetQuota(); quota != nil && quota.Value != 0 {
+			cfsQuota := quota.Value
+			r.CFSQuota = &cfsQuota
+		}
+		if cpus := cpu.GetCpus(); cpus != "" {
+			r.CPUSet = &cpus
+		}
+	}
+	// Extract Memory resources
+	if memory := resources.GetMemory(); memory != nil {
+		if limit := memory.GetLimit(); limit != nil && limit.Value != 0 {
+			memoryLimit := limit.Value
+			if memoryLimit < 0 {
+				memoryLimit = -1
+			}
+			r.MemoryLimit = &memoryLimit
+		}
+	}
+}
+
 type Mount struct {
 	Destination string   `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`
 	Type        string   `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`
diff --git a/pkg/koordlet/statesinformer/impl/states_device_linux.go b/pkg/koordlet/statesinformer/impl/states_device_linux.go
index ce746a43..c867a927 100644
--- a/pkg/koordlet/statesinformer/impl/states_device_linux.go
+++ b/pkg/koordlet/statesinformer/impl/states_device_linux.go
@@ -39,6 +39,7 @@ import (
 	schedulingv1alpha1 "github.com/koordinator-sh/koordinator/apis/scheduling/v1alpha1"
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/metriccache"
 	koordletuti "github.com/koordinator-sh/koordinator/pkg/koordlet/util"
+	"github.com/koordinator-sh/koordinator/pkg/koordlet/util/system"
 	"github.com/koordinator-sh/koordinator/pkg/util"
 )
 
@@ -231,8 +232,13 @@ func (s *statesInformer) buildGPUDevice() []schedulingv1alpha1.DeviceInfo {
 		gpu := gpus[idx]
 		health := true
 		s.gpuMutex.RLock()
-		if _, ok := s.unhealthyGPU[gpu.UUID]; ok {
+		if unhealthyInfo, ok := s.unhealthyGPU[gpu.BusID]; ok {
 			health = false
+			gpu.Status = &koordletuti.DeviceStatus{
+				Healthy:    false,
+				ErrCode:    unhealthyInfo.errCode,
+				ErrMessage: unhealthyInfo.errMessage,
+			}
 		}
 		s.gpuMutex.RUnlock()
 
@@ -256,7 +262,8 @@ func (s *statesInformer) buildGPUDevice() []schedulingv1alpha1.DeviceInfo {
 				extension.ResourceGPUMemory:      *resource.NewQuantity(int64(gpu.MemoryTotal), resource.BinarySI),
 				extension.ResourceGPUMemoryRatio: *resource.NewQuantity(100, resource.DecimalSI),
 			},
-			Topology: topology,
+			Topology:   topology,
+			Conditions: getGPUDeviceConditions(&gpu),
 		})
 	}
 	return deviceInfos
@@ -437,42 +444,41 @@ func (s *statesInformer) getGPUDriverAndModel() (string, string) {
 }
 
 func (s *statesInformer) gpuHealCheck(stopCh <-chan struct{}) {
-	count, ret := nvml.DeviceGetCount()
-	if ret != nvml.SUCCESS {
-		klog.Errorf("unable to get device count: %v", nvml.ErrorString(ret))
-		return
-	}
-	if count == 0 {
+	pciBusIDs := system.GetGPUDevicePCIBusIDs()
+	if len(pciBusIDs) == 0 {
 		klog.Errorf("no gpu device found")
 		return
 	}
-	devices := []string{}
-	for deviceIndex := 0; deviceIndex < count; deviceIndex++ {
-		gpudevice, ret := nvml.DeviceGetHandleByIndex(deviceIndex)
-		if ret != nvml.SUCCESS {
-			klog.Errorf("unable to get device at index %d: %v", deviceIndex, nvml.ErrorString(ret))
-			continue
-		}
-		uuid, ret := gpudevice.GetUUID()
-		if ret != nvml.SUCCESS {
-			klog.Errorf("failed to get device uuid at index %d, err: %v", deviceIndex, nvml.ErrorString(ret))
-		}
-		devices = append(devices, uuid)
-	}
-	unhealthyChan := make(chan string)
-	go checkHealth(stopCh, devices, unhealthyChan)
+	unhealthyChan := make(chan gpuHealthEvent)
+	go checkHealth(stopCh, pciBusIDs, unhealthyChan)
 	klog.Info("start to do gpu health check")
-	for d := range unhealthyChan {
+	for event := range unhealthyChan {
 		// FIXME: there is no way to recover from the Unhealthy state.
 		s.gpuMutex.Lock()
-		s.unhealthyGPU[d] = struct{}{}
+		if event.xidError == 0 {
+			s.unhealthyGPU[event.pciBusID] = &unhealthyGPUInfo{
+				errCode:    "DeviceHealthCheckNotSupported",
+				errMessage: event.errMessage,
+			}
+		} else {
+			s.unhealthyGPU[event.pciBusID] = &unhealthyGPUInfo{
+				errCode:    fmt.Sprintf("Xid%d", event.xidError),
+				errMessage: event.errMessage,
+			}
+		}
 		s.gpuMutex.Unlock()
-		klog.Infof("get a unhealthy gpu %s", d)
+		klog.Infof("get a unhealthy gpu %s, error: %s", event.pciBusID, event.errMessage)
 	}
 }
 
 // check status of gpus, and send unhealthy devices to the unhealthyDeviceChan channel
-func checkHealth(stopCh <-chan struct{}, devs []string, xids chan<- string) {
+type gpuHealthEvent struct {
+	pciBusID   string
+	xidError   uint64
+	errMessage string
+}
+
+func checkHealth(stopCh <-chan struct{}, devs []string, xids chan<- gpuHealthEvent) {
 	eventSet, ret := nvml.EventSetCreate()
 	if ret != nvml.SUCCESS {
 		klog.Errorf("failed to create event set, err: %v", nvml.ErrorString(ret))
@@ -481,7 +487,7 @@ func checkHealth(stopCh <-chan struct{}, devs []string, xids chan<- string) {
 	defer eventSet.Free()
 
 	for _, d := range devs {
-		device, ret := nvml.DeviceGetHandleByUUID(d)
+		device, ret := nvml.DeviceGetHandleByPciBusId(d)
 		if ret != nvml.SUCCESS {
 			klog.Errorf("failed to get device %s, err: %v", d, nvml.ErrorString(ret))
 			continue
@@ -489,7 +495,10 @@ func checkHealth(stopCh <-chan struct{}, devs []string, xids chan<- string) {
 		ret = nvml.DeviceRegisterEvents(device, nvml.EventTypeXidCriticalError, eventSet)
 		if ret == nvml.ERROR_NOT_SUPPORTED {
 			klog.Infof("Warning: %s is too old to support healthchecking: %v. Marking it unhealthy.", d, nvml.ErrorString(ret))
-			xids <- d
+			xids <- gpuHealthEvent{
+				pciBusID:   d,
+				errMessage: "device does not support health checking",
+			}
 			continue
 		}
 
@@ -517,6 +526,19 @@ func checkHealth(stopCh <-chan struct{}, devs []string, xids chan<- string) {
 			continue
 		}
 
+		pciInfo, ret := e.Device.GetPciInfo()
+		if ret != nvml.SUCCESS {
+			klog.Errorf("failed to get pci info of device %s, err: %v", e.ComputeInstanceId, nvml.ErrorString(ret))
+			continue
+		}
+		busIDBuilder := &strings.Builder{}
+		for _, v := range pciInfo.BusIdLegacy {
+			if v != 0 {
+				busIDBuilder.WriteByte(byte(v))
+			}
+		}
+		busID := strings.ToLower(busIDBuilder.String())
+
 		uuid, ret := e.Device.GetUUID()
 		if ret != nvml.SUCCESS {
 			klog.Errorf("failed to get uuid of device %s, err: %v", e.ComputeInstanceId, nvml.ErrorString(ret))
@@ -526,14 +548,32 @@ func checkHealth(stopCh <-chan struct{}, devs []string, xids chan<- string) {
 		if len(uuid) == 0 {
 			// All devices are unhealthy
 			for _, d := range devs {
-				xids <- d
+				xids <- gpuHealthEvent{
+					pciBusID:   d,
+					xidError:   e.EventData,
+					errMessage: fmt.Sprintf("Xid error detected on device, error code: %d", e.EventData),
+				}
 			}
 			continue
 		}
 
 		for _, d := range devs {
-			if d == uuid {
-				xids <- d
+			if d == busID {
+				xids <- gpuHealthEvent{
+					pciBusID:   d,
+					xidError:   e.EventData,
+					errMessage: fmt.Sprintf("Xid error detected on device, error code: %d", e.EventData),
+				}
+			}
+			// check if device still exists
+			_, ret := nvml.DeviceGetHandleByPciBusId(d)
+			if ret != nvml.SUCCESS {
+				klog.Errorf("failed to get device %s in gpu check, err: %v", d, nvml.ErrorString(ret))
+				xids <- gpuHealthEvent{
+					pciBusID:   d,
+					xidError:   e.EventData,
+					errMessage: fmt.Sprintf("failed to get device, error: %s", nvml.ErrorString(ret)),
+				}
 			}
 		}
 	}
@@ -663,6 +703,36 @@ func getXPUDeviceTopology(xpu *koordletuti.XPUDeviceInfo) *schedulingv1alpha1.De
 	}
 }
 
+func getGPUDeviceConditions(gpu *koordletuti.GPUDeviceInfo) []metav1.Condition {
+	if gpu == nil || gpu.Status == nil {
+		return nil
+	}
+
+	conditions := []metav1.Condition{
+		{
+			Type:               string(schedulingv1alpha1.DeviceConditionHealthy),
+			Status:             metav1.ConditionTrue,
+			LastTransitionTime: metav1.Now(),
+			Reason:             "DeviceHealthy",
+			Message:            "device is healthy",
+		},
+	}
+
+	if !gpu.Status.Healthy {
+		conditions[0].Status = metav1.ConditionFalse
+		conditions[0].Reason = "Unknown"
+		if gpu.Status.ErrCode != "" {
+			conditions[0].Reason = gpu.Status.ErrCode
+		}
+		conditions[0].Message = "device is unhealthy"
+		if gpu.Status.ErrMessage != "" {
+			conditions[0].Message = gpu.Status.ErrMessage
+		}
+	}
+
+	return conditions
+}
+
 func getXPUDeviceConditions(xpu *koordletuti.XPUDeviceInfo) []metav1.Condition {
 	if xpu == nil || xpu.Status == nil {
 		return nil
diff --git a/pkg/koordlet/statesinformer/impl/states_informer.go b/pkg/koordlet/statesinformer/impl/states_informer.go
index b17450e8..b0e7f205 100644
--- a/pkg/koordlet/statesinformer/impl/states_informer.go
+++ b/pkg/koordlet/statesinformer/impl/states_informer.go
@@ -64,12 +64,17 @@ type PluginState struct {
 
 type GetGPUDriverAndModelFunc func() (string, string)
 
+type unhealthyGPUInfo struct {
+	errCode    string
+	errMessage string
+}
+
 type statesInformer struct {
 	// TODO refactor device as plugin
 	config       *Config
 	metricsCache metriccache.MetricCache
 	deviceClient schedv1alpha1.DeviceInterface
-	unhealthyGPU map[string]struct{}
+	unhealthyGPU map[string]*unhealthyGPUInfo
 	gpuMutex     sync.RWMutex
 
 	option  *PluginOption
@@ -107,7 +112,7 @@ func NewStatesInformer(config *Config, kubeClient clientset.Interface, crdClient
 		config:       config,
 		metricsCache: metricsCache,
 		deviceClient: schedulingClient.Devices(),
-		unhealthyGPU: make(map[string]struct{}),
+		unhealthyGPU: make(map[string]*unhealthyGPUInfo),
 
 		option:  opt,
 		states:  stat,
diff --git a/pkg/koordlet/util/device.go b/pkg/koordlet/util/device.go
index ad6eba5e..c2d07519 100644
--- a/pkg/koordlet/util/device.go
+++ b/pkg/koordlet/util/device.go
@@ -38,11 +38,12 @@ type GPUDeviceInfo struct {
 	// UUID represents the UUID of device
 	UUID string `json:"id,omitempty"`
 	// Minor represents the Minor number of Devices, starting from 0
-	Minor       int32  `json:"minor,omitempty"`
-	MemoryTotal uint64 `json:"memory-total,omitempty"`
-	NodeID      int32  `json:"nodeID"`
-	PCIE        string `json:"pcie,omitempty"`
-	BusID       string `json:"busID,omitempty"`
+	Minor       int32         `json:"minor,omitempty"`
+	MemoryTotal uint64        `json:"memory-total,omitempty"`
+	NodeID      int32         `json:"nodeID"`
+	PCIE        string        `json:"pcie,omitempty"`
+	BusID       string        `json:"busID,omitempty"`
+	Status      *DeviceStatus `json:"status,omitempty"`
 }
 
 type RDMADevices []RDMADeviceInfo
diff --git a/pkg/koordlet/util/system/gpu.go b/pkg/koordlet/util/system/gpu.go
new file mode 100644
index 00000000..6f1909be
--- /dev/null
+++ b/pkg/koordlet/util/system/gpu.go
@@ -0,0 +1,49 @@
+/*
+Copyright 2022 The Koordinator Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package system
+
+import (
+	"os"
+	"regexp"
+	"strings"
+
+	"k8s.io/klog/v2"
+)
+
+var (
+	NVIDIADriverDir = "/sys/bus/pci/drivers/nvidia"
+	pciAddressRegex = regexp.MustCompile(`^((1?[0-9a-f]{0,4}):)?([0-9a-f]{2}):([0-9a-f]{2})\.([0-9a-f]{1})$`)
+)
+
+func GetGPUDevicePCIBusIDs() []string {
+	var pciBusIDs []string
+	entries, err := os.ReadDir(NVIDIADriverDir)
+	if err != nil {
+		klog.Errorf("GetGPUDevicePCIBusIDs: read nvidia driver dir %s error, %v", NVIDIADriverDir, err)
+		return pciBusIDs
+	}
+
+	for _, entry := range entries {
+		fileName := strings.ToLower(entry.Name())
+		matches := pciAddressRegex.FindStringSubmatch(fileName)
+		if len(matches) == 6 {
+			pciBusIDs = append(pciBusIDs, matches[0])
+		}
+	}
+
+	return pciBusIDs
+}
diff --git a/pkg/scheduler/frameworkext/fake.go b/pkg/scheduler/frameworkext/fake.go
index d7af76fe..3600f749 100644
--- a/pkg/scheduler/frameworkext/fake.go
+++ b/pkg/scheduler/frameworkext/fake.go
@@ -194,6 +194,16 @@ func (nm *FakeNominator) RemoveNominatedReservations(pod *corev1.Pod) {
 	}
 }
 
+func (nm *FakeNominator) NominatedReservePodForNode(nodeName string) []*framework.PodInfo {
+	nm.lock.RLock()
+	defer nm.lock.RUnlock()
+	pods := make([]*framework.PodInfo, len(nm.nominatedReservePod[nodeName]))
+	for i := 0; i < len(pods); i++ {
+		pods[i] = nm.nominatedReservePod[nodeName][i].DeepCopy()
+	}
+	return pods
+}
+
 func (nm *FakeNominator) GetNominatedReservation(pod *corev1.Pod, nodeName string) *ReservationInfo {
 	nm.lock.RLock()
 	defer nm.lock.RUnlock()
diff --git a/pkg/scheduler/frameworkext/interface.go b/pkg/scheduler/frameworkext/interface.go
index a5245890..baeb27d9 100644
--- a/pkg/scheduler/frameworkext/interface.go
+++ b/pkg/scheduler/frameworkext/interface.go
@@ -181,6 +181,8 @@ type ReservationNominator interface {
 	// DeleteNominatedReservePod is used to delete the nominated reserve pod.
 	// DEPRECATED: use DeleteNominatedReservePodOrReservation instead.
 	DeleteNominatedReservePod(reservePod *corev1.Pod)
+	// NominatedReservePodForNode returns nominated reserve pods on the given node.
+	NominatedReservePodForNode(nodeName string) []*framework.PodInfo
 	// DeleteNominatedReservePodOrReservation is used to delete the nominated reserve pod or
 	// the nominated reservation for the pod.
 	DeleteNominatedReservePodOrReservation(pod *corev1.Pod)
diff --git a/pkg/scheduler/plugins/coscheduling/core/core.go b/pkg/scheduler/plugins/coscheduling/core/core.go
index ad7182b3..4b7b1ccf 100644
--- a/pkg/scheduler/plugins/coscheduling/core/core.go
+++ b/pkg/scheduler/plugins/coscheduling/core/core.go
@@ -503,6 +503,20 @@ func (pgMgr *PodGroupManager) AllowGangGroup(pod *corev1.Pod, handle framework.H
 
 	gangSlices := gang.getGangGroup()
 
+	if currentBindingMembers := gang.getBindingMembers(); len(currentBindingMembers) <= 0 { // record binding members if it is unset
+		waitingPods := pgMgr.cache.getWaitingPods(gangSlices)
+		memberPods := sets.New[string]()
+		for _, pod := range waitingPods {
+			memberPods.Insert(string(pod.UID))
+		}
+		gang.setBindingMembers(memberPods)
+		klog.V(4).InfoS("AllowGangGroup: record binding members for gang",
+			"pod", klog.KObj(pod), "gang", gang.Name, "gangGroup", gang.GangGroupId, "memberPods", memberPods.Len())
+	} else {
+		klog.V(4).InfoS("AllowGangGroup: binding members already set, skip recording",
+			"pod", klog.KObj(pod), "gang", gang.Name, "gangGroup", gang.GangGroupId, "memberPods", currentBindingMembers.Len())
+	}
+
 	handle.IterateOverWaitingPods(func(waitingPod framework.WaitingPod) {
 		podGangId := util.GetId(waitingPod.GetPod().Namespace, util.GetGangNameByPod(waitingPod.GetPod()))
 		for _, gangIdTmp := range gangSlices {
@@ -513,9 +527,6 @@ func (pgMgr *PodGroupManager) AllowGangGroup(pod *corev1.Pod, handle framework.H
 			}
 		}
 	})
-
-	gang.clearWaitingGang()
-
 }
 
 func (pgMgr *PodGroupManager) GetGangByPod(pod *corev1.Pod) *Gang {
@@ -574,9 +585,23 @@ func (pgMgr *PodGroupManager) GetGangBindingInfo(pod *corev1.Pod) *GangBindingIn
 	if gang == nil {
 		return nil
 	}
-	memberCount := pgMgr.cache.getWaitingPodsNum(gang.GangGroup)
+
+	// Get the snapshot members from GangGroupInfo.
+	// This value was set in AllowGangGroup and persists through binding cycle.
+	memberPods := gang.getBindingMembers()
+	if memberPods.Len() <= 1 { // skip gang binding info when no member pods or single pod
+		klog.V(4).InfoS("Skip gang binding info due to the size of memberPods no larger than 1 (OnceSatisfied or failover)",
+			"pod", klog.KObj(pod), "gangGroup", gang.GangGroupId, "memberPods", memberPods.Len())
+		return nil
+	}
+	if !memberPods.Has(string(pod.UID)) { // only record binding info for member pods
+		klog.V(4).InfoS("Skip gang binding info due to pod not in memberPods",
+			"pod", klog.KObj(pod), "gangGroup", gang.GangGroupId, "memberPods", memberPods.Len())
+		return nil
+	}
+
 	return &GangBindingInfo{
 		GangGroupId: gang.GangGroupId,
-		MemberCount: memberCount,
+		MemberCount: memberPods.Len(),
 	}
 }
diff --git a/pkg/scheduler/plugins/coscheduling/core/gang.go b/pkg/scheduler/plugins/coscheduling/core/gang.go
index fc30046b..cabb7b3b 100644
--- a/pkg/scheduler/plugins/coscheduling/core/gang.go
+++ b/pkg/scheduler/plugins/coscheduling/core/gang.go
@@ -22,6 +22,7 @@ import (
 	"time"
 
 	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/util/sets"
 	"k8s.io/klog/v2"
 
 	"github.com/koordinator-sh/koordinator/apis/extension"
@@ -523,6 +524,18 @@ func (gang *Gang) removeWaitingGang() {
 	gang.GangGroupInfo.RemoveWaitingGang(gang.Name)
 }
 
+func (gang *Gang) setBindingMembers(pods sets.Set[string]) {
+	gang.lock.Lock()
+	defer gang.lock.Unlock()
+	gang.GangGroupInfo.SetBindingMembers(pods)
+}
+
+func (gang *Gang) getBindingMembers() sets.Set[string] {
+	gang.lock.RLock()
+	defer gang.lock.RUnlock()
+	return gang.GangGroupInfo.GetBindingMembers()
+}
+
 func (gang *Gang) isGangWorthRequeue() bool {
 	gang.lock.RLock()
 	defer gang.lock.RUnlock()
diff --git a/pkg/scheduler/plugins/coscheduling/core/ganggroup.go b/pkg/scheduler/plugins/coscheduling/core/ganggroup.go
index 9afe2c11..f6e40d7f 100644
--- a/pkg/scheduler/plugins/coscheduling/core/ganggroup.go
+++ b/pkg/scheduler/plugins/coscheduling/core/ganggroup.go
@@ -34,12 +34,11 @@ type GangGroupInfo struct {
 		WaitingGangIDs
 		- is recorded when permit return wait
 		- is cleared when
-		  - permit allow gangGroup
 		  - gang is reject on postFilter
-		  - pod is deleted
-		  - gang is deleted
-		  - pod is unreserved
-		  - pod is bound
+		  - all pods are deleted
+		  - all gangs are deleted
+		  - all pods are unreserved
+		  - all pod are bound
 	*/
 
 	WaitingGangIDs sets.Set[string]
@@ -53,6 +52,11 @@ type GangGroupInfo struct {
 		- is replaced when some memberPod of gangGroup is firstly failed during some gangGroup schedulingContext
 	*/
 	RepresentativePodKey string
+
+	// BindingMemberPods is the waiting pods when gang enters binding phase.
+	// This value is locked when AllowGangGroup is called and used by all pods during PreBind.
+	// It will be cleared when all gangs in the group complete binding.
+	BindingMemberPods sets.Set[string]
 }
 
 func NewGangGroupInfo(gangGroupId string, gangGroup []string) *GangGroupInfo {
@@ -111,8 +115,14 @@ func (gg *GangGroupInfo) RemoveWaitingGang(gangID string) {
 	defer gg.lock.Unlock()
 	isWaitingBefore := len(gg.WaitingGangIDs) > 0
 	gg.WaitingGangIDs.Delete(gangID)
-	if isWaitingBefore && len(gg.WaitingGangIDs) == 0 {
-		metrics.WaitingGangGroupNumber.WithLabelValues().Dec()
+	if len(gg.WaitingGangIDs) == 0 {
+		if isWaitingBefore {
+			metrics.WaitingGangGroupNumber.WithLabelValues().Dec()
+		}
+		if len(gg.BindingMemberPods) > 0 {
+			gg.BindingMemberPods = nil
+			klog.V(4).InfoS("GangGroupInfo: clear binding member count", "gangGroupId", gg.GangGroupId)
+		}
 	}
 }
 
@@ -124,6 +134,10 @@ func (gg *GangGroupInfo) ClearWaitingGang() {
 	if isWaitingBefore && len(gg.WaitingGangIDs) == 0 {
 		metrics.WaitingGangGroupNumber.WithLabelValues().Dec()
 	}
+	if len(gg.BindingMemberPods) > 0 {
+		gg.BindingMemberPods = nil
+		klog.V(4).InfoS("GangGroupInfo: clear binding member count", "gangGroupId", gg.GangGroupId)
+	}
 }
 
 func (gg *GangGroupInfo) RecordIfNoRepresentatives(pod *corev1.Pod) string {
@@ -157,3 +171,16 @@ func (gg *GangGroupInfo) ClearCurrentRepresentative(reason string) {
 	defer gg.lock.Unlock()
 	gg.RepresentativePodKey = ""
 }
+
+func (gg *GangGroupInfo) SetBindingMembers(pods sets.Set[string]) {
+	gg.lock.Lock()
+	defer gg.lock.Unlock()
+	gg.BindingMemberPods = pods
+	klog.V(4).InfoS("GangGroupInfo: set binding member count", "gangGroupId", gg.GangGroupId, "count", pods.Len())
+}
+
+func (gg *GangGroupInfo) GetBindingMembers() sets.Set[string] {
+	gg.lock.RLock()
+	defer gg.lock.RUnlock()
+	return gg.BindingMemberPods
+}
diff --git a/pkg/scheduler/plugins/coscheduling/coscheduling.go b/pkg/scheduler/plugins/coscheduling/coscheduling.go
index 7dc76367..33b2665a 100644
--- a/pkg/scheduler/plugins/coscheduling/coscheduling.go
+++ b/pkg/scheduler/plugins/coscheduling/coscheduling.go
@@ -214,6 +214,8 @@ func (cs *Coscheduling) Unreserve(ctx context.Context, state *framework.CycleSta
 func (cs *Coscheduling) PreBind(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
 	gangInfo := cs.pgMgr.GetGangBindingInfo(pod)
 	if gangInfo == nil {
+		delete(pod.Annotations, extension.AnnotationBindGangGroupId)
+		delete(pod.Annotations, extension.AnnotationBindGangMemberCount)
 		return nil
 	}
 	if pod.Annotations == nil {
@@ -228,6 +230,8 @@ func (cs *Coscheduling) PreBindReservation(ctx context.Context, cycleState *fram
 	pod := reservationutil.NewReservePod(r)
 	gangInfo := cs.pgMgr.GetGangBindingInfo(pod)
 	if gangInfo == nil {
+		delete(pod.Annotations, extension.AnnotationBindGangGroupId)
+		delete(pod.Annotations, extension.AnnotationBindGangMemberCount)
 		return nil
 	}
 	if r.Annotations == nil {
diff --git a/pkg/scheduler/plugins/deviceshare/device_plugin_adapter.go b/pkg/scheduler/plugins/deviceshare/device_plugin_adapter.go
index 7cab3e92..ad75415a 100644
--- a/pkg/scheduler/plugins/deviceshare/device_plugin_adapter.go
+++ b/pkg/scheduler/plugins/deviceshare/device_plugin_adapter.go
@@ -25,7 +25,6 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/client-go/kubernetes"
 	"k8s.io/klog/v2"
 	"k8s.io/utils/clock"
 
@@ -84,16 +83,17 @@ type DevicePluginAdapter interface {
 
 type DevicePluginAdaptContext struct {
 	context.Context
-	client kubernetes.Interface
-	node   *corev1.Node
+	node *corev1.Node
 }
 
 var (
 	defaultDevicePluginAdapter DevicePluginAdapter = &generalDevicePluginAdapter{
 		clock: clock.RealClock{},
 	}
-	defaultGPUDevicePluginAdapter DevicePluginAdapter = &generalGPUDevicePluginAdapter{}
-	gpuDevicePluginAdapterMap                         = map[string]DevicePluginAdapter{
+	defaultDevicePluginAdapterMap = map[schedulingv1alpha1.DeviceType]DevicePluginAdapter{
+		schedulingv1alpha1.GPU: &generalGPUDevicePluginAdapter{},
+	}
+	gpuDevicePluginAdapterMap = map[string]DevicePluginAdapter{
 		apiext.GPUVendorHuawei: &huaweiGPUDevicePluginAdapter{
 			clock: clock.RealClock{},
 		},
@@ -104,46 +104,52 @@ var (
 )
 
 func (p *Plugin) adaptForDevicePlugin(ctx context.Context, object metav1.Object, allocationResult apiext.DeviceAllocations, nodeName string) error {
-	if err := defaultDevicePluginAdapter.Adapt(nil, object, nil); err != nil {
+	nodeInfo, err := p.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
+	if err != nil {
+		klog.ErrorS(err, "Failed to get NodeInfo", "node", nodeName)
 		return err
 	}
+	adaptCtx := &DevicePluginAdaptContext{
+		Context: ctx,
+		node:    nodeInfo.Node().DeepCopy(),
+	}
 
-	if gpuAllocation, ok := allocationResult[schedulingv1alpha1.GPU]; ok {
-		nodeInfo, err := p.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
-		if err != nil {
-			klog.ErrorS(err, "Failed to get NodeInfo", "node", nodeName)
-			return err
-		}
-
-		adaptCtx := &DevicePluginAdaptContext{
-			Context: ctx,
-			client:  p.handle.ClientSet(),
-			node:    nodeInfo.Node(),
-		}
+	if err := defaultDevicePluginAdapter.Adapt(adaptCtx, object, nil); err != nil {
+		return err
+	}
 
-		if err := defaultGPUDevicePluginAdapter.Adapt(adaptCtx, object, gpuAllocation); err != nil {
-			return err
+	for deviceType, allocation := range allocationResult {
+		if adapter, ok := defaultDevicePluginAdapterMap[deviceType]; ok {
+			if err := adapter.Adapt(adaptCtx, object, allocation); err != nil {
+				return err
+			}
 		}
 
-		extendedHandle, ok := p.handle.(frameworkext.ExtendedHandle)
-		if !ok {
-			return fmt.Errorf("expect handle to be type frameworkext.ExtendedHandle, got %T", p.handle)
-		}
-		deviceLister := extendedHandle.KoordinatorSharedInformerFactory().Scheduling().V1alpha1().Devices().Lister()
-		device, err := deviceLister.Get(nodeName)
-		if err != nil {
-			klog.ErrorS(err, "Failed to get Device", "node", nodeName)
-			return err
-		}
+		if deviceType == schedulingv1alpha1.GPU {
+			extendedHandle, ok := p.handle.(frameworkext.ExtendedHandle)
+			if !ok {
+				return fmt.Errorf("expect handle to be type frameworkext.ExtendedHandle, got %T", p.handle)
+			}
+			deviceLister := extendedHandle.KoordinatorSharedInformerFactory().Scheduling().V1alpha1().Devices().Lister()
+			device, err := deviceLister.Get(nodeName)
+			if err != nil {
+				klog.ErrorS(err, "Failed to get Device", "node", nodeName)
+				return err
+			}
 
-		vendor := device.Labels[apiext.LabelGPUVendor]
-		if adapter, ok := gpuDevicePluginAdapterMap[vendor]; ok {
-			if err := adapter.Adapt(adaptCtx, object, gpuAllocation); err != nil {
-				return fmt.Errorf("failed to adapt for GPU device plugin of vendor %q: %w", vendor, err)
+			vendor := device.Labels[apiext.LabelGPUVendor]
+			if adapter, ok := gpuDevicePluginAdapterMap[vendor]; ok {
+				if err := adapter.Adapt(adaptCtx, object, allocation); err != nil {
+					return fmt.Errorf("failed to adapt for GPU device plugin of vendor %q: %w", vendor, err)
+				}
 			}
 		}
 	}
 
+	if _, err := util.PatchNode(ctx, p.handle.ClientSet(), nodeInfo.Node(), adaptCtx.node); err != nil {
+		return fmt.Errorf("failed to patch node %q: %v", adaptCtx.node.Name, err)
+	}
+
 	return nil
 }
 
@@ -208,7 +214,7 @@ func (a *cambriconGPUDevicePluginAdapter) Adapt(ctx *DevicePluginAdaptContext, o
 	}
 	vmemory := memory.Value() / cambriconVMemoryUnit
 
-	if err := lockNode(ctx, ctx.client, ctx.node, object, AnnotationCambriconDsmluLock, a.clock.Now()); err != nil {
+	if err := lockNode(ctx.node, object, AnnotationCambriconDsmluLock, a.clock.Now()); err != nil {
 		return fmt.Errorf("failed to lock node: %v", err)
 	}
 
@@ -217,7 +223,7 @@ func (a *cambriconGPUDevicePluginAdapter) Adapt(ctx *DevicePluginAdaptContext, o
 	return nil
 }
 
-func lockNode(ctx context.Context, client kubernetes.Interface, node *corev1.Node, object metav1.Object, lockKey string, lockTime time.Time) error {
+func lockNode(node *corev1.Node, object metav1.Object, lockKey string, lockTime time.Time) error {
 	if val, ok := node.Annotations[lockKey]; ok {
 		lockTime, err := time.Parse(time.RFC3339, strings.Split(val, ",")[0])
 		if err != nil {
@@ -225,34 +231,23 @@ func lockNode(ctx context.Context, client kubernetes.Interface, node *corev1.Nod
 		}
 		if time.Since(lockTime) > nodeLockTimeout {
 			// this should never happen in normal cases, and we don't want to lock the node forever
-			if err := unlockNode(ctx, client, node, lockKey); err != nil {
-				return err
-			}
+			unlockNode(node, lockKey)
 		} else {
 			return fmt.Errorf("node %q has been locked", node.Name)
 		}
 	}
-	newNode := node.DeepCopy()
-	if newNode.Annotations == nil {
-		newNode.Annotations = map[string]string{}
-	}
-	newNode.Annotations[lockKey] = fmt.Sprintf("%s,%s,%s", lockTime.Format(time.RFC3339), object.GetNamespace(), object.GetName())
-	if _, err := util.PatchNode(ctx, client, node, newNode); err != nil {
-		return fmt.Errorf("failed to patch node %q: %v", node.Name, err)
+	if node.Annotations == nil {
+		node.Annotations = map[string]string{}
 	}
+	node.Annotations[lockKey] = fmt.Sprintf("%s,%s,%s", lockTime.Format(time.RFC3339), object.GetNamespace(), object.GetName())
 	return nil
 }
 
-func unlockNode(ctx context.Context, client kubernetes.Interface, node *corev1.Node, lockKey string) error {
+func unlockNode(node *corev1.Node, lockKey string) {
 	if _, ok := node.Annotations[lockKey]; !ok {
-		return nil
-	}
-	newNode := node.DeepCopy()
-	delete(newNode.Annotations, lockKey)
-	if _, err := util.PatchNode(ctx, client, node, newNode); err != nil {
-		return fmt.Errorf("failed to patch node %q: %v", node.Name, err)
+		return
 	}
-	return nil
+	delete(node.Annotations, lockKey)
 }
 
 func buildGPUMinorsStr(allocation []*apiext.DeviceAllocation) string {
diff --git a/pkg/scheduler/plugins/deviceshare/eventhandler_pod.go b/pkg/scheduler/plugins/deviceshare/eventhandler_pod.go
index 2ac9bf52..1d72a9f7 100644
--- a/pkg/scheduler/plugins/deviceshare/eventhandler_pod.go
+++ b/pkg/scheduler/plugins/deviceshare/eventhandler_pod.go
@@ -119,7 +119,7 @@ func (n *nodeDeviceCache) updatePod(oldPod *corev1.Pod, pod *corev1.Pod) {
 	info := n.getNodeDevice(pod.Spec.NodeName, true)
 	info.lock.Lock()
 	defer info.lock.Unlock()
-	if oldPod != nil && len(oldAllocations) > 0 {
+	if oldPod != nil && oldPod.Spec.NodeName != "" && len(oldAllocations) > 0 { // avoid leaking for an unassigned pod
 		info.updateCacheUsed(oldAllocations, oldPod, false)
 		klog.V(5).InfoS("remove old pod from nodeDevice cache on node", "pod", klog.KObj(pod), "node", oldPod.Spec.NodeName)
 	}
diff --git a/pkg/scheduler/plugins/deviceshare/numa_topology.go b/pkg/scheduler/plugins/deviceshare/numa_topology.go
index 18aee995..181be803 100644
--- a/pkg/scheduler/plugins/deviceshare/numa_topology.go
+++ b/pkg/scheduler/plugins/deviceshare/numa_topology.go
@@ -26,6 +26,7 @@ import (
 type NUMATopology struct {
 	numNodePerSocket int
 	nodes            map[int][]PCIe
+	deviceToNodeID   map[schedulingv1alpha1.DeviceType]map[int32]int
 }
 
 type PCIe struct {
@@ -41,6 +42,7 @@ type PCIeIndex struct {
 
 func newNUMATopology(deviceObj *schedulingv1alpha1.Device) *NUMATopology {
 	devicesInPCIe := map[PCIeIndex]map[schedulingv1alpha1.DeviceType][]int{}
+	deviceToNodeID := map[schedulingv1alpha1.DeviceType]map[int32]int{}
 	for i := range deviceObj.Spec.Devices {
 		deviceInfo := &deviceObj.Spec.Devices[i]
 		if deviceInfo.Topology == nil || deviceInfo.Topology.NodeID == -1 {
@@ -62,9 +64,16 @@ func newNUMATopology(deviceObj *schedulingv1alpha1.Device) *NUMATopology {
 		}
 		minor := pointer.Int32Deref(deviceInfo.Minor, 0)
 		devices[deviceInfo.Type] = append(devices[deviceInfo.Type], int(minor))
+		if deviceToNodeID[deviceInfo.Type] == nil {
+			deviceToNodeID[deviceInfo.Type] = map[int32]int{}
+		}
+		deviceToNodeID[deviceInfo.Type][minor] = int(deviceInfo.Topology.NodeID)
 	}
 
 	topology := &NUMATopology{}
+	if len(deviceToNodeID) > 0 {
+		topology.deviceToNodeID = deviceToNodeID
+	}
 	nodeCounter := map[int]sets.Int{}
 	for pcieIndex, devices := range devicesInPCIe {
 		pcies := topology.nodes[pcieIndex.node]
diff --git a/pkg/scheduler/plugins/deviceshare/plugin.go b/pkg/scheduler/plugins/deviceshare/plugin.go
index a879972e..7547c948 100644
--- a/pkg/scheduler/plugins/deviceshare/plugin.go
+++ b/pkg/scheduler/plugins/deviceshare/plugin.go
@@ -329,16 +329,6 @@ func (p *Plugin) Filter(ctx context.Context, cycleState *framework.CycleState, p
 	if state.skip {
 		return nil
 	}
-	if state.designatedAllocation != nil {
-		if state.allocationResult == nil {
-			status = p.allocate(ctx, cycleState, pod, nodeInfo.Node())
-			if !status.IsSuccess() {
-				return status
-			}
-			state.allocationResult = nil
-		}
-		return nil
-	}
 
 	node := nodeInfo.Node()
 	if node == nil {
@@ -357,6 +347,17 @@ func (p *Plugin) Filter(ctx context.Context, cycleState *framework.CycleState, p
 		return nil
 	}
 
+	if state.designatedAllocation != nil {
+		if state.allocationResult == nil {
+			status = p.allocate(ctx, cycleState, pod, nodeInfo.Node())
+			if !status.IsSuccess() {
+				return status
+			}
+			state.allocationResult = nil
+		}
+		return nil
+	}
+
 	nodeDeviceInfo := p.nodeDeviceCache.getNodeDevice(node.Name, false)
 	if nodeDeviceInfo == nil {
 		return nil
diff --git a/pkg/scheduler/plugins/deviceshare/topology_hint.go b/pkg/scheduler/plugins/deviceshare/topology_hint.go
index db261364..1fc399fe 100644
--- a/pkg/scheduler/plugins/deviceshare/topology_hint.go
+++ b/pkg/scheduler/plugins/deviceshare/topology_hint.go
@@ -21,6 +21,7 @@ import (
 	"sort"
 
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/gengo/examples/set-gen/sets"
 	"k8s.io/kubernetes/pkg/scheduler/framework"
 
 	apiext "github.com/koordinator-sh/koordinator/apis/extension"
@@ -31,6 +32,7 @@ import (
 
 const (
 	ErrInsufficientNUMAScopedDevices = "Insufficient NUMA Scoped Devices"
+	ErrDesignatedAllocationLackNUMA  = "Designated Allocation Lack NUMA Node ID"
 
 	defaultNUMAScore = 500
 )
@@ -59,9 +61,49 @@ func (p *Plugin) GetPodTopologyHints(ctx context.Context, cycleState *framework.
 		return nil, nil
 	}
 
+	nodeDeviceInfo.lock.RLock()
+	numaTopology := nodeDeviceInfo.numaTopology
+	nodeDeviceInfo.lock.RUnlock()
+	if state.designatedAllocation != nil {
+		return generateDesignatedHints(state.designatedAllocation, numaTopology)
+	}
+
 	return p.generateTopologyHints(cycleState, state, nodeDeviceInfo, node, pod)
 }
 
+func generateDesignatedHints(allocations apiext.DeviceAllocations, topology *NUMATopology) (map[string][]topologymanager.NUMATopologyHint, *framework.Status) {
+	hints := map[string][]topologymanager.NUMATopologyHint{}
+	numaNodes := sets.NewInt()
+	for deviceType, deviceAllocations := range allocations {
+		for _, allocation := range deviceAllocations {
+			if deviceToNodeID, ok := topology.deviceToNodeID[deviceType]; !ok {
+				return nil, framework.NewStatus(framework.Unschedulable, ErrDesignatedAllocationLackNUMA)
+
+			} else if nodeID, ok := deviceToNodeID[allocation.Minor]; !ok {
+				return nil, framework.NewStatus(framework.Unschedulable, ErrDesignatedAllocationLackNUMA)
+			} else {
+				numaNodes.Insert(nodeID)
+			}
+		}
+		hints[string(deviceType)] = nil
+	}
+	affinity, err := bitmask.NewBitMask(numaNodes.UnsortedList()...)
+	if err != nil {
+		return nil, framework.NewStatus(framework.Unschedulable, err.Error())
+	}
+	for deviceType := range allocations {
+		hints[string(deviceType)] = []topologymanager.NUMATopologyHint{
+			{
+				NUMANodeAffinity: affinity,
+				Preferred:        true,
+				Score:            defaultNUMAScore,
+				Unsatisfied:      false,
+			},
+		}
+	}
+	return hints, nil
+}
+
 func (p *Plugin) Allocate(ctx context.Context, cycleState *framework.CycleState, affinity topologymanager.NUMATopologyHint, pod *corev1.Pod, nodeName string) *framework.Status {
 	if p.disableDeviceNUMATopologyAlignment {
 		return nil
@@ -81,6 +123,17 @@ func (p *Plugin) Allocate(ctx context.Context, cycleState *framework.CycleState,
 	}
 	node := nodeInfo.Node()
 
+	if state.designatedAllocation != nil {
+		if state.allocationResult == nil {
+			status = p.allocate(ctx, cycleState, pod, nodeInfo.Node())
+			if !status.IsSuccess() {
+				return status
+			}
+			state.allocationResult = nil
+		}
+		return nil
+	}
+
 	nodeDeviceInfo := p.nodeDeviceCache.getNodeDevice(node.Name, false)
 	if nodeDeviceInfo == nil {
 		return nil
diff --git a/pkg/scheduler/plugins/nodenumaresource/reservation.go b/pkg/scheduler/plugins/nodenumaresource/reservation.go
index 45bb8b68..707fd390 100644
--- a/pkg/scheduler/plugins/nodenumaresource/reservation.go
+++ b/pkg/scheduler/plugins/nodenumaresource/reservation.go
@@ -505,6 +505,11 @@ func (p *Plugin) allocateWithNominatedReservation(
 		return tryAllocateIgnoreReservation(p.resourceManager, restoreState, resourceOptions, restoreState.matched, pod, node)
 	}
 
+	if len(restoreState.matched) == 0 {
+		klog.V(5).Infof("no reservation reserve numa resource or cpuset")
+		return nil, nil
+	}
+
 	rInfo := p.handle.GetReservationNominator().GetNominatedReservation(pod, node.Name)
 	if rInfo == nil {
 		if resourceOptions.requiredFromReservation {
diff --git a/pkg/scheduler/plugins/reservation/cache.go b/pkg/scheduler/plugins/reservation/cache.go
index 54450d76..1aedf746 100644
--- a/pkg/scheduler/plugins/reservation/cache.go
+++ b/pkg/scheduler/plugins/reservation/cache.go
@@ -168,18 +168,17 @@ func (cache *reservationCache) addPod(reservationUID types.UID, pod *corev1.Pod)
 	return nil
 }
 
-func (cache *reservationCache) updatePod(reservationUID types.UID, oldPod, newPod *corev1.Pod) {
+func (cache *reservationCache) updatePod(oldReservationUID, newReservationUID types.UID, oldPod, newPod *corev1.Pod) {
 	cache.lock.Lock()
 	defer cache.lock.Unlock()
 
-	rInfo := cache.reservationInfos[reservationUID]
-	if rInfo != nil {
-		if oldPod != nil {
-			rInfo.RemoveAssignedPod(oldPod)
-		}
-		if newPod != nil {
-			rInfo.AddAssignedPod(newPod)
-		}
+	oldRInfo := cache.reservationInfos[oldReservationUID]
+	if oldRInfo != nil && oldPod != nil {
+		oldRInfo.RemoveAssignedPod(oldPod)
+	}
+	newRInfo := cache.reservationInfos[newReservationUID]
+	if newRInfo != nil && newPod != nil {
+		newRInfo.AddAssignedPod(newPod)
 	}
 }
 
diff --git a/pkg/scheduler/plugins/reservation/controller/pod_eventhandler.go b/pkg/scheduler/plugins/reservation/controller/pod_eventhandler.go
index 7fae8b4a..bfb16984 100644
--- a/pkg/scheduler/plugins/reservation/controller/pod_eventhandler.go
+++ b/pkg/scheduler/plugins/reservation/controller/pod_eventhandler.go
@@ -38,8 +38,17 @@ func (c *Controller) onPodUpdate(oldObj, newObj interface{}) {
 	if newPod == nil {
 		return
 	}
-	rAllocated := c.enqueueIfPodBoundReservation(newPod)
-	c.updatePod(newPod, rAllocated)
+	oldPod, _ := oldObj.(*corev1.Pod)
+	if oldPod == nil {
+		return
+	}
+	if newPod.Spec.NodeName != "" {
+		rAllocated := c.enqueueIfPodBoundReservation(newPod)
+		c.updatePod(newPod, rAllocated)
+	} else if oldPod.Spec.NodeName != "" { // become unassigned, a special case for multi-scheduler
+		_ = c.enqueueIfPodBoundReservation(oldPod)
+		c.deletePod(oldPod)
+	}
 }
 
 func (c *Controller) onPodDelete(obj interface{}) {
diff --git a/pkg/scheduler/plugins/reservation/eventhandler.go b/pkg/scheduler/plugins/reservation/eventhandler.go
index d3233bd4..cff12c37 100644
--- a/pkg/scheduler/plugins/reservation/eventhandler.go
+++ b/pkg/scheduler/plugins/reservation/eventhandler.go
@@ -51,7 +51,7 @@ func (h *reservationEventHandler) OnAdd(obj interface{}, isInInitialList bool) {
 	if reservationutil.IsReservationActive(r) {
 		h.cache.updateReservation(r)
 		klog.V(4).InfoS("add reservation into reservationCache",
-			"reservation", klog.KObj(r), "node", reservationutil.GetReservationNodeName(r))
+			"reservation", klog.KObj(r), "uid", r.UID, "node", reservationutil.GetReservationNodeName(r))
 	}
 }
 
@@ -69,7 +69,7 @@ func (h *reservationEventHandler) OnUpdate(oldObj, newObj interface{}) {
 		h.cache.updateReservation(newR)
 		h.rrNominator.DeleteReservePod(reservationutil.NewReservePod(newR))
 		klog.V(4).InfoS("update reservation into reservationCache",
-			"reservation", klog.KObj(newR), "node", reservationutil.GetReservationNodeName(newR))
+			"reservation", klog.KObj(newR), "uid", newR.UID, "node", reservationutil.GetReservationNodeName(newR))
 	} else if reservationutil.IsReservationFailed(newR) || reservationutil.IsReservationSucceeded(newR) {
 		// Here it is only marked that ReservationInfo is unavailable,
 		// and the real deletion operation is executed in deleteReservationFromCache(pkg/scheduler/frameworkext/eventhandlers/reservation_handler.go).
@@ -110,5 +110,5 @@ func (h *reservationEventHandler) OnDelete(obj interface{}) {
 	}
 	h.cache.updateReservationIfExists(r)
 	klog.V(4).InfoS("got delete reservation event but just update it if exists",
-		"reservation", klog.KObj(r), "node", reservationutil.GetReservationNodeName(r))
+		"reservation", klog.KObj(r), "uid", r.UID, "node", reservationutil.GetReservationNodeName(r))
 }
diff --git a/pkg/scheduler/plugins/reservation/nominator.go b/pkg/scheduler/plugins/reservation/nominator.go
index 83b08060..8301e474 100644
--- a/pkg/scheduler/plugins/reservation/nominator.go
+++ b/pkg/scheduler/plugins/reservation/nominator.go
@@ -373,6 +373,10 @@ func (pl *Plugin) DeleteNominatedReservePod(pod *corev1.Pod) {
 	pl.nominator.DeleteReservePod(pod)
 }
 
+func (pl *Plugin) NominatedReservePodForNode(nodeName string) []*framework.PodInfo {
+	return pl.nominator.NominatedReservePodForNode(nodeName)
+}
+
 func (pl *Plugin) GetNominatedReservation(pod *corev1.Pod, nodeName string) *frameworkext.ReservationInfo {
 	reservationID := pl.nominator.GetNominatedReservation(pod, nodeName)
 	if reservationID == "" {
diff --git a/pkg/scheduler/plugins/reservation/pod_eventhandler.go b/pkg/scheduler/plugins/reservation/pod_eventhandler.go
index 2a075613..7c14e51b 100644
--- a/pkg/scheduler/plugins/reservation/pod_eventhandler.go
+++ b/pkg/scheduler/plugins/reservation/pod_eventhandler.go
@@ -20,7 +20,6 @@ import (
 	"context"
 
 	corev1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/informers"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/klog/v2"
@@ -97,22 +96,31 @@ func (h *podEventHandler) updatePod(oldPod, newPod *corev1.Pod) {
 	}
 
 	h.nominator.DeleteNominatedReservePodOrReservation(newPod)
-	var reservationUID types.UID
+	var oldRAllocated, newRAllocated *apiext.ReservationAllocated
 	if oldPod != nil {
 		reservationAllocated, err := apiext.GetReservationAllocated(oldPod)
 		if err == nil && reservationAllocated != nil && reservationAllocated.UID != "" {
-			reservationUID = reservationAllocated.UID
+			oldRAllocated = reservationAllocated
 		}
 	}
-	if newPod != nil && reservationUID == "" {
+	if newPod != nil {
 		reservationAllocated, err := apiext.GetReservationAllocated(newPod)
 		if err == nil && reservationAllocated != nil && reservationAllocated.UID != "" {
-			reservationUID = reservationAllocated.UID
+			newRAllocated = reservationAllocated
 		}
 	}
 
-	if reservationUID != "" {
-		h.cache.updatePod(reservationUID, oldPod, newPod)
+	if oldRAllocated != nil || newRAllocated != nil {
+		h.cache.updatePod(oldRAllocated.GetUID(), newRAllocated.GetUID(), oldPod, newPod)
+		if oldRAllocated == nil {
+			klog.V(4).InfoS("add pod for reservation", "pod", klog.KObj(newPod), "reservation", newRAllocated.GetName(), "uid", newRAllocated.GetUID())
+		} else if newRAllocated == nil {
+			klog.V(4).InfoS("delete pod for reservation", "pod", klog.KObj(oldPod), "reservation", oldRAllocated.GetName(), "uid", oldRAllocated.GetUID())
+		} else if oldRAllocated.GetUID() != newRAllocated.GetUID() {
+			klog.V(4).InfoS("update pod for different reservation", "pod", klog.KObj(newPod), "oldReservation", oldRAllocated.GetName(), "oldUID", oldRAllocated.GetUID(), "newReservation", newRAllocated.GetName(), "newUID", newRAllocated.GetUID())
+		} else {
+			klog.V(5).InfoS("update pod for same reservation", "pod", klog.KObj(newPod), "reservation", newRAllocated.GetName(), "uid", newRAllocated.GetUID())
+		}
 	}
 
 	if newPod != nil && apiext.IsReservationOperatingMode(newPod) {
@@ -133,6 +141,7 @@ func (h *podEventHandler) deletePod(pod *corev1.Pod) {
 	reservationAllocated, err := apiext.GetReservationAllocated(pod)
 	if err == nil && reservationAllocated != nil && reservationAllocated.UID != "" {
 		h.cache.deletePod(reservationAllocated.UID, pod)
+		klog.V(4).InfoS("delete pod for reservation", "pod", klog.KObj(pod), "reservation", reservationAllocated.GetName(), "uid", reservationAllocated.GetUID())
 	}
 
 	if apiext.IsReservationOperatingMode(pod) {
diff --git a/pkg/scheduler/plugins/reservation/transformer.go b/pkg/scheduler/plugins/reservation/transformer.go
index 54a0afd6..7b9c30d9 100644
--- a/pkg/scheduler/plugins/reservation/transformer.go
+++ b/pkg/scheduler/plugins/reservation/transformer.go
@@ -68,16 +68,14 @@ func (pl *Plugin) AfterPreFilter(ctx context.Context, cycleState *framework.Cycl
 
 	var allNodes []string
 	var skipRestoreNodeInfo bool
-	if preRes.AllNodes() {
-		hintState, hasHint := getSchedulingHint(cycleState)
-		if !hasHint {
-			allNodes = pl.reservationCache.listAllNodes()
-		} else { // use the hint nodes if exists
-			allNodes = hintState.PreFilterNodeInfos
-			skipRestoreNodeInfo = hintState.SkipRestoreNodeInfo
-		}
-	} else { // use the PreFilter result if exists
+	hintState, hasHint := getSchedulingHint(cycleState)
+	if hasHint { // use the hint nodes if exists
+		allNodes = hintState.PreFilterNodeInfos
+		skipRestoreNodeInfo = hintState.SkipRestoreNodeInfo
+	} else if !preRes.AllNodes() { // use the PreFilter result if exists
 		allNodes = preRes.NodeNames.UnsortedList()
+	} else {
+		allNodes = pl.reservationCache.listAllNodes()
 	}
 
 	state := getStateData(cycleState)
@@ -717,6 +715,7 @@ func preRestoreReservationResourcesForNode(logger klog.Logger, extender framewor
 		nodeRState.rAllocated = framework.NewResource(rAllocated)
 		nodeRState.podRequested = podRequested
 		nodeRState.preRestored = true // no more pre-restore in the same cycle
+		klog.V(5).InfoS("Skipping restore node info", "pod", klog.KObj(pod), "node", node.Name)
 		return nil
 	}
 
diff --git a/pkg/util/pod_resources_utils.go b/pkg/util/pod_resources_utils.go
index c8c52a24..88bc5cc5 100644
--- a/pkg/util/pod_resources_utils.go
+++ b/pkg/util/pod_resources_utils.go
@@ -19,6 +19,7 @@ package util
 import (
 	corev1 "k8s.io/api/core/v1"
 	quotav1 "k8s.io/apiserver/pkg/quota/v1"
+	resourceapi "k8s.io/kubernetes/pkg/api/v1/resource"
 )
 
 // NOTE: functions in this file can be overwritten for extension
@@ -46,18 +47,7 @@ func GetPodMilliCPULimit(pod *corev1.Pod) int64 {
 }
 
 func GetPodRequest(pod *corev1.Pod, resourceNames ...corev1.ResourceName) corev1.ResourceList {
-	result := corev1.ResourceList{}
-	for _, container := range pod.Spec.Containers {
-		result = quotav1.Add(result, container.Resources.Requests)
-	}
-	// take max_resource(sum_pod, any_init_container)
-	for _, container := range pod.Spec.InitContainers {
-		result = quotav1.Max(result, container.Resources.Requests)
-	}
-	// add pod overhead if it exists
-	if pod.Spec.Overhead != nil {
-		result = quotav1.Add(result, pod.Spec.Overhead)
-	}
+	result := resourceapi.PodRequests(pod, resourceapi.PodResourcesOptions{})
 	if len(resourceNames) > 0 {
 		result = quotav1.Mask(result, resourceNames)
 	}
diff --git a/pkg/util/transformer/pod_transformer.go b/pkg/util/transformer/pod_transformer.go
index be29c602..af8c1b3a 100644
--- a/pkg/util/transformer/pod_transformer.go
+++ b/pkg/util/transformer/pod_transformer.go
@@ -35,6 +35,7 @@ import (
 var podTransformers = []func(pod *corev1.Pod){
 	TransformDeprecatedBatchResources,
 	TransformDeprecatedDeviceResources,
+	TransformReplaceResources,
 }
 
 var podTransformerFactories = []func() func(pod *corev1.Pod){
@@ -221,3 +222,36 @@ func TransformScheduleExplanationObjectKey() func(pod *corev1.Pod) {
 		pod.Labels[apiext.LabelQuestionedObjectKey] = objectKey
 	}
 }
+
+// TransformReplaceResources transforms pod resources according to the replace-resources annotation.
+func TransformReplaceResources(pod *corev1.Pod) {
+	if !k8sfeature.DefaultFeatureGate.Enabled(koordfeatures.ReplaceResourcesTransformer) &&
+		!utilfeature.DefaultFeatureGate.Enabled(koordfeatures.ReplaceResourcesTransformer) {
+		return
+	}
+	eraseResNames, replaceMappings := apiext.GetPodReplaceResourcesConfig(pod)
+	if len(eraseResNames) == 0 && len(replaceMappings) == 0 {
+		return
+	}
+	for _, containers := range [][]corev1.Container{pod.Spec.InitContainers, pod.Spec.Containers} {
+		for i := range containers {
+			container := &containers[i]
+			for _, resName := range eraseResNames {
+				delete(container.Resources.Requests, resName)
+				delete(container.Resources.Limits, resName)
+			}
+			for k, v := range replaceMappings {
+				replaceAndEraseResource(container.Resources.Requests, k, v)
+				replaceAndEraseResource(container.Resources.Limits, k, v)
+			}
+		}
+	}
+	if pod.Spec.Overhead != nil {
+		for _, resName := range eraseResNames {
+			delete(pod.Spec.Overhead, resName)
+		}
+		for k, v := range replaceMappings {
+			replaceAndEraseResource(pod.Spec.Overhead, k, v)
+		}
+	}
+}
diff --git a/pkg/webhook/pod/validating/cluster_colocation_profile.go b/pkg/webhook/pod/validating/cluster_colocation_profile.go
index b7a24abc..c0a55829 100644
--- a/pkg/webhook/pod/validating/cluster_colocation_profile.go
+++ b/pkg/webhook/pod/validating/cluster_colocation_profile.go
@@ -27,7 +27,9 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	"github.com/koordinator-sh/koordinator/apis/extension"
+	"github.com/koordinator-sh/koordinator/pkg/features"
 	"github.com/koordinator-sh/koordinator/pkg/util"
+	utilfeature "github.com/koordinator-sh/koordinator/pkg/util/feature"
 )
 
 // +kubebuilder:rbac:groups=scheduling.k8s.io,resources=priorityclasses,verbs=get;list;watch
@@ -51,7 +53,9 @@ func (h *PodValidatingHandler) clusterColocationProfileValidatingPod(ctx context
 
 		allErrs = append(allErrs, validateImmutableQoSClass(oldPod, newPod)...)
 		allErrs = append(allErrs, validateImmutablePriorityClass(oldPod, newPod)...)
-		allErrs = append(allErrs, validateImmutablePriority(oldPod, newPod)...)
+		if !utilfeature.DefaultFeatureGate.Enabled(features.ColocationProfileSkipValidatingPriority) {
+			allErrs = append(allErrs, validateImmutablePriority(oldPod, newPod)...)
+		}
 	}
 
 	allErrs = append(allErrs, validateRequiredQoSClass(newPod)...)
diff --git a/pkg/webhook/pod/validating/evaluate_quota.go b/pkg/webhook/pod/validating/evaluate_quota.go
index 16be5630..4406771a 100644
--- a/pkg/webhook/pod/validating/evaluate_quota.go
+++ b/pkg/webhook/pod/validating/evaluate_quota.go
@@ -29,10 +29,16 @@ import (
 	"github.com/koordinator-sh/koordinator/apis/thirdparty/scheduler-plugins/pkg/apis/scheduling/v1alpha1"
 	"github.com/koordinator-sh/koordinator/pkg/features"
 	utilfeature "github.com/koordinator-sh/koordinator/pkg/util/feature"
+	"github.com/koordinator-sh/koordinator/pkg/util/transformer"
 	"github.com/koordinator-sh/koordinator/pkg/webhook/elasticquota"
 	"github.com/koordinator-sh/koordinator/pkg/webhook/quotaevaluate"
 )
 
+// podTransformersForQuotaEvaluation defines the necessary pod transformers used before quota evaluation.
+var podTransformersForQuotaEvaluation = []func(pod *corev1.Pod){
+	transformer.TransformReplaceResources,
+}
+
 func (h *PodValidatingHandler) evaluateQuota(ctx context.Context, req admission.Request) (bool, string, error) {
 	if !utilfeature.DefaultFeatureGate.Enabled(features.EnableQuotaAdmission) {
 		return true, "", nil
@@ -69,6 +75,11 @@ func (h *PodValidatingHandler) evaluateQuota(ctx context.Context, req admission.
 		return false, err.Error(), err
 	}
 
+	// transform pod before evaluating if the feature is enabled
+	if utilfeature.DefaultFeatureGate.Enabled(features.ElasticQuotaEvaluationTransformPod) {
+		transformPodForQuotaEvaluation(newPod)
+	}
+
 	attribute := &quotaevaluate.Attributes{
 		QuotaNamespace: quotaList.Items[0].Namespace,
 		QuotaName:      quotaList.Items[0].Name,
@@ -82,3 +93,9 @@ func (h *PodValidatingHandler) evaluateQuota(ctx context.Context, req admission.
 	}
 	return true, "", nil
 }
+
+func transformPodForQuotaEvaluation(pod *corev1.Pod) {
+	for _, fn := range podTransformersForQuotaEvaluation {
+		fn(pod)
+	}
+}



Test patch:
diff --git a/apis/extension/reservation_test.go b/apis/extension/reservation_test.go
index 1b80648b..5dc5cea0 100644
--- a/apis/extension/reservation_test.go
+++ b/apis/extension/reservation_test.go
@@ -23,6 +23,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/uuid"
 
 	schedulingv1alpha1 "github.com/koordinator-sh/koordinator/apis/scheduling/v1alpha1"
@@ -134,6 +135,48 @@ func TestRemoveReservationAllocated(t *testing.T) {
 	assert.False(t, changed)
 }
 
+func TestReservationAllocatedGetters(t *testing.T) {
+	tests := []struct {
+		name       string
+		allocated  *ReservationAllocated
+		expectName string
+		expectUID  types.UID
+	}{
+		{
+			name:       "nil reservation allocated",
+			allocated:  nil,
+			expectName: "",
+			expectUID:  "",
+		},
+		{
+			name: "valid reservation allocated",
+			allocated: &ReservationAllocated{
+				Name: "test-reservation",
+				UID:  "test-uid-123",
+			},
+			expectName: "test-reservation",
+			expectUID:  "test-uid-123",
+		},
+		{
+			name: "empty name and uid",
+			allocated: &ReservationAllocated{
+				Name: "",
+				UID:  "",
+			},
+			expectName: "",
+			expectUID:  "",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			gotName := tt.allocated.GetName()
+			gotUID := tt.allocated.GetUID()
+			assert.Equal(t, tt.expectName, gotName)
+			assert.Equal(t, tt.expectUID, gotUID)
+		})
+	}
+}
+
 func TestExactMatchReservation(t *testing.T) {
 	tests := []struct {
 		name                   string
diff --git a/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress_test.go b/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress_test.go
index da0e1c5f..147b89c7 100644
--- a/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress_test.go
+++ b/pkg/koordlet/qosmanager/plugins/cpusuppress/cpu_suppress_test.go
@@ -2008,6 +2008,12 @@ func Test_cpuSuppress_adjustByCfsQuota(t *testing.T) {
 			preBECfsQuota:  int64(0.8 * float64(system.DefaultCPUCFSPeriod)),
 			wantBECfsQuota: 2000,
 		},
+		{
+			name:           "increase CFSQuota: first time set quota with beUnsetQuota, scale without step limit",
+			cpuQuantity:    resource.NewMilliQuantity(20*1000, resource.BinarySI),
+			preBECfsQuota:  -1,
+			wantBECfsQuota: 20 * system.DefaultCPUCFSPeriod,
+		},
 	}
 
 	for _, tt := range testCases {
diff --git a/pkg/koordlet/qosmanager/plugins/util/evict_test.go b/pkg/koordlet/qosmanager/plugins/util/evict_test.go
index 24b2b700..88b01776 100644
--- a/pkg/koordlet/qosmanager/plugins/util/evict_test.go
+++ b/pkg/koordlet/qosmanager/plugins/util/evict_test.go
@@ -30,6 +30,8 @@ import (
 	"github.com/koordinator-sh/koordinator/pkg/koordlet/util/testutil"
 )
 
+const defaultEvictPriority = 5999
+
 func Test_DefaultEvictionExecutor(t *testing.T) {
 	// test IsPodEvicted
 	evictor := NewEvictor(nil, nil, "")
@@ -406,9 +408,10 @@ func Test_AddReleased(t *testing.T) {
 
 func Test_GetPodPriorityLabel(t *testing.T) {
 	tests := []struct {
-		name     string
-		pod      *corev1.Pod
-		expected int64
+		name            string
+		pod             *corev1.Pod
+		defaultPriority int64
+		expected        int64
 	}{
 		{
 			name: "nil label",
@@ -417,7 +420,8 @@ func Test_GetPodPriorityLabel(t *testing.T) {
 					Labels: nil,
 				},
 			},
-			expected: DefaultEvictPriority,
+			defaultPriority: defaultEvictPriority,
+			expected:        defaultEvictPriority,
 		},
 		{
 			name: "no that label",
@@ -428,7 +432,8 @@ func Test_GetPodPriorityLabel(t *testing.T) {
 					},
 				},
 			},
-			expected: DefaultEvictPriority,
+			defaultPriority: defaultEvictPriority,
+			expected:        defaultEvictPriority,
 		},
 		{
 			name: "invalid value",
@@ -439,7 +444,8 @@ func Test_GetPodPriorityLabel(t *testing.T) {
 					},
 				},
 			},
-			expected: DefaultEvictPriority,
+			defaultPriority: defaultEvictPriority,
+			expected:        defaultEvictPriority,
 		},
 		{
 			name: "invalid value",
@@ -450,12 +456,13 @@ func Test_GetPodPriorityLabel(t *testing.T) {
 					},
 				},
 			},
-			expected: 1200,
+			defaultPriority: defaultEvictPriority,
+			expected:        1200,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			res := GetPodPriorityLabel(tt.pod)
+			res := GetPodPriorityLabel(tt.pod, defaultEvictPriority)
 			assert.Equal(t, res, tt.expected)
 		})
 	}
diff --git a/pkg/koordlet/statesinformer/impl/states_device_linux_test.go b/pkg/koordlet/statesinformer/impl/states_device_linux_test.go
index 56654774..1d5e741d 100644
--- a/pkg/koordlet/statesinformer/impl/states_device_linux_test.go
+++ b/pkg/koordlet/statesinformer/impl/states_device_linux_test.go
@@ -35,6 +35,94 @@ import (
 	mock_metriccache "github.com/koordinator-sh/koordinator/pkg/koordlet/metriccache/mockmetriccache"
 )
 
+func Test_getGPUDeviceConditions(t *testing.T) {
+	tests := []struct {
+		name string
+		gpu  *koordletutil.GPUDeviceInfo
+	}{
+		{
+			name: "healthy GPU device",
+			gpu: &koordletutil.GPUDeviceInfo{
+				UUID:        "test-gpu-uuid",
+				Minor:       0,
+				MemoryTotal: 8000,
+				Status: &koordletutil.DeviceStatus{
+					Healthy: true,
+				},
+			},
+		},
+		{
+			name: "unhealthy GPU device with Xid error",
+			gpu: &koordletutil.GPUDeviceInfo{
+				UUID:        "test-gpu-uuid-2",
+				Minor:       1,
+				MemoryTotal: 8000,
+				Status: &koordletutil.DeviceStatus{
+					Healthy:    false,
+					ErrCode:    "Xid44",
+					ErrMessage: "Xid error detected on device, error code: 44",
+				},
+			},
+		},
+		{
+			name: "GPU device with device health check not supported",
+			gpu: &koordletutil.GPUDeviceInfo{
+				UUID:        "test-gpu-uuid-3",
+				Minor:       2,
+				MemoryTotal: 8000,
+				Status: &koordletutil.DeviceStatus{
+					Healthy:    false,
+					ErrCode:    "DeviceHealthCheckNotSupported",
+					ErrMessage: "device does not support health checking",
+				},
+			},
+		},
+		{
+			name: "GPU device with Xid error code only",
+			gpu: &koordletutil.GPUDeviceInfo{
+				UUID:        "test-gpu-uuid-4",
+				Minor:       3,
+				MemoryTotal: 8000,
+				Status: &koordletutil.DeviceStatus{
+					Healthy: false,
+					ErrCode: "Xid44",
+				},
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := getGPUDeviceConditions(tt.gpu)
+
+			assert.NotNil(t, got, "GPU should return Conditions")
+			assert.Equal(t, 1, len(got), "Should have exactly one Condition")
+			assert.Equal(t, string(schedulingv1alpha1.DeviceConditionHealthy), got[0].Type)
+			assert.NotEmpty(t, got[0].LastTransitionTime, "LastTransitionTime should not be empty")
+
+			if tt.gpu.Status.Healthy {
+				assert.Equal(t, metav1.ConditionTrue, got[0].Status)
+				assert.Equal(t, "DeviceHealthy", got[0].Reason)
+				assert.Equal(t, "device is healthy", got[0].Message)
+			} else {
+				assert.Equal(t, metav1.ConditionFalse, got[0].Status)
+
+				if tt.gpu.Status.ErrCode == "DeviceHealthCheckNotSupported" {
+					assert.Equal(t, "DeviceHealthCheckNotSupported", got[0].Reason)
+					assert.Equal(t, tt.gpu.Status.ErrMessage, got[0].Message)
+				} else if tt.gpu.Status.ErrCode != "" {
+					assert.Equal(t, tt.gpu.Status.ErrCode, got[0].Reason)
+					if tt.gpu.Status.ErrMessage != "" {
+						assert.Equal(t, tt.gpu.Status.ErrMessage, got[0].Message)
+					} else {
+						assert.Equal(t, "device is unhealthy", got[0].Message)
+					}
+				}
+			}
+		})
+	}
+}
+
 func Test_reportGPUDevice(t *testing.T) {
 	testNode := &corev1.Node{
 		ObjectMeta: metav1.ObjectMeta{
@@ -72,6 +160,7 @@ func Test_reportGPUDevice(t *testing.T) {
 	}
 	r.reportDevice()
 	expectedDevices := []schedulingv1alpha1.DeviceInfo{
+
 		{
 			UUID:   "1",
 			Minor:  pointer.Int32(1),
@@ -114,6 +203,20 @@ func Test_reportGPUDevice(t *testing.T) {
 	}
 	device, err := fakeClient.Get(context.TODO(), "test", metav1.GetOptions{})
 	assert.Equal(t, nil, err)
+
+	// Set fixed time for conditions to avoid time comparison issues
+	fixedTime := metav1.Now()
+	for i := range device.Spec.Devices {
+		for j := range device.Spec.Devices[i].Conditions {
+			device.Spec.Devices[i].Conditions[j].LastTransitionTime = fixedTime
+		}
+	}
+	for i := range expectedDevices {
+		for j := range expectedDevices[i].Conditions {
+			expectedDevices[i].Conditions[j].LastTransitionTime = fixedTime
+		}
+	}
+
 	assert.Equal(t, device.Spec.Devices, expectedDevices)
 
 	gpuDeviceInfo = append(gpuDeviceInfo, koordletutil.GPUDeviceInfo{
@@ -166,6 +269,20 @@ func Test_reportGPUDevice(t *testing.T) {
 	})
 	device, err = fakeClient.Get(context.TODO(), "test", metav1.GetOptions{})
 	assert.Equal(t, nil, err)
+
+	// Set fixed time for conditions to avoid time comparison issues
+	fixedTime = metav1.Now()
+	for i := range device.Spec.Devices {
+		for j := range device.Spec.Devices[i].Conditions {
+			device.Spec.Devices[i].Conditions[j].LastTransitionTime = fixedTime
+		}
+	}
+	for i := range expectedDevices {
+		for j := range expectedDevices[i].Conditions {
+			expectedDevices[i].Conditions[j].LastTransitionTime = fixedTime
+		}
+	}
+
 	assert.Equal(t, device.Spec.Devices, expectedDevices)
 	assert.Equal(t, device.Labels[extension.LabelGPUVendor], extension.GPUVendorNVIDIA)
 	assert.Equal(t, device.Labels[extension.LabelGPUModel], "A100")
@@ -435,3 +552,72 @@ func Test_reportXPUDevice(t *testing.T) {
 	assert.Equal(t, device.Labels[extension.LabelGPUPartitionPolicy], "Honor")
 	assert.Equal(t, device.Annotations[extension.AnnotationGPUPartitions], "{\"4\":[{\"minors\":[0,1,2,3],\"gpuLinkType\":\"HCCS\",\"allocationScore\":1},{\"minors\":[4,5,6,7],\"gpuLinkType\":\"HCCS\",\"allocationScore\":1}]}")
 }
+
+func Test_reportGPUDeviceUnhealthy(t *testing.T) {
+	testNode := &corev1.Node{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "test",
+		},
+	}
+	fakeClient := schedulingfake.NewSimpleClientset().SchedulingV1alpha1().Devices()
+	ctl := gomock.NewController(t)
+	mockMetricCache := mock_metriccache.NewMockMetricCache(ctl)
+	var gpuDeviceInfo koordletutil.GPUDevices
+	gpuDeviceInfo = []koordletutil.GPUDeviceInfo{
+		{UUID: "healthy-gpu-1", BusID: "0000:44:00.0", NodeID: 0, PCIE: "pci0000:3a", Minor: 0, MemoryTotal: 8000},
+		{UUID: "healthy-gpu-2", BusID: "0000:4d:00.0", NodeID: 0, PCIE: "pci0000:4a", Minor: 1, MemoryTotal: 8000},
+		{UUID: "unhealthy-gpu", BusID: "0000:58:00.0", NodeID: 0, PCIE: "pci0000:54", Minor: 2, MemoryTotal: 8000},
+	}
+	mockMetricCache.EXPECT().Get(koordletutil.GPUDeviceType).Return(gpuDeviceInfo, true)
+	mockMetricCache.EXPECT().Get(koordletutil.RDMADeviceType).Return(nil, false)
+	mockMetricCache.EXPECT().Get(koordletutil.XPUDeviceType).Return(nil, false)
+	r := &statesInformer{
+		config: &Config{
+			XPUEnforceCollectFromDeviceInfos: false,
+		},
+		deviceClient: fakeClient,
+		metricsCache: mockMetricCache,
+		states: &PluginState{
+			informerPlugins: map[PluginName]informerPlugin{
+				nodeInformerName: &nodeInformer{
+					node: testNode,
+				},
+			},
+		},
+		getGPUDriverAndModelFunc: func() (string, string) {
+			return "A100", "470"
+		},
+	}
+
+	// Mark a GPU as unhealthy
+	r.unhealthyGPU = map[string]*unhealthyGPUInfo{
+		"0000:58:00.0": {
+			errCode:    "Xid44",
+			errMessage: "Xid error detected on device, error code: 44",
+		},
+	}
+
+	r.reportDevice()
+	device, err := fakeClient.Get(context.TODO(), "test", metav1.GetOptions{})
+	assert.Equal(t, nil, err)
+
+	// Verify the number of Devices
+	assert.Equal(t, 3, len(device.Spec.Devices))
+
+	for _, dev := range device.Spec.Devices {
+		if dev.Topology.BusID == "0000:58:00.0" {
+			// Unhealthy GPUs should have conditions
+			assert.NotNil(t, dev.Conditions)
+			assert.Equal(t, 1, len(dev.Conditions))
+			condition := dev.Conditions[0]
+			assert.Equal(t, string(schedulingv1alpha1.DeviceConditionHealthy), condition.Type)
+			assert.Equal(t, metav1.ConditionFalse, condition.Status)
+			assert.Equal(t, "Xid44", condition.Reason)
+			assert.Equal(t, "Xid error detected on device, error code: 44", condition.Message)
+			assert.NotEmpty(t, condition.LastTransitionTime)
+		} else {
+			// Healthy GPUs should have nil Conditions
+			assert.Nil(t, dev.Conditions)
+		}
+	}
+}
diff --git a/pkg/koordlet/util/system/gpu_test.go b/pkg/koordlet/util/system/gpu_test.go
new file mode 100644
index 00000000..d383f9fe
--- /dev/null
+++ b/pkg/koordlet/util/system/gpu_test.go
@@ -0,0 +1,75 @@
+/*
+Copyright 2022 The Koordinator Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package system
+
+import (
+	"path/filepath"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetGPUDevicePCIBusIDs(t *testing.T) {
+	helper := NewFileTestUtil(t)
+	defer helper.Cleanup()
+
+	type args struct {
+		dir   string
+		files []string
+	}
+
+	tests := []struct {
+		name string
+		args args
+		want []string
+	}{
+		{
+			name: "case1: dir exist",
+			args: args{
+				dir: filepath.Join(helper.TempDir, "/sys/bus/pci/drivers/nvidia/"),
+				files: []string{
+					"0000:3b:00.1",
+					"0000:01:00.0",
+					"0000:af:ff.7",
+					"bind",
+					"new_id",
+					"unbind",
+					"uevent",
+				},
+			},
+			want: []string{"0000:01:00.0", "0000:3b:00.1", "0000:af:ff.7"},
+		},
+		{
+			name: "case2: dir not exist",
+			args: args{
+				dir:   filepath.Join(helper.TempDir, "/path/not/exist"),
+				files: []string{},
+			},
+			want: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			NVIDIADriverDir = tt.args.dir
+			for _, driverFile := range tt.args.files {
+				helper.CreateFile(filepath.Join(NVIDIADriverDir, driverFile))
+			}
+			got := GetGPUDevicePCIBusIDs()
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
diff --git a/pkg/scheduler/frameworkext/fake_test.go b/pkg/scheduler/frameworkext/fake_test.go
new file mode 100644
index 00000000..c303fba7
--- /dev/null
+++ b/pkg/scheduler/frameworkext/fake_test.go
@@ -0,0 +1,279 @@
+/*
+Copyright 2022 The Koordinator Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package frameworkext
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
+)
+
+func TestFakeNominator_NominatedReservePodForNode(t *testing.T) {
+	tests := []struct {
+		name             string
+		nominatedPods    map[string][]*corev1.Pod
+		nodeName         string
+		expectedPodCount int
+	}{
+		{
+			name:             "empty nominator",
+			nominatedPods:    map[string][]*corev1.Pod{},
+			nodeName:         "test-node",
+			expectedPodCount: 0,
+		},
+		{
+			name: "single nominated pod on node",
+			nominatedPods: map[string][]*corev1.Pod{
+				"test-node": {
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-1",
+							Namespace: "default",
+							UID:       types.UID("pod-1-uid"),
+						},
+					},
+				},
+			},
+			nodeName:         "test-node",
+			expectedPodCount: 1,
+		},
+		{
+			name: "multiple nominated pods on same node",
+			nominatedPods: map[string][]*corev1.Pod{
+				"test-node": {
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-1",
+							Namespace: "default",
+							UID:       types.UID("pod-1-uid"),
+						},
+					},
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-2",
+							Namespace: "default",
+							UID:       types.UID("pod-2-uid"),
+						},
+					},
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-3",
+							Namespace: "default",
+							UID:       types.UID("pod-3-uid"),
+						},
+					},
+				},
+			},
+			nodeName:         "test-node",
+			expectedPodCount: 3,
+		},
+		{
+			name: "nominated pods on different nodes",
+			nominatedPods: map[string][]*corev1.Pod{
+				"test-node": {
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-1",
+							Namespace: "default",
+							UID:       types.UID("pod-1-uid"),
+						},
+					},
+				},
+				"other-node": {
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-2",
+							Namespace: "default",
+							UID:       types.UID("pod-2-uid"),
+						},
+					},
+				},
+			},
+			nodeName:         "test-node",
+			expectedPodCount: 1,
+		},
+		{
+			name: "query non-existent node",
+			nominatedPods: map[string][]*corev1.Pod{
+				"other-node": {
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name:      "pod-1",
+							Namespace: "default",
+							UID:       types.UID("pod-1-uid"),
+						},
+					},
+				},
+			},
+			nodeName:         "test-node",
+			expectedPodCount: 0,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			nominator := NewFakeReservationNominator()
+
+			// Add nominated pods
+			for nodeName, pods := range tt.nominatedPods {
+				for _, pod := range pods {
+					nominator.AddNominatedReservePod(pod, nodeName)
+				}
+			}
+
+			// Get nominated pods for the test node
+			result := nominator.NominatedReservePodForNode(tt.nodeName)
+
+			// Verify the count
+			assert.Equal(t, tt.expectedPodCount, len(result), "unexpected number of nominated pods")
+
+			// Verify that the result is a deep copy
+			if len(result) > 0 {
+				// Modify the returned PodInfo to ensure it doesn't affect the internal state
+				originalUID := result[0].Pod.UID
+				result[0].Pod.UID = "modified-uid"
+
+				// Get the pods again to verify the original data is unchanged
+				resultAgain := nominator.NominatedReservePodForNode(tt.nodeName)
+				assert.Equal(t, originalUID, resultAgain[0].Pod.UID, "deep copy should protect internal state")
+
+				// Verify that the pods match what was added
+				expectedPods := tt.nominatedPods[tt.nodeName]
+				for i, podInfo := range resultAgain {
+					assert.Equal(t, expectedPods[i].UID, podInfo.Pod.UID, "pod UID should match")
+					assert.Equal(t, expectedPods[i].Name, podInfo.Pod.Name, "pod name should match")
+					assert.Equal(t, expectedPods[i].Namespace, podInfo.Pod.Namespace, "pod namespace should match")
+				}
+			}
+		})
+	}
+}
+
+func TestFakeNominator_NominatedReservePodForNode_Concurrency(t *testing.T) {
+	nominator := NewFakeReservationNominator()
+
+	pod := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "test-pod",
+			Namespace: "default",
+			UID:       types.UID("test-pod-uid"),
+		},
+	}
+
+	nodeName := "test-node"
+	nominator.AddNominatedReservePod(pod, nodeName)
+
+	// Test concurrent reads to ensure thread safety
+	done := make(chan bool, 10)
+	for i := 0; i < 10; i++ {
+		go func() {
+			result := nominator.NominatedReservePodForNode(nodeName)
+			assert.Equal(t, 1, len(result))
+			assert.Equal(t, pod.UID, result[0].Pod.UID)
+			done <- true
+		}()
+	}
+
+	// Wait for all goroutines to complete
+	for i := 0; i < 10; i++ {
+		<-done
+	}
+}
+
+func TestFakeNominator_NominatedReservePodForNode_AfterDelete(t *testing.T) {
+	nominator := NewFakeReservationNominator()
+
+	pod1 := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "pod-1",
+			Namespace: "default",
+			UID:       types.UID("pod-1-uid"),
+		},
+	}
+
+	pod2 := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "pod-2",
+			Namespace: "default",
+			UID:       types.UID("pod-2-uid"),
+		},
+	}
+
+	nodeName := "test-node"
+
+	// Add two pods
+	nominator.AddNominatedReservePod(pod1, nodeName)
+	nominator.AddNominatedReservePod(pod2, nodeName)
+
+	result := nominator.NominatedReservePodForNode(nodeName)
+	assert.Equal(t, 2, len(result))
+
+	// Delete one pod
+	nominator.DeleteNominatedReservePod(pod1)
+
+	result = nominator.NominatedReservePodForNode(nodeName)
+	assert.Equal(t, 1, len(result))
+	assert.Equal(t, pod2.UID, result[0].Pod.UID)
+
+	// Delete the second pod
+	nominator.DeleteNominatedReservePod(pod2)
+
+	result = nominator.NominatedReservePodForNode(nodeName)
+	assert.Equal(t, 0, len(result))
+}
+
+func TestFakeNominator_NominatedReservePodForNode_UpdatePod(t *testing.T) {
+	nominator := NewFakeReservationNominator()
+
+	pod := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "test-pod",
+			Namespace: "default",
+			UID:       types.UID("test-pod-uid"),
+		},
+	}
+
+	nodeName1 := "node-1"
+	nodeName2 := "node-2"
+
+	// Add pod to node-1
+	nominator.AddNominatedReservePod(pod, nodeName1)
+
+	result := nominator.NominatedReservePodForNode(nodeName1)
+	assert.Equal(t, 1, len(result))
+
+	// Re-add the same pod to node-2 (should remove from node-1)
+	nominator.AddNominatedReservePod(pod, nodeName2)
+
+	result = nominator.NominatedReservePodForNode(nodeName1)
+	assert.Equal(t, 0, len(result), "pod should be removed from node-1")
+
+	result = nominator.NominatedReservePodForNode(nodeName2)
+	assert.Equal(t, 1, len(result), "pod should be on node-2")
+	assert.Equal(t, pod.UID, result[0].Pod.UID)
+}
+
+func TestFakeNominator_NominatedReservePodForNode_EmptyNodeName(t *testing.T) {
+	nominator := NewFakeReservationNominator()
+
+	result := nominator.NominatedReservePodForNode("")
+	assert.NotNil(t, result, "should return non-nil slice")
+	assert.Equal(t, 0, len(result), "should return empty slice for empty node name")
+}
diff --git a/pkg/scheduler/plugins/coscheduling/core/core_test.go b/pkg/scheduler/plugins/coscheduling/core/core_test.go
index 16981f3e..51b78373 100644
--- a/pkg/scheduler/plugins/coscheduling/core/core_test.go
+++ b/pkg/scheduler/plugins/coscheduling/core/core_test.go
@@ -634,12 +634,19 @@ func TestGetGangBindingInfo(t *testing.T) {
 					gang.addAssumedPod(pod)
 				}
 			}
-			// Add test pod to gang
+			// Add test pod to gang and simulate AllowGangGroup
 			if !tt.wantNil {
 				gangId := util.GetId(tt.pod.Namespace, util.GetGangNameByPod(tt.pod))
 				gang := mgr.pgMgr.cache.getGangFromCacheByGangId(gangId, false)
 				if gang != nil {
 					gang.addAssumedPod(tt.pod)
+					// Simulate AllowGangGroup by setting BindingMembers
+					memberPods := sets.New[string]()
+					memberPods.Insert(string(tt.pod.UID))
+					for _, pod := range tt.pods {
+						memberPods.Insert(string(pod.UID))
+					}
+					gang.GangGroupInfo.SetBindingMembers(memberPods)
 				}
 			}
 
diff --git a/pkg/scheduler/plugins/coscheduling/coscheduling_test.go b/pkg/scheduler/plugins/coscheduling/coscheduling_test.go
index 98a615fe..5870c3a2 100644
--- a/pkg/scheduler/plugins/coscheduling/coscheduling_test.go
+++ b/pkg/scheduler/plugins/coscheduling/coscheduling_test.go
@@ -643,6 +643,7 @@ func TestPreBind(t *testing.T) {
 		expectGangGroupID   string
 		expectMemberCount   string
 		podHasExistingLabel bool
+		onceSatisfied       bool
 	}{
 		{
 			name: "gang satisfied, should set labels on pod",
@@ -677,6 +678,30 @@ func TestPreBind(t *testing.T) {
 			expectMemberCount:   "2",
 			podHasExistingLabel: true,
 		},
+		{
+			name: "gang OnceSatisfied with retry pod, should not set gang annotations",
+			pg:   makePg("gangRetry", "gangRetry_ns", 2, &gangCreatedTime, nil),
+			pod:  st.MakePod().Name("pod-retry").UID("pod-retry").Namespace("gangRetry_ns").Label(v1alpha1.PodGroupLabel, "gangRetry").Obj(),
+			pods: []*corev1.Pod{
+				st.MakePod().Name("pod-bound-1").UID("pod-bound-1").Namespace("gangRetry_ns").Label(v1alpha1.PodGroupLabel, "gangRetry").Obj(),
+			},
+			expectLabelsSet:   true,
+			expectGangGroupID: "gangRetry_ns/gangRetry",
+			expectMemberCount: "2",
+			onceSatisfied:     true,
+		},
+		{
+			name: "gang oversub: min=2, total=3, all pods should get consistent memberCount=2",
+			pg:   makePg("gangOversub", "gangOversub_ns", 2, &gangCreatedTime, nil),
+			pod:  st.MakePod().Name("pod-oversub-3").UID("pod-oversub-3").Namespace("gangOversub_ns").Label(v1alpha1.PodGroupLabel, "gangOversub").Obj(),
+			pods: []*corev1.Pod{
+				st.MakePod().Name("pod-oversub-1").UID("pod-oversub-1").Namespace("gangOversub_ns").Label(v1alpha1.PodGroupLabel, "gangOversub").Obj(),
+				st.MakePod().Name("pod-oversub-2").UID("pod-oversub-2").UID("pod-oversub-2").Namespace("gangOversub_ns").Label(v1alpha1.PodGroupLabel, "gangOversub").Obj(),
+			},
+			expectLabelsSet:   true,
+			expectGangGroupID: "gangOversub_ns/gangOversub",
+			expectMemberCount: "2",
+		},
 	}
 
 	for _, tt := range tests {
@@ -705,14 +730,34 @@ func TestPreBind(t *testing.T) {
 
 			// Make gang satisfied if needed
 			if len(tt.pods) > 0 {
-				// Let first pod enter Permit and be assumed
-				status1, _ := gp.Permit(ctx, cycleState, tt.pod, "")
-				assert.Equal(t, framework.Wait, status1.Code())
+				if tt.onceSatisfied {
+					// For OnceSatisfied case: simulate first round gang scheduling completed
+					// First pod enters Permit and waits
+					status1, _ := gp.Permit(ctx, cycleState, tt.pod, "")
+					assert.Equal(t, framework.Wait, status1.Code())
+
+					// Other pods enter Permit and gang becomes satisfied
+					for _, pod := range tt.pods {
+						status2, _ := gp.Permit(ctx, cycleState, pod, "")
+						assert.Equal(t, framework.Success, status2.Code())
+					}
 
-				// Let second pod enter Permit and satisfy the gang requirements
-				for _, pod := range tt.pods {
-					status2, _ := gp.Permit(ctx, cycleState, pod, "")
-					assert.Equal(t, framework.Success, status2.Code())
+					// Simulate first pod bound, triggering OnceSatisfied
+					gp.PostBind(ctx, cycleState, tt.pods[0], "node-1")
+
+					// Now the retry pod (tt.pod) enters Permit directly (OnceSatisfied path)
+					retryStatus, _ := gp.Permit(ctx, cycleState, tt.pod, "")
+					assert.Equal(t, framework.Success, retryStatus.Code())
+				} else {
+					// Normal gang scheduling: Let first pod enter Permit and be assumed
+					status1, _ := gp.Permit(ctx, cycleState, tt.pod, "")
+					assert.Equal(t, framework.Wait, status1.Code())
+
+					// Let second pod enter Permit and satisfy the gang requirements
+					for _, pod := range tt.pods {
+						status2, _ := gp.Permit(ctx, cycleState, pod, "")
+						assert.Equal(t, framework.Success, status2.Code())
+					}
 				}
 			}
 
diff --git a/pkg/scheduler/plugins/deviceshare/device_plugin_adapter_test.go b/pkg/scheduler/plugins/deviceshare/device_plugin_adapter_test.go
index 0ada56f9..f4e92194 100644
--- a/pkg/scheduler/plugins/deviceshare/device_plugin_adapter_test.go
+++ b/pkg/scheduler/plugins/deviceshare/device_plugin_adapter_test.go
@@ -27,7 +27,6 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	kubefake "k8s.io/client-go/kubernetes/fake"
 	fakeclock "k8s.io/utils/clock/testing"
 
 	apiext "github.com/koordinator-sh/koordinator/apis/extension"
@@ -483,16 +482,14 @@ func TestCambriconGPUDevicePluginAdapter_Adapt(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			client := kubefake.NewSimpleClientset(tt.node)
-			err := adapter.Adapt(&DevicePluginAdaptContext{
+			ctx := &DevicePluginAdaptContext{
 				Context: context.TODO(),
-				client:  client,
-				node:    tt.node,
-			}, tt.args.object, tt.args.allocation)
+				node:    tt.node.DeepCopy(),
+			}
+			err := adapter.Adapt(ctx, tt.args.object, tt.args.allocation)
 			assert.Equal(t, tt.wantErr, err != nil, err)
 			assert.Equal(t, tt.wantObject, tt.args.object)
-			node, _ := client.CoreV1().Nodes().Get(context.TODO(), tt.node.Name, metav1.GetOptions{})
-			assert.Equal(t, tt.wantNode, node)
+			assert.Equal(t, tt.wantNode, ctx.node)
 		})
 	}
 }
@@ -852,11 +849,9 @@ func TestPlugin_adaptForDevicePlugin(t *testing.T) {
 			wantErr: true,
 			wantObject: &corev1.Pod{
 				ObjectMeta: metav1.ObjectMeta{
-					Name:      "test-pod",
-					Namespace: "default",
-					Annotations: map[string]string{
-						AnnotationBindTimestamp: strconv.FormatInt(now.UnixNano(), 10),
-					},
+					Name:        "test-pod",
+					Namespace:   "default",
+					Annotations: map[string]string{},
 				},
 			},
 			wantNode: &corev1.Node{
diff --git a/pkg/scheduler/plugins/deviceshare/devicehandler_default_test.go b/pkg/scheduler/plugins/deviceshare/devicehandler_default_test.go
index 83a4f485..220033c1 100644
--- a/pkg/scheduler/plugins/deviceshare/devicehandler_default_test.go
+++ b/pkg/scheduler/plugins/deviceshare/devicehandler_default_test.go
@@ -51,6 +51,26 @@ func TestDefaultDeviceHandler_CalcDesiredRequestsAndCount(t *testing.T) {
 
 	cache := newNodeDeviceCache()
 	cache.updateNodeDevice(fakeDeviceCRCopy.Name, fakeDeviceCRCopy)
+	nodeDeviceInfo := cache.getNodeDevice(fakeDeviceCRCopy.Name, false)
+	assert.Equal(t, map[schedulingv1alpha1.DeviceType]map[int32]int{
+		schedulingv1alpha1.GPU: {
+			0: 0,
+			1: 0,
+			2: 0,
+			3: 0,
+			4: 1,
+			5: 1,
+			6: 1,
+			7: 1,
+		},
+		schedulingv1alpha1.RDMA: {
+			1: 0,
+			2: 0,
+			3: 1,
+			4: 1,
+			5: 1,
+		},
+	}, nodeDeviceInfo.numaTopology.deviceToNodeID)
 
 	resources := corev1.ResourceList{
 		apiext.ResourceRDMA: resource.MustParse("100"),
diff --git a/pkg/scheduler/plugins/deviceshare/eventhandler_pod_test.go b/pkg/scheduler/plugins/deviceshare/eventhandler_pod_test.go
index e704f7e8..aaf40deb 100644
--- a/pkg/scheduler/plugins/deviceshare/eventhandler_pod_test.go
+++ b/pkg/scheduler/plugins/deviceshare/eventhandler_pod_test.go
@@ -365,6 +365,135 @@ func Test_nodeDeviceCache_onPodUpdate(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "old pod without NodeName should not leak",
+			oldPod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					UID:       "123456789",
+					Namespace: "default",
+					Name:      "test",
+					Annotations: map[string]string{
+						apiext.AnnotationDeviceAllocated: `{"gpu":[{"minor":1,"resources":{"koordinator.sh/gpu-core":"60","koordinator.sh/gpu-memory":"8Gi","koordinator.sh/gpu-memory-ratio":"50"}}]}`,
+					},
+				},
+				Spec: corev1.PodSpec{
+					// NodeName is empty, pod is not assigned to a node yet
+					Containers: []corev1.Container{
+						{
+							Name: "test-container-a",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									apiext.ResourceGPUCore:        resource.MustParse("60"),
+									apiext.ResourceGPUMemoryRatio: resource.MustParse("50"),
+									apiext.ResourceGPUMemory:      resource.MustParse("8Gi"),
+								},
+							},
+						},
+					},
+				},
+				Status: corev1.PodStatus{
+					Phase: corev1.PodPending,
+				},
+			},
+			pod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					UID:       "123456789",
+					Namespace: "default",
+					Name:      "test",
+					Annotations: map[string]string{
+						apiext.AnnotationDeviceAllocated: `{"gpu":[{"minor":1,"resources":{"koordinator.sh/gpu-core":"60","koordinator.sh/gpu-memory":"8Gi","koordinator.sh/gpu-memory-ratio":"50"}}]}`,
+					},
+				},
+				Spec: corev1.PodSpec{
+					NodeName: "test-node",
+					Containers: []corev1.Container{
+						{
+							Name: "test-container-a",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									apiext.ResourceGPUCore:        resource.MustParse("60"),
+									apiext.ResourceGPUMemoryRatio: resource.MustParse("50"),
+									apiext.ResourceGPUMemory:      resource.MustParse("8Gi"),
+								},
+							},
+						},
+					},
+				},
+				Status: corev1.PodStatus{
+					Phase: corev1.PodRunning,
+				},
+			},
+			deviceCache: &nodeDeviceCache{
+				nodeDeviceInfos: map[string]*nodeDevice{
+					"test-node": {
+						deviceFree: map[schedulingv1alpha1.DeviceType]deviceResources{
+							schedulingv1alpha1.GPU: {
+								1: corev1.ResourceList{
+									apiext.ResourceGPUCore:        resource.MustParse("100"),
+									apiext.ResourceGPUMemoryRatio: resource.MustParse("100"),
+									apiext.ResourceGPUMemory:      resource.MustParse("16Gi"),
+								},
+							},
+						},
+						deviceTotal: map[schedulingv1alpha1.DeviceType]deviceResources{
+							schedulingv1alpha1.GPU: {
+								1: corev1.ResourceList{
+									apiext.ResourceGPUCore:        resource.MustParse("100"),
+									apiext.ResourceGPUMemoryRatio: resource.MustParse("100"),
+									apiext.ResourceGPUMemory:      resource.MustParse("16Gi"),
+								},
+							},
+						},
+						deviceUsed: map[schedulingv1alpha1.DeviceType]deviceResources{
+							schedulingv1alpha1.GPU: {},
+						},
+						allocateSet: make(map[schedulingv1alpha1.DeviceType]map[types.NamespacedName]deviceResources),
+					},
+				},
+			},
+			wantCache: map[string]*nodeDevice{
+				"test-node": {
+					deviceFree: map[schedulingv1alpha1.DeviceType]deviceResources{
+						schedulingv1alpha1.GPU: {
+							1: corev1.ResourceList{
+								apiext.ResourceGPUCore:        *resource.NewQuantity(40, resource.DecimalSI),
+								apiext.ResourceGPUMemoryRatio: *resource.NewQuantity(50, resource.DecimalSI),
+								apiext.ResourceGPUMemory:      resource.MustParse("8Gi"),
+							},
+						},
+					},
+					deviceTotal: map[schedulingv1alpha1.DeviceType]deviceResources{
+						schedulingv1alpha1.GPU: {
+							1: corev1.ResourceList{
+								apiext.ResourceGPUCore:        resource.MustParse("100"),
+								apiext.ResourceGPUMemoryRatio: resource.MustParse("100"),
+								apiext.ResourceGPUMemory:      resource.MustParse("16Gi"),
+							},
+						},
+					},
+					deviceUsed: map[schedulingv1alpha1.DeviceType]deviceResources{
+						schedulingv1alpha1.GPU: {
+							1: corev1.ResourceList{
+								apiext.ResourceGPUCore:        resource.MustParse("60"),
+								apiext.ResourceGPUMemoryRatio: resource.MustParse("50"),
+								apiext.ResourceGPUMemory:      resource.MustParse("8Gi"),
+							},
+						},
+					},
+					allocateSet: map[schedulingv1alpha1.DeviceType]map[types.NamespacedName]deviceResources{
+						schedulingv1alpha1.GPU: {
+							podNamespacedName: {
+								1: corev1.ResourceList{
+									apiext.ResourceGPUCore:        resource.MustParse("60"),
+									apiext.ResourceGPUMemoryRatio: resource.MustParse("50"),
+									apiext.ResourceGPUMemory:      resource.MustParse("8Gi"),
+								},
+							},
+						},
+					},
+				},
+			},
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/scheduler/plugins/deviceshare/topology_hint_test.go b/pkg/scheduler/plugins/deviceshare/topology_hint_test.go
index 2e68b5cf..3fc85917 100644
--- a/pkg/scheduler/plugins/deviceshare/topology_hint_test.go
+++ b/pkg/scheduler/plugins/deviceshare/topology_hint_test.go
@@ -416,3 +416,41 @@ func TestPlugin_Allocate(t *testing.T) {
 		})
 	}
 }
+
+func Test_generateDesignatedHints(t *testing.T) {
+	type args struct {
+		allocations apiext.DeviceAllocations
+		topology    *NUMATopology
+	}
+	affinityNode1, _ := bitmask.NewBitMask(1)
+	tests := []struct {
+		name  string
+		args  args
+		want  map[string][]topologymanager.NUMATopologyHint
+		want1 *framework.Status
+	}{
+		{
+			name: "generate hints",
+			args: args{
+				allocations: apiext.DeviceAllocations{
+					schedulingv1alpha1.GPU: {
+						{
+							Minor: 5,
+						},
+					},
+				},
+				topology: newNUMATopology(fakeDeviceCR),
+			},
+			want: map[string][]topologymanager.NUMATopologyHint{
+				string(schedulingv1alpha1.GPU): {topologymanager.NUMATopologyHint{NUMANodeAffinity: affinityNode1, Unsatisfied: false, Preferred: true, Score: 500}},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, got1 := generateDesignatedHints(tt.args.allocations, tt.args.topology)
+			assert.Equalf(t, tt.want, got, "generateDesignatedHints(%v, %v)", tt.args.allocations, tt.args.topology)
+			assert.Equalf(t, tt.want1, got1, "generateDesignatedHints(%v, %v)", tt.args.allocations, tt.args.topology)
+		})
+	}
+}
diff --git a/pkg/scheduler/plugins/reservation/cache_test.go b/pkg/scheduler/plugins/reservation/cache_test.go
index 7f8c248b..39ebc4ba 100644
--- a/pkg/scheduler/plugins/reservation/cache_test.go
+++ b/pkg/scheduler/plugins/reservation/cache_test.go
@@ -264,7 +264,7 @@ func TestCacheAddOrUpdateOrDeletePod(t *testing.T) {
 	expectReservationInfo.RefreshPreCalculated()
 	assert.Equal(t, expectReservationInfo, rInfo)
 
-	cache.updatePod(reservation.UID, pod, pod)
+	cache.updatePod(reservation.UID, reservation.UID, pod, pod)
 	rInfo = cache.getReservationInfoByUID(reservation.UID)
 	sort.Slice(rInfo.ResourceNames, func(i, j int) bool {
 		return rInfo.ResourceNames[i] < rInfo.ResourceNames[j]
@@ -288,3 +288,107 @@ func TestCacheAddOrUpdateOrDeletePod(t *testing.T) {
 	expectReservationInfo.RefreshPreCalculated()
 	assert.Equal(t, expectReservationInfo, rInfo)
 }
+
+func TestCacheUpdatePodAcrossReservations(t *testing.T) {
+	cache := newReservationCache(nil)
+	reservation1 := &schedulingv1alpha1.Reservation{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:  uuid.NewUUID(),
+			Name: "test-reservation-1",
+		},
+		Spec: schedulingv1alpha1.ReservationSpec{
+			Template: &corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("4000m"),
+									corev1.ResourceMemory: resource.MustParse("4Gi"),
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		Status: schedulingv1alpha1.ReservationStatus{
+			NodeName: "test-node-1",
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("4000m"),
+				corev1.ResourceMemory: resource.MustParse("4Gi"),
+			},
+		},
+	}
+	reservation2 := &schedulingv1alpha1.Reservation{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:  uuid.NewUUID(),
+			Name: "test-reservation-2",
+		},
+		Spec: schedulingv1alpha1.ReservationSpec{
+			Template: &corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("2000m"),
+									corev1.ResourceMemory: resource.MustParse("2Gi"),
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		Status: schedulingv1alpha1.ReservationStatus{
+			NodeName: "test-node-1",
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("2000m"),
+				corev1.ResourceMemory: resource.MustParse("2Gi"),
+			},
+		},
+	}
+	cache.updateReservation(reservation1)
+	cache.updateReservation(reservation2)
+
+	pod := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:       uuid.NewUUID(),
+			Namespace: "default",
+			Name:      "test-pod-1",
+		},
+		Spec: corev1.PodSpec{
+			Containers: []corev1.Container{
+				{
+					Resources: corev1.ResourceRequirements{
+						Requests: corev1.ResourceList{
+							corev1.ResourceCPU:    resource.MustParse("2000m"),
+							corev1.ResourceMemory: resource.MustParse("2Gi"),
+						},
+					},
+				},
+			},
+		},
+	}
+
+	// add pod to reservation1
+	cache.addPod(reservation1.UID, pod)
+	rInfo1 := cache.getReservationInfoByUID(reservation1.UID)
+	assert.Len(t, rInfo1.AssignedPods, 1)
+	assert.Contains(t, rInfo1.AssignedPods, pod.UID)
+
+	// move pod from reservation1 to reservation2
+	cache.updatePod(reservation1.UID, reservation2.UID, pod, pod)
+	rInfo1 = cache.getReservationInfoByUID(reservation1.UID)
+	assert.Len(t, rInfo1.AssignedPods, 0)
+	rInfo2 := cache.getReservationInfoByUID(reservation2.UID)
+	assert.Len(t, rInfo2.AssignedPods, 1)
+	assert.Contains(t, rInfo2.AssignedPods, pod.UID)
+
+	// update pod within same reservation
+	cache.updatePod(reservation2.UID, reservation2.UID, pod, pod)
+	rInfo2 = cache.getReservationInfoByUID(reservation2.UID)
+	assert.Len(t, rInfo2.AssignedPods, 1)
+	assert.Contains(t, rInfo2.AssignedPods, pod.UID)
+}
diff --git a/pkg/scheduler/plugins/reservation/controller/controller_test.go b/pkg/scheduler/plugins/reservation/controller/controller_test.go
index 88552fed..295d2f75 100644
--- a/pkg/scheduler/plugins/reservation/controller/controller_test.go
+++ b/pkg/scheduler/plugins/reservation/controller/controller_test.go
@@ -715,6 +715,73 @@ func Test_podEventHandlers(t *testing.T) {
 	assert.Equal(t, 0, len(controller.getPodsOnReservation("aaaaaa")))
 }
 
+func TestPodEventHandlerUnassignedPod(t *testing.T) {
+	fakeClientSet := kubefake.NewSimpleClientset()
+	fakeKoordClientSet := koordfake.NewSimpleClientset()
+	sharedInformerFactory := informers.NewSharedInformerFactory(fakeClientSet, 0)
+	koordSharedInformerFactory := koordinformers.NewSharedInformerFactory(fakeKoordClientSet, 0)
+
+	reservation := &schedulingv1alpha1.Reservation{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:  "test-reservation-uid",
+			Name: "test-reservation",
+		},
+		Spec: schedulingv1alpha1.ReservationSpec{
+			Template: &corev1.PodTemplateSpec{},
+		},
+		Status: schedulingv1alpha1.ReservationStatus{
+			Phase:    schedulingv1alpha1.ReservationAvailable,
+			NodeName: "test-node-1",
+		},
+	}
+	_, err := fakeKoordClientSet.SchedulingV1alpha1().Reservations().Create(context.TODO(), reservation, metav1.CreateOptions{})
+	assert.NoError(t, err)
+
+	controller := New(sharedInformerFactory, koordSharedInformerFactory, fakeClientSet, fakeKoordClientSet, &config.ReservationArgs{})
+
+	sharedInformerFactory.Start(nil)
+	koordSharedInformerFactory.Start(nil)
+	sharedInformerFactory.WaitForCacheSync(nil)
+	koordSharedInformerFactory.WaitForCacheSync(nil)
+
+	// test pod becoming unassigned (multi-scheduler scenario)
+	oldPod := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:       "test-pod-uid",
+			Name:      "test-pod",
+			Namespace: "test-ns",
+			Annotations: map[string]string{
+				apiext.AnnotationReservationAllocated: `{"name": "test-reservation", "uid": "test-reservation-uid"}`,
+			},
+		},
+		Spec: corev1.PodSpec{
+			NodeName: "test-node-1",
+		},
+	}
+	newPod := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:       "test-pod-uid",
+			Name:      "test-pod",
+			Namespace: "test-ns",
+			Annotations: map[string]string{
+				apiext.AnnotationReservationAllocated: `{"name": "test-reservation", "uid": "test-reservation-uid"}`,
+			},
+		},
+		Spec: corev1.PodSpec{
+			NodeName: "", // became unassigned
+		},
+	}
+
+	// add pod to controller cache
+	controller.onPodAdd(oldPod)
+	assert.Equal(t, 1, len(controller.getPodsOnReservation("test-reservation-uid")))
+
+	// update pod to unassigned state
+	controller.onPodUpdate(oldPod, newPod)
+	assert.Equal(t, 0, len(controller.getPodsOnReservation("test-reservation-uid")))
+	assert.Equal(t, 0, len(controller.getPodsOnNode("test-node-1")))
+}
+
 func TestNew(t *testing.T) {
 	tests := []struct {
 		name                 string
diff --git a/pkg/scheduler/plugins/reservation/pod_eventhandler_test.go b/pkg/scheduler/plugins/reservation/pod_eventhandler_test.go
index e894adf4..259e2214 100644
--- a/pkg/scheduler/plugins/reservation/pod_eventhandler_test.go
+++ b/pkg/scheduler/plugins/reservation/pod_eventhandler_test.go
@@ -218,3 +218,99 @@ func TestPodEventHandlerWithOperatingPod(t *testing.T) {
 	rInfo = handler.cache.getReservationInfoByUID(reservationUID)
 	assert.Nil(t, rInfo)
 }
+
+func TestPodEventHandlerUpdatePodAcrossReservations(t *testing.T) {
+	handler := &podEventHandler{
+		cache:     newReservationCache(nil),
+		nominator: newNominator(nil, nil),
+	}
+	reservation1UID := uuid.NewUUID()
+	reservation1Name := "test-reservation-1"
+	reservation1 := &schedulingv1alpha1.Reservation{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: reservation1Name,
+			UID:  reservation1UID,
+		},
+		Spec: schedulingv1alpha1.ReservationSpec{
+			Template: &corev1.PodTemplateSpec{},
+		},
+		Status: schedulingv1alpha1.ReservationStatus{
+			Phase:    schedulingv1alpha1.ReservationAvailable,
+			NodeName: "test-node-1",
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU: resource.MustParse("4"),
+			},
+		},
+	}
+	reservation2UID := uuid.NewUUID()
+	reservation2Name := "test-reservation-2"
+	reservation2 := &schedulingv1alpha1.Reservation{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: reservation2Name,
+			UID:  reservation2UID,
+		},
+		Spec: schedulingv1alpha1.ReservationSpec{
+			Template: &corev1.PodTemplateSpec{},
+		},
+		Status: schedulingv1alpha1.ReservationStatus{
+			Phase:    schedulingv1alpha1.ReservationAvailable,
+			NodeName: "test-node-1",
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU: resource.MustParse("4"),
+			},
+		},
+	}
+	handler.cache.updateReservation(reservation1)
+	handler.cache.updateReservation(reservation2)
+
+	pod := &corev1.Pod{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "test-pod",
+			Namespace: "default",
+			UID:       uuid.NewUUID(),
+		},
+		Spec: corev1.PodSpec{
+			NodeName: "test-node-1",
+			Containers: []corev1.Container{
+				{
+					Name: "main",
+					Resources: corev1.ResourceRequirements{
+						Requests: corev1.ResourceList{
+							corev1.ResourceCPU: resource.MustParse("2"),
+						},
+					},
+				},
+			},
+		},
+	}
+
+	// assign pod to reservation1
+	oldPod := pod.DeepCopy()
+	apiext.SetReservationAllocated(oldPod, reservation1)
+	handler.updatePod(nil, oldPod)
+	rInfo1 := handler.cache.getReservationInfoByUID(reservation1UID)
+	assert.Len(t, rInfo1.AssignedPods, 1)
+	assert.Contains(t, rInfo1.AssignedPods, oldPod.UID)
+	rInfo2 := handler.cache.getReservationInfoByUID(reservation2UID)
+	assert.Len(t, rInfo2.AssignedPods, 0)
+
+	// move pod from reservation1 to reservation2
+	newPod := pod.DeepCopy()
+	apiext.SetReservationAllocated(newPod, reservation2)
+	handler.updatePod(oldPod, newPod)
+	rInfo1 = handler.cache.getReservationInfoByUID(reservation1UID)
+	assert.Len(t, rInfo1.AssignedPods, 0)
+	rInfo2 = handler.cache.getReservationInfoByUID(reservation2UID)
+	assert.Len(t, rInfo2.AssignedPods, 1)
+	assert.Contains(t, rInfo2.AssignedPods, newPod.UID)
+
+	// remove reservation allocated
+	oldPod = newPod.DeepCopy()
+	newPod = newPod.DeepCopy()
+	delete(newPod.Annotations, apiext.AnnotationReservationAllocated)
+	handler.updatePod(oldPod, newPod)
+	rInfo1 = handler.cache.getReservationInfoByUID(reservation1UID)
+	assert.Len(t, rInfo1.AssignedPods, 0)
+	rInfo2 = handler.cache.getReservationInfoByUID(reservation2UID)
+	assert.Len(t, rInfo2.AssignedPods, 0)
+}
diff --git a/pkg/scheduler/plugins/reservation/transformer_benchmark_test.go b/pkg/scheduler/plugins/reservation/transformer_benchmark_test.go
index c1703851..f121a3e8 100644
--- a/pkg/scheduler/plugins/reservation/transformer_benchmark_test.go
+++ b/pkg/scheduler/plugins/reservation/transformer_benchmark_test.go
@@ -372,7 +372,7 @@ func BenchmarkBeforePrefilterWithUnmatchedPod(b *testing.B) {
 					},
 				},
 			}
-			pl.reservationCache.updatePod(reservation.UID, nil, pod)
+			pl.reservationCache.updatePod(reservation.UID, reservation.UID, nil, pod)
 			nodeInfo.AddPod(pod)
 			assert.NoError(b, pl.handle.Scheduler().GetCache().AddPod(klog.Background(), pod))
 		}
@@ -783,7 +783,7 @@ func BenchmarkBeforePrefilterWithUnmatchedPodEnableLazyReservationRestore(b *tes
 					},
 				},
 			}
-			pl.reservationCache.updatePod(reservation.UID, nil, pod)
+			pl.reservationCache.updatePod(reservation.UID, reservation.UID, nil, pod)
 			nodeInfo.AddPod(pod)
 			assert.NoError(b, pl.handle.Scheduler().GetCache().AddPod(klog.Background(), pod))
 		}
diff --git a/pkg/scheduler/plugins/reservation/transformer_test.go b/pkg/scheduler/plugins/reservation/transformer_test.go
index 81ef75e1..8059b158 100644
--- a/pkg/scheduler/plugins/reservation/transformer_test.go
+++ b/pkg/scheduler/plugins/reservation/transformer_test.go
@@ -35,6 +35,7 @@ import (
 	apiext "github.com/koordinator-sh/koordinator/apis/extension"
 	schedulingv1alpha1 "github.com/koordinator-sh/koordinator/apis/scheduling/v1alpha1"
 	"github.com/koordinator-sh/koordinator/pkg/scheduler/frameworkext"
+	"github.com/koordinator-sh/koordinator/pkg/scheduler/frameworkext/hinter"
 	reservationutil "github.com/koordinator-sh/koordinator/pkg/util/reservation"
 )
 
@@ -1925,3 +1926,142 @@ func Test_parseSpecificNodesFromAffinity(t *testing.T) {
 		})
 	}
 }
+
+func TestAfterPreFilter_WithSchedulingHint(t *testing.T) {
+	node1 := &corev1.Node{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "test-node-1",
+		},
+		Status: corev1.NodeStatus{
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("32"),
+				corev1.ResourceMemory: resource.MustParse("64Gi"),
+			},
+		},
+	}
+	node2 := &corev1.Node{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: "test-node-2",
+		},
+		Status: corev1.NodeStatus{
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("32"),
+				corev1.ResourceMemory: resource.MustParse("64Gi"),
+			},
+		},
+	}
+
+	reservation := &schedulingv1alpha1.Reservation{
+		ObjectMeta: metav1.ObjectMeta{
+			UID:  uuid.NewUUID(),
+			Name: "test-reservation",
+		},
+		Spec: schedulingv1alpha1.ReservationSpec{
+			Owners: []schedulingv1alpha1.ReservationOwner{
+				{
+					LabelSelector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							"test-reservation": "true",
+						},
+					},
+				},
+			},
+			Template: &corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("4"),
+									corev1.ResourceMemory: resource.MustParse("8Gi"),
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		Status: schedulingv1alpha1.ReservationStatus{
+			Phase:    schedulingv1alpha1.ReservationAvailable,
+			NodeName: node1.Name,
+			Allocatable: corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("4"),
+				corev1.ResourceMemory: resource.MustParse("8Gi"),
+			},
+		},
+	}
+
+	tests := []struct {
+		name                string
+		hintNodes           []string
+		skipRestoreNodeInfo bool
+		preFilterResult     *framework.PreFilterResult
+		expectedNodes       []string
+	}{
+		{
+			name:                "hint takes priority over AllNodes PreFilterResult",
+			hintNodes:           []string{node1.Name},
+			skipRestoreNodeInfo: false,
+			preFilterResult:     nil, // nil means AllNodes
+			expectedNodes:       []string{node1.Name},
+		},
+		{
+			name:                "hint takes priority over specific PreFilterResult",
+			hintNodes:           []string{node1.Name},
+			skipRestoreNodeInfo: false,
+			preFilterResult:     &framework.PreFilterResult{NodeNames: sets.New(node2.Name)},
+			expectedNodes:       []string{node1.Name}, // hint wins over PreFilterResult
+		},
+		{
+			name:                "hint with SkipRestoreNodeInfo true",
+			hintNodes:           []string{node1.Name},
+			skipRestoreNodeInfo: true,
+			preFilterResult:     nil,
+			expectedNodes:       []string{node1.Name},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			pods := []*corev1.Pod{reservationutil.NewReservePod(reservation)}
+			suit := newPluginTestSuitWith(t, pods, []*corev1.Node{node1, node2})
+			p, err := suit.pluginFactory()
+			assert.NoError(t, err)
+			pl := p.(*Plugin)
+			pl.reservationCache.updateReservation(reservation)
+
+			cycleState := framework.NewCycleState()
+
+			// Setup hint state
+			hintState := &hinter.SchedulingHintStateData{
+				PreFilterNodes: tt.hintNodes,
+				Extensions: map[string]interface{}{
+					Name: HintExtensions{SkipRestoreNodeInfo: tt.skipRestoreNodeInfo},
+				},
+			}
+			cycleState.Write(hinter.SchedulingHintStateKey, hintState)
+
+			pod := &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Labels: map[string]string{
+						"test-reservation": "true",
+					},
+				},
+			}
+			_, _, status := pl.BeforePreFilter(context.TODO(), cycleState, pod)
+			assert.True(t, status.IsSuccess())
+
+			status = pl.AfterPreFilter(context.TODO(), cycleState, pod, tt.preFilterResult)
+			assert.True(t, status.IsSuccess())
+
+			// Verify state - expected nodes should be processed
+			state := getStateData(cycleState)
+			assert.Equal(t, len(tt.expectedNodes), len(state.nodeReservationStates),
+				"expected %d nodes but got %d", len(tt.expectedNodes), len(state.nodeReservationStates))
+			for _, nodeName := range tt.expectedNodes {
+				_, exists := state.nodeReservationStates[nodeName]
+				assert.True(t, exists, "node %s should be processed", nodeName)
+			}
+		})
+	}
+}
diff --git a/pkg/util/pod_resources_utils_test.go b/pkg/util/pod_resources_utils_test.go
index c6534e8f..98ac8360 100644
--- a/pkg/util/pod_resources_utils_test.go
+++ b/pkg/util/pod_resources_utils_test.go
@@ -28,7 +28,8 @@ import (
 
 func Test_GetPodRequest(t *testing.T) {
 	type args struct {
-		pod *corev1.Pod
+		pod           *corev1.Pod
+		resourceNames []corev1.ResourceName
 	}
 	tests := []struct {
 		name string
@@ -79,6 +80,46 @@ func Test_GetPodRequest(t *testing.T) {
 				corev1.ResourceMemory: resource.MustParse("18Gi"),
 			},
 		},
+		{
+			name: "get correct pod request",
+			args: args{
+				pod: &corev1.Pod{
+					Spec: corev1.PodSpec{
+						Containers: []corev1.Container{
+							{
+								Resources: corev1.ResourceRequirements{
+									Requests: corev1.ResourceList{
+										corev1.ResourceCPU:    resource.MustParse("4"),
+										corev1.ResourceMemory: resource.MustParse("10Gi"),
+									},
+									Limits: corev1.ResourceList{
+										corev1.ResourceCPU:    resource.MustParse("4"),
+										corev1.ResourceMemory: resource.MustParse("10Gi"),
+									},
+								},
+							},
+							{
+								Resources: corev1.ResourceRequirements{
+									Requests: corev1.ResourceList{
+										corev1.ResourceCPU:    resource.MustParse("4"),
+										corev1.ResourceMemory: resource.MustParse("8Gi"),
+									},
+									Limits: corev1.ResourceList{
+										corev1.ResourceCPU:    resource.MustParse("6"),
+										corev1.ResourceMemory: resource.MustParse("12Gi"),
+									},
+								},
+							},
+						},
+					},
+				},
+				resourceNames: []corev1.ResourceName{corev1.ResourceCPU},
+			},
+			want: corev1.ResourceList{
+				corev1.ResourceCPU:    resource.MustParse("8"),
+				corev1.ResourceMemory: resource.MustParse("18Gi"),
+			},
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/util/transformer/pod_transformer_test.go b/pkg/util/transformer/pod_transformer_test.go
index 8b5fc00e..12f7bc65 100644
--- a/pkg/util/transformer/pod_transformer_test.go
+++ b/pkg/util/transformer/pod_transformer_test.go
@@ -404,6 +404,204 @@ func TestTransformPod(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "enable replace-resources transformer to erase and replace resources",
+			prepareFn: func() func() {
+				return utilfeature.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate,
+					features.ReplaceResourcesTransformer, true)
+			},
+			pod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						apiext.AnnotationPodReplaceResources: "cpu:,memory:example.io/memory",
+					},
+				},
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("2"),
+									corev1.ResourceMemory: resource.MustParse("4Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("3"),
+									corev1.ResourceMemory: resource.MustParse("6Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					InitContainers: []corev1.Container{
+						{
+							Name: "init-container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("1"),
+									corev1.ResourceMemory: resource.MustParse("2Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("1.5"),
+									corev1.ResourceMemory: resource.MustParse("3Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					Overhead: corev1.ResourceList{
+						corev1.ResourceCPU:    resource.MustParse("1"),
+						corev1.ResourceMemory: resource.MustParse("1Gi"),
+					},
+				},
+			},
+			wantPod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						apiext.AnnotationPodReplaceResources: "cpu:,memory:example.io/memory",
+					},
+					Labels: map[string]string{
+						apiext.LabelQuestionedObjectKey: "/",
+					},
+				},
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("4Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("6Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					InitContainers: []corev1.Container{
+						{
+							Name: "init-container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("2Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("3Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					Overhead: corev1.ResourceList{
+						"example.io/memory": resource.MustParse("1Gi"),
+					},
+				},
+			},
+		},
+		{
+			name: "enable replace-resources transformer for scheduler",
+			prepareFn: func() func() {
+				return utilfeature.SetFeatureGateDuringTest(t, k8sfeature.DefaultFeatureGate,
+					features.ReplaceResourcesTransformer, true)
+			},
+			pod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						apiext.AnnotationPodReplaceResources: "cpu:,memory:example.io/memory",
+					},
+				},
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("2"),
+									corev1.ResourceMemory: resource.MustParse("4Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("3"),
+									corev1.ResourceMemory: resource.MustParse("6Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					InitContainers: []corev1.Container{
+						{
+							Name: "init-container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("1"),
+									corev1.ResourceMemory: resource.MustParse("2Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									corev1.ResourceCPU:    resource.MustParse("1.5"),
+									corev1.ResourceMemory: resource.MustParse("3Gi"),
+									"example.io/gpu":      resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					Overhead: corev1.ResourceList{
+						corev1.ResourceCPU:    resource.MustParse("1"),
+						corev1.ResourceMemory: resource.MustParse("1Gi"),
+					},
+				},
+			},
+			wantPod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Annotations: map[string]string{
+						apiext.AnnotationPodReplaceResources: "cpu:,memory:example.io/memory",
+					},
+					Labels: map[string]string{
+						apiext.LabelQuestionedObjectKey: "/",
+					},
+				},
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("4Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("6Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					InitContainers: []corev1.Container{
+						{
+							Name: "init-container1",
+							Resources: corev1.ResourceRequirements{
+								Requests: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("2Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+								Limits: corev1.ResourceList{
+									"example.io/memory": resource.MustParse("3Gi"),
+									"example.io/gpu":    resource.MustParse("1"),
+								},
+							},
+						},
+					},
+					Overhead: corev1.ResourceList{
+						"example.io/memory": resource.MustParse("1Gi"),
+					},
+				},
+			},
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/webhook/pod/validating/cluster_colocation_profile_test.go b/pkg/webhook/pod/validating/cluster_colocation_profile_test.go
index 89a4d30a..8509b6ca 100644
--- a/pkg/webhook/pod/validating/cluster_colocation_profile_test.go
+++ b/pkg/webhook/pod/validating/cluster_colocation_profile_test.go
@@ -33,7 +33,9 @@ import (
 
 	configv1alpha1 "github.com/koordinator-sh/koordinator/apis/config/v1alpha1"
 	"github.com/koordinator-sh/koordinator/apis/extension"
+	"github.com/koordinator-sh/koordinator/pkg/features"
 	"github.com/koordinator-sh/koordinator/pkg/util"
+	"github.com/koordinator-sh/koordinator/pkg/util/feature"
 )
 
 func init() {
@@ -52,13 +54,14 @@ func newAdmissionRequest(op admissionv1.Operation, object, oldObject runtime.Raw
 
 func TestClusterColocationProfileValidatingPod(t *testing.T) {
 	tests := []struct {
-		name        string
-		operation   admissionv1.Operation
-		oldPod      *corev1.Pod
-		newPod      *corev1.Pod
-		wantAllowed bool
-		wantReason  string
-		wantErr     bool
+		name                          string
+		operation                     admissionv1.Operation
+		oldPod                        *corev1.Pod
+		newPod                        *corev1.Pod
+		wantAllowed                   bool
+		wantReason                    string
+		wantErr                       bool
+		defaultSkipValidatingPriority bool
 	}{
 		{
 			name:        "non-colocation empty pod",
@@ -194,7 +197,7 @@ func TestClusterColocationProfileValidatingPod(t *testing.T) {
 			wantErr:     true,
 		},
 		{
-			name:      "validate koordinator priority",
+			name:      "validate koordinator priority with defaultSkipValidatingPriority=false",
 			operation: admissionv1.Update,
 			newPod: &corev1.Pod{
 				ObjectMeta: metav1.ObjectMeta{
@@ -214,6 +217,28 @@ func TestClusterColocationProfileValidatingPod(t *testing.T) {
 			wantReason:  `labels.koordinator.sh/priority: Invalid value: "8888": field is immutable`,
 			wantErr:     true,
 		},
+		{
+			name:      "validate koordinator priority with defaultSkipValidatingPriority=true",
+			operation: admissionv1.Update,
+			newPod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Labels: map[string]string{
+						extension.LabelPodPriority: "8888",
+					},
+				},
+			},
+			oldPod: &corev1.Pod{
+				ObjectMeta: metav1.ObjectMeta{
+					Labels: map[string]string{
+						extension.LabelPodPriority: "9999",
+					},
+				},
+			},
+			defaultSkipValidatingPriority: true,
+			wantAllowed:                   true,
+			wantReason:                    "",
+			wantErr:                       false,
+		},
 		{
 			name:      "validate remove koordinator priority",
 			operation: admissionv1.Update,
@@ -460,6 +485,7 @@ func TestClusterColocationProfileValidatingPod(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			defer feature.SetFeatureGateDuringTest(t, feature.DefaultMutableFeatureGate, features.ColocationProfileSkipValidatingPriority, tt.defaultSkipValidatingPriority)()
 			client := fake.NewClientBuilder().Build()
 			decoder := admission.NewDecoder(scheme.Scheme)
 			h := &PodValidatingHandler{
diff --git a/pkg/webhook/pod/validating/evaluate_quota_test.go b/pkg/webhook/pod/validating/evaluate_quota_test.go
index a2e1c655..87e15ff2 100644
--- a/pkg/webhook/pod/validating/evaluate_quota_test.go
+++ b/pkg/webhook/pod/validating/evaluate_quota_test.go
@@ -40,13 +40,14 @@ import (
 	"github.com/koordinator-sh/koordinator/pkg/webhook/quotaevaluate"
 )
 
-func TestEvalucateQuota(t *testing.T) {
+func TestEvaluateQuota(t *testing.T) {
 	testCases := []struct {
 		name        string
 		operation   admissionv1.Operation
 		oldPod      *corev1.Pod
 		newPod      *corev1.Pod
 		quota       *v1alpha1.ElasticQuota
+		prepareFn   func() func()
 		wantAllowed bool
 		wantReason  string
 		wantErr     bool
@@ -326,11 +327,53 @@ func TestEvalucateQuota(t *testing.T) {
 				corev1.ResourceMemory: resource.MustParse("4Gi"),
 			},
 		},
+		{
+			name:      "pod with replace-resources annotation, should replace or erase specified resources",
+			operation: admissionv1.Create,
+			newPod: func() *corev1.Pod {
+				pod := elasticquota.MakePod("ns1", "pod1").
+					Label("quota.scheduling.koordinator.sh/name", "quota1").
+					Container(corev1.ResourceList{
+						corev1.ResourceCPU:    resource.MustParse("2"),
+						corev1.ResourceMemory: resource.MustParse("4Gi"),
+						"example.io/gpu":      resource.MustParse("1"),
+					}).Obj()
+				pod.SetAnnotations(map[string]string{
+					extension.AnnotationPodReplaceResources: "cpu:example.io/cpu,memory:",
+				})
+				return pod
+			}(),
+			quota: elasticquota.MakeQuota("quota1").Namespace("kube-system").Max(corev1.ResourceList{
+				corev1.ResourceMemory: resource.MustParse("0Gi"),
+				"example.io/cpu":      resource.MustParse("4k"),
+				"example.io/gpu":      resource.MustParse("3"),
+			}).Obj(),
+			prepareFn: func() func() {
+				cleanupFn1 := utilfeature.SetFeatureGateDuringTest(t, utilfeature.DefaultMutableFeatureGate,
+					features.ElasticQuotaEvaluationTransformPod, true)
+				cleanupFn2 := utilfeature.SetFeatureGateDuringTest(t, utilfeature.DefaultMutableFeatureGate,
+					features.ReplaceResourcesTransformer, true)
+				return func() {
+					cleanupFn1()
+					cleanupFn2()
+				}
+			},
+			wantAllowed: true,
+			wantReason:  "",
+			wantErr:     false,
+			wantUsed: corev1.ResourceList{
+				"example.io/cpu": resource.MustParse("2k"),
+				"example.io/gpu": resource.MustParse("1"),
+			},
+		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
 			defer utilfeature.SetFeatureGateDuringTest(t, utilfeature.DefaultMutableFeatureGate, features.EnableQuotaAdmission, true)()
+			if tc.prepareFn != nil {
+				defer tc.prepareFn()()
+			}
 			scheme := runtime.NewScheme()
 			_ = v1alpha1.AddToScheme(scheme)
 			_ = clientgoscheme.AddToScheme(scheme)