>From: Mike Montour <mmontour@xxxxxxxxxx>
>I am developing an application using XFS/DMAPI on Linux 2.4.
>
>My application registers for DM_EVENT_READ and DM_EVENT_WRITE events
>on a file, then calls dm_punch_hole() on that file. The event handlers
>use dm_write_invis() to re-populate the file data on demand (including
>re-populating all of the original file data before allowing the
>first write operation to continue).
>
>This works fine for READ events. However, whenever I get a WRITE
>event, the call to dm_write_invis() blocks my program. If I kill
>(ctrl-C) the application that triggered the WRITE event, then the
>dm_write_invis() call returns successfully and my program continues.
Hmm, I guess I'd better dust off my email folders once in a while. Sorry to
respond so late.
I'm currently testing the following patch, which should alleviate the hang.
The problem is that a thread was able to get into the dmapi queues while
holding a resource (i_sem, in this case).
Dean
===========================================================================
dmapi/dmapi_xfs.c
===========================================================================
--- /usr/tmp/TmpDir.4852600-0/dmapi/dmapi_xfs.c_1.28 Wed Feb 4 16:21:21 2004
+++ dmapi/dmapi_xfs.c Wed Feb 4 15:38:34 2004
@@ -136,6 +136,7 @@
bhv_desc_t *bdp;
xfs_inode_t *ip;
uint16_t dmstate;
+ struct inode *inode = LINVFS_GET_IP(vp);
XFS_BHV_LOOKUP(vp, bdp);
ip = XFS_BHVTOI(bdp);
@@ -143,8 +144,24 @@
dmstate = ip->i_iocore.io_dmstate;
if (locktype)
xfs_rwunlock(bdp, *locktype);
+
+ if (flags & DM_FLAGS_ISEM)
+ up(&inode->i_sem);
+#ifdef DM_FLAGS_IALLOCSEM
+ else if (flags & DM_FLAGS_IALLOCSEM)
+ do_up_read(&inode->i_alloc_sem);
+#endif
+
error = dm_send_data_event(event, vp, DM_RIGHT_NULL,
offset, length, flags);
+
+ if (flags & DM_FLAGS_ISEM)
+ down(&inode->i_sem);
+#ifdef DM_FLAGS_IALLOCSEM
+ else if (flags & DM_FLAGS_IALLOCSEM)
+ do_down_read(&inode->i_alloc_sem);
+#endif
+
if (locktype)
xfs_rwlock(bdp, *locktype);
} while (!error && (ip->i_iocore.io_dmstate != dmstate));
===========================================================================
linux-2.4/xfs_lrw.c
===========================================================================
--- /usr/tmp/TmpDir.4852600-0/linux-2.4/xfs_lrw.c_1.211 Wed Feb 4 16:21:21 2004
+++ linux-2.4/xfs_lrw.c Wed Feb 4 15:11:19 2004
@@ -311,9 +311,10 @@
!(ioflags & IO_INVIS)) {
int error;
vrwlock_t locktype = VRWLOCK_READ;
+ int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG(ioflags);
error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
*offset, size,
- FILP_DELAY_FLAG(file), &locktype);
+ dmflags, &locktype);
if (error) {
if (!(ioflags & IO_ISLOCKED))
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
@@ -649,11 +650,12 @@
if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
!(ioflags & IO_INVIS) && !eventsent)) {
loff_t savedsize = *offset;
+ int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG(ioflags);
xfs_iunlock(xip, XFS_ILOCK_EXCL);
error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
*offset, size,
- FILP_DELAY_FLAG(file), &locktype);
+ dmflags, &locktype);
if (error) {
if (iolock) xfs_iunlock(xip, iolock);
return -error;
===========================================================================
linux-2.6/xfs_lrw.c
===========================================================================
--- /usr/tmp/TmpDir.4852600-0/linux-2.6/xfs_lrw.c_1.202 Wed Feb 4 16:21:21 2004
+++ linux-2.6/xfs_lrw.c Wed Feb 4 15:11:19 2004
@@ -738,11 +738,12 @@
if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
!(ioflags & IO_INVIS) && !eventsent)) {
loff_t savedsize = *offset;
+ int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG(ioflags);
xfs_iunlock(xip, XFS_ILOCK_EXCL);
error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
*offset, size,
- FILP_DELAY_FLAG(file), &locktype);
+ dmflags, &locktype);
if (error) {
if (iolock) xfs_iunlock(xip, iolock);
return -error;
===========================================================================
xfs_dmapi.h
===========================================================================
--- /usr/tmp/TmpDir.4852600-0/xfs_dmapi.h_1.43 Wed Feb 4 16:21:21 2004
+++ xfs_dmapi.h Wed Feb 4 16:15:03 2004
@@ -165,6 +165,24 @@
#define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after
dm_pending() */
#define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */
+#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
+/* i_alloc_sem was added in 2.4.22-pre1 */
+#define DM_FLAGS_IALLOCSEM 0x010 /* thread holds i_alloc_sem */
+#endif
+#endif
+
+/*
+ * Based on IO_ISDIRECT, decide which i_ flag is set.
+ */
+#ifdef DM_FLAGS_IALLOCSEM
+#define DM_SEM_FLAG(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+ DM_FLAGS_IALLOCSEM : DM_FLAGS_ISEM)
+#else
+#define DM_SEM_FLAG(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+ 0 : DM_FLAGS_ISEM)
+#endif
/*
* Macros to turn caller specified delay/block flags into
|