static long f2fs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); long ret; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) return -EOPNOTSUPP; mutex_lock(&inode->i_mutex); if (mode & FALLOC_FL_PUNCH_HOLE) ret = punch_hole(inode, offset, len); else ret = expand_inode_data(inode, offset, len, mode); if (!ret) { inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); } mutex_unlock(&inode->i_mutex); trace_f2fs_fallocate(inode, mode, offset, len, ret); return ret; }
int dedup_one_iovec(struct page_read *pr, struct iovec *iov) { unsigned long off; unsigned long off_real; unsigned long iov_end; iov_end = (unsigned long)iov->iov_base + iov->iov_len; off = (unsigned long)iov->iov_base; while (1) { int ret; struct iovec piov; unsigned long piov_end; struct iovec tiov; struct page_read * prp; ret = seek_pagemap_page(pr, off, false); if (ret == -1) return -1; if (ret == 0) { if (off < pr->cvaddr && pr->cvaddr < iov_end) off = pr->cvaddr; else return 0; } if (!pr->pe) return -1; pagemap2iovec(pr->pe, &piov); piov_end = (unsigned long)piov.iov_base + piov.iov_len; off_real = lseek(img_raw_fd(pr->pi), 0, SEEK_CUR); if (!pr->pe->in_parent) { ret = punch_hole(pr, off_real, min(piov_end, iov_end) - off, false); if (ret == -1) return ret; } prp = pr->parent; if (prp) { /* recursively */ pr_debug("Go to next parent level\n"); tiov.iov_base = (void*)off; tiov.iov_len = min(piov_end, iov_end) - off; ret = dedup_one_iovec(prp, &tiov); if (ret != 0) return -1; } if (piov_end < iov_end) { off = piov_end; continue; } else return 0; } return 0; }
static int f2fs_ioc_release_volatile_write(struct file *filp) { struct inode *inode = file_inode(filp); if (!inode_owner_or_capable(inode)) return -EACCES; if (!f2fs_is_volatile_file(inode)) return 0; punch_hole(inode, 0, F2FS_BLKSIZE); return 0; }
static int restore_shmem_content(void *addr, struct shmem_info *si) { int ret = 0; struct page_read pr; unsigned long off_real; ret = open_page_read(si->shmid, &pr, opts.auto_dedup ? O_RDWR : O_RSTR, true); if (ret) goto err_unmap; while (1) { unsigned long vaddr; unsigned nr_pages; struct iovec iov; ret = pr.get_pagemap(&pr, &iov); if (ret <= 0) break; vaddr = (unsigned long)iov.iov_base; nr_pages = iov.iov_len / PAGE_SIZE; if (vaddr + nr_pages * PAGE_SIZE > si->size) break; off_real = lseek(pr.fd_pg, 0, SEEK_CUR); ret = read(pr.fd_pg, addr + vaddr, nr_pages * PAGE_SIZE); if (ret != nr_pages * PAGE_SIZE) { ret = -1; break; } if (opts.auto_dedup) { ret = punch_hole(&pr, off_real, nr_pages * PAGE_SIZE, false); if (ret == -1) { break; } } if (pr.put_pagemap) pr.put_pagemap(&pr); } pr.close(&pr); return ret; err_unmap: munmap(addr, si->size); return -1; }
static int f2fs_ioc_release_volatile_write(struct file *filp) { struct inode *inode = file_inode(filp); if (!inode_owner_or_capable(inode)) return -EACCES; if (!f2fs_is_volatile_file(inode)) return 0; if (!f2fs_is_first_block_written(inode)) return truncate_partial_data_page(inode, 0, true); return punch_hole(inode, 0, F2FS_BLKSIZE); }
static long f2fs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); long ret = 0; /* f2fs only support ->fallocate for regular file */ if (!S_ISREG(inode->i_mode)) return -EINVAL; if (f2fs_encrypted_inode(inode) && (mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE))) return -EOPNOTSUPP; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE)) return -EOPNOTSUPP; inode_lock(inode); if (mode & FALLOC_FL_PUNCH_HOLE) { if (offset >= inode->i_size) goto out; ret = punch_hole(inode, offset, len); } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { ret = f2fs_collapse_range(inode, offset, len); } else if (mode & FALLOC_FL_ZERO_RANGE) { ret = f2fs_zero_range(inode, offset, len, mode); } else if (mode & FALLOC_FL_INSERT_RANGE) { ret = f2fs_insert_range(inode, offset, len); } else { ret = expand_inode_data(inode, offset, len, mode); } if (!ret) { inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); } out: inode_unlock(inode); trace_f2fs_fallocate(inode, mode, offset, len, ret); return ret; }
static long f2fs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); long ret = 0; if (f2fs_encrypted_inode(inode) && (mode & (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_INSERT_RANGE))) return -EOPNOTSUPP; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE)) return -EOPNOTSUPP; mutex_lock(&inode->i_mutex); if (mode & FALLOC_FL_PUNCH_HOLE) { if (offset >= inode->i_size) goto out; ret = punch_hole(inode, offset, len); } else if (mode & FALLOC_FL_COLLAPSE_RANGE) { ret = f2fs_collapse_range(inode, offset, len); } else if (mode & FALLOC_FL_ZERO_RANGE) { ret = f2fs_zero_range(inode, offset, len, mode); } else if (mode & FALLOC_FL_INSERT_RANGE) { ret = f2fs_insert_range(inode, offset, len); } else { ret = expand_inode_data(inode, offset, len, mode); } if (!ret) { inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); } out: mutex_unlock(&inode->i_mutex); trace_f2fs_fallocate(inode, mode, offset, len, ret); return ret; }
// Allocate space for file from offset to offset+len static long hmfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file_inode(file); long ret = 0; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) return -EOPNOTSUPP; if (S_ISDIR(inode->i_mode)) return -ENODEV; if (mode & FALLOC_FL_PUNCH_HOLE) ret = punch_hole(inode, offset, len, mode); else ret = expand_inode_data(inode, offset, len, mode); if (!ret) { inode->i_mtime = inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); } return ret; }