diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-04 11:15:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-04 11:15:33 -0500 |
commit | 0f2cc4ecd81dc1917a041dc93db0ada28f8356fa (patch) | |
tree | f128b50f48f50f0cda6d2b20b53e9ad6e2dfded3 /fs/gfs2 | |
parent | 1fae4cfb97302289bb5df6a8195eb28385d0b002 (diff) | |
parent | 9643f5d94aadd47a5fa9754fb60f2c957de05903 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (52 commits)
init: Open /dev/console from rootfs
mqueue: fix typo "failues" -> "failures"
mqueue: only set error codes if they are really necessary
mqueue: simplify do_open() error handling
mqueue: apply mathematics distributivity on mq_bytes calculation
mqueue: remove unneeded info->messages initialization
mqueue: fix mq_open() file descriptor leak on user-space processes
fix race in d_splice_alias()
set S_DEAD on unlink() and non-directory rename() victims
vfs: add NOFOLLOW flag to umount(2)
get rid of ->mnt_parent in tomoyo/realpath
hppfs can use existing proc_mnt, no need for do_kern_mount() in there
Mirror MS_KERNMOUNT in ->mnt_flags
get rid of useless vfsmount_lock use in put_mnt_ns()
Take vfsmount_lock to fs/internal.h
get rid of insanity with namespace roots in tomoyo
take check for new events in namespace (guts of mounts_poll()) to namespace.c
Don't mess with generic_permission() under ->d_lock in hpfs
sanitize const/signedness for udf
nilfs: sanitize const/signedness in dealing with ->d_name.name
...
Fix up fairly trivial (famous last words...) conflicts in
drivers/infiniband/core/uverbs_main.c and security/tomoyo/realpath.c
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/ops_inode.c | 113 |
1 files changed, 27 insertions, 86 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index 84350e1be66d..4e64352d49de 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -976,122 +976,62 @@ out: | |||
976 | } | 976 | } |
977 | 977 | ||
978 | /** | 978 | /** |
979 | * gfs2_readlinki - return the contents of a symlink | 979 | * gfs2_follow_link - Follow a symbolic link |
980 | * @ip: the symlink's inode | 980 | * @dentry: The dentry of the link |
981 | * @buf: a pointer to the buffer to be filled | 981 | * @nd: Data that we pass to vfs_follow_link() |
982 | * @len: a pointer to the length of @buf | ||
983 | * | 982 | * |
984 | * If @buf is too small, a piece of memory is kmalloc()ed and needs | 983 | * This can handle symlinks of any size. |
985 | * to be freed by the caller. | ||
986 | * | 984 | * |
987 | * Returns: errno | 985 | * Returns: 0 on success or error code |
988 | */ | 986 | */ |
989 | 987 | ||
990 | static int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) | 988 | static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) |
991 | { | 989 | { |
990 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
992 | struct gfs2_holder i_gh; | 991 | struct gfs2_holder i_gh; |
993 | struct buffer_head *dibh; | 992 | struct buffer_head *dibh; |
994 | unsigned int x; | 993 | unsigned int x; |
994 | char *buf; | ||
995 | int error; | 995 | int error; |
996 | 996 | ||
997 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); | 997 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); |
998 | error = gfs2_glock_nq(&i_gh); | 998 | error = gfs2_glock_nq(&i_gh); |
999 | if (error) { | 999 | if (error) { |
1000 | gfs2_holder_uninit(&i_gh); | 1000 | gfs2_holder_uninit(&i_gh); |
1001 | return error; | 1001 | nd_set_link(nd, ERR_PTR(error)); |
1002 | return NULL; | ||
1002 | } | 1003 | } |
1003 | 1004 | ||
1004 | if (!ip->i_disksize) { | 1005 | if (!ip->i_disksize) { |
1005 | gfs2_consist_inode(ip); | 1006 | gfs2_consist_inode(ip); |
1006 | error = -EIO; | 1007 | buf = ERR_PTR(-EIO); |
1007 | goto out; | 1008 | goto out; |
1008 | } | 1009 | } |
1009 | 1010 | ||
1010 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1011 | error = gfs2_meta_inode_buffer(ip, &dibh); |
1011 | if (error) | 1012 | if (error) { |
1013 | buf = ERR_PTR(error); | ||
1012 | goto out; | 1014 | goto out; |
1013 | |||
1014 | x = ip->i_disksize + 1; | ||
1015 | if (x > *len) { | ||
1016 | *buf = kmalloc(x, GFP_NOFS); | ||
1017 | if (!*buf) { | ||
1018 | error = -ENOMEM; | ||
1019 | goto out_brelse; | ||
1020 | } | ||
1021 | } | 1015 | } |
1022 | 1016 | ||
1023 | memcpy(*buf, dibh->b_data + sizeof(struct gfs2_dinode), x); | 1017 | x = ip->i_disksize + 1; |
1024 | *len = x; | 1018 | buf = kmalloc(x, GFP_NOFS); |
1025 | 1019 | if (!buf) | |
1026 | out_brelse: | 1020 | buf = ERR_PTR(-ENOMEM); |
1021 | else | ||
1022 | memcpy(buf, dibh->b_data + sizeof(struct gfs2_dinode), x); | ||
1027 | brelse(dibh); | 1023 | brelse(dibh); |
1028 | out: | 1024 | out: |
1029 | gfs2_glock_dq_uninit(&i_gh); | 1025 | gfs2_glock_dq_uninit(&i_gh); |
1030 | return error; | 1026 | nd_set_link(nd, buf); |
1031 | } | 1027 | return NULL; |
1032 | |||
1033 | /** | ||
1034 | * gfs2_readlink - Read the value of a symlink | ||
1035 | * @dentry: the symlink | ||
1036 | * @buf: the buffer to read the symlink data into | ||
1037 | * @size: the size of the buffer | ||
1038 | * | ||
1039 | * Returns: errno | ||
1040 | */ | ||
1041 | |||
1042 | static int gfs2_readlink(struct dentry *dentry, char __user *user_buf, | ||
1043 | int user_size) | ||
1044 | { | ||
1045 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | ||
1046 | char array[GFS2_FAST_NAME_SIZE], *buf = array; | ||
1047 | unsigned int len = GFS2_FAST_NAME_SIZE; | ||
1048 | int error; | ||
1049 | |||
1050 | error = gfs2_readlinki(ip, &buf, &len); | ||
1051 | if (error) | ||
1052 | return error; | ||
1053 | |||
1054 | if (user_size > len - 1) | ||
1055 | user_size = len - 1; | ||
1056 | |||
1057 | if (copy_to_user(user_buf, buf, user_size)) | ||
1058 | error = -EFAULT; | ||
1059 | else | ||
1060 | error = user_size; | ||
1061 | |||
1062 | if (buf != array) | ||
1063 | kfree(buf); | ||
1064 | |||
1065 | return error; | ||
1066 | } | 1028 | } |
1067 | 1029 | ||
1068 | /** | 1030 | static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p) |
1069 | * gfs2_follow_link - Follow a symbolic link | ||
1070 | * @dentry: The dentry of the link | ||
1071 | * @nd: Data that we pass to vfs_follow_link() | ||
1072 | * | ||
1073 | * This can handle symlinks of any size. It is optimised for symlinks | ||
1074 | * under GFS2_FAST_NAME_SIZE. | ||
1075 | * | ||
1076 | * Returns: 0 on success or error code | ||
1077 | */ | ||
1078 | |||
1079 | static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
1080 | { | 1031 | { |
1081 | struct gfs2_inode *ip = GFS2_I(dentry->d_inode); | 1032 | char *s = nd_get_link(nd); |
1082 | char array[GFS2_FAST_NAME_SIZE], *buf = array; | 1033 | if (!IS_ERR(s)) |
1083 | unsigned int len = GFS2_FAST_NAME_SIZE; | 1034 | kfree(s); |
1084 | int error; | ||
1085 | |||
1086 | error = gfs2_readlinki(ip, &buf, &len); | ||
1087 | if (!error) { | ||
1088 | error = vfs_follow_link(nd, buf); | ||
1089 | if (buf != array) | ||
1090 | kfree(buf); | ||
1091 | } else | ||
1092 | path_put(&nd->path); | ||
1093 | |||
1094 | return ERR_PTR(error); | ||
1095 | } | 1035 | } |
1096 | 1036 | ||
1097 | /** | 1037 | /** |
@@ -1426,8 +1366,9 @@ const struct inode_operations gfs2_dir_iops = { | |||
1426 | }; | 1366 | }; |
1427 | 1367 | ||
1428 | const struct inode_operations gfs2_symlink_iops = { | 1368 | const struct inode_operations gfs2_symlink_iops = { |
1429 | .readlink = gfs2_readlink, | 1369 | .readlink = generic_readlink, |
1430 | .follow_link = gfs2_follow_link, | 1370 | .follow_link = gfs2_follow_link, |
1371 | .put_link = gfs2_put_link, | ||
1431 | .permission = gfs2_permission, | 1372 | .permission = gfs2_permission, |
1432 | .setattr = gfs2_setattr, | 1373 | .setattr = gfs2_setattr, |
1433 | .getattr = gfs2_getattr, | 1374 | .getattr = gfs2_getattr, |