aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/dquot.c18
-rw-r--r--fs/namespace.c64
-rw-r--r--fs/super.c1
3 files changed, 44 insertions, 39 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index afa06a893468..05b60283c9c2 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -1321,13 +1321,11 @@ int vfs_quota_off(struct super_block *sb, int type)
1321 int cnt; 1321 int cnt;
1322 struct quota_info *dqopt = sb_dqopt(sb); 1322 struct quota_info *dqopt = sb_dqopt(sb);
1323 struct inode *toputinode[MAXQUOTAS]; 1323 struct inode *toputinode[MAXQUOTAS];
1324 struct vfsmount *toputmnt[MAXQUOTAS];
1325 1324
1326 /* We need to serialize quota_off() for device */ 1325 /* We need to serialize quota_off() for device */
1327 down(&dqopt->dqonoff_sem); 1326 down(&dqopt->dqonoff_sem);
1328 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 1327 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
1329 toputinode[cnt] = NULL; 1328 toputinode[cnt] = NULL;
1330 toputmnt[cnt] = NULL;
1331 if (type != -1 && cnt != type) 1329 if (type != -1 && cnt != type)
1332 continue; 1330 continue;
1333 if (!sb_has_quota_enabled(sb, cnt)) 1331 if (!sb_has_quota_enabled(sb, cnt))
@@ -1348,9 +1346,7 @@ int vfs_quota_off(struct super_block *sb, int type)
1348 put_quota_format(dqopt->info[cnt].dqi_format); 1346 put_quota_format(dqopt->info[cnt].dqi_format);
1349 1347
1350 toputinode[cnt] = dqopt->files[cnt]; 1348 toputinode[cnt] = dqopt->files[cnt];
1351 toputmnt[cnt] = dqopt->mnt[cnt];
1352 dqopt->files[cnt] = NULL; 1349 dqopt->files[cnt] = NULL;
1353 dqopt->mnt[cnt] = NULL;
1354 dqopt->info[cnt].dqi_flags = 0; 1350 dqopt->info[cnt].dqi_flags = 0;
1355 dqopt->info[cnt].dqi_igrace = 0; 1351 dqopt->info[cnt].dqi_igrace = 0;
1356 dqopt->info[cnt].dqi_bgrace = 0; 1352 dqopt->info[cnt].dqi_bgrace = 0;
@@ -1358,10 +1354,7 @@ int vfs_quota_off(struct super_block *sb, int type)
1358 } 1354 }
1359 up(&dqopt->dqonoff_sem); 1355 up(&dqopt->dqonoff_sem);
1360 /* Sync the superblock so that buffers with quota data are written to 1356 /* Sync the superblock so that buffers with quota data are written to
1361 * disk (and so userspace sees correct data afterwards). 1357 * disk (and so userspace sees correct data afterwards). */
1362 * The reference to vfsmnt we are still holding protects us from
1363 * umount (we don't have it only when quotas are turned on/off for
1364 * journal replay but in that case we are guarded by the fs anyway). */
1365 if (sb->s_op->sync_fs) 1358 if (sb->s_op->sync_fs)
1366 sb->s_op->sync_fs(sb, 1); 1359 sb->s_op->sync_fs(sb, 1);
1367 sync_blockdev(sb->s_bdev); 1360 sync_blockdev(sb->s_bdev);
@@ -1385,10 +1378,6 @@ int vfs_quota_off(struct super_block *sb, int type)
1385 iput(toputinode[cnt]); 1378 iput(toputinode[cnt]);
1386 } 1379 }
1387 up(&dqopt->dqonoff_sem); 1380 up(&dqopt->dqonoff_sem);
1388 /* We don't hold the reference when we turned on quotas
1389 * just for the journal replay... */
1390 if (toputmnt[cnt])
1391 mntput(toputmnt[cnt]);
1392 } 1381 }
1393 if (sb->s_bdev) 1382 if (sb->s_bdev)
1394 invalidate_bdev(sb->s_bdev, 0); 1383 invalidate_bdev(sb->s_bdev, 0);
@@ -1503,11 +1492,8 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
1503 /* Quota file not on the same filesystem? */ 1492 /* Quota file not on the same filesystem? */
1504 if (nd.mnt->mnt_sb != sb) 1493 if (nd.mnt->mnt_sb != sb)
1505 error = -EXDEV; 1494 error = -EXDEV;
1506 else { 1495 else
1507 error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); 1496 error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
1508 if (!error)
1509 sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);
1510 }
1511out_path: 1497out_path:
1512 path_release(&nd); 1498 path_release(&nd);
1513 return error; 1499 return error;
diff --git a/fs/namespace.c b/fs/namespace.c
index 2fa9fdf7d6f5..1d83302f30c3 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -172,7 +172,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root)
172 return mnt; 172 return mnt;
173} 173}
174 174
175void __mntput(struct vfsmount *mnt) 175static inline void __mntput(struct vfsmount *mnt)
176{ 176{
177 struct super_block *sb = mnt->mnt_sb; 177 struct super_block *sb = mnt->mnt_sb;
178 dput(mnt->mnt_root); 178 dput(mnt->mnt_root);
@@ -180,7 +180,46 @@ void __mntput(struct vfsmount *mnt)
180 deactivate_super(sb); 180 deactivate_super(sb);
181} 181}
182 182
183EXPORT_SYMBOL(__mntput); 183void mntput_no_expire(struct vfsmount *mnt)
184{
185repeat:
186 if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock)) {
187 if (likely(!mnt->mnt_pinned)) {
188 spin_unlock(&vfsmount_lock);
189 __mntput(mnt);
190 return;
191 }
192 atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count);
193 mnt->mnt_pinned = 0;
194 spin_unlock(&vfsmount_lock);
195 acct_auto_close_mnt(mnt);
196 security_sb_umount_close(mnt);
197 goto repeat;
198 }
199}
200
201EXPORT_SYMBOL(mntput_no_expire);
202
203void mnt_pin(struct vfsmount *mnt)
204{
205 spin_lock(&vfsmount_lock);
206 mnt->mnt_pinned++;
207 spin_unlock(&vfsmount_lock);
208}
209
210EXPORT_SYMBOL(mnt_pin);
211
212void mnt_unpin(struct vfsmount *mnt)
213{
214 spin_lock(&vfsmount_lock);
215 if (mnt->mnt_pinned) {
216 atomic_inc(&mnt->mnt_count);
217 mnt->mnt_pinned--;
218 }
219 spin_unlock(&vfsmount_lock);
220}
221
222EXPORT_SYMBOL(mnt_unpin);
184 223
185/* iterator */ 224/* iterator */
186static void *m_start(struct seq_file *m, loff_t *pos) 225static void *m_start(struct seq_file *m, loff_t *pos)
@@ -435,16 +474,6 @@ static int do_umount(struct vfsmount *mnt, int flags)
435 down_write(&current->namespace->sem); 474 down_write(&current->namespace->sem);
436 spin_lock(&vfsmount_lock); 475 spin_lock(&vfsmount_lock);
437 476
438 if (atomic_read(&sb->s_active) == 1) {
439 /* last instance - try to be smart */
440 spin_unlock(&vfsmount_lock);
441 lock_kernel();
442 DQUOT_OFF(sb);
443 acct_auto_close(sb);
444 unlock_kernel();
445 security_sb_umount_close(mnt);
446 spin_lock(&vfsmount_lock);
447 }
448 retval = -EBUSY; 477 retval = -EBUSY;
449 if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { 478 if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
450 if (!list_empty(&mnt->mnt_list)) 479 if (!list_empty(&mnt->mnt_list))
@@ -850,17 +879,6 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts)
850 detach_mnt(mnt, &old_nd); 879 detach_mnt(mnt, &old_nd);
851 spin_unlock(&vfsmount_lock); 880 spin_unlock(&vfsmount_lock);
852 path_release(&old_nd); 881 path_release(&old_nd);
853
854 /*
855 * Now lay it to rest if this was the last ref on the superblock
856 */
857 if (atomic_read(&mnt->mnt_sb->s_active) == 1) {
858 /* last instance - try to be smart */
859 lock_kernel();
860 DQUOT_OFF(mnt->mnt_sb);
861 acct_auto_close(mnt->mnt_sb);
862 unlock_kernel();
863 }
864 mntput(mnt); 882 mntput(mnt);
865 } else { 883 } else {
866 /* 884 /*
diff --git a/fs/super.c b/fs/super.c
index eed6c3132905..6689dded3c84 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -171,6 +171,7 @@ void deactivate_super(struct super_block *s)
171 if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { 171 if (atomic_dec_and_lock(&s->s_active, &sb_lock)) {
172 s->s_count -= S_BIAS-1; 172 s->s_count -= S_BIAS-1;
173 spin_unlock(&sb_lock); 173 spin_unlock(&sb_lock);
174 DQUOT_OFF(s);
174 down_write(&s->s_umount); 175 down_write(&s->s_umount);
175 fs->kill_sb(s); 176 fs->kill_sb(s);
176 put_filesystem(fs); 177 put_filesystem(fs);