aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_dfrag.c71
1 files changed, 40 insertions, 31 deletions
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 681be5c93af5..8dd7a3923f64 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -65,9 +65,9 @@
65 */ 65 */
66int 66int
67xfs_swapext( 67xfs_swapext(
68 xfs_swapext_t __user *sxp) 68 xfs_swapext_t __user *sxu)
69{ 69{
70 xfs_swapext_t sx; 70 xfs_swapext_t *sxp;
71 xfs_inode_t *ip=NULL, *tip=NULL, *ips[2]; 71 xfs_inode_t *ip=NULL, *tip=NULL, *ips[2];
72 xfs_trans_t *tp; 72 xfs_trans_t *tp;
73 xfs_mount_t *mp; 73 xfs_mount_t *mp;
@@ -76,20 +76,29 @@ xfs_swapext(
76 vnode_t *vp, *tvp; 76 vnode_t *vp, *tvp;
77 bhv_desc_t *bdp, *tbdp; 77 bhv_desc_t *bdp, *tbdp;
78 vn_bhv_head_t *bhp, *tbhp; 78 vn_bhv_head_t *bhp, *tbhp;
79 uint lock_flags=0; 79 static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
80 int ilf_fields, tilf_fields; 80 int ilf_fields, tilf_fields;
81 int error = 0; 81 int error = 0;
82 xfs_ifork_t tempif, *ifp, *tifp; 82 xfs_ifork_t *tempifp, *ifp, *tifp;
83 __uint64_t tmp; 83 __uint64_t tmp;
84 int aforkblks = 0; 84 int aforkblks = 0;
85 int taforkblks = 0; 85 int taforkblks = 0;
86 int locked = 0; 86 char locked = 0;
87 87
88 if (copy_from_user(&sx, sxp, sizeof(sx))) 88 sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
89 return XFS_ERROR(EFAULT); 89 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
90 if (!sxp || !tempifp) {
91 error = XFS_ERROR(ENOMEM);
92 goto error0;
93 }
94
95 if (copy_from_user(sxp, sxu, sizeof(xfs_swapext_t))) {
96 error = XFS_ERROR(EFAULT);
97 goto error0;
98 }
90 99
91 /* Pull information for the target fd */ 100 /* Pull information for the target fd */
92 if (((fp = fget((int)sx.sx_fdtarget)) == NULL) || 101 if (((fp = fget((int)sxp->sx_fdtarget)) == NULL) ||
93 ((vp = LINVFS_GET_VP(fp->f_dentry->d_inode)) == NULL)) { 102 ((vp = LINVFS_GET_VP(fp->f_dentry->d_inode)) == NULL)) {
94 error = XFS_ERROR(EINVAL); 103 error = XFS_ERROR(EINVAL);
95 goto error0; 104 goto error0;
@@ -104,7 +113,7 @@ xfs_swapext(
104 ip = XFS_BHVTOI(bdp); 113 ip = XFS_BHVTOI(bdp);
105 } 114 }
106 115
107 if (((tfp = fget((int)sx.sx_fdtmp)) == NULL) || 116 if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) ||
108 ((tvp = LINVFS_GET_VP(tfp->f_dentry->d_inode)) == NULL)) { 117 ((tvp = LINVFS_GET_VP(tfp->f_dentry->d_inode)) == NULL)) {
109 error = XFS_ERROR(EINVAL); 118 error = XFS_ERROR(EINVAL);
110 goto error0; 119 goto error0;
@@ -131,7 +140,7 @@ xfs_swapext(
131 140
132 mp = ip->i_mount; 141 mp = ip->i_mount;
133 142
134 sbp = &sx.sx_stat; 143 sbp = &sxp->sx_stat;
135 144
136 if (XFS_FORCED_SHUTDOWN(mp)) { 145 if (XFS_FORCED_SHUTDOWN(mp)) {
137 error = XFS_ERROR(EIO); 146 error = XFS_ERROR(EIO);
@@ -148,7 +157,7 @@ xfs_swapext(
148 ips[0] = tip; 157 ips[0] = tip;
149 ips[1] = ip; 158 ips[1] = ip;
150 } 159 }
151 lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; 160
152 xfs_lock_inodes(ips, 2, 0, lock_flags); 161 xfs_lock_inodes(ips, 2, 0, lock_flags);
153 162
154 /* Check permissions */ 163 /* Check permissions */
@@ -192,9 +201,9 @@ xfs_swapext(
192 } 201 }
193 202
194 /* Verify all data are being swapped */ 203 /* Verify all data are being swapped */
195 if (sx.sx_offset != 0 || 204 if (sxp->sx_offset != 0 ||
196 sx.sx_length != ip->i_d.di_size || 205 sxp->sx_length != ip->i_d.di_size ||
197 sx.sx_length != tip->i_d.di_size) { 206 sxp->sx_length != tip->i_d.di_size) {
198 error = XFS_ERROR(EFAULT); 207 error = XFS_ERROR(EFAULT);
199 goto error0; 208 goto error0;
200 } 209 }
@@ -255,7 +264,8 @@ xfs_swapext(
255 xfs_iunlock(ip, XFS_IOLOCK_EXCL); 264 xfs_iunlock(ip, XFS_IOLOCK_EXCL);
256 xfs_iunlock(tip, XFS_IOLOCK_EXCL); 265 xfs_iunlock(tip, XFS_IOLOCK_EXCL);
257 xfs_trans_cancel(tp, 0); 266 xfs_trans_cancel(tp, 0);
258 return error; 267 locked = 0;
268 goto error0;
259 } 269 }
260 xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL); 270 xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
261 271
@@ -266,10 +276,8 @@ xfs_swapext(
266 (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { 276 (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
267 error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks); 277 error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks);
268 if (error) { 278 if (error) {
269 xfs_iunlock(ip, lock_flags);
270 xfs_iunlock(tip, lock_flags);
271 xfs_trans_cancel(tp, 0); 279 xfs_trans_cancel(tp, 0);
272 return error; 280 goto error0;
273 } 281 }
274 } 282 }
275 if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && 283 if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
@@ -277,10 +285,8 @@ xfs_swapext(
277 error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, 285 error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK,
278 &taforkblks); 286 &taforkblks);
279 if (error) { 287 if (error) {
280 xfs_iunlock(ip, lock_flags);
281 xfs_iunlock(tip, lock_flags);
282 xfs_trans_cancel(tp, 0); 288 xfs_trans_cancel(tp, 0);
283 return error; 289 goto error0;
284 } 290 }
285 } 291 }
286 292
@@ -289,9 +295,9 @@ xfs_swapext(
289 */ 295 */
290 ifp = &ip->i_df; 296 ifp = &ip->i_df;
291 tifp = &tip->i_df; 297 tifp = &tip->i_df;
292 tempif = *ifp; /* struct copy */ 298 *tempifp = *ifp; /* struct copy */
293 *ifp = *tifp; /* struct copy */ 299 *ifp = *tifp; /* struct copy */
294 *tifp = tempif; /* struct copy */ 300 *tifp = *tempifp; /* struct copy */
295 301
296 /* 302 /*
297 * Fix the on-disk inode values 303 * Fix the on-disk inode values
@@ -369,11 +375,7 @@ xfs_swapext(
369 } 375 }
370 376
371 error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT, NULL); 377 error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT, NULL);
372 378 locked = 0;
373 fput(fp);
374 fput(tfp);
375
376 return error;
377 379
378 error0: 380 error0:
379 if (locked) { 381 if (locked) {
@@ -381,8 +383,15 @@ xfs_swapext(
381 xfs_iunlock(tip, lock_flags); 383 xfs_iunlock(tip, lock_flags);
382 } 384 }
383 385
384 if (fp != NULL) fput(fp); 386 if (fp != NULL)
385 if (tfp != NULL) fput(tfp); 387 fput(fp);
388 if (tfp != NULL)
389 fput(tfp);
390
391 if (sxp != NULL)
392 kmem_free(sxp, sizeof(xfs_swapext_t));
393 if (tempifp != NULL)
394 kmem_free(tempifp, sizeof(xfs_ifork_t));
386 395
387 return error; 396 return error;
388} 397}