diff options
Diffstat (limited to 'fs')
40 files changed, 210 insertions, 120 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 699941e90667..8ba5a897fc0a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1223,18 +1223,25 @@ ino_t v9fs_qid2ino(struct p9_qid *qid) } /** - * v9fs_vfs_follow_link - follow a symlink path + * v9fs_vfs_get_link - follow a symlink path * @dentry: dentry for symlink + * @inode: inode for symlink * @cookie: place to pass the data to put_link() */ -static const char *v9fs_vfs_follow_link(struct dentry *dentry, void **cookie) +static const char *v9fs_vfs_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry); - struct p9_fid *fid = v9fs_fid_lookup(dentry); + struct v9fs_session_info *v9ses; + struct p9_fid *fid; struct p9_wstat *st; char *res; + if (!dentry) + return ERR_PTR(-ECHILD); + + v9ses = v9fs_dentry2v9ses(dentry); + fid = v9fs_fid_lookup(dentry); p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); if (IS_ERR(fid)) @@ -1452,7 +1459,7 @@ static const struct inode_operations v9fs_file_inode_operations = { static const struct inode_operations v9fs_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link, + .get_link = v9fs_vfs_get_link, .put_link = kfree_put_link, .getattr = v9fs_vfs_getattr, .setattr = v9fs_vfs_setattr, diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index cb899af1babc..0cc105d804dd 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -899,20 +899,26 @@ error: } /** - * v9fs_vfs_follow_link_dotl - follow a symlink path + * v9fs_vfs_get_link_dotl - follow a symlink path * @dentry: dentry for symlink + * @inode: inode for symlink * @cookie: place to pass the data to put_link() */ static const char * -v9fs_vfs_follow_link_dotl(struct dentry *dentry, void **cookie) +v9fs_vfs_get_link_dotl(struct dentry *dentry, + struct inode *inode, void **cookie) { - struct p9_fid *fid = v9fs_fid_lookup(dentry); + struct p9_fid *fid; char *target; int retval; + if (!dentry) + return ERR_PTR(-ECHILD); + p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); + fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) return ERR_CAST(fid); retval = p9_client_readlink(fid, &target); @@ -984,7 +990,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = { const struct inode_operations v9fs_symlink_inode_operations_dotl = { .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link_dotl, + .get_link = v9fs_vfs_get_link_dotl, .put_link = kfree_put_link, .getattr = v9fs_vfs_getattr_dotl, .setattr = v9fs_vfs_setattr_dotl, diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index e3f9dc3ae8cc..39d1194445e1 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c @@ -20,7 +20,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page) char c; char lc; - pr_debug("follow_link(ino=%lu)\n", inode->i_ino); + pr_debug("get_link(ino=%lu)\n", inode->i_ino); bh = affs_bread(inode->i_sb, inode->i_ino); if (!bh) @@ -71,7 +71,7 @@ const struct address_space_operations affs_symlink_aops = { const struct inode_operations affs_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .setattr = affs_notify_change, }; diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index da0c33481bc0..39e6f0bdf8e3 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -12,10 +12,15 @@ #include "autofs_i.h" -static const char *autofs4_follow_link(struct dentry *dentry, void **cookie) +static const char *autofs4_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); - struct autofs_info *ino = autofs4_dentry_ino(dentry); + struct autofs_sb_info *sbi; + struct autofs_info *ino; + if (!dentry) + return ERR_PTR(-ECHILD); + sbi = autofs4_sbi(dentry->d_sb); + ino = autofs4_dentry_ino(dentry); if (ino && !autofs4_oz_mode(sbi)) ino->last_used = jiffies; return d_inode(dentry)->i_private; @@ -23,5 +28,5 @@ static const char *autofs4_follow_link(struct dentry *dentry, void **cookie) const struct inode_operations autofs4_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = autofs4_follow_link + .get_link = autofs4_get_link }; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 70f98bfde277..3d4aa69f1e0c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -10096,7 +10096,7 @@ static const struct inode_operations btrfs_special_inode_operations = { }; static const struct inode_operations btrfs_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .getattr = btrfs_getattr, .setattr = btrfs_setattr, diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 498dcfa2dcdb..da55eb8bcffa 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1756,7 +1756,7 @@ retry: */ static const struct inode_operations ceph_symlink_iops = { .readlink = generic_readlink, - .follow_link = simple_follow_link, + .get_link = simple_get_link, .setattr = ceph_setattr, .getattr = ceph_getattr, .setxattr = ceph_setxattr, diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index cbc0f4bca0c0..4593f41678ef 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -900,7 +900,7 @@ const struct inode_operations cifs_file_inode_ops = { const struct inode_operations cifs_symlink_inode_ops = { .readlink = generic_readlink, - .follow_link = cifs_follow_link, + .get_link = cifs_get_link, .put_link = kfree_put_link, .permission = cifs_permission, /* BB add the following two eventually */ diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index c3cc1609025f..6886328cf3c4 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -120,9 +120,7 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path); #endif /* Functions related to symlinks */ -extern const char *cifs_follow_link(struct dentry *direntry, void **cookie); -extern int cifs_readlink(struct dentry *direntry, char __user *buffer, - int buflen); +extern const char *cifs_get_link(struct dentry *, struct inode *, void **); extern int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname); extern int cifs_removexattr(struct dentry *, const char *); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index e3548f73bdea..6f2439b508b5 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -627,9 +627,8 @@ cifs_hl_exit: } const char * -cifs_follow_link(struct dentry *direntry, void **cookie) +cifs_get_link(struct dentry *direntry, struct inode *inode, void **cookie) { - struct inode *inode = d_inode(direntry); int rc = -ENOMEM; unsigned int xid; char *full_path = NULL; @@ -639,6 +638,9 @@ cifs_follow_link(struct dentry *direntry, void **cookie) struct cifs_tcon *tcon; struct TCP_Server_Info *server; + if (!direntry) + return ERR_PTR(-ECHILD); + xid = get_xid(); tlink = cifs_sb_tlink(cifs_sb); diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index dd6a79ef4750..f18139c7690a 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -18,7 +18,7 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) static const struct inode_operations coda_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .setattr = coda_setattr, }; diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index ec5c8325b503..b91c01ebb688 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -279,11 +279,16 @@ static int configfs_getlink(struct dentry *dentry, char * path) } -static const char *configfs_follow_link(struct dentry *dentry, void **cookie) +static const char *configfs_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - unsigned long page = get_zeroed_page(GFP_KERNEL); + unsigned long page; int error; + if (!dentry) + return ERR_PTR(-ECHILD); + + page = get_zeroed_page(GFP_KERNEL); if (!page) return ERR_PTR(-ENOMEM); @@ -297,7 +302,7 @@ static const char *configfs_follow_link(struct dentry *dentry, void **cookie) } const struct inode_operations configfs_symlink_inode_operations = { - .follow_link = configfs_follow_link, + .get_link = configfs_get_link, .readlink = generic_readlink, .put_link = free_page_put_link, .setattr = configfs_setattr, diff --git a/fs/dcache.c b/fs/dcache.c index 5c33aeb0f68f..d27f0909d9f6 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1734,7 +1734,7 @@ static unsigned d_flags_for_inode(struct inode *inode) } if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) { - if (unlikely(inode->i_op->follow_link)) { + if (unlikely(inode->i_op->get_link)) { add_flags = DCACHE_SYMLINK_TYPE; goto type_determined; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index e2e47ba5d313..5a05559cb23d 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -674,10 +674,16 @@ out: return rc ? ERR_PTR(rc) : buf; } -static const char *ecryptfs_follow_link(struct dentry *dentry, void **cookie) +static const char *ecryptfs_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { size_t len; - char *buf = ecryptfs_readlink_lower(dentry, &len); + char *buf; + + if (!dentry) + return ERR_PTR(-ECHILD); + + buf = ecryptfs_readlink_lower(dentry, &len); if (IS_ERR(buf)) return buf; fsstack_copy_attr_atime(d_inode(dentry), @@ -1095,7 +1101,7 @@ out: const struct inode_operations ecryptfs_symlink_iops = { .readlink = generic_readlink, - .follow_link = ecryptfs_follow_link, + .get_link = ecryptfs_get_link, .put_link = kfree_put_link, .permission = ecryptfs_permission, .setattr = ecryptfs_setattr, diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index ae17179f3810..46905119a27c 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -22,7 +22,7 @@ const struct inode_operations ext2_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .setattr = ext2_setattr, #ifdef CONFIG_EXT2_FS_XATTR @@ -35,7 +35,7 @@ const struct inode_operations ext2_symlink_inode_operations = { const struct inode_operations ext2_fast_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = simple_follow_link, + .get_link = simple_get_link, .setattr = ext2_setattr, #ifdef CONFIG_EXT2_FS_XATTR .setxattr = generic_setxattr, diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 0e6dc44c5ebf..3b4bfe2ebd75 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c @@ -23,17 +23,20 @@ #include "xattr.h" #ifdef CONFIG_EXT4_FS_ENCRYPTION -static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cookie) +static const char *ext4_encrypted_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { struct page *cpage = NULL; char *caddr, *paddr = NULL; struct ext4_str cstr, pstr; - struct inode *inode = d_inode(dentry); struct ext4_encrypted_symlink_data *sd; loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1); int res; u32 plen, max_size = inode->i_sb->s_blocksize; + if (!dentry) + return ERR_PTR(-ECHILD); + res = ext4_get_encryption_info(inode); if (res) return ERR_PTR(res); @@ -87,7 +90,7 @@ errout: const struct inode_operations ext4_encrypted_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = ext4_encrypted_follow_link, + .get_link = ext4_encrypted_get_link, .put_link = kfree_put_link, .setattr = ext4_setattr, .setxattr = generic_setxattr, @@ -99,7 +102,7 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = { const struct inode_operations ext4_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .setattr = ext4_setattr, .setxattr = generic_setxattr, @@ -110,7 +113,7 @@ const struct inode_operations ext4_symlink_inode_operations = { const struct inode_operations ext4_fast_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = simple_follow_link, + .get_link = simple_get_link, .setattr = ext4_setattr, .setxattr = generic_setxattr, .getxattr = generic_getxattr, diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 484df6850747..2a8d84b727ce 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -315,9 +315,10 @@ fail: return err; } -static const char *f2fs_follow_link(struct dentry *dentry, void **cookie) +static const char *f2fs_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - const char *link = page_follow_link_light(dentry, cookie); + const char *link = page_get_link(dentry, inode, cookie); if (!IS_ERR(link) && !*link) { /* this is broken symlink case */ page_put_link(NULL, *cookie); @@ -924,18 +925,21 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry, } #ifdef CONFIG_F2FS_FS_ENCRYPTION -static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cookie) +static const char *f2fs_encrypted_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { struct page *cpage = NULL; char *caddr, *paddr = NULL; struct f2fs_str cstr; struct f2fs_str pstr = FSTR_INIT(NULL, 0); - struct inode *inode = d_inode(dentry); struct f2fs_encrypted_symlink_data *sd; loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1); u32 max_size = inode->i_sb->s_blocksize; int res; + if (!dentry) + return ERR_PTR(-ECHILD); + res = f2fs_get_encryption_info(inode); if (res) return ERR_PTR(res); @@ -994,7 +998,7 @@ errout: const struct inode_operations f2fs_encrypted_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = f2fs_encrypted_follow_link, + .get_link = f2fs_encrypted_get_link, .put_link = kfree_put_link, .getattr = f2fs_getattr, .setattr = f2fs_setattr, @@ -1030,7 +1034,7 @@ const struct inode_operations f2fs_dir_inode_operations = { const struct inode_operations f2fs_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = f2fs_follow_link, + .get_link = f2fs_get_link, .put_link = page_put_link, .getattr = f2fs_getattr, .setattr = f2fs_setattr, diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 5e2e08712d3b..148e8ef7c541 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1365,14 +1365,17 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx) return err; } -static const char *fuse_follow_link(struct dentry *dentry, void **cookie) +static const char *fuse_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - struct inode *inode = d_inode(dentry); struct fuse_conn *fc = get_fuse_conn(inode); FUSE_ARGS(args); char *link; ssize_t ret; + if (!dentry) + return ERR_PTR(-ECHILD); + link = (char *) __get_free_page(GFP_KERNEL); if (!link) return ERR_PTR(-ENOMEM); @@ -1909,7 +1912,7 @@ static const struct inode_operations fuse_common_inode_operations = { static const struct inode_operations fuse_symlink_inode_operations = { .setattr = fuse_setattr, - .follow_link = fuse_follow_link, + .get_link = fuse_get_link, .put_link = free_page_put_link, .readlink = generic_readlink, .getattr = fuse_getattr, diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 063fdfcf8275..1095056046cc 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1712,24 +1712,29 @@ static int gfs2_rename2(struct inode *odir, struct dentry *odentry, } /** - * gfs2_follow_link - Follow a symbolic link + * gfs2_get_link - Follow a symbolic link * @dentry: The dentry of the link - * @nd: Data that we pass to vfs_follow_link() + * @inode: The inode of the link + * @cookie: place to store the information for ->put_link() * * This can handle symlinks of any size. * * Returns: 0 on success or error code */ -static const char *gfs2_follow_link(struct dentry *dentry, void **cookie) +static const char *gfs2_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - struct gfs2_inode *ip = GFS2_I(d_inode(dentry)); + struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder i_gh; struct buffer_head *dibh; unsigned int size; char *buf; int error; + if (!dentry) + return ERR_PTR(-ECHILD); + gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); error = gfs2_glock_nq(&i_gh); if (error) { @@ -2132,7 +2137,7 @@ const struct inode_operations gfs2_dir_iops = { const struct inode_operations gfs2_symlink_iops = { .readlink = generic_readlink, - .follow_link = gfs2_follow_link, + .get_link = gfs2_get_link, .put_link = kfree_put_link, .permission = gfs2_permission, .setattr = gfs2_setattr, diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 2ac99db3750e..6ce5309ecb7b 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -892,9 +892,13 @@ static const struct inode_operations hostfs_dir_iops = { .setattr = hostfs_setattr, }; -static const char *hostfs_follow_link(struct dentry *dentry, void **cookie) +static const char *hostfs_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - char *link = __getname(); + char *link; + if (!dentry) + return ERR_PTR(-ECHILD); + link = __getname(); if (link) { char *path = dentry_name(dentry); int err = -ENOMEM; @@ -922,7 +926,7 @@ static void hostfs_put_link(struct inode *unused, void *cookie) static const struct inode_operations hostfs_link_iops = { .readlink = generic_readlink, - .follow_link = hostfs_follow_link, + .get_link = hostfs_get_link, .put_link = hostfs_put_link, }; diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 8ce2f240125b..2cabd649d4fb 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -14,7 +14,7 @@ const struct inode_operations jffs2_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = simple_follow_link, + .get_link = simple_get_link, .setattr = jffs2_setattr, .setxattr = jffs2_setxattr, .getxattr = jffs2_getxattr, diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index 5929e2363cb8..02113282772e 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c @@ -23,7 +23,7 @@ const struct inode_operations jfs_fast_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = simple_follow_link, + .get_link = simple_get_link, .setattr = jfs_setattr, .setxattr = jfs_setxattr, .getxattr = jfs_getxattr, @@ -33,7 +33,7 @@ const struct inode_operations jfs_fast_symlink_inode_operations = { const struct inode_operations jfs_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .setattr = jfs_setattr, .setxattr = jfs_setxattr, diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index db272528ab5b..ffae8579045d 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -112,10 +112,15 @@ static int kernfs_getlink(struct dentry *dentry, char *path) return error; } -static const char *kernfs_iop_follow_link(struct dentry *dentry, void **cookie) +static const char *kernfs_iop_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { int error = -ENOMEM; - unsigned long page = get_zeroed_page(GFP_KERNEL); + unsigned long page; + + if (!dentry) + return ERR_PTR(-ECHILD); + page = get_zeroed_page(GFP_KERNEL); if (!page) return ERR_PTR(-ENOMEM); error = kernfs_getlink(dentry, (char *)page); @@ -132,7 +137,7 @@ const struct inode_operations kernfs_symlink_iops = { .getxattr = kernfs_iop_getxattr, .listxattr = kernfs_iop_listxattr, .readlink = generic_readlink, - .follow_link = kernfs_iop_follow_link, + .get_link = kernfs_iop_get_link, .put_link = free_page_put_link, .setattr = kernfs_iop_setattr, .getattr = kernfs_iop_getattr, diff --git a/fs/libfs.c b/fs/libfs.c index c7cbfb092e94..8dc37fc4b6df 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1092,14 +1092,15 @@ simple_nosetlease(struct file *filp, long arg, struct file_lock **flp, } EXPORT_SYMBOL(simple_nosetlease); -const char *simple_follow_link(struct dentry *dentry, void **cookie) +const char *simple_get_link(struct dentry *dentry, struct inode *inode, + void **cookie) { - return d_inode(dentry)->i_link; + return inode->i_link; } -EXPORT_SYMBOL(simple_follow_link); +EXPORT_SYMBOL(simple_get_link); const struct inode_operations simple_symlink_inode_operations = { - .follow_link = simple_follow_link, + .get_link = simple_get_link, .readlink = generic_readlink }; EXPORT_SYMBOL(simple_symlink_inode_operations); diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 67a23bfd7303..3cce709a8729 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -435,7 +435,7 @@ static const struct address_space_operations minix_aops = { static const struct inode_operations minix_symlink_inode_operations = { .readlink = generic_readlink, - .follow_link = page_follow_link_light, + .get_link = page_get_link, .put_link = page_put_link, .getattr = minix_getattr, }; diff --git a/fs/namei.c b/fs/namei.c index 2808958e6c67..1da3064311e2 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -842,7 +842,7 @@ static inline void path_to_nameidata(const struct path *path, } /* - * Helper to directly jump to a known parsed path from ->follow_link, + * Helper to directly jump to a known parsed path from ->get_link, * caller must have taken a reference to path beforehand. */ void nd_jump_link(struct path *path) @@ -1005,10 +1005,18 @@ const char *get_link(struct nameidata *nd) res = inode->i_link; if (!res) { if (nd->flags & LOOKUP_RCU) { - if (unlikely(unlazy_walk(nd, NULL, 0))) - return ERR_PTR(-ECHILD); + res = inode->i_op->get_link(NULL, inode, + &last->cookie); + if (res == ERR_PTR(-ECHILD)) { + if (unlikely(unlazy_walk(nd, NULL, 0))) + return ERR_PTR(-ECHILD); + res = inode->i_op->get_link(dentry, inode, + &last->cookie); + } + } else { + res = inode->i_op->get_link(dentry, inode, + &last->cookie); } - res = inode->i_op->follow_link(dentry, & |