From 63fe5162de4051bd7ce02d24932d592b8d4134f5 Mon Sep 17 00:00:00 2001 From: Patrick Caulfield Date: Wed, 26 Jun 2002 09:09:41 +0000 Subject: [PATCH] VFS Lock patch for Linux 2.4.19-rc1 --- patches/misc/linux-2.4.19-VFS-lock.patch | 246 +++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 patches/misc/linux-2.4.19-VFS-lock.patch diff --git a/patches/misc/linux-2.4.19-VFS-lock.patch b/patches/misc/linux-2.4.19-VFS-lock.patch new file mode 100644 index 0000000..8ae5dd2 --- /dev/null +++ b/patches/misc/linux-2.4.19-VFS-lock.patch @@ -0,0 +1,246 @@ +diff -Nru a/drivers/md/lvm.c b/drivers/md/lvm.c +--- a/drivers/md/lvm.c Wed May 22 10:43:49 2002 ++++ b/drivers/md/lvm.c Wed May 22 10:43:49 2002 +@@ -223,9 +223,6 @@ + #define DEVICE_OFF(device) + #define LOCAL_END_REQUEST + +-/* lvm_do_lv_create calls fsync_dev_lockfs()/unlockfs() */ +-/* #define LVM_VFS_ENHANCEMENT */ +- + #include + #include + #include +@@ -2178,12 +2175,8 @@ + if (lv_ptr->lv_access & LV_SNAPSHOT) { + lv_t *org = lv_ptr->lv_snapshot_org, *last; + +- /* sync the original logical volume */ +- fsync_dev(org->lv_dev); +-#ifdef LVM_VFS_ENHANCEMENT + /* VFS function call to sync and lock the filesystem */ + fsync_dev_lockfs(org->lv_dev); +-#endif + + down_write(&org->lv_lock); + org->lv_access |= LV_SNAPSHOT_ORG; +@@ -2209,11 +2202,9 @@ + else + set_device_ro(lv_ptr->lv_dev, 1); + +-#ifdef LVM_VFS_ENHANCEMENT + /* VFS function call to unlock the filesystem */ + if (lv_ptr->lv_access & LV_SNAPSHOT) + unlockfs(lv_ptr->lv_snapshot_org->lv_dev); +-#endif + + lvm_gendisk.part[MINOR(lv_ptr->lv_dev)].de = + lvm_fs_create_lv(vg_ptr, lv_ptr); +diff -Nru a/fs/buffer.c b/fs/buffer.c +--- a/fs/buffer.c Wed May 22 10:43:49 2002 ++++ b/fs/buffer.c Wed May 22 10:43:49 2002 +@@ -363,6 +363,34 @@ + fsync_dev(dev); + } + ++int fsync_dev_lockfs(kdev_t dev) ++{ ++ /* you are not allowed to try locking all the filesystems ++ ** on the system, your chances of getting through without ++ ** total deadlock are slim to none. ++ */ ++ if (!dev) ++ return fsync_dev(dev) ; ++ ++ sync_buffers(dev, 0); ++ ++ lock_kernel(); ++ /* note, the FS might need to start transactions to ++ ** sync the inodes, or the quota, no locking until ++ ** after these are done ++ */ ++ sync_inodes(dev); ++ DQUOT_SYNC(dev); ++ /* if inodes or quotas could be dirtied during the ++ ** sync_supers_lockfs call, the FS is responsible for getting ++ ** them on disk, without deadlocking against the lock ++ */ ++ sync_supers_lockfs(dev) ; ++ unlock_kernel(); ++ ++ return sync_buffers(dev, 1) ; ++} ++ + asmlinkage long sys_sync(void) + { + fsync_dev(0); +diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c +--- a/fs/reiserfs/super.c Wed May 22 10:43:49 2002 ++++ b/fs/reiserfs/super.c Wed May 22 10:43:49 2002 +@@ -66,7 +66,7 @@ + reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); + journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB (s)); + reiserfs_block_writes(&th) ; +- journal_end(&th, s, 1) ; ++ journal_end_sync(&th, s, 1) ; + } + s->s_dirt = dirty; + unlock_kernel() ; +diff -Nru a/fs/super.c b/fs/super.c +--- a/fs/super.c Wed May 22 10:43:49 2002 ++++ b/fs/super.c Wed May 22 10:43:49 2002 +@@ -37,6 +37,13 @@ + LIST_HEAD(super_blocks); + spinlock_t sb_lock = SPIN_LOCK_UNLOCKED; + ++/* ++ * lock/unlockfs grab a read lock on s_umount, but you need this lock to ++ * make sure no lockfs runs are in progress before inserting/removing ++ * supers from the list. ++ */ ++static DECLARE_MUTEX(lockfs_sem); ++ + /* + * Handling of filesystem drivers list. + * Rules: +@@ -431,6 +438,19 @@ + put_super(sb); + } + ++static void write_super_lockfs(struct super_block *sb) ++{ ++ lock_super(sb); ++ if (sb->s_root && sb->s_op) { ++ if (sb->s_dirt && sb->s_op->write_super) ++ sb->s_op->write_super(sb); ++ if (sb->s_op->write_super_lockfs) { ++ sb->s_op->write_super_lockfs(sb); ++ } ++ } ++ unlock_super(sb); ++} ++ + static inline void write_super(struct super_block *sb) + { + lock_super(sb); +@@ -474,6 +494,39 @@ + spin_unlock(&sb_lock); + } + ++/* ++ * Note: don't check the dirty flag before waiting, we want the lock ++ * to happen every time this is called. dev must be non-zero ++ */ ++void sync_supers_lockfs(kdev_t dev) ++{ ++ struct super_block * sb; ++ ++ down(&lockfs_sem) ; ++ if (dev) { ++ sb = get_super(dev); ++ if (sb) { ++ write_super_lockfs(sb); ++ drop_super(sb); ++ } ++ } ++} ++ ++void unlockfs(kdev_t dev) ++{ ++ struct super_block * sb; ++ ++ if (dev) { ++ sb = get_super(dev); ++ if (sb) { ++ if (sb->s_op && sb->s_op->unlockfs) ++ sb->s_op->unlockfs(sb) ; ++ drop_super(sb); ++ } ++ } ++ up(&lockfs_sem) ; ++} ++ + /** + * get_super - get the superblock of a device + * @dev: device to get the superblock for +@@ -694,6 +747,7 @@ + goto out1; + + error = -EBUSY; ++ down(&lockfs_sem); + restart: + spin_lock(&sb_lock); + +@@ -705,6 +759,7 @@ + ((flags ^ old->s_flags) & MS_RDONLY)) { + spin_unlock(&sb_lock); + destroy_super(s); ++ up(&lockfs_sem); + goto out1; + } + if (!grab_super(old)) +@@ -712,12 +767,14 @@ + destroy_super(s); + blkdev_put(bdev, BDEV_FS); + path_release(&nd); ++ up(&lockfs_sem); + return old; + } + s->s_dev = dev; + s->s_bdev = bdev; + s->s_flags = flags; + insert_super(s, fs_type); ++ up(&lockfs_sem); + if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) + goto Einval; + s->s_flags |= MS_ACTIVE; +@@ -825,7 +882,10 @@ + if (!deactivate_super(sb)) + return; + ++ down(&lockfs_sem); + down_write(&sb->s_umount); ++ up(&lockfs_sem); ++ + sb->s_root = NULL; + /* Need to clean after the sucker */ + if (fs->fs_flags & FS_LITTER) +diff -Nru a/include/linux/fs.h b/include/linux/fs.h +--- a/include/linux/fs.h Wed May 22 10:43:49 2002 ++++ b/include/linux/fs.h Wed May 22 10:43:49 2002 +@@ -1218,6 +1218,7 @@ + extern int sync_buffers(kdev_t, int); + extern void sync_dev(kdev_t); + extern int fsync_dev(kdev_t); ++extern int fsync_dev_lockfs(kdev_t); + extern int fsync_super(struct super_block *); + extern int fsync_no_super(kdev_t); + extern void sync_inodes_sb(struct super_block *); +@@ -1234,6 +1235,8 @@ + extern int filemap_fdatasync(struct address_space *); + extern int filemap_fdatawait(struct address_space *); + extern void sync_supers(kdev_t); ++extern void sync_supers_lockfs(kdev_t); ++extern void unlockfs(kdev_t); + extern int bmap(struct inode *, int); + extern int notify_change(struct dentry *, struct iattr *); + extern int permission(struct inode *, int); +diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c +--- a/kernel/ksyms.c Wed May 22 10:43:49 2002 ++++ b/kernel/ksyms.c Wed May 22 10:43:49 2002 +@@ -180,6 +180,8 @@ + EXPORT_SYMBOL(invalidate_inode_pages); + EXPORT_SYMBOL(truncate_inode_pages); + EXPORT_SYMBOL(fsync_dev); ++EXPORT_SYMBOL(fsync_dev_lockfs); ++EXPORT_SYMBOL(unlockfs); + EXPORT_SYMBOL(fsync_no_super); + EXPORT_SYMBOL(permission); + EXPORT_SYMBOL(vfs_permission); + + +_______________________________________________ +lvm-devel mailing list +lvm-devel@sistina.com +http://lists.sistina.com/mailman/listinfo/lvm-devel + -- 2.43.5