Manfred Spraul <manfred@xxxxxxxxxxxxxxxx> writes: >>>>> On 03/14/2018 08:49 PM, Eric W. Biederman wrote: >>>>>> To make it possible to keep checkpoint/restore working I have renamed >>>>>> the sysctls from xxx_next_id to xxx_nextid. That is enough change that >>>>>> a smart CRIU implementation can see that what is exported has changed, >>>>>> and act accordingly. New kernels will be able to restore the old id's. >>>>>> >>>>>> This code still needs some real world testing to verify my assumptions. >>>>>> And some work with the CRIU implementations to actually add the code >>>>>> that deals with the new for of id assignment. >>>>>> > It means that all existing checkpoint/restore application will not work with a > new kernel. > Everyone must first update the checkpoint/restore application, then update the > kernel. > > Is this acceptable? There is no nead. I just reread through how next_id is implementated in ipc/util.c and I had been reading it wrong. There is no need to change the sysctl. What criu needs is an interface that specifies the next_id to allocate both the high and the low bits and that is what this the sysctl provides. The implemenation could use a little cleanup so it is easier to understand something like this perhaps: diff --git a/ipc/util.c b/ipc/util.c index 3783b7991cc7..2d4ec6e5b70b 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -192,46 +192,32 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) return NULL; } -#ifdef CONFIG_CHECKPOINT_RESTORE -/* - * Specify desired id for next allocated IPC object. - */ -#define ipc_idr_alloc(ids, new) \ - idr_alloc(&(ids)->ipcs_idr, (new), \ - (ids)->next_id < 0 ? 0 : ipcid_to_idx((ids)->next_id),\ - 0, GFP_NOWAIT) - -static inline int ipc_buildid(int id, struct ipc_ids *ids, - struct kern_ipc_perm *new) -{ - if (ids->next_id < 0) { /* default, behave as !CHECKPOINT_RESTORE */ - new->seq = ids->seq++; - if (ids->seq > IPCID_SEQ_MAX) - ids->seq = 0; - } else { - new->seq = ipcid_to_seqx(ids->next_id); - ids->next_id = -1; - } - return SEQ_MULTIPLIER * new->seq + id; -} - -#else -#define ipc_idr_alloc(ids, new) \ - idr_alloc(&(ids)->ipcs_idr, (new), 0, 0, GFP_NOWAIT) - -static inline int ipc_buildid(int id, struct ipc_ids *ids, - struct kern_ipc_perm *new) +static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new) { + int id; +#ifdef CONFIG_CHECKPOINT_RESTORE + if (unlikely(new->id >= 0)) { + int idx = ipcid_to_idx(new->id); + id = idr_alloc(&ids->ipcs_idr, new, idx, 0, GFP_NOWAIT); + if (id < 0) + return id; + if (id != idx) { + idr_remove(&ids->ipcs_idr, id); + return -EBUSY; + } + new->seq = ipcid_to_seqx(new->id); + return id; + } +#endif + id = idr_alloc(&ids->ipcs_idr, new, 0, 0, GFP_NOWAIT); new->seq = ids->seq++; if (ids->seq > IPCID_SEQ_MAX) ids->seq = 0; - - return SEQ_MULTIPLIER * new->seq + id; + new->id = SEQ_MULTIPLIER * new->seq + id; + return id; } -#endif /* CONFIG_CHECKPOINT_RESTORE */ - /** * ipc_addid - add an ipc identifier * @ids: ipc identifier set @@ -269,6 +255,10 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit) new->cuid = new->uid = euid; new->gid = new->cgid = egid; + new->id = ids->next_id; + if (new->id >= 0) + ids->next_id = -1; + id = ipc_idr_alloc(ids, new); idr_preload_end(); @@ -290,8 +280,6 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit) if (id > ids->max_id) ids->max_id = id; - new->id = ipc_buildid(id, ids, new); - return id; } Eric -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html