Hi Eric, Today's linux-next merge of the userns tree got a conflict in fs/libfs.c between commit 61ba64fc0768 ("libfs: simple_follow_link()") from the vfs tree and commit d5044ae07353 ("fs: Add helper functions for permanently empty directories.") from the userns tree. I fixed it up (see below) and can carry the fix as necessary (no action is required). -- Cheers, Stephen Rothwell sfr@xxxxxxxxxxxxxxxx diff --cc fs/libfs.c index 65e1feca8b98,02813592e121..000000000000 --- a/fs/libfs.c +++ b/fs/libfs.c @@@ -1097,14 -1094,98 +1097,109 @@@ simple_nosetlease(struct file *filp, lo } EXPORT_SYMBOL(simple_nosetlease); +const char *simple_follow_link(struct dentry *dentry, void **cookie) +{ + return d_inode(dentry)->i_link; +} +EXPORT_SYMBOL(simple_follow_link); + +const struct inode_operations simple_symlink_inode_operations = { + .follow_link = simple_follow_link, + .readlink = generic_readlink +}; +EXPORT_SYMBOL(simple_symlink_inode_operations); + + /* + * Operations for a permanently empty directory. + */ + static struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) + { + return ERR_PTR(-ENOENT); + } + + static int empty_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) + { + struct inode *inode = d_inode(dentry); + generic_fillattr(inode, stat); + return 0; + } + + static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr) + { + return -EPERM; + } + + static int empty_dir_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) + { + return -EOPNOTSUPP; + } + + static ssize_t empty_dir_getxattr(struct dentry *dentry, const char *name, + void *value, size_t size) + { + return -EOPNOTSUPP; + } + + static int empty_dir_removexattr(struct dentry *dentry, const char *name) + { + return -EOPNOTSUPP; + } + + static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size) + { + return -EOPNOTSUPP; + } + + static const struct inode_operations empty_dir_inode_operations = { + .lookup = empty_dir_lookup, + .permission = generic_permission, + .setattr = empty_dir_setattr, + .getattr = empty_dir_getattr, + .setxattr = empty_dir_setxattr, + .getxattr = empty_dir_getxattr, + .removexattr = empty_dir_removexattr, + .listxattr = empty_dir_listxattr, + }; + + static loff_t empty_dir_llseek(struct file *file, loff_t offset, int whence) + { + /* An empty directory has two entries . and .. at offsets 0 and 1 */ + return generic_file_llseek_size(file, offset, whence, 2, 2); + } + + static int empty_dir_readdir(struct file *file, struct dir_context *ctx) + { + dir_emit_dots(file, ctx); + return 0; + } + + static const struct file_operations empty_dir_operations = { + .llseek = empty_dir_llseek, + .read = generic_read_dir, + .iterate = empty_dir_readdir, + .fsync = noop_fsync, + }; + + + void make_empty_dir_inode(struct inode *inode) + { + set_nlink(inode, 2); + inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; + inode->i_uid = GLOBAL_ROOT_UID; + inode->i_gid = GLOBAL_ROOT_GID; + inode->i_rdev = 0; + inode->i_size = 2; + inode->i_blkbits = PAGE_SHIFT; + inode->i_blocks = 0; + + inode->i_op = &empty_dir_inode_operations; + inode->i_fop = &empty_dir_operations; + } + + bool is_empty_dir_inode(struct inode *inode) + { + return (inode->i_fop == &empty_dir_operations) && + (inode->i_op == &empty_dir_inode_operations); + }
Attachment:
pgpQMQm4Ur1BD.pgp
Description: OpenPGP digital signature