diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 467093acadbb89..a0ac055ba246d5 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1199,7 +1199,8 @@ static void fuse_readahead(struct readahead_control *rac) static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to) { - struct inode *inode = iocb->ki_filp->f_mapping->host; + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); /* @@ -1215,6 +1216,12 @@ static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to) return err; } + /* if we have dlm support acquire a read lock for the area + * we are reading from. */ + if (fc->writeback_cache && fc->dlm) + fuse_get_dlm_lock(file, iocb->ki_pos, + iov_iter_count(to), FUSE_PAGE_LOCK_READ); + return generic_file_read_iter(iocb, to); } @@ -1708,7 +1715,8 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from) iocb->ki_pos; size_t length = iov_iter_count(from); - fuse_get_dlm_write_lock(file, pos, length); + fuse_get_dlm_lock(file, pos, length, + FUSE_PAGE_LOCK_WRITE); } } } @@ -2570,7 +2578,7 @@ static void fuse_vma_close(struct vm_area_struct *vma) /** * Request a DLM lock from the FUSE server. * - * This routine is similar to fuse_get_dlm_write_lock(), but it + * This routine is similar to fuse_get_dlm_lock(), but it * does not cache the DLM lock in the kernel. */ static int fuse_get_page_mkwrite_lock(struct file *file, loff_t offset, size_t length) diff --git a/fs/fuse/fuse_dlm_cache.c b/fs/fuse/fuse_dlm_cache.c index d765dd8018cc6a..ea296a2e9ec89c 100644 --- a/fs/fuse/fuse_dlm_cache.c +++ b/fs/fuse/fuse_dlm_cache.c @@ -487,10 +487,14 @@ bool fuse_dlm_range_is_locked(struct fuse_inode *inode, uint64_t start, } /** - * request a dlm lock from the fuse server + * fuse_get_dlm_lock - request a dlm lock from the fuse server + * @file: the file being accessed + * @offset: byte offset into the file (need not be page-aligned) + * @length: length of the region in bytes (need not be page-aligned) + * @mode: FUSE_PAGE_LOCK_READ or FUSE_PAGE_LOCK_WRITE */ -void fuse_get_dlm_write_lock(struct file *file, loff_t offset, - size_t length) +void fuse_get_dlm_lock(struct file *file, loff_t offset, + size_t length, enum fuse_page_lock_mode mode) { struct fuse_file *ff = file->private_data; struct inode *inode = file_inode(file); @@ -500,7 +504,7 @@ void fuse_get_dlm_write_lock(struct file *file, loff_t offset, uint64_t end = (offset + length - 1) | (PAGE_SIZE - 1); /* note that the offset and length don't have to be page aligned here - * but since we only get here on writeback caching we will send out + * but since we only get here on writeback caching we will send out * page aligned requests */ offset &= PAGE_MASK; @@ -513,8 +517,7 @@ void fuse_get_dlm_write_lock(struct file *file, loff_t offset, * at the same time. It is intentionally not protected * since a DLM implementation in the FUSE server should take care * of any races in lock requests */ - if (fuse_dlm_range_is_locked(fi, offset, - end, FUSE_PAGE_LOCK_WRITE)) + if (fuse_dlm_range_is_locked(fi, offset, end, mode)) return; /* we already have this area locked */ memset(&inarg, 0, sizeof(inarg)); @@ -522,7 +525,8 @@ void fuse_get_dlm_write_lock(struct file *file, loff_t offset, inarg.start = offset; inarg.end = end; - inarg.type = FUSE_DLM_LOCK_WRITE; + inarg.type = (mode == FUSE_PAGE_LOCK_WRITE) ? + FUSE_DLM_LOCK_WRITE : FUSE_DLM_LOCK_READ; args.opcode = FUSE_DLM_WB_LOCK; args.nodeid = get_node_id(inode); @@ -551,8 +555,6 @@ void fuse_get_dlm_write_lock(struct file *file, loff_t offset, return; } else { /* ignore any errors here, there is no way we can react appropriately */ - fuse_dlm_lock_range(fi, outarg.start, - outarg.end, - FUSE_PAGE_LOCK_WRITE); + fuse_dlm_lock_range(fi, outarg.start, outarg.end, mode); } } diff --git a/fs/fuse/fuse_dlm_cache.h b/fs/fuse/fuse_dlm_cache.h index 438d31d28b666e..5c3deaa3536866 100644 --- a/fs/fuse/fuse_dlm_cache.h +++ b/fs/fuse/fuse_dlm_cache.h @@ -43,8 +43,8 @@ int fuse_dlm_unlock_range(struct fuse_inode *inode, uint64_t start, bool fuse_dlm_range_is_locked(struct fuse_inode *inode, uint64_t start, uint64_t end, enum fuse_page_lock_mode mode); -/* this is the interface to the filesystem */ -void fuse_get_dlm_write_lock(struct file *file, loff_t offset, - size_t length); +/* This is the interface to the filesystem */ +void fuse_get_dlm_lock(struct file *file, loff_t offset, + size_t length, enum fuse_page_lock_mode mode); #endif /* _FS_FUSE_DLM_CACHE_H */