Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bb462a4 authored by Wengang Wang's avatar Wengang Wang Committed by Greg Kroah-Hartman
Browse files

ocfs2: free up write context when direct IO failed

commit 5040f8df56fb90c7919f1c9b0b6e54c843437456 upstream.

The write context should also be freed even when direct IO failed.
Otherwise a memory leak is introduced and entries remain in
oi->ip_unwritten_list causing the following BUG later in unlink path:

  ERROR: bug expression: !list_empty(&oi->ip_unwritten_list)
  ERROR: Clear inode of 215043, inode has unwritten extents
  ...
  Call Trace:
  ? __set_current_blocked+0x42/0x68
  ocfs2_evict_inode+0x91/0x6a0 [ocfs2]
  ? bit_waitqueue+0x40/0x33
  evict+0xdb/0x1af
  iput+0x1a2/0x1f7
  do_unlinkat+0x194/0x28f
  SyS_unlinkat+0x1b/0x2f
  do_syscall_64+0x79/0x1ae
  entry_SYSCALL_64_after_hwframe+0x151/0x0

This patch also logs, with frequency limit, direct IO failures.

Link: http://lkml.kernel.org/r/20181102170632.25921-1-wen.gang.wang@oracle.com


Signed-off-by: default avatarWengang Wang <wen.gang.wang@oracle.com>
Reviewed-by: default avatarJunxiao Bi <junxiao.bi@oracle.com>
Reviewed-by: default avatarChangwei Ge <ge.changwei@h3c.com>
Reviewed-by: default avatarJoseph Qi <jiangqi903@gmail.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 148dc931
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -2412,8 +2412,16 @@ static int ocfs2_dio_end_io(struct kiocb *iocb,
	/* this io's submitter should not have unlocked this before we could */
	BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));

	if (bytes > 0 && private)
		ret = ocfs2_dio_end_io_write(inode, private, offset, bytes);
	if (bytes <= 0)
		mlog_ratelimited(ML_ERROR, "Direct IO failed, bytes = %lld",
				 (long long)bytes);
	if (private) {
		if (bytes > 0)
			ret = ocfs2_dio_end_io_write(inode, private, offset,
						     bytes);
		else
			ocfs2_dio_free_write_ctx(inode, private);
	}

	ocfs2_iocb_clear_rw_locked(iocb);

+9 −0
Original line number Diff line number Diff line
@@ -178,6 +178,15 @@ do { \
			      ##__VA_ARGS__);				\
} while (0)

#define mlog_ratelimited(mask, fmt, ...)				\
do {									\
	static DEFINE_RATELIMIT_STATE(_rs,				\
				      DEFAULT_RATELIMIT_INTERVAL,	\
				      DEFAULT_RATELIMIT_BURST);		\
	if (__ratelimit(&_rs))						\
		mlog(mask, fmt, ##__VA_ARGS__);				\
} while (0)

#define mlog_errno(st) ({						\
	int _st = (st);							\
	if (_st != -ERESTARTSYS && _st != -EINTR &&			\