@@ -565,10 +565,12 @@ static u64 get_writepages_data_length(struct inode *inode,
565565 struct page * page , u64 start )
566566{
567567 struct ceph_inode_info * ci = ceph_inode (inode );
568- struct ceph_snap_context * snapc = page_snap_context ( page ) ;
568+ struct ceph_snap_context * snapc ;
569569 struct ceph_cap_snap * capsnap = NULL ;
570570 u64 end = i_size_read (inode );
571+ u64 ret ;
571572
573+ snapc = page_snap_context (ceph_fscrypt_pagecache_page (page ));
572574 if (snapc != ci -> i_head_snapc ) {
573575 bool found = false;
574576 spin_lock (& ci -> i_ceph_lock );
@@ -583,9 +585,12 @@ static u64 get_writepages_data_length(struct inode *inode,
583585 spin_unlock (& ci -> i_ceph_lock );
584586 WARN_ON (!found );
585587 }
586- if (end > page_offset (page ) + thp_size (page ))
587- end = page_offset (page ) + thp_size (page );
588- return end > start ? end - start : 0 ;
588+ if (end > ceph_fscrypt_page_offset (page ) + thp_size (page ))
589+ end = ceph_fscrypt_page_offset (page ) + thp_size (page );
590+ ret = end > start ? end - start : 0 ;
591+ if (ret && fscrypt_is_bounce_page (page ))
592+ ret = round_up (ret , CEPH_FSCRYPT_BLOCK_SIZE );
593+ return ret ;
589594}
590595
591596/*
@@ -604,10 +609,12 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
604609 loff_t page_off = page_offset (page );
605610 int err ;
606611 loff_t len = thp_size (page );
612+ loff_t wlen ;
607613 struct ceph_writeback_ctl ceph_wbc ;
608614 struct ceph_osd_client * osdc = & fsc -> client -> osdc ;
609615 struct ceph_osd_request * req ;
610616 bool caching = ceph_is_cache_enabled (inode );
617+ struct page * bounce_page = NULL ;
611618
612619 dout ("writepage %p idx %lu\n" , page , page -> index );
613620
@@ -643,39 +650,59 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
643650 if (ceph_wbc .i_size < page_off + len )
644651 len = ceph_wbc .i_size - page_off ;
645652
653+ wlen = IS_ENCRYPTED (inode ) ? round_up (len , CEPH_FSCRYPT_BLOCK_SIZE ) : len ;
646654 dout ("writepage %p page %p index %lu on %llu~%llu snapc %p seq %lld\n" ,
647- inode , page , page -> index , page_off , len , snapc , snapc -> seq );
655+ inode , page , page -> index , page_off , wlen , snapc , snapc -> seq );
648656
649657 if (atomic_long_inc_return (& fsc -> writeback_count ) >
650658 CONGESTION_ON_THRESH (fsc -> mount_options -> congestion_kb ))
651659 fsc -> write_congested = true;
652660
653- req = ceph_osdc_new_request (osdc , & ci -> i_layout , ceph_vino (inode ), page_off , & len , 0 , 1 ,
654- CEPH_OSD_OP_WRITE , CEPH_OSD_FLAG_WRITE , snapc ,
655- ceph_wbc .truncate_seq , ceph_wbc .truncate_size ,
656- true);
661+ req = ceph_osdc_new_request (osdc , & ci -> i_layout , ceph_vino (inode ),
662+ page_off , & wlen , 0 , 1 , CEPH_OSD_OP_WRITE ,
663+ CEPH_OSD_FLAG_WRITE , snapc ,
664+ ceph_wbc .truncate_seq ,
665+ ceph_wbc .truncate_size , true);
657666 if (IS_ERR (req )) {
658667 redirty_page_for_writepage (wbc , page );
659668 return PTR_ERR (req );
660669 }
661670
671+ if (wlen < len )
672+ len = wlen ;
673+
662674 set_page_writeback (page );
663675 if (caching )
664676 ceph_set_page_fscache (page );
665677 ceph_fscache_write_to_cache (inode , page_off , len , caching );
666678
679+ if (IS_ENCRYPTED (inode )) {
680+ bounce_page = fscrypt_encrypt_pagecache_blocks (page ,
681+ CEPH_FSCRYPT_BLOCK_SIZE , 0 ,
682+ GFP_NOFS );
683+ if (IS_ERR (bounce_page )) {
684+ redirty_page_for_writepage (wbc , page );
685+ end_page_writeback (page );
686+ ceph_osdc_put_request (req );
687+ return PTR_ERR (bounce_page );
688+ }
689+ }
690+
667691 /* it may be a short write due to an object boundary */
668692 WARN_ON_ONCE (len > thp_size (page ));
669- osd_req_op_extent_osd_data_pages (req , 0 , & page , len , 0 , false, false);
670- dout ("writepage %llu~%llu (%llu bytes)\n" , page_off , len , len );
693+ osd_req_op_extent_osd_data_pages (req , 0 ,
694+ bounce_page ? & bounce_page : & page , wlen , 0 ,
695+ false, false);
696+ dout ("writepage %llu~%llu (%llu bytes, %sencrypted)\n" ,
697+ page_off , len , wlen , IS_ENCRYPTED (inode ) ? "" : "not " );
671698
672699 req -> r_mtime = inode -> i_mtime ;
673700 ceph_osdc_start_request (osdc , req );
674701 err = ceph_osdc_wait_request (osdc , req );
675702
676703 ceph_update_write_metrics (& fsc -> mdsc -> metric , req -> r_start_latency ,
677704 req -> r_end_latency , len , err );
678-
705+ fscrypt_free_bounce_page ( bounce_page );
679706 ceph_osdc_put_request (req );
680707 if (err == 0 )
681708 err = len ;
@@ -794,6 +821,11 @@ static void writepages_finish(struct ceph_osd_request *req)
794821 total_pages += num_pages ;
795822 for (j = 0 ; j < num_pages ; j ++ ) {
796823 page = osd_data -> pages [j ];
824+ if (fscrypt_is_bounce_page (page )) {
825+ page = fscrypt_pagecache_page (page );
826+ fscrypt_free_bounce_page (osd_data -> pages [j ]);
827+ osd_data -> pages [j ] = page ;
828+ }
797829 BUG_ON (!page );
798830 WARN_ON (!PageUptodate (page ));
799831
@@ -1064,9 +1096,28 @@ static int ceph_writepages_start(struct address_space *mapping,
10641096 fsc -> mount_options -> congestion_kb ))
10651097 fsc -> write_congested = true;
10661098
1067- pages [locked_pages ++ ] = page ;
1068- fbatch .folios [i ] = NULL ;
1099+ if (IS_ENCRYPTED (inode )) {
1100+ pages [locked_pages ] =
1101+ fscrypt_encrypt_pagecache_blocks (page ,
1102+ PAGE_SIZE , 0 ,
1103+ locked_pages ? GFP_NOWAIT : GFP_NOFS );
1104+ if (IS_ERR (pages [locked_pages ])) {
1105+ if (PTR_ERR (pages [locked_pages ]) == - EINVAL )
1106+ pr_err ("%s: inode->i_blkbits=%hhu\n" ,
1107+ __func__ , inode -> i_blkbits );
1108+ /* better not fail on first page! */
1109+ BUG_ON (locked_pages == 0 );
1110+ pages [locked_pages ] = NULL ;
1111+ redirty_page_for_writepage (wbc , page );
1112+ unlock_page (page );
1113+ break ;
1114+ }
1115+ ++ locked_pages ;
1116+ } else {
1117+ pages [locked_pages ++ ] = page ;
1118+ }
10691119
1120+ fbatch .folios [i ] = NULL ;
10701121 len += thp_size (page );
10711122 }
10721123
@@ -1094,7 +1145,7 @@ static int ceph_writepages_start(struct address_space *mapping,
10941145 }
10951146
10961147new_request :
1097- offset = page_offset (pages [0 ]);
1148+ offset = ceph_fscrypt_page_offset (pages [0 ]);
10981149 len = wsize ;
10991150
11001151 req = ceph_osdc_new_request (& fsc -> client -> osdc ,
@@ -1115,8 +1166,8 @@ static int ceph_writepages_start(struct address_space *mapping,
11151166 ceph_wbc .truncate_size , true);
11161167 BUG_ON (IS_ERR (req ));
11171168 }
1118- BUG_ON (len < page_offset (pages [locked_pages - 1 ]) +
1119- thp_size (page ) - offset );
1169+ BUG_ON (len < ceph_fscrypt_page_offset (pages [locked_pages - 1 ]) +
1170+ thp_size (pages [ locked_pages - 1 ] ) - offset );
11201171
11211172 req -> r_callback = writepages_finish ;
11221173 req -> r_inode = inode ;
@@ -1126,7 +1177,9 @@ static int ceph_writepages_start(struct address_space *mapping,
11261177 data_pages = pages ;
11271178 op_idx = 0 ;
11281179 for (i = 0 ; i < locked_pages ; i ++ ) {
1129- u64 cur_offset = page_offset (pages [i ]);
1180+ struct page * page = ceph_fscrypt_pagecache_page (pages [i ]);
1181+
1182+ u64 cur_offset = page_offset (page );
11301183 /*
11311184 * Discontinuity in page range? Ceph can handle that by just passing
11321185 * multiple extents in the write op.
@@ -1155,9 +1208,9 @@ static int ceph_writepages_start(struct address_space *mapping,
11551208 op_idx ++ ;
11561209 }
11571210
1158- set_page_writeback (pages [ i ] );
1211+ set_page_writeback (page );
11591212 if (caching )
1160- ceph_set_page_fscache (pages [ i ] );
1213+ ceph_set_page_fscache (page );
11611214 len += thp_size (page );
11621215 }
11631216 ceph_fscache_write_to_cache (inode , offset , len , caching );
@@ -1173,8 +1226,16 @@ static int ceph_writepages_start(struct address_space *mapping,
11731226 offset );
11741227 len = max (len , min_len );
11751228 }
1229+ if (IS_ENCRYPTED (inode ))
1230+ len = round_up (len , CEPH_FSCRYPT_BLOCK_SIZE );
1231+
11761232 dout ("writepages got pages at %llu~%llu\n" , offset , len );
11771233
1234+ if (IS_ENCRYPTED (inode ) &&
1235+ ((offset | len ) & ~CEPH_FSCRYPT_BLOCK_MASK ))
1236+ pr_warn ("%s: bad encrypted write offset=%lld len=%llu\n" ,
1237+ __func__ , offset , len );
1238+
11781239 osd_req_op_extent_osd_data_pages (req , op_idx , data_pages , len ,
11791240 0 , from_pool , false);
11801241 osd_req_op_extent_update (req , op_idx , len );
0 commit comments