summaryrefslogtreecommitdiffstats
path: root/kernel/nsproxy.c
Commit message (Expand)AuthorAgeFilesLines
* pidns: Capture the user namespace and filter ns_last_pidEric W. Biederman2012-11-191-1/+1
* userns: make each net (net_ns) belong to a user_nsEric W. Biederman2012-11-191-1/+1
* kernel: Map most files to use export.h instead of module.hPaul Gortmaker2011-10-311-1/+1
* make sure that nsproxy_cache is initialized early enoughAl Viro2011-07-201-3/+1Star
* cgroup: remove the ns_cgroupDaniel Lezcano2011-05-271-4/+0Star
* ns: Introduce the setns syscallEric W. Biederman2011-05-101-0/+42
* userns: user namespaces: convert several capable() callsSerge E. Hallyn2011-03-241-6/+1Star
* userns: add a user namespace owner of ipc nsSerge E. Hallyn2011-03-241-0/+5
* userns: allow sethostname in a containerSerge E. Hallyn2011-03-241-6/+1Star
* userns: add a user_namespace as creator/owner of uts_namespaceSerge E. Hallyn2011-03-241-0/+5
* include cleanup: Update gfp.h and slab.h includes to prepare for breaking imp...Tejun Heo2010-03-301-0/+1
* nsproxy: remove INIT_NSPROXY()Alexey Dobriyan2010-03-131-1/+12
* nsproxy: extract create_nsproxy()Alexey Dobriyan2009-06-181-12/+7Star
* User namespaces: set of cleanups (v2)Serge Hallyn2008-11-251-13/+2Star
* removed unused #include <linux/version.h>'sAdrian Bunk2008-08-231-1/+0Star
* cgroup_clone: use pid of newly created task for new cgroupSerge E. Hallyn2008-07-251-7/+1Star
* ipc: sysvsem: refuse clone(CLONE_SYSVSEM|CLONE_NEWIPC)Serge E. Hallyn2008-04-291-0/+12
* namespaces: move the IPC namespace under IPC_NS optionPavel Emelyanov2008-02-081-0/+1
* pid namespaces: allow cloning of new namespacePavel Emelyanov2007-10-191-1/+2
* Make access to task's nsproxy lighterPavel Emelyanov2007-10-191-13/+27
* pid namespaces: define and use task_active_pid_ns() wrapperSukadev Bhattiprolu2007-10-191-1/+1
* cgroups: implement namespace tracking subsystemSerge E. Hallyn2007-10-191-1/+16
* Use KMEM_CACHE macro to create the nsproxy cachePavel Emelyanov2007-10-171-2/+1Star
* [NET]: Add network namespace clone & unshare support.Eric W. Biederman2007-10-111-2/+13
* mm: Remove slab destructors from kmem_cache_create().Paul Mundt2007-07-201-1/+1
* namespace: ensure clone_flags are always stored in an unsigned longEric W. Biederman2007-07-161-3/+3
* add a kmem_cache for nsproxy objectsCedric Le Goater2007-07-161-4/+17
* fix create_new_namespaces() return valueCedric Le Goater2007-07-161-6/+17
* user namespace: add unshareSerge E. Hallyn2007-07-161-2/+3
* user namespace: add the frameworkCedric Le Goater2007-07-161-0/+9
* remove CONFIG_UTS_NS and CONFIG_IPC_NSCedric Le Goater2007-07-161-10/+0Star
* fix refcounting of nsproxy object when unsharedCedric Le Goater2007-06-241-8/+2Star
* Merge sys_clone()/sys_unshare() nsproxy and namespace handlingBadari Pulavarty2007-05-081-53/+86
* Revert "[PATCH] namespaces: fix exit race by splitting exit"Linus Torvalds2007-01-301-15/+1Star
* [PATCH] namespaces: fix exit race by splitting exitSerge E. Hallyn2007-01-301-1/+15
* [PATCH] Revert "[PATCH] identifier to nsproxy"Eric W. Biederman2006-12-131-3/+1Star
* [PATCH] to nsproxyCedric Le Goater2006-12-081-7/+19
* [PATCH] identifier to nsproxyCedric Le Goater2006-12-081-1/+3
* [PATCH] rename struct namespace to struct mnt_namespaceKirill Korotaev2006-12-081-8/+8
* [PATCH] kernel/nsproxy.c: use kmemdup()Alexey Dobriyan2006-10-201-4/+2Star
* [PATCH] nsproxy cloning error path fixPavel2006-10-021-1/+1
* [PATCH] IPC namespace coreKirill Korotaev2006-10-021-13/+28
* [PATCH] namespaces: utsname: implement CLONE_NEWUTS flagSerge E. Hallyn2006-10-021-1/+1
* [PATCH] namespaces: utsname: implement utsname namespacesSerge E. Hallyn2006-10-021-0/+14
* [PATCH] namespaces: incorporate fs namespace into nsproxySerge E. Hallyn2006-10-021-1/+31
* [PATCH] nsproxy: move init_nsproxy into kernel/nsproxy.cSerge E. Hallyn2006-10-021-0/+3
* [PATCH] namespaces: add nsproxySerge E. Hallyn2006-10-021-0/+77
span>notify_prev->notify_next = mp; } else { pvr2_context_notify_first = mp; } mp->notify_flag = !0; } } else { if (mp->notify_flag) { mp->notify_flag = 0; if (mp->notify_next) { mp->notify_next->notify_prev = mp->notify_prev; } else { pvr2_context_notify_last = mp->notify_prev; } if (mp->notify_prev) { mp->notify_prev->notify_next = mp->notify_next; } else { pvr2_context_notify_first = mp->notify_next; } } } mutex_unlock(&pvr2_context_mutex); if (signal_flag) wake_up(&pvr2_context_sync_data); } static void pvr2_context_destroy(struct pvr2_context *mp) { pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp); pvr2_hdw_destroy(mp->hdw); pvr2_context_set_notify(mp, 0); mutex_lock(&pvr2_context_mutex); if (mp->exist_next) { mp->exist_next->exist_prev = mp->exist_prev; } else { pvr2_context_exist_last = mp->exist_prev; } if (mp->exist_prev) { mp->exist_prev->exist_next = mp->exist_next; } else { pvr2_context_exist_first = mp->exist_next; } if (!pvr2_context_exist_first) { /* Trigger wakeup on control thread in case it is waiting for an exit condition. */ wake_up(&pvr2_context_sync_data); } mutex_unlock(&pvr2_context_mutex); kfree(mp); } static void pvr2_context_notify(struct pvr2_context *mp) { pvr2_context_set_notify(mp,!0); } static void pvr2_context_check(struct pvr2_context *mp) { struct pvr2_channel *ch1, *ch2; pvr2_trace(PVR2_TRACE_CTXT, "pvr2_context %p (notify)", mp); if (!mp->initialized_flag && !mp->disconnect_flag) { mp->initialized_flag = !0; pvr2_trace(PVR2_TRACE_CTXT, "pvr2_context %p (initialize)", mp); /* Finish hardware initialization */ if (pvr2_hdw_initialize(mp->hdw, (void (*)(void *))pvr2_context_notify, mp)) { mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw); /* Trigger interface initialization. By doing this here initialization runs in our own safe and cozy thread context. */ if (mp->setup_func) mp->setup_func(mp); } else { pvr2_trace(PVR2_TRACE_CTXT, "pvr2_context %p (thread skipping setup)", mp); /* Even though initialization did not succeed, we're still going to continue anyway. We need to do this in order to await the expected disconnect (which we will detect in the normal course of operation). */ } } for (ch1 = mp->mc_first; ch1; ch1 = ch2) { ch2 = ch1->mc_next; if (ch1->check_func) ch1->check_func(ch1); } if (mp->disconnect_flag && !mp->mc_first) { /* Go away... */ pvr2_context_destroy(mp); return; } } static int pvr2_context_shutok(void) { return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL); } static int pvr2_context_thread_func(void *foo) { struct pvr2_context *mp; pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start"); do { while ((mp = pvr2_context_notify_first) != NULL) { pvr2_context_set_notify(mp, 0); pvr2_context_check(mp); } wait_event_interruptible( pvr2_context_sync_data, ((pvr2_context_notify_first != NULL) || pvr2_context_shutok())); } while (!pvr2_context_shutok()); pvr2_context_cleaned_flag = !0; wake_up(&pvr2_context_cleanup_data); pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up"); wait_event_interruptible( pvr2_context_sync_data, kthread_should_stop()); pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end"); return 0; } int pvr2_context_global_init(void) { pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func, NULL, "pvrusb2-context"); return IS_ERR(pvr2_context_thread_ptr) ? -ENOMEM : 0; } void pvr2_context_global_done(void) { pvr2_context_cleanup_flag = !0; wake_up(&pvr2_context_sync_data); wait_event_interruptible( pvr2_context_cleanup_data, pvr2_context_cleaned_flag); kthread_stop(pvr2_context_thread_ptr); } struct pvr2_context *pvr2_context_create( struct usb_interface *intf, const struct usb_device_id *devid, void (*setup_func)(struct pvr2_context *)) { struct pvr2_context *mp = NULL; mp = kzalloc(sizeof(*mp),GFP_KERNEL); if (!mp) goto done; pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp); mp->setup_func = setup_func; mutex_init(&mp->mutex); mutex_lock(&pvr2_context_mutex); mp->exist_prev = pvr2_context_exist_last; mp->exist_next = NULL; pvr2_context_exist_last = mp; if (mp->exist_prev) { mp->exist_prev->exist_next = mp; } else { pvr2_context_exist_first = mp; } mutex_unlock(&pvr2_context_mutex); mp->hdw = pvr2_hdw_create(intf,devid); if (!mp->hdw) { pvr2_context_destroy(mp); mp = NULL; goto done; } pvr2_context_set_notify(mp, !0); done: return mp; } static void pvr2_context_reset_input_limits(struct pvr2_context *mp) { unsigned int tmsk,mmsk; struct pvr2_channel *cp; struct pvr2_hdw *hdw = mp->hdw; mmsk = pvr2_hdw_get_input_available(hdw); tmsk = mmsk; for (cp = mp->mc_first; cp; cp = cp->mc_next) { if (!cp->input_mask) continue; tmsk &= cp->input_mask; } pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk); pvr2_hdw_commit_ctl(hdw); } static void pvr2_context_enter(struct pvr2_context *mp) { mutex_lock(&mp->mutex); } static void pvr2_context_exit(struct pvr2_context *mp) { int destroy_flag = 0; if (!(mp->mc_first || !mp->disconnect_flag)) { destroy_flag = !0; } mutex_unlock(&mp->mutex); if (destroy_flag) pvr2_context_notify(mp); } void pvr2_context_disconnect(struct pvr2_context *mp) { pvr2_hdw_disconnect(mp->hdw); mp->disconnect_flag = !0; pvr2_context_notify(mp); } void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp) { pvr2_context_enter(mp); cp->hdw = mp->hdw; cp->mc_head = mp; cp->mc_next = NULL; cp->mc_prev = mp->mc_last; if (mp->mc_last) { mp->mc_last->mc_next = cp; } else { mp->mc_first = cp; } mp->mc_last = cp; pvr2_context_exit(mp); } static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp) { if (!cp->stream) return; pvr2_stream_kill(cp->stream->stream); cp->stream->user = NULL; cp->stream = NULL; } void pvr2_channel_done(struct pvr2_channel *cp) { struct pvr2_context *mp = cp->mc_head; pvr2_context_enter(mp); cp->input_mask = 0; pvr2_channel_disclaim_stream(cp); pvr2_context_reset_input_limits(mp); if (cp->mc_next) { cp->mc_next->mc_prev = cp->mc_prev; } else { mp->mc_last = cp->mc_prev; } if (cp->mc_prev) { cp->mc_prev->mc_next = cp->mc_next; } else { mp->mc_first = cp->mc_next; } cp->hdw = NULL; pvr2_context_exit(mp); } int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk) { unsigned int tmsk,mmsk; int ret = 0; struct pvr2_channel *p2; struct pvr2_hdw *hdw = cp->hdw; mmsk = pvr2_hdw_get_input_available(hdw); cmsk &= mmsk; if (cmsk == cp->input_mask) { /* No change; nothing to do */ return 0; } pvr2_context_enter(cp->mc_head); do { if (!cmsk) { cp->input_mask = 0; pvr2_context_reset_input_limits(cp->mc_head); break; } tmsk = mmsk; for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) { if (p2 == cp) continue; if (!p2->input_mask) continue; tmsk &= p2->input_mask; } if (!(tmsk & cmsk)) { ret = -EPERM; break; } tmsk &= cmsk; if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) { /* Internal failure changing allowed list; probably should not happen, but react if it does. */ break; } cp->input_mask = cmsk; pvr2_hdw_commit_ctl(hdw); } while (0); pvr2_context_exit(cp->mc_head); return ret; } unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp) { return cp->input_mask; } int pvr2_channel_claim_stream(struct pvr2_channel *cp, struct pvr2_context_stream *sp) { int code = 0; pvr2_context_enter(cp->mc_head); do { if (sp == cp->stream) break; if (sp && sp->user) { code = -EBUSY; break; } pvr2_channel_disclaim_stream(cp); if (!sp) break; sp->user = cp; cp->stream = sp; } while (0); pvr2_context_exit(cp->mc_head); return code; } // This is the marker for the real beginning of a legitimate mpeg2 stream. static char stream_sync_key[] = { 0x00, 0x00, 0x01, 0xba, }; struct pvr2_ioread *pvr2_channel_create_mpeg_stream( struct pvr2_context_stream *sp) { struct pvr2_ioread *cp; cp = pvr2_ioread_create(); if (!cp) return NULL; pvr2_ioread_setup(cp,sp->stream); pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key)); return cp; }