@@ -255,7 +255,7 @@ static int simplefs_write_end(struct file *file,
255255 * over the data block pointers, releasing the associated data blocks, and
256256 * updating the inode metadata (size and block count).
257257 */
258- static int simplefs_file_open (struct inode * inode , struct file * filp )
258+ static int simplefs_open (struct inode * inode , struct file * filp )
259259{
260260 bool wronly = (filp -> f_flags & O_WRONLY );
261261 bool rdwr = (filp -> f_flags & O_RDWR );
@@ -293,6 +293,170 @@ static int simplefs_file_open(struct inode *inode, struct file *filp)
293293 return 0 ;
294294}
295295
296+ static ssize_t simplefs_read (struct file * file ,
297+ char __user * buf ,
298+ size_t len ,
299+ loff_t * ppos )
300+ {
301+ struct inode * inode = file_inode (file );
302+ struct super_block * sb = inode -> i_sb ;
303+ ssize_t bytes_read = 0 ;
304+ loff_t pos = * ppos ;
305+
306+ if (pos > inode -> i_size )
307+ return 0 ;
308+
309+ /* find extent block */
310+ struct buffer_head * bh = sb_bread (sb , SIMPLEFS_INODE (inode )-> ei_block );
311+ struct simplefs_file_ei_block * ei_block =
312+ (struct simplefs_file_ei_block * ) bh -> b_data ;
313+
314+
315+ if (pos + len > inode -> i_size )
316+ len = inode -> i_size - pos ;
317+
318+ /* count block position */
319+ sector_t block_index = pos / SIMPLEFS_BLOCK_SIZE ;
320+ sector_t ei_index = block_index / SIMPLEFS_MAX_BLOCKS_PER_EXTENT ;
321+ sector_t block_offset = ei_block -> extents [ei_index ].ee_start +
322+ block_index % SIMPLEFS_MAX_BLOCKS_PER_EXTENT ;
323+
324+ while (len > 0 ) {
325+ struct buffer_head * bh_data = sb_bread (sb , block_offset );
326+ if (!bh_data ) {
327+ pr_err ("Failed to read data block %llu\n" , block_offset );
328+ bytes_read = - EIO ;
329+ break ;
330+ }
331+
332+ size_t offset = pos % SIMPLEFS_BLOCK_SIZE ;
333+ size_t bytes_to_read =
334+ min_t (size_t , len , SIMPLEFS_BLOCK_SIZE - pos % SIMPLEFS_BLOCK_SIZE );
335+ if (copy_to_user (buf + bytes_read , bh_data -> b_data + offset ,
336+ bytes_to_read )) {
337+ brelse (bh_data );
338+ bytes_read = - EFAULT ;
339+ break ;
340+ }
341+ brelse (bh_data );
342+
343+ /* successfully read data */
344+ bytes_read += bytes_to_read ;
345+ len -= bytes_to_read ;
346+ pos += bytes_to_read ;
347+
348+ /* count extent block */
349+ block_index ++ ;
350+ ei_index = block_index / SIMPLEFS_MAX_BLOCKS_PER_EXTENT ;
351+ block_offset = ei_block -> extents [ei_index ].ee_start +
352+ block_index % SIMPLEFS_MAX_BLOCKS_PER_EXTENT ;
353+ }
354+
355+ brelse (bh );
356+ * ppos = pos ;
357+
358+ return bytes_read ;
359+ }
360+
361+ static ssize_t simplefs_write (struct file * file ,
362+ const char __user * buf ,
363+ size_t len ,
364+ loff_t * ppos )
365+ {
366+ struct inode * inode = file_inode (file );
367+ struct super_block * sb = inode -> i_sb ;
368+ ssize_t bytes_write = 0 ;
369+ loff_t pos = * ppos ;
370+
371+ if (pos > inode -> i_size )
372+ return 0 ;
373+ len = min_t (size_t , len , SIMPLEFS_MAX_FILESIZE - pos );
374+
375+ /* find extent block */
376+ struct buffer_head * bh = sb_bread (sb , SIMPLEFS_INODE (inode )-> ei_block );
377+ if (!bh )
378+ return - EIO ;
379+ struct simplefs_file_ei_block * ei_block =
380+ (struct simplefs_file_ei_block * ) bh -> b_data ;
381+
382+ /* count block position */
383+ sector_t block_index = pos / SIMPLEFS_BLOCK_SIZE ;
384+ sector_t ei_index = block_index / SIMPLEFS_MAX_BLOCKS_PER_EXTENT ;
385+
386+ /* write data */
387+ while (len > 0 ) {
388+ /* check if block is allocated */
389+ if (ei_block -> extents [ei_index ].ee_start == 0 ) {
390+ int bno = get_free_blocks (sb , 8 );
391+ if (!bno ) {
392+ bytes_write = - ENOSPC ;
393+ break ;
394+ }
395+ ei_block -> extents [ei_index ].ee_start = bno ;
396+ ei_block -> extents [ei_index ].ee_len = 8 ;
397+ ei_block -> extents [ei_index ].ee_block =
398+ ei_index ? ei_block -> extents [ei_index - 1 ].ee_block +
399+ ei_block -> extents [ei_index - 1 ].ee_len
400+ : 0 ;
401+ }
402+
403+ struct buffer_head * bh_data =
404+ sb_bread (sb , ei_block -> extents [ei_index ].ee_start +
405+ block_index % SIMPLEFS_MAX_BLOCKS_PER_EXTENT );
406+ if (!bh_data ) {
407+ pr_err ("Failed to read data block %llu\n" ,
408+ ei_block -> extents [ei_index ].ee_start +
409+ block_index % SIMPLEFS_MAX_BLOCKS_PER_EXTENT );
410+ bytes_write = - EIO ;
411+ break ;
412+ }
413+ /* copy data from buffer */
414+ size_t bytes_to_write =
415+ min_t (size_t , len , SIMPLEFS_BLOCK_SIZE - pos % SIMPLEFS_BLOCK_SIZE );
416+
417+ if (copy_from_user (bh_data -> b_data + pos % SIMPLEFS_BLOCK_SIZE , buf ,
418+ bytes_to_write )) {
419+ brelse (bh_data );
420+ bytes_write = - EFAULT ;
421+ break ;
422+ }
423+
424+ mark_buffer_dirty (bh_data );
425+ sync_dirty_buffer (bh_data );
426+ brelse (bh_data );
427+
428+ /* successfully write data */
429+ len = len - bytes_to_write ;
430+ bytes_write += bytes_to_write ;
431+ pos += bytes_to_write ;
432+
433+ /* count extent block */
434+ block_index = pos / SIMPLEFS_BLOCK_SIZE ;
435+ ei_index = block_index / SIMPLEFS_MAX_BLOCKS_PER_EXTENT ;
436+ }
437+ mark_buffer_dirty (bh );
438+ sync_dirty_buffer (bh );
439+ brelse (bh );
440+
441+ inode -> i_size = max (pos , inode -> i_size );
442+ inode -> i_blocks = DIV_ROUND_UP (inode -> i_size , SIMPLEFS_BLOCK_SIZE ) + 1 ;
443+ #if SIMPLEFS_AT_LEAST (6 , 7 , 0 )
444+ struct timespec64 cur_time = current_time (inode );
445+ inode_set_mtime_to_ts (inode , cur_time );
446+ inode_set_ctime_to_ts (inode , cur_time );
447+ #elif SIMPLEFS_AT_LEAST (6 , 6 , 0 )
448+ struct timespec64 cur_time = current_time (inode );
449+ inode -> i_mtime = cur_time ;
450+ inode_set_ctime_to_ts (inode , cur_time );
451+ #else
452+ inode -> i_mtime = inode -> i_ctime = current_time (inode );
453+ #endif
454+ mark_inode_dirty (inode );
455+ * ppos = pos ;
456+
457+ return bytes_write ;
458+ }
459+
296460const struct address_space_operations simplefs_aops = {
297461#if SIMPLEFS_AT_LEAST (5 , 19 , 0 )
298462 .readahead = simplefs_readahead ,
@@ -310,5 +474,7 @@ const struct file_operations simplefs_file_ops = {
310474 .read_iter = generic_file_read_iter ,
311475 .write_iter = generic_file_write_iter ,
312476 .fsync = generic_file_fsync ,
313- .open = simplefs_file_open ,
477+ .open = simplefs_open ,
478+ .read = simplefs_read , /*if exist, read_iter will not be called*/
479+ .write = simplefs_write , /*if exist, write_iter will not be called*/
314480};
0 commit comments