diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/swapfile.c | 64 |
1 files changed, 39 insertions, 25 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c index 14590775212d..fc687b234eb5 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1889,6 +1889,43 @@ static struct swap_info_struct *alloc_swap_info(void) return p; } +static int claim_swapfile(struct swap_info_struct *p, struct inode *inode) +{ + int error; + + if (S_ISBLK(inode->i_mode)) { + p->bdev = bdgrab(I_BDEV(inode)); + error = blkdev_get(p->bdev, + FMODE_READ | FMODE_WRITE | FMODE_EXCL, + sys_swapon); + if (error < 0) { + p->bdev = NULL; + error = -EINVAL; + goto bad_swap; + } + p->old_block_size = block_size(p->bdev); + error = set_blocksize(p->bdev, PAGE_SIZE); + if (error < 0) + goto bad_swap; + p->flags |= SWP_BLKDEV; + } else if (S_ISREG(inode->i_mode)) { + p->bdev = inode->i_sb->s_bdev; + mutex_lock(&inode->i_mutex); + if (IS_SWAPFILE(inode)) { + error = -EBUSY; + goto bad_swap; + } + } else { + error = -EINVAL; + goto bad_swap; + } + + return 0; + +bad_swap: + return error; +} + SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) { struct swap_info_struct *p; @@ -1942,32 +1979,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) } } - if (S_ISBLK(inode->i_mode)) { - p->bdev = bdgrab(I_BDEV(inode)); - error = blkdev_get(p->bdev, - FMODE_READ | FMODE_WRITE | FMODE_EXCL, - sys_swapon); - if (error < 0) { - p->bdev = NULL; - error = -EINVAL; - goto bad_swap; - } - p->old_block_size = block_size(p->bdev); - error = set_blocksize(p->bdev, PAGE_SIZE); - if (error < 0) - goto bad_swap; - p->flags |= SWP_BLKDEV; - } else if (S_ISREG(inode->i_mode)) { - p->bdev = inode->i_sb->s_bdev; - mutex_lock(&inode->i_mutex); - if (IS_SWAPFILE(inode)) { - error = -EBUSY; - goto bad_swap; - } - } else { - error = -EINVAL; + error = claim_swapfile(p, inode); + if (unlikely(error)) goto bad_swap; - } swapfilepages = i_size_read(inode) >> PAGE_SHIFT; |