| .. | .. |
|---|
| 100 | 100 | static const struct rhashtable_params ipc_kht_params = { |
|---|
| 101 | 101 | .head_offset = offsetof(struct kern_ipc_perm, khtnode), |
|---|
| 102 | 102 | .key_offset = offsetof(struct kern_ipc_perm, key), |
|---|
| 103 | | - .key_len = FIELD_SIZEOF(struct kern_ipc_perm, key), |
|---|
| 104 | | - .locks_mul = 1, |
|---|
| 103 | + .key_len = sizeof_field(struct kern_ipc_perm, key), |
|---|
| 105 | 104 | .automatic_shrinking = true, |
|---|
| 106 | 105 | }; |
|---|
| 107 | 106 | |
|---|
| .. | .. |
|---|
| 110 | 109 | * @ids: ipc identifier set |
|---|
| 111 | 110 | * |
|---|
| 112 | 111 | * Set up the sequence range to use for the ipc identifier range (limited |
|---|
| 113 | | - * below IPCMNI) then initialise the keys hashtable and ids idr. |
|---|
| 112 | + * below ipc_mni) then initialise the keys hashtable and ids idr. |
|---|
| 114 | 113 | */ |
|---|
| 115 | 114 | void ipc_init_ids(struct ipc_ids *ids) |
|---|
| 116 | 115 | { |
|---|
| .. | .. |
|---|
| 120 | 119 | rhashtable_init(&ids->key_ht, &ipc_kht_params); |
|---|
| 121 | 120 | idr_init(&ids->ipcs_idr); |
|---|
| 122 | 121 | ids->max_idx = -1; |
|---|
| 122 | + ids->last_idx = -1; |
|---|
| 123 | 123 | #ifdef CONFIG_CHECKPOINT_RESTORE |
|---|
| 124 | 124 | ids->next_id = -1; |
|---|
| 125 | 125 | #endif |
|---|
| 126 | 126 | } |
|---|
| 127 | 127 | |
|---|
| 128 | 128 | #ifdef CONFIG_PROC_FS |
|---|
| 129 | | -static const struct file_operations sysvipc_proc_fops; |
|---|
| 129 | +static const struct proc_ops sysvipc_proc_ops; |
|---|
| 130 | 130 | /** |
|---|
| 131 | 131 | * ipc_init_proc_interface - create a proc interface for sysipc types using a seq_file interface. |
|---|
| 132 | 132 | * @path: Path in procfs |
|---|
| .. | .. |
|---|
| 151 | 151 | pde = proc_create_data(path, |
|---|
| 152 | 152 | S_IRUGO, /* world readable */ |
|---|
| 153 | 153 | NULL, /* parent dir */ |
|---|
| 154 | | - &sysvipc_proc_fops, |
|---|
| 154 | + &sysvipc_proc_ops, |
|---|
| 155 | 155 | iface); |
|---|
| 156 | 156 | if (!pde) |
|---|
| 157 | 157 | kfree(iface); |
|---|
| .. | .. |
|---|
| 193 | 193 | * |
|---|
| 194 | 194 | * The caller must own kern_ipc_perm.lock.of the new object. |
|---|
| 195 | 195 | * On error, the function returns a (negative) error code. |
|---|
| 196 | + * |
|---|
| 197 | + * To conserve sequence number space, especially with extended ipc_mni, |
|---|
| 198 | + * the sequence number is incremented only when the returned ID is less than |
|---|
| 199 | + * the last one. |
|---|
| 196 | 200 | */ |
|---|
| 197 | 201 | static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new) |
|---|
| 198 | 202 | { |
|---|
| .. | .. |
|---|
| 216 | 220 | */ |
|---|
| 217 | 221 | |
|---|
| 218 | 222 | if (next_id < 0) { /* !CHECKPOINT_RESTORE or next_id is unset */ |
|---|
| 219 | | - new->seq = ids->seq++; |
|---|
| 220 | | - if (ids->seq > IPCID_SEQ_MAX) |
|---|
| 221 | | - ids->seq = 0; |
|---|
| 222 | | - idx = idr_alloc(&ids->ipcs_idr, new, 0, 0, GFP_NOWAIT); |
|---|
| 223 | + int max_idx; |
|---|
| 224 | + |
|---|
| 225 | + max_idx = max(ids->in_use*3/2, ipc_min_cycle); |
|---|
| 226 | + max_idx = min(max_idx, ipc_mni); |
|---|
| 227 | + |
|---|
| 228 | + /* allocate the idx, with a NULL struct kern_ipc_perm */ |
|---|
| 229 | + idx = idr_alloc_cyclic(&ids->ipcs_idr, NULL, 0, max_idx, |
|---|
| 230 | + GFP_NOWAIT); |
|---|
| 231 | + |
|---|
| 232 | + if (idx >= 0) { |
|---|
| 233 | + /* |
|---|
| 234 | + * idx got allocated successfully. |
|---|
| 235 | + * Now calculate the sequence number and set the |
|---|
| 236 | + * pointer for real. |
|---|
| 237 | + */ |
|---|
| 238 | + if (idx <= ids->last_idx) { |
|---|
| 239 | + ids->seq++; |
|---|
| 240 | + if (ids->seq >= ipcid_seq_max()) |
|---|
| 241 | + ids->seq = 0; |
|---|
| 242 | + } |
|---|
| 243 | + ids->last_idx = idx; |
|---|
| 244 | + |
|---|
| 245 | + new->seq = ids->seq; |
|---|
| 246 | + /* no need for smp_wmb(), this is done |
|---|
| 247 | + * inside idr_replace, as part of |
|---|
| 248 | + * rcu_assign_pointer |
|---|
| 249 | + */ |
|---|
| 250 | + idr_replace(&ids->ipcs_idr, new, idx); |
|---|
| 251 | + } |
|---|
| 223 | 252 | } else { |
|---|
| 224 | 253 | new->seq = ipcid_to_seqx(next_id); |
|---|
| 225 | 254 | idx = idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id), |
|---|
| 226 | 255 | 0, GFP_NOWAIT); |
|---|
| 227 | 256 | } |
|---|
| 228 | 257 | if (idx >= 0) |
|---|
| 229 | | - new->id = SEQ_MULTIPLIER * new->seq + idx; |
|---|
| 258 | + new->id = (new->seq << ipcmni_seq_shift()) + idx; |
|---|
| 230 | 259 | return idx; |
|---|
| 231 | 260 | } |
|---|
| 232 | 261 | |
|---|
| .. | .. |
|---|
| 254 | 283 | /* 1) Initialize the refcount so that ipc_rcu_putref works */ |
|---|
| 255 | 284 | refcount_set(&new->refcount, 1); |
|---|
| 256 | 285 | |
|---|
| 257 | | - if (limit > IPCMNI) |
|---|
| 258 | | - limit = IPCMNI; |
|---|
| 286 | + if (limit > ipc_mni) |
|---|
| 287 | + limit = ipc_mni; |
|---|
| 259 | 288 | |
|---|
| 260 | 289 | if (ids->in_use >= limit) |
|---|
| 261 | 290 | return -ENOSPC; |
|---|
| .. | .. |
|---|
| 739 | 768 | if (total >= ids->in_use) |
|---|
| 740 | 769 | goto out; |
|---|
| 741 | 770 | |
|---|
| 742 | | - for (; pos < IPCMNI; pos++) { |
|---|
| 771 | + for (; pos < ipc_mni; pos++) { |
|---|
| 743 | 772 | ipc = idr_find(&ids->ipcs_idr, pos); |
|---|
| 744 | 773 | if (ipc != NULL) { |
|---|
| 745 | 774 | rcu_read_lock(); |
|---|
| .. | .. |
|---|
| 855 | 884 | return seq_release_private(inode, file); |
|---|
| 856 | 885 | } |
|---|
| 857 | 886 | |
|---|
| 858 | | -static const struct file_operations sysvipc_proc_fops = { |
|---|
| 859 | | - .open = sysvipc_proc_open, |
|---|
| 860 | | - .read = seq_read, |
|---|
| 861 | | - .llseek = seq_lseek, |
|---|
| 862 | | - .release = sysvipc_proc_release, |
|---|
| 887 | +static const struct proc_ops sysvipc_proc_ops = { |
|---|
| 888 | + .proc_flags = PROC_ENTRY_PERMANENT, |
|---|
| 889 | + .proc_open = sysvipc_proc_open, |
|---|
| 890 | + .proc_read = seq_read, |
|---|
| 891 | + .proc_lseek = seq_lseek, |
|---|
| 892 | + .proc_release = sysvipc_proc_release, |
|---|
| 863 | 893 | }; |
|---|
| 864 | 894 | #endif /* CONFIG_PROC_FS */ |
|---|