Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 23033
b: refs/heads/master
c: 6362e4d
h: refs/heads/master
i:
  23031: 6605702
v: v3
  • Loading branch information
Jan Kara authored and Linus Torvalds committed Mar 23, 2006
1 parent 1ef98a8 commit 25f6e14
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 804f1594cc3deb161e531a43d90c501f0db2635a
refs/heads/master: 6362e4d4eda61efb04ac1cdae32e48ac6d90b701
52 changes: 39 additions & 13 deletions trunk/fs/dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@
* spinlock to internal buffers before writing.
*
* Lock ordering (including related VFS locks) is the following:
* i_mutex > dqonoff_sem > iprune_sem > journal_lock > dqptr_sem >
* > dquot->dq_lock > dqio_sem
* i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > dqio_sem
* i_mutex on quota files is special (it's below dqio_sem)
*/

Expand Down Expand Up @@ -407,23 +406,49 @@ int dquot_release(struct dquot *dquot)

/* Invalidate all dquots on the list. Note that this function is called after
* quota is disabled and pointers from inodes removed so there cannot be new
* quota users. Also because we hold dqonoff_sem there can be no quota users
* for this sb+type at all. */
* quota users. There can still be some users of quotas due to inodes being
* just deleted or pruned by prune_icache() (those are not attached to any
* list). We have to wait for such users.
*/
static void invalidate_dquots(struct super_block *sb, int type)
{
struct dquot *dquot, *tmp;

restart:
spin_lock(&dq_list_lock);
list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
if (dquot->dq_sb != sb)
continue;
if (dquot->dq_type != type)
continue;
#ifdef __DQUOT_PARANOIA
if (atomic_read(&dquot->dq_count))
BUG();
#endif
/* Quota now has no users and it has been written on last dqput() */
/* Wait for dquot users */
if (atomic_read(&dquot->dq_count)) {
DEFINE_WAIT(wait);

atomic_inc(&dquot->dq_count);
prepare_to_wait(&dquot->dq_wait_unused, &wait,
TASK_UNINTERRUPTIBLE);
spin_unlock(&dq_list_lock);
/* Once dqput() wakes us up, we know it's time to free
* the dquot.
* IMPORTANT: we rely on the fact that there is always
* at most one process waiting for dquot to free.
* Otherwise dq_count would be > 1 and we would never
* wake up.
*/
if (atomic_read(&dquot->dq_count) > 1)
schedule();
finish_wait(&dquot->dq_wait_unused, &wait);
dqput(dquot);
/* At this moment dquot() need not exist (it could be
* reclaimed by prune_dqcache(). Hence we must
* restart. */
goto restart;
}
/*
* Quota now has no users and it has been written on last
* dqput()
*/
remove_dquot_hash(dquot);
remove_free_dquot(dquot);
remove_inuse(dquot);
Expand Down Expand Up @@ -540,6 +565,10 @@ static void dqput(struct dquot *dquot)
if (atomic_read(&dquot->dq_count) > 1) {
/* We have more than one user... nothing to do */
atomic_dec(&dquot->dq_count);
/* Releasing dquot during quotaoff phase? */
if (!sb_has_quota_enabled(dquot->dq_sb, dquot->dq_type) &&
atomic_read(&dquot->dq_count) == 1)
wake_up(&dquot->dq_wait_unused);
spin_unlock(&dq_list_lock);
return;
}
Expand Down Expand Up @@ -581,6 +610,7 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
INIT_LIST_HEAD(&dquot->dq_inuse);
INIT_HLIST_NODE(&dquot->dq_hash);
INIT_LIST_HEAD(&dquot->dq_dirty);
init_waitqueue_head(&dquot->dq_wait_unused);
dquot->dq_sb = sb;
dquot->dq_type = type;
atomic_set(&dquot->dq_count, 1);
Expand Down Expand Up @@ -732,13 +762,9 @@ static void drop_dquot_ref(struct super_block *sb, int type)
{
LIST_HEAD(tofree_head);

/* We need to be guarded against prune_icache to reach all the
* inodes - otherwise some can be on the local list of prune_icache */
down(&iprune_sem);
down_write(&sb_dqopt(sb)->dqptr_sem);
remove_dquot_ref(sb, type, &tofree_head);
up_write(&sb_dqopt(sb)->dqptr_sem);
up(&iprune_sem);
put_dquot_list(&tofree_head);
}

Expand Down

0 comments on commit 25f6e14

Please sign in to comment.