--- linux.old/fs/xfs/xfs_log.c Wed Mar 20 04:51:25 2002 +++ linux/fs/xfs/xfs_log.c Sat Mar 30 00:38:58 2002 @@ -324,6 +324,11 @@ int rval; xlog_t *log = mp->m_log; + if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) { + printk("ignoring xfs_log_force on a read-only filesystem\n"); + return 0; + } + #if defined(DEBUG) || defined(XLOG_NOLOG) if (! xlog_debug && xlog_devt == log->l_dev) return 0; --- linux.old/fs/xfs/xfs_mount.c Sat Mar 9 03:21:26 2002 +++ linux/fs/xfs/xfs_mount.c Sat Mar 30 00:39:39 2002 @@ -1680,6 +1680,7 @@ int level) { int s = mutex_spinlock(&mp->m_freeze_lock); + unsigned long flags; mp->m_frozen = level; mutex_spinunlock(&mp->m_freeze_lock, s); @@ -1688,13 +1689,27 @@ while (atomic_read(&mp->m_active_trans) > 0) delay(100); } + + flags = current->flags; + current->flags |= PF_NO_FREEZE; + + /* make sure the log is written after we freeze */ + xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC); + + if (! (flags & PF_NO_FREEZE)) { + current->flags &= ~PF_NO_FREEZE; + } } void xfs_finish_freeze( xfs_mount_t *mp) { - int s = mutex_spinlock(&mp->m_freeze_lock); + int s; + + if (current->flags & PF_NO_FREEZE) return; + + s = mutex_spinlock(&mp->m_freeze_lock); if (mp->m_frozen) { mp->m_frozen = 0; @@ -1713,6 +1728,10 @@ { int s; int do_lock = 0; + + /* some processes must not freeze - eg. a lvcreate or kupdated, otherwise + lvcreate locks solid as it tries to flush blocks, and that gets here */ + if (current->flags & PF_NO_FREEZE) return; if (!mp->m_frozen) { if (level == XFS_FREEZE_TRANS) --- linux.old/fs/buffer.c Sat Mar 30 00:28:28 2002 +++ linux/fs/buffer.c Sat Mar 30 00:40:54 2002 @@ -392,6 +392,14 @@ int fsync_dev(kdev_t dev) { + int ret; + unsigned long flags; + + flags = current->flags; + /* we set this flag to prevent the XFS pagebuf code causing a deadlock + during a sync - a frozen filesystem should freeze only new IO, not + existing data waiting to be flushed */ + current->flags |= PF_NO_FREEZE; sync_buffers(dev, 0); lock_kernel(); @@ -400,7 +408,13 @@ sync_supers(dev); unlock_kernel(); - return sync_buffers(dev, 1); + ret = sync_buffers(dev, 1); + + if (! (flags & PF_NO_FREEZE)) { + current->flags &= ~PF_NO_FREEZE; + } + + return ret; } /* @@ -3038,6 +3052,9 @@ siginitsetinv(¤t->blocked, sigmask(SIGCONT) | sigmask(SIGSTOP)); recalc_sigpending(tsk); spin_unlock_irq(&tsk->sigmask_lock); + + /* kupdated can also do IO of old blocks on a frozen filesystem */ + current->flags |= PF_NO_FREEZE; complete((struct completion *)startup); --- linux.old/include/linux/sched.h Sat Mar 30 00:30:23 2002 +++ linux/include/linux/sched.h Fri Mar 29 23:34:13 2002 @@ -428,6 +428,7 @@ #define PF_FREE_PAGES 0x00002000 /* per process page freeing */ #define PF_NOIO 0x00004000 /* avoid generating further I/O */ #define PF_FSTRANS 0x00008000 /* inside a filesystem transaction */ +#define PF_NO_FREEZE 0x01000000 /* ignore fs freeze flag */ #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */