static struct mount *next_group(struct mount *m, struct mount *origin) { while (1) { while (1) { struct mount *next; if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) return first_slave(m); next = next_peer(m); if (m->mnt_group_id == origin->mnt_group_id) { if (next == origin) return NULL; } else if (m->mnt_slave.next != &next->mnt_slave) break; m = next; } /* m is the last peer */ while (1) { struct mount *master = m->mnt_master; if (m->mnt_slave.next != &master->mnt_slave_list) return next_slave(m); m = next_peer(master); if (master->mnt_group_id == origin->mnt_group_id) break; if (master->mnt_slave.next == &m->mnt_slave) break; m = master; } if (m == origin) return NULL; } }
/* * return the source mount to be used for cloning * * @dest the current destination mount * @last_dest the last seen destination mount * @last_src the last seen source mount * @type return CL_SLAVE if the new mount has to be * cloned as a slave. */ static struct vfsmount *get_source(struct vfsmount *dest, struct vfsmount *last_dest, struct vfsmount *last_src, int *type) { struct vfsmount *p_last_src = NULL; struct vfsmount *p_last_dest = NULL; while (last_dest != dest->mnt_master) { p_last_dest = last_dest; p_last_src = last_src; last_dest = last_dest->mnt_master; last_src = last_src->mnt_master; } if (p_last_dest) { do { p_last_dest = next_peer(p_last_dest); } while (IS_MNT_NEW(p_last_dest)); /* is that a peer of the earlier? */ if (dest == p_last_dest) { *type = CL_MAKE_SHARED; return p_last_src; } } /* slave of the earlier, then */ *type = CL_SLAVE; /* beginning of peer group among the slaves? */ if (IS_MNT_SHARED(dest)) *type |= CL_MAKE_SHARED; return last_src; }
static struct mount *get_source(struct mount *dest, struct mount *last_dest, struct mount *last_src, int *type) { struct mount *p_last_src = NULL; struct mount *p_last_dest = NULL; while (last_dest != dest->mnt_master) { p_last_dest = last_dest; p_last_src = last_src; last_dest = last_dest->mnt_master; last_src = last_src->mnt_master; } if (p_last_dest) { do { p_last_dest = next_peer(p_last_dest); } while (IS_MNT_NEW(p_last_dest)); if (dest == p_last_dest) { *type = CL_MAKE_SHARED; return p_last_src; } } *type = CL_SLAVE; if (IS_MNT_SHARED(dest)) *type |= CL_MAKE_SHARED; return last_src; }
static int do_make_slave(struct mount *mnt) { struct mount *peer_mnt = mnt, *master = mnt->mnt_master; struct mount *slave_mnt; /* * slave 'mnt' to a peer mount that has the * same root dentry. If none is available then * slave it to anything that is available. */ while ((peer_mnt = next_peer(peer_mnt)) != mnt && peer_mnt->mnt.mnt_root != mnt->mnt.mnt_root) ; if (peer_mnt == mnt) { peer_mnt = next_peer(mnt); if (peer_mnt == mnt) peer_mnt = NULL; } if (mnt->mnt_group_id && IS_MNT_SHARED(mnt) && list_empty(&mnt->mnt_share)) mnt_release_group_id(mnt); list_del_init(&mnt->mnt_share); mnt->mnt_group_id = 0; if (peer_mnt) master = peer_mnt; if (master) { list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) slave_mnt->mnt_master = master; list_move(&mnt->mnt_slave, &master->mnt_slave_list); list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); INIT_LIST_HEAD(&mnt->mnt_slave_list); } else { struct list_head *p = &mnt->mnt_slave_list; while (!list_empty(p)) { slave_mnt = list_first_entry(p, struct mount, mnt_slave); list_del_init(&slave_mnt->mnt_slave); slave_mnt->mnt_master = NULL; } } mnt->mnt_master = master; CLEAR_MNT_SHARED(mnt); return 0; }
/* * mount 'source_mnt' under the destination 'dest_mnt' at * dentry 'dest_dentry'. And propagate that mount to * all the peer and slave mounts of 'dest_mnt'. * Link all the new mounts into a propagation tree headed at * source_mnt. Also link all the new mounts using ->mnt_list * headed at source_mnt's ->mnt_list * * @dest_mnt: destination mount. * @dest_dentry: destination dentry. * @source_mnt: source mount. * @tree_list : list of heads of trees to be attached. */ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp, struct mount *source_mnt, struct hlist_head *tree_list) { struct mount *m, *n; int ret = 0; /* * we don't want to bother passing tons of arguments to * propagate_one(); everything is serialized by namespace_sem, * so globals will do just fine. */ user_ns = current->nsproxy->mnt_ns->user_ns; last_dest = dest_mnt; last_source = source_mnt; mp = dest_mp; list = tree_list; dest_master = dest_mnt->mnt_master; /* all peers of dest_mnt, except dest_mnt itself */ for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) { ret = propagate_one(n); if (ret) goto out; } /* all slave groups */ for (m = next_group(dest_mnt, dest_mnt); m; m = next_group(m, dest_mnt)) { /* everything in that slave group */ n = m; do { ret = propagate_one(n); if (ret) goto out; n = next_peer(n); } while (n != m); } out: read_seqlock_excl(&mount_lock); hlist_for_each_entry(n, tree_list, mnt_hash) { m = n->mnt_parent; if (m->mnt_master != dest_mnt->mnt_master) CLEAR_MNT_MARK(m->mnt_master); }
static struct vfsmount *get_peer_under_root(struct vfsmount *mnt, struct mnt_namespace *ns, const struct path *root) { struct vfsmount *m = mnt; do { /* Check the namespace first for optimization */ if (m->mnt_ns == ns && is_path_reachable(m, m->mnt_root, root)) return m; m = next_peer(m); } while (m != mnt); return NULL; }
static struct mount *get_peer_under_root(struct mount *mnt, struct mnt_namespace *ns, const struct path *root) { struct mount *m = mnt; do { if (m->mnt_ns == ns && is_path_reachable(m, m->mnt.mnt_root, root)) return m; m = next_peer(m); } while (m != mnt); return NULL; }
void accept_handler(boost::shared_ptr<connection> peer, const boost::system::error_code &ec) { std::cout << "ACCEPTOR: Accept handler called, we have a new stream!" << std::endl; boost::asio::async_read( peer->stream, boost::asio::buffer(&peer->buffer_space[0], 64), boost::bind(&example::read_handler, this, peer, _1, _2) ); // Get ready for the next connection boost::shared_ptr<connection> next_peer(boost::make_shared<connection>(next_connection_id_++, service_)); acceptor_.async_accept( next_peer->stream, boost::bind(&example::accept_handler, this, next_peer, _1) ); }
/* * get the next mount in the propagation tree. * @m: the mount seen last * @origin: the original mount from where the tree walk initiated * * Note that peer groups form contiguous segments of slave lists. * We rely on that in get_source() to be able to find out if * vfsmount found while iterating with propagation_next() is * a peer of one we'd found earlier. */ static struct mount *propagation_next(struct mount *m, struct mount *origin) { /* are there any slaves of this mount? */ if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) return first_slave(m); while (1) { struct mount *master = m->mnt_master; if (master == origin->mnt_master) { struct mount *next = next_peer(m); return (next == origin) ? NULL : next; } else if (m->mnt_slave.next != &master->mnt_slave_list) return next_slave(m); /* back at master */ m = master; } }