mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-11 17:10:13 +00:00
Compare commits
34 Commits
6a23ae0a96
...
e7c375b181
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7c375b181 | ||
|
|
418592a040 | ||
|
|
e97c61885b | ||
|
|
36c6f3c03d | ||
|
|
a257e97421 | ||
|
|
c87488a123 | ||
|
|
5f02151c41 | ||
|
|
e9d50b78fd | ||
|
|
56325e8c68 | ||
|
|
1274162464 | ||
|
|
3cd1548a27 | ||
|
|
78f0e33cd6 | ||
|
|
a3f8f86627 | ||
|
|
75fdd57499 | ||
|
|
90f601b497 | ||
|
|
8637fa89e6 | ||
|
|
c014021253 | ||
|
|
124af0868e | ||
|
|
e106e269c5 | ||
|
|
f2c1f63163 | ||
|
|
63b5aa01da | ||
|
|
97315e7c90 | ||
|
|
a1d3bc606b | ||
|
|
f4fa7c25f6 | ||
|
|
9db8d46712 | ||
|
|
34ab4c7558 | ||
|
|
330e2c5148 | ||
|
|
5c56bf214a | ||
|
|
9631350885 | ||
|
|
0d9c80aa57 | ||
|
|
9225f02ff2 | ||
|
|
e4185bed73 | ||
|
|
2c2b67af5f | ||
|
|
0778ac7df5 |
@ -231,7 +231,7 @@ int sb_set_blocksize(struct super_block *sb, int size)
|
|||||||
|
|
||||||
EXPORT_SYMBOL(sb_set_blocksize);
|
EXPORT_SYMBOL(sb_set_blocksize);
|
||||||
|
|
||||||
int sb_min_blocksize(struct super_block *sb, int size)
|
int __must_check sb_min_blocksize(struct super_block *sb, int size)
|
||||||
{
|
{
|
||||||
int minsize = bdev_logical_block_size(sb->s_bdev);
|
int minsize = bdev_logical_block_size(sb->s_bdev);
|
||||||
if (size < minsize)
|
if (size < minsize)
|
||||||
|
|||||||
@ -599,6 +599,7 @@ mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)
|
|||||||
uint8_t *datbuf = NULL, *oobbuf = NULL;
|
uint8_t *datbuf = NULL, *oobbuf = NULL;
|
||||||
size_t datbuf_len, oobbuf_len;
|
size_t datbuf_len, oobbuf_len;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
u64 end;
|
||||||
|
|
||||||
if (copy_from_user(&req, argp, sizeof(req)))
|
if (copy_from_user(&req, argp, sizeof(req)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -618,7 +619,7 @@ mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)
|
|||||||
req.len &= 0xffffffff;
|
req.len &= 0xffffffff;
|
||||||
req.ooblen &= 0xffffffff;
|
req.ooblen &= 0xffffffff;
|
||||||
|
|
||||||
if (req.start + req.len > mtd->size)
|
if (check_add_overflow(req.start, req.len, &end) || end > mtd->size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
datbuf_len = min_t(size_t, req.len, mtd->erasesize);
|
datbuf_len = min_t(size_t, req.len, mtd->erasesize);
|
||||||
@ -698,6 +699,7 @@ mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)
|
|||||||
size_t datbuf_len, oobbuf_len;
|
size_t datbuf_len, oobbuf_len;
|
||||||
size_t orig_len, orig_ooblen;
|
size_t orig_len, orig_ooblen;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
u64 end;
|
||||||
|
|
||||||
if (copy_from_user(&req, argp, sizeof(req)))
|
if (copy_from_user(&req, argp, sizeof(req)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -724,7 +726,7 @@ mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)
|
|||||||
req.len &= 0xffffffff;
|
req.len &= 0xffffffff;
|
||||||
req.ooblen &= 0xffffffff;
|
req.ooblen &= 0xffffffff;
|
||||||
|
|
||||||
if (req.start + req.len > mtd->size) {
|
if (check_add_overflow(req.start, req.len, &end) || end > mtd->size) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ config MTD_NAND_ECC_MEDIATEK
|
|||||||
|
|
||||||
config MTD_NAND_ECC_REALTEK
|
config MTD_NAND_ECC_REALTEK
|
||||||
tristate "Realtek RTL93xx hardware ECC engine"
|
tristate "Realtek RTL93xx hardware ECC engine"
|
||||||
depends on HAS_IOMEM
|
depends on HAS_IOMEM && HAS_DMA
|
||||||
depends on MACH_REALTEK_RTL || COMPILE_TEST
|
depends on MACH_REALTEK_RTL || COMPILE_TEST
|
||||||
select MTD_NAND_ECC
|
select MTD_NAND_ECC
|
||||||
help
|
help
|
||||||
|
|||||||
@ -380,7 +380,7 @@ static void rtl_ecc_cleanup_ctx(struct nand_device *nand)
|
|||||||
nand_ecc_cleanup_req_tweaking(&ctx->req_ctx);
|
nand_ecc_cleanup_req_tweaking(&ctx->req_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nand_ecc_engine_ops rtl_ecc_engine_ops = {
|
static const struct nand_ecc_engine_ops rtl_ecc_engine_ops = {
|
||||||
.init_ctx = rtl_ecc_init_ctx,
|
.init_ctx = rtl_ecc_init_ctx,
|
||||||
.cleanup_ctx = rtl_ecc_cleanup_ctx,
|
.cleanup_ctx = rtl_ecc_cleanup_ctx,
|
||||||
.prepare_io_req = rtl_ecc_prepare_io_req,
|
.prepare_io_req = rtl_ecc_prepare_io_req,
|
||||||
@ -418,8 +418,8 @@ static int rtl_ecc_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
rtlc->buf = dma_alloc_noncoherent(dev, RTL_ECC_DMA_SIZE, &rtlc->buf_dma,
|
rtlc->buf = dma_alloc_noncoherent(dev, RTL_ECC_DMA_SIZE, &rtlc->buf_dma,
|
||||||
DMA_BIDIRECTIONAL, GFP_KERNEL);
|
DMA_BIDIRECTIONAL, GFP_KERNEL);
|
||||||
if (IS_ERR(rtlc->buf))
|
if (!rtlc->buf)
|
||||||
return PTR_ERR(rtlc->buf);
|
return -ENOMEM;
|
||||||
|
|
||||||
rtlc->dev = dev;
|
rtlc->dev = dev;
|
||||||
rtlc->engine.dev = dev;
|
rtlc->engine.dev = dev;
|
||||||
|
|||||||
@ -906,7 +906,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
|
|||||||
err = devm_request_irq(&pdev->dev, r->start,
|
err = devm_request_irq(&pdev->dev, r->start,
|
||||||
s5pc110_onenand_irq,
|
s5pc110_onenand_irq,
|
||||||
IRQF_SHARED, "onenand",
|
IRQF_SHARED, "onenand",
|
||||||
&onenand);
|
onenand);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to get irq\n");
|
dev_err(&pdev->dev, "failed to get irq\n");
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@ -2871,7 +2871,7 @@ cadence_nand_irq_cleanup(int irqnum, struct cdns_nand_ctrl *cdns_ctrl)
|
|||||||
static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
||||||
{
|
{
|
||||||
dma_cap_mask_t mask;
|
dma_cap_mask_t mask;
|
||||||
struct dma_device *dma_dev = cdns_ctrl->dmac->device;
|
struct dma_device *dma_dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cdns_ctrl->cdma_desc = dma_alloc_coherent(cdns_ctrl->dev,
|
cdns_ctrl->cdma_desc = dma_alloc_coherent(cdns_ctrl->dev,
|
||||||
@ -2915,6 +2915,7 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dma_dev = cdns_ctrl->dmac->device;
|
||||||
cdns_ctrl->io.iova_dma = dma_map_resource(dma_dev->dev, cdns_ctrl->io.dma,
|
cdns_ctrl->io.iova_dma = dma_map_resource(dma_dev->dev, cdns_ctrl->io.dma,
|
||||||
cdns_ctrl->io.size,
|
cdns_ctrl->io.size,
|
||||||
DMA_BIDIRECTIONAL, 0);
|
DMA_BIDIRECTIONAL, 0);
|
||||||
|
|||||||
@ -58,7 +58,7 @@ static const struct spinand_info fmsh_spinand_table[] = {
|
|||||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||||
&write_cache_variants,
|
&write_cache_variants,
|
||||||
&update_cache_variants),
|
&update_cache_variants),
|
||||||
SPINAND_HAS_QE_BIT,
|
0,
|
||||||
SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)),
|
SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -229,7 +229,7 @@ error:
|
|||||||
* @name: The name of the cell.
|
* @name: The name of the cell.
|
||||||
* @namesz: The strlen of the cell name.
|
* @namesz: The strlen of the cell name.
|
||||||
* @vllist: A colon/comma separated list of numeric IP addresses or NULL.
|
* @vllist: A colon/comma separated list of numeric IP addresses or NULL.
|
||||||
* @excl: T if an error should be given if the cell name already exists.
|
* @reason: The reason we're doing the lookup
|
||||||
* @trace: The reason to be logged if the lookup is successful.
|
* @trace: The reason to be logged if the lookup is successful.
|
||||||
*
|
*
|
||||||
* Look up a cell record by name and query the DNS for VL server addresses if
|
* Look up a cell record by name and query the DNS for VL server addresses if
|
||||||
@ -239,7 +239,8 @@ error:
|
|||||||
*/
|
*/
|
||||||
struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
||||||
const char *name, unsigned int namesz,
|
const char *name, unsigned int namesz,
|
||||||
const char *vllist, bool excl,
|
const char *vllist,
|
||||||
|
enum afs_lookup_cell_for reason,
|
||||||
enum afs_cell_trace trace)
|
enum afs_cell_trace trace)
|
||||||
{
|
{
|
||||||
struct afs_cell *cell, *candidate, *cursor;
|
struct afs_cell *cell, *candidate, *cursor;
|
||||||
@ -247,12 +248,18 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
|||||||
enum afs_cell_state state;
|
enum afs_cell_state state;
|
||||||
int ret, n;
|
int ret, n;
|
||||||
|
|
||||||
_enter("%s,%s", name, vllist);
|
_enter("%s,%s,%u", name, vllist, reason);
|
||||||
|
|
||||||
if (!excl) {
|
if (reason != AFS_LOOKUP_CELL_PRELOAD) {
|
||||||
cell = afs_find_cell(net, name, namesz, trace);
|
cell = afs_find_cell(net, name, namesz, trace);
|
||||||
if (!IS_ERR(cell))
|
if (!IS_ERR(cell)) {
|
||||||
|
if (reason == AFS_LOOKUP_CELL_DYNROOT)
|
||||||
|
goto no_wait;
|
||||||
|
if (cell->state == AFS_CELL_SETTING_UP ||
|
||||||
|
cell->state == AFS_CELL_UNLOOKED)
|
||||||
|
goto lookup_cell;
|
||||||
goto wait_for_cell;
|
goto wait_for_cell;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assume we're probably going to create a cell and preallocate and
|
/* Assume we're probably going to create a cell and preallocate and
|
||||||
@ -298,26 +305,69 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
|||||||
rb_insert_color(&cell->net_node, &net->cells);
|
rb_insert_color(&cell->net_node, &net->cells);
|
||||||
up_write(&net->cells_lock);
|
up_write(&net->cells_lock);
|
||||||
|
|
||||||
afs_queue_cell(cell, afs_cell_trace_queue_new);
|
lookup_cell:
|
||||||
|
if (reason != AFS_LOOKUP_CELL_PRELOAD &&
|
||||||
|
reason != AFS_LOOKUP_CELL_ROOTCELL) {
|
||||||
|
set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
|
||||||
|
afs_queue_cell(cell, afs_cell_trace_queue_new);
|
||||||
|
}
|
||||||
|
|
||||||
wait_for_cell:
|
wait_for_cell:
|
||||||
_debug("wait_for_cell");
|
|
||||||
state = smp_load_acquire(&cell->state); /* vs error */
|
state = smp_load_acquire(&cell->state); /* vs error */
|
||||||
if (state != AFS_CELL_ACTIVE &&
|
switch (state) {
|
||||||
state != AFS_CELL_DEAD) {
|
case AFS_CELL_ACTIVE:
|
||||||
|
case AFS_CELL_DEAD:
|
||||||
|
break;
|
||||||
|
case AFS_CELL_UNLOOKED:
|
||||||
|
default:
|
||||||
|
if (reason == AFS_LOOKUP_CELL_PRELOAD ||
|
||||||
|
reason == AFS_LOOKUP_CELL_ROOTCELL)
|
||||||
|
break;
|
||||||
|
_debug("wait_for_cell");
|
||||||
afs_see_cell(cell, afs_cell_trace_wait);
|
afs_see_cell(cell, afs_cell_trace_wait);
|
||||||
wait_var_event(&cell->state,
|
wait_var_event(&cell->state,
|
||||||
({
|
({
|
||||||
state = smp_load_acquire(&cell->state); /* vs error */
|
state = smp_load_acquire(&cell->state); /* vs error */
|
||||||
state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
|
state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
|
||||||
}));
|
}));
|
||||||
|
_debug("waited_for_cell %d %d", cell->state, cell->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_wait:
|
||||||
/* Check the state obtained from the wait check. */
|
/* Check the state obtained from the wait check. */
|
||||||
|
state = smp_load_acquire(&cell->state); /* vs error */
|
||||||
if (state == AFS_CELL_DEAD) {
|
if (state == AFS_CELL_DEAD) {
|
||||||
ret = cell->error;
|
ret = cell->error;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (state == AFS_CELL_ACTIVE) {
|
||||||
|
switch (cell->dns_status) {
|
||||||
|
case DNS_LOOKUP_NOT_DONE:
|
||||||
|
if (cell->dns_source == DNS_RECORD_FROM_CONFIG) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fallthrough;
|
||||||
|
default:
|
||||||
|
ret = -EIO;
|
||||||
|
goto error;
|
||||||
|
case DNS_LOOKUP_GOOD:
|
||||||
|
case DNS_LOOKUP_GOOD_WITH_BAD:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case DNS_LOOKUP_GOT_NOT_FOUND:
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto error;
|
||||||
|
case DNS_LOOKUP_BAD:
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
goto error;
|
||||||
|
case DNS_LOOKUP_GOT_LOCAL_FAILURE:
|
||||||
|
case DNS_LOOKUP_GOT_TEMP_FAILURE:
|
||||||
|
case DNS_LOOKUP_GOT_NS_FAILURE:
|
||||||
|
ret = -EDESTADDRREQ;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_leave(" = %p [cell]", cell);
|
_leave(" = %p [cell]", cell);
|
||||||
return cell;
|
return cell;
|
||||||
@ -325,7 +375,7 @@ wait_for_cell:
|
|||||||
cell_already_exists:
|
cell_already_exists:
|
||||||
_debug("cell exists");
|
_debug("cell exists");
|
||||||
cell = cursor;
|
cell = cursor;
|
||||||
if (excl) {
|
if (reason == AFS_LOOKUP_CELL_PRELOAD) {
|
||||||
ret = -EEXIST;
|
ret = -EEXIST;
|
||||||
} else {
|
} else {
|
||||||
afs_use_cell(cursor, trace);
|
afs_use_cell(cursor, trace);
|
||||||
@ -384,7 +434,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* allocate a cell record for the root/workstation cell */
|
/* allocate a cell record for the root/workstation cell */
|
||||||
new_root = afs_lookup_cell(net, rootcell, len, vllist, false,
|
new_root = afs_lookup_cell(net, rootcell, len, vllist,
|
||||||
|
AFS_LOOKUP_CELL_ROOTCELL,
|
||||||
afs_cell_trace_use_lookup_ws);
|
afs_cell_trace_use_lookup_ws);
|
||||||
if (IS_ERR(new_root)) {
|
if (IS_ERR(new_root)) {
|
||||||
_leave(" = %ld", PTR_ERR(new_root));
|
_leave(" = %ld", PTR_ERR(new_root));
|
||||||
@ -777,6 +828,7 @@ static bool afs_manage_cell(struct afs_cell *cell)
|
|||||||
switch (cell->state) {
|
switch (cell->state) {
|
||||||
case AFS_CELL_SETTING_UP:
|
case AFS_CELL_SETTING_UP:
|
||||||
goto set_up_cell;
|
goto set_up_cell;
|
||||||
|
case AFS_CELL_UNLOOKED:
|
||||||
case AFS_CELL_ACTIVE:
|
case AFS_CELL_ACTIVE:
|
||||||
goto cell_is_active;
|
goto cell_is_active;
|
||||||
case AFS_CELL_REMOVING:
|
case AFS_CELL_REMOVING:
|
||||||
@ -797,7 +849,7 @@ set_up_cell:
|
|||||||
goto remove_cell;
|
goto remove_cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
|
afs_set_cell_state(cell, AFS_CELL_UNLOOKED);
|
||||||
|
|
||||||
cell_is_active:
|
cell_is_active:
|
||||||
if (afs_has_cell_expired(cell, &next_manage))
|
if (afs_has_cell_expired(cell, &next_manage))
|
||||||
@ -807,6 +859,8 @@ cell_is_active:
|
|||||||
ret = afs_update_cell(cell);
|
ret = afs_update_cell(cell);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
cell->error = ret;
|
cell->error = ret;
|
||||||
|
if (cell->state == AFS_CELL_UNLOOKED)
|
||||||
|
afs_set_cell_state(cell, AFS_CELL_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_manage < TIME64_MAX && cell->net->live) {
|
if (next_manage < TIME64_MAX && cell->net->live) {
|
||||||
|
|||||||
@ -108,7 +108,8 @@ static struct dentry *afs_dynroot_lookup_cell(struct inode *dir, struct dentry *
|
|||||||
dotted = true;
|
dotted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell = afs_lookup_cell(net, name, len, NULL, false,
|
cell = afs_lookup_cell(net, name, len, NULL,
|
||||||
|
AFS_LOOKUP_CELL_DYNROOT,
|
||||||
afs_cell_trace_use_lookup_dynroot);
|
afs_cell_trace_use_lookup_dynroot);
|
||||||
if (IS_ERR(cell)) {
|
if (IS_ERR(cell)) {
|
||||||
ret = PTR_ERR(cell);
|
ret = PTR_ERR(cell);
|
||||||
|
|||||||
@ -343,6 +343,7 @@ extern const char afs_init_sysname[];
|
|||||||
|
|
||||||
enum afs_cell_state {
|
enum afs_cell_state {
|
||||||
AFS_CELL_SETTING_UP,
|
AFS_CELL_SETTING_UP,
|
||||||
|
AFS_CELL_UNLOOKED,
|
||||||
AFS_CELL_ACTIVE,
|
AFS_CELL_ACTIVE,
|
||||||
AFS_CELL_REMOVING,
|
AFS_CELL_REMOVING,
|
||||||
AFS_CELL_DEAD,
|
AFS_CELL_DEAD,
|
||||||
@ -1049,9 +1050,18 @@ static inline bool afs_cb_is_broken(unsigned int cb_break,
|
|||||||
extern int afs_cell_init(struct afs_net *, const char *);
|
extern int afs_cell_init(struct afs_net *, const char *);
|
||||||
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
|
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
|
||||||
enum afs_cell_trace);
|
enum afs_cell_trace);
|
||||||
|
enum afs_lookup_cell_for {
|
||||||
|
AFS_LOOKUP_CELL_DYNROOT,
|
||||||
|
AFS_LOOKUP_CELL_MOUNTPOINT,
|
||||||
|
AFS_LOOKUP_CELL_DIRECT_MOUNT,
|
||||||
|
AFS_LOOKUP_CELL_PRELOAD,
|
||||||
|
AFS_LOOKUP_CELL_ROOTCELL,
|
||||||
|
AFS_LOOKUP_CELL_ALIAS_CHECK,
|
||||||
|
};
|
||||||
struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
struct afs_cell *afs_lookup_cell(struct afs_net *net,
|
||||||
const char *name, unsigned int namesz,
|
const char *name, unsigned int namesz,
|
||||||
const char *vllist, bool excl,
|
const char *vllist,
|
||||||
|
enum afs_lookup_cell_for reason,
|
||||||
enum afs_cell_trace trace);
|
enum afs_cell_trace trace);
|
||||||
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
|
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
|
||||||
void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);
|
void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);
|
||||||
|
|||||||
@ -107,7 +107,8 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
|
|||||||
if (size > AFS_MAXCELLNAME)
|
if (size > AFS_MAXCELLNAME)
|
||||||
return -ENAMETOOLONG;
|
return -ENAMETOOLONG;
|
||||||
|
|
||||||
cell = afs_lookup_cell(ctx->net, p, size, NULL, false,
|
cell = afs_lookup_cell(ctx->net, p, size, NULL,
|
||||||
|
AFS_LOOKUP_CELL_MOUNTPOINT,
|
||||||
afs_cell_trace_use_lookup_mntpt);
|
afs_cell_trace_use_lookup_mntpt);
|
||||||
if (IS_ERR(cell)) {
|
if (IS_ERR(cell)) {
|
||||||
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
|
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
|
||||||
|
|||||||
@ -122,7 +122,8 @@ static int afs_proc_cells_write(struct file *file, char *buf, size_t size)
|
|||||||
if (strcmp(buf, "add") == 0) {
|
if (strcmp(buf, "add") == 0) {
|
||||||
struct afs_cell *cell;
|
struct afs_cell *cell;
|
||||||
|
|
||||||
cell = afs_lookup_cell(net, name, strlen(name), args, true,
|
cell = afs_lookup_cell(net, name, strlen(name), args,
|
||||||
|
AFS_LOOKUP_CELL_PRELOAD,
|
||||||
afs_cell_trace_use_lookup_add);
|
afs_cell_trace_use_lookup_add);
|
||||||
if (IS_ERR(cell)) {
|
if (IS_ERR(cell)) {
|
||||||
ret = PTR_ERR(cell);
|
ret = PTR_ERR(cell);
|
||||||
|
|||||||
@ -290,7 +290,7 @@ static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
/* lookup the cell record */
|
/* lookup the cell record */
|
||||||
if (cellname) {
|
if (cellname) {
|
||||||
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
|
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
|
||||||
NULL, false,
|
NULL, AFS_LOOKUP_CELL_DIRECT_MOUNT,
|
||||||
afs_cell_trace_use_lookup_mount);
|
afs_cell_trace_use_lookup_mount);
|
||||||
if (IS_ERR(cell)) {
|
if (IS_ERR(cell)) {
|
||||||
pr_err("kAFS: unable to lookup cell '%*.*s'\n",
|
pr_err("kAFS: unable to lookup cell '%*.*s'\n",
|
||||||
|
|||||||
@ -269,7 +269,8 @@ static int yfs_check_canonical_cell_name(struct afs_cell *cell, struct key *key)
|
|||||||
if (!name_len || name_len > AFS_MAXCELLNAME)
|
if (!name_len || name_len > AFS_MAXCELLNAME)
|
||||||
master = ERR_PTR(-EOPNOTSUPP);
|
master = ERR_PTR(-EOPNOTSUPP);
|
||||||
else
|
else
|
||||||
master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false,
|
master = afs_lookup_cell(cell->net, cell_name, name_len, NULL,
|
||||||
|
AFS_LOOKUP_CELL_ALIAS_CHECK,
|
||||||
afs_cell_trace_use_lookup_canonical);
|
afs_cell_trace_use_lookup_canonical);
|
||||||
kfree(cell_name);
|
kfree(cell_name);
|
||||||
if (IS_ERR(master))
|
if (IS_ERR(master))
|
||||||
|
|||||||
@ -61,7 +61,19 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
|
|||||||
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
|
off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
|
||||||
di = (struct bfs_inode *)bh->b_data + off;
|
di = (struct bfs_inode *)bh->b_data + off;
|
||||||
|
|
||||||
inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
|
/*
|
||||||
|
* https://martin.hinner.info/fs/bfs/bfs-structure.html explains that
|
||||||
|
* BFS in SCO UnixWare environment used only lower 9 bits of di->i_mode
|
||||||
|
* value. This means that, although bfs_write_inode() saves whole
|
||||||
|
* inode->i_mode bits (which include S_IFMT bits and S_IS{UID,GID,VTX}
|
||||||
|
* bits), middle 7 bits of di->i_mode value can be garbage when these
|
||||||
|
* bits were not saved by bfs_write_inode().
|
||||||
|
* Since we can't tell whether middle 7 bits are garbage, use only
|
||||||
|
* lower 12 bits (i.e. tolerate S_IS{UID,GID,VTX} bits possibly being
|
||||||
|
* garbage) and reconstruct S_IFMT bits for Linux environment from
|
||||||
|
* di->i_vtype value.
|
||||||
|
*/
|
||||||
|
inode->i_mode = 0x00000FFF & le32_to_cpu(di->i_mode);
|
||||||
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
|
if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
|
||||||
inode->i_mode |= S_IFDIR;
|
inode->i_mode |= S_IFDIR;
|
||||||
inode->i_op = &bfs_dir_inops;
|
inode->i_op = &bfs_dir_inops;
|
||||||
@ -71,6 +83,11 @@ struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
|
|||||||
inode->i_op = &bfs_file_inops;
|
inode->i_op = &bfs_file_inops;
|
||||||
inode->i_fop = &bfs_file_operations;
|
inode->i_fop = &bfs_file_operations;
|
||||||
inode->i_mapping->a_ops = &bfs_aops;
|
inode->i_mapping->a_ops = &bfs_aops;
|
||||||
|
} else {
|
||||||
|
brelse(bh);
|
||||||
|
printf("Unknown vtype=%u %s:%08lx\n",
|
||||||
|
le32_to_cpu(di->i_vtype), inode->i_sb->s_id, ino);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
|
BFS_I(inode)->i_sblock = le32_to_cpu(di->i_sblock);
|
||||||
|
|||||||
@ -837,8 +837,10 @@ out:
|
|||||||
inode_unlock(d_inode(root));
|
inode_unlock(d_inode(root));
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
if (f)
|
if (f) {
|
||||||
|
exe_file_allow_write_access(f);
|
||||||
filp_close(f, NULL);
|
filp_close(f, NULL);
|
||||||
|
}
|
||||||
kfree(e);
|
kfree(e);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -533,6 +533,7 @@ static struct file_system_type efivarfs_type = {
|
|||||||
.init_fs_context = efivarfs_init_fs_context,
|
.init_fs_context = efivarfs_init_fs_context,
|
||||||
.kill_sb = efivarfs_kill_sb,
|
.kill_sb = efivarfs_kill_sb,
|
||||||
.parameters = efivarfs_parameters,
|
.parameters = efivarfs_parameters,
|
||||||
|
.fs_flags = FS_POWER_FREEZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static __init int efivarfs_init(void)
|
static __init int efivarfs_init(void)
|
||||||
|
|||||||
@ -433,7 +433,10 @@ static int exfat_read_boot_sector(struct super_block *sb)
|
|||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
|
|
||||||
/* set block size to read super block */
|
/* set block size to read super block */
|
||||||
sb_min_blocksize(sb, 512);
|
if (!sb_min_blocksize(sb, 512)) {
|
||||||
|
exfat_err(sb, "unable to set blocksize");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* read boot sector */
|
/* read boot sector */
|
||||||
sbi->boot_bh = sb_bread(sb, 0);
|
sbi->boot_bh = sb_bread(sb, 0);
|
||||||
|
|||||||
@ -1595,8 +1595,12 @@ int fat_fill_super(struct super_block *sb, struct fs_context *fc,
|
|||||||
|
|
||||||
setup(sb); /* flavour-specific stuff that needs options */
|
setup(sb); /* flavour-specific stuff that needs options */
|
||||||
|
|
||||||
|
error = -EINVAL;
|
||||||
|
if (!sb_min_blocksize(sb, 512)) {
|
||||||
|
fat_msg(sb, KERN_ERR, "unable to set blocksize");
|
||||||
|
goto out_fail;
|
||||||
|
}
|
||||||
error = -EIO;
|
error = -EIO;
|
||||||
sb_min_blocksize(sb, 512);
|
|
||||||
bh = sb_bread(sb, 0);
|
bh = sb_bread(sb, 0);
|
||||||
if (bh == NULL) {
|
if (bh == NULL) {
|
||||||
fat_msg(sb, KERN_ERR, "unable to read boot sector");
|
fat_msg(sb, KERN_ERR, "unable to read boot sector");
|
||||||
|
|||||||
@ -373,7 +373,7 @@ static int virtio_fs_add_queues_sysfs(struct virtio_fs *fs)
|
|||||||
|
|
||||||
sprintf(buff, "%d", i);
|
sprintf(buff, "%d", i);
|
||||||
fsvq->kobj = kobject_create_and_add(buff, fs->mqs_kobj);
|
fsvq->kobj = kobject_create_and_add(buff, fs->mqs_kobj);
|
||||||
if (!fs->mqs_kobj) {
|
if (!fsvq->kobj) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_del;
|
goto out_del;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -979,7 +979,7 @@ static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
{
|
{
|
||||||
struct hostfs_fs_info *fsi = fc->s_fs_info;
|
struct hostfs_fs_info *fsi = fc->s_fs_info;
|
||||||
struct fs_parse_result result;
|
struct fs_parse_result result;
|
||||||
char *host_root;
|
char *host_root, *tmp_root;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
opt = fs_parse(fc, hostfs_param_specs, param, &result);
|
opt = fs_parse(fc, hostfs_param_specs, param, &result);
|
||||||
@ -990,11 +990,13 @@ static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
case Opt_hostfs:
|
case Opt_hostfs:
|
||||||
host_root = param->string;
|
host_root = param->string;
|
||||||
if (!*host_root)
|
if (!*host_root)
|
||||||
host_root = "";
|
break;
|
||||||
fsi->host_root_path =
|
tmp_root = kasprintf(GFP_KERNEL, "%s%s",
|
||||||
kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
|
fsi->host_root_path, host_root);
|
||||||
if (fsi->host_root_path == NULL)
|
if (!tmp_root)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
kfree(fsi->host_root_path);
|
||||||
|
fsi->host_root_path = tmp_root;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,17 +1006,17 @@ static int hostfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
static int hostfs_parse_monolithic(struct fs_context *fc, void *data)
|
static int hostfs_parse_monolithic(struct fs_context *fc, void *data)
|
||||||
{
|
{
|
||||||
struct hostfs_fs_info *fsi = fc->s_fs_info;
|
struct hostfs_fs_info *fsi = fc->s_fs_info;
|
||||||
char *host_root = (char *)data;
|
char *tmp_root, *host_root = (char *)data;
|
||||||
|
|
||||||
/* NULL is printed as '(null)' by printf(): avoid that. */
|
/* NULL is printed as '(null)' by printf(): avoid that. */
|
||||||
if (host_root == NULL)
|
if (host_root == NULL)
|
||||||
host_root = "";
|
return 0;
|
||||||
|
|
||||||
fsi->host_root_path =
|
tmp_root = kasprintf(GFP_KERNEL, "%s%s", fsi->host_root_path, host_root);
|
||||||
kasprintf(GFP_KERNEL, "%s/%s", root_ino, host_root);
|
if (!tmp_root)
|
||||||
if (fsi->host_root_path == NULL)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
kfree(fsi->host_root_path);
|
||||||
|
fsi->host_root_path = tmp_root;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1049,6 +1051,11 @@ static int hostfs_init_fs_context(struct fs_context *fc)
|
|||||||
if (!fsi)
|
if (!fsi)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
fsi->host_root_path = kasprintf(GFP_KERNEL, "%s/", root_ino);
|
||||||
|
if (!fsi->host_root_path) {
|
||||||
|
kfree(fsi);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
fc->s_fs_info = fsi;
|
fc->s_fs_info = fsi;
|
||||||
fc->ops = &hostfs_context_ops;
|
fc->ops = &hostfs_context_ops;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
12
fs/inode.c
12
fs/inode.c
@ -1967,6 +1967,18 @@ retry:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(iput);
|
EXPORT_SYMBOL(iput);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iput_not_last - put an inode assuming this is not the last reference
|
||||||
|
* @inode: inode to put
|
||||||
|
*/
|
||||||
|
void iput_not_last(struct inode *inode)
|
||||||
|
{
|
||||||
|
VFS_BUG_ON_INODE(atomic_read(&inode->i_count) < 2, inode);
|
||||||
|
|
||||||
|
WARN_ON(atomic_sub_return(1, &inode->i_count) == 0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iput_not_last);
|
||||||
|
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
/**
|
/**
|
||||||
* bmap - find a block number in a file
|
* bmap - find a block number in a file
|
||||||
|
|||||||
@ -610,6 +610,11 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc)
|
|||||||
goto out_freesbi;
|
goto out_freesbi;
|
||||||
}
|
}
|
||||||
opt->blocksize = sb_min_blocksize(s, opt->blocksize);
|
opt->blocksize = sb_min_blocksize(s, opt->blocksize);
|
||||||
|
if (!opt->blocksize) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"ISOFS: unable to set blocksize\n");
|
||||||
|
goto out_freesbi;
|
||||||
|
}
|
||||||
|
|
||||||
sbi->s_high_sierra = 0; /* default is iso9660 */
|
sbi->s_high_sierra = 0; /* default is iso9660 */
|
||||||
sbi->s_session = opt->session;
|
sbi->s_session = opt->session;
|
||||||
|
|||||||
@ -132,16 +132,6 @@ EXPORT_SYMBOL_GPL(fs_kobj);
|
|||||||
*/
|
*/
|
||||||
__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
|
__cacheline_aligned_in_smp DEFINE_SEQLOCK(mount_lock);
|
||||||
|
|
||||||
static inline struct mnt_namespace *node_to_mnt_ns(const struct rb_node *node)
|
|
||||||
{
|
|
||||||
struct ns_common *ns;
|
|
||||||
|
|
||||||
if (!node)
|
|
||||||
return NULL;
|
|
||||||
ns = rb_entry(node, struct ns_common, ns_tree_node);
|
|
||||||
return container_of(ns, struct mnt_namespace, ns);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mnt_ns_release(struct mnt_namespace *ns)
|
static void mnt_ns_release(struct mnt_namespace *ns)
|
||||||
{
|
{
|
||||||
/* keep alive for {list,stat}mount() */
|
/* keep alive for {list,stat}mount() */
|
||||||
@ -151,7 +141,8 @@ static void mnt_ns_release(struct mnt_namespace *ns)
|
|||||||
kfree(ns);
|
kfree(ns);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, if (_T) mnt_ns_release(_T))
|
DEFINE_FREE(mnt_ns_release, struct mnt_namespace *,
|
||||||
|
if (!IS_ERR(_T)) mnt_ns_release(_T))
|
||||||
|
|
||||||
static void mnt_ns_release_rcu(struct rcu_head *rcu)
|
static void mnt_ns_release_rcu(struct rcu_head *rcu)
|
||||||
{
|
{
|
||||||
@ -5454,11 +5445,11 @@ static int statmount_string(struct kstatmount *s, u64 flag)
|
|||||||
ret = statmount_sb_source(s, seq);
|
ret = statmount_sb_source(s, seq);
|
||||||
break;
|
break;
|
||||||
case STATMOUNT_MNT_UIDMAP:
|
case STATMOUNT_MNT_UIDMAP:
|
||||||
sm->mnt_uidmap = start;
|
offp = &sm->mnt_uidmap;
|
||||||
ret = statmount_mnt_uidmap(s, seq);
|
ret = statmount_mnt_uidmap(s, seq);
|
||||||
break;
|
break;
|
||||||
case STATMOUNT_MNT_GIDMAP:
|
case STATMOUNT_MNT_GIDMAP:
|
||||||
sm->mnt_gidmap = start;
|
offp = &sm->mnt_gidmap;
|
||||||
ret = statmount_mnt_gidmap(s, seq);
|
ret = statmount_mnt_gidmap(s, seq);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -5736,7 +5727,7 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
|
|||||||
ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize);
|
ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (kreq->spare != 0)
|
if (kreq->mnt_ns_fd != 0 && kreq->mnt_ns_id)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
|
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
|
||||||
if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET)
|
if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET)
|
||||||
@ -5753,16 +5744,12 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq
|
|||||||
{
|
{
|
||||||
struct mnt_namespace *mnt_ns;
|
struct mnt_namespace *mnt_ns;
|
||||||
|
|
||||||
if (kreq->mnt_ns_id && kreq->spare)
|
if (kreq->mnt_ns_id) {
|
||||||
return ERR_PTR(-EINVAL);
|
mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id);
|
||||||
|
} else if (kreq->mnt_ns_fd) {
|
||||||
if (kreq->mnt_ns_id)
|
|
||||||
return lookup_mnt_ns(kreq->mnt_ns_id);
|
|
||||||
|
|
||||||
if (kreq->spare) {
|
|
||||||
struct ns_common *ns;
|
struct ns_common *ns;
|
||||||
|
|
||||||
CLASS(fd, f)(kreq->spare);
|
CLASS(fd, f)(kreq->mnt_ns_fd);
|
||||||
if (fd_empty(f))
|
if (fd_empty(f))
|
||||||
return ERR_PTR(-EBADF);
|
return ERR_PTR(-EBADF);
|
||||||
|
|
||||||
@ -5777,6 +5764,8 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq
|
|||||||
} else {
|
} else {
|
||||||
mnt_ns = current->nsproxy->mnt_ns;
|
mnt_ns = current->nsproxy->mnt_ns;
|
||||||
}
|
}
|
||||||
|
if (!mnt_ns)
|
||||||
|
return ERR_PTR(-ENOENT);
|
||||||
|
|
||||||
refcount_inc(&mnt_ns->passive);
|
refcount_inc(&mnt_ns->passive);
|
||||||
return mnt_ns;
|
return mnt_ns;
|
||||||
@ -5801,8 +5790,8 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ns = grab_requested_mnt_ns(&kreq);
|
ns = grab_requested_mnt_ns(&kreq);
|
||||||
if (!ns)
|
if (IS_ERR(ns))
|
||||||
return -ENOENT;
|
return PTR_ERR(ns);
|
||||||
|
|
||||||
if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
|
if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
|
||||||
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
|
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
|
||||||
@ -5912,8 +5901,8 @@ static void __free_klistmount_free(const struct klistmount *kls)
|
|||||||
static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *kreq,
|
static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *kreq,
|
||||||
size_t nr_mnt_ids)
|
size_t nr_mnt_ids)
|
||||||
{
|
{
|
||||||
|
|
||||||
u64 last_mnt_id = kreq->param;
|
u64 last_mnt_id = kreq->param;
|
||||||
|
struct mnt_namespace *ns;
|
||||||
|
|
||||||
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
|
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
|
||||||
if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET)
|
if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET)
|
||||||
@ -5927,9 +5916,10 @@ static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *
|
|||||||
if (!kls->kmnt_ids)
|
if (!kls->kmnt_ids)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
kls->ns = grab_requested_mnt_ns(kreq);
|
ns = grab_requested_mnt_ns(kreq);
|
||||||
if (!kls->ns)
|
if (IS_ERR(ns))
|
||||||
return -ENOENT;
|
return PTR_ERR(ns);
|
||||||
|
kls->ns = ns;
|
||||||
|
|
||||||
kls->mnt_parent_id = kreq->mnt_id;
|
kls->mnt_parent_id = kreq->mnt_id;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
13
fs/super.c
13
fs/super.c
@ -1183,11 +1183,14 @@ static inline bool get_active_super(struct super_block *sb)
|
|||||||
|
|
||||||
static const char *filesystems_freeze_ptr = "filesystems_freeze";
|
static const char *filesystems_freeze_ptr = "filesystems_freeze";
|
||||||
|
|
||||||
static void filesystems_freeze_callback(struct super_block *sb, void *unused)
|
static void filesystems_freeze_callback(struct super_block *sb, void *freeze_all_ptr)
|
||||||
{
|
{
|
||||||
if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super)
|
if (!sb->s_op->freeze_fs && !sb->s_op->freeze_super)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (freeze_all_ptr && !(sb->s_type->fs_flags & FS_POWER_FREEZE))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!get_active_super(sb))
|
if (!get_active_super(sb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1201,9 +1204,13 @@ static void filesystems_freeze_callback(struct super_block *sb, void *unused)
|
|||||||
deactivate_super(sb);
|
deactivate_super(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesystems_freeze(void)
|
void filesystems_freeze(bool freeze_all)
|
||||||
{
|
{
|
||||||
__iterate_supers(filesystems_freeze_callback, NULL,
|
void *freeze_all_ptr = NULL;
|
||||||
|
|
||||||
|
if (freeze_all)
|
||||||
|
freeze_all_ptr = &freeze_all;
|
||||||
|
__iterate_supers(filesystems_freeze_callback, freeze_all_ptr,
|
||||||
SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE);
|
SUPER_ITER_UNLOCKED | SUPER_ITER_REVERSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1693,7 +1693,10 @@ xfs_fs_fill_super(
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
sb_min_blocksize(sb, BBSIZE);
|
if (!sb_min_blocksize(sb, BBSIZE)) {
|
||||||
|
xfs_err(mp, "unable to set blocksize");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
sb->s_xattr = xfs_xattr_handlers;
|
sb->s_xattr = xfs_xattr_handlers;
|
||||||
sb->s_export_op = &xfs_export_operations;
|
sb->s_export_op = &xfs_export_operations;
|
||||||
#ifdef CONFIG_XFS_QUOTA
|
#ifdef CONFIG_XFS_QUOTA
|
||||||
|
|||||||
@ -2689,6 +2689,7 @@ struct file_system_type {
|
|||||||
#define FS_ALLOW_IDMAP 32 /* FS has been updated to handle vfs idmappings. */
|
#define FS_ALLOW_IDMAP 32 /* FS has been updated to handle vfs idmappings. */
|
||||||
#define FS_MGTIME 64 /* FS uses multigrain timestamps */
|
#define FS_MGTIME 64 /* FS uses multigrain timestamps */
|
||||||
#define FS_LBS 128 /* FS supports LBS */
|
#define FS_LBS 128 /* FS supports LBS */
|
||||||
|
#define FS_POWER_FREEZE 256 /* Always freeze on suspend/hibernate */
|
||||||
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
|
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
|
||||||
int (*init_fs_context)(struct fs_context *);
|
int (*init_fs_context)(struct fs_context *);
|
||||||
const struct fs_parameter_spec *parameters;
|
const struct fs_parameter_spec *parameters;
|
||||||
@ -2823,6 +2824,7 @@ extern int current_umask(void);
|
|||||||
|
|
||||||
extern void ihold(struct inode * inode);
|
extern void ihold(struct inode * inode);
|
||||||
extern void iput(struct inode *);
|
extern void iput(struct inode *);
|
||||||
|
void iput_not_last(struct inode *);
|
||||||
int inode_update_timestamps(struct inode *inode, int flags);
|
int inode_update_timestamps(struct inode *inode, int flags);
|
||||||
int generic_update_time(struct inode *, int);
|
int generic_update_time(struct inode *, int);
|
||||||
|
|
||||||
@ -3423,8 +3425,8 @@ static inline void remove_inode_hash(struct inode *inode)
|
|||||||
extern void inode_sb_list_add(struct inode *inode);
|
extern void inode_sb_list_add(struct inode *inode);
|
||||||
extern void inode_add_lru(struct inode *inode);
|
extern void inode_add_lru(struct inode *inode);
|
||||||
|
|
||||||
extern int sb_set_blocksize(struct super_block *, int);
|
int sb_set_blocksize(struct super_block *sb, int size);
|
||||||
extern int sb_min_blocksize(struct super_block *, int);
|
int __must_check sb_min_blocksize(struct super_block *sb, int size);
|
||||||
|
|
||||||
int generic_file_mmap(struct file *, struct vm_area_struct *);
|
int generic_file_mmap(struct file *, struct vm_area_struct *);
|
||||||
int generic_file_mmap_prepare(struct vm_area_desc *desc);
|
int generic_file_mmap_prepare(struct vm_area_desc *desc);
|
||||||
@ -3606,7 +3608,7 @@ extern void drop_super_exclusive(struct super_block *sb);
|
|||||||
extern void iterate_supers(void (*f)(struct super_block *, void *), void *arg);
|
extern void iterate_supers(void (*f)(struct super_block *, void *), void *arg);
|
||||||
extern void iterate_supers_type(struct file_system_type *,
|
extern void iterate_supers_type(struct file_system_type *,
|
||||||
void (*)(struct super_block *, void *), void *);
|
void (*)(struct super_block *, void *), void *);
|
||||||
void filesystems_freeze(void);
|
void filesystems_freeze(bool freeze_all);
|
||||||
void filesystems_thaw(void);
|
void filesystems_thaw(void);
|
||||||
|
|
||||||
extern int dcache_dir_open(struct inode *, struct file *);
|
extern int dcache_dir_open(struct inode *, struct file *);
|
||||||
|
|||||||
@ -197,7 +197,7 @@ struct statmount {
|
|||||||
*/
|
*/
|
||||||
struct mnt_id_req {
|
struct mnt_id_req {
|
||||||
__u32 size;
|
__u32 size;
|
||||||
__u32 spare;
|
__u32 mnt_ns_fd;
|
||||||
__u64 mnt_id;
|
__u64 mnt_id;
|
||||||
__u64 param;
|
__u64 param;
|
||||||
__u64 mnt_ns_id;
|
__u64 mnt_ns_id;
|
||||||
|
|||||||
@ -821,8 +821,7 @@ int hibernate(void)
|
|||||||
goto Restore;
|
goto Restore;
|
||||||
|
|
||||||
ksys_sync_helper();
|
ksys_sync_helper();
|
||||||
if (filesystem_freeze_enabled)
|
filesystems_freeze(filesystem_freeze_enabled);
|
||||||
filesystems_freeze();
|
|
||||||
|
|
||||||
error = freeze_processes();
|
error = freeze_processes();
|
||||||
if (error)
|
if (error)
|
||||||
@ -928,8 +927,7 @@ int hibernate_quiet_exec(int (*func)(void *data), void *data)
|
|||||||
if (error)
|
if (error)
|
||||||
goto restore;
|
goto restore;
|
||||||
|
|
||||||
if (filesystem_freeze_enabled)
|
filesystems_freeze(filesystem_freeze_enabled);
|
||||||
filesystems_freeze();
|
|
||||||
|
|
||||||
error = freeze_processes();
|
error = freeze_processes();
|
||||||
if (error)
|
if (error)
|
||||||
@ -1079,8 +1077,7 @@ static int software_resume(void)
|
|||||||
if (error)
|
if (error)
|
||||||
goto Restore;
|
goto Restore;
|
||||||
|
|
||||||
if (filesystem_freeze_enabled)
|
filesystems_freeze(filesystem_freeze_enabled);
|
||||||
filesystems_freeze();
|
|
||||||
|
|
||||||
pm_pr_dbg("Preparing processes for hibernation restore.\n");
|
pm_pr_dbg("Preparing processes for hibernation restore.\n");
|
||||||
error = freeze_processes();
|
error = freeze_processes();
|
||||||
|
|||||||
@ -375,8 +375,7 @@ static int suspend_prepare(suspend_state_t state)
|
|||||||
if (error)
|
if (error)
|
||||||
goto Restore;
|
goto Restore;
|
||||||
|
|
||||||
if (filesystem_freeze_enabled)
|
filesystems_freeze(filesystem_freeze_enabled);
|
||||||
filesystems_freeze();
|
|
||||||
trace_suspend_resume(TPS("freeze_processes"), 0, true);
|
trace_suspend_resume(TPS("freeze_processes"), 0, true);
|
||||||
error = suspend_freeze_processes();
|
error = suspend_freeze_processes();
|
||||||
trace_suspend_resume(TPS("freeze_processes"), 0, false);
|
trace_suspend_resume(TPS("freeze_processes"), 0, false);
|
||||||
|
|||||||
@ -25,7 +25,7 @@ static struct scx_sched __rcu *scx_root;
|
|||||||
* guarantee system safety. Maintain a dedicated task list which contains every
|
* guarantee system safety. Maintain a dedicated task list which contains every
|
||||||
* task between its fork and eventual free.
|
* task between its fork and eventual free.
|
||||||
*/
|
*/
|
||||||
static DEFINE_SPINLOCK(scx_tasks_lock);
|
static DEFINE_RAW_SPINLOCK(scx_tasks_lock);
|
||||||
static LIST_HEAD(scx_tasks);
|
static LIST_HEAD(scx_tasks);
|
||||||
|
|
||||||
/* ops enable/disable */
|
/* ops enable/disable */
|
||||||
@ -476,7 +476,7 @@ static void scx_task_iter_start(struct scx_task_iter *iter)
|
|||||||
BUILD_BUG_ON(__SCX_DSQ_ITER_ALL_FLAGS &
|
BUILD_BUG_ON(__SCX_DSQ_ITER_ALL_FLAGS &
|
||||||
((1U << __SCX_DSQ_LNODE_PRIV_SHIFT) - 1));
|
((1U << __SCX_DSQ_LNODE_PRIV_SHIFT) - 1));
|
||||||
|
|
||||||
spin_lock_irq(&scx_tasks_lock);
|
raw_spin_lock_irq(&scx_tasks_lock);
|
||||||
|
|
||||||
iter->cursor = (struct sched_ext_entity){ .flags = SCX_TASK_CURSOR };
|
iter->cursor = (struct sched_ext_entity){ .flags = SCX_TASK_CURSOR };
|
||||||
list_add(&iter->cursor.tasks_node, &scx_tasks);
|
list_add(&iter->cursor.tasks_node, &scx_tasks);
|
||||||
@ -507,14 +507,14 @@ static void scx_task_iter_unlock(struct scx_task_iter *iter)
|
|||||||
__scx_task_iter_rq_unlock(iter);
|
__scx_task_iter_rq_unlock(iter);
|
||||||
if (iter->list_locked) {
|
if (iter->list_locked) {
|
||||||
iter->list_locked = false;
|
iter->list_locked = false;
|
||||||
spin_unlock_irq(&scx_tasks_lock);
|
raw_spin_unlock_irq(&scx_tasks_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __scx_task_iter_maybe_relock(struct scx_task_iter *iter)
|
static void __scx_task_iter_maybe_relock(struct scx_task_iter *iter)
|
||||||
{
|
{
|
||||||
if (!iter->list_locked) {
|
if (!iter->list_locked) {
|
||||||
spin_lock_irq(&scx_tasks_lock);
|
raw_spin_lock_irq(&scx_tasks_lock);
|
||||||
iter->list_locked = true;
|
iter->list_locked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2940,9 +2940,9 @@ void scx_post_fork(struct task_struct *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irq(&scx_tasks_lock);
|
raw_spin_lock_irq(&scx_tasks_lock);
|
||||||
list_add_tail(&p->scx.tasks_node, &scx_tasks);
|
list_add_tail(&p->scx.tasks_node, &scx_tasks);
|
||||||
spin_unlock_irq(&scx_tasks_lock);
|
raw_spin_unlock_irq(&scx_tasks_lock);
|
||||||
|
|
||||||
percpu_up_read(&scx_fork_rwsem);
|
percpu_up_read(&scx_fork_rwsem);
|
||||||
}
|
}
|
||||||
@ -2966,9 +2966,9 @@ void sched_ext_free(struct task_struct *p)
|
|||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&scx_tasks_lock, flags);
|
raw_spin_lock_irqsave(&scx_tasks_lock, flags);
|
||||||
list_del_init(&p->scx.tasks_node);
|
list_del_init(&p->scx.tasks_node);
|
||||||
spin_unlock_irqrestore(&scx_tasks_lock, flags);
|
raw_spin_unlock_irqrestore(&scx_tasks_lock, flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @p is off scx_tasks and wholly ours. scx_enable()'s READY -> ENABLED
|
* @p is off scx_tasks and wholly ours. scx_enable()'s READY -> ENABLED
|
||||||
@ -4276,7 +4276,7 @@ static void scx_dump_state(struct scx_exit_info *ei, size_t dump_len)
|
|||||||
size_t avail, used;
|
size_t avail, used;
|
||||||
bool idle;
|
bool idle;
|
||||||
|
|
||||||
rq_lock(rq, &rf);
|
rq_lock_irqsave(rq, &rf);
|
||||||
|
|
||||||
idle = list_empty(&rq->scx.runnable_list) &&
|
idle = list_empty(&rq->scx.runnable_list) &&
|
||||||
rq->curr->sched_class == &idle_sched_class;
|
rq->curr->sched_class == &idle_sched_class;
|
||||||
@ -4345,7 +4345,7 @@ static void scx_dump_state(struct scx_exit_info *ei, size_t dump_len)
|
|||||||
list_for_each_entry(p, &rq->scx.runnable_list, scx.runnable_node)
|
list_for_each_entry(p, &rq->scx.runnable_list, scx.runnable_node)
|
||||||
scx_dump_task(&s, &dctx, p, ' ');
|
scx_dump_task(&s, &dctx, p, ' ');
|
||||||
next:
|
next:
|
||||||
rq_unlock(rq, &rf);
|
rq_unlock_irqrestore(rq, &rf);
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_newline(&s);
|
dump_newline(&s);
|
||||||
@ -5321,8 +5321,8 @@ void __init init_sched_ext_class(void)
|
|||||||
BUG_ON(!zalloc_cpumask_var_node(&rq->scx.cpus_to_kick_if_idle, GFP_KERNEL, n));
|
BUG_ON(!zalloc_cpumask_var_node(&rq->scx.cpus_to_kick_if_idle, GFP_KERNEL, n));
|
||||||
BUG_ON(!zalloc_cpumask_var_node(&rq->scx.cpus_to_preempt, GFP_KERNEL, n));
|
BUG_ON(!zalloc_cpumask_var_node(&rq->scx.cpus_to_preempt, GFP_KERNEL, n));
|
||||||
BUG_ON(!zalloc_cpumask_var_node(&rq->scx.cpus_to_wait, GFP_KERNEL, n));
|
BUG_ON(!zalloc_cpumask_var_node(&rq->scx.cpus_to_wait, GFP_KERNEL, n));
|
||||||
init_irq_work(&rq->scx.deferred_irq_work, deferred_irq_workfn);
|
rq->scx.deferred_irq_work = IRQ_WORK_INIT_HARD(deferred_irq_workfn);
|
||||||
init_irq_work(&rq->scx.kick_cpus_irq_work, kick_cpus_irq_workfn);
|
rq->scx.kick_cpus_irq_work = IRQ_WORK_INIT_HARD(kick_cpus_irq_workfn);
|
||||||
|
|
||||||
if (cpu_online(cpu))
|
if (cpu_online(cpu))
|
||||||
cpu_rq(cpu)->scx.flags |= SCX_RQ_ONLINE;
|
cpu_rq(cpu)->scx.flags |= SCX_RQ_ONLINE;
|
||||||
@ -6401,7 +6401,7 @@ __bpf_kfunc void scx_bpf_cpuperf_set(s32 cpu, u32 perf)
|
|||||||
|
|
||||||
guard(rcu)();
|
guard(rcu)();
|
||||||
|
|
||||||
sch = rcu_dereference(sch);
|
sch = rcu_dereference(scx_root);
|
||||||
if (unlikely(!sch))
|
if (unlikely(!sch))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
15
mm/shmem.c
15
mm/shmem.c
@ -131,8 +131,7 @@ struct shmem_options {
|
|||||||
#define SHMEM_SEEN_INODES 2
|
#define SHMEM_SEEN_INODES 2
|
||||||
#define SHMEM_SEEN_HUGE 4
|
#define SHMEM_SEEN_HUGE 4
|
||||||
#define SHMEM_SEEN_INUMS 8
|
#define SHMEM_SEEN_INUMS 8
|
||||||
#define SHMEM_SEEN_NOSWAP 16
|
#define SHMEM_SEEN_QUOTA 16
|
||||||
#define SHMEM_SEEN_QUOTA 32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||||
@ -4680,7 +4679,6 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
"Turning off swap in unprivileged tmpfs mounts unsupported");
|
"Turning off swap in unprivileged tmpfs mounts unsupported");
|
||||||
}
|
}
|
||||||
ctx->noswap = true;
|
ctx->noswap = true;
|
||||||
ctx->seen |= SHMEM_SEEN_NOSWAP;
|
|
||||||
break;
|
break;
|
||||||
case Opt_quota:
|
case Opt_quota:
|
||||||
if (fc->user_ns != &init_user_ns)
|
if (fc->user_ns != &init_user_ns)
|
||||||
@ -4830,14 +4828,15 @@ static int shmem_reconfigure(struct fs_context *fc)
|
|||||||
err = "Current inum too high to switch to 32-bit inums";
|
err = "Current inum too high to switch to 32-bit inums";
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if ((ctx->seen & SHMEM_SEEN_NOSWAP) && ctx->noswap && !sbinfo->noswap) {
|
|
||||||
|
/*
|
||||||
|
* "noswap" doesn't use fsparam_flag_no, i.e. there's no "swap"
|
||||||
|
* counterpart for (re-)enabling swap.
|
||||||
|
*/
|
||||||
|
if (ctx->noswap && !sbinfo->noswap) {
|
||||||
err = "Cannot disable swap on remount";
|
err = "Cannot disable swap on remount";
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!(ctx->seen & SHMEM_SEEN_NOSWAP) && !ctx->noswap && sbinfo->noswap) {
|
|
||||||
err = "Cannot enable swap on remount if it was disabled on first mount";
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->seen & SHMEM_SEEN_QUOTA &&
|
if (ctx->seen & SHMEM_SEEN_QUOTA &&
|
||||||
!sb_any_quota_loaded(fc->root->d_sb)) {
|
!sb_any_quota_loaded(fc->root->d_sb)) {
|
||||||
|
|||||||
@ -1335,11 +1335,10 @@ static void hook_sb_delete(struct super_block *const sb)
|
|||||||
* At this point, we own the ihold() reference that was
|
* At this point, we own the ihold() reference that was
|
||||||
* originally set up by get_inode_object() and the
|
* originally set up by get_inode_object() and the
|
||||||
* __iget() reference that we just set in this loop
|
* __iget() reference that we just set in this loop
|
||||||
* walk. Therefore the following call to iput() will
|
* walk. Therefore there are at least two references
|
||||||
* not sleep nor drop the inode because there is now at
|
* on the inode.
|
||||||
* least two references to it.
|
|
||||||
*/
|
*/
|
||||||
iput(inode);
|
iput_not_last(inode);
|
||||||
} else {
|
} else {
|
||||||
spin_unlock(&object->lock);
|
spin_unlock(&object->lock);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user