aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/api.c
Commit message (Expand)AuthorAge
* crypto: api - Use formatting of module nameAlex Riesen2009-06-02
* crypto: api - Use kzfreeJohannes Weiner2009-06-02
* crypto: api - Fix algorithm module auto-loadingHerbert Xu2009-04-21
* Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6Linus Torvalds2009-03-26
|\
| * crypto: api - Fix crypto_alloc_tfm/create_create_tfm return conventionHerbert Xu2009-02-18
| * crypto: api - crypto_alg_mod_lookup either tested or untestedHerbert Xu2009-02-18
* | crypto: api - Fix module load deadlock with fallback algorithmsHerbert Xu2009-02-26
|/
* crypto: api - Fix zeroing on freeHerbert Xu2009-02-05
* crypto: api - Rebirth of crypto_alloc_tfmHerbert Xu2008-12-24
* crypto: api - Move type exit function into crypto_tfmHerbert Xu2008-12-24
* crypto: api - Use test infrastructureHerbert Xu2008-08-29
* crypto: api - Export crypto_alg_lookup instead of __crypto_alg_lookupHerbert Xu2008-08-29
* [CRYPTO] hash: Add asynchronous hash supportLoc Ho2008-07-10
* [CRYPTO] api: Make the crypto subsystem fully modularSebastian Siewior2008-04-20
* [CRYPTO] skcipher: Create default givcipher instancesHerbert Xu2008-01-10
* crypto: convert "crypto" subdirectory to UTF-8John Anthony Kazos Jr2007-10-19
* [CRYPTO] api: Wake up all waiters when larval completesHerbert Xu2007-07-11
* [CRYPTO] api: Read module pointer before freeing algorithmHerbert Xu2007-05-19
* [CRYPTO] api: Allow multiple frontends per backendHerbert Xu2007-02-06
* [CRYPTO] api: Remove deprecated interfaceHerbert Xu2007-02-06
* [CRYPTO] api: Remove unused functionsAdrian Bunk2006-12-06
* [CRYPTO] api: fix crypto_alloc_base() return valueAkinobu Mita2006-10-11
* [CRYPTO] api: Add crypto_comp and crypto_has_*Herbert Xu2006-09-20
* [CRYPTO] api: Added crypto_type supportHerbert Xu2006-09-20
* [CRYPTO] api: Added crypto_alloc_baseHerbert Xu2006-09-20
* [CRYPTO] api: Added asynchronous flagHerbert Xu2006-09-20
* [CRYPTO] api: Added spawnsHerbert Xu2006-09-20
* [CRYPTO] api: Allow algorithm lookup by typeHerbert Xu2006-09-20
* [CRYPTO] api: Add cryptomgrHerbert Xu2006-09-20
* [CRYPTO] api: Added event notificationHerbert Xu2006-09-20
* [CRYPTO] api: Split out low-level APIHerbert Xu2006-09-20
* [CRYPTO] api: Add crypto_alg reference countingHerbert Xu2006-09-20
* [CRYPTO] api: Rename crypto_alg_get to crypto_mod_getHerbert Xu2006-09-20
* [CRYPTO] api: Allow replacement when registering new algorithmsHerbert Xu2006-06-26
* [CRYPTO] api: Removed const from cra_name/cra_driver_nameHerbert Xu2006-06-26
* [CRYPTO] api: Added cra_init/cra_exitHerbert Xu2006-06-26
* [CRYPTO] all: Use kzalloc where possibleEric Sesterhenn2006-03-21
* [CRYPTO] api: Align tfm context as wide as possibleHerbert Xu2006-03-21
* [CRYPTO] api: Require block size to be less than PAGE_SIZE/8Herbert Xu2006-01-09
* [CRYPTO] Allow multiple implementations of the same algorithmHerbert Xu2006-01-09
* [CRYPTO] Check cra_alignmask against cra_blocksizeHerbert Xu2005-10-29
* [CRYPTO]: Added CRYPTO_TFM_REQ_MAY_SLEEP flagHerbert Xu2005-09-01
* [CRYPTO] Add null short circuit to crypto_free_tfmJesper Juhl2005-07-06
* [CRYPTO] Ensure cit_iv is aligned correctlyHerbert Xu2005-07-06
* [CRYPTO] Make crypto_alg_lookup staticAdrian Bunk2005-07-06
* [CRYPTO] Add alignmask for low-level cipher implementationsHerbert Xu2005-07-06
* Linux-2.6.12-rc2v2.6.12-rc2Linus Torvalds2005-04-16
iterator start) * sighand->siglock (fake signal delivery inside freeze_task()) * * freezer_write() (unfreeze): * cgroup_mutex * freezer->lock * write_lock css_set_lock (cgroup iterator start) * task->alloc_lock * read_lock css_set_lock (cgroup iterator start) * task->alloc_lock (inside __thaw_task(), prevents race with refrigerator()) * sighand->siglock */ static struct cgroup_subsys_state *freezer_create(struct cgroup *cgroup) { struct freezer *freezer; freezer = kzalloc(sizeof(struct freezer), GFP_KERNEL); if (!freezer) return ERR_PTR(-ENOMEM); spin_lock_init(&freezer->lock); freezer->state = CGROUP_THAWED; return &freezer->css; } static void freezer_destroy(struct cgroup *cgroup) { struct freezer *freezer = cgroup_freezer(cgroup); if (freezer->state != CGROUP_THAWED) atomic_dec(&system_freezing_cnt); kfree(freezer); } /* task is frozen or will freeze immediately when next it gets woken */ static bool is_task_frozen_enough(struct task_struct *task) { return frozen(task) || (task_is_stopped_or_traced(task) && freezing(task)); } /* * The call to cgroup_lock() in the freezer.state write method prevents * a write to that file racing against an attach, and hence the * can_attach() result will remain valid until the attach completes. */ static int freezer_can_attach(struct cgroup *new_cgroup, struct cgroup_taskset *tset) { struct freezer *freezer; struct task_struct *task; /* * Anything frozen can't move or be moved to/from. */ cgroup_taskset_for_each(task, new_cgroup, tset) if (cgroup_freezing(task)) return -EBUSY; freezer = cgroup_freezer(new_cgroup); if (freezer->state != CGROUP_THAWED) return -EBUSY; return 0; } static void freezer_fork(struct task_struct *task) { struct freezer *freezer; /* * No lock is needed, since the task isn't on tasklist yet, * so it can't be moved to another cgroup, which means the * freezer won't be removed and will be valid during this * function call. Nevertheless, apply RCU read-side critical * section to suppress RCU lockdep false positives. */ rcu_read_lock(); freezer = task_freezer(task); rcu_read_unlock(); /* * The root cgroup is non-freezable, so we can skip the * following check. */ if (!freezer->css.cgroup->parent) return; spin_lock_irq(&freezer->lock); BUG_ON(freezer->state == CGROUP_FROZEN); /* Locking avoids race with FREEZING -> THAWED transitions. */ if (freezer->state == CGROUP_FREEZING) freeze_task(task); spin_unlock_irq(&freezer->lock); } /* * caller must hold freezer->lock */ static void update_if_frozen(struct cgroup *cgroup, struct freezer *freezer) { struct cgroup_iter it; struct task_struct *task; unsigned int nfrozen = 0, ntotal = 0; enum freezer_state old_state = freezer->state; cgroup_iter_start(cgroup, &it); while ((task = cgroup_iter_next(cgroup, &it))) { ntotal++; if (freezing(task) && is_task_frozen_enough(task)) nfrozen++; } if (old_state == CGROUP_THAWED) { BUG_ON(nfrozen > 0); } else if (old_state == CGROUP_FREEZING) { if (nfrozen == ntotal) freezer->state = CGROUP_FROZEN; } else { /* old_state == CGROUP_FROZEN */ BUG_ON(nfrozen != ntotal); } cgroup_iter_end(cgroup, &it); } static int freezer_read(struct cgroup *cgroup, struct cftype *cft, struct seq_file *m) { struct freezer *freezer; enum freezer_state state; if (!cgroup_lock_live_group(cgroup)) return -ENODEV; freezer = cgroup_freezer(cgroup); spin_lock_irq(&freezer->lock); state = freezer->state; if (state == CGROUP_FREEZING) { /* We change from FREEZING to FROZEN lazily if the cgroup was * only partially frozen when we exitted write. */ update_if_frozen(cgroup, freezer); state = freezer->state; } spin_unlock_irq(&freezer->lock); cgroup_unlock(); seq_puts(m, freezer_state_strs[state]); seq_putc(m, '\n'); return 0; } static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) { struct cgroup_iter it; struct task_struct *task; unsigned int num_cant_freeze_now = 0; cgroup_iter_start(cgroup, &it); while ((task = cgroup_iter_next(cgroup, &it))) { if (!freeze_task(task)) continue; if (is_task_frozen_enough(task)) continue; if (!freezing(task) && !freezer_should_skip(task)) num_cant_freeze_now++; } cgroup_iter_end(cgroup, &it); return num_cant_freeze_now ? -EBUSY : 0; } static void unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer) { struct cgroup_iter it; struct task_struct *task; cgroup_iter_start(cgroup, &it); while ((task = cgroup_iter_next(cgroup, &it))) __thaw_task(task); cgroup_iter_end(cgroup, &it); } static int freezer_change_state(struct cgroup *cgroup, enum freezer_state goal_state) { struct freezer *freezer; int retval = 0; freezer = cgroup_freezer(cgroup); spin_lock_irq(&freezer->lock); update_if_frozen(cgroup, freezer); switch (goal_state) { case CGROUP_THAWED: if (freezer->state != CGROUP_THAWED) atomic_dec(&system_freezing_cnt); freezer->state = CGROUP_THAWED; unfreeze_cgroup(cgroup, freezer); break; case CGROUP_FROZEN: if (freezer->state == CGROUP_THAWED) atomic_inc(&system_freezing_cnt); freezer->state = CGROUP_FREEZING; retval = try_to_freeze_cgroup(cgroup, freezer); break; default: BUG(); } spin_unlock_irq(&freezer->lock); return retval; } static int freezer_write(struct cgroup *cgroup, struct cftype *cft, const char *buffer) { int retval; enum freezer_state goal_state; if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0) goal_state = CGROUP_THAWED; else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0) goal_state = CGROUP_FROZEN; else return -EINVAL; if (!cgroup_lock_live_group(cgroup)) return -ENODEV; retval = freezer_change_state(cgroup, goal_state); cgroup_unlock(); return retval; } static struct cftype files[] = { { .name = "state", .flags = CFTYPE_NOT_ON_ROOT, .read_seq_string = freezer_read, .write_string = freezer_write, }, { } /* terminate */ }; struct cgroup_subsys freezer_subsys = { .name = "freezer", .create = freezer_create, .destroy = freezer_destroy, .subsys_id = freezer_subsys_id, .can_attach = freezer_can_attach, .fork = freezer_fork, .base_cftypes = files, };