... | ... | ||
---|---|---|---|
7 | NUMA nodes based on their performance weight, thereby optimizing memory | 7 | NUMA nodes based on their performance weight, thereby optimizing memory |
8 | bandwidth utilization. The weight values are configured through sysfs. | 8 | bandwidth utilization. The weight values are configured through sysfs. |
9 | 9 | ||
10 | Previously, sysfs entries for weighted interleave were managed statically | 10 | Previously, sysfs entries for weighted interleave were managed statically |
11 | at initialization. This led to several issues: | 11 | at initialization. This led to several issues: |
12 | - Memory Leaks: Improper `kobject` deallocation caused memory leaks | 12 | - Memory Leaks: Improper `kobject` teardown caused memory leaks |
13 | when initialization failed or when nodes were removed. | 13 | when initialization failed or when nodes were removed. |
14 | - Lack of Dynamic Updates: Sysfs attributes were created only during | 14 | - Lack of Dynamic Updates: Sysfs attributes were created only during |
15 | initialization, preventing nodes added at runtime from being recognized. | 15 | initialization, preventing nodes added at runtime from being recognized. |
16 | - Handling of Unusable Nodes: Sysfs entries were generated for all | 16 | - Handling of Unusable Nodes: Sysfs entries were generated for all |
17 | possible nodes (`N_POSSIBLE`), including memoryless or unavailable nodes, | 17 | possible nodes (`N_POSSIBLE`), including memoryless or unavailable nodes, |
18 | leading to sysfs entries for unusable nodes and potential | 18 | leading to sysfs entries for unusable nodes and potential |
19 | misconfigurations. | 19 | misconfigurations. |
20 | 20 | ||
21 | ### Patch Overview | 21 | ### Patch Overview |
22 | 1. [PATCH 1/3] Fix memory leaks in weighted interleave sysfs | 22 | 1. [PATCH 1/3] mm/mempolicy: Fix memory leaks in weighted interleave sysfs |
23 | - Ensures proper cleanup of `kobject` allocations. | 23 | - Ensures proper cleanup of `kobject` allocations. |
24 | - Replaces unnecessary `kfree()` calls with `kobject_put()`, preventing | 24 | - Adds `kobject_del()` before `kobject_put()` to clean up sysfs state correctly. |
25 | memory leaks and improving system stability. | 25 | - Prevents memory/resource leaks and improves teardown behavior. |
26 | 26 | ||
27 | 2. [PATCH 2/3] Enable dynamic updates for weighted interleave sysfs | 27 | 2. [PATCH 2/3] mm/mempolicy: Prepare weighted interleave sysfs for memory hotplug |
28 | - Restructures sysfs handling to allow runtime updates. | 28 | - Refactors static sysfs layout into a new `sysfs_wi_group` structure. |
29 | - The sysfs attributes are now globally accessible, enabling external | 29 | - Makes per-node sysfs attributes accessible to external modules. |
30 | modules to manage interleave settings dynamically. | 30 | - Lays groundwork for future hotplug support by enabling runtime modification. |
31 | 31 | ||
32 | 3. [PATCH 3/3] Support memory hotplug in weighted interleave | 32 | 3. [PATCH 3/3] mm/mempolicy: Support memory hotplug in weighted interleave |
33 | - Modifies sysfs creation logic to restrict entries to nodes that are | 33 | - Dynamically adds/removes sysfs entries when nodes are online/offline. |
34 | online and have memory, excluding unusable nodes. | 34 | - Limits sysfs creation to nodes with memory, avoiding unusable node entries. |
35 | - Introduces a memory hotplug mechanism to dynamically add and remove | 35 | - Hooks into memory hotplug notifier for runtime updates. |
36 | sysfs attributes when nodes transition into or out of the `N_MEMORY` set. | ||
37 | - Ensures that sysfs attributes are properly removed when nodes go offline, | ||
38 | preventing stale or redundant entries from persisting. | ||
39 | 36 | ||
40 | These patches have been tested under CXL-based memory configurations, | 37 | These patches have been tested under CXL-based memory configurations, |
41 | including hotplug scenarios, to ensure proper behavior and stability. | 38 | including hotplug scenarios, to ensure proper behavior and stability. |
42 | 39 | ||
43 | mm/mempolicy.c | 195 ++++++++++++++++++++++++++++++++----------------- | 40 | mm/mempolicy.c | 193 +++++++++++++++++++++++++++++++------------------ |
44 | 1 file changed, 127 insertions(+), 68 deletions(-) | 41 | 1 file changed, 124 insertions(+), 69 deletions(-) |
45 | 42 | ||
46 | 43 | ||
47 | base-commit: 38fec10eb60d687e30c8c6b5420d86e8149f7557 | 44 | base-commit: 0af2f6be1b4281385b618cb86ad946eded089ac8 |
48 | -- | 45 | -- |
49 | 2.34.1 | 46 | 2.34.1 | diff view generated by jsdifflib |
1 | Memory leaks occurred when removing sysfs attributes for weighted | 1 | Memory leaks occurred when removing sysfs attributes for weighted |
---|---|---|---|
2 | interleave. Improper kobject deallocation led to unreleased memory | 2 | interleave. Improper kobject deallocation led to unreleased memory |
3 | when initialization failed or when nodes were removed. | 3 | when initialization failed or when nodes were removed. |
4 | 4 | ||
5 | This patch resolves the issue by replacing unnecessary `kfree()` | 5 | This patch resolves the issue by replacing unnecessary `kfree()` |
6 | calls with `kobject_put()`, ensuring proper cleanup and preventing | 6 | calls with proper `kobject_del()` and `kobject_put()` sequences, |
7 | memory leaks. | 7 | ensuring correct teardown and preventing memory leaks. |
8 | 8 | ||
9 | By correctly using `kobject_put()`, the release function now | 9 | By explicitly calling `kobject_del()` before `kobject_put()`, |
10 | properly deallocates memory without causing resource leaks, | 10 | the release function is now invoked safely, and internal sysfs |
11 | thereby improving system stability. | 11 | state is correctly cleaned up. This guarantees that the memory |
12 | associated with the kobject is fully released and avoids | ||
13 | resource leaks, thereby improving system stability. | ||
12 | 14 | ||
13 | Fixes: dce41f5ae253 ("mm/mempolicy: implement the sysfs-based weighted_interleave interface") | 15 | Fixes: dce41f5ae253 ("mm/mempolicy: implement the sysfs-based weighted_interleave interface") |
14 | Signed-off-by: Rakie Kim <rakie.kim@sk.com> | 16 | Signed-off-by: Rakie Kim <rakie.kim@sk.com> |
15 | Signed-off-by: Honggyu Kim <honggyu.kim@sk.com> | 17 | Signed-off-by: Honggyu Kim <honggyu.kim@sk.com> |
16 | Signed-off-by: Yunjeong Mun <yunjeong.mun@sk.com> | 18 | Signed-off-by: Yunjeong Mun <yunjeong.mun@sk.com> |
17 | Reviewed-by: Gregory Price <gourry@gourry.net> | 19 | Reviewed-by: Gregory Price <gourry@gourry.net> |
18 | --- | 20 | --- |
19 | mm/mempolicy.c | 61 +++++++++++++++++++++++++------------------------- | 21 | mm/mempolicy.c | 66 ++++++++++++++++++++++++-------------------------- |
20 | 1 file changed, 31 insertions(+), 30 deletions(-) | 22 | 1 file changed, 32 insertions(+), 34 deletions(-) |
21 | 23 | ||
22 | diff --git a/mm/mempolicy.c b/mm/mempolicy.c | 24 | diff --git a/mm/mempolicy.c b/mm/mempolicy.c |
23 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/mm/mempolicy.c | 26 | --- a/mm/mempolicy.c |
25 | +++ b/mm/mempolicy.c | 27 | +++ b/mm/mempolicy.c |
... | ... | ||
36 | static const struct kobj_type wi_ktype = { | 38 | static const struct kobj_type wi_ktype = { |
37 | @@ -XXX,XX +XXX,XX @@ static int add_weighted_interleave_group(struct kobject *root_kobj) | 39 | @@ -XXX,XX +XXX,XX @@ static int add_weighted_interleave_group(struct kobject *root_kobj) |
38 | struct kobject *wi_kobj; | 40 | struct kobject *wi_kobj; |
39 | int nid, err; | 41 | int nid, err; |
40 | 42 | ||
41 | - wi_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); | ||
42 | - if (!wi_kobj) | ||
43 | + node_attrs = kcalloc(nr_node_ids, sizeof(struct iw_node_attr *), | 43 | + node_attrs = kcalloc(nr_node_ids, sizeof(struct iw_node_attr *), |
44 | + GFP_KERNEL); | 44 | + GFP_KERNEL); |
45 | + if (!node_attrs) | 45 | + if (!node_attrs) |
46 | + return -ENOMEM; | ||
47 | + | ||
48 | wi_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); | ||
49 | - if (!wi_kobj) | ||
50 | + if (!wi_kobj) { | ||
51 | + kfree(node_attrs); | ||
46 | return -ENOMEM; | 52 | return -ENOMEM; |
47 | |||
48 | + wi_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); | ||
49 | + if (!wi_kobj) { | ||
50 | + err = -ENOMEM; | ||
51 | + goto node_out; | ||
52 | + } | 53 | + } |
53 | + | 54 | |
54 | err = kobject_init_and_add(wi_kobj, &wi_ktype, root_kobj, | 55 | err = kobject_init_and_add(wi_kobj, &wi_ktype, root_kobj, |
55 | "weighted_interleave"); | 56 | "weighted_interleave"); |
56 | if (err) { | 57 | - if (err) { |
57 | - kfree(wi_kobj); | 58 | - kfree(wi_kobj); |
58 | - return err; | 59 | - return err; |
59 | + kobject_put(wi_kobj); | 60 | - } |
60 | + goto err_out; | 61 | + if (err) |
61 | } | 62 | + goto err_put_kobj; |
62 | 63 | ||
63 | for_each_node_state(nid, N_POSSIBLE) { | 64 | for_each_node_state(nid, N_POSSIBLE) { |
64 | @@ -XXX,XX +XXX,XX @@ static int add_weighted_interleave_group(struct kobject *root_kobj) | 65 | err = add_weight_node(nid, wi_kobj); |
65 | break; | 66 | if (err) { |
67 | pr_err("failed to add sysfs [node%d]\n", nid); | ||
68 | - break; | ||
69 | + goto err_del_kobj; | ||
66 | } | 70 | } |
67 | } | 71 | } |
68 | - if (err) | 72 | - if (err) |
69 | + if (err) { | 73 | - kobject_put(wi_kobj); |
70 | kobject_put(wi_kobj); | ||
71 | + goto err_out; | ||
72 | + } | ||
73 | + | 74 | + |
74 | return 0; | 75 | return 0; |
75 | + | 76 | + |
76 | +node_out: | 77 | +err_del_kobj: |
77 | + kfree(node_attrs); | 78 | + kobject_del(wi_kobj); |
78 | +err_out: | 79 | +err_put_kobj: |
80 | + kobject_put(wi_kobj); | ||
79 | + return err; | 81 | + return err; |
80 | } | 82 | } |
81 | 83 | ||
82 | static void mempolicy_kobj_release(struct kobject *kobj) | 84 | static void mempolicy_kobj_release(struct kobject *kobj) |
83 | @@ -XXX,XX +XXX,XX @@ static void mempolicy_kobj_release(struct kobject *kobj) | 85 | @@ -XXX,XX +XXX,XX @@ static void mempolicy_kobj_release(struct kobject *kobj) |
... | ... | ||
108 | 110 | ||
109 | err = kobject_init_and_add(mempolicy_kobj, &mempolicy_ktype, mm_kobj, | 111 | err = kobject_init_and_add(mempolicy_kobj, &mempolicy_ktype, mm_kobj, |
110 | "mempolicy"); | 112 | "mempolicy"); |
111 | if (err) | 113 | if (err) |
112 | - goto node_out; | 114 | - goto node_out; |
113 | + goto err_out; | 115 | + goto err_put_kobj; |
114 | 116 | ||
115 | err = add_weighted_interleave_group(mempolicy_kobj); | 117 | err = add_weighted_interleave_group(mempolicy_kobj); |
116 | - if (err) { | 118 | - if (err) { |
117 | - pr_err("mempolicy sysfs structure failed to initialize\n"); | 119 | - pr_err("mempolicy sysfs structure failed to initialize\n"); |
118 | - kobject_put(mempolicy_kobj); | 120 | - kobject_put(mempolicy_kobj); |
119 | - return err; | 121 | - return err; |
120 | - } | 122 | - } |
121 | + if (err) | 123 | + if (err) |
122 | + goto err_out; | 124 | + goto err_del_kobj; |
123 | + | ||
124 | + return 0; | ||
125 | 125 | ||
126 | - return err; | 126 | - return err; |
127 | -node_out: | 127 | -node_out: |
128 | - kfree(node_attrs); | 128 | - kfree(node_attrs); |
129 | -mempol_out: | 129 | -mempol_out: |
130 | - kfree(mempolicy_kobj); | 130 | - kfree(mempolicy_kobj); |
131 | err_out: | 131 | -err_out: |
132 | - pr_err("failed to add mempolicy kobject to the system\n"); | 132 | - pr_err("failed to add mempolicy kobject to the system\n"); |
133 | + return 0; | ||
134 | + | ||
135 | +err_del_kobj: | ||
136 | + kobject_del(mempolicy_kobj); | ||
137 | +err_put_kobj: | ||
133 | + kobject_put(mempolicy_kobj); | 138 | + kobject_put(mempolicy_kobj); |
134 | return err; | 139 | return err; |
135 | } | 140 | } |
136 | 141 | ||
137 | -- | 142 | -- |
138 | 2.34.1 | 143 | 2.34.1 | diff view generated by jsdifflib |
1 | Previously, the weighted interleave sysfs structure was statically | 1 | Previously, the weighted interleave sysfs structure was statically |
---|---|---|---|
2 | managed, preventing dynamic updates when nodes were added or removed. | 2 | managed during initialization. This prevented new nodes from being |
3 | recognized when memory hotplug events occurred, limiting the ability | ||
4 | to update or extend sysfs entries dynamically at runtime. | ||
3 | 5 | ||
4 | This patch restructures the weighted interleave sysfs to support | 6 | To address this, this patch refactors the sysfs infrastructure and |
5 | dynamic insertion and deletion. The sysfs that was part of | 7 | encapsulates it within a new structure, `sysfs_wi_group`, which holds |
6 | the 'weighted_interleave_group' is now globally accessible, | 8 | both the kobject and an array of node attribute pointers. |
7 | allowing external access to that sysfs. | ||
8 | 9 | ||
9 | With this change, sysfs management for weighted interleave is | 10 | By allocating this group structure globally, the per-node sysfs |
10 | more flexible, supporting hotplug events and runtime updates | 11 | attributes can be managed beyond initialization time, enabling |
11 | more effectively. | 12 | external modules to insert or remove node entries in response to |
13 | events such as memory hotplug or node online/offline transitions. | ||
14 | |||
15 | Instead of allocating all per-node sysfs attributes at once, the | ||
16 | initialization path now uses the existing sysfs_wi_node_add() and | ||
17 | sysfs_wi_node_delete() helpers. This refactoring makes it possible | ||
18 | to modularly manage per-node sysfs entries and ensures the | ||
19 | infrastructure is ready for runtime extension. | ||
12 | 20 | ||
13 | Signed-off-by: Rakie Kim <rakie.kim@sk.com> | 21 | Signed-off-by: Rakie Kim <rakie.kim@sk.com> |
14 | Signed-off-by: Honggyu Kim <honggyu.kim@sk.com> | 22 | Signed-off-by: Honggyu Kim <honggyu.kim@sk.com> |
15 | Signed-off-by: Yunjeong Mun <yunjeong.mun@sk.com> | 23 | Signed-off-by: Yunjeong Mun <yunjeong.mun@sk.com> |
16 | Reviewed-by: Gregory Price <gourry@gourry.net> | 24 | Reviewed-by: Gregory Price <gourry@gourry.net> |
17 | --- | 25 | --- |
18 | mm/mempolicy.c | 71 ++++++++++++++++++++++---------------------------- | 26 | mm/mempolicy.c | 61 ++++++++++++++++++++++++-------------------------- |
19 | 1 file changed, 31 insertions(+), 40 deletions(-) | 27 | 1 file changed, 29 insertions(+), 32 deletions(-) |
20 | 28 | ||
21 | diff --git a/mm/mempolicy.c b/mm/mempolicy.c | 29 | diff --git a/mm/mempolicy.c b/mm/mempolicy.c |
22 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/mm/mempolicy.c | 31 | --- a/mm/mempolicy.c |
24 | +++ b/mm/mempolicy.c | 32 | +++ b/mm/mempolicy.c |
... | ... | ||
42 | 50 | ||
43 | -static struct iw_node_attr **node_attrs; | 51 | -static struct iw_node_attr **node_attrs; |
44 | - | 52 | - |
45 | -static void sysfs_wi_node_release(struct iw_node_attr *node_attr, | 53 | -static void sysfs_wi_node_release(struct iw_node_attr *node_attr, |
46 | - struct kobject *parent) | 54 | - struct kobject *parent) |
47 | +static void sysfs_wi_node_release(int nid) | 55 | +static void sysfs_wi_node_delete(int nid) |
48 | { | 56 | { |
49 | - if (!node_attr) | 57 | - if (!node_attr) |
50 | + if (!wi_group->nattrs[nid]) | 58 | + if (!wi_group->nattrs[nid]) |
51 | return; | 59 | return; |
52 | - sysfs_remove_file(parent, &node_attr->kobj_attr.attr); | 60 | - sysfs_remove_file(parent, &node_attr->kobj_attr.attr); |
... | ... | ||
68 | + int nid; | 76 | + int nid; |
69 | 77 | ||
70 | - kfree(node_attrs); | 78 | - kfree(node_attrs); |
71 | - kfree(wi_kobj); | 79 | - kfree(wi_kobj); |
72 | + for (nid = 0; nid < nr_node_ids; nid++) | 80 | + for (nid = 0; nid < nr_node_ids; nid++) |
73 | + sysfs_wi_node_release(nid); | 81 | + sysfs_wi_node_delete(nid); |
74 | + kfree(wi_group); | 82 | + kfree(wi_group); |
75 | } | 83 | } |
76 | 84 | ||
77 | static const struct kobj_type wi_ktype = { | 85 | static const struct kobj_type wi_ktype = { |
78 | @@ -XXX,XX +XXX,XX @@ static const struct kobj_type wi_ktype = { | 86 | @@ -XXX,XX +XXX,XX @@ static const struct kobj_type wi_ktype = { |
... | ... | ||
100 | + wi_group->nattrs[nid] = node_attr; | 108 | + wi_group->nattrs[nid] = node_attr; |
101 | return 0; | 109 | return 0; |
102 | } | 110 | } |
103 | 111 | ||
104 | -static int add_weighted_interleave_group(struct kobject *root_kobj) | 112 | -static int add_weighted_interleave_group(struct kobject *root_kobj) |
105 | +static int add_weighted_interleave_group(struct kobject *mempolicy_kobj) | 113 | +static int __init add_weighted_interleave_group(struct kobject *mempolicy_kobj) |
106 | { | 114 | { |
107 | - struct kobject *wi_kobj; | 115 | - struct kobject *wi_kobj; |
108 | int nid, err; | 116 | int nid, err; |
109 | 117 | ||
110 | - node_attrs = kcalloc(nr_node_ids, sizeof(struct iw_node_attr *), | 118 | - node_attrs = kcalloc(nr_node_ids, sizeof(struct iw_node_attr *), |
111 | - GFP_KERNEL); | 119 | - GFP_KERNEL); |
112 | - if (!node_attrs) | 120 | - if (!node_attrs) |
113 | + wi_group = kzalloc(sizeof(struct sysfs_wi_group) + \ | 121 | + wi_group = kzalloc(struct_size(wi_group, nattrs, nr_node_ids), |
114 | + nr_node_ids * sizeof(struct iw_node_attr *), \ | 122 | + GFP_KERNEL); |
115 | + GFP_KERNEL); | ||
116 | + if (!wi_group) | 123 | + if (!wi_group) |
117 | return -ENOMEM; | 124 | return -ENOMEM; |
118 | 125 | ||
119 | - wi_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); | 126 | - wi_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); |
120 | - if (!wi_kobj) { | 127 | - if (!wi_kobj) { |
121 | - err = -ENOMEM; | 128 | - kfree(node_attrs); |
122 | - goto node_out; | 129 | - return -ENOMEM; |
123 | - } | 130 | - } |
124 | - | 131 | - |
125 | - err = kobject_init_and_add(wi_kobj, &wi_ktype, root_kobj, | 132 | - err = kobject_init_and_add(wi_kobj, &wi_ktype, root_kobj, |
126 | + err = kobject_init_and_add(&wi_group->wi_kobj, &wi_ktype, mempolicy_kobj, | 133 | + err = kobject_init_and_add(&wi_group->wi_kobj, &wi_ktype, mempolicy_kobj, |
127 | "weighted_interleave"); | 134 | "weighted_interleave"); |
128 | - if (err) { | 135 | if (err) |
129 | - kobject_put(wi_kobj); | 136 | goto err_put_kobj; |
130 | + if (err) | ||
131 | goto err_out; | ||
132 | - } | ||
133 | 137 | ||
134 | for_each_node_state(nid, N_POSSIBLE) { | 138 | for_each_node_state(nid, N_POSSIBLE) { |
135 | - err = add_weight_node(nid, wi_kobj); | 139 | - err = add_weight_node(nid, wi_kobj); |
136 | + err = sysfs_wi_node_add(nid); | 140 | + err = sysfs_wi_node_add(nid); |
137 | if (err) { | 141 | if (err) { |
138 | pr_err("failed to add sysfs [node%d]\n", nid); | 142 | pr_err("failed to add sysfs [node%d]\n", nid); |
139 | - break; | 143 | goto err_del_kobj; |
140 | + goto err_out; | 144 | @@ -XXX,XX +XXX,XX @@ static int add_weighted_interleave_group(struct kobject *root_kobj) |
141 | } | ||
142 | } | ||
143 | - if (err) { | ||
144 | - kobject_put(wi_kobj); | ||
145 | - goto err_out; | ||
146 | - } | ||
147 | |||
148 | return 0; | 145 | return 0; |
149 | 146 | ||
150 | -node_out: | 147 | err_del_kobj: |
151 | - kfree(node_attrs); | 148 | - kobject_del(wi_kobj); |
152 | err_out: | 149 | + kobject_del(&wi_group->wi_kobj); |
150 | err_put_kobj: | ||
151 | - kobject_put(wi_kobj); | ||
153 | + kobject_put(&wi_group->wi_kobj); | 152 | + kobject_put(&wi_group->wi_kobj); |
154 | return err; | 153 | return err; |
155 | } | 154 | } |
156 | 155 | ||
157 | -- | 156 | -- |
158 | 2.34.1 | 157 | 2.34.1 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
26 | events. | 26 | events. |
27 | 27 | ||
28 | Signed-off-by: Rakie Kim <rakie.kim@sk.com> | 28 | Signed-off-by: Rakie Kim <rakie.kim@sk.com> |
29 | Signed-off-by: Honggyu Kim <honggyu.kim@sk.com> | 29 | Signed-off-by: Honggyu Kim <honggyu.kim@sk.com> |
30 | Signed-off-by: Yunjeong Mun <yunjeong.mun@sk.com> | 30 | Signed-off-by: Yunjeong Mun <yunjeong.mun@sk.com> |
31 | Reviewed-by: Oscar Salvador <osalvador@suse.de> | ||
31 | --- | 32 | --- |
32 | mm/mempolicy.c | 113 +++++++++++++++++++++++++++++++++++++++---------- | 33 | mm/mempolicy.c | 106 ++++++++++++++++++++++++++++++++++++++----------- |
33 | 1 file changed, 90 insertions(+), 23 deletions(-) | 34 | 1 file changed, 83 insertions(+), 23 deletions(-) |
34 | 35 | ||
35 | diff --git a/mm/mempolicy.c b/mm/mempolicy.c | 36 | diff --git a/mm/mempolicy.c b/mm/mempolicy.c |
36 | index XXXXXXX..XXXXXXX 100644 | 37 | index XXXXXXX..XXXXXXX 100644 |
37 | --- a/mm/mempolicy.c | 38 | --- a/mm/mempolicy.c |
38 | +++ b/mm/mempolicy.c | 39 | +++ b/mm/mempolicy.c |
... | ... | ||
52 | struct iw_node_attr *nattrs[]; | 53 | struct iw_node_attr *nattrs[]; |
53 | }; | 54 | }; |
54 | 55 | ||
55 | @@ -XXX,XX +XXX,XX @@ static ssize_t node_store(struct kobject *kobj, struct kobj_attribute *attr, | 56 | @@ -XXX,XX +XXX,XX @@ static ssize_t node_store(struct kobject *kobj, struct kobj_attribute *attr, |
56 | 57 | ||
57 | static void sysfs_wi_node_release(int nid) | 58 | static void sysfs_wi_node_delete(int nid) |
58 | { | 59 | { |
59 | - if (!wi_group->nattrs[nid]) | 60 | - if (!wi_group->nattrs[nid]) |
60 | + struct iw_node_attr *attr; | 61 | + struct iw_node_attr *attr; |
61 | + | 62 | + |
62 | + if (nid < 0 || nid >= nr_node_ids) | 63 | + if (nid < 0 || nid >= nr_node_ids) |
... | ... | ||
66 | + attr = wi_group->nattrs[nid]; | 67 | + attr = wi_group->nattrs[nid]; |
67 | + if (!attr) { | 68 | + if (!attr) { |
68 | + mutex_unlock(&wi_group->kobj_lock); | 69 | + mutex_unlock(&wi_group->kobj_lock); |
69 | return; | 70 | return; |
70 | + } | 71 | + } |
72 | + | ||
73 | + wi_group->nattrs[nid] = NULL; | ||
74 | + mutex_unlock(&wi_group->kobj_lock); | ||
71 | 75 | ||
72 | - sysfs_remove_file(&wi_group->wi_kobj, | 76 | - sysfs_remove_file(&wi_group->wi_kobj, |
73 | - &wi_group->nattrs[nid]->kobj_attr.attr); | 77 | - &wi_group->nattrs[nid]->kobj_attr.attr); |
74 | - kfree(wi_group->nattrs[nid]->kobj_attr.attr.name); | 78 | - kfree(wi_group->nattrs[nid]->kobj_attr.attr.name); |
75 | - kfree(wi_group->nattrs[nid]); | 79 | - kfree(wi_group->nattrs[nid]); |
76 | + wi_group->nattrs[nid] = NULL; | ||
77 | + mutex_unlock(&wi_group->kobj_lock); | ||
78 | + | ||
79 | + sysfs_remove_file(&wi_group->wi_kobj, &attr->kobj_attr.attr); | 80 | + sysfs_remove_file(&wi_group->wi_kobj, &attr->kobj_attr.attr); |
80 | + kfree(attr->kobj_attr.attr.name); | 81 | + kfree(attr->kobj_attr.attr.name); |
81 | + kfree(attr); | 82 | + kfree(attr); |
82 | } | 83 | } |
83 | 84 | ||
... | ... | ||
121 | + pr_info("Node [%d] already exists\n", nid); | 122 | + pr_info("Node [%d] already exists\n", nid); |
122 | + kfree(new_attr); | 123 | + kfree(new_attr); |
123 | + kfree(name); | 124 | + kfree(name); |
124 | + return 0; | 125 | + return 0; |
125 | + } | 126 | + } |
127 | + wi_group->nattrs[nid] = new_attr; | ||
126 | 128 | ||
127 | - if (sysfs_create_file(&wi_group->wi_kobj, &node_attr->kobj_attr.attr)) { | 129 | - if (sysfs_create_file(&wi_group->wi_kobj, &node_attr->kobj_attr.attr)) { |
128 | - kfree(node_attr->kobj_attr.attr.name); | 130 | - kfree(node_attr->kobj_attr.attr.name); |
129 | - kfree(node_attr); | 131 | - kfree(node_attr); |
130 | - pr_err("failed to add attribute to weighted_interleave\n"); | 132 | - pr_err("failed to add attribute to weighted_interleave\n"); |
131 | - return -ENOMEM; | 133 | - return -ENOMEM; |
132 | + wi_group->nattrs[nid] = new_attr; | ||
133 | + mutex_unlock(&wi_group->kobj_lock); | ||
134 | + | ||
135 | + sysfs_attr_init(&wi_group->nattrs[nid]->kobj_attr.attr); | 134 | + sysfs_attr_init(&wi_group->nattrs[nid]->kobj_attr.attr); |
136 | + wi_group->nattrs[nid]->kobj_attr.attr.name = name; | 135 | + wi_group->nattrs[nid]->kobj_attr.attr.name = name; |
137 | + wi_group->nattrs[nid]->kobj_attr.attr.mode = 0644; | 136 | + wi_group->nattrs[nid]->kobj_attr.attr.mode = 0644; |
138 | + wi_group->nattrs[nid]->kobj_attr.show = node_show; | 137 | + wi_group->nattrs[nid]->kobj_attr.show = node_show; |
139 | + wi_group->nattrs[nid]->kobj_attr.store = node_store; | 138 | + wi_group->nattrs[nid]->kobj_attr.store = node_store; |
... | ... | ||
145 | + kfree(wi_group->nattrs[nid]->kobj_attr.attr.name); | 144 | + kfree(wi_group->nattrs[nid]->kobj_attr.attr.name); |
146 | + kfree(wi_group->nattrs[nid]); | 145 | + kfree(wi_group->nattrs[nid]); |
147 | + wi_group->nattrs[nid] = NULL; | 146 | + wi_group->nattrs[nid] = NULL; |
148 | + pr_err("Failed to add attribute to weighted_interleave: %d\n", ret); | 147 | + pr_err("Failed to add attribute to weighted_interleave: %d\n", ret); |
149 | } | 148 | } |
149 | + mutex_unlock(&wi_group->kobj_lock); | ||
150 | 150 | ||
151 | - wi_group->nattrs[nid] = node_attr; | 151 | - wi_group->nattrs[nid] = node_attr; |
152 | - return 0; | 152 | - return 0; |
153 | + return ret; | 153 | + return ret; |
154 | +} | 154 | +} |
... | ... | ||
159 | + int err; | 159 | + int err; |
160 | + struct memory_notify *arg = data; | 160 | + struct memory_notify *arg = data; |
161 | + int nid = arg->status_change_nid; | 161 | + int nid = arg->status_change_nid; |
162 | + | 162 | + |
163 | + if (nid < 0) | 163 | + if (nid < 0) |
164 | + goto notifier_end; | 164 | + return NOTIFY_OK; |
165 | + | 165 | + |
166 | + switch(action) { | 166 | + switch(action) { |
167 | + case MEM_ONLINE: | 167 | + case MEM_ONLINE: |
168 | + if (node_state(nid, N_MEMORY)) { | 168 | + err = sysfs_wi_node_add(nid); |
169 | + err = sysfs_wi_node_add(nid); | 169 | + if (err) |
170 | + if (err) { | 170 | + pr_err("failed to add sysfs [node%d]\n", nid); |
171 | + pr_err("failed to add sysfs [node%d]\n", nid); | ||
172 | + return NOTIFY_BAD; | ||
173 | + } | ||
174 | + } | ||
175 | + break; | 171 | + break; |
176 | + case MEM_OFFLINE: | 172 | + case MEM_OFFLINE: |
177 | + if (!node_state(nid, N_MEMORY)) | 173 | + sysfs_wi_node_delete(nid); |
178 | + sysfs_wi_node_release(nid); | ||
179 | + break; | 174 | + break; |
180 | + } | 175 | + } |
181 | + | 176 | + |
182 | +notifier_end: | ||
183 | + return NOTIFY_OK; | 177 | + return NOTIFY_OK; |
184 | } | 178 | } |
185 | 179 | ||
186 | static int add_weighted_interleave_group(struct kobject *mempolicy_kobj) | 180 | static int __init add_weighted_interleave_group(struct kobject *mempolicy_kobj) |
187 | @@ -XXX,XX +XXX,XX @@ static int add_weighted_interleave_group(struct kobject *mempolicy_kobj) | 181 | @@ -XXX,XX +XXX,XX @@ static int __init add_weighted_interleave_group(struct kobject *mempolicy_kobj) |
188 | GFP_KERNEL); | 182 | GFP_KERNEL); |
189 | if (!wi_group) | 183 | if (!wi_group) |
190 | return -ENOMEM; | 184 | return -ENOMEM; |
191 | + mutex_init(&wi_group->kobj_lock); | 185 | + mutex_init(&wi_group->kobj_lock); |
192 | 186 | ||
193 | err = kobject_init_and_add(&wi_group->wi_kobj, &wi_ktype, mempolicy_kobj, | 187 | err = kobject_init_and_add(&wi_group->wi_kobj, &wi_ktype, mempolicy_kobj, |
194 | "weighted_interleave"); | 188 | "weighted_interleave"); |
195 | if (err) | 189 | if (err) |
196 | goto err_out; | 190 | goto err_put_kobj; |
197 | 191 | ||
198 | - for_each_node_state(nid, N_POSSIBLE) { | 192 | - for_each_node_state(nid, N_POSSIBLE) { |
199 | + for_each_online_node(nid) { | 193 | + for_each_online_node(nid) { |
200 | + if (!node_state(nid, N_MEMORY)) | 194 | + if (!node_state(nid, N_MEMORY)) |
201 | + continue; | 195 | + continue; |
202 | + | 196 | + |
203 | err = sysfs_wi_node_add(nid); | 197 | err = sysfs_wi_node_add(nid); |
204 | if (err) { | 198 | if (err) { |
205 | pr_err("failed to add sysfs [node%d]\n", nid); | 199 | pr_err("failed to add sysfs [node%d]\n", nid); |
206 | @@ -XXX,XX +XXX,XX @@ static int add_weighted_interleave_group(struct kobject *mempolicy_kobj) | 200 | @@ -XXX,XX +XXX,XX @@ static int __init add_weighted_interleave_group(struct kobject *mempolicy_kobj) |
207 | } | 201 | } |
208 | } | 202 | } |
209 | 203 | ||
210 | + hotplug_memory_notifier(wi_node_notifier, DEFAULT_CALLBACK_PRI); | 204 | + hotplug_memory_notifier(wi_node_notifier, DEFAULT_CALLBACK_PRI); |
211 | return 0; | 205 | return 0; |
212 | 206 | ||
213 | err_out: | 207 | err_del_kobj: |
214 | -- | 208 | -- |
215 | 2.34.1 | 209 | 2.34.1 | diff view generated by jsdifflib |