Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/kernel_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: blktests-ci

on:
pull_request:

jobs:
build-kernel:
runs-on: ubuntu-latest
steps:
- name: Configure git
run: |
git config --global --add safe.directory '*'
- name: Checkout git
run: |
sudo apt-get install -y libelf-dev
mkdir -p linux
cd linux
git init
git remote add origin https://github.com/${{ github.repository }}
git fetch origin --depth=5 ${{ github.event.pull_request.head.sha }}
git reset --hard ${{ github.event.pull_request.head.sha }}
git log -1
- name: Build kernel
run: |
cd linux
make defconfig
make -j 8

61 changes: 61 additions & 0 deletions block/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,63 @@ static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode,
return ops->pr_clear(bdev, c.key);
}

static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
struct pr_keys __user *arg)
{
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_keys k_in, *k_out;
size_t k_len;
int ret, num_keys;

if (!blkdev_pr_allowed(bdev, mode))
return -EPERM;
if (!ops || !ops->pr_read_keys)
return -EOPNOTSUPP;

if (copy_from_user(&k_in, arg, sizeof(k_in)))
return -EFAULT;

num_keys = k_in.num_keys;
k_out = kzalloc(sizeof(struct pr_keys) + num_keys * sizeof(u64),
GFP_KERNEL);
if (!k_out)
return -ENOMEM;

k_out->num_keys = num_keys;
ret = ops->pr_read_keys(bdev, k_out);
if (ret) {
kfree(k_out);
return ret;
}

k_len = sizeof(k_in) + num_keys * sizeof(u64);
if (copy_to_user(arg, k_out, k_len))
ret = -EFAULT;

kfree(k_out);
return ret;
}

static int blkdev_pr_read_reservation(struct block_device *bdev,
blk_mode_t mode, struct pr_held_reservation __user *arg)
{
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_held_reservation r;
int ret;

if (!blkdev_pr_allowed(bdev, mode))
return -EPERM;
if (!ops || !ops->pr_read_reservation)
return -EOPNOTSUPP;

ret = ops->pr_read_reservation(bdev, &r);
if (ret)
return ret;
if (copy_to_user(arg, &r, sizeof(r)))
return -EFAULT;
return 0;
}

static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd,
unsigned long arg)
{
Expand Down Expand Up @@ -643,6 +700,10 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
return blkdev_pr_preempt(bdev, mode, argp, true);
case IOC_PR_CLEAR:
return blkdev_pr_clear(bdev, mode, argp);
case IOC_PR_READ_KEYS:
return blkdev_pr_read_keys(bdev, mode, argp);
case IOC_PR_READ_RESV:
return blkdev_pr_read_reservation(bdev, mode, argp);
default:
return -ENOIOCTLCMD;
}
Expand Down
10 changes: 7 additions & 3 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2008,9 +2008,13 @@ static int sd_pr_read_reservation(struct block_device *bdev,
if (result)
return result;

rsv->generation = get_unaligned_be32(&data[0]);
rsv->type = 0;
len = get_unaligned_be32(&data[4]);
if (!len)
if (!len) {
rsv->key = 0;
return 0;
}

/* Make sure we have at least the key and type */
if (len < 14) {
Expand All @@ -2020,9 +2024,9 @@ static int sd_pr_read_reservation(struct block_device *bdev,
return -EINVAL;
}

rsv->generation = get_unaligned_be32(&data[0]);
rsv->key = get_unaligned_be64(&data[8]);
rsv->type = scsi_pr_type_to_block(data[21] & 0x0f);
if (len == 16)
rsv->type = scsi_pr_type_to_block(data[21] & 0x0f);
return 0;
}

Expand Down
12 changes: 0 additions & 12 deletions include/linux/pr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@

#include <uapi/linux/pr.h>

struct pr_keys {
u32 generation;
u32 num_keys;
u64 keys[];
};

struct pr_held_reservation {
u64 key;
u32 generation;
enum pr_type type;
};

struct pr_ops {
int (*pr_register)(struct block_device *bdev, u64 old_key, u64 new_key,
u32 flags);
Expand Down
14 changes: 14 additions & 0 deletions include/uapi/linux/pr.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ struct pr_clear {
__u32 __pad;
};

struct pr_keys {
__u32 generation;
__u32 num_keys;
__u64 keys[];
};

struct pr_held_reservation {
__u64 key;
__u32 generation;
__u32 type;
};

#define PR_FL_IGNORE_KEY (1 << 0) /* ignore existing key */

#define IOC_PR_REGISTER _IOW('p', 200, struct pr_registration)
Expand All @@ -64,5 +76,7 @@ struct pr_clear {
#define IOC_PR_PREEMPT _IOW('p', 203, struct pr_preempt)
#define IOC_PR_PREEMPT_ABORT _IOW('p', 204, struct pr_preempt)
#define IOC_PR_CLEAR _IOW('p', 205, struct pr_clear)
#define IOC_PR_READ_KEYS _IOWR('p', 206, struct pr_keys)
#define IOC_PR_READ_RESV _IOWR('p', 207, struct pr_held_reservation)

#endif /* _UAPI_PR_H */