diff options
-rw-r--r-- | fs/ext2/inode.c | 4 | ||||
-rw-r--r-- | fs/notify/inode_mark.c | 45 | ||||
-rw-r--r-- | fs/ocfs2/quota_global.c | 10 | ||||
-rw-r--r-- | fs/ocfs2/quota_local.c | 11 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 1 | ||||
-rw-r--r-- | fs/quota/dquot.c | 136 | ||||
-rw-r--r-- | fs/quota/quota.c | 22 | ||||
-rw-r--r-- | fs/super.c | 81 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | include/linux/quota.h | 1 |
10 files changed, 152 insertions, 161 deletions
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index e173afe92661..0093ea2512a8 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -1478,6 +1478,10 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | |||
1478 | inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; | 1478 | inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; |
1479 | else | 1479 | else |
1480 | ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); | 1480 | ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); |
1481 | if (i_size_read(inode) < 0) { | ||
1482 | ret = -EFSCORRUPTED; | ||
1483 | goto bad_inode; | ||
1484 | } | ||
1481 | ei->i_dtime = 0; | 1485 | ei->i_dtime = 0; |
1482 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); | 1486 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); |
1483 | ei->i_state = 0; | 1487 | ei->i_state = 0; |
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 741077deef3b..a3645249f7ec 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c | |||
@@ -150,12 +150,10 @@ int fsnotify_add_inode_mark(struct fsnotify_mark *mark, | |||
150 | */ | 150 | */ |
151 | void fsnotify_unmount_inodes(struct super_block *sb) | 151 | void fsnotify_unmount_inodes(struct super_block *sb) |
152 | { | 152 | { |
153 | struct inode *inode, *next_i, *need_iput = NULL; | 153 | struct inode *inode, *iput_inode = NULL; |
154 | 154 | ||
155 | spin_lock(&sb->s_inode_list_lock); | 155 | spin_lock(&sb->s_inode_list_lock); |
156 | list_for_each_entry_safe(inode, next_i, &sb->s_inodes, i_sb_list) { | 156 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { |
157 | struct inode *need_iput_tmp; | ||
158 | |||
159 | /* | 157 | /* |
160 | * We cannot __iget() an inode in state I_FREEING, | 158 | * We cannot __iget() an inode in state I_FREEING, |
161 | * I_WILL_FREE, or I_NEW which is fine because by that point | 159 | * I_WILL_FREE, or I_NEW which is fine because by that point |
@@ -178,49 +176,24 @@ void fsnotify_unmount_inodes(struct super_block *sb) | |||
178 | continue; | 176 | continue; |
179 | } | 177 | } |
180 | 178 | ||
181 | need_iput_tmp = need_iput; | 179 | __iget(inode); |
182 | need_iput = NULL; | ||
183 | |||
184 | /* In case fsnotify_inode_delete() drops a reference. */ | ||
185 | if (inode != need_iput_tmp) | ||
186 | __iget(inode); | ||
187 | else | ||
188 | need_iput_tmp = NULL; | ||
189 | spin_unlock(&inode->i_lock); | 180 | spin_unlock(&inode->i_lock); |
190 | |||
191 | /* In case the dropping of a reference would nuke next_i. */ | ||
192 | while (&next_i->i_sb_list != &sb->s_inodes) { | ||
193 | spin_lock(&next_i->i_lock); | ||
194 | if (!(next_i->i_state & (I_FREEING | I_WILL_FREE)) && | ||
195 | atomic_read(&next_i->i_count)) { | ||
196 | __iget(next_i); | ||
197 | need_iput = next_i; | ||
198 | spin_unlock(&next_i->i_lock); | ||
199 | break; | ||
200 | } | ||
201 | spin_unlock(&next_i->i_lock); | ||
202 | next_i = list_next_entry(next_i, i_sb_list); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * We can safely drop s_inode_list_lock here because either | ||
207 | * we actually hold references on both inode and next_i or | ||
208 | * end of list. Also no new inodes will be added since the | ||
209 | * umount has begun. | ||
210 | */ | ||
211 | spin_unlock(&sb->s_inode_list_lock); | 181 | spin_unlock(&sb->s_inode_list_lock); |
212 | 182 | ||
213 | if (need_iput_tmp) | 183 | if (iput_inode) |
214 | iput(need_iput_tmp); | 184 | iput(iput_inode); |
215 | 185 | ||
216 | /* for each watch, send FS_UNMOUNT and then remove it */ | 186 | /* for each watch, send FS_UNMOUNT and then remove it */ |
217 | fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 187 | fsnotify(inode, FS_UNMOUNT, inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
218 | 188 | ||
219 | fsnotify_inode_delete(inode); | 189 | fsnotify_inode_delete(inode); |
220 | 190 | ||
221 | iput(inode); | 191 | iput_inode = inode; |
222 | 192 | ||
223 | spin_lock(&sb->s_inode_list_lock); | 193 | spin_lock(&sb->s_inode_list_lock); |
224 | } | 194 | } |
225 | spin_unlock(&sb->s_inode_list_lock); | 195 | spin_unlock(&sb->s_inode_list_lock); |
196 | |||
197 | if (iput_inode) | ||
198 | iput(iput_inode); | ||
226 | } | 199 | } |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 87e577a49b0d..cec495a921e3 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
@@ -634,7 +634,15 @@ static void qsync_work_fn(struct work_struct *work) | |||
634 | dqi_sync_work.work); | 634 | dqi_sync_work.work); |
635 | struct super_block *sb = oinfo->dqi_gqinode->i_sb; | 635 | struct super_block *sb = oinfo->dqi_gqinode->i_sb; |
636 | 636 | ||
637 | dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type); | 637 | /* |
638 | * We have to be careful here not to deadlock on s_umount as umount | ||
639 | * disabling quotas may be in progress and it waits for this work to | ||
640 | * complete. If trylock fails, we'll do the sync next time... | ||
641 | */ | ||
642 | if (down_read_trylock(&sb->s_umount)) { | ||
643 | dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type); | ||
644 | up_read(&sb->s_umount); | ||
645 | } | ||
638 | schedule_delayed_work(&oinfo->dqi_sync_work, | 646 | schedule_delayed_work(&oinfo->dqi_sync_work, |
639 | msecs_to_jiffies(oinfo->dqi_syncms)); | 647 | msecs_to_jiffies(oinfo->dqi_syncms)); |
640 | } | 648 | } |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 8a54fd8a4fa5..32c5a40c1257 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
@@ -454,7 +454,7 @@ out: | |||
454 | /* Sync changes in local quota file into global quota file and | 454 | /* Sync changes in local quota file into global quota file and |
455 | * reinitialize local quota file. | 455 | * reinitialize local quota file. |
456 | * The function expects local quota file to be already locked and | 456 | * The function expects local quota file to be already locked and |
457 | * dqonoff_mutex locked. */ | 457 | * s_umount locked in shared mode. */ |
458 | static int ocfs2_recover_local_quota_file(struct inode *lqinode, | 458 | static int ocfs2_recover_local_quota_file(struct inode *lqinode, |
459 | int type, | 459 | int type, |
460 | struct ocfs2_quota_recovery *rec) | 460 | struct ocfs2_quota_recovery *rec) |
@@ -597,7 +597,7 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, | |||
597 | printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for " | 597 | printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for " |
598 | "slot %u\n", osb->dev_str, slot_num); | 598 | "slot %u\n", osb->dev_str, slot_num); |
599 | 599 | ||
600 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 600 | down_read(&sb->s_umount); |
601 | for (type = 0; type < OCFS2_MAXQUOTAS; type++) { | 601 | for (type = 0; type < OCFS2_MAXQUOTAS; type++) { |
602 | if (list_empty(&(rec->r_list[type]))) | 602 | if (list_empty(&(rec->r_list[type]))) |
603 | continue; | 603 | continue; |
@@ -674,7 +674,7 @@ out_put: | |||
674 | break; | 674 | break; |
675 | } | 675 | } |
676 | out: | 676 | out: |
677 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | 677 | up_read(&sb->s_umount); |
678 | kfree(rec); | 678 | kfree(rec); |
679 | return status; | 679 | return status; |
680 | } | 680 | } |
@@ -840,7 +840,10 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) | |||
840 | } | 840 | } |
841 | ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); | 841 | ocfs2_release_local_quota_bitmaps(&oinfo->dqi_chunk); |
842 | 842 | ||
843 | /* dqonoff_mutex protects us against racing with recovery thread... */ | 843 | /* |
844 | * s_umount held in exclusive mode protects us against racing with | ||
845 | * recovery thread... | ||
846 | */ | ||
844 | if (oinfo->dqi_rec) { | 847 | if (oinfo->dqi_rec) { |
845 | ocfs2_free_quota_recovery(oinfo->dqi_rec); | 848 | ocfs2_free_quota_recovery(oinfo->dqi_rec); |
846 | mark_clean = 0; | 849 | mark_clean = 0; |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index c894d945b084..a24e42f95341 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -985,7 +985,6 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb) | |||
985 | for (type = 0; type < OCFS2_MAXQUOTAS; type++) { | 985 | for (type = 0; type < OCFS2_MAXQUOTAS; type++) { |
986 | if (!sb_has_quota_loaded(sb, type)) | 986 | if (!sb_has_quota_loaded(sb, type)) |
987 | continue; | 987 | continue; |
988 | /* Cancel periodic syncing before we grab dqonoff_mutex */ | ||
989 | oinfo = sb_dqinfo(sb, type)->dqi_priv; | 988 | oinfo = sb_dqinfo(sb, type)->dqi_priv; |
990 | cancel_delayed_work_sync(&oinfo->dqi_sync_work); | 989 | cancel_delayed_work_sync(&oinfo->dqi_sync_work); |
991 | inode = igrab(sb->s_dquot.files[type]); | 990 | inode = igrab(sb->s_dquot.files[type]); |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 8738a0d62c09..406fed92362a 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -119,8 +119,7 @@ | |||
119 | * spinlock to internal buffers before writing. | 119 | * spinlock to internal buffers before writing. |
120 | * | 120 | * |
121 | * Lock ordering (including related VFS locks) is the following: | 121 | * Lock ordering (including related VFS locks) is the following: |
122 | * dqonoff_mutex > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex | 122 | * s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex |
123 | * dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc. | ||
124 | */ | 123 | */ |
125 | 124 | ||
126 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); | 125 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); |
@@ -572,7 +571,8 @@ int dquot_scan_active(struct super_block *sb, | |||
572 | struct dquot *dquot, *old_dquot = NULL; | 571 | struct dquot *dquot, *old_dquot = NULL; |
573 | int ret = 0; | 572 | int ret = 0; |
574 | 573 | ||
575 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 574 | WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount)); |
575 | |||
576 | spin_lock(&dq_list_lock); | 576 | spin_lock(&dq_list_lock); |
577 | list_for_each_entry(dquot, &inuse_list, dq_inuse) { | 577 | list_for_each_entry(dquot, &inuse_list, dq_inuse) { |
578 | if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) | 578 | if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) |
@@ -603,7 +603,6 @@ int dquot_scan_active(struct super_block *sb, | |||
603 | spin_unlock(&dq_list_lock); | 603 | spin_unlock(&dq_list_lock); |
604 | out: | 604 | out: |
605 | dqput(old_dquot); | 605 | dqput(old_dquot); |
606 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | ||
607 | return ret; | 606 | return ret; |
608 | } | 607 | } |
609 | EXPORT_SYMBOL(dquot_scan_active); | 608 | EXPORT_SYMBOL(dquot_scan_active); |
@@ -617,7 +616,8 @@ int dquot_writeback_dquots(struct super_block *sb, int type) | |||
617 | int cnt; | 616 | int cnt; |
618 | int err, ret = 0; | 617 | int err, ret = 0; |
619 | 618 | ||
620 | mutex_lock(&dqopt->dqonoff_mutex); | 619 | WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount)); |
620 | |||
621 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 621 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
622 | if (type != -1 && cnt != type) | 622 | if (type != -1 && cnt != type) |
623 | continue; | 623 | continue; |
@@ -653,7 +653,6 @@ int dquot_writeback_dquots(struct super_block *sb, int type) | |||
653 | && info_dirty(&dqopt->info[cnt])) | 653 | && info_dirty(&dqopt->info[cnt])) |
654 | sb->dq_op->write_info(sb, cnt); | 654 | sb->dq_op->write_info(sb, cnt); |
655 | dqstats_inc(DQST_SYNCS); | 655 | dqstats_inc(DQST_SYNCS); |
656 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
657 | 656 | ||
658 | return ret; | 657 | return ret; |
659 | } | 658 | } |
@@ -683,7 +682,6 @@ int dquot_quota_sync(struct super_block *sb, int type) | |||
683 | * Now when everything is written we can discard the pagecache so | 682 | * Now when everything is written we can discard the pagecache so |
684 | * that userspace sees the changes. | 683 | * that userspace sees the changes. |
685 | */ | 684 | */ |
686 | mutex_lock(&dqopt->dqonoff_mutex); | ||
687 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 685 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
688 | if (type != -1 && cnt != type) | 686 | if (type != -1 && cnt != type) |
689 | continue; | 687 | continue; |
@@ -693,7 +691,6 @@ int dquot_quota_sync(struct super_block *sb, int type) | |||
693 | truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); | 691 | truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); |
694 | inode_unlock(dqopt->files[cnt]); | 692 | inode_unlock(dqopt->files[cnt]); |
695 | } | 693 | } |
696 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
697 | 694 | ||
698 | return 0; | 695 | return 0; |
699 | } | 696 | } |
@@ -935,7 +932,7 @@ static int dqinit_needed(struct inode *inode, int type) | |||
935 | return 0; | 932 | return 0; |
936 | } | 933 | } |
937 | 934 | ||
938 | /* This routine is guarded by dqonoff_mutex mutex */ | 935 | /* This routine is guarded by s_umount semaphore */ |
939 | static void add_dquot_ref(struct super_block *sb, int type) | 936 | static void add_dquot_ref(struct super_block *sb, int type) |
940 | { | 937 | { |
941 | struct inode *inode, *old_inode = NULL; | 938 | struct inode *inode, *old_inode = NULL; |
@@ -2050,21 +2047,13 @@ int dquot_get_next_id(struct super_block *sb, struct kqid *qid) | |||
2050 | struct quota_info *dqopt = sb_dqopt(sb); | 2047 | struct quota_info *dqopt = sb_dqopt(sb); |
2051 | int err; | 2048 | int err; |
2052 | 2049 | ||
2053 | mutex_lock(&dqopt->dqonoff_mutex); | 2050 | if (!sb_has_quota_active(sb, qid->type)) |
2054 | if (!sb_has_quota_active(sb, qid->type)) { | 2051 | return -ESRCH; |
2055 | err = -ESRCH; | 2052 | if (!dqopt->ops[qid->type]->get_next_id) |
2056 | goto out; | 2053 | return -ENOSYS; |
2057 | } | ||
2058 | if (!dqopt->ops[qid->type]->get_next_id) { | ||
2059 | err = -ENOSYS; | ||
2060 | goto out; | ||
2061 | } | ||
2062 | mutex_lock(&dqopt->dqio_mutex); | 2054 | mutex_lock(&dqopt->dqio_mutex); |
2063 | err = dqopt->ops[qid->type]->get_next_id(sb, qid); | 2055 | err = dqopt->ops[qid->type]->get_next_id(sb, qid); |
2064 | mutex_unlock(&dqopt->dqio_mutex); | 2056 | mutex_unlock(&dqopt->dqio_mutex); |
2065 | out: | ||
2066 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2067 | |||
2068 | return err; | 2057 | return err; |
2069 | } | 2058 | } |
2070 | EXPORT_SYMBOL(dquot_get_next_id); | 2059 | EXPORT_SYMBOL(dquot_get_next_id); |
@@ -2107,6 +2096,10 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2107 | struct quota_info *dqopt = sb_dqopt(sb); | 2096 | struct quota_info *dqopt = sb_dqopt(sb); |
2108 | struct inode *toputinode[MAXQUOTAS]; | 2097 | struct inode *toputinode[MAXQUOTAS]; |
2109 | 2098 | ||
2099 | /* s_umount should be held in exclusive mode */ | ||
2100 | if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount))) | ||
2101 | up_read(&sb->s_umount); | ||
2102 | |||
2110 | /* Cannot turn off usage accounting without turning off limits, or | 2103 | /* Cannot turn off usage accounting without turning off limits, or |
2111 | * suspend quotas and simultaneously turn quotas off. */ | 2104 | * suspend quotas and simultaneously turn quotas off. */ |
2112 | if ((flags & DQUOT_USAGE_ENABLED && !(flags & DQUOT_LIMITS_ENABLED)) | 2105 | if ((flags & DQUOT_USAGE_ENABLED && !(flags & DQUOT_LIMITS_ENABLED)) |
@@ -2114,18 +2107,14 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2114 | DQUOT_USAGE_ENABLED))) | 2107 | DQUOT_USAGE_ENABLED))) |
2115 | return -EINVAL; | 2108 | return -EINVAL; |
2116 | 2109 | ||
2117 | /* We need to serialize quota_off() for device */ | ||
2118 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2119 | |||
2120 | /* | 2110 | /* |
2121 | * Skip everything if there's nothing to do. We have to do this because | 2111 | * Skip everything if there's nothing to do. We have to do this because |
2122 | * sometimes we are called when fill_super() failed and calling | 2112 | * sometimes we are called when fill_super() failed and calling |
2123 | * sync_fs() in such cases does no good. | 2113 | * sync_fs() in such cases does no good. |
2124 | */ | 2114 | */ |
2125 | if (!sb_any_quota_loaded(sb)) { | 2115 | if (!sb_any_quota_loaded(sb)) |
2126 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2127 | return 0; | 2116 | return 0; |
2128 | } | 2117 | |
2129 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 2118 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
2130 | toputinode[cnt] = NULL; | 2119 | toputinode[cnt] = NULL; |
2131 | if (type != -1 && cnt != type) | 2120 | if (type != -1 && cnt != type) |
@@ -2179,7 +2168,6 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2179 | dqopt->info[cnt].dqi_bgrace = 0; | 2168 | dqopt->info[cnt].dqi_bgrace = 0; |
2180 | dqopt->ops[cnt] = NULL; | 2169 | dqopt->ops[cnt] = NULL; |
2181 | } | 2170 | } |
2182 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2183 | 2171 | ||
2184 | /* Skip syncing and setting flags if quota files are hidden */ | 2172 | /* Skip syncing and setting flags if quota files are hidden */ |
2185 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) | 2173 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) |
@@ -2196,20 +2184,14 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2196 | * must also discard the blockdev buffers so that we see the | 2184 | * must also discard the blockdev buffers so that we see the |
2197 | * changes done by userspace on the next quotaon() */ | 2185 | * changes done by userspace on the next quotaon() */ |
2198 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 2186 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
2199 | if (toputinode[cnt]) { | 2187 | /* This can happen when suspending quotas on remount-ro... */ |
2200 | mutex_lock(&dqopt->dqonoff_mutex); | 2188 | if (toputinode[cnt] && !sb_has_quota_loaded(sb, cnt)) { |
2201 | /* If quota was reenabled in the meantime, we have | 2189 | inode_lock(toputinode[cnt]); |
2202 | * nothing to do */ | 2190 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | |
2203 | if (!sb_has_quota_loaded(sb, cnt)) { | ||
2204 | inode_lock(toputinode[cnt]); | ||
2205 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | | ||
2206 | S_NOATIME | S_NOQUOTA); | 2191 | S_NOATIME | S_NOQUOTA); |
2207 | truncate_inode_pages(&toputinode[cnt]->i_data, | 2192 | truncate_inode_pages(&toputinode[cnt]->i_data, 0); |
2208 | 0); | 2193 | inode_unlock(toputinode[cnt]); |
2209 | inode_unlock(toputinode[cnt]); | 2194 | mark_inode_dirty_sync(toputinode[cnt]); |
2210 | mark_inode_dirty_sync(toputinode[cnt]); | ||
2211 | } | ||
2212 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2213 | } | 2195 | } |
2214 | if (sb->s_bdev) | 2196 | if (sb->s_bdev) |
2215 | invalidate_bdev(sb->s_bdev); | 2197 | invalidate_bdev(sb->s_bdev); |
@@ -2281,6 +2263,10 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2281 | error = -EINVAL; | 2263 | error = -EINVAL; |
2282 | goto out_fmt; | 2264 | goto out_fmt; |
2283 | } | 2265 | } |
2266 | if (sb_has_quota_loaded(sb, type)) { | ||
2267 | error = -EBUSY; | ||
2268 | goto out_fmt; | ||
2269 | } | ||
2284 | 2270 | ||
2285 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { | 2271 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { |
2286 | /* As we bypass the pagecache we must now flush all the | 2272 | /* As we bypass the pagecache we must now flush all the |
@@ -2292,11 +2278,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2292 | sync_filesystem(sb); | 2278 | sync_filesystem(sb); |
2293 | invalidate_bdev(sb->s_bdev); | 2279 | invalidate_bdev(sb->s_bdev); |
2294 | } | 2280 | } |
2295 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2296 | if (sb_has_quota_loaded(sb, type)) { | ||
2297 | error = -EBUSY; | ||
2298 | goto out_lock; | ||
2299 | } | ||
2300 | 2281 | ||
2301 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { | 2282 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { |
2302 | /* We don't want quota and atime on quota files (deadlocks | 2283 | /* We don't want quota and atime on quota files (deadlocks |
@@ -2317,7 +2298,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2317 | error = -EIO; | 2298 | error = -EIO; |
2318 | dqopt->files[type] = igrab(inode); | 2299 | dqopt->files[type] = igrab(inode); |
2319 | if (!dqopt->files[type]) | 2300 | if (!dqopt->files[type]) |
2320 | goto out_lock; | 2301 | goto out_file_flags; |
2321 | error = -EINVAL; | 2302 | error = -EINVAL; |
2322 | if (!fmt->qf_ops->check_quota_file(sb, type)) | 2303 | if (!fmt->qf_ops->check_quota_file(sb, type)) |
2323 | goto out_file_init; | 2304 | goto out_file_init; |
@@ -2340,14 +2321,13 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2340 | spin_unlock(&dq_state_lock); | 2321 | spin_unlock(&dq_state_lock); |
2341 | 2322 | ||
2342 | add_dquot_ref(sb, type); | 2323 | add_dquot_ref(sb, type); |
2343 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2344 | 2324 | ||
2345 | return 0; | 2325 | return 0; |
2346 | 2326 | ||
2347 | out_file_init: | 2327 | out_file_init: |
2348 | dqopt->files[type] = NULL; | 2328 | dqopt->files[type] = NULL; |
2349 | iput(inode); | 2329 | iput(inode); |
2350 | out_lock: | 2330 | out_file_flags: |
2351 | if (oldflags != -1) { | 2331 | if (oldflags != -1) { |
2352 | inode_lock(inode); | 2332 | inode_lock(inode); |
2353 | /* Set the flags back (in the case of accidental quotaon() | 2333 | /* Set the flags back (in the case of accidental quotaon() |
@@ -2356,7 +2336,6 @@ out_lock: | |||
2356 | inode->i_flags |= oldflags; | 2336 | inode->i_flags |= oldflags; |
2357 | inode_unlock(inode); | 2337 | inode_unlock(inode); |
2358 | } | 2338 | } |
2359 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2360 | out_fmt: | 2339 | out_fmt: |
2361 | put_quota_format(fmt); | 2340 | put_quota_format(fmt); |
2362 | 2341 | ||
@@ -2371,15 +2350,16 @@ int dquot_resume(struct super_block *sb, int type) | |||
2371 | int ret = 0, cnt; | 2350 | int ret = 0, cnt; |
2372 | unsigned int flags; | 2351 | unsigned int flags; |
2373 | 2352 | ||
2353 | /* s_umount should be held in exclusive mode */ | ||
2354 | if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount))) | ||
2355 | up_read(&sb->s_umount); | ||
2356 | |||
2374 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 2357 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
2375 | if (type != -1 && cnt != type) | 2358 | if (type != -1 && cnt != type) |
2376 | continue; | 2359 | continue; |
2377 | 2360 | if (!sb_has_quota_suspended(sb, cnt)) | |
2378 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2379 | if (!sb_has_quota_suspended(sb, cnt)) { | ||
2380 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2381 | continue; | 2361 | continue; |
2382 | } | 2362 | |
2383 | inode = dqopt->files[cnt]; | 2363 | inode = dqopt->files[cnt]; |
2384 | dqopt->files[cnt] = NULL; | 2364 | dqopt->files[cnt] = NULL; |
2385 | spin_lock(&dq_state_lock); | 2365 | spin_lock(&dq_state_lock); |
@@ -2388,7 +2368,6 @@ int dquot_resume(struct super_block *sb, int type) | |||
2388 | cnt); | 2368 | cnt); |
2389 | dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt); | 2369 | dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt); |
2390 | spin_unlock(&dq_state_lock); | 2370 | spin_unlock(&dq_state_lock); |
2391 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2392 | 2371 | ||
2393 | flags = dquot_generic_flag(flags, cnt); | 2372 | flags = dquot_generic_flag(flags, cnt); |
2394 | ret = vfs_load_quota_inode(inode, cnt, | 2373 | ret = vfs_load_quota_inode(inode, cnt, |
@@ -2424,42 +2403,30 @@ EXPORT_SYMBOL(dquot_quota_on); | |||
2424 | int dquot_enable(struct inode *inode, int type, int format_id, | 2403 | int dquot_enable(struct inode *inode, int type, int format_id, |
2425 | unsigned int flags) | 2404 | unsigned int flags) |
2426 | { | 2405 | { |
2427 | int ret = 0; | ||
2428 | struct super_block *sb = inode->i_sb; | 2406 | struct super_block *sb = inode->i_sb; |
2429 | struct quota_info *dqopt = sb_dqopt(sb); | ||
2430 | 2407 | ||
2431 | /* Just unsuspend quotas? */ | 2408 | /* Just unsuspend quotas? */ |
2432 | BUG_ON(flags & DQUOT_SUSPENDED); | 2409 | BUG_ON(flags & DQUOT_SUSPENDED); |
2410 | /* s_umount should be held in exclusive mode */ | ||
2411 | if (WARN_ON_ONCE(down_read_trylock(&sb->s_umount))) | ||
2412 | up_read(&sb->s_umount); | ||
2433 | 2413 | ||
2434 | if (!flags) | 2414 | if (!flags) |
2435 | return 0; | 2415 | return 0; |
2436 | /* Just updating flags needed? */ | 2416 | /* Just updating flags needed? */ |
2437 | if (sb_has_quota_loaded(sb, type)) { | 2417 | if (sb_has_quota_loaded(sb, type)) { |
2438 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2439 | /* Now do a reliable test... */ | ||
2440 | if (!sb_has_quota_loaded(sb, type)) { | ||
2441 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2442 | goto load_quota; | ||
2443 | } | ||
2444 | if (flags & DQUOT_USAGE_ENABLED && | 2418 | if (flags & DQUOT_USAGE_ENABLED && |
2445 | sb_has_quota_usage_enabled(sb, type)) { | 2419 | sb_has_quota_usage_enabled(sb, type)) |
2446 | ret = -EBUSY; | 2420 | return -EBUSY; |
2447 | goto out_lock; | ||
2448 | } | ||
2449 | if (flags & DQUOT_LIMITS_ENABLED && | 2421 | if (flags & DQUOT_LIMITS_ENABLED && |
2450 | sb_has_quota_limits_enabled(sb, type)) { | 2422 | sb_has_quota_limits_enabled(sb, type)) |
2451 | ret = -EBUSY; | 2423 | return -EBUSY; |
2452 | goto out_lock; | ||
2453 | } | ||
2454 | spin_lock(&dq_state_lock); | 2424 | spin_lock(&dq_state_lock); |
2455 | sb_dqopt(sb)->flags |= dquot_state_flag(flags, type); | 2425 | sb_dqopt(sb)->flags |= dquot_state_flag(flags, type); |
2456 | spin_unlock(&dq_state_lock); | 2426 | spin_unlock(&dq_state_lock); |
2457 | out_lock: | 2427 | return 0; |
2458 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2459 | return ret; | ||
2460 | } | 2428 | } |
2461 | 2429 | ||
2462 | load_quota: | ||
2463 | return vfs_load_quota_inode(inode, type, format_id, flags); | 2430 | return vfs_load_quota_inode(inode, type, format_id, flags); |
2464 | } | 2431 | } |
2465 | EXPORT_SYMBOL(dquot_enable); | 2432 | EXPORT_SYMBOL(dquot_enable); |
@@ -2751,7 +2718,6 @@ int dquot_get_state(struct super_block *sb, struct qc_state *state) | |||
2751 | struct quota_info *dqopt = sb_dqopt(sb); | 2718 | struct quota_info *dqopt = sb_dqopt(sb); |
2752 | int type; | 2719 | int type; |
2753 | 2720 | ||
2754 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | ||
2755 | memset(state, 0, sizeof(*state)); | 2721 | memset(state, 0, sizeof(*state)); |
2756 | for (type = 0; type < MAXQUOTAS; type++) { | 2722 | for (type = 0; type < MAXQUOTAS; type++) { |
2757 | if (!sb_has_quota_active(sb, type)) | 2723 | if (!sb_has_quota_active(sb, type)) |
@@ -2773,7 +2739,6 @@ int dquot_get_state(struct super_block *sb, struct qc_state *state) | |||
2773 | tstate->nextents = 1; /* We don't know... */ | 2739 | tstate->nextents = 1; /* We don't know... */ |
2774 | spin_unlock(&dq_data_lock); | 2740 | spin_unlock(&dq_data_lock); |
2775 | } | 2741 | } |
2776 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | ||
2777 | return 0; | 2742 | return 0; |
2778 | } | 2743 | } |
2779 | EXPORT_SYMBOL(dquot_get_state); | 2744 | EXPORT_SYMBOL(dquot_get_state); |
@@ -2787,18 +2752,13 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii) | |||
2787 | if ((ii->i_fieldmask & QC_WARNS_MASK) || | 2752 | if ((ii->i_fieldmask & QC_WARNS_MASK) || |
2788 | (ii->i_fieldmask & QC_RT_SPC_TIMER)) | 2753 | (ii->i_fieldmask & QC_RT_SPC_TIMER)) |
2789 | return -EINVAL; | 2754 | return -EINVAL; |
2790 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 2755 | if (!sb_has_quota_active(sb, type)) |
2791 | if (!sb_has_quota_active(sb, type)) { | 2756 | return -ESRCH; |
2792 | err = -ESRCH; | ||
2793 | goto out; | ||
2794 | } | ||
2795 | mi = sb_dqopt(sb)->info + type; | 2757 | mi = sb_dqopt(sb)->info + type; |
2796 | if (ii->i_fieldmask & QC_FLAGS) { | 2758 | if (ii->i_fieldmask & QC_FLAGS) { |
2797 | if ((ii->i_flags & QCI_ROOT_SQUASH && | 2759 | if ((ii->i_flags & QCI_ROOT_SQUASH && |
2798 | mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) { | 2760 | mi->dqi_format->qf_fmt_id != QFMT_VFS_OLD)) |
2799 | err = -EINVAL; | 2761 | return -EINVAL; |
2800 | goto out; | ||
2801 | } | ||
2802 | } | 2762 | } |
2803 | spin_lock(&dq_data_lock); | 2763 | spin_lock(&dq_data_lock); |
2804 | if (ii->i_fieldmask & QC_SPC_TIMER) | 2764 | if (ii->i_fieldmask & QC_SPC_TIMER) |
@@ -2815,8 +2775,6 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct qc_info *ii) | |||
2815 | mark_info_dirty(sb, type); | 2775 | mark_info_dirty(sb, type); |
2816 | /* Force write to disk */ | 2776 | /* Force write to disk */ |
2817 | sb->dq_op->write_info(sb, type); | 2777 | sb->dq_op->write_info(sb, type); |
2818 | out: | ||
2819 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | ||
2820 | return err; | 2778 | return err; |
2821 | } | 2779 | } |
2822 | EXPORT_SYMBOL(dquot_set_dqinfo); | 2780 | EXPORT_SYMBOL(dquot_set_dqinfo); |
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 5acd0c4769af..07e08c7d05ca 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -104,13 +104,9 @@ static int quota_getfmt(struct super_block *sb, int type, void __user *addr) | |||
104 | { | 104 | { |
105 | __u32 fmt; | 105 | __u32 fmt; |
106 | 106 | ||
107 | mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); | 107 | if (!sb_has_quota_active(sb, type)) |
108 | if (!sb_has_quota_active(sb, type)) { | ||
109 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | ||
110 | return -ESRCH; | 108 | return -ESRCH; |
111 | } | ||
112 | fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; | 109 | fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; |
113 | mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); | ||
114 | if (copy_to_user(addr, &fmt, sizeof(fmt))) | 110 | if (copy_to_user(addr, &fmt, sizeof(fmt))) |
115 | return -EFAULT; | 111 | return -EFAULT; |
116 | return 0; | 112 | return 0; |
@@ -789,9 +785,14 @@ static int quotactl_cmd_write(int cmd) | |||
789 | } | 785 | } |
790 | return 1; | 786 | return 1; |
791 | } | 787 | } |
792 | |||
793 | #endif /* CONFIG_BLOCK */ | 788 | #endif /* CONFIG_BLOCK */ |
794 | 789 | ||
790 | /* Return true if quotactl command is manipulating quota on/off state */ | ||
791 | static bool quotactl_cmd_onoff(int cmd) | ||
792 | { | ||
793 | return (cmd == Q_QUOTAON) || (cmd == Q_QUOTAOFF); | ||
794 | } | ||
795 | |||
795 | /* | 796 | /* |
796 | * look up a superblock on which quota ops will be performed | 797 | * look up a superblock on which quota ops will be performed |
797 | * - use the name of a block device to find the superblock thereon | 798 | * - use the name of a block device to find the superblock thereon |
@@ -809,7 +810,9 @@ static struct super_block *quotactl_block(const char __user *special, int cmd) | |||
809 | putname(tmp); | 810 | putname(tmp); |
810 | if (IS_ERR(bdev)) | 811 | if (IS_ERR(bdev)) |
811 | return ERR_CAST(bdev); | 812 | return ERR_CAST(bdev); |
812 | if (quotactl_cmd_write(cmd)) | 813 | if (quotactl_cmd_onoff(cmd)) |
814 | sb = get_super_exclusive_thawed(bdev); | ||
815 | else if (quotactl_cmd_write(cmd)) | ||
813 | sb = get_super_thawed(bdev); | 816 | sb = get_super_thawed(bdev); |
814 | else | 817 | else |
815 | sb = get_super(bdev); | 818 | sb = get_super(bdev); |
@@ -872,7 +875,10 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special, | |||
872 | 875 | ||
873 | ret = do_quotactl(sb, type, cmds, id, addr, pathp); | 876 | ret = do_quotactl(sb, type, cmds, id, addr, pathp); |
874 | 877 | ||
875 | drop_super(sb); | 878 | if (!quotactl_cmd_onoff(cmds)) |
879 | drop_super(sb); | ||
880 | else | ||
881 | drop_super_exclusive(sb); | ||
876 | out: | 882 | out: |
877 | if (pathp && !IS_ERR(pathp)) | 883 | if (pathp && !IS_ERR(pathp)) |
878 | path_put(pathp); | 884 | path_put(pathp); |
diff --git a/fs/super.c b/fs/super.c index c183835566c1..1709ed029a2c 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -244,7 +244,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, | |||
244 | mutex_init(&s->s_vfs_rename_mutex); | 244 | mutex_init(&s->s_vfs_rename_mutex); |
245 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); | 245 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); |
246 | mutex_init(&s->s_dquot.dqio_mutex); | 246 | mutex_init(&s->s_dquot.dqio_mutex); |
247 | mutex_init(&s->s_dquot.dqonoff_mutex); | ||
248 | s->s_maxbytes = MAX_NON_LFS; | 247 | s->s_maxbytes = MAX_NON_LFS; |
249 | s->s_op = &default_op; | 248 | s->s_op = &default_op; |
250 | s->s_time_gran = 1000000000; | 249 | s->s_time_gran = 1000000000; |
@@ -558,6 +557,13 @@ void drop_super(struct super_block *sb) | |||
558 | 557 | ||
559 | EXPORT_SYMBOL(drop_super); | 558 | EXPORT_SYMBOL(drop_super); |
560 | 559 | ||
560 | void drop_super_exclusive(struct super_block *sb) | ||
561 | { | ||
562 | up_write(&sb->s_umount); | ||
563 | put_super(sb); | ||
564 | } | ||
565 | EXPORT_SYMBOL(drop_super_exclusive); | ||
566 | |||
561 | /** | 567 | /** |
562 | * iterate_supers - call function for all active superblocks | 568 | * iterate_supers - call function for all active superblocks |
563 | * @f: function to call | 569 | * @f: function to call |
@@ -628,15 +634,7 @@ void iterate_supers_type(struct file_system_type *type, | |||
628 | 634 | ||
629 | EXPORT_SYMBOL(iterate_supers_type); | 635 | EXPORT_SYMBOL(iterate_supers_type); |
630 | 636 | ||
631 | /** | 637 | static struct super_block *__get_super(struct block_device *bdev, bool excl) |
632 | * get_super - get the superblock of a device | ||
633 | * @bdev: device to get the superblock for | ||
634 | * | ||
635 | * Scans the superblock list and finds the superblock of the file system | ||
636 | * mounted on the device given. %NULL is returned if no match is found. | ||
637 | */ | ||
638 | |||
639 | struct super_block *get_super(struct block_device *bdev) | ||
640 | { | 638 | { |
641 | struct super_block *sb; | 639 | struct super_block *sb; |
642 | 640 | ||
@@ -651,11 +649,17 @@ rescan: | |||
651 | if (sb->s_bdev == bdev) { | 649 | if (sb->s_bdev == bdev) { |
652 | sb->s_count++; | 650 | sb->s_count++; |
653 | spin_unlock(&sb_lock); | 651 | spin_unlock(&sb_lock); |
654 | down_read(&sb->s_umount); | 652 | if (!excl) |
653 | down_read(&sb->s_umount); | ||
654 | else | ||
655 | down_write(&sb->s_umount); | ||
655 | /* still alive? */ | 656 | /* still alive? */ |
656 | if (sb->s_root && (sb->s_flags & MS_BORN)) | 657 | if (sb->s_root && (sb->s_flags & MS_BORN)) |
657 | return sb; | 658 | return sb; |
658 | up_read(&sb->s_umount); | 659 | if (!excl) |
660 | up_read(&sb->s_umount); | ||
661 | else | ||
662 | up_write(&sb->s_umount); | ||
659 | /* nope, got unmounted */ | 663 | /* nope, got unmounted */ |
660 | spin_lock(&sb_lock); | 664 | spin_lock(&sb_lock); |
661 | __put_super(sb); | 665 | __put_super(sb); |
@@ -666,32 +670,67 @@ rescan: | |||
666 | return NULL; | 670 | return NULL; |
667 | } | 671 | } |
668 | 672 | ||
669 | EXPORT_SYMBOL(get_super); | ||
670 | |||
671 | /** | 673 | /** |
672 | * get_super_thawed - get thawed superblock of a device | 674 | * get_super - get the superblock of a device |
673 | * @bdev: device to get the superblock for | 675 | * @bdev: device to get the superblock for |
674 | * | 676 | * |
675 | * Scans the superblock list and finds the superblock of the file system | 677 | * Scans the superblock list and finds the superblock of the file system |
676 | * mounted on the device. The superblock is returned once it is thawed | 678 | * mounted on the device given. %NULL is returned if no match is found. |
677 | * (or immediately if it was not frozen). %NULL is returned if no match | ||
678 | * is found. | ||
679 | */ | 679 | */ |
680 | struct super_block *get_super_thawed(struct block_device *bdev) | 680 | struct super_block *get_super(struct block_device *bdev) |
681 | { | ||
682 | return __get_super(bdev, false); | ||
683 | } | ||
684 | EXPORT_SYMBOL(get_super); | ||
685 | |||
686 | static struct super_block *__get_super_thawed(struct block_device *bdev, | ||
687 | bool excl) | ||
681 | { | 688 | { |
682 | while (1) { | 689 | while (1) { |
683 | struct super_block *s = get_super(bdev); | 690 | struct super_block *s = __get_super(bdev, excl); |
684 | if (!s || s->s_writers.frozen == SB_UNFROZEN) | 691 | if (!s || s->s_writers.frozen == SB_UNFROZEN) |
685 | return s; | 692 | return s; |
686 | up_read(&s->s_umount); | 693 | if (!excl) |
694 | up_read(&s->s_umount); | ||
695 | else | ||
696 | up_write(&s->s_umount); | ||
687 | wait_event(s->s_writers.wait_unfrozen, | 697 | wait_event(s->s_writers.wait_unfrozen, |
688 | s->s_writers.frozen == SB_UNFROZEN); | 698 | s->s_writers.frozen == SB_UNFROZEN); |
689 | put_super(s); | 699 | put_super(s); |
690 | } | 700 | } |
691 | } | 701 | } |
702 | |||
703 | /** | ||
704 | * get_super_thawed - get thawed superblock of a device | ||
705 | * @bdev: device to get the superblock for | ||
706 | * | ||
707 | * Scans the superblock list and finds the superblock of the file system | ||
708 | * mounted on the device. The superblock is returned once it is thawed | ||
709 | * (or immediately if it was not frozen). %NULL is returned if no match | ||
710 | * is found. | ||
711 | */ | ||
712 | struct super_block *get_super_thawed(struct block_device *bdev) | ||
713 | { | ||
714 | return __get_super_thawed(bdev, false); | ||
715 | } | ||
692 | EXPORT_SYMBOL(get_super_thawed); | 716 | EXPORT_SYMBOL(get_super_thawed); |
693 | 717 | ||
694 | /** | 718 | /** |
719 | * get_super_exclusive_thawed - get thawed superblock of a device | ||
720 | * @bdev: device to get the superblock for | ||
721 | * | ||
722 | * Scans the superblock list and finds the superblock of the file system | ||
723 | * mounted on the device. The superblock is returned once it is thawed | ||
724 | * (or immediately if it was not frozen) and s_umount semaphore is held | ||
725 | * in exclusive mode. %NULL is returned if no match is found. | ||
726 | */ | ||
727 | struct super_block *get_super_exclusive_thawed(struct block_device *bdev) | ||
728 | { | ||
729 | return __get_super_thawed(bdev, true); | ||
730 | } | ||
731 | EXPORT_SYMBOL(get_super_exclusive_thawed); | ||
732 | |||
733 | /** | ||
695 | * get_active_super - get an active reference to the superblock of a device | 734 | * get_active_super - get an active reference to the superblock of a device |
696 | * @bdev: device to get the superblock for | 735 | * @bdev: device to get the superblock for |
697 | * | 736 | * |
diff --git a/include/linux/fs.h b/include/linux/fs.h index e6e4146bf9ae..2ba074328894 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2903,8 +2903,10 @@ extern void put_filesystem(struct file_system_type *fs); | |||
2903 | extern struct file_system_type *get_fs_type(const char *name); | 2903 | extern struct file_system_type *get_fs_type(const char *name); |
2904 | extern struct super_block *get_super(struct block_device *); | 2904 | extern struct super_block *get_super(struct block_device *); |
2905 | extern struct super_block *get_super_thawed(struct block_device *); | 2905 | extern struct super_block *get_super_thawed(struct block_device *); |
2906 | extern struct super_block *get_super_exclusive_thawed(struct block_device *bdev); | ||
2906 | extern struct super_block *get_active_super(struct block_device *bdev); | 2907 | extern struct super_block *get_active_super(struct block_device *bdev); |
2907 | extern void drop_super(struct super_block *sb); | 2908 | extern void drop_super(struct super_block *sb); |
2909 | extern void drop_super_exclusive(struct super_block *sb); | ||
2908 | extern void iterate_supers(void (*)(struct super_block *, void *), void *); | 2910 | extern void iterate_supers(void (*)(struct super_block *, void *), void *); |
2909 | extern void iterate_supers_type(struct file_system_type *, | 2911 | extern void iterate_supers_type(struct file_system_type *, |
2910 | void (*)(struct super_block *, void *), void *); | 2912 | void (*)(struct super_block *, void *), void *); |
diff --git a/include/linux/quota.h b/include/linux/quota.h index 78a98821f9d0..3434eef2a5aa 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -520,7 +520,6 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev, | |||
520 | struct quota_info { | 520 | struct quota_info { |
521 | unsigned int flags; /* Flags for diskquotas on this device */ | 521 | unsigned int flags; /* Flags for diskquotas on this device */ |
522 | struct mutex dqio_mutex; /* lock device while I/O in progress */ | 522 | struct mutex dqio_mutex; /* lock device while I/O in progress */ |
523 | struct mutex dqonoff_mutex; /* Serialize quotaon & quotaoff */ | ||
524 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ | 523 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ |
525 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ | 524 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ |
526 | const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ | 525 | const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ |