Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
11493c87
Commit
11493c87
authored
Apr 17, 2003
by
Andries E. Brouwer
Committed by
David S. Miller
Apr 17, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SPARC64]: Remove LVM ioctls.
parent
d475dd45
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
478 deletions
+0
-478
arch/sparc64/kernel/ioctl32.c
arch/sparc64/kernel/ioctl32.c
+0
-478
No files found.
arch/sparc64/kernel/ioctl32.c
View file @
11493c87
...
...
@@ -54,9 +54,6 @@
#include <linux/elevator.h>
#include <linux/rtc.h>
#include <linux/pci.h>
#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
#include <linux/lvm.h>
#endif
/* LVM */
#include <linux/dm-ioctl.h>
#include <scsi/scsi.h>
...
...
@@ -2766,443 +2763,6 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
return
-
EINVAL
;
}
#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
/* Ugh, LVM. Pitty it was not cleaned up before accepted :((. */
typedef
struct
{
uint8_t
vg_name
[
NAME_LEN
];
uint32_t
vg_number
;
uint32_t
vg_access
;
uint32_t
vg_status
;
uint32_t
lv_max
;
uint32_t
lv_cur
;
uint32_t
lv_open
;
uint32_t
pv_max
;
uint32_t
pv_cur
;
uint32_t
pv_act
;
uint32_t
dummy
;
uint32_t
vgda
;
uint32_t
pe_size
;
uint32_t
pe_total
;
uint32_t
pe_allocated
;
uint32_t
pvg_total
;
u32
proc
;
u32
pv
[
ABS_MAX_PV
+
1
];
u32
lv
[
ABS_MAX_LV
+
1
];
uint8_t
vg_uuid
[
UUID_LEN
+
1
];
/* volume group UUID */
uint8_t
dummy1
[
200
];
}
vg32_t
;
typedef
struct
{
uint8_t
id
[
2
];
uint16_t
version
;
lvm_disk_data_t
pv_on_disk
;
lvm_disk_data_t
vg_on_disk
;
lvm_disk_data_t
pv_namelist_on_disk
;
lvm_disk_data_t
lv_on_disk
;
lvm_disk_data_t
pe_on_disk
;
uint8_t
pv_name
[
NAME_LEN
];
uint8_t
vg_name
[
NAME_LEN
];
uint8_t
system_id
[
NAME_LEN
];
kdev_t
pv_dev
;
uint32_t
pv_number
;
uint32_t
pv_status
;
uint32_t
pv_allocatable
;
uint32_t
pv_size
;
uint32_t
lv_cur
;
uint32_t
pe_size
;
uint32_t
pe_total
;
uint32_t
pe_allocated
;
uint32_t
pe_stale
;
u32
pe
;
u32
inode
;
uint8_t
pv_uuid
[
UUID_LEN
+
1
];
}
pv32_t
;
typedef
struct
{
char
lv_name
[
NAME_LEN
];
u32
lv
;
}
lv_req32_t
;
typedef
struct
{
u32
lv_index
;
u32
lv
;
/* Transfer size because user space and kernel space differ */
uint16_t
size
;
}
lv_status_byindex_req32_t
;
typedef
struct
{
compat_dev_t
dev
;
u32
lv
;
}
lv_status_bydev_req32_t
;
typedef
struct
{
uint8_t
lv_name
[
NAME_LEN
];
kdev_t
old_dev
;
kdev_t
new_dev
;
u32
old_pe
;
u32
new_pe
;
}
le_remap_req32_t
;
typedef
struct
{
char
pv_name
[
NAME_LEN
];
u32
pv
;
}
pv_status_req32_t
;
typedef
struct
{
uint8_t
lv_name
[
NAME_LEN
];
uint8_t
vg_name
[
NAME_LEN
];
uint32_t
lv_access
;
uint32_t
lv_status
;
uint32_t
lv_open
;
kdev_t
lv_dev
;
uint32_t
lv_number
;
uint32_t
lv_mirror_copies
;
uint32_t
lv_recovery
;
uint32_t
lv_schedule
;
uint32_t
lv_size
;
u32
lv_current_pe
;
uint32_t
lv_current_le
;
uint32_t
lv_allocated_le
;
uint32_t
lv_stripes
;
uint32_t
lv_stripesize
;
uint32_t
lv_badblock
;
uint32_t
lv_allocation
;
uint32_t
lv_io_timeout
;
uint32_t
lv_read_ahead
;
/* delta to version 1 starts here */
u32
lv_snapshot_org
;
u32
lv_snapshot_prev
;
u32
lv_snapshot_next
;
u32
lv_block_exception
;
uint32_t
lv_remap_ptr
;
uint32_t
lv_remap_end
;
uint32_t
lv_chunk_size
;
uint32_t
lv_snapshot_minor
;
char
dummy
[
200
];
}
lv32_t
;
typedef
struct
{
u32
hash
[
2
];
u32
rsector_org
;
kdev_t
rdev_org
;
u32
rsector_new
;
kdev_t
rdev_new
;
}
lv_block_exception32_t
;
static
void
put_lv_t
(
lv_t
*
l
)
{
if
(
l
->
lv_current_pe
)
vfree
(
l
->
lv_current_pe
);
if
(
l
->
lv_block_exception
)
vfree
(
l
->
lv_block_exception
);
kfree
(
l
);
}
static
lv_t
*
get_lv_t
(
u32
p
,
int
*
errp
)
{
int
err
,
i
;
u32
ptr1
,
ptr2
;
size_t
size
;
lv_block_exception32_t
__user
*
lbe32
;
lv_block_exception_t
*
lbe
;
lv32_t
__user
*
ul
=
A
(
p
);
lv_t
*
l
=
(
lv_t
*
)
kmalloc
(
sizeof
(
lv_t
),
GFP_KERNEL
);
if
(
!
l
)
{
*
errp
=
-
ENOMEM
;
return
NULL
;
}
memset
(
l
,
0
,
sizeof
(
lv_t
));
err
=
copy_from_user
(
l
,
ul
,
(
long
)
&
((
lv32_t
*
)
0
)
->
lv_current_pe
);
err
|=
__copy_from_user
(
&
l
->
lv_current_le
,
&
ul
->
lv_current_le
,
((
long
)
&
ul
->
lv_snapshot_org
)
-
((
long
)
&
ul
->
lv_current_le
));
err
|=
__copy_from_user
(
&
l
->
lv_remap_ptr
,
&
ul
->
lv_remap_ptr
,
((
long
)
&
ul
->
dummy
[
0
])
-
((
long
)
&
ul
->
lv_remap_ptr
));
err
|=
__get_user
(
ptr1
,
&
ul
->
lv_current_pe
);
err
|=
__get_user
(
ptr2
,
&
ul
->
lv_block_exception
);
if
(
err
)
{
kfree
(
l
);
*
errp
=
-
EFAULT
;
return
NULL
;
}
if
(
ptr1
)
{
size
=
l
->
lv_allocated_le
*
sizeof
(
pe_t
);
l
->
lv_current_pe
=
vmalloc
(
size
);
if
(
l
->
lv_current_pe
)
err
=
copy_from_user
(
l
->
lv_current_pe
,
A
(
ptr1
),
size
);
}
if
(
!
err
&&
ptr2
)
{
size
=
l
->
lv_remap_end
*
sizeof
(
lv_block_exception_t
);
l
->
lv_block_exception
=
lbe
=
vmalloc
(
size
);
if
(
l
->
lv_block_exception
)
{
lbe32
=
A
(
ptr2
);
memset
(
lbe
,
0
,
size
);
for
(
i
=
0
;
i
<
l
->
lv_remap_end
;
i
++
,
lbe
++
,
lbe32
++
)
{
err
|=
get_user
(
lbe
->
rsector_org
,
&
lbe32
->
rsector_org
);
err
|=
__get_user
(
lbe
->
rdev_org
,
&
lbe32
->
rdev_org
);
err
|=
__get_user
(
lbe
->
rsector_new
,
&
lbe32
->
rsector_new
);
err
|=
__get_user
(
lbe
->
rdev_new
,
&
lbe32
->
rdev_new
);
}
}
}
if
(
err
||
(
ptr1
&&
!
l
->
lv_current_pe
)
||
(
ptr2
&&
!
l
->
lv_block_exception
))
{
if
(
!
err
)
*
errp
=
-
ENOMEM
;
else
*
errp
=
-
EFAULT
;
put_lv_t
(
l
);
return
NULL
;
}
return
l
;
}
static
int
copy_lv_t
(
u32
ptr
,
lv_t
*
l
)
{
int
err
;
lv32_t
__user
*
ul
=
A
(
ptr
);
u32
ptr1
;
size_t
size
;
err
=
get_user
(
ptr1
,
&
ul
->
lv_current_pe
);
if
(
err
)
return
-
EFAULT
;
err
=
copy_to_user
(
ul
,
l
,
(
long
)
&
((
lv32_t
*
)
0
)
->
lv_current_pe
);
err
|=
__copy_to_user
(
&
ul
->
lv_current_le
,
&
l
->
lv_current_le
,
((
long
)
&
ul
->
lv_snapshot_org
)
-
((
long
)
&
ul
->
lv_current_le
));
err
|=
__copy_to_user
(
&
ul
->
lv_remap_ptr
,
&
l
->
lv_remap_ptr
,
((
long
)
&
ul
->
dummy
[
0
])
-
((
long
)
&
ul
->
lv_remap_ptr
));
size
=
l
->
lv_allocated_le
*
sizeof
(
pe_t
);
if
(
ptr1
)
err
|=
__copy_to_user
(
A
(
ptr1
),
l
->
lv_current_pe
,
size
);
return
err
?
-
EFAULT
:
0
;
}
static
int
do_lvm_ioctl
(
unsigned
int
fd
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
vg_t
*
v
=
NULL
;
union
{
lv_req_t
lv_req
;
le_remap_req_t
le_remap
;
lv_status_byindex_req_t
lv_byindex
;
lv_status_bydev_req_t
lv_bydev
;
pv_status_req_t
pv_status
;
}
u
;
pv_t
p
;
int
err
;
u32
ptr
=
0
;
int
i
;
mm_segment_t
old_fs
;
void
*
karg
=
&
u
;
switch
(
cmd
)
{
case
VG_STATUS
:
v
=
kmalloc
(
sizeof
(
vg_t
),
GFP_KERNEL
);
if
(
!
v
)
return
-
ENOMEM
;
karg
=
v
;
break
;
case
VG_CREATE_OLD
:
case
VG_CREATE
:
v
=
kmalloc
(
sizeof
(
vg_t
),
GFP_KERNEL
);
if
(
!
v
)
return
-
ENOMEM
;
if
(
copy_from_user
(
v
,
(
void
*
)
arg
,
(
long
)
&
((
vg32_t
*
)
0
)
->
proc
))
{
kfree
(
v
);
return
-
EFAULT
;
}
/* 'proc' field is unused, just NULL it out. */
v
->
proc
=
NULL
;
if
(
copy_from_user
(
v
->
vg_uuid
,
((
vg32_t
*
)
arg
)
->
vg_uuid
,
UUID_LEN
+
1
))
{
kfree
(
v
);
return
-
EFAULT
;
}
karg
=
v
;
memset
(
v
->
pv
,
0
,
sizeof
(
v
->
pv
)
+
sizeof
(
v
->
lv
));
if
(
v
->
pv_max
>
ABS_MAX_PV
||
v
->
lv_max
>
ABS_MAX_LV
)
return
-
EPERM
;
for
(
i
=
0
;
i
<
v
->
pv_max
;
i
++
)
{
err
=
__get_user
(
ptr
,
&
((
vg32_t
*
)
arg
)
->
pv
[
i
]);
if
(
err
)
break
;
if
(
ptr
)
{
v
->
pv
[
i
]
=
kmalloc
(
sizeof
(
pv_t
),
GFP_KERNEL
);
if
(
!
v
->
pv
[
i
])
{
err
=
-
ENOMEM
;
break
;
}
err
=
copy_from_user
(
v
->
pv
[
i
],
A
(
ptr
),
sizeof
(
pv32_t
)
-
8
-
UUID_LEN
+
1
);
if
(
err
)
{
err
=
-
EFAULT
;
break
;
}
err
=
copy_from_user
(
&
v
->
pv
[
i
]
->
pv_uuid
[
0
],
&
((
pv32_t
__user
*
)
A
(
ptr
))
->
pv_uuid
[
0
],
UUID_LEN
+
1
);
if
(
err
)
{
err
=
-
EFAULT
;
break
;
}
v
->
pv
[
i
]
->
pe
=
NULL
;
v
->
pv
[
i
]
->
bd
=
NULL
;
}
}
if
(
!
err
)
{
for
(
i
=
0
;
i
<
v
->
lv_max
;
i
++
)
{
err
=
__get_user
(
ptr
,
&
((
vg32_t
*
)
arg
)
->
lv
[
i
]);
if
(
err
)
break
;
if
(
ptr
)
{
v
->
lv
[
i
]
=
get_lv_t
(
ptr
,
&
err
);
if
(
err
)
break
;
}
}
}
break
;
case
LV_CREATE
:
case
LV_EXTEND
:
case
LV_REDUCE
:
case
LV_REMOVE
:
case
LV_RENAME
:
case
LV_STATUS_BYNAME
:
err
=
copy_from_user
(
&
u
.
pv_status
,
arg
,
sizeof
(
u
.
pv_status
.
pv_name
));
if
(
err
)
return
-
EFAULT
;
if
(
cmd
!=
LV_REMOVE
)
{
err
=
__get_user
(
ptr
,
&
((
lv_req32_t
*
)
arg
)
->
lv
);
if
(
err
)
return
err
;
u
.
lv_req
.
lv
=
get_lv_t
(
ptr
,
&
err
);
}
else
u
.
lv_req
.
lv
=
NULL
;
break
;
case
LV_STATUS_BYINDEX
:
err
=
get_user
(
u
.
lv_byindex
.
lv_index
,
&
((
lv_status_byindex_req32_t
*
)
arg
)
->
lv_index
);
err
|=
__get_user
(
ptr
,
&
((
lv_status_byindex_req32_t
*
)
arg
)
->
lv
);
if
(
err
)
return
err
;
u
.
lv_byindex
.
lv
=
get_lv_t
(
ptr
,
&
err
);
break
;
case
LV_STATUS_BYDEV
:
err
=
get_user
(
u
.
lv_bydev
.
dev
,
&
((
lv_status_bydev_req32_t
*
)
arg
)
->
dev
);
err
|=
__get_user
(
ptr
,
&
((
lv_status_bydev_req32_t
*
)
arg
)
->
lv
);
if
(
err
)
return
err
;
u
.
lv_bydev
.
lv
=
get_lv_t
(
ptr
,
&
err
);
break
;
case
VG_EXTEND
:
err
=
copy_from_user
(
&
p
,
(
void
*
)
arg
,
sizeof
(
pv32_t
)
-
8
-
UUID_LEN
+
1
);
if
(
err
)
return
-
EFAULT
;
err
=
copy_from_user
(
p
.
pv_uuid
,
((
pv32_t
*
)
arg
)
->
pv_uuid
,
UUID_LEN
+
1
);
if
(
err
)
return
-
EFAULT
;
p
.
pe
=
NULL
;
p
.
bd
=
NULL
;
karg
=
&
p
;
break
;
case
PV_CHANGE
:
case
PV_STATUS
:
err
=
copy_from_user
(
&
u
.
pv_status
,
arg
,
sizeof
(
u
.
lv_req
.
lv_name
));
if
(
err
)
return
-
EFAULT
;
err
=
__get_user
(
ptr
,
&
((
pv_status_req32_t
*
)
arg
)
->
pv
);
if
(
err
)
return
err
;
u
.
pv_status
.
pv
=
&
p
;
if
(
cmd
==
PV_CHANGE
)
{
err
=
copy_from_user
(
&
p
,
A
(
ptr
),
sizeof
(
pv32_t
)
-
8
-
UUID_LEN
+
1
);
if
(
err
)
return
-
EFAULT
;
p
.
pe
=
NULL
;
p
.
bd
=
NULL
;
}
break
;
};
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
err
=
sys_ioctl
(
fd
,
cmd
,
(
unsigned
long
)
karg
);
set_fs
(
old_fs
);
switch
(
cmd
)
{
case
VG_STATUS
:
if
(
!
err
)
{
if
(
copy_to_user
((
void
*
)
arg
,
v
,
(
long
)
&
((
vg32_t
*
)
0
)
->
proc
)
||
clear_user
(
&
((
vg32_t
*
)
arg
)
->
proc
,
sizeof
(
vg32_t
)
-
(
long
)
&
((
vg32_t
*
)
0
)
->
proc
))
err
=
-
EFAULT
;
}
if
(
copy_to_user
(((
vg32_t
*
)
arg
)
->
vg_uuid
,
v
->
vg_uuid
,
UUID_LEN
+
1
))
{
err
=
-
EFAULT
;
}
kfree
(
v
);
break
;
case
VG_CREATE_OLD
:
case
VG_CREATE
:
for
(
i
=
0
;
i
<
v
->
pv_max
;
i
++
)
{
if
(
v
->
pv
[
i
])
kfree
(
v
->
pv
[
i
]);
}
for
(
i
=
0
;
i
<
v
->
lv_max
;
i
++
)
{
if
(
v
->
lv
[
i
])
put_lv_t
(
v
->
lv
[
i
]);
}
kfree
(
v
);
break
;
case
LV_STATUS_BYNAME
:
if
(
!
err
&&
u
.
lv_req
.
lv
)
err
=
copy_lv_t
(
ptr
,
u
.
lv_req
.
lv
);
/* Fall through */
case
LV_CREATE
:
case
LV_EXTEND
:
case
LV_REDUCE
:
if
(
u
.
lv_req
.
lv
)
put_lv_t
(
u
.
lv_req
.
lv
);
break
;
case
LV_STATUS_BYINDEX
:
if
(
u
.
lv_byindex
.
lv
)
{
if
(
!
err
)
err
=
copy_lv_t
(
ptr
,
u
.
lv_byindex
.
lv
);
put_lv_t
(
u
.
lv_byindex
.
lv
);
}
break
;
case
LV_STATUS_BYDEV
:
if
(
u
.
lv_bydev
.
lv
)
{
if
(
!
err
)
err
=
copy_lv_t
(
ptr
,
u
.
lv_bydev
.
lv
);
put_lv_t
(
u
.
lv_byindex
.
lv
);
}
break
;
case
PV_STATUS
:
if
(
!
err
)
{
err
=
copy_to_user
(
A
(
ptr
),
&
p
,
sizeof
(
pv32_t
)
-
8
-
UUID_LEN
+
1
);
if
(
err
)
return
-
EFAULT
;
err
=
copy_to_user
(
&
((
pv_t
__user
*
)
A
(
ptr
))
->
pv_uuid
[
0
],
&
p
.
pv_uuid
[
0
],
UUID_LEN
+
1
);
if
(
err
)
return
-
EFAULT
;
}
break
;
};
return
err
;
}
#endif
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
/* This really belongs in include/linux/drm.h -DaveM */
#include "../../../drivers/char/drm/drm.h"
...
...
@@ -4887,28 +4447,6 @@ COMPATIBLE_IOCTL(ATMTCP_CREATE)
COMPATIBLE_IOCTL
(
ATMTCP_REMOVE
)
COMPATIBLE_IOCTL
(
ATMMPC_CTRL
)
COMPATIBLE_IOCTL
(
ATMMPC_DATA
)
#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
/* 0xfe - lvm */
COMPATIBLE_IOCTL
(
VG_SET_EXTENDABLE
)
COMPATIBLE_IOCTL
(
VG_STATUS_GET_COUNT
)
COMPATIBLE_IOCTL
(
VG_STATUS_GET_NAMELIST
)
COMPATIBLE_IOCTL
(
VG_REMOVE
)
COMPATIBLE_IOCTL
(
VG_RENAME
)
COMPATIBLE_IOCTL
(
VG_REDUCE
)
COMPATIBLE_IOCTL
(
PE_LOCK_UNLOCK
)
COMPATIBLE_IOCTL
(
PV_FLUSH
)
COMPATIBLE_IOCTL
(
LVM_LOCK_LVM
)
COMPATIBLE_IOCTL
(
LVM_GET_IOP_VERSION
)
#ifdef LVM_TOTAL_RESET
COMPATIBLE_IOCTL
(
LVM_RESET
)
#endif
COMPATIBLE_IOCTL
(
LV_SET_ACCESS
)
COMPATIBLE_IOCTL
(
LV_SET_STATUS
)
COMPATIBLE_IOCTL
(
LV_SET_ALLOCATION
)
COMPATIBLE_IOCTL
(
LE_REMAP
)
COMPATIBLE_IOCTL
(
LV_BMAP
)
COMPATIBLE_IOCTL
(
LV_SNAPSHOT_USE_RATE
)
#endif
/* LVM */
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
COMPATIBLE_IOCTL
(
DRM_IOCTL_GET_MAGIC
)
COMPATIBLE_IOCTL
(
DRM_IOCTL_IRQ_BUSID
)
...
...
@@ -5172,22 +4710,6 @@ HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
HANDLE_IOCTL
(
SONET_SETFRAMING
,
do_atm_ioctl
)
HANDLE_IOCTL
(
SONET_GETFRAMING
,
do_atm_ioctl
)
HANDLE_IOCTL
(
SONET_GETFRSENSE
,
do_atm_ioctl
)
#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
HANDLE_IOCTL
(
VG_STATUS
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
VG_CREATE_OLD
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
VG_CREATE
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
VG_EXTEND
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_CREATE
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_REMOVE
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_EXTEND
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_REDUCE
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_RENAME
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_STATUS_BYNAME
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_STATUS_BYINDEX
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
LV_STATUS_BYDEV
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
PV_CHANGE
,
do_lvm_ioctl
)
HANDLE_IOCTL
(
PV_STATUS
,
do_lvm_ioctl
)
#endif
/* LVM */
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
HANDLE_IOCTL
(
DRM32_IOCTL_VERSION
,
drm32_version
)
HANDLE_IOCTL
(
DRM32_IOCTL_GET_UNIQUE
,
drm32_getsetunique
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment