예제 #1
0
파일: holder.cpp 프로젝트: darkk/porto
void TContainerHolder::RemoveLeftovers() {
    TError error;

    for (auto hy: Hierarchies) {
        std::vector<TCgroup> cgroups;

        error = hy->Cgroup(PORTO_ROOT_CGROUP).ChildsAll(cgroups);
        if (error)
            L_ERR() << "Cannot dump porto " << hy->Type << " cgroups : "
                    << error << std::endl;

        for (auto cg = cgroups.rbegin(); cg != cgroups.rend(); cg++) {
            std::string name = cg->Name.substr(strlen(PORTO_ROOT_CGROUP) + 1);
            if (Containers.count(name))
                continue;

            if (!cg->IsEmpty())
                (void)cg->KillAll(9);
            (void)cg->Remove();
        }
    }

    for (auto it: Containers) {
        auto container = it.second;
        if (container->Prop->Get<bool>(P_WEAK)) {
            auto holder_lock = ScopedLock();
            L_ACT() << "Destroy weak container " << it.first << std::endl;
            Destroy(holder_lock, container);
        }
    }
}
예제 #2
0
파일: cgroup.cpp 프로젝트: noxiouz/porto
TError TCgroup::Remove() const {
    struct stat st;
    TError error;

    if (Secondary())
        return TError(EError::Unknown, "Cannot create secondary cgroup " + Type());

    L_ACT() << "Remove cgroup " << *this << std::endl;
    error = Path().Rmdir();

    /* workaround for bad synchronization */
    if (error && error.GetErrno() == EBUSY &&
            !Path().StatStrict(st) && st.st_nlink == 2) {
        for (int i = 0; i < 100; i++) {
            usleep(config().daemon().cgroup_remove_timeout_s() * 10000);
            error = Path().Rmdir();
            if (!error || error.GetErrno() != EBUSY)
                break;
        }
    }

    if (error && (error.GetErrno() != ENOENT || Exists()))
        L_ERR() << "Cannot remove cgroup " << *this << " : " << error << std::endl;

    return error;
}
예제 #3
0
파일: holder.cpp 프로젝트: darkk/porto
TError TContainerHolder::Restore(TScopedLock &holder_lock, const std::string &name,
                                 const kv::TNode &node) {
    if (name == ROOT_CONTAINER || name == PORTO_ROOT_CONTAINER)
        return TError::Success();

    L_ACT() << "Restore container " << name << " (" << node.ShortDebugString() << ")" << std::endl;

    auto parent = GetParent(name);
    if (!parent)
        return TError(EError::InvalidValue, "invalid parent container");

    int id = 0;
    TError error = RestoreId(node, id);
    if (error)
        return error;

    if (!id)
        return TError(EError::Unknown, "Couldn't restore container id");

    auto c = std::make_shared<TContainer>(shared_from_this(), Storage, name, parent, id);
    error = c->Restore(holder_lock, node);
    if (error) {
        L_ERR() << "Can't restore container " << name << ": " << error << std::endl;
        return error;
    }

    Containers[name] = c;
    Statistics->Created++;
    return TError::Success();
}
예제 #4
0
void TTclass::Prepare(std::map<std::string, uint64_t> prio,
                       std::map<std::string, uint64_t> rate,
                       std::map<std::string, uint64_t> ceil) {
    L_ACT() << "Prepare tc class 0x" << std::hex << Handle << std::dec << " prio={" << MapToStr(prio) << "} rate={" << MapToStr(rate) << "} ceil={" << MapToStr(ceil) << "}" << std::endl;
    Prio = prio;
    Rate = rate;
    Ceil = ceil;
}
예제 #5
0
파일: cgroup.cpp 프로젝트: noxiouz/porto
TError TCgroup::Attach(pid_t pid) const {
    if (Secondary())
        return TError(EError::Unknown, "Cannot attach to secondary cgroup " + Type());

    L_ACT() << "Attach process " << pid << " to " << *this << std::endl;
    TError error = Knob("cgroup.procs").WriteAll(std::to_string(pid));
    if (error)
        L_ERR() << "Cannot attach process " << pid << " to " << *this << " : " << error << std::endl;

    return error;
}
예제 #6
0
파일: cgroup.cpp 프로젝트: noxiouz/porto
TError TCgroup::Create() const {
    TError error;

    if (Secondary())
        return TError(EError::Unknown, "Cannot create secondary cgroup " + Type());

    L_ACT() << "Create cgroup " << *this << std::endl;
    error = Path().Mkdir(0755);
    if (error)
        L_ERR() << "Cannot create cgroup " << *this << " : " << error << std::endl;

    return error;
}
예제 #7
0
파일: holder.cpp 프로젝트: darkk/porto
bool TContainerHolder::RestoreFromStorage() {
    std::vector<std::shared_ptr<TKeyValueNode>> nodes;

    auto holder_lock = ScopedLock();

    TError error = Storage->ListNodes(nodes);
    if (error) {
        L_ERR() << "Can't list key-value nodes: " << error << std::endl;
        return false;
    }

    auto name2node = SortNodes(nodes);
    bool restored = false;
    for (auto &pair : name2node) {
        auto node = pair.second;
        auto name = pair.first;

        L_ACT() << "Found " << name << " container in kvs" << std::endl;

        kv::TNode n;
        error = node->Load(n);
        if (error)
            continue;

        restored = true;
        error = Restore(holder_lock, name, n);
        if (error) {
            L_ERR() << "Can't restore " << name << ": " << error << std::endl;
            Statistics->RestoreFailed++;
            node->Remove();
            continue;
        }

        // FIXME since v1.0 we need to cleanup kvalue nodes with old naming
        if (TKeyValueStorage::Get(n, P_RAW_NAME, name))
            node->Remove();
    }

    if (restored) {
        for (auto &c: Containers) {
            if (c.second->IsLostAndRestored()) {
                ScheduleCgroupSync();
                break;
            }
        }
    }

    return restored;
}
예제 #8
0
파일: cgroup.cpp 프로젝트: noxiouz/porto
TError TCgroup::KillAll(int signal) const {
    std::vector<pid_t> tasks;
    TError error;

    L_ACT() << "KillAll " << signal << " " << *this << std::endl;

    error = GetTasks(tasks);
    if (!error) {
        for (const auto &pid : tasks) {
            if (kill(pid, signal) && errno != ESRCH) {
                error = TError(EError::Unknown, errno, StringFormat("kill(%d, %d)", pid, signal));
                L_ERR() << "Cannot kill process " << pid << " : " << error << std::endl;
            }
        }
    }

    return error;
}
예제 #9
0
TError TNetwork::Destroy() {
    auto lock = ScopedLock();

    L_ACT() << "Removing network..." << std::endl;

    if (Tclass) {
        TError error = Tclass->Remove();
        if (error)
            return error;
        Tclass = nullptr;
    }

    if (Qdisc) {
        TError error = Qdisc->Remove();
        if (error)
            return error;
        Qdisc = nullptr;
    }

    return TError::Success();
}
예제 #10
0
파일: holder.cpp 프로젝트: darkk/porto
bool TContainerHolder::DeliverEvent(const TEvent &event) {
    if (Verbose)
        L_EVT() << "Deliver event " << event.GetMsg() << std::endl;

    bool delivered = false;

    auto holder_lock = ScopedLock();

    switch (event.Type) {
    case EEventType::OOM:
    {
        std::shared_ptr<TContainer> target = event.Container.lock();
        if (target) {
            // check whether container can die due to OOM under holder lock,
            // assume container state is not changed when only holding
            // container lock
            if (target->MayReceiveOom(event.OOM.Fd)) {
                TNestedScopedLock lock(*target, holder_lock);
                if (target->IsValid() && target->MayReceiveOom(event.OOM.Fd)) {
                    // we don't want any concurrent stop/start/pause/etc and
                    // don't care whether parent acquired or not
                    target->AcquireForced();
                    target->DeliverEvent(holder_lock, event);
                    target->Release();
                    delivered = true;
                }
            }
        }
        break;
    }
    case EEventType::Respawn:
    {
        std::shared_ptr<TContainer> target = event.Container.lock();
        if (target) {
            // check whether container can respawn under holder lock,
            // assume container state is not changed when only holding
            // container lock
            if (target->MayRespawn()) {
                TNestedScopedLock lock(*target, holder_lock);
                if (target->IsValid() && target->MayRespawn() && !target->IsAcquired()) {
                    target->DeliverEvent(holder_lock, event);
                    delivered = true;
                }
            }
        }
        break;
    }
    case EEventType::Exit:
    {
        auto list = List();
        for (auto &target : list) {
            // check whether container can exit under holder lock,
            // assume container state is not changed when only holding
            // container lock
            if (target->MayExit(event.Exit.Pid)) {
                TNestedScopedLock lock(*target, holder_lock);
                if (target->IsValid() && target->MayExit(event.Exit.Pid)) {
                    // we don't want any concurrent stop/start/pause/etc and
                    // don't care whether parent acquired or not
                    target->AcquireForced();
                    target->DeliverEvent(holder_lock, event);
                    target->Release();
                    break;
                }
            }
        }
        AckExitStatus(event.Exit.Pid);
        delivered = true;
        break;
    }
    case EEventType::CgroupSync:
    {
        bool rearm = false;
        auto list = List();
        for (auto &target : list) {
            // don't lock container here, LostAndRestored is never changed
            // after startup
            if (target->IsLostAndRestored())
                rearm = true;

            if (target->IsAcquired())
                continue;

            TNestedScopedLock lock(*target, holder_lock);
            if (target->IsValid() && target->IsLostAndRestored()) {
                if (target->IsAcquired())
                    continue;
                target->SyncStateWithCgroup(holder_lock);
            }
        }
        if (rearm)
            ScheduleCgroupSync();
        delivered = true;
        break;
    }
    case EEventType::WaitTimeout:
    {
        auto w = event.WaitTimeout.Waiter.lock();
        if (w)
            w->Signal(nullptr);
        delivered = true;
        break;
    }
    case EEventType::DestroyWeak:
    {
        auto container = event.Container.lock();
        if (container) {
            TNestedScopedLock lock(*container, holder_lock);
            L_ACT() << "Destroy weak container " << container->GetName() << std::endl;
            Destroy(holder_lock, container);
        }
    }
    case EEventType::RotateLogs:
    {
        { /* gc */
            std::vector<std::string> remove;
            for (auto target : List())
                // don't lock container here, we don't care if we race, we
                // make real check under lock later
                if (target->CanRemoveDead())
                    remove.push_back(target->GetName());

            for (auto name : remove) {
                std::shared_ptr<TContainer> container;
                TError error = Get(name, container);
                if (error)
                    continue;

                TNestedScopedLock lock(*container, holder_lock, std::try_to_lock);
                if (!lock.IsLocked() ||
                    !container->IsValid() ||
                    !container->CanRemoveDead())
                    continue;

                TScopedAcquire acquire(container);
                if (!acquire.IsAcquired())
                    continue;

                L_ACT() << "Remove old dead " << name << std::endl;

                error = Destroy(holder_lock, container);
                if (error)
                    L_ERR() << "Can't destroy " << name << ": " << error << std::endl;
                else
                    Statistics->RemoveDead++;
            }
        }

        auto list = List();
        for (auto &target : list) {
            if (target->IsAcquired())
                continue;

            TNestedScopedLock lock(*target, holder_lock);
            if (target->IsValid() && !target->IsAcquired())
                target->DeliverEvent(holder_lock, event);
        }

        ScheduleLogRotatation();
        Statistics->Rotated++;
        delivered = true;
        break;
    }
    default:
        L_ERR() << "Unknown event " << event.GetMsg() << std::endl;
    }

    if (!delivered)
        L() << "Couldn't deliver " << event.GetMsg() << std::endl;

    return delivered;
}
예제 #11
0
파일: cgroup.cpp 프로젝트: noxiouz/porto
TError TCgroup::Set(const std::string &knob, const std::string &value) const {
    if (!Subsystem)
        return TError(EError::Unknown, "Cannot set to null cgroup");
    L_ACT() << "Set " << *this << " " << knob << " = " << value << std::endl;
    return Knob(knob).WriteAll(value);
}