summaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-05-02 13:32:22 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-05-10 22:19:45 -0400
commit680baacbca69d18a6d7315374ad83d05ac9c0977 (patch)
treea69822ef5234d4a308b780ff51c5d9b77bd3a89b /fs/cifs
parent46afd6f61cc33ae4b3a2aed4bb454d11d4114c27 (diff)
new ->follow_link() and ->put_link() calling conventions
a) instead of storing the symlink body (via nd_set_link()) and returning an opaque pointer later passed to ->put_link(), ->follow_link() _stores_ that opaque pointer (into void * passed by address by caller) and returns the symlink body. Returning ERR_PTR() on error, NULL on jump (procfs magic symlinks) and pointer to symlink body for normal symlinks. Stored pointer is ignored in all cases except the last one. Storing NULL for opaque pointer (or not storing it at all) means no call of ->put_link(). b) the body used to be passed to ->put_link() implicitly (via nameidata). Now only the opaque pointer is. In the cases when we used the symlink body to free stuff, ->follow_link() now should store it as opaque pointer in addition to returning it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/link.c28
2 files changed, 14 insertions, 16 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 252f5c15806b..61012da7e9d8 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -120,7 +120,7 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
120#endif 120#endif
121 121
122/* Functions related to symlinks */ 122/* Functions related to symlinks */
123extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); 123extern const char *cifs_follow_link(struct dentry *direntry, void **cookie, struct nameidata *nd);
124extern int cifs_readlink(struct dentry *direntry, char __user *buffer, 124extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
125 int buflen); 125 int buflen);
126extern int cifs_symlink(struct inode *inode, struct dentry *direntry, 126extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 252e672d5604..4a439c2c0c7f 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -626,8 +626,8 @@ cifs_hl_exit:
626 return rc; 626 return rc;
627} 627}
628 628
629void * 629const char *
630cifs_follow_link(struct dentry *direntry, struct nameidata *nd) 630cifs_follow_link(struct dentry *direntry, void **cookie, struct nameidata *nd)
631{ 631{
632 struct inode *inode = d_inode(direntry); 632 struct inode *inode = d_inode(direntry);
633 int rc = -ENOMEM; 633 int rc = -ENOMEM;
@@ -643,16 +643,18 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
643 643
644 tlink = cifs_sb_tlink(cifs_sb); 644 tlink = cifs_sb_tlink(cifs_sb);
645 if (IS_ERR(tlink)) { 645 if (IS_ERR(tlink)) {
646 rc = PTR_ERR(tlink); 646 free_xid(xid);
647 tlink = NULL; 647 return ERR_CAST(tlink);
648 goto out;
649 } 648 }
650 tcon = tlink_tcon(tlink); 649 tcon = tlink_tcon(tlink);
651 server = tcon->ses->server; 650 server = tcon->ses->server;
652 651
653 full_path = build_path_from_dentry(direntry); 652 full_path = build_path_from_dentry(direntry);
654 if (!full_path) 653 if (!full_path) {
655 goto out; 654 free_xid(xid);
655 cifs_put_tlink(tlink);
656 return ERR_PTR(-ENOMEM);
657 }
656 658
657 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode); 659 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
658 660
@@ -670,17 +672,13 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
670 &target_path, cifs_sb); 672 &target_path, cifs_sb);
671 673
672 kfree(full_path); 674 kfree(full_path);
673out: 675 free_xid(xid);
676 cifs_put_tlink(tlink);
674 if (rc != 0) { 677 if (rc != 0) {
675 kfree(target_path); 678 kfree(target_path);
676 target_path = ERR_PTR(rc); 679 return ERR_PTR(rc);
677 } 680 }
678 681 return *cookie = target_path;
679 free_xid(xid);
680 if (tlink)
681 cifs_put_tlink(tlink);
682 nd_set_link(nd, target_path);
683 return NULL;
684} 682}
685 683
686int 684int