@@ -667,6 +667,29 @@ struct io_unlink {
667
667
struct filename * filename ;
668
668
};
669
669
670
+ struct io_mkdir {
671
+ struct file * file ;
672
+ int dfd ;
673
+ umode_t mode ;
674
+ struct filename * filename ;
675
+ };
676
+
677
+ struct io_symlink {
678
+ struct file * file ;
679
+ int new_dfd ;
680
+ struct filename * oldpath ;
681
+ struct filename * newpath ;
682
+ };
683
+
684
+ struct io_hardlink {
685
+ struct file * file ;
686
+ int old_dfd ;
687
+ int new_dfd ;
688
+ struct filename * oldpath ;
689
+ struct filename * newpath ;
690
+ int flags ;
691
+ };
692
+
670
693
struct io_completion {
671
694
struct file * file ;
672
695
u32 cflags ;
@@ -826,6 +849,9 @@ struct io_kiocb {
826
849
struct io_shutdown shutdown ;
827
850
struct io_rename rename ;
828
851
struct io_unlink unlink ;
852
+ struct io_mkdir mkdir ;
853
+ struct io_symlink symlink ;
854
+ struct io_hardlink hardlink ;
829
855
/* use only after cleaning per-op data, see io_clean_op() */
830
856
struct io_completion compl ;
831
857
};
@@ -1037,6 +1063,9 @@ static const struct io_op_def io_op_defs[] = {
1037
1063
},
1038
1064
[IORING_OP_RENAMEAT ] = {},
1039
1065
[IORING_OP_UNLINKAT ] = {},
1066
+ [IORING_OP_MKDIRAT ] = {},
1067
+ [IORING_OP_SYMLINKAT ] = {},
1068
+ [IORING_OP_LINKAT ] = {},
1040
1069
};
1041
1070
1042
1071
/* requests with any of those set should undergo io_disarm_next() */
@@ -3680,6 +3709,149 @@ static int io_unlinkat(struct io_kiocb *req, unsigned int issue_flags)
3680
3709
return 0 ;
3681
3710
}
3682
3711
3712
+ static int io_mkdirat_prep (struct io_kiocb * req ,
3713
+ const struct io_uring_sqe * sqe )
3714
+ {
3715
+ struct io_mkdir * mkd = & req -> mkdir ;
3716
+ const char __user * fname ;
3717
+
3718
+ if (unlikely (req -> ctx -> flags & IORING_SETUP_IOPOLL ))
3719
+ return - EINVAL ;
3720
+ if (sqe -> ioprio || sqe -> off || sqe -> rw_flags || sqe -> buf_index ||
3721
+ sqe -> splice_fd_in )
3722
+ return - EINVAL ;
3723
+ if (unlikely (req -> flags & REQ_F_FIXED_FILE ))
3724
+ return - EBADF ;
3725
+
3726
+ mkd -> dfd = READ_ONCE (sqe -> fd );
3727
+ mkd -> mode = READ_ONCE (sqe -> len );
3728
+
3729
+ fname = u64_to_user_ptr (READ_ONCE (sqe -> addr ));
3730
+ mkd -> filename = getname (fname );
3731
+ if (IS_ERR (mkd -> filename ))
3732
+ return PTR_ERR (mkd -> filename );
3733
+
3734
+ req -> flags |= REQ_F_NEED_CLEANUP ;
3735
+ return 0 ;
3736
+ }
3737
+
3738
+ static int io_mkdirat (struct io_kiocb * req , int issue_flags )
3739
+ {
3740
+ struct io_mkdir * mkd = & req -> mkdir ;
3741
+ int ret ;
3742
+
3743
+ if (issue_flags & IO_URING_F_NONBLOCK )
3744
+ return - EAGAIN ;
3745
+
3746
+ ret = do_mkdirat (mkd -> dfd , mkd -> filename , mkd -> mode );
3747
+
3748
+ req -> flags &= ~REQ_F_NEED_CLEANUP ;
3749
+ if (ret < 0 )
3750
+ req_set_fail (req );
3751
+ io_req_complete (req , ret );
3752
+ return 0 ;
3753
+ }
3754
+
3755
+ static int io_symlinkat_prep (struct io_kiocb * req ,
3756
+ const struct io_uring_sqe * sqe )
3757
+ {
3758
+ struct io_symlink * sl = & req -> symlink ;
3759
+ const char __user * oldpath , * newpath ;
3760
+
3761
+ if (unlikely (req -> ctx -> flags & IORING_SETUP_IOPOLL ))
3762
+ return - EINVAL ;
3763
+ if (sqe -> ioprio || sqe -> len || sqe -> rw_flags || sqe -> buf_index ||
3764
+ sqe -> splice_fd_in )
3765
+ return - EINVAL ;
3766
+ if (unlikely (req -> flags & REQ_F_FIXED_FILE ))
3767
+ return - EBADF ;
3768
+
3769
+ sl -> new_dfd = READ_ONCE (sqe -> fd );
3770
+ oldpath = u64_to_user_ptr (READ_ONCE (sqe -> addr ));
3771
+ newpath = u64_to_user_ptr (READ_ONCE (sqe -> addr2 ));
3772
+
3773
+ sl -> oldpath = getname (oldpath );
3774
+ if (IS_ERR (sl -> oldpath ))
3775
+ return PTR_ERR (sl -> oldpath );
3776
+
3777
+ sl -> newpath = getname (newpath );
3778
+ if (IS_ERR (sl -> newpath )) {
3779
+ putname (sl -> oldpath );
3780
+ return PTR_ERR (sl -> newpath );
3781
+ }
3782
+
3783
+ req -> flags |= REQ_F_NEED_CLEANUP ;
3784
+ return 0 ;
3785
+ }
3786
+
3787
+ static int io_symlinkat (struct io_kiocb * req , int issue_flags )
3788
+ {
3789
+ struct io_symlink * sl = & req -> symlink ;
3790
+ int ret ;
3791
+
3792
+ if (issue_flags & IO_URING_F_NONBLOCK )
3793
+ return - EAGAIN ;
3794
+
3795
+ ret = do_symlinkat (sl -> oldpath , sl -> new_dfd , sl -> newpath );
3796
+
3797
+ req -> flags &= ~REQ_F_NEED_CLEANUP ;
3798
+ if (ret < 0 )
3799
+ req_set_fail (req );
3800
+ io_req_complete (req , ret );
3801
+ return 0 ;
3802
+ }
3803
+
3804
+ static int io_linkat_prep (struct io_kiocb * req ,
3805
+ const struct io_uring_sqe * sqe )
3806
+ {
3807
+ struct io_hardlink * lnk = & req -> hardlink ;
3808
+ const char __user * oldf , * newf ;
3809
+
3810
+ if (unlikely (req -> ctx -> flags & IORING_SETUP_IOPOLL ))
3811
+ return - EINVAL ;
3812
+ if (sqe -> ioprio || sqe -> rw_flags || sqe -> buf_index || sqe -> splice_fd_in )
3813
+ return - EINVAL ;
3814
+ if (unlikely (req -> flags & REQ_F_FIXED_FILE ))
3815
+ return - EBADF ;
3816
+
3817
+ lnk -> old_dfd = READ_ONCE (sqe -> fd );
3818
+ lnk -> new_dfd = READ_ONCE (sqe -> len );
3819
+ oldf = u64_to_user_ptr (READ_ONCE (sqe -> addr ));
3820
+ newf = u64_to_user_ptr (READ_ONCE (sqe -> addr2 ));
3821
+ lnk -> flags = READ_ONCE (sqe -> hardlink_flags );
3822
+
3823
+ lnk -> oldpath = getname (oldf );
3824
+ if (IS_ERR (lnk -> oldpath ))
3825
+ return PTR_ERR (lnk -> oldpath );
3826
+
3827
+ lnk -> newpath = getname (newf );
3828
+ if (IS_ERR (lnk -> newpath )) {
3829
+ putname (lnk -> oldpath );
3830
+ return PTR_ERR (lnk -> newpath );
3831
+ }
3832
+
3833
+ req -> flags |= REQ_F_NEED_CLEANUP ;
3834
+ return 0 ;
3835
+ }
3836
+
3837
+ static int io_linkat (struct io_kiocb * req , int issue_flags )
3838
+ {
3839
+ struct io_hardlink * lnk = & req -> hardlink ;
3840
+ int ret ;
3841
+
3842
+ if (issue_flags & IO_URING_F_NONBLOCK )
3843
+ return - EAGAIN ;
3844
+
3845
+ ret = do_linkat (lnk -> old_dfd , lnk -> oldpath , lnk -> new_dfd ,
3846
+ lnk -> newpath , lnk -> flags );
3847
+
3848
+ req -> flags &= ~REQ_F_NEED_CLEANUP ;
3849
+ if (ret < 0 )
3850
+ req_set_fail (req );
3851
+ io_req_complete (req , ret );
3852
+ return 0 ;
3853
+ }
3854
+
3683
3855
static int io_shutdown_prep (struct io_kiocb * req ,
3684
3856
const struct io_uring_sqe * sqe )
3685
3857
{
@@ -6169,6 +6341,12 @@ static int io_req_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
6169
6341
return io_renameat_prep (req , sqe );
6170
6342
case IORING_OP_UNLINKAT :
6171
6343
return io_unlinkat_prep (req , sqe );
6344
+ case IORING_OP_MKDIRAT :
6345
+ return io_mkdirat_prep (req , sqe );
6346
+ case IORING_OP_SYMLINKAT :
6347
+ return io_symlinkat_prep (req , sqe );
6348
+ case IORING_OP_LINKAT :
6349
+ return io_linkat_prep (req , sqe );
6172
6350
}
6173
6351
6174
6352
printk_once (KERN_WARNING "io_uring: unhandled opcode %d\n" ,
@@ -6332,6 +6510,17 @@ static void io_clean_op(struct io_kiocb *req)
6332
6510
case IORING_OP_UNLINKAT :
6333
6511
putname (req -> unlink .filename );
6334
6512
break ;
6513
+ case IORING_OP_MKDIRAT :
6514
+ putname (req -> mkdir .filename );
6515
+ break ;
6516
+ case IORING_OP_SYMLINKAT :
6517
+ putname (req -> symlink .oldpath );
6518
+ putname (req -> symlink .newpath );
6519
+ break ;
6520
+ case IORING_OP_LINKAT :
6521
+ putname (req -> hardlink .oldpath );
6522
+ putname (req -> hardlink .newpath );
6523
+ break ;
6335
6524
}
6336
6525
}
6337
6526
if ((req -> flags & REQ_F_POLLED ) && req -> apoll ) {
@@ -6460,6 +6649,15 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)
6460
6649
case IORING_OP_UNLINKAT :
6461
6650
ret = io_unlinkat (req , issue_flags );
6462
6651
break ;
6652
+ case IORING_OP_MKDIRAT :
6653
+ ret = io_mkdirat (req , issue_flags );
6654
+ break ;
6655
+ case IORING_OP_SYMLINKAT :
6656
+ ret = io_symlinkat (req , issue_flags );
6657
+ break ;
6658
+ case IORING_OP_LINKAT :
6659
+ ret = io_linkat (req , issue_flags );
6660
+ break ;
6463
6661
default :
6464
6662
ret = - EINVAL ;
6465
6663
break ;
0 commit comments