checkpoint/restart: fix code to handle open symlinks
RFC PATCH 1/4 checkpoint/restart: fix code to handle open symlinks
There's no such thing as an opened symlink.
---
linux-2.6.git-dave/checkpoint/ckpt_file.c | 3 --- linux-2.6.git-dave/checkpoint/rstr_file.c | 1 - linux-2.6.git-dave/include/linux/checkpoint_hdr.h | 1 - 3 files changed, 5 deletions(-)
checkpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-no-opened-symlinks +0 -3
@@ -104,9 +104,6 @@ static int cr_write_fd_data(struct cr_ctcase S_IFDIR : fd_type =CR_FD_DIR ;break ; -case S_IFLNK : - fd_type =CR_FD_LINK ; -break ;default :cr_hbuf_put (ctx,sizeof (*hh));return -EBADF ;
checkpoint/rstr_file.c renamed from checkpoint/rstr_file.c~fix-no-opened-symlinks +0 -1
@@ -94,7 +94,6 @@ cr_read_fd_data(struct cr_ctx *ctx, struswitch (hh->fd_type) {case CR_FD_FILE :case CR_FD_DIR : -case CR_FD_LINK : file =cr_read_open_fname (ctx, hh->f_flags, hh->f_mode);break ;default :
include/linux/checkpoint_hdr.h renamed from include/linux/checkpoint_hdr.h~fix-no-opened-symlinks +0 -1
@@ -137,7 +137,6 @@ struct cr_hdr_fd_ent {enum fd_type {CR_FD_FILE =1 ,CR_FD_DIR , -CR_FD_LINK };struct cr_hdr_fd_data {
_
RFC PATCH 2/4 checkpoint/restart: fix cr_ctx_checkpoint() locking
The existing ctx->vfsroot is dangerous. We take it from the root task via: ctx->root_task->fs->root and don't take a ref on the 'fs' in there. We also take a ref on the fs.root which is worthless.
So, replace ctx->vfsroot with a reference to the 'fs' instead. This gives us easy access to fs.root later on, and also lets us do proper refcounting.
This, of course, eventually needs to be done per-process but this should at least remove a potential oops.
---
linux-2.6.git-dave/checkpoint/checkpoint.c | 7 ++----- linux-2.6.git-dave/checkpoint/ckpt_file.c | 2 +- linux-2.6.git-dave/checkpoint/ckpt_mem.c | 2 +- linux-2.6.git-dave/checkpoint/sys.c | 4 ++-- linux-2.6.git-dave/include/linux/checkpoint.h | 2 +- 5 files changed, 7 insertions(+), 10 deletions(-)
checkpoint/checkpoint.c renamed from checkpoint/checkpoint.c~fix-cr_ctx_checkpoint-locking +2 -5
@@ -511,12 +511,9 @@ static int cr_ctx_checkpoint(struct cr_c* assume checkpointer is in container's root vfs * FIXME: this works for now, but will change with real containers */ -task_lock (ctx->root_task); - ctx->vfsroot = &ctx->root_task->fs->root; -task_unlock (ctx->root_task); -if (!ctx->vfsroot) + ctx->fs =get_fs_struct (ctx->root_task); +if (!ctx->fs)return -EAGAIN ; -path_get (ctx->vfsroot);return 0 ; }
checkpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-cr_ctx_checkpoint-locking +1 -1
@@ -117,7 +117,7 @@ static int cr_write_fd_data(struct cr_ctif (ret <0 )return ret; -return cr_write_fname (ctx, &file->f_path, ctx->vfsroot); +return cr_write_fname (ctx, &file->f_path, &ctx->fs.root); }/**
checkpoint/ckpt_mem.c renamed from checkpoint/ckpt_mem.c~fix-cr_ctx_checkpoint-locking +1 -1
@@ -436,7 +436,7 @@ static int cr_write_vma(struct cr_ctx *c/* save the file name, if relevant */ if (vma->vm_file) { - ret =cr_write_fname (ctx, &vma->vm_file->f_path, ctx->vfsroot); + ret =cr_write_fname (ctx, &vma->vm_file->f_path, &ctx->fs.root);if (ret <0 )return ret; }
checkpoint/sys.c renamed from checkpoint/sys.c~fix-cr_ctx_checkpoint-locking +2 -2
@@ -152,8 +152,8 @@ static void cr_ctx_free(struct cr_ctx *ckfree (ctx->hbuf); -if (ctx->vfsroot) -path_put (ctx->vfsroot); +if (ctx->fs) +put_fs_struct (ctx->fs);cr_pgarr_free (ctx);cr_objhash_free (ctx);
include/linux/checkpoint.h renamed from include/linux/checkpoint.h~fix-cr_ctx_checkpoint-locking +1 -1
@@ -41,7 +41,7 @@ struct cr_ctx {struct list_head pgarr_list;/* page array to dump VMA contents */ -struct path *vfsroot;/* container root (FIXME) */ +struct fs_struct *fs;/* container root/pwd (FIXME) */ /* [multi-process checkpoint] */ struct task_struct **tasks_arr;/* array of all tasks [checkpoint] */
_
Re: [RFC][PATCH 2/4] checkpoint/restart: fix cr_ctx_checkpoint() locking
any reason why you want to reference the entire ->fs instead of, as I suggested, make a *copy* of ->fs->root and then reference its contents ?
Quoted 91 lines · Dave Hansen
The existing
ctx->vfsrootis dangerous. We take it from the root task via:ctx->root_task->fs->rootand don't take a ref on the 'fs' in there. We also take a ref on the fs.root which is worthless.So, replace
ctx->vfsrootwith a reference to the 'fs' instead. This gives us easy access to fs.root later on, and also lets us do proper refcounting.This, of course, eventually needs to be done per-process but this should at least remove a potential oops.
---
linux-2.6.git-dave/checkpoint/checkpoint.c | 7 ++----- linux-2.6.git-dave/checkpoint/ckpt_file.c | 2 +- linux-2.6.git-dave/checkpoint/ckpt_mem.c | 2 +- linux-2.6.git-dave/checkpoint/sys.c | 4 ++-- linux-2.6.git-dave/include/linux/checkpoint.h | 2 +- 5 files changed, 7 insertions(+), 10 deletions(-)diff -puN checkpoint/checkpoint.c~fix-cr_ctx_checkpoint-locking
checkpoint/checkpoint.ccheckpoint/checkpoint.c renamed from checkpoint/checkpoint.c~fix-cr_ctx_checkpoint-locking +2
-5@@ -511,12 +511,9 @@ static int cr_ctx_checkpoint(struct cr_c* assume checkpointer is in container's root vfs * FIXME: this works for now, but will change with real containers */ -task_lock (ctx->root_task); - ctx->vfsroot = &ctx->root_task->fs->root; -task_unlock (ctx->root_task); -if (!ctx->vfsroot) + ctx->fs =get_fs_struct (ctx->root_task); +if (!ctx->fs)return -EAGAIN ; -path_get (ctx->vfsroot);return 0 ; }diff -puN checkpoint/ckpt_file.c~fix-cr_ctx_checkpoint-locking
checkpoint/ckpt_file.ccheckpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-cr_ctx_checkpoint-locking +1
-1@@ -117,7 +117,7 @@ static int cr_write_fd_data(struct cr_ctif (ret <0 )return ret; -return cr_write_fname (ctx, &file->f_path, ctx->vfsroot); +return cr_write_fname (ctx, &file->f_path, &ctx->fs.root); }/** diff -puN checkpoint/ckpt_mem.c~fix-cr_ctx_checkpoint-locking
checkpoint/ckpt_mem.ccheckpoint/ckpt_mem.c renamed from checkpoint/ckpt_mem.c~fix-cr_ctx_checkpoint-locking +1
-1@@ -436,7 +436,7 @@ static int cr_write_vma(struct cr_ctx *c/* save the file name, if relevant */ if (vma->vm_file) { - ret =cr_write_fname (ctx, &vma->vm_file->f_path, ctx->vfsroot); + ret =cr_write_fname (ctx, &vma->vm_file->f_path, &ctx->fs.root);if (ret <0 )return ret; }diff -puN checkpoint/sys.c~fix-cr_ctx_checkpoint-locking
checkpoint/sys.ccheckpoint/sys.c renamed from checkpoint/sys.c~fix-cr_ctx_checkpoint-locking +2
-2@@ -152,8 +152,8 @@ static void cr_ctx_free(struct cr_ctx *ckfree (ctx->hbuf); -if (ctx->vfsroot) -path_put (ctx->vfsroot); +if (ctx->fs) +put_fs_struct (ctx->fs);cr_pgarr_free (ctx);cr_objhash_free (ctx);diff -puN
include/linux/checkpoint.h~fix-cr_ctx_checkpoint-lockinginclude/linux/checkpoint.hinclude/linux/checkpoint.h renamed from include/linux/checkpoint.h~fix-cr_ctx_checkpoint-locking +1
-1@@ -41,7 +41,7 @@ struct cr_ctx {struct list_head pgarr_list;/* page array to dump VMA contents */ -struct path *vfsroot;/* container root (FIXME) */ +struct fs_struct *fs;/* container root/pwd (FIXME) */ /* [multi-process checkpoint] */ struct task_struct **tasks_arr;/* array of all tasks [checkpoint] */ _
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [RFC][PATCH 2/4] checkpoint/restart: fix cr_ctx_checkpoint() locking
Quoted 3 lines · Oren Laadan
any reason why you want to reference the entire ->fs instead of, as I suggested, make a *copy* of ->fs->root and then reference its contents ?
This looked simpler to me. We're going to have to rip this sucker out anyway, so I went for what I thought was the smallest amount of code.
-- Dave
RFC PATCH 3/4 checkpoint/restart: fix 'struct file' references
In reply to Dave HansenWe must hold a reference to 'file' when it get passed in to fd_install(). After fd_install() the entry in the fdtable takes on the reference. If we don't hold a reference to it, another thread can come along after fd_install() and fput() it before we've done the get_file().
In cr_read_fd_data(), the cr_obj_add_ref() code does the get_file() internally. But, we need to do this (and get the ref) before we do the cr_attach_file(). Otherwise, the file can go away after the cr_attach_file() and before the cr_obj_add_ref().
---
linux-2.6.git-dave/checkpoint/rstr_file.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
checkpoint/rstr_file.c renamed from checkpoint/rstr_file.c~fix-refs-order-in-cr_attach_get_file +6 -5
@@ -59,8 +59,8 @@ static int cr_attach_get_file(struct filif (fd >=0 ) {fsnotify_open (file->f_path.dentry); -fd_install (fd, file);get_file (file); +fd_install (fd, file); }return fd; }
@@ -107,6 +107,11 @@ cr_read_fd_data(struct cr_ctx *ctx, stru/* FIX: need to restore uid, gid, owner etc */ +/* register new <objref, file> tuple in hash table */ + ret =cr_obj_add_ref (ctx, file, parent,CR_OBJ_FILE ,0 ); +if (ret <0 ) + goto out; + fd =cr_attach_file (file);/* no need to cleanup 'file' below */ if (fd <0 ) {filp_close (file,NULL );
@@ -114,10 +119,6 @@ cr_read_fd_data(struct cr_ctx *ctx, stru goto out; } -/* register new <objref, file> tuple in hash table */ - ret =cr_obj_add_ref (ctx, file, parent,CR_OBJ_FILE ,0 ); -if (ret <0 ) - goto out; ret =sys_fcntl (fd,F_SETFL , hh->f_flags &CR_SETFL_MASK );if (ret <0 ) goto out;
_
RFC PATCH 4/4 checkpoint/restart: simplify cr_scan_fds()
In reply to Dave HansenI think having all the allocations in one place, plus the reduction in the number of lines speaks for itself. In any case, this is last in the series and can be dropped if you don't like it.
---
linux-2.6.git-dave/checkpoint/ckpt_file.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
checkpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-cr_scan_fds-realloc +4 -9
@@ -38,6 +38,7 @@ int cr_scan_fds(struct files_struct *filint i, n =0 ;int tot =CR_DEFAULT_FDTABLE ; +retry: fds =kmalloc (tot *sizeof (*fds),GFP_KERNEL );if (!fds)return -ENOMEM ;
@@ -55,18 +56,12 @@ int cr_scan_fds(struct files_struct *filif (!fcheck_files (files, i))continue ;if (n == tot) { -/* -* fcheck_files() is safe with drop/re-acquire -* of the lock, because it tests: fd < max_fds -*/ +/* we undershot the size of fds[] */ spin_unlock (&files->file_lock);rcu_read_unlock (); tot *=2 ;/* won't overflow: kmalloc will fail */ - fds =krealloc (fds, tot *sizeof (*fds),GFP_KERNEL ); -if (!fds) -return -ENOMEM ; -rcu_read_lock (); -spin_lock (&files->file_lock); +kfree (fds); + goto retry; } fds[n++] = i; }
_
Re: [RFC][PATCH 4/4] checkpoint/restart: simplify cr_scan_fds()
Quoted 15 lines · Dave Hansen
I think having all the allocations in one place, plus the reduction in the number of lines speaks for itself. In any case, this is last in the series and can be dropped if you don't like it.
---
linux-2.6.git-dave/checkpoint/ckpt_file.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)diff -puN checkpoint/ckpt_file.c~fix-cr_scan_fds-realloc
checkpoint/ckpt_file.c
checkpoint/ckpt_file.c int cr_scan_fds(struct files_struct *fil · line 38
Quoted 1 line
checkpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-cr_scan_fds-realloc +0
-0@@ -38,6 +38,7 @@ int cr_scan_fds(struct files_struct *filint i, n =0 ;
Heh, well I think you'll need to initialize n after the retry: label.
Otherwise, I can see the appeal of this...
Quoted 33 lines
checkpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-cr_scan_fds-realloc +4
-9int tot =CR_DEFAULT_FDTABLE ; +retry: fds =kmalloc (tot *sizeof (*fds),GFP_KERNEL );if (!fds)return -ENOMEM ;@@ -55,18 +56,12 @@ int cr_scan_fds(struct files_struct *filif (!fcheck_files (files, i))continue ;if (n == tot) { -/* -* fcheck_files() is safe with drop/re-acquire -* of the lock, because it tests: fd < max_fds -*/ +/* we undershot the size of fds[] */ spin_unlock (&files->file_lock);rcu_read_unlock (); tot *=2 ;/* won't overflow: kmalloc will fail */ - fds =krealloc (fds, tot *sizeof (*fds),GFP_KERNEL ); -if (!fds) -return -ENOMEM ; -rcu_read_lock (); -spin_lock (&files->file_lock); +kfree (fds); + goto retry; } fds[n++] = i; }_
_______________________________________________
Containers mailing list Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
https://lists.linux-foundation.org/mailman/listinfo/containers
Re: [RFC][PATCH 4/4] checkpoint/restart: simplify cr_scan_fds()
In reply to Dave Hansen(as discussed in the LKML thread) as far as I can see the existing code is safe, and this code is not more correct (for restart) in terms of races with changes to the file table ?
Quoted 45 lines · Dave Hansen
I think having all the allocations in one place, plus the reduction in the number of lines speaks for itself. In any case, this is last in the series and can be dropped if you don't like it.
---
linux-2.6.git-dave/checkpoint/ckpt_file.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)diff -puN checkpoint/ckpt_file.c~fix-cr_scan_fds-realloc
checkpoint/ckpt_file.ccheckpoint/ckpt_file.c renamed from checkpoint/ckpt_file.c~fix-cr_scan_fds-realloc +4
-9@@ -38,6 +38,7 @@ int cr_scan_fds(struct files_struct *filint i, n =0 ;int tot =CR_DEFAULT_FDTABLE ; +retry: fds =kmalloc (tot *sizeof (*fds),GFP_KERNEL );if (!fds)return -ENOMEM ;@@ -55,18 +56,12 @@ int cr_scan_fds(struct files_struct *filif (!fcheck_files (files, i))continue ;if (n == tot) { -/* -* fcheck_files() is safe with drop/re-acquire -* of the lock, because it tests: fd < max_fds -*/ +/* we undershot the size of fds[] */ spin_unlock (&files->file_lock);rcu_read_unlock (); tot *=2 ;/* won't overflow: kmalloc will fail */ - fds =krealloc (fds, tot *sizeof (*fds),GFP_KERNEL ); -if (!fds) -return -ENOMEM ; -rcu_read_lock (); -spin_lock (&files->file_lock); +kfree (fds); + goto retry; } fds[n++] = i; }_
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [RFC][PATCH 4/4] checkpoint/restart: simplify cr_scan_fds()
Quoted 3 lines · Oren Laadan
(as discussed in the LKML thread) as far as I can see the existing code is safe, and this code is not more correct (for restart) in terms of races with changes to the file table ?
Agreed. This just saves a few lines of code.
-- Dave