diff options
| -rw-r--r-- | fs/xfs/quota/xfs_qm_syscalls.c | 70 | ||||
| -rw-r--r-- | fs/xfs/xfs_utils.c | 83 | ||||
| -rw-r--r-- | fs/xfs/xfs_utils.h | 1 |
3 files changed, 52 insertions, 102 deletions
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 73f2b203975e..d257eb8557c4 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
| @@ -238,40 +238,74 @@ out_unlock: | |||
| 238 | return error; | 238 | return error; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | STATIC int | ||
| 242 | xfs_qm_scall_trunc_qfile( | ||
| 243 | struct xfs_mount *mp, | ||
| 244 | xfs_ino_t ino) | ||
| 245 | { | ||
| 246 | struct xfs_inode *ip; | ||
| 247 | struct xfs_trans *tp; | ||
| 248 | int error; | ||
| 249 | |||
| 250 | if (ino == NULLFSINO) | ||
| 251 | return 0; | ||
| 252 | |||
| 253 | error = xfs_iget(mp, NULL, ino, 0, 0, &ip); | ||
| 254 | if (error) | ||
| 255 | return error; | ||
| 256 | |||
| 257 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
| 258 | |||
| 259 | tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE); | ||
| 260 | error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, | ||
| 261 | XFS_TRANS_PERM_LOG_RES, | ||
| 262 | XFS_ITRUNCATE_LOG_COUNT); | ||
| 263 | if (error) { | ||
| 264 | xfs_trans_cancel(tp, 0); | ||
| 265 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
| 266 | goto out_put; | ||
| 267 | } | ||
| 268 | |||
| 269 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 270 | xfs_trans_ijoin(tp, ip); | ||
| 271 | |||
| 272 | error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK, 1); | ||
| 273 | if (error) { | ||
| 274 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | | ||
| 275 | XFS_TRANS_ABORT); | ||
| 276 | goto out_unlock; | ||
| 277 | } | ||
| 278 | |||
| 279 | xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
| 280 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
| 281 | |||
| 282 | out_unlock: | ||
| 283 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
| 284 | out_put: | ||
| 285 | IRELE(ip); | ||
| 286 | return error; | ||
| 287 | } | ||
| 288 | |||
| 241 | int | 289 | int |
| 242 | xfs_qm_scall_trunc_qfiles( | 290 | xfs_qm_scall_trunc_qfiles( |
| 243 | xfs_mount_t *mp, | 291 | xfs_mount_t *mp, |
| 244 | uint flags) | 292 | uint flags) |
| 245 | { | 293 | { |
| 246 | int error = 0, error2 = 0; | 294 | int error = 0, error2 = 0; |
| 247 | xfs_inode_t *qip; | ||
| 248 | 295 | ||
| 249 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { | 296 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { |
| 250 | qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); | 297 | qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); |
| 251 | return XFS_ERROR(EINVAL); | 298 | return XFS_ERROR(EINVAL); |
| 252 | } | 299 | } |
| 253 | 300 | ||
| 254 | if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) { | 301 | if (flags & XFS_DQ_USER) |
| 255 | error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip); | 302 | error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino); |
| 256 | if (!error) { | 303 | if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) |
| 257 | error = xfs_truncate_file(mp, qip); | 304 | error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino); |
| 258 | IRELE(qip); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) && | ||
| 263 | mp->m_sb.sb_gquotino != NULLFSINO) { | ||
| 264 | error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip); | ||
| 265 | if (!error2) { | ||
| 266 | error2 = xfs_truncate_file(mp, qip); | ||
| 267 | IRELE(qip); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | 305 | ||
| 271 | return error ? error : error2; | 306 | return error ? error : error2; |
| 272 | } | 307 | } |
| 273 | 308 | ||
| 274 | |||
| 275 | /* | 309 | /* |
| 276 | * Switch on (a given) quota enforcement for a filesystem. This takes | 310 | * Switch on (a given) quota enforcement for a filesystem. This takes |
| 277 | * effect immediately. | 311 | * effect immediately. |
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 102ce4898ab7..b7d5769d2df0 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c | |||
| @@ -320,86 +320,3 @@ xfs_bumplink( | |||
| 320 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 320 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
| 321 | return 0; | 321 | return 0; |
| 322 | } | 322 | } |
| 323 | |||
| 324 | /* | ||
| 325 | * Try to truncate the given file to 0 length. Currently called | ||
| 326 | * only out of xfs_remove when it has to truncate a file to free | ||
| 327 | * up space for the remove to proceed. | ||
| 328 | */ | ||
| 329 | int | ||
| 330 | xfs_truncate_file( | ||
| 331 | xfs_mount_t *mp, | ||
| 332 | xfs_inode_t *ip) | ||
| 333 | { | ||
| 334 | xfs_trans_t *tp; | ||
| 335 | int error; | ||
| 336 | |||
| 337 | #ifdef QUOTADEBUG | ||
| 338 | /* | ||
| 339 | * This is called to truncate the quotainodes too. | ||
| 340 | */ | ||
| 341 | if (XFS_IS_UQUOTA_ON(mp)) { | ||
| 342 | if (ip->i_ino != mp->m_sb.sb_uquotino) | ||
| 343 | ASSERT(ip->i_udquot); | ||
| 344 | } | ||
| 345 | if (XFS_IS_OQUOTA_ON(mp)) { | ||
| 346 | if (ip->i_ino != mp->m_sb.sb_gquotino) | ||
| 347 | ASSERT(ip->i_gdquot); | ||
| 348 | } | ||
| 349 | #endif | ||
| 350 | /* | ||
| 351 | * Make the call to xfs_itruncate_start before starting the | ||
| 352 | * transaction, because we cannot make the call while we're | ||
| 353 | * in a transaction. | ||
| 354 | */ | ||
| 355 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
| 356 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, (xfs_fsize_t)0); | ||
| 357 | if (error) { | ||
| 358 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
| 359 | return error; | ||
| 360 | } | ||
| 361 | |||
| 362 | tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE); | ||
| 363 | if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, | ||
| 364 | XFS_TRANS_PERM_LOG_RES, | ||
| 365 | XFS_ITRUNCATE_LOG_COUNT))) { | ||
| 366 | xfs_trans_cancel(tp, 0); | ||
| 367 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
| 368 | return error; | ||
| 369 | } | ||
| 370 | |||
| 371 | /* | ||
| 372 | * Follow the normal truncate locking protocol. Since we | ||
| 373 | * hold the inode in the transaction, we know that its number | ||
| 374 | * of references will stay constant. | ||
| 375 | */ | ||
| 376 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 377 | xfs_trans_ijoin(tp, ip); | ||
| 378 | |||
| 379 | /* | ||
| 380 | * Signal a sync xaction. The only case where that isn't | ||
| 381 | * the case is if we're truncating an already unlinked file | ||
| 382 | * on a wsync fs. In that case, we know the blocks can't | ||
| 383 | * reappear in the file because the links to file are | ||
| 384 | * permanently toast. Currently, we're always going to | ||
| 385 | * want a sync transaction because this code is being | ||
| 386 | * called from places where nlink is guaranteed to be 1 | ||
| 387 | * but I'm leaving the tests in to protect against future | ||
| 388 | * changes -- rcc. | ||
| 389 | */ | ||
| 390 | error = xfs_itruncate_finish(&tp, ip, (xfs_fsize_t)0, | ||
| 391 | XFS_DATA_FORK, | ||
| 392 | ((ip->i_d.di_nlink != 0 || | ||
| 393 | !(mp->m_flags & XFS_MOUNT_WSYNC)) | ||
| 394 | ? 1 : 0)); | ||
| 395 | if (error) { | ||
| 396 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | | ||
| 397 | XFS_TRANS_ABORT); | ||
| 398 | } else { | ||
| 399 | xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
| 400 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
| 401 | } | ||
| 402 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
| 403 | |||
| 404 | return error; | ||
| 405 | } | ||
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index ef321225d269..f55b9678264f 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #ifndef __XFS_UTILS_H__ | 18 | #ifndef __XFS_UTILS_H__ |
| 19 | #define __XFS_UTILS_H__ | 19 | #define __XFS_UTILS_H__ |
| 20 | 20 | ||
| 21 | extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *); | ||
| 22 | extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, | 21 | extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, |
| 23 | xfs_dev_t, cred_t *, prid_t, int, | 22 | xfs_dev_t, cred_t *, prid_t, int, |
| 24 | xfs_inode_t **, int *); | 23 | xfs_inode_t **, int *); |
