@@ -35,6 +35,7 @@ struct nfs_local_kiocb {
35
35
struct bio_vec * bvec ;
36
36
struct nfs_pgio_header * hdr ;
37
37
struct work_struct work ;
38
+ void (* aio_complete_work )(struct work_struct * );
38
39
struct nfsd_file * localio ;
39
40
};
40
41
@@ -48,6 +49,11 @@ struct nfs_local_fsync_ctx {
48
49
static bool localio_enabled __read_mostly = true;
49
50
module_param (localio_enabled , bool , 0644 );
50
51
52
+ static bool localio_O_DIRECT_semantics __read_mostly = false;
53
+ module_param (localio_O_DIRECT_semantics , bool , 0644 );
54
+ MODULE_PARM_DESC (localio_O_DIRECT_semantics ,
55
+ "LOCALIO will use O_DIRECT semantics to filesystem." );
56
+
51
57
static inline bool nfs_client_is_local (const struct nfs_client * clp )
52
58
{
53
59
return !!test_bit (NFS_CS_LOCAL_IO , & clp -> cl_flags );
@@ -285,10 +291,19 @@ nfs_local_iocb_alloc(struct nfs_pgio_header *hdr,
285
291
kfree (iocb );
286
292
return NULL ;
287
293
}
288
- init_sync_kiocb (& iocb -> kiocb , file );
294
+
295
+ if (localio_O_DIRECT_semantics &&
296
+ test_bit (NFS_IOHDR_ODIRECT , & hdr -> flags )) {
297
+ iocb -> kiocb .ki_filp = file ;
298
+ iocb -> kiocb .ki_flags = IOCB_DIRECT ;
299
+ } else
300
+ init_sync_kiocb (& iocb -> kiocb , file );
301
+
289
302
iocb -> kiocb .ki_pos = hdr -> args .offset ;
290
303
iocb -> hdr = hdr ;
291
304
iocb -> kiocb .ki_flags &= ~IOCB_APPEND ;
305
+ iocb -> aio_complete_work = NULL ;
306
+
292
307
return iocb ;
293
308
}
294
309
@@ -343,6 +358,18 @@ nfs_local_pgio_release(struct nfs_local_kiocb *iocb)
343
358
nfs_local_hdr_release (hdr , hdr -> task .tk_ops );
344
359
}
345
360
361
+ /*
362
+ * Complete the I/O from iocb->kiocb.ki_complete()
363
+ *
364
+ * Note that this function can be called from a bottom half context,
365
+ * hence we need to queue the rpc_call_done() etc to a workqueue
366
+ */
367
+ static inline void nfs_local_pgio_aio_complete (struct nfs_local_kiocb * iocb )
368
+ {
369
+ INIT_WORK (& iocb -> work , iocb -> aio_complete_work );
370
+ queue_work (nfsiod_workqueue , & iocb -> work );
371
+ }
372
+
346
373
static void
347
374
nfs_local_read_done (struct nfs_local_kiocb * iocb , long status )
348
375
{
@@ -365,6 +392,23 @@ nfs_local_read_done(struct nfs_local_kiocb *iocb, long status)
365
392
status > 0 ? status : 0 , hdr -> res .eof );
366
393
}
367
394
395
+ static void nfs_local_read_aio_complete_work (struct work_struct * work )
396
+ {
397
+ struct nfs_local_kiocb * iocb =
398
+ container_of (work , struct nfs_local_kiocb , work );
399
+
400
+ nfs_local_pgio_release (iocb );
401
+ }
402
+
403
+ static void nfs_local_read_aio_complete (struct kiocb * kiocb , long ret )
404
+ {
405
+ struct nfs_local_kiocb * iocb =
406
+ container_of (kiocb , struct nfs_local_kiocb , kiocb );
407
+
408
+ nfs_local_read_done (iocb , ret );
409
+ nfs_local_pgio_aio_complete (iocb ); /* Calls nfs_local_read_aio_complete_work */
410
+ }
411
+
368
412
static void nfs_local_call_read (struct work_struct * work )
369
413
{
370
414
struct nfs_local_kiocb * iocb =
@@ -379,10 +423,10 @@ static void nfs_local_call_read(struct work_struct *work)
379
423
nfs_local_iter_init (& iter , iocb , READ );
380
424
381
425
status = filp -> f_op -> read_iter (& iocb -> kiocb , & iter );
382
- WARN_ON_ONCE (status == - EIOCBQUEUED );
383
-
384
- nfs_local_read_done (iocb , status );
385
- nfs_local_pgio_release ( iocb );
426
+ if (status != - EIOCBQUEUED ) {
427
+ nfs_local_read_done ( iocb , status );
428
+ nfs_local_pgio_release (iocb );
429
+ }
386
430
387
431
revert_creds (save_cred );
388
432
}
@@ -410,6 +454,11 @@ nfs_do_local_read(struct nfs_pgio_header *hdr,
410
454
nfs_local_pgio_init (hdr , call_ops );
411
455
hdr -> res .eof = false;
412
456
457
+ if (iocb -> kiocb .ki_flags & IOCB_DIRECT ) {
458
+ iocb -> kiocb .ki_complete = nfs_local_read_aio_complete ;
459
+ iocb -> aio_complete_work = nfs_local_read_aio_complete_work ;
460
+ }
461
+
413
462
INIT_WORK (& iocb -> work , nfs_local_call_read );
414
463
queue_work (nfslocaliod_workqueue , & iocb -> work );
415
464
@@ -534,6 +583,24 @@ nfs_local_write_done(struct nfs_local_kiocb *iocb, long status)
534
583
nfs_local_pgio_done (hdr , status );
535
584
}
536
585
586
+ static void nfs_local_write_aio_complete_work (struct work_struct * work )
587
+ {
588
+ struct nfs_local_kiocb * iocb =
589
+ container_of (work , struct nfs_local_kiocb , work );
590
+
591
+ nfs_local_vfs_getattr (iocb );
592
+ nfs_local_pgio_release (iocb );
593
+ }
594
+
595
+ static void nfs_local_write_aio_complete (struct kiocb * kiocb , long ret )
596
+ {
597
+ struct nfs_local_kiocb * iocb =
598
+ container_of (kiocb , struct nfs_local_kiocb , kiocb );
599
+
600
+ nfs_local_write_done (iocb , ret );
601
+ nfs_local_pgio_aio_complete (iocb ); /* Calls nfs_local_write_aio_complete_work */
602
+ }
603
+
537
604
static void nfs_local_call_write (struct work_struct * work )
538
605
{
539
606
struct nfs_local_kiocb * iocb =
@@ -552,11 +619,11 @@ static void nfs_local_call_write(struct work_struct *work)
552
619
file_start_write (filp );
553
620
status = filp -> f_op -> write_iter (& iocb -> kiocb , & iter );
554
621
file_end_write (filp );
555
- WARN_ON_ONCE (status == - EIOCBQUEUED );
556
-
557
- nfs_local_write_done (iocb , status );
558
- nfs_local_vfs_getattr (iocb );
559
- nfs_local_pgio_release ( iocb );
622
+ if (status != - EIOCBQUEUED ) {
623
+ nfs_local_write_done ( iocb , status );
624
+ nfs_local_vfs_getattr (iocb );
625
+ nfs_local_pgio_release (iocb );
626
+ }
560
627
561
628
revert_creds (save_cred );
562
629
current -> flags = old_flags ;
@@ -592,10 +659,16 @@ nfs_do_local_write(struct nfs_pgio_header *hdr,
592
659
case NFS_FILE_SYNC :
593
660
iocb -> kiocb .ki_flags |= IOCB_DSYNC |IOCB_SYNC ;
594
661
}
662
+
595
663
nfs_local_pgio_init (hdr , call_ops );
596
664
597
665
nfs_set_local_verifier (hdr -> inode , hdr -> res .verf , hdr -> args .stable );
598
666
667
+ if (iocb -> kiocb .ki_flags & IOCB_DIRECT ) {
668
+ iocb -> kiocb .ki_complete = nfs_local_write_aio_complete ;
669
+ iocb -> aio_complete_work = nfs_local_write_aio_complete_work ;
670
+ }
671
+
599
672
INIT_WORK (& iocb -> work , nfs_local_call_write );
600
673
queue_work (nfslocaliod_workqueue , & iocb -> work );
601
674
0 commit comments