Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

erofs: make filesystem exportable

Implement export operations in order to make EROFS support accessing
inodes with filehandles so that it can be exported via NFS and used
by overlayfs.

Without this patch, 'exportfs -rv' will report:
exportfs: /root/erofs_mp does not support NFS export

Also tested with unionmount-testsuite and the testcase below passes now:
./run --ov --erofs --verify hard-link

For more details about the testcase, see:
https://github.com/amir73il/unionmount-testsuite/pull/6

Signed-off-by: Hongnan Li <hongnan.li@linux.alibaba.com>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Link: https://lore.kernel.org/r/20220425040712.91685-1-hongnan.li@linux.alibaba.com
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>

authored by

Hongnan Li and committed by
Gao Xiang
3e917cc3 dcbe6803

+43 -4
+1 -1
fs/erofs/internal.h
··· 484 484 /* namei.c */ 485 485 extern const struct inode_operations erofs_dir_iops; 486 486 487 - int erofs_namei(struct inode *dir, struct qstr *name, 487 + int erofs_namei(struct inode *dir, const struct qstr *name, 488 488 erofs_nid_t *nid, unsigned int *d_type); 489 489 490 490 /* dir.c */
+2 -3
fs/erofs/namei.c
··· 165 165 return candidate; 166 166 } 167 167 168 - int erofs_namei(struct inode *dir, 169 - struct qstr *name, 170 - erofs_nid_t *nid, unsigned int *d_type) 168 + int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid, 169 + unsigned int *d_type) 171 170 { 172 171 int ndirents; 173 172 struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
+40
fs/erofs/super.c
··· 13 13 #include <linux/fs_context.h> 14 14 #include <linux/fs_parser.h> 15 15 #include <linux/dax.h> 16 + #include <linux/exportfs.h> 16 17 #include "xattr.h" 17 18 18 19 #define CREATE_TRACE_POINTS ··· 578 577 static int erofs_init_managed_cache(struct super_block *sb) { return 0; } 579 578 #endif 580 579 580 + static struct inode *erofs_nfs_get_inode(struct super_block *sb, 581 + u64 ino, u32 generation) 582 + { 583 + return erofs_iget(sb, ino, false); 584 + } 585 + 586 + static struct dentry *erofs_fh_to_dentry(struct super_block *sb, 587 + struct fid *fid, int fh_len, int fh_type) 588 + { 589 + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 590 + erofs_nfs_get_inode); 591 + } 592 + 593 + static struct dentry *erofs_fh_to_parent(struct super_block *sb, 594 + struct fid *fid, int fh_len, int fh_type) 595 + { 596 + return generic_fh_to_parent(sb, fid, fh_len, fh_type, 597 + erofs_nfs_get_inode); 598 + } 599 + 600 + static struct dentry *erofs_get_parent(struct dentry *child) 601 + { 602 + erofs_nid_t nid; 603 + unsigned int d_type; 604 + int err; 605 + 606 + err = erofs_namei(d_inode(child), &dotdot_name, &nid, &d_type); 607 + if (err) 608 + return ERR_PTR(err); 609 + return d_obtain_alias(erofs_iget(child->d_sb, nid, d_type == FT_DIR)); 610 + } 611 + 612 + static const struct export_operations erofs_export_ops = { 613 + .fh_to_dentry = erofs_fh_to_dentry, 614 + .fh_to_parent = erofs_fh_to_parent, 615 + .get_parent = erofs_get_parent, 616 + }; 617 + 581 618 static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) 582 619 { 583 620 struct inode *inode; ··· 658 619 659 620 sb->s_op = &erofs_sops; 660 621 sb->s_xattr = erofs_xattr_handlers; 622 + sb->s_export_op = &erofs_export_ops; 661 623 662 624 if (test_opt(&sbi->opt, POSIX_ACL)) 663 625 sb->s_flags |= SB_POSIXACL;