diff options
45 files changed, 234 insertions, 132 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 06d443450f21..4fba54b9fcec 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -50,7 +50,7 @@ prototypes: int (*rename2) (struct inode *, struct dentry *, struct inode *, struct dentry *, unsigned int); int (*readlink) (struct dentry *, char __user *,int); - const char *(*follow_link) (struct dentry *, void **); + const char *(*get_link) (struct dentry *, struct inode *, void **); void (*put_link) (struct inode *, void *); void (*truncate) (struct inode *); int (*permission) (struct inode *, int, unsigned int); @@ -83,7 +83,7 @@ rmdir: yes (both) (see below) rename: yes (all) (see below) rename2: yes (all) (see below) readlink: no -follow_link: no +get_link: no put_link: no setattr: yes permission: no (may not block if called in rcu-walk mode) diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 3eb7c35c9698..cf92a8c55594 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -509,3 +509,9 @@ in your dentry operations instead. any symlink that might use page_follow_link_light/page_put_link() must have inode_nohighmem(inode) called before anything might start playing with its pagecache. +-- +[mandatory] + ->follow_link() is replaced with ->get_link(); same API, except that + * ->get_link() gets inode as a separate argument + * ->get_link() may be called in RCU mode - in that case NULL + dentry is passed diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 69b203651905..153fdf908328 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -118,12 +118,14 @@ failed: return rc; } -static const char *ll_follow_link(struct dentry *dentry, void **cookie) +static const char *ll_get_link(struct dentry *dentry, + struct inode *inode, void **cookie) { - struct inode *inode = d_inode(dentry); struct ptlrpc_request *request = NULL; int rc; char *symname = NULL; + if (!dentry) + return ERR_PTR(-ECHILD); CDEBUG(D_VFSTRACE, "VFS Op\n"); ll_inode_size_lock(inode); @@ -149,7 +151,7 @@ static void ll_put_link(struct inode *unused, void *cookie) struct inode_operations ll_fast_symlink_inode_operations = { .readlink = generic_readlink, .setattr = ll_setattr, - .follow_link = ll_follow_link, + .get_link = ll_get_link, .put_link = ll_put_link, .getattr = ll_getattr, .permission = ll_inode_permission, 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, |