@@ -29,7 +29,6 @@ struct dfuse_info {
2929 char * di_mountpoint ;
3030 int32_t di_thread_count ;
3131 uint32_t di_eq_count ;
32- bool di_threaded ;
3332 bool di_foreground ;
3433 bool di_caching ;
3534 bool di_multi_user ;
@@ -96,6 +95,9 @@ struct dfuse_eq {
9695 * memory consumption */
9796#define DFUSE_MAX_PRE_READ (1024 * 1024 * 4)
9897
98+ /* Maximum file-size for pre-read in all cases */
99+ #define DFUSE_MAX_PRE_READ_ONCE (1024 * 1024 * 1)
100+
99101/* Launch fuse, and do not return until complete */
100102int
101103dfuse_launch_fuse (struct dfuse_info * dfuse_info , struct fuse_args * args );
@@ -137,9 +139,10 @@ struct dfuse_inode_entry;
137139 * when EOF is returned to the kernel. If it's still present on release then it's freed then.
138140 */
139141struct dfuse_pre_read {
140- pthread_mutex_t dra_lock ;
142+ d_list_t req_list ;
141143 struct dfuse_event * dra_ev ;
142144 int dra_rc ;
145+ bool complete ;
143146};
144147
145148/** what is returned as the handle for fuse fuse_file_info on create/open/opendir */
@@ -149,8 +152,6 @@ struct dfuse_obj_hdl {
149152 /** the DFS object handle. Not created for directories. */
150153 dfs_obj_t * doh_obj ;
151154
152- struct dfuse_pre_read * doh_readahead ;
153-
154155 /** the inode entry for the file */
155156 struct dfuse_inode_entry * doh_ie ;
156157
@@ -169,17 +170,24 @@ struct dfuse_obj_hdl {
169170 /* Pointer to the last returned drc entry */
170171 struct dfuse_readdir_c * doh_rd_nextc ;
171172
172- /* Linear read function, if a file is read from start to end then this normally requires
173- * a final read request at the end of the file that returns zero bytes. Detect this case
174- * and when the final read is detected then just return without a round trip.
175- * Store a flag for this being enabled (starts as true, but many I/O patterns will set it
176- * to false), the expected position of the next read and a boolean for if EOF has been
177- * detected.
173+ /* Linear read tracking. If a file is opened and read from start to finish then this is
174+ * called a linear read, linear reads however may or may not read EOF at the end of a file,
175+ * as the reader may be checking the file size.
176+ *
177+ * Detect this case and track it at the file handle level, this is then used in two places:
178+ * For read of EOF it means the round-trip can be avoided.
179+ * On release we can use this flag to apply a setting to the directory inode.
180+ *
181+ * This flag starts enabled and many I/O patterns will disable it. We also store the next
182+ * expected read position and if EOF has been reached.
178183 */
184+
179185 off_t doh_linear_read_pos ;
180186 bool doh_linear_read ;
181187 bool doh_linear_read_eof ;
182188
189+ bool doh_set_linear_read ;
190+
183191 /** True if caching is enabled for this file. */
184192 bool doh_caching ;
185193
@@ -197,6 +205,8 @@ struct dfuse_obj_hdl {
197205 bool doh_kreaddir_finished ;
198206
199207 bool doh_evict_on_close ;
208+ /* the handle is doing readhead for the moment */
209+ bool doh_readahead_inflight ;
200210};
201211
202212/* Readdir support.
@@ -401,11 +411,20 @@ struct dfuse_event {
401411 d_iov_t de_iov ;
402412 d_sg_list_t de_sgl ;
403413 d_list_t de_list ;
414+
415+ /* Position in a list of events, this will either be off active->open_reads or
416+ * de->de_read_slaves.
417+ */
418+ d_list_t de_read_list ;
419+ /* List of slave events */
420+ d_list_t de_read_slaves ;
404421 struct dfuse_eq * de_eqt ;
405422 union {
406423 struct dfuse_obj_hdl * de_oh ;
407424 struct dfuse_inode_entry * de_ie ;
425+ struct read_chunk_data * de_cd ;
408426 };
427+ struct dfuse_info * de_di ;
409428 off_t de_req_position ; /**< The file position requested by fuse */
410429 union {
411430 size_t de_req_len ;
@@ -1009,10 +1028,32 @@ struct dfuse_inode_entry {
10091028 */
10101029 ATOMIC bool ie_linear_read ;
10111030
1031+ struct active_inode * ie_active ;
1032+
10121033 /* Entry on the evict list */
10131034 d_list_t ie_evict_entry ;
10141035};
10151036
1037+ struct active_inode {
1038+ d_list_t chunks ;
1039+ d_list_t open_reads ;
1040+ pthread_spinlock_t lock ;
1041+ ATOMIC uint64_t read_count ;
1042+ struct dfuse_pre_read * readahead ;
1043+ };
1044+
1045+ /* Increase active count on inode. This takes a reference and allocates ie->active as required */
1046+ int
1047+ active_ie_init (struct dfuse_inode_entry * ie );
1048+
1049+ /* Mark a oh as closing and drop the ref on inode active */
1050+ void
1051+ active_oh_decref (struct dfuse_info * dfuse_info , struct dfuse_obj_hdl * oh );
1052+
1053+ /* Decrease active count on inode, called on error where there is no oh */
1054+ void
1055+ active_ie_decref (struct dfuse_info * dfuse_info , struct dfuse_inode_entry * ie );
1056+
10161057/* Flush write-back cache writes to a inode. It does this by waiting for and then releasing an
10171058 * exclusive lock on the inode. Writes take a shared lock so this will block until all pending
10181059 * writes are complete.
@@ -1108,6 +1149,13 @@ dfuse_compute_inode(struct dfuse_cont *dfs,
11081149void
11091150dfuse_cache_evict_dir (struct dfuse_info * dfuse_info , struct dfuse_inode_entry * ie );
11101151
1152+ /* Free any read chunk data for an inode.
1153+ *
1154+ * Returns true if feature was used.
1155+ */
1156+ bool
1157+ read_chunk_close (struct dfuse_inode_entry * ie );
1158+
11111159/* Metadata caching functions. */
11121160
11131161/* Mark the cache as up-to-date from now */
@@ -1171,7 +1219,15 @@ bool
11711219dfuse_dcache_get_valid (struct dfuse_inode_entry * ie , double max_age );
11721220
11731221void
1174- dfuse_pre_read (struct dfuse_info * dfuse_info , struct dfuse_obj_hdl * oh );
1222+ dfuse_pre_read (struct dfuse_info * dfuse_info , struct dfuse_obj_hdl * oh , struct dfuse_event * ev );
1223+
1224+ int
1225+ dfuse_pre_read_init (struct dfuse_info * dfuse_info , struct dfuse_inode_entry * ie ,
1226+ struct dfuse_event * * evp );
1227+
1228+ void
1229+ dfuse_pre_read_abort (struct dfuse_info * dfuse_info , struct dfuse_obj_hdl * oh ,
1230+ struct dfuse_event * ev , int rc );
11751231
11761232int
11771233check_for_uns_ep (struct dfuse_info * dfuse_info , struct dfuse_inode_entry * ie , char * attr ,
0 commit comments