diff options
43 files changed, 206 insertions, 218 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 4fba54b9fcec..619af9bfdcb3 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -51,7 +51,6 @@ prototypes: | |||
51 | struct inode *, struct dentry *, unsigned int); | 51 | struct inode *, struct dentry *, unsigned int); |
52 | int (*readlink) (struct dentry *, char __user *,int); | 52 | int (*readlink) (struct dentry *, char __user *,int); |
53 | const char *(*get_link) (struct dentry *, struct inode *, void **); | 53 | const char *(*get_link) (struct dentry *, struct inode *, void **); |
54 | void (*put_link) (struct inode *, void *); | ||
55 | void (*truncate) (struct inode *); | 54 | void (*truncate) (struct inode *); |
56 | int (*permission) (struct inode *, int, unsigned int); | 55 | int (*permission) (struct inode *, int, unsigned int); |
57 | int (*get_acl)(struct inode *, int); | 56 | int (*get_acl)(struct inode *, int); |
@@ -84,7 +83,6 @@ rename: yes (all) (see below) | |||
84 | rename2: yes (all) (see below) | 83 | rename2: yes (all) (see below) |
85 | readlink: no | 84 | readlink: no |
86 | get_link: no | 85 | get_link: no |
87 | put_link: no | ||
88 | setattr: yes | 86 | setattr: yes |
89 | permission: no (may not block if called in rcu-walk mode) | 87 | permission: no (may not block if called in rcu-walk mode) |
90 | get_acl: no | 88 | get_acl: no |
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index cf92a8c55594..0f88e6020487 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting | |||
@@ -515,3 +515,9 @@ in your dentry operations instead. | |||
515 | * ->get_link() gets inode as a separate argument | 515 | * ->get_link() gets inode as a separate argument |
516 | * ->get_link() may be called in RCU mode - in that case NULL | 516 | * ->get_link() may be called in RCU mode - in that case NULL |
517 | dentry is passed | 517 | dentry is passed |
518 | -- | ||
519 | [mandatory] | ||
520 | ->get_link() gets struct delayed_call *done now, and should do | ||
521 | set_delayed_call() where it used to set *cookie. | ||
522 | ->put_link() is gone - just give the destructor to set_delayed_call() | ||
523 | in ->get_link(). | ||
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 8c6f07ad373a..b02a7d598258 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -350,8 +350,8 @@ struct inode_operations { | |||
350 | int (*rename2) (struct inode *, struct dentry *, | 350 | int (*rename2) (struct inode *, struct dentry *, |
351 | struct inode *, struct dentry *, unsigned int); | 351 | struct inode *, struct dentry *, unsigned int); |
352 | int (*readlink) (struct dentry *, char __user *,int); | 352 | int (*readlink) (struct dentry *, char __user *,int); |
353 | const char *(*follow_link) (struct dentry *, void **); | 353 | const char *(*get_link) (struct dentry *, struct inode *, |
354 | void (*put_link) (struct inode *, void *); | 354 | struct delayed_call *); |
355 | int (*permission) (struct inode *, int); | 355 | int (*permission) (struct inode *, int); |
356 | int (*get_acl)(struct inode *, int); | 356 | int (*get_acl)(struct inode *, int); |
357 | int (*setattr) (struct dentry *, struct iattr *); | 357 | int (*setattr) (struct dentry *, struct iattr *); |
@@ -434,20 +434,19 @@ otherwise noted. | |||
434 | readlink: called by the readlink(2) system call. Only required if | 434 | readlink: called by the readlink(2) system call. Only required if |
435 | you want to support reading symbolic links | 435 | you want to support reading symbolic links |
436 | 436 | ||
437 | follow_link: called by the VFS to follow a symbolic link to the | 437 | get_link: called by the VFS to follow a symbolic link to the |
438 | inode it points to. Only required if you want to support | 438 | inode it points to. Only required if you want to support |
439 | symbolic links. This method returns the symlink body | 439 | symbolic links. This method returns the symlink body |
440 | to traverse (and possibly resets the current position with | 440 | to traverse (and possibly resets the current position with |
441 | nd_jump_link()). If the body won't go away until the inode | 441 | nd_jump_link()). If the body won't go away until the inode |
442 | is gone, nothing else is needed; if it needs to be otherwise | 442 | is gone, nothing else is needed; if it needs to be otherwise |
443 | pinned, the data needed to release whatever we'd grabbed | 443 | pinned, arrange for its release by having get_link(..., ..., done) |
444 | is to be stored in void * variable passed by address to | 444 | do set_delayed_call(done, destructor, argument). |
445 | follow_link() instance. | 445 | In that case destructor(argument) will be called once VFS is |
446 | 446 | done with the body you've returned. | |
447 | put_link: called by the VFS to release resources allocated by | 447 | May be called in RCU mode; that is indicated by NULL dentry |
448 | follow_link(). The cookie stored by follow_link() is passed | 448 | argument. If request can't be handled without leaving RCU mode, |
449 | to this method as the last parameter; only called when | 449 | have it return ERR_PTR(-ECHILD). |
450 | cookie isn't NULL. | ||
451 | 450 | ||
452 | permission: called by the VFS to check for access rights on a POSIX-like | 451 | permission: called by the VFS to check for access rights on a POSIX-like |
453 | filesystem. | 452 | filesystem. |
diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 153fdf908328..e489a3271f06 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c | |||
@@ -118,8 +118,14 @@ failed: | |||
118 | return rc; | 118 | return rc; |
119 | } | 119 | } |
120 | 120 | ||
121 | static void ll_put_link(void *p) | ||
122 | { | ||
123 | ptlrpc_req_finished(p); | ||
124 | } | ||
125 | |||
121 | static const char *ll_get_link(struct dentry *dentry, | 126 | static const char *ll_get_link(struct dentry *dentry, |
122 | struct inode *inode, void **cookie) | 127 | struct inode *inode, |
128 | struct delayed_call *done) | ||
123 | { | 129 | { |
124 | struct ptlrpc_request *request = NULL; | 130 | struct ptlrpc_request *request = NULL; |
125 | int rc; | 131 | int rc; |
@@ -137,22 +143,16 @@ static const char *ll_get_link(struct dentry *dentry, | |||
137 | } | 143 | } |
138 | 144 | ||
139 | /* symname may contain a pointer to the request message buffer, | 145 | /* symname may contain a pointer to the request message buffer, |
140 | * we delay request releasing until ll_put_link then. | 146 | * we delay request releasing then. |
141 | */ | 147 | */ |
142 | *cookie = request; | 148 | set_delayed_call(done, ll_put_link, request); |
143 | return symname; | 149 | return symname; |
144 | } | 150 | } |
145 | 151 | ||
146 | static void ll_put_link(struct inode *unused, void *cookie) | ||
147 | { | ||
148 | ptlrpc_req_finished(cookie); | ||
149 | } | ||
150 | |||
151 | struct inode_operations ll_fast_symlink_inode_operations = { | 152 | struct inode_operations ll_fast_symlink_inode_operations = { |
152 | .readlink = generic_readlink, | 153 | .readlink = generic_readlink, |
153 | .setattr = ll_setattr, | 154 | .setattr = ll_setattr, |
154 | .get_link = ll_get_link, | 155 | .get_link = ll_get_link, |
155 | .put_link = ll_put_link, | ||
156 | .getattr = ll_getattr, | 156 | .getattr = ll_getattr, |
157 | .permission = ll_inode_permission, | 157 | .permission = ll_inode_permission, |
158 | .setxattr = ll_setxattr, | 158 | .setxattr = ll_setxattr, |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 8ba5a897fc0a..f928f8702f4c 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -1226,11 +1226,12 @@ ino_t v9fs_qid2ino(struct p9_qid *qid) | |||
1226 | * v9fs_vfs_get_link - follow a symlink path | 1226 | * v9fs_vfs_get_link - follow a symlink path |
1227 | * @dentry: dentry for symlink | 1227 | * @dentry: dentry for symlink |
1228 | * @inode: inode for symlink | 1228 | * @inode: inode for symlink |
1229 | * @cookie: place to pass the data to put_link() | 1229 | * @done: delayed call for when we are done with the return value |
1230 | */ | 1230 | */ |
1231 | 1231 | ||
1232 | static const char *v9fs_vfs_get_link(struct dentry *dentry, | 1232 | static const char *v9fs_vfs_get_link(struct dentry *dentry, |
1233 | struct inode *inode, void **cookie) | 1233 | struct inode *inode, |
1234 | struct delayed_call *done) | ||
1234 | { | 1235 | { |
1235 | struct v9fs_session_info *v9ses; | 1236 | struct v9fs_session_info *v9ses; |
1236 | struct p9_fid *fid; | 1237 | struct p9_fid *fid; |
@@ -1266,7 +1267,8 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry, | |||
1266 | 1267 | ||
1267 | p9stat_free(st); | 1268 | p9stat_free(st); |
1268 | kfree(st); | 1269 | kfree(st); |
1269 | return *cookie = res; | 1270 | set_delayed_call(done, kfree_link, res); |
1271 | return res; | ||
1270 | } | 1272 | } |
1271 | 1273 | ||
1272 | /** | 1274 | /** |
@@ -1460,7 +1462,6 @@ static const struct inode_operations v9fs_file_inode_operations = { | |||
1460 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1462 | static const struct inode_operations v9fs_symlink_inode_operations = { |
1461 | .readlink = generic_readlink, | 1463 | .readlink = generic_readlink, |
1462 | .get_link = v9fs_vfs_get_link, | 1464 | .get_link = v9fs_vfs_get_link, |
1463 | .put_link = kfree_put_link, | ||
1464 | .getattr = v9fs_vfs_getattr, | 1465 | .getattr = v9fs_vfs_getattr, |
1465 | .setattr = v9fs_vfs_setattr, | 1466 | .setattr = v9fs_vfs_setattr, |
1466 | }; | 1467 | }; |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 0cc105d804dd..a34702c998f5 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -902,12 +902,13 @@ error: | |||
902 | * v9fs_vfs_get_link_dotl - follow a symlink path | 902 | * v9fs_vfs_get_link_dotl - follow a symlink path |
903 | * @dentry: dentry for symlink | 903 | * @dentry: dentry for symlink |
904 | * @inode: inode for symlink | 904 | * @inode: inode for symlink |
905 | * @cookie: place to pass the data to put_link() | 905 | * @done: destructor for return value |
906 | */ | 906 | */ |
907 | 907 | ||
908 | static const char * | 908 | static const char * |
909 | v9fs_vfs_get_link_dotl(struct dentry *dentry, | 909 | v9fs_vfs_get_link_dotl(struct dentry *dentry, |
910 | struct inode *inode, void **cookie) | 910 | struct inode *inode, |
911 | struct delayed_call *done) | ||
911 | { | 912 | { |
912 | struct p9_fid *fid; | 913 | struct p9_fid *fid; |
913 | char *target; | 914 | char *target; |
@@ -924,7 +925,8 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry, | |||
924 | retval = p9_client_readlink(fid, &target); | 925 | retval = p9_client_readlink(fid, &target); |
925 | if (retval) | 926 | if (retval) |
926 | return ERR_PTR(retval); | 927 | return ERR_PTR(retval); |
927 | return *cookie = target; | 928 | set_delayed_call(done, kfree_link, target); |
929 | return target; | ||
928 | } | 930 | } |
929 | 931 | ||
930 | int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) | 932 | int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) |
@@ -991,7 +993,6 @@ const struct inode_operations v9fs_file_inode_operations_dotl = { | |||
991 | const struct inode_operations v9fs_symlink_inode_operations_dotl = { | 993 | const struct inode_operations v9fs_symlink_inode_operations_dotl = { |
992 | .readlink = generic_readlink, | 994 | .readlink = generic_readlink, |
993 | .get_link = v9fs_vfs_get_link_dotl, | 995 | .get_link = v9fs_vfs_get_link_dotl, |
994 | .put_link = kfree_put_link, | ||
995 | .getattr = v9fs_vfs_getattr_dotl, | 996 | .getattr = v9fs_vfs_getattr_dotl, |
996 | .setattr = v9fs_vfs_setattr_dotl, | 997 | .setattr = v9fs_vfs_setattr_dotl, |
997 | .setxattr = generic_setxattr, | 998 | .setxattr = generic_setxattr, |
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c index 39d1194445e1..69b03dbb792f 100644 --- a/fs/affs/symlink.c +++ b/fs/affs/symlink.c | |||
@@ -72,6 +72,5 @@ const struct address_space_operations affs_symlink_aops = { | |||
72 | const struct inode_operations affs_symlink_inode_operations = { | 72 | const struct inode_operations affs_symlink_inode_operations = { |
73 | .readlink = generic_readlink, | 73 | .readlink = generic_readlink, |
74 | .get_link = page_get_link, | 74 | .get_link = page_get_link, |
75 | .put_link = page_put_link, | ||
76 | .setattr = affs_notify_change, | 75 | .setattr = affs_notify_change, |
77 | }; | 76 | }; |
diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index 39e6f0bdf8e3..84e037d1d129 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c | |||
@@ -13,7 +13,8 @@ | |||
13 | #include "autofs_i.h" | 13 | #include "autofs_i.h" |
14 | 14 | ||
15 | static const char *autofs4_get_link(struct dentry *dentry, | 15 | static const char *autofs4_get_link(struct dentry *dentry, |
16 | struct inode *inode, void **cookie) | 16 | struct inode *inode, |
17 | struct delayed_call *done) | ||
17 | { | 18 | { |
18 | struct autofs_sb_info *sbi; | 19 | struct autofs_sb_info *sbi; |
19 | struct autofs_info *ino; | 20 | struct autofs_info *ino; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3d4aa69f1e0c..1a41a65fd2ff 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -10097,7 +10097,6 @@ static const struct inode_operations btrfs_special_inode_operations = { | |||
10097 | static const struct inode_operations btrfs_symlink_inode_operations = { | 10097 | static const struct inode_operations btrfs_symlink_inode_operations = { |
10098 | .readlink = generic_readlink, | 10098 | .readlink = generic_readlink, |
10099 | .get_link = page_get_link, | 10099 | .get_link = page_get_link, |
10100 | .put_link = page_put_link, | ||
10101 | .getattr = btrfs_getattr, | 10100 | .getattr = btrfs_getattr, |
10102 | .setattr = btrfs_setattr, | 10101 | .setattr = btrfs_setattr, |
10103 | .permission = btrfs_permission, | 10102 | .permission = btrfs_permission, |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4593f41678ef..90e4e2b398b6 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -901,7 +901,6 @@ const struct inode_operations cifs_file_inode_ops = { | |||
901 | const struct inode_operations cifs_symlink_inode_ops = { | 901 | const struct inode_operations cifs_symlink_inode_ops = { |
902 | .readlink = generic_readlink, | 902 | .readlink = generic_readlink, |
903 | .get_link = cifs_get_link, | 903 | .get_link = cifs_get_link, |
904 | .put_link = kfree_put_link, | ||
905 | .permission = cifs_permission, | 904 | .permission = cifs_permission, |
906 | /* BB add the following two eventually */ | 905 | /* BB add the following two eventually */ |
907 | /* revalidate: cifs_revalidate, | 906 | /* revalidate: cifs_revalidate, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 6886328cf3c4..26a1187d4323 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -120,7 +120,8 @@ 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 */ |
123 | extern const char *cifs_get_link(struct dentry *, struct inode *, void **); | 123 | extern const char *cifs_get_link(struct dentry *, struct inode *, |
124 | struct delayed_call *); | ||
124 | extern int cifs_symlink(struct inode *inode, struct dentry *direntry, | 125 | extern int cifs_symlink(struct inode *inode, struct dentry *direntry, |
125 | const char *symname); | 126 | const char *symname); |
126 | extern int cifs_removexattr(struct dentry *, const char *); | 127 | extern int cifs_removexattr(struct dentry *, const char *); |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 6f2439b508b5..062c2375549a 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -627,7 +627,8 @@ cifs_hl_exit: | |||
627 | } | 627 | } |
628 | 628 | ||
629 | const char * | 629 | const char * |
630 | cifs_get_link(struct dentry *direntry, struct inode *inode, void **cookie) | 630 | cifs_get_link(struct dentry *direntry, struct inode *inode, |
631 | struct delayed_call *done) | ||
631 | { | 632 | { |
632 | int rc = -ENOMEM; | 633 | int rc = -ENOMEM; |
633 | unsigned int xid; | 634 | unsigned int xid; |
@@ -680,7 +681,8 @@ cifs_get_link(struct dentry *direntry, struct inode *inode, void **cookie) | |||
680 | kfree(target_path); | 681 | kfree(target_path); |
681 | return ERR_PTR(rc); | 682 | return ERR_PTR(rc); |
682 | } | 683 | } |
683 | return *cookie = target_path; | 684 | set_delayed_call(done, kfree_link, target_path); |
685 | return target_path; | ||
684 | } | 686 | } |
685 | 687 | ||
686 | int | 688 | int |
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index f18139c7690a..1bfb7ba4e85e 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c | |||
@@ -19,7 +19,6 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) | |||
19 | static const struct inode_operations coda_symlink_inode_operations = { | 19 | static const struct inode_operations coda_symlink_inode_operations = { |
20 | .readlink = generic_readlink, | 20 | .readlink = generic_readlink, |
21 | .get_link = page_get_link, | 21 | .get_link = page_get_link, |
22 | .put_link = page_put_link, | ||
23 | .setattr = coda_setattr, | 22 | .setattr = coda_setattr, |
24 | }; | 23 | }; |
25 | 24 | ||
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index e9de962e518d..db6d69289608 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c | |||
@@ -280,31 +280,32 @@ static int configfs_getlink(struct dentry *dentry, char * path) | |||
280 | } | 280 | } |
281 | 281 | ||
282 | static const char *configfs_get_link(struct dentry *dentry, | 282 | static const char *configfs_get_link(struct dentry *dentry, |
283 | struct inode *inode, void **cookie) | 283 | struct inode *inode, |
284 | struct delayed_call *done) | ||
284 | { | 285 | { |
285 | char *page; | 286 | char *body; |
286 | int error; | 287 | int error; |
287 | 288 | ||
288 | if (!dentry) | 289 | if (!dentry) |
289 | return ERR_PTR(-ECHILD); | 290 | return ERR_PTR(-ECHILD); |
290 | 291 | ||
291 | page = kzalloc(PAGE_SIZE, GFP_KERNEL); | 292 | body = kzalloc(PAGE_SIZE, GFP_KERNEL); |
292 | if (!page) | 293 | if (!body) |
293 | return ERR_PTR(-ENOMEM); | 294 | return ERR_PTR(-ENOMEM); |
294 | 295 | ||
295 | error = configfs_getlink(dentry, page); | 296 | error = configfs_getlink(dentry, body); |
296 | if (!error) { | 297 | if (!error) { |
297 | return *cookie = page; | 298 | set_delayed_call(done, kfree_link, body); |
299 | return body; | ||
298 | } | 300 | } |
299 | 301 | ||
300 | kfree(page); | 302 | kfree(body); |
301 | return ERR_PTR(error); | 303 | return ERR_PTR(error); |
302 | } | 304 | } |
303 | 305 | ||
304 | const struct inode_operations configfs_symlink_inode_operations = { | 306 | const struct inode_operations configfs_symlink_inode_operations = { |
305 | .get_link = configfs_get_link, | 307 | .get_link = configfs_get_link, |
306 | .readlink = generic_readlink, | 308 | .readlink = generic_readlink, |
307 | .put_link = kfree_put_link, | ||
308 | .setattr = configfs_setattr, | 309 | .setattr = configfs_setattr, |
309 | }; | 310 | }; |
310 | 311 | ||
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 5a05559cb23d..a4dddc61594c 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -675,7 +675,8 @@ out: | |||
675 | } | 675 | } |
676 | 676 | ||
677 | static const char *ecryptfs_get_link(struct dentry *dentry, | 677 | static const char *ecryptfs_get_link(struct dentry *dentry, |
678 | struct inode *inode, void **cookie) | 678 | struct inode *inode, |
679 | struct delayed_call *done) | ||
679 | { | 680 | { |
680 | size_t len; | 681 | size_t len; |
681 | char *buf; | 682 | char *buf; |
@@ -689,7 +690,8 @@ static const char *ecryptfs_get_link(struct dentry *dentry, | |||
689 | fsstack_copy_attr_atime(d_inode(dentry), | 690 | fsstack_copy_attr_atime(d_inode(dentry), |
690 | d_inode(ecryptfs_dentry_to_lower(dentry))); | 691 | d_inode(ecryptfs_dentry_to_lower(dentry))); |
691 | buf[len] = '\0'; | 692 | buf[len] = '\0'; |
692 | return *cookie = buf; | 693 | set_delayed_call(done, kfree_link, buf); |
694 | return buf; | ||
693 | } | 695 | } |
694 | 696 | ||
695 | /** | 697 | /** |
@@ -1102,7 +1104,6 @@ out: | |||
1102 | const struct inode_operations ecryptfs_symlink_iops = { | 1104 | const struct inode_operations ecryptfs_symlink_iops = { |
1103 | .readlink = generic_readlink, | 1105 | .readlink = generic_readlink, |
1104 | .get_link = ecryptfs_get_link, | 1106 | .get_link = ecryptfs_get_link, |
1105 | .put_link = kfree_put_link, | ||
1106 | .permission = ecryptfs_permission, | 1107 | .permission = ecryptfs_permission, |
1107 | .setattr = ecryptfs_setattr, | 1108 | .setattr = ecryptfs_setattr, |
1108 | .getattr = ecryptfs_getattr_link, | 1109 | .getattr = ecryptfs_getattr_link, |
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index 46905119a27c..3495d8ae4b33 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c | |||
@@ -23,7 +23,6 @@ | |||
23 | const struct inode_operations ext2_symlink_inode_operations = { | 23 | const struct inode_operations ext2_symlink_inode_operations = { |
24 | .readlink = generic_readlink, | 24 | .readlink = generic_readlink, |
25 | .get_link = page_get_link, | 25 | .get_link = page_get_link, |
26 | .put_link = page_put_link, | ||
27 | .setattr = ext2_setattr, | 26 | .setattr = ext2_setattr, |
28 | #ifdef CONFIG_EXT2_FS_XATTR | 27 | #ifdef CONFIG_EXT2_FS_XATTR |
29 | .setxattr = generic_setxattr, | 28 | .setxattr = generic_setxattr, |
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c index 3b4bfe2ebd75..2281ac27b213 100644 --- a/fs/ext4/symlink.c +++ b/fs/ext4/symlink.c | |||
@@ -24,7 +24,8 @@ | |||
24 | 24 | ||
25 | #ifdef CONFIG_EXT4_FS_ENCRYPTION | 25 | #ifdef CONFIG_EXT4_FS_ENCRYPTION |
26 | static const char *ext4_encrypted_get_link(struct dentry *dentry, | 26 | static const char *ext4_encrypted_get_link(struct dentry *dentry, |
27 | struct inode *inode, void **cookie) | 27 | struct inode *inode, |
28 | struct delayed_call *done) | ||
28 | { | 29 | { |
29 | struct page *cpage = NULL; | 30 | struct page *cpage = NULL; |
30 | char *caddr, *paddr = NULL; | 31 | char *caddr, *paddr = NULL; |
@@ -80,7 +81,8 @@ static const char *ext4_encrypted_get_link(struct dentry *dentry, | |||
80 | paddr[res] = '\0'; | 81 | paddr[res] = '\0'; |
81 | if (cpage) | 82 | if (cpage) |
82 | page_cache_release(cpage); | 83 | page_cache_release(cpage); |
83 | return *cookie = paddr; | 84 | set_delayed_call(done, kfree_link, paddr); |
85 | return paddr; | ||
84 | errout: | 86 | errout: |
85 | if (cpage) | 87 | if (cpage) |
86 | page_cache_release(cpage); | 88 | page_cache_release(cpage); |
@@ -91,7 +93,6 @@ errout: | |||
91 | const struct inode_operations ext4_encrypted_symlink_inode_operations = { | 93 | const struct inode_operations ext4_encrypted_symlink_inode_operations = { |
92 | .readlink = generic_readlink, | 94 | .readlink = generic_readlink, |
93 | .get_link = ext4_encrypted_get_link, | 95 | .get_link = ext4_encrypted_get_link, |
94 | .put_link = kfree_put_link, | ||
95 | .setattr = ext4_setattr, | 96 | .setattr = ext4_setattr, |
96 | .setxattr = generic_setxattr, | 97 | .setxattr = generic_setxattr, |
97 | .getxattr = generic_getxattr, | 98 | .getxattr = generic_getxattr, |
@@ -103,7 +104,6 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = { | |||
103 | const struct inode_operations ext4_symlink_inode_operations = { | 104 | const struct inode_operations ext4_symlink_inode_operations = { |
104 | .readlink = generic_readlink, | 105 | .readlink = generic_readlink, |
105 | .get_link = page_get_link, | 106 | .get_link = page_get_link, |
106 | .put_link = page_put_link, | ||
107 | .setattr = ext4_setattr, | 107 | .setattr = ext4_setattr, |
108 | .setxattr = generic_setxattr, | 108 | .setxattr = generic_setxattr, |
109 | .getxattr = generic_getxattr, | 109 | .getxattr = generic_getxattr, |
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 2a8d84b727ce..e7587fce1b80 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c | |||
@@ -316,12 +316,14 @@ fail: | |||
316 | } | 316 | } |
317 | 317 | ||
318 | static const char *f2fs_get_link(struct dentry *dentry, | 318 | static const char *f2fs_get_link(struct dentry *dentry, |
319 | struct inode *inode, void **cookie) | 319 | struct inode *inode, |
320 | struct delayed_call *done) | ||
320 | { | 321 | { |
321 | const char *link = page_get_link(dentry, inode, cookie); | 322 | const char *link = page_get_link(dentry, inode, done); |
322 | if (!IS_ERR(link) && !*link) { | 323 | if (!IS_ERR(link) && !*link) { |
323 | /* this is broken symlink case */ | 324 | /* this is broken symlink case */ |
324 | page_put_link(NULL, *cookie); | 325 | do_delayed_call(done); |
326 | clear_delayed_call(done); | ||
325 | link = ERR_PTR(-ENOENT); | 327 | link = ERR_PTR(-ENOENT); |
326 | } | 328 | } |
327 | return link; | 329 | return link; |
@@ -926,7 +928,8 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry, | |||
926 | 928 | ||
927 | #ifdef CONFIG_F2FS_FS_ENCRYPTION | 929 | #ifdef CONFIG_F2FS_FS_ENCRYPTION |
928 | static const char *f2fs_encrypted_get_link(struct dentry *dentry, | 930 | static const char *f2fs_encrypted_get_link(struct dentry *dentry, |
929 | struct inode *inode, void **cookie) | 931 | struct inode *inode, |
932 | struct delayed_call *done) | ||
930 | { | 933 | { |
931 | struct page *cpage = NULL; | 934 | struct page *cpage = NULL; |
932 | char *caddr, *paddr = NULL; | 935 | char *caddr, *paddr = NULL; |
@@ -988,7 +991,8 @@ static const char *f2fs_encrypted_get_link(struct dentry *dentry, | |||
988 | paddr[res] = '\0'; | 991 | paddr[res] = '\0'; |
989 | 992 | ||
990 | page_cache_release(cpage); | 993 | page_cache_release(cpage); |
991 | return *cookie = paddr; | 994 | set_delayed_call(done, kfree_link, paddr); |
995 | return paddr; | ||
992 | errout: | 996 | errout: |
993 | kfree(cstr.name); | 997 | kfree(cstr.name); |
994 | f2fs_fname_crypto_free_buffer(&pstr); | 998 | f2fs_fname_crypto_free_buffer(&pstr); |
@@ -999,7 +1003,6 @@ errout: | |||
999 | const struct inode_operations f2fs_encrypted_symlink_inode_operations = { | 1003 | const struct inode_operations f2fs_encrypted_symlink_inode_operations = { |
1000 | .readlink = generic_readlink, | 1004 | .readlink = generic_readlink, |
1001 | .get_link = f2fs_encrypted_get_link, | 1005 | .get_link = f2fs_encrypted_get_link, |
1002 | .put_link = kfree_put_link, | ||
1003 | .getattr = f2fs_getattr, | 1006 | .getattr = f2fs_getattr, |
1004 | .setattr = f2fs_setattr, | 1007 | .setattr = f2fs_setattr, |
1005 | .setxattr = generic_setxattr, | 1008 | .setxattr = generic_setxattr, |
@@ -1035,7 +1038,6 @@ const struct inode_operations f2fs_dir_inode_operations = { | |||
1035 | const struct inode_operations f2fs_symlink_inode_operations = { | 1038 | const struct inode_operations f2fs_symlink_inode_operations = { |
1036 | .readlink = generic_readlink, | 1039 | .readlink = generic_readlink, |
1037 | .get_link = f2fs_get_link, | 1040 | .get_link = f2fs_get_link, |
1038 | .put_link = page_put_link, | ||
1039 | .getattr = f2fs_getattr, | 1041 | .getattr = f2fs_getattr, |
1040 | .setattr = f2fs_setattr, | 1042 | .setattr = f2fs_setattr, |
1041 | #ifdef CONFIG_F2FS_FS_XATTR | 1043 | #ifdef CONFIG_F2FS_FS_XATTR |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index def0a4d082bc..712601f299b8 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1366,7 +1366,8 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx) | |||
1366 | } | 1366 | } |
1367 | 1367 | ||
1368 | static const char *fuse_get_link(struct dentry *dentry, | 1368 | static const char *fuse_get_link(struct dentry *dentry, |
1369 | struct inode *inode, void **cookie) | 1369 | struct inode *inode, |
1370 | struct delayed_call *done) | ||
1370 | { | 1371 | { |
1371 | struct fuse_conn *fc = get_fuse_conn(inode); | 1372 | struct fuse_conn *fc = get_fuse_conn(inode); |
1372 | FUSE_ARGS(args); | 1373 | FUSE_ARGS(args); |
@@ -1392,7 +1393,7 @@ static const char *fuse_get_link(struct dentry *dentry, | |||
1392 | link = ERR_PTR(ret); | 1393 | link = ERR_PTR(ret); |
1393 | } else { | 1394 | } else { |
1394 | link[ret] = '\0'; | 1395 | link[ret] = '\0'; |
1395 | *cookie = link; | 1396 | set_delayed_call(done, kfree_link, link); |
1396 | } | 1397 | } |
1397 | fuse_invalidate_atime(inode); | 1398 | fuse_invalidate_atime(inode); |
1398 | return link; | 1399 | return link; |
@@ -1913,7 +1914,6 @@ static const struct inode_operations fuse_common_inode_operations = { | |||
1913 | static const struct inode_operations fuse_symlink_inode_operations = { | 1914 | static const struct inode_operations fuse_symlink_inode_operations = { |
1914 | .setattr = fuse_setattr, | 1915 | .setattr = fuse_setattr, |
1915 | .get_link = fuse_get_link, | 1916 | .get_link = fuse_get_link, |
1916 | .put_link = kfree_put_link, | ||
1917 | .readlink = generic_readlink, | 1917 | .readlink = generic_readlink, |
1918 | .getattr = fuse_getattr, | 1918 | .getattr = fuse_getattr, |
1919 | .setxattr = fuse_setxattr, | 1919 | .setxattr = fuse_setxattr, |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 1095056046cc..1bae189f3245 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -1715,7 +1715,7 @@ static int gfs2_rename2(struct inode *odir, struct dentry *odentry, | |||
1715 | * gfs2_get_link - Follow a symbolic link | 1715 | * gfs2_get_link - Follow a symbolic link |
1716 | * @dentry: The dentry of the link | 1716 | * @dentry: The dentry of the link |
1717 | * @inode: The inode of the link | 1717 | * @inode: The inode of the link |
1718 | * @cookie: place to store the information for ->put_link() | 1718 | * @done: destructor for return value |
1719 | * | 1719 | * |
1720 | * This can handle symlinks of any size. | 1720 | * This can handle symlinks of any size. |
1721 | * | 1721 | * |
@@ -1723,7 +1723,8 @@ static int gfs2_rename2(struct inode *odir, struct dentry *odentry, | |||
1723 | */ | 1723 | */ |
1724 | 1724 | ||
1725 | static const char *gfs2_get_link(struct dentry *dentry, | 1725 | static const char *gfs2_get_link(struct dentry *dentry, |
1726 | struct inode *inode, void **cookie) | 1726 | struct inode *inode, |
1727 | struct delayed_call *done) | ||
1727 | { | 1728 | { |
1728 | struct gfs2_inode *ip = GFS2_I(inode); | 1729 | struct gfs2_inode *ip = GFS2_I(inode); |
1729 | struct gfs2_holder i_gh; | 1730 | struct gfs2_holder i_gh; |
@@ -1764,7 +1765,7 @@ static const char *gfs2_get_link(struct dentry *dentry, | |||
1764 | out: | 1765 | out: |
1765 | gfs2_glock_dq_uninit(&i_gh); | 1766 | gfs2_glock_dq_uninit(&i_gh); |
1766 | if (!IS_ERR(buf)) | 1767 | if (!IS_ERR(buf)) |
1767 | *cookie = buf; | 1768 | set_delayed_call(done, kfree_link, buf); |
1768 | return buf; | 1769 | return buf; |
1769 | } | 1770 | } |
1770 | 1771 | ||
@@ -2138,7 +2139,6 @@ const struct inode_operations gfs2_dir_iops = { | |||
2138 | const struct inode_operations gfs2_symlink_iops = { | 2139 | const struct inode_operations gfs2_symlink_iops = { |
2139 | .readlink = generic_readlink, | 2140 | .readlink = generic_readlink, |
2140 | .get_link = gfs2_get_link, | 2141 | .get_link = gfs2_get_link, |
2141 | .put_link = kfree_put_link, | ||
2142 | .permission = gfs2_permission, | 2142 | .permission = gfs2_permission, |
2143 | .setattr = gfs2_setattr, | 2143 | .setattr = gfs2_setattr, |
2144 | .getattr = gfs2_getattr, | 2144 | .getattr = gfs2_getattr, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 6ce5309ecb7b..7db524cc85b6 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -893,12 +893,13 @@ static const struct inode_operations hostfs_dir_iops = { | |||
893 | }; | 893 | }; |
894 | 894 | ||
895 | static const char *hostfs_get_link(struct dentry *dentry, | 895 | static const char *hostfs_get_link(struct dentry *dentry, |
896 | struct inode *inode, void **cookie) | 896 | struct inode *inode, |
897 | struct delayed_call *done) | ||
897 | { | 898 | { |
898 | char *link; | 899 | char *link; |
899 | if (!dentry) | 900 | if (!dentry) |
900 | return ERR_PTR(-ECHILD); | 901 | return ERR_PTR(-ECHILD); |
901 | link = __getname(); | 902 | link = kmalloc(PATH_MAX, GFP_KERNEL); |
902 | if (link) { | 903 | if (link) { |
903 | char *path = dentry_name(dentry); | 904 | char *path = dentry_name(dentry); |
904 | int err = -ENOMEM; | 905 | int err = -ENOMEM; |
@@ -909,25 +910,20 @@ static const char *hostfs_get_link(struct dentry *dentry, | |||
909 | __putname(path); | 910 | __putname(path); |
910 | } | 911 | } |
911 | if (err < 0) { | 912 | if (err < 0) { |
912 | __putname(link); | 913 | kfree(link); |
913 | return ERR_PTR(err); | 914 | return ERR_PTR(err); |
914 | } | 915 | } |
915 | } else { | 916 | } else { |
916 | return ERR_PTR(-ENOMEM); | 917 | return ERR_PTR(-ENOMEM); |
917 | } | 918 | } |
918 | 919 | ||
919 | return *cookie = link; | 920 | set_delayed_call(done, kfree_link, link); |
920 | } | 921 | return link; |
921 | |||
922 | static void hostfs_put_link(struct inode *unused, void *cookie) | ||
923 | { | ||
924 | __putname(cookie); | ||
925 | } | 922 | } |
926 | 923 | ||
927 | static const struct inode_operations hostfs_link_iops = { | 924 | static const struct inode_operations hostfs_link_iops = { |
928 | .readlink = generic_readlink, | 925 | .readlink = generic_readlink, |
929 | .get_link = hostfs_get_link, | 926 | .get_link = hostfs_get_link, |
930 | .put_link = hostfs_put_link, | ||
931 | }; | 927 | }; |
932 | 928 | ||
933 | static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) | 929 | static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) |
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c index 02113282772e..f8db4fde0b0b 100644 --- a/fs/jfs/symlink.c +++ b/fs/jfs/symlink.c | |||
@@ -34,7 +34,6 @@ const struct inode_operations jfs_fast_symlink_inode_operations = { | |||
34 | const struct inode_operations jfs_symlink_inode_operations = { | 34 | const struct inode_operations jfs_symlink_inode_operations = { |
35 | .readlink = generic_readlink, | 35 | .readlink = generic_readlink, |
36 | .get_link = page_get_link, | 36 | .get_link = page_get_link, |
37 | .put_link = page_put_link, | ||
38 | .setattr = jfs_setattr, | 37 | .setattr = jfs_setattr, |
39 | .setxattr = jfs_setxattr, | 38 | .setxattr = jfs_setxattr, |
40 | .getxattr = jfs_getxattr, | 39 | .getxattr = jfs_getxattr, |
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index f9efdaeda7b0..117b8b3416f9 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c | |||
@@ -113,22 +113,24 @@ static int kernfs_getlink(struct dentry *dentry, char *path) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static const char *kernfs_iop_get_link(struct dentry *dentry, | 115 | static const char *kernfs_iop_get_link(struct dentry *dentry, |
116 | struct inode *inode, void **cookie) | 116 | struct inode *inode, |
117 | struct delayed_call *done) | ||
117 | { | 118 | { |
118 | int error = -ENOMEM; | 119 | char *body; |
119 | char *page; | 120 | int error; |
120 | 121 | ||
121 | if (!dentry) | 122 | if (!dentry) |
122 | return ERR_PTR(-ECHILD); | 123 | return ERR_PTR(-ECHILD); |
123 | page = kzalloc(PAGE_SIZE, GFP_KERNEL); | 124 | body = kzalloc(PAGE_SIZE, GFP_KERNEL); |
124 | if (!page) | 125 | if (!body) |
125 | return ERR_PTR(-ENOMEM); | 126 | return ERR_PTR(-ENOMEM); |
126 | error = kernfs_getlink(dentry, page); | 127 | error = kernfs_getlink(dentry, body); |
127 | if (unlikely(error < 0)) { | 128 | if (unlikely(error < 0)) { |
128 | kfree(page); | 129 | kfree(body); |
129 | return ERR_PTR(error); | 130 | return ERR_PTR(error); |
130 | } | 131 | } |
131 | return *cookie = page; | 132 | set_delayed_call(done, kfree_link, body); |
133 | return body; | ||
132 | } | 134 | } |
133 | 135 | ||
134 | const struct inode_operations kernfs_symlink_iops = { | 136 | const struct inode_operations kernfs_symlink_iops = { |
@@ -138,7 +140,6 @@ const struct inode_operations kernfs_symlink_iops = { | |||
138 | .listxattr = kernfs_iop_listxattr, | 140 | .listxattr = kernfs_iop_listxattr, |
139 | .readlink = generic_readlink, | 141 | .readlink = generic_readlink, |
140 | .get_link = kernfs_iop_get_link, | 142 | .get_link = kernfs_iop_get_link, |
141 | .put_link = kfree_put_link, | ||
142 | .setattr = kernfs_iop_setattr, | 143 | .setattr = kernfs_iop_setattr, |
143 | .getattr = kernfs_iop_getattr, | 144 | .getattr = kernfs_iop_getattr, |
144 | .permission = kernfs_iop_permission, | 145 | .permission = kernfs_iop_permission, |
diff --git a/fs/libfs.c b/fs/libfs.c index fec7ab0632dc..01491299f348 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -1019,11 +1019,12 @@ int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
1019 | } | 1019 | } |
1020 | EXPORT_SYMBOL(noop_fsync); | 1020 | EXPORT_SYMBOL(noop_fsync); |
1021 | 1021 | ||
1022 | void kfree_put_link(struct inode *unused, void *cookie) | 1022 | /* Because kfree isn't assignment-compatible with void(void*) ;-/ */ |
1023 | void kfree_link(void *p) | ||
1023 | { | 1024 | { |
1024 | kfree(cookie); | 1025 | kfree(p); |
1025 | } | 1026 | } |
1026 | EXPORT_SYMBOL(kfree_put_link); | 1027 | EXPORT_SYMBOL(kfree_link); |
1027 | 1028 | ||
1028 | /* | 1029 | /* |
1029 | * nop .set_page_dirty method so that people can use .page_mkwrite on | 1030 | * nop .set_page_dirty method so that people can use .page_mkwrite on |
@@ -1087,7 +1088,7 @@ simple_nosetlease(struct file *filp, long arg, struct file_lock **flp, | |||
1087 | EXPORT_SYMBOL(simple_nosetlease); | 1088 | EXPORT_SYMBOL(simple_nosetlease); |
1088 | 1089 | ||
1089 | const char *simple_get_link(struct dentry *dentry, struct inode *inode, | 1090 | const char *simple_get_link(struct dentry *dentry, struct inode *inode, |
1090 | void **cookie) | 1091 | struct delayed_call *done) |
1091 | { | 1092 | { |
1092 | return inode->i_link; | 1093 | return inode->i_link; |
1093 | } | 1094 | } |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 3cce709a8729..cb1789ca1ee6 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -436,7 +436,6 @@ static const struct address_space_operations minix_aops = { | |||
436 | static const struct inode_operations minix_symlink_inode_operations = { | 436 | static const struct inode_operations minix_symlink_inode_operations = { |
437 | .readlink = generic_readlink, | 437 | .readlink = generic_readlink, |
438 | .get_link = page_get_link, | 438 | .get_link = page_get_link, |
439 | .put_link = page_put_link, | ||
440 | .getattr = minix_getattr, | 439 | .getattr = minix_getattr, |
441 | }; | 440 | }; |
442 | 441 | ||
diff --git a/fs/namei.c b/fs/namei.c index 8f517888c3e1..3c909aebef70 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -505,13 +505,13 @@ struct nameidata { | |||
505 | int total_link_count; | 505 | int total_link_count; |
506 | struct saved { | 506 | struct saved { |
507 | struct path link; | 507 | struct path link; |
508 | void *cookie; | 508 | struct delayed_call done; |
509 | const char *name; | 509 | const char *name; |
510 | struct inode *inode; | ||
511 | unsigned seq; | 510 | unsigned seq; |
512 | } *stack, internal[EMBEDDED_LEVELS]; | 511 | } *stack, internal[EMBEDDED_LEVELS]; |
513 | struct filename *name; | 512 | struct filename *name; |
514 | struct nameidata *saved; | 513 | struct nameidata *saved; |
514 | struct inode *link_inode; | ||
515 | unsigned root_seq; | 515 | unsigned root_seq; |
516 | int dfd; | 516 | int dfd; |
517 | }; | 517 | }; |
@@ -592,11 +592,8 @@ static void drop_links(struct nameidata *nd) | |||
592 | int i = nd->depth; | 592 | int i = nd->depth; |
593 | while (i--) { | 593 | while (i--) { |
594 | struct saved *last = nd->stack + i; | 594 | struct saved *last = nd->stack + i; |
595 | struct inode *inode = last->inode; | 595 | do_delayed_call(&last->done); |
596 | if (last->cookie && inode->i_op->put_link) { | 596 | clear_delayed_call(&last->done); |
597 | inode->i_op->put_link(inode, last->cookie); | ||
598 | last->cookie = NULL; | ||
599 | } | ||
600 | } | 597 | } |
601 | } | 598 | } |
602 | 599 | ||
@@ -858,9 +855,7 @@ void nd_jump_link(struct path *path) | |||
858 | static inline void put_link(struct nameidata *nd) | 855 | static inline void put_link(struct nameidata *nd) |
859 | { | 856 | { |
860 | struct saved *last = nd->stack + --nd->depth; | 857 | struct saved *last = nd->stack + --nd->depth; |
861 | struct inode *inode = last->inode; | 858 | do_delayed_call(&last->done); |
862 | if (last->cookie && inode->i_op->put_link) | ||
863 | inode->i_op->put_link(inode, last->cookie); | ||
864 | if (!(nd->flags & LOOKUP_RCU)) | 859 | if (!(nd->flags & LOOKUP_RCU)) |
865 | path_put(&last->link); | 860 | path_put(&last->link); |
866 | } | 861 | } |
@@ -892,7 +887,7 @@ static inline int may_follow_link(struct nameidata *nd) | |||
892 | return 0; | 887 | return 0; |
893 | 888 | ||
894 | /* Allowed if owner and follower match. */ | 889 | /* Allowed if owner and follower match. */ |
895 | inode = nd->stack[0].inode; | 890 | inode = nd->link_inode; |
896 | if (uid_eq(current_cred()->fsuid, inode->i_uid)) | 891 | if (uid_eq(current_cred()->fsuid, inode->i_uid)) |
897 | return 0; | 892 | return 0; |
898 | 893 | ||
@@ -983,7 +978,7 @@ const char *get_link(struct nameidata *nd) | |||
983 | { | 978 | { |
984 | struct saved *last = nd->stack + nd->depth - 1; | 979 | struct saved *last = nd->stack + nd->depth - 1; |
985 | struct dentry *dentry = last->link.dentry; | 980 | struct dentry *dentry = last->link.dentry; |
986 | struct inode *inode = last->inode; | 981 | struct inode *inode = nd->link_inode; |
987 | int error; | 982 | int error; |
988 | const char *res; | 983 | const char *res; |
989 | 984 | ||
@@ -1004,23 +999,21 @@ const char *get_link(struct nameidata *nd) | |||
1004 | nd->last_type = LAST_BIND; | 999 | nd->last_type = LAST_BIND; |
1005 | res = inode->i_link; | 1000 | res = inode->i_link; |
1006 | if (!res) { | 1001 | if (!res) { |
1002 | const char * (*get)(struct dentry *, struct inode *, | ||
1003 | struct delayed_call *); | ||
1004 | get = inode->i_op->get_link; | ||
1007 | if (nd->flags & LOOKUP_RCU) { | 1005 | if (nd->flags & LOOKUP_RCU) { |
1008 | res = inode->i_op->get_link(NULL, inode, | 1006 | res = get(NULL, inode, &last->done); |
1009 | &last->cookie); | ||
1010 | if (res == ERR_PTR(-ECHILD)) { | 1007 | if (res == ERR_PTR(-ECHILD)) { |
1011 | if (unlikely(unlazy_walk(nd, NULL, 0))) | 1008 | if (unlikely(unlazy_walk(nd, NULL, 0))) |
1012 | return ERR_PTR(-ECHILD); | 1009 | return ERR_PTR(-ECHILD); |
1013 | res = inode->i_op->get_link(dentry, inode, | 1010 | res = get(dentry, inode, &last->done); |
1014 | &last->cookie); | ||
1015 | } | 1011 | } |
1016 | } else { | 1012 | } else { |
1017 | res = inode->i_op->get_link(dentry, inode, | 1013 | res = get(dentry, inode, &last->done); |
1018 | &last->cookie); | ||
1019 | } | 1014 | } |
1020 | if (IS_ERR_OR_NULL(res)) { | 1015 | if (IS_ERR_OR_NULL(res)) |
1021 | last->cookie = NULL; | ||
1022 | return res; | 1016 | return res; |
1023 | } | ||
1024 | } | 1017 | } |
1025 | if (*res == '/') { | 1018 | if (*res == '/') { |
1026 | if (nd->flags & LOOKUP_RCU) { | 1019 | if (nd->flags & LOOKUP_RCU) { |
@@ -1699,8 +1692,8 @@ static int pick_link(struct nameidata *nd, struct path *link, | |||
1699 | 1692 | ||
1700 | last = nd->stack + nd->depth++; | 1693 | last = nd->stack + nd->depth++; |
1701 | last->link = *link; | 1694 | last->link = *link; |
1702 | last->cookie = NULL; | 1695 | clear_delayed_call(&last->done); |
1703 | last->inode = inode; | 1696 | nd->link_inode = inode; |
1704 | last->seq = seq; | 1697 | last->seq = seq; |
1705 | return 1; | 1698 | return 1; |
1706 | } | 1699 | } |
@@ -4508,26 +4501,25 @@ EXPORT_SYMBOL(readlink_copy); | |||
4508 | */ | 4501 | */ |
4509 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 4502 | int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
4510 | { | 4503 | { |
4511 | void *cookie; | 4504 | DEFINE_DELAYED_CALL(done); |
4512 | struct inode *inode = d_inode(dentry); | 4505 | struct inode *inode = d_inode(dentry); |
4513 | const char *link = inode->i_link; | 4506 | const char *link = inode->i_link; |
4514 | int res; | 4507 | int res; |
4515 | 4508 | ||
4516 | if (!link) { | 4509 | if (!link) { |
4517 | link = inode->i_op->get_link(dentry, inode, &cookie); | 4510 | link = inode->i_op->get_link(dentry, inode, &done); |
4518 | if (IS_ERR(link)) | 4511 | if (IS_ERR(link)) |
4519 | return PTR_ERR(link); | 4512 | return PTR_ERR(link); |
4520 | } | 4513 | } |
4521 | res = readlink_copy(buffer, buflen, link); | 4514 | res = readlink_copy(buffer, buflen, link); |
4522 | if (inode->i_op->put_link) | 4515 | do_delayed_call(&done); |
4523 | inode->i_op->put_link(inode, cookie); | ||
4524 | return res; | 4516 | return res; |
4525 | } | 4517 | } |
4526 | EXPORT_SYMBOL(generic_readlink); | 4518 | EXPORT_SYMBOL(generic_readlink); |
4527 | 4519 | ||
4528 | /* get the link contents into pagecache */ | 4520 | /* get the link contents into pagecache */ |
4529 | const char *page_get_link(struct dentry *dentry, struct inode *inode, | 4521 | const char *page_get_link(struct dentry *dentry, struct inode *inode, |
4530 | void **cookie) | 4522 | struct delayed_call *callback) |
4531 | { | 4523 | { |
4532 | char *kaddr; | 4524 | char *kaddr; |
4533 | struct page *page; | 4525 | struct page *page; |
@@ -4546,7 +4538,7 @@ const char *page_get_link(struct dentry *dentry, struct inode *inode, | |||
4546 | if (IS_ERR(page)) | 4538 | if (IS_ERR(page)) |
4547 | return (char*)page; | 4539 | return (char*)page; |
4548 | } | 4540 | } |
4549 | *cookie = page; | 4541 | set_delayed_call(callback, page_put_link, page); |
4550 | BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM); | 4542 | BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM); |
4551 | kaddr = page_address(page); | 4543 | kaddr = page_address(page); |
4552 | nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1); | 4544 | nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1); |
@@ -4555,21 +4547,19 @@ const char *page_get_link(struct dentry *dentry, struct inode *inode, | |||
4555 | 4547 | ||
4556 | EXPORT_SYMBOL(page_get_link); | 4548 | EXPORT_SYMBOL(page_get_link); |
4557 | 4549 | ||
4558 | void page_put_link(struct inode *unused, void *cookie) | 4550 | void page_put_link(void *arg) |
4559 | { | 4551 | { |
4560 | struct page *page = cookie; | 4552 | put_page(arg); |
4561 | page_cache_release(page); | ||
4562 | } | 4553 | } |
4563 | EXPORT_SYMBOL(page_put_link); | 4554 | EXPORT_SYMBOL(page_put_link); |
4564 | 4555 | ||
4565 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) | 4556 | int page_readlink(struct dentry *dentry, char __user *buffer, int buflen) |
4566 | { | 4557 | { |
4567 | void *cookie = NULL; | 4558 | DEFINE_DELAYED_CALL(done); |
4568 | int res = readlink_copy(buffer, buflen, | 4559 | int res = readlink_copy(buffer, buflen, |
4569 | page_get_link(dentry, d_inode(dentry), | 4560 | page_get_link(dentry, d_inode(dentry), |
4570 | &cookie)); | 4561 | &done)); |
4571 | if (cookie) | 4562 | do_delayed_call(&done); |
4572 | page_put_link(NULL, cookie); | ||
4573 | return res; | 4563 | return res; |
4574 | } | 4564 | } |
4575 | EXPORT_SYMBOL(page_readlink); | 4565 | EXPORT_SYMBOL(page_readlink); |
@@ -4619,6 +4609,5 @@ EXPORT_SYMBOL(page_symlink); | |||
4619 | const struct inode_operations page_symlink_inode_operations = { | 4609 | const struct inode_operations page_symlink_inode_operations = { |
4620 | .readlink = generic_readlink, | 4610 | .readlink = generic_readlink, |
4621 | .get_link = page_get_link, | 4611 | .get_link = page_get_link, |
4622 | .put_link = page_put_link, | ||
4623 | }; | 4612 | }; |
4624 | EXPORT_SYMBOL(page_symlink_inode_operations); | 4613 | EXPORT_SYMBOL(page_symlink_inode_operations); |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 3ab6cdbcde60..ce1eb3f9dfe8 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -245,7 +245,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) | |||
245 | static const struct inode_operations ncp_symlink_inode_operations = { | 245 | static const struct inode_operations ncp_symlink_inode_operations = { |
246 | .readlink = generic_readlink, | 246 | .readlink = generic_readlink, |
247 | .get_link = page_get_link, | 247 | .get_link = page_get_link, |
248 | .put_link = page_put_link, | ||
249 | .setattr = ncp_notify_change, | 248 | .setattr = ncp_notify_change, |
250 | }; | 249 | }; |
251 | #endif | 250 | #endif |
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 95c69af7e4d0..4fe3eead3868 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c | |||
@@ -43,7 +43,8 @@ error: | |||
43 | } | 43 | } |
44 | 44 | ||
45 | static const char *nfs_get_link(struct dentry *dentry, | 45 | static const char *nfs_get_link(struct dentry *dentry, |
46 | struct inode *inode, void **cookie) | 46 | struct inode *inode, |
47 | struct delayed_call *done) | ||
47 | { | 48 | { |
48 | struct page *page; | 49 | struct page *page; |
49 | void *err; | 50 | void *err; |
@@ -68,7 +69,7 @@ static const char *nfs_get_link(struct dentry *dentry, | |||
68 | if (IS_ERR(page)) | 69 | if (IS_ERR(page)) |
69 | return ERR_CAST(page); | 70 | return ERR_CAST(page); |
70 | } | 71 | } |
71 | *cookie = page; | 72 | set_delayed_call(done, page_put_link, page); |
72 | return page_address(page); | 73 | return page_address(page); |
73 | } | 74 | } |
74 | 75 | ||
@@ -78,7 +79,6 @@ static const char *nfs_get_link(struct dentry *dentry, | |||
78 | const struct inode_operations nfs_symlink_inode_operations = { | 79 | const struct inode_operations nfs_symlink_inode_operations = { |
79 | .readlink = generic_readlink, | 80 | .readlink = generic_readlink, |
80 | .get_link = nfs_get_link, | 81 | .get_link = nfs_get_link, |
81 | .put_link = page_put_link, | ||
82 | .getattr = nfs_getattr, | 82 | .getattr = nfs_getattr, |
83 | .setattr = nfs_setattr, | 83 | .setattr = nfs_setattr, |
84 | }; | 84 | }; |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 63dddb7d4b18..7ccdb961eea9 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
@@ -570,7 +570,6 @@ const struct inode_operations nilfs_special_inode_operations = { | |||
570 | const struct inode_operations nilfs_symlink_inode_operations = { | 570 | const struct inode_operations nilfs_symlink_inode_operations = { |
571 | .readlink = generic_readlink, | 571 | .readlink = generic_readlink, |
572 | .get_link = page_get_link, | 572 | .get_link = page_get_link, |
573 | .put_link = page_put_link, | ||
574 | .permission = nilfs_permission, | 573 | .permission = nilfs_permission, |
575 | }; | 574 | }; |
576 | 575 | ||
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index b4e79bc720f7..6c2a3e3c521c 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c | |||
@@ -89,7 +89,6 @@ const struct address_space_operations ocfs2_fast_symlink_aops = { | |||
89 | const struct inode_operations ocfs2_symlink_inode_operations = { | 89 | const struct inode_operations ocfs2_symlink_inode_operations = { |
90 | .readlink = generic_readlink, | 90 | .readlink = generic_readlink, |
91 | .get_link = page_get_link, | 91 | .get_link = page_get_link, |
92 | .put_link = page_put_link, | ||
93 | .getattr = ocfs2_getattr, | 92 | .getattr = ocfs2_getattr, |
94 | .setattr = ocfs2_setattr, | 93 | .setattr = ocfs2_setattr, |
95 | .setxattr = generic_setxattr, | 94 | .setxattr = generic_setxattr, |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 38a0b8b9f8b9..964a60fa7afc 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -131,19 +131,12 @@ out_dput: | |||
131 | return err; | 131 | return err; |
132 | } | 132 | } |
133 | 133 | ||
134 | |||
135 | struct ovl_link_data { | ||
136 | struct dentry *realdentry; | ||
137 | void *cookie; | ||
138 | }; | ||
139 | |||
140 | static const char *ovl_get_link(struct dentry *dentry, | 134 | static const char *ovl_get_link(struct dentry *dentry, |
141 | struct inode *inode, void **cookie) | 135 | struct inode *inode, |
136 | struct delayed_call *done) | ||
142 | { | 137 | { |
143 | struct dentry *realdentry; | 138 | struct dentry *realdentry; |
144 | struct inode *realinode; | 139 | struct inode *realinode; |
145 | struct ovl_link_data *data = NULL; | ||
146 | const char *ret; | ||
147 | 140 | ||
148 | if (!dentry) | 141 | if (!dentry) |
149 | return ERR_PTR(-ECHILD); | 142 | return ERR_PTR(-ECHILD); |
@@ -154,38 +147,7 @@ static const char *ovl_get_link(struct dentry *dentry, | |||
154 | if (WARN_ON(!realinode->i_op->get_link)) | 147 | if (WARN_ON(!realinode->i_op->get_link)) |
155 | return ERR_PTR(-EPERM); | 148 | return ERR_PTR(-EPERM); |
156 | 149 | ||
157 | if (realinode->i_op->put_link) { | 150 | return realinode->i_op->get_link(realdentry, realinode, done); |
158 | data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL); | ||
159 | if (!data) | ||
160 | return ERR_PTR(-ENOMEM); | ||
161 | data->realdentry = realdentry; | ||
162 | } | ||
163 | |||
164 | ret = realinode->i_op->get_link(realdentry, realinode, cookie); | ||
165 | if (IS_ERR_OR_NULL(ret)) { | ||
166 | kfree(data); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | if (data) | ||
171 | data->cookie = *cookie; | ||
172 | |||
173 | *cookie = data; | ||
174 | |||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | static void ovl_put_link(struct inode *unused, void *c) | ||
179 | { | ||
180 | struct inode *realinode; | ||
181 | struct ovl_link_data *data = c; | ||
182 | |||
183 | if (!data) | ||
184 | return; | ||
185 | |||
186 | realinode = data->realdentry->d_inode; | ||
187 | realinode->i_op->put_link(realinode, data->cookie); | ||
188 | kfree(data); | ||
189 | } | 151 | } |
190 | 152 | ||
191 | static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | 153 | static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) |
@@ -383,7 +345,6 @@ static const struct inode_operations ovl_file_inode_operations = { | |||
383 | static const struct inode_operations ovl_symlink_inode_operations = { | 345 | static const struct inode_operations ovl_symlink_inode_operations = { |
384 | .setattr = ovl_setattr, | 346 | .setattr = ovl_setattr, |
385 | .get_link = ovl_get_link, | 347 | .get_link = ovl_get_link, |
386 | .put_link = ovl_put_link, | ||
387 | .readlink = ovl_readlink, | 348 | .readlink = ovl_readlink, |
388 | .getattr = ovl_getattr, | 349 | .getattr = ovl_getattr, |
389 | .setxattr = ovl_setxattr, | 350 | .setxattr = ovl_setxattr, |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1a489e2b9768..71660bb9e9f7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1565,7 +1565,8 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path) | |||
1565 | } | 1565 | } |
1566 | 1566 | ||
1567 | static const char *proc_pid_get_link(struct dentry *dentry, | 1567 | static const char *proc_pid_get_link(struct dentry *dentry, |
1568 | struct inode *inode, void **cookie) | 1568 | struct inode *inode, |
1569 | struct delayed_call *done) | ||
1569 | { | 1570 | { |
1570 | struct path path; | 1571 | struct path path; |
1571 | int error = -EACCES; | 1572 | int error = -EACCES; |
@@ -1949,12 +1950,13 @@ struct map_files_info { | |||
1949 | */ | 1950 | */ |
1950 | static const char * | 1951 | static const char * |
1951 | proc_map_files_get_link(struct dentry *dentry, | 1952 | proc_map_files_get_link(struct dentry *dentry, |
1952 | struct inode *inode, void **cookie) | 1953 | struct inode *inode, |
1954 | struct delayed_call *done) | ||
1953 | { | 1955 | { |
1954 | if (!capable(CAP_SYS_ADMIN)) | 1956 | if (!capable(CAP_SYS_ADMIN)) |
1955 | return ERR_PTR(-EPERM); | 1957 | return ERR_PTR(-EPERM); |
1956 | 1958 | ||
1957 | return proc_pid_get_link(dentry, inode, NULL); | 1959 | return proc_pid_get_link(dentry, inode, done); |
1958 | } | 1960 | } |
1959 | 1961 | ||
1960 | /* | 1962 | /* |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 10360b268794..d0e9b9b6223e 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -393,25 +393,25 @@ static const struct file_operations proc_reg_file_ops_no_compat = { | |||
393 | }; | 393 | }; |
394 | #endif | 394 | #endif |
395 | 395 | ||
396 | static void proc_put_link(void *p) | ||
397 | { | ||
398 | unuse_pde(p); | ||
399 | } | ||
400 | |||
396 | static const char *proc_get_link(struct dentry *dentry, | 401 | static const char *proc_get_link(struct dentry *dentry, |
397 | struct inode *inode, void **cookie) | 402 | struct inode *inode, |
403 | struct delayed_call *done) | ||
398 | { | 404 | { |
399 | struct proc_dir_entry *pde = PDE(inode); | 405 | struct proc_dir_entry *pde = PDE(inode); |
400 | if (unlikely(!use_pde(pde))) | 406 | if (unlikely(!use_pde(pde))) |
401 | return ERR_PTR(-EINVAL); | 407 | return ERR_PTR(-EINVAL); |
402 | *cookie = pde; | 408 | set_delayed_call(done, proc_put_link, pde); |
403 | return pde->data; | 409 | return pde->data; |
404 | } | 410 | } |
405 | 411 | ||
406 | static void proc_put_link(struct inode *unused, void *p) | ||
407 | { | ||
408 | unuse_pde(p); | ||
409 | } | ||
410 | |||
411 | const struct inode_operations proc_link_inode_operations = { | 412 | const struct inode_operations proc_link_inode_operations = { |
412 | .readlink = generic_readlink, | 413 | .readlink = generic_readlink, |
413 | .get_link = proc_get_link, | 414 | .get_link = proc_get_link, |
414 | .put_link = proc_put_link, | ||
415 | }; | 415 | }; |
416 | 416 | ||
417 | struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) | 417 | struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) |
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 63861c15e109..1dece8781f91 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c | |||
@@ -31,7 +31,8 @@ static const struct proc_ns_operations *ns_entries[] = { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | static const char *proc_ns_get_link(struct dentry *dentry, | 33 | static const char *proc_ns_get_link(struct dentry *dentry, |
34 | struct inode *inode, void **cookie) | 34 | struct inode *inode, |
35 | struct delayed_call *done) | ||
35 | { | 36 | { |
36 | const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; | 37 | const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops; |
37 | struct task_struct *task; | 38 | struct task_struct *task; |
diff --git a/fs/proc/self.c b/fs/proc/self.c index 7a8b19ead3b6..67e8db442cf0 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c | |||
@@ -19,7 +19,8 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, | |||
19 | } | 19 | } |
20 | 20 | ||
21 | static const char *proc_self_get_link(struct dentry *dentry, | 21 | static const char *proc_self_get_link(struct dentry *dentry, |
22 | struct inode *inode, void **cookie) | 22 | struct inode *inode, |
23 | struct delayed_call *done) | ||
23 | { | 24 | { |
24 | struct pid_namespace *ns = inode->i_sb->s_fs_info; | 25 | struct pid_namespace *ns = inode->i_sb->s_fs_info; |
25 | pid_t tgid = task_tgid_nr_ns(current, ns); | 26 | pid_t tgid = task_tgid_nr_ns(current, ns); |
@@ -32,13 +33,13 @@ static const char *proc_self_get_link(struct dentry *dentry, | |||
32 | if (unlikely(!name)) | 33 | if (unlikely(!name)) |
33 | return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); | 34 | return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); |
34 | sprintf(name, "%d", tgid); | 35 | sprintf(name, "%d", tgid); |
35 | return *cookie = name; | 36 | set_delayed_call(done, kfree_link, name); |
37 | return name; | ||
36 | } | 38 | } |
37 | 39 | ||
38 | static const struct inode_operations proc_self_inode_operations = { | 40 | static const struct inode_operations proc_self_inode_operations = { |
39 | .readlink = proc_self_readlink, | 41 | .readlink = proc_self_readlink, |
40 | .get_link = proc_self_get_link, | 42 | .get_link = proc_self_get_link, |
41 | .put_link = kfree_put_link, | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | static unsigned self_inum; | 45 | static unsigned self_inum; |
diff --git a/fs/proc/thread_self.c b/fs/proc/thread_self.c index 03eaa84604da..9eacd59e0360 100644 --- a/fs/proc/thread_self.c +++ b/fs/proc/thread_self.c | |||
@@ -20,7 +20,8 @@ static int proc_thread_self_readlink(struct dentry *dentry, char __user *buffer, | |||
20 | } | 20 | } |
21 | 21 | ||
22 | static const char *proc_thread_self_get_link(struct dentry *dentry, | 22 | static const char *proc_thread_self_get_link(struct dentry *dentry, |
23 | struct inode *inode, void **cookie) | 23 | struct inode *inode, |
24 | struct delayed_call *done) | ||
24 | { | 25 | { |
25 | struct pid_namespace *ns = inode->i_sb->s_fs_info; | 26 | struct pid_namespace *ns = inode->i_sb->s_fs_info; |
26 | pid_t tgid = task_tgid_nr_ns(current, ns); | 27 | pid_t tgid = task_tgid_nr_ns(current, ns); |
@@ -34,13 +35,13 @@ static const char *proc_thread_self_get_link(struct dentry *dentry, | |||
34 | if (unlikely(!name)) | 35 | if (unlikely(!name)) |
35 | return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); | 36 | return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); |
36 | sprintf(name, "%d/task/%d", tgid, pid); | 37 | sprintf(name, "%d/task/%d", tgid, pid); |
37 | return *cookie = name; | 38 | set_delayed_call(done, kfree_link, name); |
39 | return name; | ||
38 | } | 40 | } |
39 | 41 | ||
40 | static const struct inode_operations proc_thread_self_inode_operations = { | 42 | static const struct inode_operations proc_thread_self_inode_operations = { |
41 | .readlink = proc_thread_self_readlink, | 43 | .readlink = proc_thread_self_readlink, |
42 | .get_link = proc_thread_self_get_link, | 44 | .get_link = proc_thread_self_get_link, |
43 | .put_link = kfree_put_link, | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | static unsigned thread_self_inum; | 47 | static unsigned thread_self_inum; |
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index ecbf11e961ab..2a12d46d7fb4 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -1666,7 +1666,6 @@ const struct inode_operations reiserfs_dir_inode_operations = { | |||
1666 | const struct inode_operations reiserfs_symlink_inode_operations = { | 1666 | const struct inode_operations reiserfs_symlink_inode_operations = { |
1667 | .readlink = generic_readlink, | 1667 | .readlink = generic_readlink, |
1668 | .get_link = page_get_link, | 1668 | .get_link = page_get_link, |
1669 | .put_link = page_put_link, | ||
1670 | .setattr = reiserfs_setattr, | 1669 | .setattr = reiserfs_setattr, |
1671 | .setxattr = reiserfs_setxattr, | 1670 | .setxattr = reiserfs_setxattr, |
1672 | .getxattr = reiserfs_getxattr, | 1671 | .getxattr = reiserfs_getxattr, |
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c index 7c635a5da783..dbcc2f54bad4 100644 --- a/fs/squashfs/symlink.c +++ b/fs/squashfs/symlink.c | |||
@@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = { | |||
120 | const struct inode_operations squashfs_symlink_inode_ops = { | 120 | const struct inode_operations squashfs_symlink_inode_ops = { |
121 | .readlink = generic_readlink, | 121 | .readlink = generic_readlink, |
122 | .get_link = page_get_link, | 122 | .get_link = page_get_link, |
123 | .put_link = page_put_link, | ||
124 | .getxattr = generic_getxattr, | 123 | .getxattr = generic_getxattr, |
125 | .listxattr = squashfs_listxattr | 124 | .listxattr = squashfs_listxattr |
126 | }; | 125 | }; |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 80a40bcb721c..07ac18c355e7 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -147,7 +147,6 @@ static inline void write3byte(struct sysv_sb_info *sbi, | |||
147 | static const struct inode_operations sysv_symlink_inode_operations = { | 147 | static const struct inode_operations sysv_symlink_inode_operations = { |
148 | .readlink = generic_readlink, | 148 | .readlink = generic_readlink, |
149 | .get_link = page_get_link, | 149 | .get_link = page_get_link, |
150 | .put_link = page_put_link, | ||
151 | .getattr = sysv_getattr, | 150 | .getattr = sysv_getattr, |
152 | }; | 151 | }; |
153 | 152 | ||
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index f638fd58b5b3..06eafafe636e 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -417,7 +417,7 @@ STATIC const char * | |||
417 | xfs_vn_get_link( | 417 | xfs_vn_get_link( |
418 | struct dentry *dentry, | 418 | struct dentry *dentry, |
419 | struct inode *inode, | 419 | struct inode *inode, |
420 | void **cookie) | 420 | struct delayed_call *done) |
421 | { | 421 | { |
422 | char *link; | 422 | char *link; |
423 | int error = -ENOMEM; | 423 | int error = -ENOMEM; |
@@ -433,7 +433,8 @@ xfs_vn_get_link( | |||
433 | if (unlikely(error)) | 433 | if (unlikely(error)) |
434 | goto out_kfree; | 434 | goto out_kfree; |
435 | 435 | ||
436 | return *cookie = link; | 436 | set_delayed_call(done, kfree_link, link); |
437 | return link; | ||
437 | 438 | ||
438 | out_kfree: | 439 | out_kfree: |
439 | kfree(link); | 440 | kfree(link); |
@@ -1177,7 +1178,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { | |||
1177 | static const struct inode_operations xfs_symlink_inode_operations = { | 1178 | static const struct inode_operations xfs_symlink_inode_operations = { |
1178 | .readlink = generic_readlink, | 1179 | .readlink = generic_readlink, |
1179 | .get_link = xfs_vn_get_link, | 1180 | .get_link = xfs_vn_get_link, |
1180 | .put_link = kfree_put_link, | ||
1181 | .getattr = xfs_vn_getattr, | 1181 | .getattr = xfs_vn_getattr, |
1182 | .setattr = xfs_vn_setattr, | 1182 | .setattr = xfs_vn_setattr, |
1183 | .setxattr = generic_setxattr, | 1183 | .setxattr = generic_setxattr, |
diff --git a/include/linux/delayed_call.h b/include/linux/delayed_call.h new file mode 100644 index 000000000000..f7fa76ae1a9b --- /dev/null +++ b/include/linux/delayed_call.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef _DELAYED_CALL_H | ||
2 | #define _DELAYED_CALL_H | ||
3 | |||
4 | /* | ||
5 | * Poor man's closures; I wish we could've done them sanely polymorphic, | ||
6 | * but... | ||
7 | */ | ||
8 | |||
9 | struct delayed_call { | ||
10 | void (*fn)(void *); | ||
11 | void *arg; | ||
12 | }; | ||
13 | |||
14 | #define DEFINE_DELAYED_CALL(name) struct delayed_call name = {NULL, NULL} | ||
15 | |||
16 | /* I really wish we had closures with sane typechecking... */ | ||
17 | static inline void set_delayed_call(struct delayed_call *call, | ||
18 | void (*fn)(void *), void *arg) | ||
19 | { | ||
20 | call->fn = fn; | ||
21 | call->arg = arg; | ||
22 | } | ||
23 | |||
24 | static inline void do_delayed_call(struct delayed_call *call) | ||
25 | { | ||
26 | if (call->fn) | ||
27 | call->fn(call->arg); | ||
28 | } | ||
29 | |||
30 | static inline void clear_delayed_call(struct delayed_call *call) | ||
31 | { | ||
32 | call->fn = NULL; | ||
33 | } | ||
34 | #endif | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 138e206df2fc..5de5edb01e70 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/blk_types.h> | 31 | #include <linux/blk_types.h> |
32 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
33 | #include <linux/percpu-rwsem.h> | 33 | #include <linux/percpu-rwsem.h> |
34 | #include <linux/delayed_call.h> | ||
34 | 35 | ||
35 | #include <asm/byteorder.h> | 36 | #include <asm/byteorder.h> |
36 | #include <uapi/linux/fs.h> | 37 | #include <uapi/linux/fs.h> |
@@ -1633,12 +1634,11 @@ struct file_operations { | |||
1633 | 1634 | ||
1634 | struct inode_operations { | 1635 | struct inode_operations { |
1635 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); | 1636 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); |
1636 | const char * (*get_link) (struct dentry *, struct inode *, void **); | 1637 | const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); |
1637 | int (*permission) (struct inode *, int); | 1638 | int (*permission) (struct inode *, int); |
1638 | struct posix_acl * (*get_acl)(struct inode *, int); | 1639 | struct posix_acl * (*get_acl)(struct inode *, int); |
1639 | 1640 | ||
1640 | int (*readlink) (struct dentry *, char __user *,int); | 1641 | int (*readlink) (struct dentry *, char __user *,int); |
1641 | void (*put_link) (struct inode *, void *); | ||
1642 | 1642 | ||
1643 | int (*create) (struct inode *,struct dentry *, umode_t, bool); | 1643 | int (*create) (struct inode *,struct dentry *, umode_t, bool); |
1644 | int (*link) (struct dentry *,struct inode *,struct dentry *); | 1644 | int (*link) (struct dentry *,struct inode *,struct dentry *); |
@@ -2736,13 +2736,14 @@ extern const struct file_operations generic_ro_fops; | |||
2736 | 2736 | ||
2737 | extern int readlink_copy(char __user *, int, const char *); | 2737 | extern int readlink_copy(char __user *, int, const char *); |
2738 | extern int page_readlink(struct dentry *, char __user *, int); | 2738 | extern int page_readlink(struct dentry *, char __user *, int); |
2739 | extern const char *page_get_link(struct dentry *, struct inode *, void **); | 2739 | extern const char *page_get_link(struct dentry *, struct inode *, |
2740 | extern void page_put_link(struct inode *, void *); | 2740 | struct delayed_call *); |
2741 | extern void page_put_link(void *); | ||
2741 | extern int __page_symlink(struct inode *inode, const char *symname, int len, | 2742 | extern int __page_symlink(struct inode *inode, const char *symname, int len, |
2742 | int nofs); | 2743 | int nofs); |
2743 | extern int page_symlink(struct inode *inode, const char *symname, int len); | 2744 | extern int page_symlink(struct inode *inode, const char *symname, int len); |
2744 | extern const struct inode_operations page_symlink_inode_operations; | 2745 | extern const struct inode_operations page_symlink_inode_operations; |
2745 | extern void kfree_put_link(struct inode *, void *); | 2746 | extern void kfree_link(void *); |
2746 | extern int generic_readlink(struct dentry *, char __user *, int); | 2747 | extern int generic_readlink(struct dentry *, char __user *, int); |
2747 | extern void generic_fillattr(struct inode *, struct kstat *); | 2748 | extern void generic_fillattr(struct inode *, struct kstat *); |
2748 | int vfs_getattr_nosec(struct path *path, struct kstat *stat); | 2749 | int vfs_getattr_nosec(struct path *path, struct kstat *stat); |
@@ -2753,7 +2754,8 @@ void __inode_sub_bytes(struct inode *inode, loff_t bytes); | |||
2753 | void inode_sub_bytes(struct inode *inode, loff_t bytes); | 2754 | void inode_sub_bytes(struct inode *inode, loff_t bytes); |
2754 | loff_t inode_get_bytes(struct inode *inode); | 2755 | loff_t inode_get_bytes(struct inode *inode); |
2755 | void inode_set_bytes(struct inode *inode, loff_t bytes); | 2756 | void inode_set_bytes(struct inode *inode, loff_t bytes); |
2756 | const char *simple_get_link(struct dentry *, struct inode *, void **); | 2757 | const char *simple_get_link(struct dentry *, struct inode *, |
2758 | struct delayed_call *); | ||
2757 | extern const struct inode_operations simple_symlink_inode_operations; | 2759 | extern const struct inode_operations simple_symlink_inode_operations; |
2758 | 2760 | ||
2759 | extern int iterate_dir(struct file *, struct dir_context *); | 2761 | extern int iterate_dir(struct file *, struct dir_context *); |
diff --git a/mm/shmem.c b/mm/shmem.c index 0605716aee06..bab9041b1967 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -2496,8 +2496,15 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s | |||
2496 | return 0; | 2496 | return 0; |
2497 | } | 2497 | } |
2498 | 2498 | ||
2499 | static void shmem_put_link(void *arg) | ||
2500 | { | ||
2501 | mark_page_accessed(arg); | ||
2502 | put_page(arg); | ||
2503 | } | ||
2504 | |||
2499 | static const char *shmem_get_link(struct dentry *dentry, | 2505 | static const char *shmem_get_link(struct dentry *dentry, |
2500 | struct inode *inode, void **cookie) | 2506 | struct inode *inode, |
2507 | struct delayed_call *done) | ||
2501 | { | 2508 | { |
2502 | struct page *page = NULL; | 2509 | struct page *page = NULL; |
2503 | int error; | 2510 | int error; |
@@ -2515,17 +2522,10 @@ static const char *shmem_get_link(struct dentry *dentry, | |||
2515 | return ERR_PTR(error); | 2522 | return ERR_PTR(error); |
2516 | unlock_page(page); | 2523 | unlock_page(page); |
2517 | } | 2524 | } |
2518 | *cookie = page; | 2525 | set_delayed_call(done, shmem_put_link, page); |
2519 | return page_address(page); | 2526 | return page_address(page); |
2520 | } | 2527 | } |
2521 | 2528 | ||
2522 | static void shmem_put_link(struct inode *unused, void *cookie) | ||
2523 | { | ||
2524 | struct page *page = cookie; | ||
2525 | mark_page_accessed(page); | ||
2526 | page_cache_release(page); | ||
2527 | } | ||
2528 | |||
2529 | #ifdef CONFIG_TMPFS_XATTR | 2529 | #ifdef CONFIG_TMPFS_XATTR |
2530 | /* | 2530 | /* |
2531 | * Superblocks without xattr inode operations may get some security.* xattr | 2531 | * Superblocks without xattr inode operations may get some security.* xattr |
@@ -2680,7 +2680,6 @@ static const struct inode_operations shmem_short_symlink_operations = { | |||
2680 | static const struct inode_operations shmem_symlink_inode_operations = { | 2680 | static const struct inode_operations shmem_symlink_inode_operations = { |
2681 | .readlink = generic_readlink, | 2681 | .readlink = generic_readlink, |
2682 | .get_link = shmem_get_link, | 2682 | .get_link = shmem_get_link, |
2683 | .put_link = shmem_put_link, | ||
2684 | #ifdef CONFIG_TMPFS_XATTR | 2683 | #ifdef CONFIG_TMPFS_XATTR |
2685 | .setxattr = shmem_setxattr, | 2684 | .setxattr = shmem_setxattr, |
2686 | .getxattr = shmem_getxattr, | 2685 | .getxattr = shmem_getxattr, |