aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
commita0e881b7c189fa2bd76c024dbff91e79511c971d (patch)
tree0c801918565b08921d21aceee5b326f64d998f5f /fs/namespace.c
parenteff0d13f3823f35d70228cd151d2a2c89288ff32 (diff)
parentdbc6e0222d79e78925fe20733844a796a4b72cf9 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull second vfs pile from Al Viro: "The stuff in there: fsfreeze deadlock fixes by Jan (essentially, the deadlock reproduced by xfstests 068), symlink and hardlink restriction patches, plus assorted cleanups and fixes. Note that another fsfreeze deadlock (emergency thaw one) is *not* dealt with - the series by Fernando conflicts a lot with Jan's, breaks userland ABI (FIFREEZE semantics gets changed) and trades the deadlock for massive vfsmount leak; this is going to be handled next cycle. There probably will be another pull request, but that stuff won't be in it." Fix up trivial conflicts due to unrelated changes next to each other in drivers/{staging/gdm72xx/usb_boot.c, usb/gadget/storage_common.c} * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (54 commits) delousing target_core_file a bit Documentation: Correct s_umount state for freeze_fs/unfreeze_fs fs: Remove old freezing mechanism ext2: Implement freezing btrfs: Convert to new freezing mechanism nilfs2: Convert to new freezing mechanism ntfs: Convert to new freezing mechanism fuse: Convert to new freezing mechanism gfs2: Convert to new freezing mechanism ocfs2: Convert to new freezing mechanism xfs: Convert to new freezing code ext4: Convert to new freezing mechanism fs: Protect write paths by sb_start_write - sb_end_write fs: Skip atime update on frozen filesystem fs: Add freezing handling to mnt_want_write() / mnt_drop_write() fs: Improve filesystem freezing handling switch the protection of percpu_counter list to spinlock nfsd: Push mnt_want_write() outside of i_mutex btrfs: Push mnt_want_write() outside of i_mutex fat: Push mnt_want_write() outside of i_mutex ...
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index c53d3381b0d0..4d31f73e2561 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -283,24 +283,22 @@ static int mnt_is_readonly(struct vfsmount *mnt)
283} 283}
284 284
285/* 285/*
286 * Most r/o checks on a fs are for operations that take 286 * Most r/o & frozen checks on a fs are for operations that take discrete
287 * discrete amounts of time, like a write() or unlink(). 287 * amounts of time, like a write() or unlink(). We must keep track of when
288 * We must keep track of when those operations start 288 * those operations start (for permission checks) and when they end, so that we
289 * (for permission checks) and when they end, so that 289 * can determine when writes are able to occur to a filesystem.
290 * we can determine when writes are able to occur to
291 * a filesystem.
292 */ 290 */
293/** 291/**
294 * mnt_want_write - get write access to a mount 292 * __mnt_want_write - get write access to a mount without freeze protection
295 * @m: the mount on which to take a write 293 * @m: the mount on which to take a write
296 * 294 *
297 * This tells the low-level filesystem that a write is 295 * This tells the low-level filesystem that a write is about to be performed to
298 * about to be performed to it, and makes sure that 296 * it, and makes sure that writes are allowed (mnt it read-write) before
299 * writes are allowed before returning success. When 297 * returning success. This operation does not protect against filesystem being
300 * the write operation is finished, mnt_drop_write() 298 * frozen. When the write operation is finished, __mnt_drop_write() must be
301 * must be called. This is effectively a refcount. 299 * called. This is effectively a refcount.
302 */ 300 */
303int mnt_want_write(struct vfsmount *m) 301int __mnt_want_write(struct vfsmount *m)
304{ 302{
305 struct mount *mnt = real_mount(m); 303 struct mount *mnt = real_mount(m);
306 int ret = 0; 304 int ret = 0;
@@ -326,6 +324,27 @@ int mnt_want_write(struct vfsmount *m)
326 ret = -EROFS; 324 ret = -EROFS;
327 } 325 }
328 preempt_enable(); 326 preempt_enable();
327
328 return ret;
329}
330
331/**
332 * mnt_want_write - get write access to a mount
333 * @m: the mount on which to take a write
334 *
335 * This tells the low-level filesystem that a write is about to be performed to
336 * it, and makes sure that writes are allowed (mount is read-write, filesystem
337 * is not frozen) before returning success. When the write operation is
338 * finished, mnt_drop_write() must be called. This is effectively a refcount.
339 */
340int mnt_want_write(struct vfsmount *m)
341{
342 int ret;
343
344 sb_start_write(m->mnt_sb);
345 ret = __mnt_want_write(m);
346 if (ret)
347 sb_end_write(m->mnt_sb);
329 return ret; 348 return ret;
330} 349}
331EXPORT_SYMBOL_GPL(mnt_want_write); 350EXPORT_SYMBOL_GPL(mnt_want_write);
@@ -355,38 +374,76 @@ int mnt_clone_write(struct vfsmount *mnt)
355EXPORT_SYMBOL_GPL(mnt_clone_write); 374EXPORT_SYMBOL_GPL(mnt_clone_write);
356 375
357/** 376/**
358 * mnt_want_write_file - get write access to a file's mount 377 * __mnt_want_write_file - get write access to a file's mount
359 * @file: the file who's mount on which to take a write 378 * @file: the file who's mount on which to take a write
360 * 379 *
361 * This is like mnt_want_write, but it takes a file and can 380 * This is like __mnt_want_write, but it takes a file and can
362 * do some optimisations if the file is open for write already 381 * do some optimisations if the file is open for write already
363 */ 382 */
364int mnt_want_write_file(struct file *file) 383int __mnt_want_write_file(struct file *file)
365{ 384{
366 struct inode *inode = file->f_dentry->d_inode; 385 struct inode *inode = file->f_dentry->d_inode;
386
367 if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode)) 387 if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
368 return mnt_want_write(file->f_path.mnt); 388 return __mnt_want_write(file->f_path.mnt);
369 else 389 else
370 return mnt_clone_write(file->f_path.mnt); 390 return mnt_clone_write(file->f_path.mnt);
371} 391}
392
393/**
394 * mnt_want_write_file - get write access to a file's mount
395 * @file: the file who's mount on which to take a write
396 *
397 * This is like mnt_want_write, but it takes a file and can
398 * do some optimisations if the file is open for write already
399 */
400int mnt_want_write_file(struct file *file)
401{
402 int ret;
403
404 sb_start_write(file->f_path.mnt->mnt_sb);
405 ret = __mnt_want_write_file(file);
406 if (ret)
407 sb_end_write(file->f_path.mnt->mnt_sb);
408 return ret;
409}
372EXPORT_SYMBOL_GPL(mnt_want_write_file); 410EXPORT_SYMBOL_GPL(mnt_want_write_file);
373 411
374/** 412/**
375 * mnt_drop_write - give up write access to a mount 413 * __mnt_drop_write - give up write access to a mount
376 * @mnt: the mount on which to give up write access 414 * @mnt: the mount on which to give up write access
377 * 415 *
378 * Tells the low-level filesystem that we are done 416 * Tells the low-level filesystem that we are done
379 * performing writes to it. Must be matched with 417 * performing writes to it. Must be matched with
380 * mnt_want_write() call above. 418 * __mnt_want_write() call above.
381 */ 419 */
382void mnt_drop_write(struct vfsmount *mnt) 420void __mnt_drop_write(struct vfsmount *mnt)
383{ 421{
384 preempt_disable(); 422 preempt_disable();
385 mnt_dec_writers(real_mount(mnt)); 423 mnt_dec_writers(real_mount(mnt));
386 preempt_enable(); 424 preempt_enable();
387} 425}
426
427/**
428 * mnt_drop_write - give up write access to a mount
429 * @mnt: the mount on which to give up write access
430 *
431 * Tells the low-level filesystem that we are done performing writes to it and
432 * also allows filesystem to be frozen again. Must be matched with
433 * mnt_want_write() call above.
434 */
435void mnt_drop_write(struct vfsmount *mnt)
436{
437 __mnt_drop_write(mnt);
438 sb_end_write(mnt->mnt_sb);
439}
388EXPORT_SYMBOL_GPL(mnt_drop_write); 440EXPORT_SYMBOL_GPL(mnt_drop_write);
389 441
442void __mnt_drop_write_file(struct file *file)
443{
444 __mnt_drop_write(file->f_path.mnt);
445}
446
390void mnt_drop_write_file(struct file *file) 447void mnt_drop_write_file(struct file *file)
391{ 448{
392 mnt_drop_write(file->f_path.mnt); 449 mnt_drop_write(file->f_path.mnt);