diff options
Diffstat (limited to 'fs/xfs/xfs_dfrag.c')
-rw-r--r-- | fs/xfs/xfs_dfrag.c | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index f8278cfcc1d3..e6d839bddbf0 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -79,6 +79,12 @@ xfs_swapext( | |||
79 | goto out_put_target_file; | 79 | goto out_put_target_file; |
80 | } | 80 | } |
81 | 81 | ||
82 | if (IS_SWAPFILE(file->f_path.dentry->d_inode) || | ||
83 | IS_SWAPFILE(target_file->f_path.dentry->d_inode)) { | ||
84 | error = XFS_ERROR(EINVAL); | ||
85 | goto out_put_target_file; | ||
86 | } | ||
87 | |||
82 | ip = XFS_I(file->f_path.dentry->d_inode); | 88 | ip = XFS_I(file->f_path.dentry->d_inode); |
83 | tip = XFS_I(target_file->f_path.dentry->d_inode); | 89 | tip = XFS_I(target_file->f_path.dentry->d_inode); |
84 | 90 | ||
@@ -118,19 +124,17 @@ xfs_swap_extents( | |||
118 | xfs_bstat_t *sbp = &sxp->sx_stat; | 124 | xfs_bstat_t *sbp = &sxp->sx_stat; |
119 | xfs_ifork_t *tempifp, *ifp, *tifp; | 125 | xfs_ifork_t *tempifp, *ifp, *tifp; |
120 | int ilf_fields, tilf_fields; | 126 | int ilf_fields, tilf_fields; |
121 | static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; | ||
122 | int error = 0; | 127 | int error = 0; |
123 | int aforkblks = 0; | 128 | int aforkblks = 0; |
124 | int taforkblks = 0; | 129 | int taforkblks = 0; |
125 | __uint64_t tmp; | 130 | __uint64_t tmp; |
126 | char locked = 0; | ||
127 | 131 | ||
128 | mp = ip->i_mount; | 132 | mp = ip->i_mount; |
129 | 133 | ||
130 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); | 134 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); |
131 | if (!tempifp) { | 135 | if (!tempifp) { |
132 | error = XFS_ERROR(ENOMEM); | 136 | error = XFS_ERROR(ENOMEM); |
133 | goto error0; | 137 | goto out; |
134 | } | 138 | } |
135 | 139 | ||
136 | sbp = &sxp->sx_stat; | 140 | sbp = &sxp->sx_stat; |
@@ -143,25 +147,24 @@ xfs_swap_extents( | |||
143 | */ | 147 | */ |
144 | xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); | 148 | xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); |
145 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); | 149 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); |
146 | locked = 1; | ||
147 | 150 | ||
148 | /* Verify that both files have the same format */ | 151 | /* Verify that both files have the same format */ |
149 | if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { | 152 | if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { |
150 | error = XFS_ERROR(EINVAL); | 153 | error = XFS_ERROR(EINVAL); |
151 | goto error0; | 154 | goto out_unlock; |
152 | } | 155 | } |
153 | 156 | ||
154 | /* Verify both files are either real-time or non-realtime */ | 157 | /* Verify both files are either real-time or non-realtime */ |
155 | if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) { | 158 | if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) { |
156 | error = XFS_ERROR(EINVAL); | 159 | error = XFS_ERROR(EINVAL); |
157 | goto error0; | 160 | goto out_unlock; |
158 | } | 161 | } |
159 | 162 | ||
160 | /* Should never get a local format */ | 163 | /* Should never get a local format */ |
161 | if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL || | 164 | if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL || |
162 | tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | 165 | tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
163 | error = XFS_ERROR(EINVAL); | 166 | error = XFS_ERROR(EINVAL); |
164 | goto error0; | 167 | goto out_unlock; |
165 | } | 168 | } |
166 | 169 | ||
167 | if (VN_CACHED(VFS_I(tip)) != 0) { | 170 | if (VN_CACHED(VFS_I(tip)) != 0) { |
@@ -169,13 +172,13 @@ xfs_swap_extents( | |||
169 | error = xfs_flushinval_pages(tip, 0, -1, | 172 | error = xfs_flushinval_pages(tip, 0, -1, |
170 | FI_REMAPF_LOCKED); | 173 | FI_REMAPF_LOCKED); |
171 | if (error) | 174 | if (error) |
172 | goto error0; | 175 | goto out_unlock; |
173 | } | 176 | } |
174 | 177 | ||
175 | /* Verify O_DIRECT for ftmp */ | 178 | /* Verify O_DIRECT for ftmp */ |
176 | if (VN_CACHED(VFS_I(tip)) != 0) { | 179 | if (VN_CACHED(VFS_I(tip)) != 0) { |
177 | error = XFS_ERROR(EINVAL); | 180 | error = XFS_ERROR(EINVAL); |
178 | goto error0; | 181 | goto out_unlock; |
179 | } | 182 | } |
180 | 183 | ||
181 | /* Verify all data are being swapped */ | 184 | /* Verify all data are being swapped */ |
@@ -183,7 +186,7 @@ xfs_swap_extents( | |||
183 | sxp->sx_length != ip->i_d.di_size || | 186 | sxp->sx_length != ip->i_d.di_size || |
184 | sxp->sx_length != tip->i_d.di_size) { | 187 | sxp->sx_length != tip->i_d.di_size) { |
185 | error = XFS_ERROR(EFAULT); | 188 | error = XFS_ERROR(EFAULT); |
186 | goto error0; | 189 | goto out_unlock; |
187 | } | 190 | } |
188 | 191 | ||
189 | /* | 192 | /* |
@@ -193,7 +196,7 @@ xfs_swap_extents( | |||
193 | */ | 196 | */ |
194 | if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) { | 197 | if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) { |
195 | error = XFS_ERROR(EINVAL); | 198 | error = XFS_ERROR(EINVAL); |
196 | goto error0; | 199 | goto out_unlock; |
197 | } | 200 | } |
198 | 201 | ||
199 | /* | 202 | /* |
@@ -208,7 +211,7 @@ xfs_swap_extents( | |||
208 | (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || | 211 | (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || |
209 | (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { | 212 | (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { |
210 | error = XFS_ERROR(EBUSY); | 213 | error = XFS_ERROR(EBUSY); |
211 | goto error0; | 214 | goto out_unlock; |
212 | } | 215 | } |
213 | 216 | ||
214 | /* We need to fail if the file is memory mapped. Once we have tossed | 217 | /* We need to fail if the file is memory mapped. Once we have tossed |
@@ -219,7 +222,7 @@ xfs_swap_extents( | |||
219 | */ | 222 | */ |
220 | if (VN_MAPPED(VFS_I(ip))) { | 223 | if (VN_MAPPED(VFS_I(ip))) { |
221 | error = XFS_ERROR(EBUSY); | 224 | error = XFS_ERROR(EBUSY); |
222 | goto error0; | 225 | goto out_unlock; |
223 | } | 226 | } |
224 | 227 | ||
225 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 228 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
@@ -242,8 +245,7 @@ xfs_swap_extents( | |||
242 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 245 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
243 | xfs_iunlock(tip, XFS_IOLOCK_EXCL); | 246 | xfs_iunlock(tip, XFS_IOLOCK_EXCL); |
244 | xfs_trans_cancel(tp, 0); | 247 | xfs_trans_cancel(tp, 0); |
245 | locked = 0; | 248 | goto out; |
246 | goto error0; | ||
247 | } | 249 | } |
248 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); | 250 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); |
249 | 251 | ||
@@ -253,19 +255,15 @@ xfs_swap_extents( | |||
253 | if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) && | 255 | if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) && |
254 | (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { | 256 | (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { |
255 | error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks); | 257 | error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks); |
256 | if (error) { | 258 | if (error) |
257 | xfs_trans_cancel(tp, 0); | 259 | goto out_trans_cancel; |
258 | goto error0; | ||
259 | } | ||
260 | } | 260 | } |
261 | if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && | 261 | if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && |
262 | (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { | 262 | (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { |
263 | error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, | 263 | error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, |
264 | &taforkblks); | 264 | &taforkblks); |
265 | if (error) { | 265 | if (error) |
266 | xfs_trans_cancel(tp, 0); | 266 | goto out_trans_cancel; |
267 | goto error0; | ||
268 | } | ||
269 | } | 267 | } |
270 | 268 | ||
271 | /* | 269 | /* |
@@ -332,10 +330,10 @@ xfs_swap_extents( | |||
332 | 330 | ||
333 | 331 | ||
334 | IHOLD(ip); | 332 | IHOLD(ip); |
335 | xfs_trans_ijoin(tp, ip, lock_flags); | 333 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
336 | 334 | ||
337 | IHOLD(tip); | 335 | IHOLD(tip); |
338 | xfs_trans_ijoin(tp, tip, lock_flags); | 336 | xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
339 | 337 | ||
340 | xfs_trans_log_inode(tp, ip, ilf_fields); | 338 | xfs_trans_log_inode(tp, ip, ilf_fields); |
341 | xfs_trans_log_inode(tp, tip, tilf_fields); | 339 | xfs_trans_log_inode(tp, tip, tilf_fields); |
@@ -344,19 +342,19 @@ xfs_swap_extents( | |||
344 | * If this is a synchronous mount, make sure that the | 342 | * If this is a synchronous mount, make sure that the |
345 | * transaction goes to disk before returning to the user. | 343 | * transaction goes to disk before returning to the user. |
346 | */ | 344 | */ |
347 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 345 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
348 | xfs_trans_set_sync(tp); | 346 | xfs_trans_set_sync(tp); |
349 | } | ||
350 | 347 | ||
351 | error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT); | 348 | error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT); |
352 | locked = 0; | ||
353 | 349 | ||
354 | error0: | 350 | out_unlock: |
355 | if (locked) { | 351 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
356 | xfs_iunlock(ip, lock_flags); | 352 | xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
357 | xfs_iunlock(tip, lock_flags); | 353 | out: |
358 | } | 354 | kmem_free(tempifp); |
359 | if (tempifp != NULL) | ||
360 | kmem_free(tempifp); | ||
361 | return error; | 355 | return error; |
356 | |||
357 | out_trans_cancel: | ||
358 | xfs_trans_cancel(tp, 0); | ||
359 | goto out_unlock; | ||
362 | } | 360 | } |