diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 106 |
1 files changed, 44 insertions, 62 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 4bd112313f33..6f04493b8aba 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -78,92 +78,74 @@ xfs_find_handle( | |||
78 | int hsize; | 78 | int hsize; |
79 | xfs_handle_t handle; | 79 | xfs_handle_t handle; |
80 | struct inode *inode; | 80 | struct inode *inode; |
81 | struct file *file = NULL; | ||
82 | struct path path; | ||
83 | int error; | ||
84 | struct xfs_inode *ip; | ||
81 | 85 | ||
82 | memset((char *)&handle, 0, sizeof(handle)); | 86 | if (cmd == XFS_IOC_FD_TO_HANDLE) { |
83 | 87 | file = fget(hreq->fd); | |
84 | switch (cmd) { | 88 | if (!file) |
85 | case XFS_IOC_PATH_TO_FSHANDLE: | 89 | return -EBADF; |
86 | case XFS_IOC_PATH_TO_HANDLE: { | 90 | inode = file->f_path.dentry->d_inode; |
87 | struct path path; | 91 | } else { |
88 | int error = user_lpath((const char __user *)hreq->path, &path); | 92 | error = user_lpath((const char __user *)hreq->path, &path); |
89 | if (error) | 93 | if (error) |
90 | return error; | 94 | return error; |
91 | 95 | inode = path.dentry->d_inode; | |
92 | ASSERT(path.dentry); | ||
93 | ASSERT(path.dentry->d_inode); | ||
94 | inode = igrab(path.dentry->d_inode); | ||
95 | path_put(&path); | ||
96 | break; | ||
97 | } | 96 | } |
97 | ip = XFS_I(inode); | ||
98 | 98 | ||
99 | case XFS_IOC_FD_TO_HANDLE: { | 99 | /* |
100 | struct file *file; | 100 | * We can only generate handles for inodes residing on a XFS filesystem, |
101 | 101 | * and only for regular files, directories or symbolic links. | |
102 | file = fget(hreq->fd); | 102 | */ |
103 | if (!file) | 103 | error = -EINVAL; |
104 | return -EBADF; | 104 | if (inode->i_sb->s_magic != XFS_SB_MAGIC) |
105 | goto out_put; | ||
105 | 106 | ||
106 | ASSERT(file->f_path.dentry); | 107 | error = -EBADF; |
107 | ASSERT(file->f_path.dentry->d_inode); | 108 | if (!S_ISREG(inode->i_mode) && |
108 | inode = igrab(file->f_path.dentry->d_inode); | 109 | !S_ISDIR(inode->i_mode) && |
109 | fput(file); | 110 | !S_ISLNK(inode->i_mode)) |
110 | break; | 111 | goto out_put; |
111 | } | ||
112 | 112 | ||
113 | default: | ||
114 | ASSERT(0); | ||
115 | return -XFS_ERROR(EINVAL); | ||
116 | } | ||
117 | 113 | ||
118 | if (inode->i_sb->s_magic != XFS_SB_MAGIC) { | 114 | memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t)); |
119 | /* we're not in XFS anymore, Toto */ | ||
120 | iput(inode); | ||
121 | return -XFS_ERROR(EINVAL); | ||
122 | } | ||
123 | 115 | ||
124 | switch (inode->i_mode & S_IFMT) { | 116 | if (cmd == XFS_IOC_PATH_TO_FSHANDLE) { |
125 | case S_IFREG: | 117 | /* |
126 | case S_IFDIR: | 118 | * This handle only contains an fsid, zero the rest. |
127 | case S_IFLNK: | 119 | */ |
128 | break; | 120 | memset(&handle.ha_fid, 0, sizeof(handle.ha_fid)); |
129 | default: | 121 | hsize = sizeof(xfs_fsid_t); |
130 | iput(inode); | 122 | } else { |
131 | return -XFS_ERROR(EBADF); | ||
132 | } | ||
133 | |||
134 | /* now we can grab the fsid */ | ||
135 | memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid, | ||
136 | sizeof(xfs_fsid_t)); | ||
137 | hsize = sizeof(xfs_fsid_t); | ||
138 | |||
139 | if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { | ||
140 | xfs_inode_t *ip = XFS_I(inode); | ||
141 | int lock_mode; | 123 | int lock_mode; |
142 | 124 | ||
143 | /* need to get access to the xfs_inode to read the generation */ | ||
144 | lock_mode = xfs_ilock_map_shared(ip); | 125 | lock_mode = xfs_ilock_map_shared(ip); |
145 | |||
146 | /* fill in fid section of handle from inode */ | ||
147 | handle.ha_fid.fid_len = sizeof(xfs_fid_t) - | 126 | handle.ha_fid.fid_len = sizeof(xfs_fid_t) - |
148 | sizeof(handle.ha_fid.fid_len); | 127 | sizeof(handle.ha_fid.fid_len); |
149 | handle.ha_fid.fid_pad = 0; | 128 | handle.ha_fid.fid_pad = 0; |
150 | handle.ha_fid.fid_gen = ip->i_d.di_gen; | 129 | handle.ha_fid.fid_gen = ip->i_d.di_gen; |
151 | handle.ha_fid.fid_ino = ip->i_ino; | 130 | handle.ha_fid.fid_ino = ip->i_ino; |
152 | |||
153 | xfs_iunlock_map_shared(ip, lock_mode); | 131 | xfs_iunlock_map_shared(ip, lock_mode); |
154 | 132 | ||
155 | hsize = XFS_HSIZE(handle); | 133 | hsize = XFS_HSIZE(handle); |
156 | } | 134 | } |
157 | 135 | ||
158 | /* now copy our handle into the user buffer & write out the size */ | 136 | error = -EFAULT; |
159 | if (copy_to_user(hreq->ohandle, &handle, hsize) || | 137 | if (copy_to_user(hreq->ohandle, &handle, hsize) || |
160 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) { | 138 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) |
161 | iput(inode); | 139 | goto out_put; |
162 | return -XFS_ERROR(EFAULT); | ||
163 | } | ||
164 | 140 | ||
165 | iput(inode); | 141 | error = 0; |
166 | return 0; | 142 | |
143 | out_put: | ||
144 | if (cmd == XFS_IOC_FD_TO_HANDLE) | ||
145 | fput(file); | ||
146 | else | ||
147 | path_put(&path); | ||
148 | return error; | ||
167 | } | 149 | } |
168 | 150 | ||
169 | /* | 151 | /* |