and call it from open_related_ns().
Unified · Split
| @@ -17,6 +17,7 @@ struct fs_context; · 16 unmodified lines | |||
| 17 | struct pipe_inode_info; | 17 | struct pipe_inode_info; |
| 18 | struct iov_iter; | 18 | struct iov_iter; |
| 19 | struct mnt_idmap; | 19 | struct mnt_idmap; |
| 20 | struct ns_common; | ||
| 20 | 21 | ||
| 21 | /* | 22 | /* |
| 22 | * block/bdev.c | 23 | * block/bdev.c |
| @@ -321,3 +322,4 @@ struct stashed_operations { · 298 unmodified lines | |||
| 321 | int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, | 322 | int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, |
| 322 | struct path *path); | 323 | struct path *path); |
| 323 | void stashed_dentry_prune(struct dentry *dentry); | 324 | void stashed_dentry_prune(struct dentry *dentry); |
| 325 | int open_namespace(struct ns_common *ns); | ||
| @@ -82,40 +82,47 @@ int ns_get_path(struct path *path, struct task_struct *task, · 81 unmodified lines | |||
| 82 | return ns_get_path_cb(path, ns_get_path_task, &args); | 82 | return ns_get_path_cb(path, ns_get_path_task, &args); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | int open_related_ns(struct ns_common *ns, | 85 | /** |
| 86 | struct ns_common *(*get_ns)(struct ns_common *ns)) | 86 | * open_namespace - open a namespace |
| 87 | * @ns: the namespace to open | ||
| 88 | * | ||
| 89 | * This will consume a reference to @ns indendent of success or failure. | ||
| 90 | * | ||
| 91 | * Return: A file descriptor on success or a negative error code on failure. | ||
| 92 | */ | ||
| 93 | int open_namespace(struct ns_common *ns) | ||
| 87 | { | 94 | { |
| 88 | struct path path = {}; | 95 | struct path path __free(path_put) = {}; |
| 89 | struct ns_common *relative; | ||
| 90 | struct file *f; | 96 | struct file *f; |
| 91 | int err; | 97 | int err; |
| 92 | int fd; | ||
| 93 | 98 | ||
| 94 | fd = get_unused_fd_flags(O_CLOEXEC); | 99 | /* call first to consume reference */ |
| 100 | err = path_from_stashed(&ns->stashed, nsfs_mnt, ns, &path); | ||
| 101 | if (err < 0) | ||
| 102 | return err; | ||
| 103 | |||
| 104 | CLASS(get_unused_fd, fd)(O_CLOEXEC); | ||
| 95 | if (fd < 0) | 105 | if (fd < 0) |
| 96 | return fd; | 106 | return fd; |
| 97 | 107 | ||
| 108 | f = dentry_open(&path, O_RDONLY, current_cred()); | ||
| 109 | if (IS_ERR(f)) | ||
| 110 | return PTR_ERR(f); | ||
| 111 | |||
| 112 | fd_install(fd, f); | ||
| 113 | return take_fd(fd); | ||
| 114 | } | ||
| 115 | |||
| 116 | int open_related_ns(struct ns_common *ns, | ||
| 117 | struct ns_common *(*get_ns)(struct ns_common *ns)) | ||
| 118 | { | ||
| 119 | struct ns_common *relative; | ||
| 120 | |||
| 98 | relative = get_ns(ns); | 121 | relative = get_ns(ns); |
| 99 | if (IS_ERR(relative)) { | 122 | if (IS_ERR(relative)) |
| 100 | put_unused_fd(fd); | ||
| 101 | return PTR_ERR(relative); | 123 | return PTR_ERR(relative); |
| 102 | } | ||
| 103 | 124 | ||
| 104 | err = path_from_stashed(&relative->stashed, nsfs_mnt, relative, &path); | 125 | return open_namespace(relative); |
| 105 | if (err < 0) { | ||
| 106 | put_unused_fd(fd); | ||
| 107 | return err; | ||
| 108 | } | ||
| 109 | |||
| 110 | f = dentry_open(&path, O_RDONLY, current_cred()); | ||
| 111 | path_put(&path); | ||
| 112 | if (IS_ERR(f)) { | ||
| 113 | put_unused_fd(fd); | ||
| 114 | fd = PTR_ERR(f); | ||
| 115 | } else | ||
| 116 | fd_install(fd, f); | ||
| 117 | |||
| 118 | return fd; | ||
| 119 | } | 126 | } |
| 120 | EXPORT_SYMBOL_GPL(open_related_ns); | 127 | EXPORT_SYMBOL_GPL(open_related_ns); |
| 121 | 128 | ||