From 00cd8dd3bf95f2cc8435b4cac01d9995635c6d0b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 Jun 2012 17:13:09 -0400 Subject: stop passing nameidata to ->lookup() Just the flags; only NFS cares even about that, but there are legitimate uses for such argument. And getting rid of that completely would require splitting ->lookup() into a couple of methods (at least), so let's leave that alone for now... Signed-off-by: Al Viro --- fs/ufs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ufs') diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index a2281cadefa..bc77fa170b9 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -46,7 +46,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode) return err; } -static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) +static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) { struct inode * inode = NULL; ino_t ino; -- cgit v1.2.3 From ebfc3b49a7ac25920cb5be5445f602e51d2ea559 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 10 Jun 2012 18:05:36 -0400 Subject: don't pass nameidata to ->create() boolean "does it have to be exclusive?" flag is passed instead; Local filesystem should just ignore it - the object is guaranteed not to be there yet. Signed-off-by: Al Viro --- fs/ufs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ufs') diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index bc77fa170b9..90d74b8f8eb 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -71,7 +71,7 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsi * with d_instantiate(). */ static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode, - struct nameidata *nd) + bool excl) { struct inode *inode; int err; -- cgit v1.2.3 From 65e5e83f7d01a3790deb1ba2e0d887e715c43307 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 12 Jul 2012 16:28:06 +0300 Subject: fs/ufs: remove extra superblock write on unmount UFS calls 'ufs_write_super()' from 'ufs_put_super()' in order to write the superblocks to the media. However, it is not needed because VFS calls '->sync_fs()' before calling '->put_super()' - so by the time we are in 'ufs_write_super()', the superblocks are already synchronized. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ufs/super.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 302f340d007..ae91e0af266 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1238,9 +1238,6 @@ static void ufs_put_super(struct super_block *sb) UFSD("ENTER\n"); - if (sb->s_dirt) - ufs_write_super(sb); - if (!(sb->s_flags & MS_RDONLY)) ufs_put_super_internal(sb); -- cgit v1.2.3 From 7bd54ef722e9938768f524677be0ac4985d8473a Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 12 Jul 2012 16:28:07 +0300 Subject: fs/ufs: re-arrange the code a bit This patch does not do any functional changes. It only moves 3 functions in fs/ufs/super.c a little bit up in order to prepare for further changes where I'll need this new arrangement to avoid forward declarations. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ufs/super.c | 117 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 58 insertions(+), 59 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/super.c b/fs/ufs/super.c index ae91e0af266..ad56c6dffc6 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -691,6 +691,64 @@ static void ufs_put_super_internal(struct super_block *sb) UFSD("EXIT\n"); } +static int ufs_sync_fs(struct super_block *sb, int wait) +{ + struct ufs_sb_private_info * uspi; + struct ufs_super_block_first * usb1; + struct ufs_super_block_third * usb3; + unsigned flags; + + lock_ufs(sb); + lock_super(sb); + + UFSD("ENTER\n"); + + flags = UFS_SB(sb)->s_flags; + uspi = UFS_SB(sb)->s_uspi; + usb1 = ubh_get_usb_first(uspi); + usb3 = ubh_get_usb_third(uspi); + + usb1->fs_time = cpu_to_fs32(sb, get_seconds()); + if ((flags & UFS_ST_MASK) == UFS_ST_SUN || + (flags & UFS_ST_MASK) == UFS_ST_SUNOS || + (flags & UFS_ST_MASK) == UFS_ST_SUNx86) + ufs_set_fs_state(sb, usb1, usb3, + UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); + ufs_put_cstotal(sb); + sb->s_dirt = 0; + + UFSD("EXIT\n"); + unlock_super(sb); + unlock_ufs(sb); + + return 0; +} + +static void ufs_write_super(struct super_block *sb) +{ + if (!(sb->s_flags & MS_RDONLY)) + ufs_sync_fs(sb, 1); + else + sb->s_dirt = 0; +} + +static void ufs_put_super(struct super_block *sb) +{ + struct ufs_sb_info * sbi = UFS_SB(sb); + + UFSD("ENTER\n"); + + if (!(sb->s_flags & MS_RDONLY)) + ufs_put_super_internal(sb); + + ubh_brelse_uspi (sbi->s_uspi); + kfree (sbi->s_uspi); + kfree (sbi); + sb->s_fs_info = NULL; + UFSD("EXIT\n"); + return; +} + static int ufs_fill_super(struct super_block *sb, void *data, int silent) { struct ufs_sb_info * sbi; @@ -1191,65 +1249,6 @@ failed_nomem: return -ENOMEM; } -static int ufs_sync_fs(struct super_block *sb, int wait) -{ - struct ufs_sb_private_info * uspi; - struct ufs_super_block_first * usb1; - struct ufs_super_block_third * usb3; - unsigned flags; - - lock_ufs(sb); - lock_super(sb); - - UFSD("ENTER\n"); - - flags = UFS_SB(sb)->s_flags; - uspi = UFS_SB(sb)->s_uspi; - usb1 = ubh_get_usb_first(uspi); - usb3 = ubh_get_usb_third(uspi); - - usb1->fs_time = cpu_to_fs32(sb, get_seconds()); - if ((flags & UFS_ST_MASK) == UFS_ST_SUN || - (flags & UFS_ST_MASK) == UFS_ST_SUNOS || - (flags & UFS_ST_MASK) == UFS_ST_SUNx86) - ufs_set_fs_state(sb, usb1, usb3, - UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); - ufs_put_cstotal(sb); - sb->s_dirt = 0; - - UFSD("EXIT\n"); - unlock_super(sb); - unlock_ufs(sb); - - return 0; -} - -static void ufs_write_super(struct super_block *sb) -{ - if (!(sb->s_flags & MS_RDONLY)) - ufs_sync_fs(sb, 1); - else - sb->s_dirt = 0; -} - -static void ufs_put_super(struct super_block *sb) -{ - struct ufs_sb_info * sbi = UFS_SB(sb); - - UFSD("ENTER\n"); - - if (!(sb->s_flags & MS_RDONLY)) - ufs_put_super_internal(sb); - - ubh_brelse_uspi (sbi->s_uspi); - kfree (sbi->s_uspi); - kfree (sbi); - sb->s_fs_info = NULL; - UFSD("EXIT\n"); - return; -} - - static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) { struct ufs_sb_private_info * uspi; -- cgit v1.2.3 From 9e9ad5f408889db6038a59b38ede29ff1ba9ef2f Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 12 Jul 2012 16:28:08 +0300 Subject: fs/ufs: get rid of write_super This patch makes UFS stop using the VFS '->write_super()' method along with the 's_dirt' superblock flag, because they are on their way out. The way we implement this is that we schedule a delay job instead relying on 's_dirt' and '->write_super()'. The whole "superblock write-out" VFS infrastructure is served by the 'sync_supers()' kernel thread, which wakes up every 5 (by default) seconds and writes out all dirty superblocks using the '->write_super()' call-back. But the problem with this thread is that it wastes power by waking up the system every 5 seconds, even if there are no diry superblocks, or there are no client file-systems which would need this (e.g., btrfs does not use '->write_super()'). So we want to kill it completely and thus, we need to make file-systems to stop using the '->write_super()' VFS service, and then remove it together with the kernel thread. Tested using fsstress from the LTP project. Signed-off-by: Artem Bityutskiy Signed-off-by: Al Viro --- fs/ufs/balloc.c | 8 ++++---- fs/ufs/ialloc.c | 4 ++-- fs/ufs/super.c | 40 ++++++++++++++++++++++++++++++---------- fs/ufs/ufs.h | 5 +++++ fs/ufs/ufs_fs.h | 1 + 5 files changed, 42 insertions(+), 16 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 42694e11c23..1b3e410bf33 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -116,7 +116,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); if (sb->s_flags & MS_SYNCHRONOUS) ubh_sync_block(UCPI_UBH(ucpi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); unlock_super (sb); UFSD("EXIT\n"); @@ -214,7 +214,7 @@ do_more: goto do_more; } - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); unlock_super (sb); UFSD("EXIT\n"); return; @@ -557,7 +557,7 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); if (sb->s_flags & MS_SYNCHRONOUS) ubh_sync_block(UCPI_UBH(ucpi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); @@ -677,7 +677,7 @@ succed: ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); if (sb->s_flags & MS_SYNCHRONOUS) ubh_sync_block(UCPI_UBH(ucpi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); result += cgno * uspi->s_fpg; UFSD("EXIT3, result %llu\n", (unsigned long long)result); diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 4ec5c1085a8..e84cbe21b98 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -116,7 +116,7 @@ void ufs_free_inode (struct inode * inode) if (sb->s_flags & MS_SYNCHRONOUS) ubh_sync_block(UCPI_UBH(ucpi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); unlock_super (sb); UFSD("EXIT\n"); } @@ -288,7 +288,7 @@ cg_found: ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); if (sb->s_flags & MS_SYNCHRONOUS) ubh_sync_block(UCPI_UBH(ucpi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); inode->i_ino = cg * uspi->s_ipg + bit; inode_init_owner(inode, dir, mode); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index ad56c6dffc6..444927e5706 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -302,7 +302,7 @@ void ufs_error (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH(uspi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); sb->s_flags |= MS_RDONLY; } va_start (args, fmt); @@ -334,7 +334,7 @@ void ufs_panic (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) { usb1->fs_clean = UFS_FSBAD; ubh_mark_buffer_dirty(USPI_UBH(uspi)); - sb->s_dirt = 1; + ufs_mark_sb_dirty(sb); } va_start (args, fmt); vsnprintf (error_buf, sizeof(error_buf), fmt, args); @@ -715,7 +715,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait) ufs_set_fs_state(sb, usb1, usb3, UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); ufs_put_cstotal(sb); - sb->s_dirt = 0; UFSD("EXIT\n"); unlock_super(sb); @@ -724,12 +723,31 @@ static int ufs_sync_fs(struct super_block *sb, int wait) return 0; } -static void ufs_write_super(struct super_block *sb) +static void delayed_sync_fs(struct work_struct *work) { - if (!(sb->s_flags & MS_RDONLY)) - ufs_sync_fs(sb, 1); - else - sb->s_dirt = 0; + struct ufs_sb_info *sbi; + + sbi = container_of(work, struct ufs_sb_info, sync_work.work); + + spin_lock(&sbi->work_lock); + sbi->work_queued = 0; + spin_unlock(&sbi->work_lock); + + ufs_sync_fs(sbi->sb, 1); +} + +void ufs_mark_sb_dirty(struct super_block *sb) +{ + struct ufs_sb_info *sbi = UFS_SB(sb); + unsigned long delay; + + spin_lock(&sbi->work_lock); + if (!sbi->work_queued) { + delay = msecs_to_jiffies(dirty_writeback_interval * 10); + queue_delayed_work(system_long_wq, &sbi->sync_work, delay); + sbi->work_queued = 1; + } + spin_unlock(&sbi->work_lock); } static void ufs_put_super(struct super_block *sb) @@ -740,6 +758,7 @@ static void ufs_put_super(struct super_block *sb) if (!(sb->s_flags & MS_RDONLY)) ufs_put_super_internal(sb); + cancel_delayed_work_sync(&sbi->sync_work); ubh_brelse_uspi (sbi->s_uspi); kfree (sbi->s_uspi); @@ -774,6 +793,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) if (!sbi) goto failed_nomem; sb->s_fs_info = sbi; + sbi->sb = sb; UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY)); @@ -785,6 +805,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) } #endif mutex_init(&sbi->mutex); + spin_lock_init(&sbi->work_lock); + INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); /* * Set default mount options * Parse mount options @@ -1304,7 +1326,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) ufs_set_fs_state(sb, usb1, usb3, UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); ubh_mark_buffer_dirty (USPI_UBH(uspi)); - sb->s_dirt = 0; sb->s_flags |= MS_RDONLY; } else { /* @@ -1454,7 +1475,6 @@ static const struct super_operations ufs_super_ops = { .write_inode = ufs_write_inode, .evict_inode = ufs_evict_inode, .put_super = ufs_put_super, - .write_super = ufs_write_super, .sync_fs = ufs_sync_fs, .statfs = ufs_statfs, .remount_fs = ufs_remount, diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 528750b7e70..343e6fc571e 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -20,6 +20,10 @@ struct ufs_sb_info { unsigned s_mount_opt; struct mutex mutex; struct task_struct *mutex_owner; + struct super_block *sb; + int work_queued; /* non-zero if the delayed work is queued */ + struct delayed_work sync_work; /* FS sync delayed work */ + spinlock_t work_lock; /* protects sync_work and work_queued */ }; struct ufs_inode_info { @@ -123,6 +127,7 @@ extern __printf(3, 4) void ufs_error(struct super_block *, const char *, const char *, ...); extern __printf(3, 4) void ufs_panic(struct super_block *, const char *, const char *, ...); +void ufs_mark_sb_dirty(struct super_block *sb); /* symlink.c */ extern const struct inode_operations ufs_fast_symlink_inode_operations; diff --git a/fs/ufs/ufs_fs.h b/fs/ufs/ufs_fs.h index 8aba544f9fa..0cbd5d340b6 100644 --- a/fs/ufs/ufs_fs.h +++ b/fs/ufs/ufs_fs.h @@ -34,6 +34,7 @@ #include #include #include +#include #include typedef __u64 __bitwise __fs64; -- cgit v1.2.3 From 72235465864d84cedb2d9f26f8e1de824ee20339 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 10 Feb 2012 12:21:22 -0800 Subject: userns: Convert the ufs filesystem to use kuid/kgid where appropriate Cc: Evgeniy Dushistov Acked-by: Serge Hallyn Signed-off-by: Eric W. Biederman --- fs/ufs/inode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index dd7c89d8a1c..eb6d0b7dc87 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -597,8 +597,8 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) /* * Linux now has 32-bit uid and gid, so we can support EFT. */ - inode->i_uid = ufs_get_inode_uid(sb, ufs_inode); - inode->i_gid = ufs_get_inode_gid(sb, ufs_inode); + i_uid_write(inode, ufs_get_inode_uid(sb, ufs_inode)); + i_gid_write(inode, ufs_get_inode_gid(sb, ufs_inode)); inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size); inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec); @@ -645,8 +645,8 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) /* * Linux now has 32-bit uid and gid, so we can support EFT. */ - inode->i_uid = fs32_to_cpu(sb, ufs2_inode->ui_uid); - inode->i_gid = fs32_to_cpu(sb, ufs2_inode->ui_gid); + i_uid_write(inode, fs32_to_cpu(sb, ufs2_inode->ui_uid)); + i_gid_write(inode, fs32_to_cpu(sb, ufs2_inode->ui_gid)); inode->i_size = fs64_to_cpu(sb, ufs2_inode->ui_size); inode->i_atime.tv_sec = fs64_to_cpu(sb, ufs2_inode->ui_atime); @@ -745,8 +745,8 @@ static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode) ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); - ufs_set_inode_uid(sb, ufs_inode, inode->i_uid); - ufs_set_inode_gid(sb, ufs_inode, inode->i_gid); + ufs_set_inode_uid(sb, ufs_inode, i_uid_read(inode)); + ufs_set_inode_gid(sb, ufs_inode, i_gid_read(inode)); ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); ufs_inode->ui_atime.tv_sec = cpu_to_fs32(sb, inode->i_atime.tv_sec); @@ -789,8 +789,8 @@ static void ufs2_update_inode(struct inode *inode, struct ufs2_inode *ufs_inode) ufs_inode->ui_mode = cpu_to_fs16(sb, inode->i_mode); ufs_inode->ui_nlink = cpu_to_fs16(sb, inode->i_nlink); - ufs_inode->ui_uid = cpu_to_fs32(sb, inode->i_uid); - ufs_inode->ui_gid = cpu_to_fs32(sb, inode->i_gid); + ufs_inode->ui_uid = cpu_to_fs32(sb, i_uid_read(inode)); + ufs_inode->ui_gid = cpu_to_fs32(sb, i_gid_read(inode)); ufs_inode->ui_size = cpu_to_fs64(sb, inode->i_size); ufs_inode->ui_atime = cpu_to_fs64(sb, inode->i_atime.tv_sec); -- cgit v1.2.3 From 8c0a85377048b64c880e76ec7368904fe46d0b94 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Wed, 26 Sep 2012 11:33:07 +1000 Subject: fs: push rcu_barrier() from deactivate_locked_super() to filesystems There's no reason to call rcu_barrier() on every deactivate_locked_super(). We only need to make sure that all delayed rcu free inodes are flushed before we destroy related cache. Removing rcu_barrier() from deactivate_locked_super() affects some fast paths. E.g. on my machine exit_group() of a last process in IPC namespace takes 0.07538s. rcu_barrier() takes 0.05188s of that time. Signed-off-by: Kirill A. Shutemov Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- fs/ufs/super.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/ufs') diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 444927e5706..f7cfecfe1ca 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1466,6 +1466,11 @@ static int init_inodecache(void) static void destroy_inodecache(void) { + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); kmem_cache_destroy(ufs_inode_cachep); } -- cgit v1.2.3 From b6963327e0521e682c2fffd018574251d3c22b41 Mon Sep 17 00:00:00 2001 From: Marco Stornelli Date: Sat, 6 Oct 2012 12:42:28 +0200 Subject: ufs: drop lock/unlock super Removed lock/unlock super. Added a new private s_lock mutex. Signed-off-by: Marco Stornelli Signed-off-by: Al Viro --- fs/ufs/balloc.c | 30 +++++++++++++++--------------- fs/ufs/ialloc.c | 16 ++++++++-------- fs/ufs/super.c | 21 +++++++++++---------- fs/ufs/ufs.h | 1 + 4 files changed, 35 insertions(+), 33 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 1b3e410bf33..a7ea492ae66 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -54,7 +54,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) if (ufs_fragnum(fragment) + count > uspi->s_fpg) ufs_error (sb, "ufs_free_fragments", "internal error"); - lock_super(sb); + mutex_lock(&UFS_SB(sb)->s_lock); cgno = ufs_dtog(uspi, fragment); bit = ufs_dtogd(uspi, fragment); @@ -118,12 +118,12 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) ubh_sync_block(UCPI_UBH(ucpi)); ufs_mark_sb_dirty(sb); - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT\n"); return; failed: - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT (FAILED)\n"); return; } @@ -155,7 +155,7 @@ void ufs_free_blocks(struct inode *inode, u64 fragment, unsigned count) goto failed; } - lock_super(sb); + mutex_lock(&UFS_SB(sb)->s_lock); do_more: overflow = 0; @@ -215,12 +215,12 @@ do_more: } ufs_mark_sb_dirty(sb); - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT\n"); return; failed_unlock: - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); failed: UFSD("EXIT (FAILED)\n"); return; @@ -361,7 +361,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, usb1 = ubh_get_usb_first(uspi); *err = -ENOSPC; - lock_super (sb); + mutex_lock(&UFS_SB(sb)->s_lock); tmp = ufs_data_ptr_to_cpu(sb, p); if (count + ufs_fragnum(fragment) > uspi->s_fpb) { @@ -382,19 +382,19 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, "fragment %llu, tmp %llu\n", (unsigned long long)fragment, (unsigned long long)tmp); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); return INVBLOCK; } if (fragment < UFS_I(inode)->i_lastfrag) { UFSD("EXIT (ALREADY ALLOCATED)\n"); - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); return 0; } } else { if (tmp) { UFSD("EXIT (ALREADY ALLOCATED)\n"); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); return 0; } } @@ -403,7 +403,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, * There is not enough space for user on the device */ if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) { - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT (FAILED)\n"); return 0; } @@ -428,7 +428,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, ufs_clear_frags(inode, result + oldcount, newcount - oldcount, locked_page != NULL); } - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT, result %llu\n", (unsigned long long)result); return result; } @@ -443,7 +443,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, fragment + count); ufs_clear_frags(inode, result + oldcount, newcount - oldcount, locked_page != NULL); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT, result %llu\n", (unsigned long long)result); return result; } @@ -481,7 +481,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, *err = 0; UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag, fragment + count); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); if (newcount < request) ufs_free_fragments (inode, result + newcount, request - newcount); ufs_free_fragments (inode, tmp, oldcount); @@ -489,7 +489,7 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment, return result; } - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT (FAILED)\n"); return 0; } diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index e84cbe21b98..d0426d74817 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -71,11 +71,11 @@ void ufs_free_inode (struct inode * inode) ino = inode->i_ino; - lock_super (sb); + mutex_lock(&UFS_SB(sb)->s_lock); if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) { ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino); - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); return; } @@ -83,7 +83,7 @@ void ufs_free_inode (struct inode * inode) bit = ufs_inotocgoff (ino); ucpi = ufs_load_cylinder (sb, cg); if (!ucpi) { - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); return; } ucg = ubh_get_ucg(UCPI_UBH(ucpi)); @@ -117,7 +117,7 @@ void ufs_free_inode (struct inode * inode) ubh_sync_block(UCPI_UBH(ucpi)); ufs_mark_sb_dirty(sb); - unlock_super (sb); + mutex_unlock(&UFS_SB(sb)->s_lock); UFSD("EXIT\n"); } @@ -197,7 +197,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode) uspi = sbi->s_uspi; usb1 = ubh_get_usb_first(uspi); - lock_super (sb); + mutex_lock(&sbi->s_lock); /* * Try to place the inode in its parent directory @@ -333,20 +333,20 @@ cg_found: brelse(bh); } - unlock_super (sb); + mutex_unlock(&sbi->s_lock); UFSD("allocating inode %lu\n", inode->i_ino); UFSD("EXIT\n"); return inode; fail_remove_inode: - unlock_super(sb); + mutex_unlock(&sbi->s_lock); clear_nlink(inode); iput(inode); UFSD("EXIT (FAILED): err %d\n", err); return ERR_PTR(err); failed: - unlock_super (sb); + mutex_unlock(&sbi->s_lock); make_bad_inode(inode); iput (inode); UFSD("EXIT (FAILED): err %d\n", err); diff --git a/fs/ufs/super.c b/fs/ufs/super.c index f7cfecfe1ca..dc8e3a861d0 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -699,7 +699,7 @@ static int ufs_sync_fs(struct super_block *sb, int wait) unsigned flags; lock_ufs(sb); - lock_super(sb); + mutex_lock(&UFS_SB(sb)->s_lock); UFSD("ENTER\n"); @@ -717,7 +717,7 @@ static int ufs_sync_fs(struct super_block *sb, int wait) ufs_put_cstotal(sb); UFSD("EXIT\n"); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return 0; @@ -805,6 +805,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) } #endif mutex_init(&sbi->mutex); + mutex_init(&sbi->s_lock); spin_lock_init(&sbi->work_lock); INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); /* @@ -1280,7 +1281,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) unsigned flags; lock_ufs(sb); - lock_super(sb); + mutex_lock(&UFS_SB(sb)->s_lock); uspi = UFS_SB(sb)->s_uspi; flags = UFS_SB(sb)->s_flags; usb1 = ubh_get_usb_first(uspi); @@ -1294,7 +1295,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) new_mount_opt = 0; ufs_set_opt (new_mount_opt, ONERROR_LOCK); if (!ufs_parse_options (data, &new_mount_opt)) { - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return -EINVAL; } @@ -1302,14 +1303,14 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) new_mount_opt |= ufstype; } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) { printk("ufstype can't be changed during remount\n"); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return -EINVAL; } if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { UFS_SB(sb)->s_mount_opt = new_mount_opt; - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return 0; } @@ -1334,7 +1335,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) #ifndef CONFIG_UFS_FS_WRITE printk("ufs was compiled with read-only support, " "can't be mounted as read-write\n"); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return -EINVAL; #else @@ -1344,13 +1345,13 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) ufstype != UFS_MOUNT_UFSTYPE_SUNx86 && ufstype != UFS_MOUNT_UFSTYPE_UFS2) { printk("this ufstype is read-only supported\n"); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return -EINVAL; } if (!ufs_read_cylinder_structures(sb)) { printk("failed during remounting\n"); - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return -EPERM; } @@ -1358,7 +1359,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) #endif } UFS_SB(sb)->s_mount_opt = new_mount_opt; - unlock_super(sb); + mutex_unlock(&UFS_SB(sb)->s_lock); unlock_ufs(sb); return 0; } diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 343e6fc571e..ff2c15ab81a 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -24,6 +24,7 @@ struct ufs_sb_info { int work_queued; /* non-zero if the delayed work is queued */ struct delayed_work sync_work; /* FS sync delayed work */ spinlock_t work_lock; /* protects sync_work and work_queued */ + struct mutex s_lock; }; struct ufs_inode_info { -- cgit v1.2.3 From 83f6e3710a932d400100767ad445a4bd9476e083 Mon Sep 17 00:00:00 2001 From: Marco Stornelli Date: Sat, 15 Dec 2012 11:45:14 +0100 Subject: ufs: drop vmtruncate Removed vmtruncate Signed-off-by: Marco Stornelli Signed-off-by: Al Viro --- fs/ufs/inode.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'fs/ufs') diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index eb6d0b7dc87..ff24e4449ec 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -526,6 +526,14 @@ int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len) return __block_write_begin(page, pos, len, ufs_getfrag_block); } +static void ufs_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > inode->i_size) + truncate_pagecache(inode, to, inode->i_size); +} + static int ufs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) @@ -534,11 +542,8 @@ static int ufs_write_begin(struct file *file, struct address_space *mapping, ret = block_write_begin(mapping, pos, len, flags, pagep, ufs_getfrag_block); - if (unlikely(ret)) { - loff_t isize = mapping->host->i_size; - if (pos + len > isize) - vmtruncate(mapping->host, isize); - } + if (unlikely(ret)) + ufs_write_failed(mapping, pos + len); return ret; } -- cgit v1.2.3