[Ocfs2-commits] zab commits r2631 - in branches/locking-changes: .
Documentation Documentation/filesystems fs/ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon Oct 3 19:21:13 CDT 2005
Author: zab
Date: 2005-10-03 19:21:10 -0500 (Mon, 03 Oct 2005)
New Revision: 2631
Added:
branches/locking-changes/Documentation/
branches/locking-changes/Documentation/filesystems/
branches/locking-changes/Documentation/filesystems/ocfs2.txt
Modified:
branches/locking-changes/fs/ocfs2/aops.c
branches/locking-changes/fs/ocfs2/aops.h
branches/locking-changes/fs/ocfs2/file.c
branches/locking-changes/fs/ocfs2/mmap.c
Log:
Move locking around to avoid file io -> nopage -> readpage deadlocking
o push locking into readpage and take it out of file read and nopage
o push locking into prepare_write and take it out of file write
o take a new file read/write serializing lock
o release rw lock in dio->end_io so pending o_direct is safe wrt truncate
o sendfile relies on readpage locking, just use generic method
o add a little (incomplete) doc that describes lock ordering
Added: branches/locking-changes/Documentation/filesystems/ocfs2.txt
===================================================================
--- branches/locking-changes/Documentation/filesystems/ocfs2.txt 2005-10-03 23:13:24 UTC (rev 2630)
+++ branches/locking-changes/Documentation/filesystems/ocfs2.txt 2005-10-04 00:21:10 UTC (rev 2631)
@@ -0,0 +1,121 @@
+
+For now this just documents locking ordering. The intent is to have a
+dense enough markup that one can visualize an entire path in a reasonably
+sized terminal. So:
+
+ ( - lock
+ ) - unlock
+ () - lock and unlock without anything interesting in between
+ + - descending into another function
+
+worst case buffered file write (extending, buf from mmaped ocfs2)
++ ocfs2_file_aio_write
+ ( i_sem
+ ( rw_lock
+ ( meta_lock
+ + ocfs2_extend_allocation
+ () ip_alloc_sem
+ ) meta_lock
+ + generic_file_aio_write_nolock
+ + ocfs2_prepare_write
+ ( meta_lock
+ ( ip_alloc_sem
+ ) ip_alloc_sem
+ ) meta_lock
+ + ocfs2_nopage
+ + filemap_nopage
+ + ocfs2_readpage
+ ( meta_lock
+ ( ip_alloc_sem
+ ( data_lock
+ ) data_lock
+ ) ip_alloc_sem
+ ) meta_lock
+ + ocfs2_commit_write
+ ( meta_lock
+ ( data_lock
+ ) data_lock
+ ) meta_lock
+ ) rw_lock
+ ) i_sem
+
+O_DIRECT file write:
++ ocfs2_file_aio_write
+ ( i_sem
+ ( rw_lock
+ () meta_lock
+ + __blkdev_direct_IO
+ ( i_alloc_sem
+ + ocfs2_direct_io_get_blocks
+ ( meta_lock
+ ( ip_alloc_sem
+ ) ip_alloc_sem
+ ) meta_lock
+ ) i_sem
++ dio_complete
+ ) i_alloc_sem
+ + ocfs2_dio_end_io
+ ) rw_lock
+
+buffered file read (nopage when buf is mmaped):
++ ocfs2_file_aio_read
+ + generic_file_aio_read
+ + ocfs2_readpage
+ ( meta_lock
+ ( ip_alloc_sem
+ ( data_lock
+ ) data_lock
+ ) ip_alloc_sem
+ ) meta_lock
+ + ocfs2_nopage
+ + filemap_nopage
+ + ocfs2_readpage
+ ( meta_lock
+ ( ip_alloc_sem
+ ( data_lock
+ ) data_lock
+ ) ip_alloc_sem
+ ) meta_lock
+
+O_DIRECT file read:
++ ocfs2_file_aio_read
+ + __blkdev_direct_IO
+ () i_sem
+ ( i_alloc_sem
+ + ocfs2_direct_io_get_blocks
+ ( meta_lock
+ ( ip_alloc_sem
+ ) ip_alloc_sem
+ ) meta_lock
++ dio_complete
+ ) i_alloc_sem
+ + ocfs2_dio_end_io
+ ) rw_lock
+
+truncate:
++ do_truncate
+ ( i_sem
+ + notify_change
+ ( i_alloc_sem
+ + ocfs2_setattr
+ ( meta_lock
+ + ocfs2_truncate_file
+ () data_lock
+ ) meta_lock
+ ) i_alloc_sem
+ ) i_sem
+
+readpage: (via sendfile, sys_readahead, fault->nopage)
++ ocfs2_readpage
+ ( meta_lock
+ ( ip_alloc_sem
+ ( data_lock
+ ) data_lock
+ ) ip_alloc_sem
+ ) meta_lock
+
+.. make this prettier ..
+
+-- Locks and what they cover --
+
+
Modified: branches/locking-changes/fs/ocfs2/aops.c
===================================================================
--- branches/locking-changes/fs/ocfs2/aops.c 2005-10-03 23:13:24 UTC (rev 2630)
+++ branches/locking-changes/fs/ocfs2/aops.c 2005-10-04 00:21:10 UTC (rev 2631)
@@ -31,11 +31,13 @@
#include "ocfs2.h"
#include "alloc.h"
+#include "aops.h"
#include "dlmglue.h"
#include "extent_map.h"
#include "file.h"
#include "inode.h"
#include "journal.h"
+#include "super.h"
#include "symlink.h"
#include "buffer_head_io.h"
@@ -190,14 +192,56 @@
static int ocfs2_readpage(struct file *file, struct page *page)
{
+ struct inode *inode = page->mapping->host;
+ loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT;
int ret;
mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0));
+ ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ /*
+ * i_size might have just been updated as we grabed the meta lock. We
+ * might now be discovering a truncate that hit on another node.
+ * block_read_full_page->get_block freaks out if it is asked to read
+ * beyond the end of a file, so we check here. Callers
+ * (generic_file_read, fault->nopage) are clever enough to check i_size
+ * and notice that the page they just read isn't needed.
+ *
+ * XXX sys_readahead() seems to get that wrong?
+ */
+ if (i_size_read(inode) >= start) {
+ char *addr = kmap(page);
+ memset(addr, 0, PAGE_SIZE);
+ flush_dcache_page(page);
+ kunmap(page);
+ SetPageUptodate(page);
+ unlock_page(page);
+ ret = 0;
+ goto out_alloc;
+ }
+
+ ret = ocfs2_data_lock(inode, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_alloc;
+ }
+
ret = block_read_full_page(page, ocfs2_get_block);
+
+ ocfs2_data_unlock(inode, 0);
+out_alloc:
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
+ ocfs2_meta_unlock(inode, 0);
+out:
mlog_exit(ret);
-
return ret;
}
@@ -218,17 +262,34 @@
return ret;
}
+/*
+ * ocfs2_prepare_write() can be an outer-most ocfs2 call when it is called
+ * from loopback. It must be able to perform its own locking around
+ * ocfs2_get_block().
+ */
int ocfs2_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
+ struct inode *inode = page->mapping->host;
int ret;
mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
+ ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
ret = block_prepare_write(page, from, to, ocfs2_get_block);
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ocfs2_meta_unlock(inode, 0);
+out:
mlog_exit(ret);
-
return ret;
}
@@ -518,6 +579,25 @@
return ret;
}
+/*
+ * ocfs2_dio_end_io is called by the dio core when a dio is finished. We're
+ * particularly interested in the aio/dio case. Like the core uses
+ * i_alloc_sem, we use the rw_lock DLM lock to protect io on one node from
+ * truncation on another.
+ */
+static void ocfs2_dio_end_io(struct kiocb *iocb,
+ loff_t offset,
+ ssize_t bytes,
+ void *private)
+{
+ struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+
+ /* this io's submitter should not have unlocked this before we could */
+ BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
+ ocfs2_iocb_clear_rw_locked(iocb);
+ ocfs2_rw_unlock(inode, 0);
+}
+
static ssize_t ocfs2_direct_IO(int rw,
struct kiocb *iocb,
const struct iovec *iov,
@@ -531,7 +611,7 @@
mlog_entry_void();
ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, ocfs2_direct_IO_get_blocks,
- NULL);
+ ocfs2_dio_end_io);
mlog_exit(ret);
return ret;
}
Modified: branches/locking-changes/fs/ocfs2/aops.h
===================================================================
--- branches/locking-changes/fs/ocfs2/aops.h 2005-10-03 23:13:24 UTC (rev 2630)
+++ branches/locking-changes/fs/ocfs2/aops.h 2005-10-04 00:21:10 UTC (rev 2631)
@@ -30,4 +30,12 @@
unsigned from,
unsigned to);
+/* all ocfs2_dio_end_io()'s fault */
+#define ocfs2_iocb_is_rw_locked(iocb) \
+ test_bit(0, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_set_rw_locked(iocb) \
+ set_bit(0, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_clear_rw_locked(iocb) \
+ clear_bit(0, (unsigned long *)&iocb->private)
+
#endif /* OCFS2_FILE_H */
Modified: branches/locking-changes/fs/ocfs2/file.c
===================================================================
--- branches/locking-changes/fs/ocfs2/file.c 2005-10-03 23:13:24 UTC (rev 2630)
+++ branches/locking-changes/fs/ocfs2/file.c 2005-10-04 00:21:10 UTC (rev 2631)
@@ -875,13 +875,14 @@
{
struct iovec local_iov = { .iov_base = (void __user *)buf,
.iov_len = count };
- int ret, level;
+ int ret, rw_level = -1, meta_level = -1;
u32 clusters;
- ocfs2_super *osb = NULL;
struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
- int do_direct = 0;
loff_t newsize, saved_pos;
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+#endif
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
(unsigned int)count,
@@ -889,29 +890,46 @@
filp->f_dentry->d_name.name);
/* happy write of zero bytes */
- if (count == 0) {
- ret = 0;
- goto out;
- }
+ if (count == 0)
+ return 0;
if (!inode) {
mlog(0, "bad inode\n");
- ret = -EIO;
- goto out;
+ return -EIO;
}
- osb = OCFS2_SB(inode->i_sb);
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ /* ugh, work around some applications which open everything O_DIRECT +
+ * O_APPEND and really don't mean to use O_DIRECT. */
+ if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS &&
+ (filp->f_flags & O_APPEND) && (filp->f_flags & O_DIRECT))
+ filp->f_flags &= ~O_DIRECT;
+#endif
+
down(&inode->i_sem);
- /* this ginormous block is in here because it has so many inputs
- * and outputs from this function.. */
- level = !!(filp->f_flags & O_APPEND);
+ /* concurrent O_DIRECT writes are allowed */
+ rw_level = (filp->f_flags & O_DIRECT) ? 0 : 1;
+ ret = ocfs2_rw_lock(inode, rw_level);
+ if (ret < 0) {
+ rw_level = -1;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * We sample i_size under a read level meta lock to see if our write
+ * is extending the file, if it is we back off and get a write level
+ * meta lock.
+ */
+ meta_level = (filp->f_flags & O_APPEND) ? 1 : 0;
for(;;) {
- ret = ocfs2_meta_lock(inode, NULL, NULL, level);
+ ret = ocfs2_meta_lock(inode, NULL, NULL, meta_level);
if (ret < 0) {
+ meta_level = -1;
mlog_errno(ret);
- goto out_i_sem;
+ goto out;
}
/* work on a copy of ppos until we're sure that we won't have
@@ -919,14 +937,6 @@
if (filp->f_flags & O_APPEND) {
saved_pos = i_size_read(inode);
mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos);
-#ifdef OCFS2_ORACORE_WORKAROUNDS
- if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) {
- /* ugh, work around some applications which
- * open everything O_DIRECT + O_APPEND and
- * really don't mean to use O_DIRECT. */
- filp->f_flags &= ~O_DIRECT;
- }
-#endif
} else {
saved_pos = iocb->ki_pos;
}
@@ -940,9 +950,9 @@
if (newsize <= i_size_read(inode))
break;
- if (level == 0) {
- ocfs2_meta_unlock(inode, level);
- level = 1;
+ if (meta_level == 0) {
+ ocfs2_meta_unlock(inode, meta_level);
+ meta_level = 1;
continue;
}
@@ -965,7 +975,7 @@
if (ret < 0) {
if (ret != -ENOSPC)
mlog_errno(ret);
- goto out_meta_unlock;
+ goto out;
}
/* Fill any holes which would've been created by this
@@ -974,53 +984,31 @@
ret = ocfs2_zero_extend(inode, (u64) newsize - count);
if (ret < 0) {
mlog_errno(ret);
- goto out_meta_unlock;
+ goto out;
}
break;
}
- /* we've got whatever cluster lock is appropriate now, so we
- * can stuff *ppos back. */
+ /* ok, we're done with i_size and alloc work */
iocb->ki_pos = saved_pos;
+ ocfs2_meta_unlock(inode, meta_level);
+ meta_level = -1;
- if (filp->f_flags & O_DIRECT) {
-#ifdef OCFS2_ORACORE_WORKAROUNDS
- if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) {
- int sector_size = 1 << osb->s_sectsize_bits;
+ /* communicate with ocfs2_dio_end_io */
+ ocfs2_iocb_set_rw_locked(iocb);
- if ((saved_pos & (sector_size - 1)) ||
- (count & (sector_size - 1)) ||
- ((unsigned long)buf & (sector_size - 1))) {
- do_direct = 0;
- filp->f_flags |= O_SYNC;
- } else {
- do_direct = 1;
- }
- } else
-#endif
- do_direct = 1;
-
- mlog(0, "O_DIRECT\n");
- }
-
- if (!do_direct) {
- ret = ocfs2_data_lock(inode, 1);
- if (ret < 0) {
- mlog_errno(ret);
- goto out_meta_unlock;
- }
- }
-
- down_read(&OCFS2_I(inode)->ip_alloc_sem);
-
#ifdef OCFS2_ORACORE_WORKAROUNDS
- if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) {
+ if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS &&
+ filp->f_flags & O_DIRECT) {
unsigned int saved_flags = filp->f_flags;
+ int sector_size = 1 << osb->s_sectsize_bits;
- if (do_direct)
- filp->f_flags |= O_DIRECT;
- else
+ if ((saved_pos & (sector_size - 1)) ||
+ (count & (sector_size - 1)) ||
+ ((unsigned long)buf & (sector_size - 1))) {
+ filp->f_flags |= O_SYNC;
filp->f_flags &= ~O_DIRECT;
+ }
ret = generic_file_aio_write_nolock(iocb, &local_iov, 1,
&iocb->ki_pos);
@@ -1031,17 +1019,29 @@
ret = generic_file_aio_write_nolock(iocb, &local_iov, 1,
&iocb->ki_pos);
- up_read(&OCFS2_I(inode)->ip_alloc_sem);
+ /* buffered aio wouldn't have proper lock coverage today */
+ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
- if (!do_direct)
- ocfs2_data_unlock(inode, 1);
+ /*
+ * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
+ * function pointer which is called when o_direct io completes so that
+ * it can unlock our rw lock. (it's the clustered equivalent of
+ * i_alloc_sem; protects truncate from racing with pending ios).
+ * Unfortunately there are error cases which call end_io and others
+ * that don't. so we don't have to unlock the rw_lock if either an
+ * async dio is going to do it in the future or an end_io after an
+ * error has already done it.
+ */
+ if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb))
+ rw_level = -1;
-out_meta_unlock:
- ocfs2_meta_unlock(inode, level);
-out_i_sem:
+out:
+ if (meta_level != -1)
+ ocfs2_meta_unlock(inode, meta_level);
+ if (rw_level != -1)
+ ocfs2_rw_unlock(inode, rw_level);
up(&inode->i_sem);
-out:
mlog_exit(ret);
return ret;
}
@@ -1051,10 +1051,12 @@
size_t count,
loff_t pos)
{
- int ret = 0;
- ocfs2_super *osb = NULL;
+ int ret = 0, rw_level = -1;
struct file *filp = iocb->ki_filp;
struct inode *inode = filp->f_dentry->d_inode;
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+#endif
mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
(unsigned int)count,
@@ -1067,8 +1069,6 @@
goto bail;
}
- osb = OCFS2_SB(inode->i_sb);
-
#ifdef OCFS2_ORACORE_WORKAROUNDS
if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) {
if (filp->f_flags & O_DIRECT) {
@@ -1084,86 +1084,40 @@
}
#endif
- ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
- if (ret < 0) {
- mlog_errno(ret);
- goto bail;
- }
-
- if (!(filp->f_flags & O_DIRECT)) {
- ret = ocfs2_data_lock(inode, 0);
+ /*
+ * buffered reads protect themselves in ->readpage(). O_DIRECT reads
+ * need locks to protect pending reads from racing with truncate.
+ */
+ if (filp->f_flags & O_DIRECT) {
+ ret = ocfs2_rw_lock(inode, 0);
if (ret < 0) {
mlog_errno(ret);
- goto bail_unlock_meta;
+ goto bail;
}
+ rw_level = 0;
+ /* communicate with ocfs2_dio_end_io */
+ ocfs2_iocb_set_rw_locked(iocb);
}
- down_read(&OCFS2_I(inode)->ip_alloc_sem);
-
ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos);
-
- up_read(&OCFS2_I(inode)->ip_alloc_sem);
-
if (ret == -EINVAL)
mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
- if (!(filp->f_flags & O_DIRECT))
- ocfs2_data_unlock(inode, 0);
-bail_unlock_meta:
- ocfs2_meta_unlock(inode, 0);
+ /* buffered aio wouldn't have proper lock coverage today */
+ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
+ /* see ocfs2_file_aio_write */
+ if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb))
+ rw_level = -1;
+
bail:
+ if (rw_level != -1)
+ ocfs2_rw_unlock(inode, rw_level);
mlog_exit(ret);
return ret;
}
-static ssize_t ocfs2_file_sendfile(struct file *in_file,
- loff_t *ppos,
- size_t count,
- read_actor_t actor,
- void *target)
-{
- int ret;
- struct inode *inode = in_file->f_mapping->host;
-
- mlog_entry("inode %"MLFu64", ppos %lld, count = %u\n",
- OCFS2_I(inode)->ip_blkno, (long long) *ppos,
- (unsigned int) count);
-
- /* Obviously, there is no user buffer to worry about here --
- * this simplifies locking, so no need to walk vmas a la
- * read/write. We take a simple set of cluster locks against
- * the inode and call generic_file_sendfile. */
- ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
- if (ret < 0) {
- mlog_errno(ret);
- goto bail;
- }
-
- ret = ocfs2_data_lock(inode, 0);
- if (ret < 0) {
- mlog_errno(ret);
- goto bail_unlock_meta;
- }
-
- down_read(&OCFS2_I(inode)->ip_alloc_sem);
-
- ret = generic_file_sendfile(in_file, ppos, count, actor, target);
- if (ret < 0)
- mlog_errno(ret);
-
- up_read(&OCFS2_I(inode)->ip_alloc_sem);
-
- ocfs2_data_unlock(inode, 0);
-bail_unlock_meta:
- ocfs2_meta_unlock(inode, 0);
-
-bail:
- mlog_exit(ret);
- return ret;
-}
-
struct inode_operations ocfs2_file_iops = {
.setattr = ocfs2_setattr,
.getattr = ocfs2_getattr,
@@ -1177,7 +1131,7 @@
struct file_operations ocfs2_fops = {
.read = do_sync_read,
.write = do_sync_write,
- .sendfile = ocfs2_file_sendfile,
+ .sendfile = generic_file_sendfile,
.mmap = ocfs2_mmap,
.fsync = ocfs2_sync_file,
.release = ocfs2_file_release,
Modified: branches/locking-changes/fs/ocfs2/mmap.c
===================================================================
--- branches/locking-changes/fs/ocfs2/mmap.c 2005-10-03 23:13:24 UTC (rev 2630)
+++ branches/locking-changes/fs/ocfs2/mmap.c 2005-10-04 00:21:10 UTC (rev 2631)
@@ -47,16 +47,12 @@
int *type)
{
struct inode *inode = area->vm_file->f_dentry->d_inode;
- struct page *page;
+ struct page *page = NOPAGE_SIGBUS;
sigset_t blocked, oldset;
int ret;
mlog_entry("(inode %lu, address %lu)\n", inode->i_ino, address);
- /* For lack of a better error... Unfortunately returns
- * from nopage aren't very expressive right now. */
- page = NOPAGE_SIGBUS;
-
/* The best way to deal with signals in this path is
* to block them upfront, rather than allowing the
* locking paths to return -ERESTARTSYS. */
@@ -67,41 +63,15 @@
ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
if (ret < 0) {
mlog_errno(ret);
- goto bail;
+ goto out;
}
- /* Since we don't allow shared writable, we need only
- * worry about read locking here. */
- ret = ocfs2_meta_lock(inode, NULL, NULL, 0);
- if (ret < 0) {
- mlog_errno(ret);
-
- if (ret == -ENOMEM)
- page = NOPAGE_OOM;
- goto bail_setmask;
- }
-
- ret = ocfs2_data_lock(inode, 0);
- if (ret < 0) {
- mlog_errno(ret);
-
- if (ret == -ENOMEM)
- page = NOPAGE_OOM;
- goto bail_unlock;
- }
-
page = filemap_nopage(area, address, type);
- ocfs2_data_unlock(inode, 0);
-
-bail_unlock:
- ocfs2_meta_unlock(inode, 0);
-
-bail_setmask:
ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
if (ret < 0)
mlog_errno(ret);
-bail:
+out:
mlog_exit_ptr(page);
return page;
}
More information about the Ocfs2-commits
mailing list