Skip to content

Commit 1505ba0

Browse files
bvanasschebrauner
authored andcommitted
fs: Split fcntl_rw_hint()
Split fcntl_rw_hint() such that there is one helper function per fcntl. Use READ_ONCE() and WRITE_ONCE() to access the i_write_hint member instead of protecting such accesses with the inode lock. READ_ONCE() is not used in I/O path code that reads i_write_hint. Users who want F_SET_RW_HINT to affect I/O need to make sure that F_SET_RW_HINT has completed before I/O is submitted that should use the configured write hint. Cc: Christoph Hellwig <hch@lst.de> Suggested-by: Christoph Hellwig <hch@lst.de> Cc: Kanchan Joshi <joshi.k@samsung.com> Cc: Jeff Layton <jlayton@kernel.org> Cc: Chuck Lever <chuck.lever@oracle.com> Cc: Jens Axboe <axboe@kernel.dk> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Bart Van Assche <bvanassche@acm.org> Link: https://lore.kernel.org/r/20240202203926.2478590-4-bvanassche@acm.org Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent e769779 commit 1505ba0

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

fs/fcntl.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -290,32 +290,33 @@ static bool rw_hint_valid(u64 hint)
290290
}
291291
}
292292

293-
static long fcntl_rw_hint(struct file *file, unsigned int cmd,
294-
unsigned long arg)
293+
static long fcntl_get_rw_hint(struct file *file, unsigned int cmd,
294+
unsigned long arg)
295295
{
296296
struct inode *inode = file_inode(file);
297297
u64 __user *argp = (u64 __user *)arg;
298-
u64 hint;
298+
u64 hint = READ_ONCE(inode->i_write_hint);
299299

300-
switch (cmd) {
301-
case F_GET_RW_HINT:
302-
hint = inode->i_write_hint;
303-
if (copy_to_user(argp, &hint, sizeof(*argp)))
304-
return -EFAULT;
305-
return 0;
306-
case F_SET_RW_HINT:
307-
if (copy_from_user(&hint, argp, sizeof(hint)))
308-
return -EFAULT;
309-
if (!rw_hint_valid(hint))
310-
return -EINVAL;
300+
if (copy_to_user(argp, &hint, sizeof(*argp)))
301+
return -EFAULT;
302+
return 0;
303+
}
311304

312-
inode_lock(inode);
313-
inode->i_write_hint = hint;
314-
inode_unlock(inode);
315-
return 0;
316-
default:
305+
static long fcntl_set_rw_hint(struct file *file, unsigned int cmd,
306+
unsigned long arg)
307+
{
308+
struct inode *inode = file_inode(file);
309+
u64 __user *argp = (u64 __user *)arg;
310+
u64 hint;
311+
312+
if (copy_from_user(&hint, argp, sizeof(hint)))
313+
return -EFAULT;
314+
if (!rw_hint_valid(hint))
317315
return -EINVAL;
318-
}
316+
317+
WRITE_ONCE(inode->i_write_hint, hint);
318+
319+
return 0;
319320
}
320321

321322
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
@@ -421,8 +422,10 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
421422
err = memfd_fcntl(filp, cmd, argi);
422423
break;
423424
case F_GET_RW_HINT:
425+
err = fcntl_get_rw_hint(filp, cmd, arg);
426+
break;
424427
case F_SET_RW_HINT:
425-
err = fcntl_rw_hint(filp, cmd, arg);
428+
err = fcntl_set_rw_hint(filp, cmd, arg);
426429
break;
427430
default:
428431
break;

0 commit comments

Comments
 (0)