Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
1b186d25
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
1b186d25
编写于
3月 07, 2016
作者:
D
Dave Chinner
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'xfs-get-next-dquot-4.6' into for-next
上级
c53473be
be607946
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
394 addition
and
86 deletion
+394
-86
fs/quota/quota.c
fs/quota/quota.c
+64
-2
fs/xfs/libxfs/xfs_quota_defs.h
fs/xfs/libxfs/xfs_quota_defs.h
+2
-1
fs/xfs/xfs_dquot.c
fs/xfs/xfs_dquot.c
+114
-15
fs/xfs/xfs_file.c
fs/xfs/xfs_file.c
+57
-25
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode.h
+2
-0
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm.c
+43
-12
fs/xfs/xfs_qm.h
fs/xfs/xfs_qm.h
+35
-13
fs/xfs/xfs_qm_syscalls.c
fs/xfs/xfs_qm_syscalls.c
+17
-10
fs/xfs/xfs_quotaops.c
fs/xfs/xfs_quotaops.c
+34
-2
fs/xfs/xfs_trans_dquot.c
fs/xfs/xfs_trans_dquot.c
+9
-6
include/linux/quota.h
include/linux/quota.h
+2
-0
include/uapi/linux/dqblk_xfs.h
include/uapi/linux/dqblk_xfs.h
+1
-0
include/uapi/linux/quota.h
include/uapi/linux/quota.h
+14
-0
未找到文件。
fs/quota/quota.c
浏览文件 @
1b186d25
...
...
@@ -79,7 +79,7 @@ unsigned int qtype_enforce_flag(int type)
return
0
;
}
static
int
quota_quotaon
(
struct
super_block
*
sb
,
int
type
,
int
cmd
,
qid_t
id
,
static
int
quota_quotaon
(
struct
super_block
*
sb
,
int
type
,
qid_t
id
,
struct
path
*
path
)
{
if
(
!
sb
->
s_qcop
->
quota_on
&&
!
sb
->
s_qcop
->
quota_enable
)
...
...
@@ -222,6 +222,34 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
return
0
;
}
/*
* Return quota for next active quota >= this id, if any exists,
* otherwise return -ESRCH via ->get_nextdqblk
*/
static
int
quota_getnextquota
(
struct
super_block
*
sb
,
int
type
,
qid_t
id
,
void
__user
*
addr
)
{
struct
kqid
qid
;
struct
qc_dqblk
fdq
;
struct
if_nextdqblk
idq
;
int
ret
;
if
(
!
sb
->
s_qcop
->
get_nextdqblk
)
return
-
ENOSYS
;
qid
=
make_kqid
(
current_user_ns
(),
type
,
id
);
if
(
!
qid_valid
(
qid
))
return
-
EINVAL
;
ret
=
sb
->
s_qcop
->
get_nextdqblk
(
sb
,
&
qid
,
&
fdq
);
if
(
ret
)
return
ret
;
/* struct if_nextdqblk is a superset of struct if_dqblk */
copy_to_if_dqblk
((
struct
if_dqblk
*
)
&
idq
,
&
fdq
);
idq
.
dqb_id
=
from_kqid
(
current_user_ns
(),
qid
);
if
(
copy_to_user
(
addr
,
&
idq
,
sizeof
(
idq
)))
return
-
EFAULT
;
return
0
;
}
static
void
copy_from_if_dqblk
(
struct
qc_dqblk
*
dst
,
struct
if_dqblk
*
src
)
{
dst
->
d_spc_hardlimit
=
qbtos
(
src
->
dqb_bhardlimit
);
...
...
@@ -625,6 +653,34 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id,
return
ret
;
}
/*
* Return quota for next active quota >= this id, if any exists,
* otherwise return -ESRCH via ->get_nextdqblk.
*/
static
int
quota_getnextxquota
(
struct
super_block
*
sb
,
int
type
,
qid_t
id
,
void
__user
*
addr
)
{
struct
fs_disk_quota
fdq
;
struct
qc_dqblk
qdq
;
struct
kqid
qid
;
qid_t
id_out
;
int
ret
;
if
(
!
sb
->
s_qcop
->
get_nextdqblk
)
return
-
ENOSYS
;
qid
=
make_kqid
(
current_user_ns
(),
type
,
id
);
if
(
!
qid_valid
(
qid
))
return
-
EINVAL
;
ret
=
sb
->
s_qcop
->
get_nextdqblk
(
sb
,
&
qid
,
&
qdq
);
if
(
ret
)
return
ret
;
id_out
=
from_kqid
(
current_user_ns
(),
qid
);
copy_to_xfs_dqblk
(
&
fdq
,
&
qdq
,
type
,
id_out
);
if
(
copy_to_user
(
addr
,
&
fdq
,
sizeof
(
fdq
)))
return
-
EFAULT
;
return
ret
;
}
static
int
quota_rmxquota
(
struct
super_block
*
sb
,
void
__user
*
addr
)
{
__u32
flags
;
...
...
@@ -659,7 +715,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
switch
(
cmd
)
{
case
Q_QUOTAON
:
return
quota_quotaon
(
sb
,
type
,
cmd
,
id
,
path
);
return
quota_quotaon
(
sb
,
type
,
id
,
path
);
case
Q_QUOTAOFF
:
return
quota_quotaoff
(
sb
,
type
);
case
Q_GETFMT
:
...
...
@@ -670,6 +726,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
return
quota_setinfo
(
sb
,
type
,
addr
);
case
Q_GETQUOTA
:
return
quota_getquota
(
sb
,
type
,
id
,
addr
);
case
Q_GETNEXTQUOTA
:
return
quota_getnextquota
(
sb
,
type
,
id
,
addr
);
case
Q_SETQUOTA
:
return
quota_setquota
(
sb
,
type
,
id
,
addr
);
case
Q_SYNC
:
...
...
@@ -690,6 +748,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
return
quota_setxquota
(
sb
,
type
,
id
,
addr
);
case
Q_XGETQUOTA
:
return
quota_getxquota
(
sb
,
type
,
id
,
addr
);
case
Q_XGETNEXTQUOTA
:
return
quota_getnextxquota
(
sb
,
type
,
id
,
addr
);
case
Q_XQUOTASYNC
:
if
(
sb
->
s_flags
&
MS_RDONLY
)
return
-
EROFS
;
...
...
@@ -708,10 +768,12 @@ static int quotactl_cmd_write(int cmd)
switch
(
cmd
)
{
case
Q_GETFMT
:
case
Q_GETINFO
:
case
Q_GETNEXTQUOTA
:
case
Q_SYNC
:
case
Q_XGETQSTAT
:
case
Q_XGETQSTATV
:
case
Q_XGETQUOTA
:
case
Q_XGETNEXTQUOTA
:
case
Q_XQUOTASYNC
:
return
0
;
}
...
...
fs/xfs/libxfs/xfs_quota_defs.h
浏览文件 @
1b186d25
...
...
@@ -37,7 +37,7 @@ typedef __uint16_t xfs_qwarncnt_t;
#define XFS_DQ_PROJ 0x0002
/* project quota */
#define XFS_DQ_GROUP 0x0004
/* a group quota */
#define XFS_DQ_DIRTY 0x0008
/* dquot is dirty */
#define XFS_DQ_FREEING 0x0010
/* dquot is be
e
ing torn down */
#define XFS_DQ_FREEING 0x0010
/* dquot is being torn down */
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
...
...
@@ -116,6 +116,7 @@ typedef __uint16_t xfs_qwarncnt_t;
#define XFS_QMOPT_DQREPAIR 0x0001000
/* repair dquot if damaged */
#define XFS_QMOPT_GQUOTA 0x0002000
/* group dquot requested */
#define XFS_QMOPT_ENOSPC 0x0004000
/* enospc instead of edquot (prj) */
#define XFS_QMOPT_DQNEXT 0x0008000
/* return next dquot >= this ID */
/*
* flags to xfs_trans_mod_dquot to indicate which field needs to be
...
...
fs/xfs/xfs_dquot.c
浏览文件 @
1b186d25
...
...
@@ -92,26 +92,28 @@ xfs_qm_adjust_dqlimits(
{
struct
xfs_quotainfo
*
q
=
mp
->
m_quotainfo
;
struct
xfs_disk_dquot
*
d
=
&
dq
->
q_core
;
struct
xfs_def_quota
*
defq
;
int
prealloc
=
0
;
ASSERT
(
d
->
d_id
);
defq
=
xfs_get_defquota
(
dq
,
q
);
if
(
q
->
qi_
bsoftlimit
&&
!
d
->
d_blk_softlimit
)
{
d
->
d_blk_softlimit
=
cpu_to_be64
(
q
->
qi_
bsoftlimit
);
if
(
defq
->
bsoftlimit
&&
!
d
->
d_blk_softlimit
)
{
d
->
d_blk_softlimit
=
cpu_to_be64
(
defq
->
bsoftlimit
);
prealloc
=
1
;
}
if
(
q
->
qi_
bhardlimit
&&
!
d
->
d_blk_hardlimit
)
{
d
->
d_blk_hardlimit
=
cpu_to_be64
(
q
->
qi_
bhardlimit
);
if
(
defq
->
bhardlimit
&&
!
d
->
d_blk_hardlimit
)
{
d
->
d_blk_hardlimit
=
cpu_to_be64
(
defq
->
bhardlimit
);
prealloc
=
1
;
}
if
(
q
->
qi_
isoftlimit
&&
!
d
->
d_ino_softlimit
)
d
->
d_ino_softlimit
=
cpu_to_be64
(
q
->
qi_
isoftlimit
);
if
(
q
->
qi_
ihardlimit
&&
!
d
->
d_ino_hardlimit
)
d
->
d_ino_hardlimit
=
cpu_to_be64
(
q
->
qi_
ihardlimit
);
if
(
q
->
qi_
rtbsoftlimit
&&
!
d
->
d_rtb_softlimit
)
d
->
d_rtb_softlimit
=
cpu_to_be64
(
q
->
qi_
rtbsoftlimit
);
if
(
q
->
qi_
rtbhardlimit
&&
!
d
->
d_rtb_hardlimit
)
d
->
d_rtb_hardlimit
=
cpu_to_be64
(
q
->
qi_
rtbhardlimit
);
if
(
defq
->
isoftlimit
&&
!
d
->
d_ino_softlimit
)
d
->
d_ino_softlimit
=
cpu_to_be64
(
defq
->
isoftlimit
);
if
(
defq
->
ihardlimit
&&
!
d
->
d_ino_hardlimit
)
d
->
d_ino_hardlimit
=
cpu_to_be64
(
defq
->
ihardlimit
);
if
(
defq
->
rtbsoftlimit
&&
!
d
->
d_rtb_softlimit
)
d
->
d_rtb_softlimit
=
cpu_to_be64
(
defq
->
rtbsoftlimit
);
if
(
defq
->
rtbhardlimit
&&
!
d
->
d_rtb_hardlimit
)
d
->
d_rtb_hardlimit
=
cpu_to_be64
(
defq
->
rtbhardlimit
);
if
(
prealloc
)
xfs_dquot_set_prealloc_limits
(
dq
);
...
...
@@ -232,7 +234,8 @@ xfs_qm_init_dquot_blk(
{
struct
xfs_quotainfo
*
q
=
mp
->
m_quotainfo
;
xfs_dqblk_t
*
d
;
int
curid
,
i
;
xfs_dqid_t
curid
;
int
i
;
ASSERT
(
tp
);
ASSERT
(
xfs_buf_islocked
(
bp
));
...
...
@@ -243,7 +246,6 @@ xfs_qm_init_dquot_blk(
* ID of the first dquot in the block - id's are zero based.
*/
curid
=
id
-
(
id
%
q
->
qi_dqperchunk
);
ASSERT
(
curid
>=
0
);
memset
(
d
,
0
,
BBTOB
(
q
->
qi_dqchunklen
));
for
(
i
=
0
;
i
<
q
->
qi_dqperchunk
;
i
++
,
d
++
,
curid
++
)
{
d
->
dd_diskdq
.
d_magic
=
cpu_to_be16
(
XFS_DQUOT_MAGIC
);
...
...
@@ -464,12 +466,13 @@ xfs_qm_dqtobp(
struct
xfs_bmbt_irec
map
;
int
nmaps
=
1
,
error
;
struct
xfs_buf
*
bp
;
struct
xfs_inode
*
quotip
=
xfs_dq_to_quota_inode
(
dqp
)
;
struct
xfs_inode
*
quotip
;
struct
xfs_mount
*
mp
=
dqp
->
q_mount
;
xfs_dqid_t
id
=
be32_to_cpu
(
dqp
->
q_core
.
d_id
);
struct
xfs_trans
*
tp
=
(
tpp
?
*
tpp
:
NULL
);
uint
lock_mode
;
quotip
=
xfs_quota_inode
(
dqp
->
q_mount
,
dqp
->
dq_flags
);
dqp
->
q_fileoffset
=
(
xfs_fileoff_t
)
id
/
mp
->
m_quotainfo
->
qi_dqperchunk
;
lock_mode
=
xfs_ilock_data_map_shared
(
quotip
);
...
...
@@ -684,6 +687,56 @@ xfs_qm_dqread(
return
error
;
}
/*
* Advance to the next id in the current chunk, or if at the
* end of the chunk, skip ahead to first id in next allocated chunk
* using the SEEK_DATA interface.
*/
int
xfs_dq_get_next_id
(
xfs_mount_t
*
mp
,
uint
type
,
xfs_dqid_t
*
id
,
loff_t
eof
)
{
struct
xfs_inode
*
quotip
;
xfs_fsblock_t
start
;
loff_t
offset
;
uint
lock
;
xfs_dqid_t
next_id
;
int
error
=
0
;
/* Simple advance */
next_id
=
*
id
+
1
;
/* If new ID is within the current chunk, advancing it sufficed */
if
(
next_id
%
mp
->
m_quotainfo
->
qi_dqperchunk
)
{
*
id
=
next_id
;
return
0
;
}
/* Nope, next_id is now past the current chunk, so find the next one */
start
=
(
xfs_fsblock_t
)
next_id
/
mp
->
m_quotainfo
->
qi_dqperchunk
;
quotip
=
xfs_quota_inode
(
mp
,
type
);
lock
=
xfs_ilock_data_map_shared
(
quotip
);
offset
=
__xfs_seek_hole_data
(
VFS_I
(
quotip
),
XFS_FSB_TO_B
(
mp
,
start
),
eof
,
SEEK_DATA
);
if
(
offset
<
0
)
error
=
offset
;
xfs_iunlock
(
quotip
,
lock
);
/* -ENXIO is essentially "no more data" */
if
(
error
)
return
(
error
==
-
ENXIO
?
-
ENOENT
:
error
);
/* Convert next data offset back to a quota id */
*
id
=
XFS_B_TO_FSB
(
mp
,
offset
)
*
mp
->
m_quotainfo
->
qi_dqperchunk
;
return
0
;
}
/*
* Given the file system, inode OR id, and type (UDQUOT/GDQUOT), return a
* a locked dquot, doing an allocation (if requested) as needed.
...
...
@@ -704,6 +757,7 @@ xfs_qm_dqget(
struct
xfs_quotainfo
*
qi
=
mp
->
m_quotainfo
;
struct
radix_tree_root
*
tree
=
xfs_dquot_tree
(
qi
,
type
);
struct
xfs_dquot
*
dqp
;
loff_t
eof
=
0
;
int
error
;
ASSERT
(
XFS_IS_QUOTA_RUNNING
(
mp
));
...
...
@@ -731,6 +785,21 @@ xfs_qm_dqget(
}
#endif
/* Get the end of the quota file if we need it */
if
(
flags
&
XFS_QMOPT_DQNEXT
)
{
struct
xfs_inode
*
quotip
;
xfs_fileoff_t
last
;
uint
lock_mode
;
quotip
=
xfs_quota_inode
(
mp
,
type
);
lock_mode
=
xfs_ilock_data_map_shared
(
quotip
);
error
=
xfs_bmap_last_offset
(
quotip
,
&
last
,
XFS_DATA_FORK
);
xfs_iunlock
(
quotip
,
lock_mode
);
if
(
error
)
return
error
;
eof
=
XFS_FSB_TO_B
(
mp
,
last
);
}
restart:
mutex_lock
(
&
qi
->
qi_tree_lock
);
dqp
=
radix_tree_lookup
(
tree
,
id
);
...
...
@@ -744,6 +813,18 @@ xfs_qm_dqget(
goto
restart
;
}
/* uninit / unused quota found in radix tree, keep looking */
if
(
flags
&
XFS_QMOPT_DQNEXT
)
{
if
(
XFS_IS_DQUOT_UNINITIALIZED
(
dqp
))
{
xfs_dqunlock
(
dqp
);
mutex_unlock
(
&
qi
->
qi_tree_lock
);
error
=
xfs_dq_get_next_id
(
mp
,
type
,
&
id
,
eof
);
if
(
error
)
return
error
;
goto
restart
;
}
}
dqp
->
q_nrefs
++
;
mutex_unlock
(
&
qi
->
qi_tree_lock
);
...
...
@@ -770,6 +851,13 @@ xfs_qm_dqget(
if
(
ip
)
xfs_ilock
(
ip
,
XFS_ILOCK_EXCL
);
/* If we are asked to find next active id, keep looking */
if
(
error
==
-
ENOENT
&&
(
flags
&
XFS_QMOPT_DQNEXT
))
{
error
=
xfs_dq_get_next_id
(
mp
,
type
,
&
id
,
eof
);
if
(
!
error
)
goto
restart
;
}
if
(
error
)
return
error
;
...
...
@@ -820,6 +908,17 @@ xfs_qm_dqget(
qi
->
qi_dquots
++
;
mutex_unlock
(
&
qi
->
qi_tree_lock
);
/* If we are asked to find next active id, keep looking */
if
(
flags
&
XFS_QMOPT_DQNEXT
)
{
if
(
XFS_IS_DQUOT_UNINITIALIZED
(
dqp
))
{
xfs_qm_dqput
(
dqp
);
error
=
xfs_dq_get_next_id
(
mp
,
type
,
&
id
,
eof
);
if
(
error
)
return
error
;
goto
restart
;
}
}
dqret:
ASSERT
((
ip
==
NULL
)
||
xfs_isilocked
(
ip
,
XFS_ILOCK_EXCL
));
trace_xfs_dqget_miss
(
dqp
);
...
...
fs/xfs/xfs_file.c
浏览文件 @
1b186d25
...
...
@@ -1337,31 +1337,31 @@ xfs_find_get_desired_pgoff(
return
found
;
}
STATIC
loff_t
xfs_seek_hole_data
(
struct
file
*
file
,
/*
* caller must lock inode with xfs_ilock_data_map_shared,
* can we craft an appropriate ASSERT?
*
* end is because the VFS-level lseek interface is defined such that any
* offset past i_size shall return -ENXIO, but we use this for quota code
* which does not maintain i_size, and we want to SEEK_DATA past i_size.
*/
loff_t
__xfs_seek_hole_data
(
struct
inode
*
inode
,
loff_t
start
,
loff_t
end
,
int
whence
)
{
struct
inode
*
inode
=
file
->
f_mapping
->
host
;
struct
xfs_inode
*
ip
=
XFS_I
(
inode
);
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
loff_t
uninitialized_var
(
offset
);
xfs_fsize_t
isize
;
xfs_fileoff_t
fsbno
;
xfs_filblks_t
end
;
uint
lock
;
xfs_filblks_t
lastbno
;
int
error
;
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
lock
=
xfs_ilock_data_map_shared
(
ip
);
isize
=
i_size_read
(
inode
);
if
(
start
>=
isize
)
{
if
(
start
>=
end
)
{
error
=
-
ENXIO
;
goto
out_
unlock
;
goto
out_
error
;
}
/*
...
...
@@ -1369,22 +1369,22 @@ xfs_seek_hole_data(
* by fsbno to the end block of the file.
*/
fsbno
=
XFS_B_TO_FSBT
(
mp
,
start
);
end
=
XFS_B_TO_FSB
(
mp
,
isize
);
lastbno
=
XFS_B_TO_FSB
(
mp
,
end
);
for
(;;)
{
struct
xfs_bmbt_irec
map
[
2
];
int
nmap
=
2
;
unsigned
int
i
;
error
=
xfs_bmapi_read
(
ip
,
fsbno
,
end
-
fsbno
,
map
,
&
nmap
,
error
=
xfs_bmapi_read
(
ip
,
fsbno
,
lastbno
-
fsbno
,
map
,
&
nmap
,
XFS_BMAPI_ENTIRE
);
if
(
error
)
goto
out_
unlock
;
goto
out_
error
;
/* No extents at given offset, must be beyond EOF */
if
(
nmap
==
0
)
{
error
=
-
ENXIO
;
goto
out_
unlock
;
goto
out_
error
;
}
for
(
i
=
0
;
i
<
nmap
;
i
++
)
{
...
...
@@ -1426,7 +1426,7 @@ xfs_seek_hole_data(
* hole at the end of any file).
*/
if
(
whence
==
SEEK_HOLE
)
{
offset
=
isize
;
offset
=
end
;
break
;
}
/*
...
...
@@ -1434,7 +1434,7 @@ xfs_seek_hole_data(
*/
ASSERT
(
whence
==
SEEK_DATA
);
error
=
-
ENXIO
;
goto
out_
unlock
;
goto
out_
error
;
}
ASSERT
(
i
>
1
);
...
...
@@ -1445,14 +1445,14 @@ xfs_seek_hole_data(
*/
fsbno
=
map
[
i
-
1
].
br_startoff
+
map
[
i
-
1
].
br_blockcount
;
start
=
XFS_FSB_TO_B
(
mp
,
fsbno
);
if
(
start
>=
isize
)
{
if
(
start
>=
end
)
{
if
(
whence
==
SEEK_HOLE
)
{
offset
=
isize
;
offset
=
end
;
break
;
}
ASSERT
(
whence
==
SEEK_DATA
);
error
=
-
ENXIO
;
goto
out_
unlock
;
goto
out_
error
;
}
}
...
...
@@ -1464,7 +1464,39 @@ xfs_seek_hole_data(
* situation in particular.
*/
if
(
whence
==
SEEK_HOLE
)
offset
=
min_t
(
loff_t
,
offset
,
isize
);
offset
=
min_t
(
loff_t
,
offset
,
end
);
return
offset
;
out_error:
return
error
;
}
STATIC
loff_t
xfs_seek_hole_data
(
struct
file
*
file
,
loff_t
start
,
int
whence
)
{
struct
inode
*
inode
=
file
->
f_mapping
->
host
;
struct
xfs_inode
*
ip
=
XFS_I
(
inode
);
struct
xfs_mount
*
mp
=
ip
->
i_mount
;
uint
lock
;
loff_t
offset
,
end
;
int
error
=
0
;
if
(
XFS_FORCED_SHUTDOWN
(
mp
))
return
-
EIO
;
lock
=
xfs_ilock_data_map_shared
(
ip
);
end
=
i_size_read
(
inode
);
offset
=
__xfs_seek_hole_data
(
inode
,
start
,
end
,
whence
);
if
(
offset
<
0
)
{
error
=
offset
;
goto
out_unlock
;
}
offset
=
vfs_setpos
(
file
,
offset
,
inode
->
i_sb
->
s_maxbytes
);
out_unlock:
...
...
fs/xfs/xfs_inode.h
浏览文件 @
1b186d25
...
...
@@ -437,6 +437,8 @@ int xfs_update_prealloc_flags(struct xfs_inode *ip,
int
xfs_zero_eof
(
struct
xfs_inode
*
ip
,
xfs_off_t
offset
,
xfs_fsize_t
isize
,
bool
*
did_zeroing
);
int
xfs_iozero
(
struct
xfs_inode
*
ip
,
loff_t
pos
,
size_t
count
);
loff_t
__xfs_seek_hole_data
(
struct
inode
*
inode
,
loff_t
start
,
loff_t
eof
,
int
whence
);
/* from xfs_iops.c */
...
...
fs/xfs/xfs_qm.c
浏览文件 @
1b186d25
...
...
@@ -560,6 +560,37 @@ xfs_qm_shrink_count(
return
list_lru_shrink_count
(
&
qi
->
qi_lru
,
sc
);
}
STATIC
void
xfs_qm_set_defquota
(
xfs_mount_t
*
mp
,
uint
type
,
xfs_quotainfo_t
*
qinf
)
{
xfs_dquot_t
*
dqp
;
struct
xfs_def_quota
*
defq
;
int
error
;
error
=
xfs_qm_dqread
(
mp
,
0
,
type
,
XFS_QMOPT_DOWARN
,
&
dqp
);
if
(
!
error
)
{
xfs_disk_dquot_t
*
ddqp
=
&
dqp
->
q_core
;
defq
=
xfs_get_defquota
(
dqp
,
qinf
);
/*
* Timers and warnings have been already set, let's just set the
* default limits for this quota type
*/
defq
->
bhardlimit
=
be64_to_cpu
(
ddqp
->
d_blk_hardlimit
);
defq
->
bsoftlimit
=
be64_to_cpu
(
ddqp
->
d_blk_softlimit
);
defq
->
ihardlimit
=
be64_to_cpu
(
ddqp
->
d_ino_hardlimit
);
defq
->
isoftlimit
=
be64_to_cpu
(
ddqp
->
d_ino_softlimit
);
defq
->
rtbhardlimit
=
be64_to_cpu
(
ddqp
->
d_rtb_hardlimit
);
defq
->
rtbsoftlimit
=
be64_to_cpu
(
ddqp
->
d_rtb_softlimit
);
xfs_qm_dqdestroy
(
dqp
);
}
}
/*
* This initializes all the quota information that's kept in the
* mount structure
...
...
@@ -606,19 +637,19 @@ xfs_qm_init_quotainfo(
* We try to get the limits from the superuser's limits fields.
* This is quite hacky, but it is standard quota practice.
*
* We look at the USR dquot with id == 0 first, but if user quotas
* are not enabled we goto the GRP dquot with id == 0.
* We don't really care to keep separate default limits for user
* and group quotas, at least not at this point.
*
* Since we may not have done a quotacheck by this point, just read
* the dquot without attaching it to any hashtables or lists.
*
* Timers and warnings are globally set by the first timer found in
* user/group/proj quota types, otherwise a default value is used.
* This should be split into different fields per quota type.
*/
error
=
xfs_qm_dqread
(
mp
,
0
,
XFS_IS_UQUOTA_RUNNING
(
mp
)
?
XFS_DQ_USER
:
(
XFS_IS_GQUOTA_RUNNING
(
mp
)
?
XFS_DQ_GROUP
:
XFS_DQ_PROJ
),
XFS_QMOPT_DOWARN
,
&
dqp
);
if
(
!
error
)
{
xfs_disk_dquot_t
*
ddqp
=
&
dqp
->
q_core
;
...
...
@@ -639,13 +670,6 @@ xfs_qm_init_quotainfo(
be16_to_cpu
(
ddqp
->
d_iwarns
)
:
XFS_QM_IWARNLIMIT
;
qinf
->
qi_rtbwarnlimit
=
ddqp
->
d_rtbwarns
?
be16_to_cpu
(
ddqp
->
d_rtbwarns
)
:
XFS_QM_RTBWARNLIMIT
;
qinf
->
qi_bhardlimit
=
be64_to_cpu
(
ddqp
->
d_blk_hardlimit
);
qinf
->
qi_bsoftlimit
=
be64_to_cpu
(
ddqp
->
d_blk_softlimit
);
qinf
->
qi_ihardlimit
=
be64_to_cpu
(
ddqp
->
d_ino_hardlimit
);
qinf
->
qi_isoftlimit
=
be64_to_cpu
(
ddqp
->
d_ino_softlimit
);
qinf
->
qi_rtbhardlimit
=
be64_to_cpu
(
ddqp
->
d_rtb_hardlimit
);
qinf
->
qi_rtbsoftlimit
=
be64_to_cpu
(
ddqp
->
d_rtb_softlimit
);
xfs_qm_dqdestroy
(
dqp
);
}
else
{
qinf
->
qi_btimelimit
=
XFS_QM_BTIMELIMIT
;
...
...
@@ -656,6 +680,13 @@ xfs_qm_init_quotainfo(
qinf
->
qi_rtbwarnlimit
=
XFS_QM_RTBWARNLIMIT
;
}
if
(
XFS_IS_UQUOTA_RUNNING
(
mp
))
xfs_qm_set_defquota
(
mp
,
XFS_DQ_USER
,
qinf
);
if
(
XFS_IS_GQUOTA_RUNNING
(
mp
))
xfs_qm_set_defquota
(
mp
,
XFS_DQ_GROUP
,
qinf
);
if
(
XFS_IS_PQUOTA_RUNNING
(
mp
))
xfs_qm_set_defquota
(
mp
,
XFS_DQ_PROJ
,
qinf
);
qinf
->
qi_shrinker
.
count_objects
=
xfs_qm_shrink_count
;
qinf
->
qi_shrinker
.
scan_objects
=
xfs_qm_shrink_scan
;
qinf
->
qi_shrinker
.
seeks
=
DEFAULT_SEEKS
;
...
...
fs/xfs/xfs_qm.h
浏览文件 @
1b186d25
...
...
@@ -53,6 +53,15 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
*/
#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1
struct
xfs_def_quota
{
xfs_qcnt_t
bhardlimit
;
/* default data blk hard limit */
xfs_qcnt_t
bsoftlimit
;
/* default data blk soft limit */
xfs_qcnt_t
ihardlimit
;
/* default inode count hard limit */
xfs_qcnt_t
isoftlimit
;
/* default inode count soft limit */
xfs_qcnt_t
rtbhardlimit
;
/* default realtime blk hard limit */
xfs_qcnt_t
rtbsoftlimit
;
/* default realtime blk soft limit */
};
/*
* Various quota information for individual filesystems.
* The mount structure keeps a pointer to this.
...
...
@@ -76,12 +85,9 @@ typedef struct xfs_quotainfo {
struct
mutex
qi_quotaofflock
;
/* to serialize quotaoff */
xfs_filblks_t
qi_dqchunklen
;
/* # BBs in a chunk of dqs */
uint
qi_dqperchunk
;
/* # ondisk dqs in above chunk */
xfs_qcnt_t
qi_bhardlimit
;
/* default data blk hard limit */
xfs_qcnt_t
qi_bsoftlimit
;
/* default data blk soft limit */
xfs_qcnt_t
qi_ihardlimit
;
/* default inode count hard limit */
xfs_qcnt_t
qi_isoftlimit
;
/* default inode count soft limit */
xfs_qcnt_t
qi_rtbhardlimit
;
/* default realtime blk hard limit */
xfs_qcnt_t
qi_rtbsoftlimit
;
/* default realtime blk soft limit */
struct
xfs_def_quota
qi_usr_default
;
struct
xfs_def_quota
qi_grp_default
;
struct
xfs_def_quota
qi_prj_default
;
struct
shrinker
qi_shrinker
;
}
xfs_quotainfo_t
;
...
...
@@ -104,15 +110,15 @@ xfs_dquot_tree(
}
static
inline
struct
xfs_inode
*
xfs_
dq_to_quota_inode
(
struct
xfs_dquot
*
dqp
)
xfs_
quota_inode
(
xfs_mount_t
*
mp
,
uint
dq_flags
)
{
switch
(
dq
p
->
dq
_flags
&
XFS_DQ_ALLTYPES
)
{
switch
(
dq_flags
&
XFS_DQ_ALLTYPES
)
{
case
XFS_DQ_USER
:
return
dqp
->
q_mount
->
m_quotainfo
->
qi_uquotaip
;
return
mp
->
m_quotainfo
->
qi_uquotaip
;
case
XFS_DQ_GROUP
:
return
dqp
->
q_mount
->
m_quotainfo
->
qi_gquotaip
;
return
mp
->
m_quotainfo
->
qi_gquotaip
;
case
XFS_DQ_PROJ
:
return
dqp
->
q_mount
->
m_quotainfo
->
qi_pquotaip
;
return
mp
->
m_quotainfo
->
qi_pquotaip
;
default:
ASSERT
(
0
);
}
...
...
@@ -164,11 +170,27 @@ extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint);
/* quota ops */
extern
int
xfs_qm_scall_trunc_qfiles
(
struct
xfs_mount
*
,
uint
);
extern
int
xfs_qm_scall_getquota
(
struct
xfs_mount
*
,
xfs_dqid_t
,
uint
,
struct
qc_dqblk
*
);
extern
int
xfs_qm_scall_getquota
(
struct
xfs_mount
*
,
xfs_dqid_t
*
,
uint
,
struct
qc_dqblk
*
,
uint
);
extern
int
xfs_qm_scall_setqlim
(
struct
xfs_mount
*
,
xfs_dqid_t
,
uint
,
struct
qc_dqblk
*
);
extern
int
xfs_qm_scall_quotaon
(
struct
xfs_mount
*
,
uint
);
extern
int
xfs_qm_scall_quotaoff
(
struct
xfs_mount
*
,
uint
);
static
inline
struct
xfs_def_quota
*
xfs_get_defquota
(
struct
xfs_dquot
*
dqp
,
struct
xfs_quotainfo
*
qi
)
{
struct
xfs_def_quota
*
defq
;
if
(
XFS_QM_ISUDQ
(
dqp
))
defq
=
&
qi
->
qi_usr_default
;
else
if
(
XFS_QM_ISGDQ
(
dqp
))
defq
=
&
qi
->
qi_grp_default
;
else
{
ASSERT
(
XFS_QM_ISPDQ
(
dqp
));
defq
=
&
qi
->
qi_prj_default
;
}
return
defq
;
}
#endif
/* __XFS_QM_H__ */
fs/xfs/xfs_qm_syscalls.c
浏览文件 @
1b186d25
...
...
@@ -404,6 +404,7 @@ xfs_qm_scall_setqlim(
struct
xfs_disk_dquot
*
ddq
;
struct
xfs_dquot
*
dqp
;
struct
xfs_trans
*
tp
;
struct
xfs_def_quota
*
defq
;
int
error
;
xfs_qcnt_t
hard
,
soft
;
...
...
@@ -431,6 +432,8 @@ xfs_qm_scall_setqlim(
ASSERT
(
error
!=
-
ENOENT
);
goto
out_unlock
;
}
defq
=
xfs_get_defquota
(
dqp
,
q
);
xfs_dqunlock
(
dqp
);
tp
=
xfs_trans_alloc
(
mp
,
XFS_TRANS_QM_SETQLIM
);
...
...
@@ -458,8 +461,8 @@ xfs_qm_scall_setqlim(
ddq
->
d_blk_softlimit
=
cpu_to_be64
(
soft
);
xfs_dquot_set_prealloc_limits
(
dqp
);
if
(
id
==
0
)
{
q
->
qi_
bhardlimit
=
hard
;
q
->
qi_
bsoftlimit
=
soft
;
defq
->
bhardlimit
=
hard
;
defq
->
bsoftlimit
=
soft
;
}
}
else
{
xfs_debug
(
mp
,
"blkhard %Ld < blksoft %Ld"
,
hard
,
soft
);
...
...
@@ -474,8 +477,8 @@ xfs_qm_scall_setqlim(
ddq
->
d_rtb_hardlimit
=
cpu_to_be64
(
hard
);
ddq
->
d_rtb_softlimit
=
cpu_to_be64
(
soft
);
if
(
id
==
0
)
{
q
->
qi_
rtbhardlimit
=
hard
;
q
->
qi_
rtbsoftlimit
=
soft
;
defq
->
rtbhardlimit
=
hard
;
defq
->
rtbsoftlimit
=
soft
;
}
}
else
{
xfs_debug
(
mp
,
"rtbhard %Ld < rtbsoft %Ld"
,
hard
,
soft
);
...
...
@@ -491,8 +494,8 @@ xfs_qm_scall_setqlim(
ddq
->
d_ino_hardlimit
=
cpu_to_be64
(
hard
);
ddq
->
d_ino_softlimit
=
cpu_to_be64
(
soft
);
if
(
id
==
0
)
{
q
->
qi_
ihardlimit
=
hard
;
q
->
qi_
isoftlimit
=
soft
;
defq
->
ihardlimit
=
hard
;
defq
->
isoftlimit
=
soft
;
}
}
else
{
xfs_debug
(
mp
,
"ihard %Ld < isoft %Ld"
,
hard
,
soft
);
...
...
@@ -635,9 +638,10 @@ xfs_qm_log_quotaoff(
int
xfs_qm_scall_getquota
(
struct
xfs_mount
*
mp
,
xfs_dqid_t
id
,
xfs_dqid_t
*
id
,
uint
type
,
struct
qc_dqblk
*
dst
)
struct
qc_dqblk
*
dst
,
uint
dqget_flags
)
{
struct
xfs_dquot
*
dqp
;
int
error
;
...
...
@@ -647,7 +651,7 @@ xfs_qm_scall_getquota(
* we aren't passing the XFS_QMOPT_DOALLOC flag. If it doesn't
* exist, we'll get ENOENT back.
*/
error
=
xfs_qm_dqget
(
mp
,
NULL
,
id
,
type
,
0
,
&
dqp
);
error
=
xfs_qm_dqget
(
mp
,
NULL
,
*
id
,
type
,
dqget_flags
,
&
dqp
);
if
(
error
)
return
error
;
...
...
@@ -660,6 +664,9 @@ xfs_qm_scall_getquota(
goto
out_put
;
}
/* Fill in the ID we actually read from disk */
*
id
=
be32_to_cpu
(
dqp
->
q_core
.
d_id
);
memset
(
dst
,
0
,
sizeof
(
*
dst
));
dst
->
d_spc_hardlimit
=
XFS_FSB_TO_B
(
mp
,
be64_to_cpu
(
dqp
->
q_core
.
d_blk_hardlimit
));
...
...
@@ -701,7 +708,7 @@ xfs_qm_scall_getquota(
if
(((
XFS_IS_UQUOTA_ENFORCED
(
mp
)
&&
type
==
XFS_DQ_USER
)
||
(
XFS_IS_GQUOTA_ENFORCED
(
mp
)
&&
type
==
XFS_DQ_GROUP
)
||
(
XFS_IS_PQUOTA_ENFORCED
(
mp
)
&&
type
==
XFS_DQ_PROJ
))
&&
id
!=
0
)
{
*
id
!=
0
)
{
if
((
dst
->
d_space
>
dst
->
d_spc_softlimit
)
&&
(
dst
->
d_spc_softlimit
>
0
))
{
ASSERT
(
dst
->
d_spc_timer
!=
0
);
...
...
fs/xfs/xfs_quotaops.c
浏览文件 @
1b186d25
...
...
@@ -231,14 +231,45 @@ xfs_fs_get_dqblk(
struct
qc_dqblk
*
qdq
)
{
struct
xfs_mount
*
mp
=
XFS_M
(
sb
);
xfs_dqid_t
id
;
if
(
!
XFS_IS_QUOTA_RUNNING
(
mp
))
return
-
ENOSYS
;
if
(
!
XFS_IS_QUOTA_ON
(
mp
))
return
-
ESRCH
;
return
xfs_qm_scall_getquota
(
mp
,
from_kqid
(
&
init_user_ns
,
qid
),
xfs_quota_type
(
qid
.
type
),
qdq
);
id
=
from_kqid
(
&
init_user_ns
,
qid
);
return
xfs_qm_scall_getquota
(
mp
,
&
id
,
xfs_quota_type
(
qid
.
type
),
qdq
,
0
);
}
/* Return quota info for active quota >= this qid */
STATIC
int
xfs_fs_get_nextdqblk
(
struct
super_block
*
sb
,
struct
kqid
*
qid
,
struct
qc_dqblk
*
qdq
)
{
int
ret
;
struct
xfs_mount
*
mp
=
XFS_M
(
sb
);
xfs_dqid_t
id
;
if
(
!
XFS_IS_QUOTA_RUNNING
(
mp
))
return
-
ENOSYS
;
if
(
!
XFS_IS_QUOTA_ON
(
mp
))
return
-
ESRCH
;
id
=
from_kqid
(
&
init_user_ns
,
*
qid
);
ret
=
xfs_qm_scall_getquota
(
mp
,
&
id
,
xfs_quota_type
(
qid
->
type
),
qdq
,
XFS_QMOPT_DQNEXT
);
if
(
ret
)
return
ret
;
/* ID may be different, so convert back what we got */
*
qid
=
make_kqid
(
current_user_ns
(),
qid
->
type
,
id
);
return
0
;
}
STATIC
int
...
...
@@ -267,5 +298,6 @@ const struct quotactl_ops xfs_quotactl_operations = {
.
quota_disable
=
xfs_quota_disable
,
.
rm_xquota
=
xfs_fs_rm_xquota
,
.
get_dqblk
=
xfs_fs_get_dqblk
,
.
get_nextdqblk
=
xfs_fs_get_nextdqblk
,
.
set_dqblk
=
xfs_fs_set_dqblk
,
};
fs/xfs/xfs_trans_dquot.c
浏览文件 @
1b186d25
...
...
@@ -609,17 +609,20 @@ xfs_trans_dqresv(
xfs_qcnt_t
total_count
;
xfs_qcnt_t
*
resbcountp
;
xfs_quotainfo_t
*
q
=
mp
->
m_quotainfo
;
struct
xfs_def_quota
*
defq
;
xfs_dqlock
(
dqp
);
defq
=
xfs_get_defquota
(
dqp
,
q
);
if
(
flags
&
XFS_TRANS_DQ_RES_BLKS
)
{
hardlimit
=
be64_to_cpu
(
dqp
->
q_core
.
d_blk_hardlimit
);
if
(
!
hardlimit
)
hardlimit
=
q
->
qi_
bhardlimit
;
hardlimit
=
defq
->
bhardlimit
;
softlimit
=
be64_to_cpu
(
dqp
->
q_core
.
d_blk_softlimit
);
if
(
!
softlimit
)
softlimit
=
q
->
qi_
bsoftlimit
;
softlimit
=
defq
->
bsoftlimit
;
timer
=
be32_to_cpu
(
dqp
->
q_core
.
d_btimer
);
warns
=
be16_to_cpu
(
dqp
->
q_core
.
d_bwarns
);
warnlimit
=
dqp
->
q_mount
->
m_quotainfo
->
qi_bwarnlimit
;
...
...
@@ -628,10 +631,10 @@ xfs_trans_dqresv(
ASSERT
(
flags
&
XFS_TRANS_DQ_RES_RTBLKS
);
hardlimit
=
be64_to_cpu
(
dqp
->
q_core
.
d_rtb_hardlimit
);
if
(
!
hardlimit
)
hardlimit
=
q
->
qi_
rtbhardlimit
;
hardlimit
=
defq
->
rtbhardlimit
;
softlimit
=
be64_to_cpu
(
dqp
->
q_core
.
d_rtb_softlimit
);
if
(
!
softlimit
)
softlimit
=
q
->
qi_
rtbsoftlimit
;
softlimit
=
defq
->
rtbsoftlimit
;
timer
=
be32_to_cpu
(
dqp
->
q_core
.
d_rtbtimer
);
warns
=
be16_to_cpu
(
dqp
->
q_core
.
d_rtbwarns
);
warnlimit
=
dqp
->
q_mount
->
m_quotainfo
->
qi_rtbwarnlimit
;
...
...
@@ -672,10 +675,10 @@ xfs_trans_dqresv(
warnlimit
=
dqp
->
q_mount
->
m_quotainfo
->
qi_iwarnlimit
;
hardlimit
=
be64_to_cpu
(
dqp
->
q_core
.
d_ino_hardlimit
);
if
(
!
hardlimit
)
hardlimit
=
q
->
qi_
ihardlimit
;
hardlimit
=
defq
->
ihardlimit
;
softlimit
=
be64_to_cpu
(
dqp
->
q_core
.
d_ino_softlimit
);
if
(
!
softlimit
)
softlimit
=
q
->
qi_
isoftlimit
;
softlimit
=
defq
->
isoftlimit
;
if
(
hardlimit
&&
total_count
>
hardlimit
)
{
xfs_quota_warn
(
mp
,
dqp
,
QUOTA_NL_IHARDWARN
);
...
...
include/linux/quota.h
浏览文件 @
1b186d25
...
...
@@ -425,6 +425,8 @@ struct quotactl_ops {
int
(
*
quota_sync
)(
struct
super_block
*
,
int
);
int
(
*
set_info
)(
struct
super_block
*
,
int
,
struct
qc_info
*
);
int
(
*
get_dqblk
)(
struct
super_block
*
,
struct
kqid
,
struct
qc_dqblk
*
);
int
(
*
get_nextdqblk
)(
struct
super_block
*
,
struct
kqid
*
,
struct
qc_dqblk
*
);
int
(
*
set_dqblk
)(
struct
super_block
*
,
struct
kqid
,
struct
qc_dqblk
*
);
int
(
*
get_state
)(
struct
super_block
*
,
struct
qc_state
*
);
int
(
*
rm_xquota
)(
struct
super_block
*
,
unsigned
int
);
...
...
include/uapi/linux/dqblk_xfs.h
浏览文件 @
1b186d25
...
...
@@ -39,6 +39,7 @@
#define Q_XQUOTARM XQM_CMD(6)
/* free disk space used by dquots */
#define Q_XQUOTASYNC XQM_CMD(7)
/* delalloc flush, updates dquots */
#define Q_XGETQSTATV XQM_CMD(8)
/* newer version of get quota */
#define Q_XGETNEXTQUOTA XQM_CMD(9)
/* get disk limits and usage >= ID */
/*
* fs_disk_quota structure:
...
...
include/uapi/linux/quota.h
浏览文件 @
1b186d25
...
...
@@ -71,6 +71,7 @@
#define Q_SETINFO 0x800006
/* set information about quota files */
#define Q_GETQUOTA 0x800007
/* get user quota structure */
#define Q_SETQUOTA 0x800008
/* set user quota structure */
#define Q_GETNEXTQUOTA 0x800009
/* get disk limits and usage >= ID */
/* Quota format type IDs */
#define QFMT_VFS_OLD 1
...
...
@@ -119,6 +120,19 @@ struct if_dqblk {
__u32
dqb_valid
;
};
struct
if_nextdqblk
{
__u64
dqb_bhardlimit
;
__u64
dqb_bsoftlimit
;
__u64
dqb_curspace
;
__u64
dqb_ihardlimit
;
__u64
dqb_isoftlimit
;
__u64
dqb_curinodes
;
__u64
dqb_btime
;
__u64
dqb_itime
;
__u32
dqb_valid
;
__u32
dqb_id
;
};
/*
* Structure used for setting quota information about file via quotactl
* Following flags are used to specify which fields are valid
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录