Merge 92477dd1fa ("Merge tag 's390-5.15-ebpf-jit-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux") into android-mainline
Steps on the way to 5.15-rc3 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ia35478d4c4a085bff847b8cd484bd3290f9529b8
This commit is contained in:
@@ -248,8 +248,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
|
||||
|
||||
#define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask) \
|
||||
({ \
|
||||
/* Branch instruction needs 6 bytes */ \
|
||||
int rel = (addrs[(i) + (off) + 1] - (addrs[(i) + 1] - 6)) / 2;\
|
||||
int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2; \
|
||||
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\
|
||||
REG_SET_SEEN(b1); \
|
||||
REG_SET_SEEN(b2); \
|
||||
@@ -761,10 +760,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4(0xb9080000, dst_reg, src_reg);
|
||||
break;
|
||||
case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */
|
||||
if (!imm)
|
||||
break;
|
||||
if (imm != 0) {
|
||||
/* alfi %dst,imm */
|
||||
EMIT6_IMM(0xc20b0000, dst_reg, imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */
|
||||
@@ -786,17 +785,22 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4(0xb9090000, dst_reg, src_reg);
|
||||
break;
|
||||
case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */
|
||||
if (!imm)
|
||||
break;
|
||||
if (imm != 0) {
|
||||
/* alfi %dst,-imm */
|
||||
EMIT6_IMM(0xc20b0000, dst_reg, -imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */
|
||||
if (!imm)
|
||||
break;
|
||||
if (imm == -0x80000000) {
|
||||
/* algfi %dst,0x80000000 */
|
||||
EMIT6_IMM(0xc20a0000, dst_reg, 0x80000000);
|
||||
} else {
|
||||
/* agfi %dst,-imm */
|
||||
EMIT6_IMM(0xc2080000, dst_reg, -imm);
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* BPF_MUL
|
||||
@@ -811,10 +815,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4(0xb90c0000, dst_reg, src_reg);
|
||||
break;
|
||||
case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */
|
||||
if (imm == 1)
|
||||
break;
|
||||
if (imm != 1) {
|
||||
/* msfi %r5,imm */
|
||||
EMIT6_IMM(0xc2010000, dst_reg, imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */
|
||||
@@ -867,6 +871,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
if (BPF_OP(insn->code) == BPF_MOD)
|
||||
/* lhgi %dst,0 */
|
||||
EMIT4_IMM(0xa7090000, dst_reg, 0);
|
||||
else
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
}
|
||||
/* lhi %w0,0 */
|
||||
@@ -999,10 +1005,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT4(0xb9820000, dst_reg, src_reg);
|
||||
break;
|
||||
case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */
|
||||
if (!imm)
|
||||
break;
|
||||
if (imm != 0) {
|
||||
/* xilf %dst,imm */
|
||||
EMIT6_IMM(0xc0070000, dst_reg, imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */
|
||||
@@ -1033,10 +1039,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0);
|
||||
break;
|
||||
case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */
|
||||
if (imm == 0)
|
||||
break;
|
||||
if (imm != 0) {
|
||||
/* sll %dst,imm(%r0) */
|
||||
EMIT4_DISP(0x89000000, dst_reg, REG_0, imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */
|
||||
@@ -1058,10 +1064,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0);
|
||||
break;
|
||||
case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */
|
||||
if (imm == 0)
|
||||
break;
|
||||
if (imm != 0) {
|
||||
/* srl %dst,imm(%r0) */
|
||||
EMIT4_DISP(0x88000000, dst_reg, REG_0, imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */
|
||||
@@ -1083,10 +1089,10 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
||||
EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0);
|
||||
break;
|
||||
case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */
|
||||
if (imm == 0)
|
||||
break;
|
||||
if (imm != 0) {
|
||||
/* sra %dst,imm(%r0) */
|
||||
EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm);
|
||||
}
|
||||
EMIT_ZERO(dst_reg);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */
|
||||
|
||||
@@ -19,8 +19,10 @@ void ioport_unmap(void __iomem *addr)
|
||||
EXPORT_SYMBOL(ioport_map);
|
||||
EXPORT_SYMBOL(ioport_unmap);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iounmap);
|
||||
#endif
|
||||
|
||||
@@ -57,7 +57,7 @@ nvkm_control_mthd_pstate_info(struct nvkm_control *ctrl, void *data, u32 size)
|
||||
args->v0.count = 0;
|
||||
args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
|
||||
args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
|
||||
args->v0.pwrsrc = -ENOSYS;
|
||||
args->v0.pwrsrc = -ENODEV;
|
||||
args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,5 +269,3 @@ module_exit(max14577_regulator_exit);
|
||||
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
|
||||
MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:max14577-regulator");
|
||||
MODULE_ALIAS("platform:max77836-regulator");
|
||||
|
||||
@@ -991,7 +991,7 @@ static const struct rpmh_vreg_init_data pm8009_1_vreg_data[] = {
|
||||
RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"),
|
||||
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"),
|
||||
RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"),
|
||||
RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"),
|
||||
RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo_lv, "vdd-l7"),
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -600,6 +600,12 @@ static int rockchip_spi_transfer_one(
|
||||
int ret;
|
||||
bool use_dma;
|
||||
|
||||
/* Zero length transfers won't trigger an interrupt on completion */
|
||||
if (!xfer->len) {
|
||||
spi_finalize_current_transfer(ctlr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
|
||||
(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY));
|
||||
|
||||
|
||||
@@ -204,9 +204,6 @@ struct tegra_slink_data {
|
||||
struct dma_async_tx_descriptor *tx_dma_desc;
|
||||
};
|
||||
|
||||
static int tegra_slink_runtime_suspend(struct device *dev);
|
||||
static int tegra_slink_runtime_resume(struct device *dev);
|
||||
|
||||
static inline u32 tegra_slink_readl(struct tegra_slink_data *tspi,
|
||||
unsigned long reg)
|
||||
{
|
||||
@@ -1185,7 +1182,8 @@ static int tegra_slink_resume(struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __maybe_unused tegra_slink_runtime_suspend(struct device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int tegra_slink_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct tegra_slink_data *tspi = spi_master_get_devdata(master);
|
||||
@@ -1197,7 +1195,7 @@ static int __maybe_unused tegra_slink_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused tegra_slink_runtime_resume(struct device *dev)
|
||||
static int tegra_slink_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct spi_master *master = dev_get_drvdata(dev);
|
||||
struct tegra_slink_data *tspi = spi_master_get_devdata(master);
|
||||
@@ -1210,6 +1208,7 @@ static int __maybe_unused tegra_slink_runtime_resume(struct device *dev)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct dev_pm_ops slink_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(tegra_slink_runtime_suspend,
|
||||
|
||||
@@ -20,6 +20,37 @@
|
||||
#include <linux/sched.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
* Handle invalidation of an mmap'd file. We invalidate all the PTEs referring
|
||||
* to the pages in this file's pagecache, forcing the kernel to go through
|
||||
* ->fault() or ->page_mkwrite() - at which point we can handle invalidation
|
||||
* more fully.
|
||||
*/
|
||||
void afs_invalidate_mmap_work(struct work_struct *work)
|
||||
{
|
||||
struct afs_vnode *vnode = container_of(work, struct afs_vnode, cb_work);
|
||||
|
||||
unmap_mapping_pages(vnode->vfs_inode.i_mapping, 0, 0, false);
|
||||
}
|
||||
|
||||
void afs_server_init_callback_work(struct work_struct *work)
|
||||
{
|
||||
struct afs_server *server = container_of(work, struct afs_server, initcb_work);
|
||||
struct afs_vnode *vnode;
|
||||
struct afs_cell *cell = server->cell;
|
||||
|
||||
down_read(&cell->fs_open_mmaps_lock);
|
||||
|
||||
list_for_each_entry(vnode, &cell->fs_open_mmaps, cb_mmap_link) {
|
||||
if (vnode->cb_server == server) {
|
||||
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
||||
queue_work(system_unbound_wq, &vnode->cb_work);
|
||||
}
|
||||
}
|
||||
|
||||
up_read(&cell->fs_open_mmaps_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow the fileserver to request callback state (re-)initialisation.
|
||||
* Unfortunately, UUIDs are not guaranteed unique.
|
||||
@@ -29,8 +60,11 @@ void afs_init_callback_state(struct afs_server *server)
|
||||
rcu_read_lock();
|
||||
do {
|
||||
server->cb_s_break++;
|
||||
server = rcu_dereference(server->uuid_next);
|
||||
} while (0);
|
||||
atomic_inc(&server->cell->fs_s_break);
|
||||
if (!list_empty(&server->cell->fs_open_mmaps))
|
||||
queue_work(system_unbound_wq, &server->initcb_work);
|
||||
|
||||
} while ((server = rcu_dereference(server->uuid_next)));
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
@@ -44,11 +78,17 @@ void __afs_break_callback(struct afs_vnode *vnode, enum afs_cb_break_reason reas
|
||||
clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
|
||||
if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
|
||||
vnode->cb_break++;
|
||||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
afs_clear_permits(vnode);
|
||||
|
||||
if (vnode->lock_state == AFS_VNODE_LOCK_WAITING_FOR_CB)
|
||||
afs_lock_may_be_available(vnode);
|
||||
|
||||
if (reason != afs_cb_break_for_deleted &&
|
||||
vnode->status.type == AFS_FTYPE_FILE &&
|
||||
atomic_read(&vnode->cb_nr_mmap))
|
||||
queue_work(system_unbound_wq, &vnode->cb_work);
|
||||
|
||||
trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, true);
|
||||
} else {
|
||||
trace_afs_cb_break(&vnode->fid, vnode->cb_break, reason, false);
|
||||
|
||||
@@ -166,6 +166,8 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
|
||||
seqlock_init(&cell->volume_lock);
|
||||
cell->fs_servers = RB_ROOT;
|
||||
seqlock_init(&cell->fs_lock);
|
||||
INIT_LIST_HEAD(&cell->fs_open_mmaps);
|
||||
init_rwsem(&cell->fs_open_mmaps_lock);
|
||||
rwlock_init(&cell->vl_servers_lock);
|
||||
cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS);
|
||||
|
||||
|
||||
57
fs/afs/dir.c
57
fs/afs/dir.c
@@ -1077,9 +1077,9 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
*/
|
||||
static int afs_d_revalidate_rcu(struct dentry *dentry)
|
||||
{
|
||||
struct afs_vnode *dvnode, *vnode;
|
||||
struct afs_vnode *dvnode;
|
||||
struct dentry *parent;
|
||||
struct inode *dir, *inode;
|
||||
struct inode *dir;
|
||||
long dir_version, de_version;
|
||||
|
||||
_enter("%p", dentry);
|
||||
@@ -1109,18 +1109,6 @@ static int afs_d_revalidate_rcu(struct dentry *dentry)
|
||||
return -ECHILD;
|
||||
}
|
||||
|
||||
/* Check to see if the vnode referred to by the dentry still
|
||||
* has a callback.
|
||||
*/
|
||||
if (d_really_is_positive(dentry)) {
|
||||
inode = d_inode_rcu(dentry);
|
||||
if (inode) {
|
||||
vnode = AFS_FS_I(inode);
|
||||
if (!afs_check_validity(vnode))
|
||||
return -ECHILD;
|
||||
}
|
||||
}
|
||||
|
||||
return 1; /* Still valid */
|
||||
}
|
||||
|
||||
@@ -1156,17 +1144,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
if (IS_ERR(key))
|
||||
key = NULL;
|
||||
|
||||
if (d_really_is_positive(dentry)) {
|
||||
inode = d_inode(dentry);
|
||||
if (inode) {
|
||||
vnode = AFS_FS_I(inode);
|
||||
afs_validate(vnode, key);
|
||||
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
|
||||
goto out_bad;
|
||||
}
|
||||
}
|
||||
|
||||
/* lock down the parent dentry so we can peer at it */
|
||||
/* Hold the parent dentry so we can peer at it */
|
||||
parent = dget_parent(dentry);
|
||||
dir = AFS_FS_I(d_inode(parent));
|
||||
|
||||
@@ -1175,7 +1153,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
|
||||
if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
|
||||
_debug("%pd: parent dir deleted", dentry);
|
||||
goto out_bad_parent;
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
/* We only need to invalidate a dentry if the server's copy changed
|
||||
@@ -1201,12 +1179,12 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
case 0:
|
||||
/* the filename maps to something */
|
||||
if (d_really_is_negative(dentry))
|
||||
goto out_bad_parent;
|
||||
goto not_found;
|
||||
inode = d_inode(dentry);
|
||||
if (is_bad_inode(inode)) {
|
||||
printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
|
||||
dentry);
|
||||
goto out_bad_parent;
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
vnode = AFS_FS_I(inode);
|
||||
@@ -1228,9 +1206,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
dentry, fid.unique,
|
||||
vnode->fid.unique,
|
||||
vnode->vfs_inode.i_generation);
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
set_bit(AFS_VNODE_DELETED, &vnode->flags);
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
goto not_found;
|
||||
}
|
||||
goto out_valid;
|
||||
@@ -1245,7 +1220,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
default:
|
||||
_debug("failed to iterate dir %pd: %d",
|
||||
parent, ret);
|
||||
goto out_bad_parent;
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
out_valid:
|
||||
@@ -1256,16 +1231,9 @@ out_valid_noupdate:
|
||||
_leave(" = 1 [valid]");
|
||||
return 1;
|
||||
|
||||
/* the dirent, if it exists, now points to a different vnode */
|
||||
not_found:
|
||||
spin_lock(&dentry->d_lock);
|
||||
dentry->d_flags |= DCACHE_NFSFS_RENAMED;
|
||||
spin_unlock(&dentry->d_lock);
|
||||
|
||||
out_bad_parent:
|
||||
_debug("dropping dentry %pd2", dentry);
|
||||
dput(parent);
|
||||
out_bad:
|
||||
key_put(key);
|
||||
|
||||
_leave(" = 0 [bad]");
|
||||
@@ -1792,6 +1760,10 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = afs_validate(vnode, op->key);
|
||||
if (ret < 0)
|
||||
goto error_op;
|
||||
|
||||
afs_op_set_vnode(op, 0, dvnode);
|
||||
afs_op_set_vnode(op, 1, vnode);
|
||||
op->file[0].dv_delta = 1;
|
||||
@@ -1805,6 +1777,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
|
||||
op->create.reason = afs_edit_dir_for_link;
|
||||
return afs_do_sync_operation(op);
|
||||
|
||||
error_op:
|
||||
afs_put_operation(op);
|
||||
error:
|
||||
d_drop(dentry);
|
||||
_leave(" = %d", ret);
|
||||
@@ -1989,6 +1963,11 @@ static int afs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
||||
if (IS_ERR(op))
|
||||
return PTR_ERR(op);
|
||||
|
||||
ret = afs_validate(vnode, op->key);
|
||||
op->error = ret;
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
afs_op_set_vnode(op, 0, orig_dvnode);
|
||||
afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */
|
||||
op->file[0].dv_delta = 1;
|
||||
|
||||
@@ -263,7 +263,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
|
||||
if (b == nr_blocks) {
|
||||
_debug("init %u", b);
|
||||
afs_edit_init_block(meta, block, b);
|
||||
i_size_write(&vnode->vfs_inode, (b + 1) * AFS_DIR_BLOCK_SIZE);
|
||||
afs_set_i_size(vnode, (b + 1) * AFS_DIR_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/* Only lower dir pages have a counter in the header. */
|
||||
@@ -296,7 +296,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
|
||||
new_directory:
|
||||
afs_edit_init_block(meta, meta, 0);
|
||||
i_size = AFS_DIR_BLOCK_SIZE;
|
||||
i_size_write(&vnode->vfs_inode, i_size);
|
||||
afs_set_i_size(vnode, i_size);
|
||||
slot = AFS_DIR_RESV_BLOCKS0;
|
||||
page = page0;
|
||||
block = meta;
|
||||
|
||||
@@ -24,12 +24,16 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
|
||||
static int afs_releasepage(struct page *page, gfp_t gfp_flags);
|
||||
|
||||
static void afs_readahead(struct readahead_control *ractl);
|
||||
static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter);
|
||||
static void afs_vm_open(struct vm_area_struct *area);
|
||||
static void afs_vm_close(struct vm_area_struct *area);
|
||||
static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff);
|
||||
|
||||
const struct file_operations afs_file_operations = {
|
||||
.open = afs_open,
|
||||
.release = afs_release,
|
||||
.llseek = generic_file_llseek,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.read_iter = afs_file_read_iter,
|
||||
.write_iter = afs_file_write,
|
||||
.mmap = afs_file_mmap,
|
||||
.splice_read = generic_file_splice_read,
|
||||
@@ -59,8 +63,10 @@ const struct address_space_operations afs_fs_aops = {
|
||||
};
|
||||
|
||||
static const struct vm_operations_struct afs_vm_ops = {
|
||||
.open = afs_vm_open,
|
||||
.close = afs_vm_close,
|
||||
.fault = filemap_fault,
|
||||
.map_pages = filemap_map_pages,
|
||||
.map_pages = afs_vm_map_pages,
|
||||
.page_mkwrite = afs_page_mkwrite,
|
||||
};
|
||||
|
||||
@@ -295,7 +301,7 @@ static void afs_req_issue_op(struct netfs_read_subrequest *subreq)
|
||||
fsreq->subreq = subreq;
|
||||
fsreq->pos = subreq->start + subreq->transferred;
|
||||
fsreq->len = subreq->len - subreq->transferred;
|
||||
fsreq->key = subreq->rreq->netfs_priv;
|
||||
fsreq->key = key_get(subreq->rreq->netfs_priv);
|
||||
fsreq->vnode = vnode;
|
||||
fsreq->iter = &fsreq->def_iter;
|
||||
|
||||
@@ -304,6 +310,7 @@ static void afs_req_issue_op(struct netfs_read_subrequest *subreq)
|
||||
fsreq->pos, fsreq->len);
|
||||
|
||||
afs_fetch_data(fsreq->vnode, fsreq);
|
||||
afs_put_read(fsreq);
|
||||
}
|
||||
|
||||
static int afs_symlink_readpage(struct page *page)
|
||||
@@ -490,15 +497,88 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void afs_add_open_mmap(struct afs_vnode *vnode)
|
||||
{
|
||||
if (atomic_inc_return(&vnode->cb_nr_mmap) == 1) {
|
||||
down_write(&vnode->volume->cell->fs_open_mmaps_lock);
|
||||
|
||||
list_add_tail(&vnode->cb_mmap_link,
|
||||
&vnode->volume->cell->fs_open_mmaps);
|
||||
|
||||
up_write(&vnode->volume->cell->fs_open_mmaps_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void afs_drop_open_mmap(struct afs_vnode *vnode)
|
||||
{
|
||||
if (!atomic_dec_and_test(&vnode->cb_nr_mmap))
|
||||
return;
|
||||
|
||||
down_write(&vnode->volume->cell->fs_open_mmaps_lock);
|
||||
|
||||
if (atomic_read(&vnode->cb_nr_mmap) == 0)
|
||||
list_del_init(&vnode->cb_mmap_link);
|
||||
|
||||
up_write(&vnode->volume->cell->fs_open_mmaps_lock);
|
||||
flush_work(&vnode->cb_work);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle setting up a memory mapping on an AFS file.
|
||||
*/
|
||||
static int afs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
|
||||
int ret;
|
||||
|
||||
afs_add_open_mmap(vnode);
|
||||
|
||||
ret = generic_file_mmap(file, vma);
|
||||
if (ret == 0)
|
||||
vma->vm_ops = &afs_vm_ops;
|
||||
else
|
||||
afs_drop_open_mmap(vnode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void afs_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
afs_add_open_mmap(AFS_FS_I(file_inode(vma->vm_file)));
|
||||
}
|
||||
|
||||
static void afs_vm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
afs_drop_open_mmap(AFS_FS_I(file_inode(vma->vm_file)));
|
||||
}
|
||||
|
||||
static vm_fault_t afs_vm_map_pages(struct vm_fault *vmf, pgoff_t start_pgoff, pgoff_t end_pgoff)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(vmf->vma->vm_file));
|
||||
struct afs_file *af = vmf->vma->vm_file->private_data;
|
||||
|
||||
switch (afs_validate(vnode, af->key)) {
|
||||
case 0:
|
||||
return filemap_map_pages(vmf, start_pgoff, end_pgoff);
|
||||
case -ENOMEM:
|
||||
return VM_FAULT_OOM;
|
||||
case -EINTR:
|
||||
case -ERESTARTSYS:
|
||||
return VM_FAULT_RETRY;
|
||||
case -ESTALE:
|
||||
default:
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t afs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp));
|
||||
struct afs_file *af = iocb->ki_filp->private_data;
|
||||
int ret;
|
||||
|
||||
ret = afs_validate(vnode, af->key);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return generic_file_read_iter(iocb, iter);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include "afs_fs.h"
|
||||
#include "internal.h"
|
||||
#include "protocol_afs.h"
|
||||
#include "protocol_yfs.h"
|
||||
|
||||
static unsigned int afs_fs_probe_fast_poll_interval = 30 * HZ;
|
||||
@@ -102,7 +103,7 @@ void afs_fileserver_probe_result(struct afs_call *call)
|
||||
struct afs_addr_list *alist = call->alist;
|
||||
struct afs_server *server = call->server;
|
||||
unsigned int index = call->addr_ix;
|
||||
unsigned int rtt_us = 0;
|
||||
unsigned int rtt_us = 0, cap0;
|
||||
int ret = call->error;
|
||||
|
||||
_enter("%pU,%u", &server->uuid, index);
|
||||
@@ -159,6 +160,11 @@ responded:
|
||||
clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
|
||||
alist->addrs[index].srx_service = call->service_id;
|
||||
}
|
||||
cap0 = ntohl(call->tmp);
|
||||
if (cap0 & AFS3_VICED_CAPABILITY_64BITFILES)
|
||||
set_bit(AFS_SERVER_FL_HAS_FS64, &server->flags);
|
||||
else
|
||||
clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags);
|
||||
}
|
||||
|
||||
if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) &&
|
||||
|
||||
@@ -456,9 +456,7 @@ void afs_fs_fetch_data(struct afs_operation *op)
|
||||
struct afs_read *req = op->fetch.req;
|
||||
__be32 *bp;
|
||||
|
||||
if (upper_32_bits(req->pos) ||
|
||||
upper_32_bits(req->len) ||
|
||||
upper_32_bits(req->pos + req->len))
|
||||
if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
|
||||
return afs_fs_fetch_data64(op);
|
||||
|
||||
_enter("");
|
||||
@@ -1113,9 +1111,7 @@ void afs_fs_store_data(struct afs_operation *op)
|
||||
(unsigned long long)op->store.pos,
|
||||
(unsigned long long)op->store.i_size);
|
||||
|
||||
if (upper_32_bits(op->store.pos) ||
|
||||
upper_32_bits(op->store.size) ||
|
||||
upper_32_bits(op->store.i_size))
|
||||
if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
|
||||
return afs_fs_store_data64(op);
|
||||
|
||||
call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData,
|
||||
@@ -1229,7 +1225,7 @@ static void afs_fs_setattr_size(struct afs_operation *op)
|
||||
key_serial(op->key), vp->fid.vid, vp->fid.vnode);
|
||||
|
||||
ASSERT(attr->ia_valid & ATTR_SIZE);
|
||||
if (upper_32_bits(attr->ia_size))
|
||||
if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
|
||||
return afs_fs_setattr_size64(op);
|
||||
|
||||
call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status,
|
||||
@@ -1657,20 +1653,33 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
|
||||
return ret;
|
||||
|
||||
count = ntohl(call->tmp);
|
||||
|
||||
call->count = count;
|
||||
call->count2 = count;
|
||||
afs_extract_discard(call, count * sizeof(__be32));
|
||||
if (count == 0) {
|
||||
call->unmarshall = 4;
|
||||
call->tmp = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Extract the first word of the capabilities to call->tmp */
|
||||
afs_extract_to_tmp(call);
|
||||
call->unmarshall++;
|
||||
fallthrough;
|
||||
|
||||
/* Extract capabilities words */
|
||||
case 2:
|
||||
ret = afs_extract_data(call, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* TODO: Examine capabilities */
|
||||
afs_extract_discard(call, (count - 1) * sizeof(__be32));
|
||||
call->unmarshall++;
|
||||
fallthrough;
|
||||
|
||||
/* Extract remaining capabilities words */
|
||||
case 3:
|
||||
ret = afs_extract_data(call, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
call->unmarshall++;
|
||||
break;
|
||||
|
||||
@@ -53,16 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the file size and block count. Estimate the number of 512 bytes blocks
|
||||
* used, rounded up to nearest 1K for consistency with other AFS clients.
|
||||
*/
|
||||
static void afs_set_i_size(struct afs_vnode *vnode, u64 size)
|
||||
{
|
||||
i_size_write(&vnode->vfs_inode, size);
|
||||
vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise an inode from the vnode status.
|
||||
*/
|
||||
@@ -587,22 +577,32 @@ static void afs_zap_data(struct afs_vnode *vnode)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the server reinit counter for a vnode's current server.
|
||||
* Check to see if we have a server currently serving this volume and that it
|
||||
* hasn't been reinitialised or dropped from the list.
|
||||
*/
|
||||
static bool afs_get_s_break_rcu(struct afs_vnode *vnode, unsigned int *_s_break)
|
||||
static bool afs_check_server_good(struct afs_vnode *vnode)
|
||||
{
|
||||
struct afs_server_list *slist = rcu_dereference(vnode->volume->servers);
|
||||
struct afs_server_list *slist;
|
||||
struct afs_server *server;
|
||||
bool good;
|
||||
int i;
|
||||
|
||||
if (vnode->cb_fs_s_break == atomic_read(&vnode->volume->cell->fs_s_break))
|
||||
return true;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
slist = rcu_dereference(vnode->volume->servers);
|
||||
for (i = 0; i < slist->nr_servers; i++) {
|
||||
server = slist->servers[i].server;
|
||||
if (server == vnode->cb_server) {
|
||||
*_s_break = READ_ONCE(server->cb_s_break);
|
||||
return true;
|
||||
good = (vnode->cb_s_break == server->cb_s_break);
|
||||
rcu_read_unlock();
|
||||
return good;
|
||||
}
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -611,57 +611,46 @@ static bool afs_get_s_break_rcu(struct afs_vnode *vnode, unsigned int *_s_break)
|
||||
*/
|
||||
bool afs_check_validity(struct afs_vnode *vnode)
|
||||
{
|
||||
struct afs_volume *volume = vnode->volume;
|
||||
enum afs_cb_break_reason need_clear = afs_cb_break_no_break;
|
||||
time64_t now = ktime_get_real_seconds();
|
||||
bool valid;
|
||||
unsigned int cb_break, cb_s_break, cb_v_break;
|
||||
unsigned int cb_break;
|
||||
int seq = 0;
|
||||
|
||||
do {
|
||||
read_seqbegin_or_lock(&vnode->cb_lock, &seq);
|
||||
cb_v_break = READ_ONCE(volume->cb_v_break);
|
||||
cb_break = vnode->cb_break;
|
||||
|
||||
if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) &&
|
||||
afs_get_s_break_rcu(vnode, &cb_s_break)) {
|
||||
if (vnode->cb_s_break != cb_s_break ||
|
||||
vnode->cb_v_break != cb_v_break) {
|
||||
vnode->cb_s_break = cb_s_break;
|
||||
vnode->cb_v_break = cb_v_break;
|
||||
need_clear = afs_cb_break_for_vsbreak;
|
||||
valid = false;
|
||||
} else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
|
||||
if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
|
||||
if (vnode->cb_v_break != vnode->volume->cb_v_break)
|
||||
need_clear = afs_cb_break_for_v_break;
|
||||
else if (!afs_check_server_good(vnode))
|
||||
need_clear = afs_cb_break_for_s_reinit;
|
||||
else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
|
||||
need_clear = afs_cb_break_for_zap;
|
||||
valid = false;
|
||||
} else if (vnode->cb_expires_at - 10 <= now) {
|
||||
else if (vnode->cb_expires_at - 10 <= now)
|
||||
need_clear = afs_cb_break_for_lapsed;
|
||||
valid = false;
|
||||
} else {
|
||||
valid = true;
|
||||
}
|
||||
} else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
|
||||
valid = true;
|
||||
;
|
||||
} else {
|
||||
vnode->cb_v_break = cb_v_break;
|
||||
valid = false;
|
||||
need_clear = afs_cb_break_no_promise;
|
||||
}
|
||||
|
||||
} while (need_seqretry(&vnode->cb_lock, seq));
|
||||
|
||||
done_seqretry(&vnode->cb_lock, seq);
|
||||
|
||||
if (need_clear != afs_cb_break_no_break) {
|
||||
if (need_clear == afs_cb_break_no_break)
|
||||
return true;
|
||||
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
if (cb_break == vnode->cb_break)
|
||||
if (need_clear == afs_cb_break_no_promise)
|
||||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
else if (cb_break == vnode->cb_break)
|
||||
__afs_break_callback(vnode, need_clear);
|
||||
else
|
||||
trace_afs_cb_miss(&vnode->fid, need_clear);
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -675,21 +664,20 @@ bool afs_check_validity(struct afs_vnode *vnode)
|
||||
*/
|
||||
int afs_validate(struct afs_vnode *vnode, struct key *key)
|
||||
{
|
||||
bool valid;
|
||||
int ret;
|
||||
|
||||
_enter("{v={%llx:%llu} fl=%lx},%x",
|
||||
vnode->fid.vid, vnode->fid.vnode, vnode->flags,
|
||||
key_serial(key));
|
||||
|
||||
rcu_read_lock();
|
||||
valid = afs_check_validity(vnode);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
|
||||
if (unlikely(test_bit(AFS_VNODE_DELETED, &vnode->flags))) {
|
||||
if (vnode->vfs_inode.i_nlink)
|
||||
clear_nlink(&vnode->vfs_inode);
|
||||
goto valid;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags) &&
|
||||
afs_check_validity(vnode))
|
||||
goto valid;
|
||||
|
||||
down_write(&vnode->validate_lock);
|
||||
|
||||
@@ -390,6 +390,9 @@ struct afs_cell {
|
||||
/* Active fileserver interaction state. */
|
||||
struct rb_root fs_servers; /* afs_server (by server UUID) */
|
||||
seqlock_t fs_lock; /* For fs_servers */
|
||||
struct rw_semaphore fs_open_mmaps_lock;
|
||||
struct list_head fs_open_mmaps; /* List of vnodes that are mmapped */
|
||||
atomic_t fs_s_break; /* Counter of CB.InitCallBackState messages */
|
||||
|
||||
/* VL server list. */
|
||||
rwlock_t vl_servers_lock; /* Lock on vl_servers */
|
||||
@@ -503,6 +506,7 @@ struct afs_server {
|
||||
struct hlist_node addr4_link; /* Link in net->fs_addresses4 */
|
||||
struct hlist_node addr6_link; /* Link in net->fs_addresses6 */
|
||||
struct hlist_node proc_link; /* Link in net->fs_proc */
|
||||
struct work_struct initcb_work; /* Work for CB.InitCallBackState* */
|
||||
struct afs_server *gc_next; /* Next server in manager's list */
|
||||
time64_t unuse_time; /* Time at which last unused */
|
||||
unsigned long flags;
|
||||
@@ -516,6 +520,7 @@ struct afs_server {
|
||||
#define AFS_SERVER_FL_IS_YFS 16 /* Server is YFS not AFS */
|
||||
#define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */
|
||||
#define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */
|
||||
#define AFS_SERVER_FL_HAS_FS64 19 /* Fileserver supports FS.{Fetch,Store}Data64 */
|
||||
atomic_t ref; /* Object refcount */
|
||||
atomic_t active; /* Active user count */
|
||||
u32 addr_version; /* Address list version */
|
||||
@@ -657,7 +662,11 @@ struct afs_vnode {
|
||||
afs_lock_type_t lock_type : 8;
|
||||
|
||||
/* outstanding callback notification on this file */
|
||||
struct work_struct cb_work; /* Work for mmap'd files */
|
||||
struct list_head cb_mmap_link; /* Link in cell->fs_open_mmaps */
|
||||
void *cb_server; /* Server with callback/filelock */
|
||||
atomic_t cb_nr_mmap; /* Number of mmaps */
|
||||
unsigned int cb_fs_s_break; /* Mass server break counter (cell->fs_s_break) */
|
||||
unsigned int cb_s_break; /* Mass break counter on ->server */
|
||||
unsigned int cb_v_break; /* Mass break counter on ->volume */
|
||||
unsigned int cb_break; /* Break counter on vnode */
|
||||
@@ -965,6 +974,8 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def;
|
||||
/*
|
||||
* callback.c
|
||||
*/
|
||||
extern void afs_invalidate_mmap_work(struct work_struct *);
|
||||
extern void afs_server_init_callback_work(struct work_struct *work);
|
||||
extern void afs_init_callback_state(struct afs_server *);
|
||||
extern void __afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason);
|
||||
extern void afs_break_callback(struct afs_vnode *, enum afs_cb_break_reason);
|
||||
@@ -1585,6 +1596,16 @@ static inline void afs_update_dentry_version(struct afs_operation *op,
|
||||
(void *)(unsigned long)dir_vp->scb.status.data_version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the file size and block count. Estimate the number of 512 bytes blocks
|
||||
* used, rounded up to nearest 1K for consistency with other AFS clients.
|
||||
*/
|
||||
static inline void afs_set_i_size(struct afs_vnode *vnode, u64 size)
|
||||
{
|
||||
i_size_write(&vnode->vfs_inode, size);
|
||||
vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a conflicting operation on a directory that we just unlinked from.
|
||||
* If someone managed to sneak a link or an unlink in on the file we just
|
||||
|
||||
15
fs/afs/protocol_afs.h
Normal file
15
fs/afs/protocol_afs.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* AFS protocol bits
|
||||
*
|
||||
* Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*/
|
||||
|
||||
|
||||
#define AFSCAPABILITIESMAX 196 /* Maximum number of words in a capability set */
|
||||
|
||||
/* AFS3 Fileserver capabilities word 0 */
|
||||
#define AFS3_VICED_CAPABILITY_ERRORTRANS 0x0001 /* Uses UAE errors */
|
||||
#define AFS3_VICED_CAPABILITY_64BITFILES 0x0002 /* FetchData64 & StoreData64 supported */
|
||||
#define AFS3_VICED_CAPABILITY_WRITELOCKACL 0x0004 /* Can lock a file even without lock perm */
|
||||
#define AFS3_VICED_CAPABILITY_SANEACLS 0x0008 /* ACLs reviewed for sanity - don't use */
|
||||
@@ -168,3 +168,9 @@ enum yfs_lock_type {
|
||||
yfs_LockMandatoryWrite = 0x101,
|
||||
yfs_LockMandatoryExtend = 0x102,
|
||||
};
|
||||
|
||||
/* RXYFS Viced Capability Flags */
|
||||
#define YFS_VICED_CAPABILITY_ERRORTRANS 0x0001 /* Deprecated v0.195 */
|
||||
#define YFS_VICED_CAPABILITY_64BITFILES 0x0002 /* Deprecated v0.195 */
|
||||
#define YFS_VICED_CAPABILITY_WRITELOCKACL 0x0004 /* Can lock a file even without lock perm */
|
||||
#define YFS_VICED_CAPABILITY_SANEACLS 0x0008 /* Deprecated v0.195 */
|
||||
|
||||
@@ -374,6 +374,7 @@ selected_server:
|
||||
if (vnode->cb_server != server) {
|
||||
vnode->cb_server = server;
|
||||
vnode->cb_s_break = server->cb_s_break;
|
||||
vnode->cb_fs_s_break = atomic_read(&server->cell->fs_s_break);
|
||||
vnode->cb_v_break = vnode->volume->cb_v_break;
|
||||
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
|
||||
}
|
||||
|
||||
@@ -235,6 +235,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
|
||||
server->addr_version = alist->version;
|
||||
server->uuid = *uuid;
|
||||
rwlock_init(&server->fs_lock);
|
||||
INIT_WORK(&server->initcb_work, afs_server_init_callback_work);
|
||||
init_waitqueue_head(&server->probe_wq);
|
||||
INIT_LIST_HEAD(&server->probe_link);
|
||||
spin_lock_init(&server->probe_lock);
|
||||
@@ -467,6 +468,7 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
|
||||
if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
|
||||
afs_give_up_callbacks(net, server);
|
||||
|
||||
flush_work(&server->initcb_work);
|
||||
afs_put_server(net, server, afs_server_trace_destroy);
|
||||
}
|
||||
|
||||
|
||||
@@ -698,6 +698,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
|
||||
vnode->lock_state = AFS_VNODE_LOCK_NONE;
|
||||
|
||||
init_rwsem(&vnode->rmdir_lock);
|
||||
INIT_WORK(&vnode->cb_work, afs_invalidate_mmap_work);
|
||||
|
||||
_leave(" = %p", &vnode->vfs_inode);
|
||||
return &vnode->vfs_inode;
|
||||
|
||||
@@ -137,7 +137,7 @@ int afs_write_end(struct file *file, struct address_space *mapping,
|
||||
write_seqlock(&vnode->cb_lock);
|
||||
i_size = i_size_read(&vnode->vfs_inode);
|
||||
if (maybe_i_size > i_size)
|
||||
i_size_write(&vnode->vfs_inode, maybe_i_size);
|
||||
afs_set_i_size(vnode, maybe_i_size);
|
||||
write_sequnlock(&vnode->cb_lock);
|
||||
}
|
||||
|
||||
@@ -471,13 +471,18 @@ static void afs_extend_writeback(struct address_space *mapping,
|
||||
}
|
||||
|
||||
/* Has the page moved or been split? */
|
||||
if (unlikely(page != xas_reload(&xas)))
|
||||
if (unlikely(page != xas_reload(&xas))) {
|
||||
put_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!trylock_page(page))
|
||||
if (!trylock_page(page)) {
|
||||
put_page(page);
|
||||
break;
|
||||
}
|
||||
if (!PageDirty(page) || PageWriteback(page)) {
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -487,6 +492,7 @@ static void afs_extend_writeback(struct address_space *mapping,
|
||||
t = afs_page_dirty_to(page, priv);
|
||||
if (f != 0 && !new_content) {
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -801,6 +807,7 @@ int afs_writepages(struct address_space *mapping,
|
||||
ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(iocb->ki_filp));
|
||||
struct afs_file *af = iocb->ki_filp->private_data;
|
||||
ssize_t result;
|
||||
size_t count = iov_iter_count(from);
|
||||
|
||||
@@ -816,6 +823,10 @@ ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
result = afs_validate(vnode, af->key);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
result = generic_file_write_iter(iocb, from);
|
||||
|
||||
_leave(" = %zd", result);
|
||||
@@ -829,13 +840,18 @@ ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from)
|
||||
*/
|
||||
int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
struct afs_vnode *vnode = AFS_FS_I(inode);
|
||||
struct afs_vnode *vnode = AFS_FS_I(file_inode(file));
|
||||
struct afs_file *af = file->private_data;
|
||||
int ret;
|
||||
|
||||
_enter("{%llx:%llu},{n=%pD},%d",
|
||||
vnode->fid.vid, vnode->fid.vnode, file,
|
||||
datasync);
|
||||
|
||||
ret = afs_validate(vnode, af->key);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return file_write_and_wait_range(file, start, end);
|
||||
}
|
||||
|
||||
@@ -849,11 +865,14 @@ vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
|
||||
struct file *file = vmf->vma->vm_file;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct afs_vnode *vnode = AFS_FS_I(inode);
|
||||
struct afs_file *af = file->private_data;
|
||||
unsigned long priv;
|
||||
vm_fault_t ret = VM_FAULT_RETRY;
|
||||
|
||||
_enter("{{%llx:%llu}},{%lx}", vnode->fid.vid, vnode->fid.vnode, page->index);
|
||||
|
||||
afs_validate(vnode, af->key);
|
||||
|
||||
sb_start_pagefault(inode->i_sb);
|
||||
|
||||
/* Wait for the page to be written to the cache before we allow it to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/cache.c - CIFS filesystem cache index structure definitions
|
||||
* CIFS filesystem cache index structure definitions
|
||||
*
|
||||
* Copyright (c) 2010 Novell, Inc.
|
||||
* Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* fs/cifs_debug.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2000,2005
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifs_fs_sb.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2004
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifs_ioctl.h
|
||||
*
|
||||
* Structure definitions for io control for cifs/smb3
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/cifs_spnego.c -- SPNEGO upcall management for CIFS
|
||||
* SPNEGO upcall management for CIFS
|
||||
*
|
||||
* Copyright (c) 2007 Red Hat, Inc.
|
||||
* Author(s): Jeff Layton (jlayton@redhat.com)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifs_spnego.h -- SPNEGO upcall management for CIFS
|
||||
* SPNEGO upcall management for CIFS
|
||||
*
|
||||
* Copyright (c) 2007 Red Hat, Inc.
|
||||
* Author(s): Jeff Layton (jlayton@redhat.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* fs/cifs/cifs_unicode.c
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2000,2009
|
||||
* Modified by Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/cifsacl.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2007,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifsacl.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/cifsencrypt.c
|
||||
*
|
||||
* Encryption and hashing operations relating to NTLM, NTLMv2. See MS-NLMP
|
||||
* for more detailed information
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/cifsfs.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifsfs.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002, 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifsglob.h
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
@@ -1400,6 +1399,7 @@ struct cifsInodeInfo {
|
||||
#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
|
||||
#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
|
||||
#define CIFS_INO_MODIFIED_ATTR (6) /* Indicate change in mtime/ctime */
|
||||
#define CIFS_INO_CLOSE_ON_LOCK (7) /* Not to defer the close when lock is set */
|
||||
unsigned long flags;
|
||||
spinlock_t writers_lock;
|
||||
unsigned int writers; /* Number of writers on this inode */
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifspdu.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2009
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/cifsproto.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
@@ -268,6 +267,9 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
|
||||
|
||||
extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
|
||||
|
||||
extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
|
||||
const char *path);
|
||||
|
||||
extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx);
|
||||
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
|
||||
int from_reconnect);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/cifssmb.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2010
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/connect.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2011
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
@@ -1090,7 +1089,7 @@ next_pdu:
|
||||
module_put_and_exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Returns true if srcaddr isn't specified and rhs isn't specified, or
|
||||
* if srcaddr is specified and matches the IP address of the rhs argument
|
||||
*/
|
||||
@@ -1550,6 +1549,9 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||
|
||||
/**
|
||||
* cifs_setup_ipc - helper to setup the IPC tcon for the session
|
||||
* @ses: smb session to issue the request on
|
||||
* @ctx: the superblock configuration context to use for building the
|
||||
* new tree connection for the IPC (interprocess communication RPC)
|
||||
*
|
||||
* A new IPC connection is made and stored in the session
|
||||
* tcon_ipc. The IPC tcon has the same lifetime as the session.
|
||||
@@ -1605,6 +1607,7 @@ out:
|
||||
|
||||
/**
|
||||
* cifs_free_ipc - helper to release the session IPC tcon
|
||||
* @ses: smb session to unmount the IPC from
|
||||
*
|
||||
* Needs to be called everytime a session is destroyed.
|
||||
*
|
||||
@@ -1855,6 +1858,8 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
|
||||
|
||||
/**
|
||||
* cifs_get_smb_ses - get a session matching @ctx data from @server
|
||||
* @server: server to setup the session to
|
||||
* @ctx: superblock configuration context to use to setup the session
|
||||
*
|
||||
* This function assumes it is being called from cifs_mount() where we
|
||||
* already got a server reference (server refcount +1). See
|
||||
@@ -2065,6 +2070,8 @@ cifs_put_tcon(struct cifs_tcon *tcon)
|
||||
|
||||
/**
|
||||
* cifs_get_tcon - get a tcon matching @ctx data from @ses
|
||||
* @ses: smb session to issue the request on
|
||||
* @ctx: the superblock configuration context to use for building the
|
||||
*
|
||||
* - tcon refcount is the number of mount points using the tcon.
|
||||
* - ses refcount is the number of tcon using the session.
|
||||
@@ -3030,7 +3037,7 @@ build_unc_path_to_root(const struct smb3_fs_context *ctx,
|
||||
return full_path;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
|
||||
*
|
||||
* If a referral is found, cifs_sb->ctx->mount_options will be (re-)allocated
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/dir.c
|
||||
*
|
||||
* vfs operations that deal with dentries
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/dns_resolve.c
|
||||
*
|
||||
* Copyright (c) 2007 Igor Mammedov
|
||||
* Author(s): Igor Mammedov (niallain@gmail.com)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/dns_resolve.h -- DNS Resolver upcall management for CIFS DFS
|
||||
* DNS Resolver upcall management for CIFS DFS
|
||||
* Handles host name to IP address resolution
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2008
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/export.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/file.c
|
||||
*
|
||||
* vfs operations that deal with files
|
||||
*
|
||||
@@ -883,6 +882,7 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||
dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
|
||||
if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
|
||||
cinode->lease_granted &&
|
||||
!test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
|
||||
dclose) {
|
||||
if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
|
||||
inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||
@@ -1865,6 +1865,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
|
||||
cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
|
||||
tcon->ses->server);
|
||||
cifs_sb = CIFS_FILE_SB(file);
|
||||
set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags);
|
||||
|
||||
if (cap_unix(tcon->ses) &&
|
||||
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/fscache.c - CIFS filesystem cache interface
|
||||
* CIFS filesystem cache interface
|
||||
*
|
||||
* Copyright (c) 2010 Novell, Inc.
|
||||
* Author(s): Suresh Jayaraman <sjayaraman@suse.de>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/fscache.h - CIFS filesystem cache interface definitions
|
||||
* CIFS filesystem cache interface definitions
|
||||
*
|
||||
* Copyright (c) 2010 Novell, Inc.
|
||||
* Authors(s): Suresh Jayaraman (sjayaraman@suse.de>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/inode.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2010
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
@@ -1625,7 +1624,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
goto unlink_out;
|
||||
}
|
||||
|
||||
cifs_close_deferred_file(CIFS_I(inode));
|
||||
cifs_close_deferred_file_under_dentry(tcon, full_path);
|
||||
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
||||
rc = CIFSPOSIXDelFile(xid, tcon, full_path,
|
||||
@@ -2114,9 +2113,9 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
|
||||
goto cifs_rename_exit;
|
||||
}
|
||||
|
||||
cifs_close_deferred_file(CIFS_I(d_inode(source_dentry)));
|
||||
cifs_close_deferred_file_under_dentry(tcon, from_name);
|
||||
if (d_inode(target_dentry) != NULL)
|
||||
cifs_close_deferred_file(CIFS_I(d_inode(target_dentry)));
|
||||
cifs_close_deferred_file_under_dentry(tcon, to_name);
|
||||
|
||||
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
|
||||
to_name);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/ioctl.c
|
||||
*
|
||||
* vfs operations that deal with io control
|
||||
*
|
||||
@@ -359,7 +358,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
||||
if (pSMBFile == NULL)
|
||||
break;
|
||||
tcon = tlink_tcon(pSMBFile->tlink);
|
||||
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||
/* caps = le64_to_cpu(tcon->fsUnixInfo.Capability); */
|
||||
|
||||
if (get_user(ExtAttrBits, (int __user *)arg)) {
|
||||
rc = -EFAULT;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/link.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/misc.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
@@ -736,7 +735,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
|
||||
if (cancel_delayed_work(&cfile->deferred)) {
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
continue;
|
||||
break;
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
@@ -767,7 +766,7 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
||||
if (cancel_delayed_work(&cfile->deferred)) {
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
continue;
|
||||
break;
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
@@ -781,6 +780,43 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
|
||||
kfree(tmp_list);
|
||||
}
|
||||
}
|
||||
void
|
||||
cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
|
||||
{
|
||||
struct cifsFileInfo *cfile;
|
||||
struct list_head *tmp;
|
||||
struct file_list *tmp_list, *tmp_next_list;
|
||||
struct list_head file_head;
|
||||
void *page;
|
||||
const char *full_path;
|
||||
|
||||
INIT_LIST_HEAD(&file_head);
|
||||
page = alloc_dentry_path();
|
||||
spin_lock(&tcon->open_file_lock);
|
||||
list_for_each(tmp, &tcon->openFileList) {
|
||||
cfile = list_entry(tmp, struct cifsFileInfo, tlist);
|
||||
full_path = build_path_from_dentry(cfile->dentry, page);
|
||||
if (strstr(full_path, path)) {
|
||||
if (delayed_work_pending(&cfile->deferred)) {
|
||||
if (cancel_delayed_work(&cfile->deferred)) {
|
||||
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
|
||||
if (tmp_list == NULL)
|
||||
break;
|
||||
tmp_list->cfile = cfile;
|
||||
list_add_tail(&tmp_list->list, &file_head);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
|
||||
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
|
||||
_cifsFileInfo_put(tmp_list->cfile, true, false);
|
||||
list_del(&tmp_list->list);
|
||||
kfree(tmp_list);
|
||||
}
|
||||
free_dentry_path(page);
|
||||
}
|
||||
|
||||
/* parses DFS refferal V3 structure
|
||||
* caller is responsible for freeing target_nodes
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* fs/cifs/netmisc.c
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/ntlmssp.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/readdir.c
|
||||
*
|
||||
* Directory search handling
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/rfc1002pdu.h
|
||||
*
|
||||
* Protocol Data Unit definitions for RFC 1001/1002 support
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/sess.c
|
||||
*
|
||||
* SMB/CIFS session setup handling routines
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/smb2file.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002, 2011
|
||||
* Author(s): Steve French (sfrench@us.ibm.com),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/smb2glob.h
|
||||
*
|
||||
* Definitions for various global variables and structures
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/smb2inode.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/smb2misc.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2011
|
||||
* Etersoft, 2012
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/smb2pdu.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2009, 2013
|
||||
* Etersoft, 2012
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/smb2pdu.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2009, 2013
|
||||
* Etersoft, 2012
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/smb2proto.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/smb2status.h
|
||||
*
|
||||
* SMB2 Status code (network error) definitions
|
||||
* Definitions are from MS-ERREF
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/smb2transport.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002, 2011
|
||||
* Etersoft, 2012
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
/*
|
||||
* fs/cifs/smberr.h
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2004
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/transport.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2002,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* fs/cifs/winucase.c
|
||||
*
|
||||
* Copyright (c) Jeffrey Layton <jlayton@redhat.com>, 2013
|
||||
*
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1
|
||||
/*
|
||||
* fs/cifs/xattr.c
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2003, 2007
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -191,19 +191,77 @@ int get_nlink(struct kstat *st)
|
||||
return nlink;
|
||||
}
|
||||
|
||||
void ksmbd_conv_path_to_unix(char *path)
|
||||
char *ksmbd_conv_path_to_unix(char *path)
|
||||
{
|
||||
size_t path_len, remain_path_len, out_path_len;
|
||||
char *out_path, *out_next;
|
||||
int i, pre_dotdot_cnt = 0, slash_cnt = 0;
|
||||
bool is_last;
|
||||
|
||||
strreplace(path, '\\', '/');
|
||||
}
|
||||
path_len = strlen(path);
|
||||
remain_path_len = path_len;
|
||||
if (path_len == 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
void ksmbd_strip_last_slash(char *path)
|
||||
{
|
||||
int len = strlen(path);
|
||||
out_path = kzalloc(path_len + 2, GFP_KERNEL);
|
||||
if (!out_path)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
out_path_len = 0;
|
||||
out_next = out_path;
|
||||
|
||||
while (len && path[len - 1] == '/') {
|
||||
path[len - 1] = '\0';
|
||||
len--;
|
||||
do {
|
||||
char *name = path + path_len - remain_path_len;
|
||||
char *next = strchrnul(name, '/');
|
||||
size_t name_len = next - name;
|
||||
|
||||
is_last = !next[0];
|
||||
if (name_len == 2 && name[0] == '.' && name[1] == '.') {
|
||||
pre_dotdot_cnt++;
|
||||
/* handle the case that path ends with "/.." */
|
||||
if (is_last)
|
||||
goto follow_dotdot;
|
||||
} else {
|
||||
if (pre_dotdot_cnt) {
|
||||
follow_dotdot:
|
||||
slash_cnt = 0;
|
||||
for (i = out_path_len - 1; i >= 0; i--) {
|
||||
if (out_path[i] == '/' &&
|
||||
++slash_cnt == pre_dotdot_cnt + 1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 &&
|
||||
slash_cnt != pre_dotdot_cnt) {
|
||||
kfree(out_path);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
out_next = &out_path[i+1];
|
||||
*out_next = '\0';
|
||||
out_path_len = i + 1;
|
||||
|
||||
}
|
||||
|
||||
if (name_len != 0 &&
|
||||
!(name_len == 1 && name[0] == '.') &&
|
||||
!(name_len == 2 && name[0] == '.' && name[1] == '.')) {
|
||||
next[0] = '\0';
|
||||
sprintf(out_next, "%s/", name);
|
||||
out_next += name_len + 1;
|
||||
out_path_len += name_len + 1;
|
||||
next[0] = '/';
|
||||
}
|
||||
pre_dotdot_cnt = 0;
|
||||
}
|
||||
|
||||
remain_path_len -= name_len + 1;
|
||||
} while (!is_last);
|
||||
|
||||
if (out_path_len > 0)
|
||||
out_path[out_path_len-1] = '\0';
|
||||
path[path_len] = '\0';
|
||||
return out_path;
|
||||
}
|
||||
|
||||
void ksmbd_conv_path_to_windows(char *path)
|
||||
|
||||
@@ -16,8 +16,7 @@ int ksmbd_validate_filename(char *filename);
|
||||
int parse_stream_name(char *filename, char **stream_name, int *s_type);
|
||||
char *convert_to_nt_pathname(char *filename, char *sharepath);
|
||||
int get_nlink(struct kstat *st);
|
||||
void ksmbd_conv_path_to_unix(char *path);
|
||||
void ksmbd_strip_last_slash(char *path);
|
||||
char *ksmbd_conv_path_to_unix(char *path);
|
||||
void ksmbd_conv_path_to_windows(char *path);
|
||||
char *ksmbd_extract_sharename(char *treename);
|
||||
char *convert_to_unix_name(struct ksmbd_share_config *share, char *name);
|
||||
|
||||
@@ -634,7 +634,7 @@ static char *
|
||||
smb2_get_name(struct ksmbd_share_config *share, const char *src,
|
||||
const int maxlen, struct nls_table *local_nls)
|
||||
{
|
||||
char *name, *unixname;
|
||||
char *name, *norm_name, *unixname;
|
||||
|
||||
name = smb_strndup_from_utf16(src, maxlen, 1, local_nls);
|
||||
if (IS_ERR(name)) {
|
||||
@@ -643,11 +643,15 @@ smb2_get_name(struct ksmbd_share_config *share, const char *src,
|
||||
}
|
||||
|
||||
/* change it to absolute unix name */
|
||||
ksmbd_conv_path_to_unix(name);
|
||||
ksmbd_strip_last_slash(name);
|
||||
|
||||
unixname = convert_to_unix_name(share, name);
|
||||
norm_name = ksmbd_conv_path_to_unix(name);
|
||||
if (IS_ERR(norm_name)) {
|
||||
kfree(name);
|
||||
return norm_name;
|
||||
}
|
||||
kfree(name);
|
||||
|
||||
unixname = convert_to_unix_name(share, norm_name);
|
||||
kfree(norm_name);
|
||||
if (!unixname) {
|
||||
pr_err("can not convert absolute name\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -4041,6 +4045,10 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
path = &fp->filp->f_path;
|
||||
/* single EA entry is requested with given user.* name */
|
||||
if (req->InputBufferLength) {
|
||||
if (le32_to_cpu(req->InputBufferLength) <
|
||||
sizeof(struct smb2_ea_info_req))
|
||||
return -EINVAL;
|
||||
|
||||
ea_req = (struct smb2_ea_info_req *)req->Buffer;
|
||||
} else {
|
||||
/* need to send all EAs, if no specific EA is requested*/
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define SUBMOD_NAME "smb_direct"
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/rwlock.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mempool.h>
|
||||
#include <linux/highmem.h>
|
||||
|
||||
@@ -20,12 +20,33 @@
|
||||
* depending on the status field in the last byte. The
|
||||
* first byte is where the name start either way, and a
|
||||
* zero means it's empty.
|
||||
*
|
||||
* Also, due to a bug in gcc, we don't want to use the
|
||||
* real (differently sized) name arrays in the inode and
|
||||
* link entries, but always the 'de_name[]' one in the
|
||||
* fake struct entry.
|
||||
*
|
||||
* See
|
||||
*
|
||||
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c6
|
||||
*
|
||||
* for details, but basically gcc will take the size of the
|
||||
* 'name' array from one of the used union entries randomly.
|
||||
*
|
||||
* This use of 'de_name[]' (48 bytes) avoids the false positive
|
||||
* warnings that would happen if gcc decides to use 'inode.di_name'
|
||||
* (16 bytes) even when the pointer and size were to come from
|
||||
* 'link.dl_name' (48 bytes).
|
||||
*
|
||||
* In all cases the actual name pointer itself is the same, it's
|
||||
* only the gcc internal 'what is the size of this field' logic
|
||||
* that can get confused.
|
||||
*/
|
||||
union qnx4_directory_entry {
|
||||
struct {
|
||||
char de_name;
|
||||
char de_pad[62];
|
||||
char de_status;
|
||||
const char de_name[48];
|
||||
u8 de_pad[15];
|
||||
u8 de_status;
|
||||
};
|
||||
struct qnx4_inode_entry inode;
|
||||
struct qnx4_link_info link;
|
||||
@@ -53,29 +74,26 @@ static int qnx4_readdir(struct file *file, struct dir_context *ctx)
|
||||
ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK;
|
||||
for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) {
|
||||
union qnx4_directory_entry *de;
|
||||
const char *name;
|
||||
|
||||
offset = ix * QNX4_DIR_ENTRY_SIZE;
|
||||
de = (union qnx4_directory_entry *) (bh->b_data + offset);
|
||||
|
||||
if (!de->de_name)
|
||||
if (!de->de_name[0])
|
||||
continue;
|
||||
if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK)))
|
||||
continue;
|
||||
if (!(de->de_status & QNX4_FILE_LINK)) {
|
||||
size = sizeof(de->inode.di_fname);
|
||||
name = de->inode.di_fname;
|
||||
ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
|
||||
} else {
|
||||
size = sizeof(de->link.dl_fname);
|
||||
name = de->link.dl_fname;
|
||||
ino = ( le32_to_cpu(de->link.dl_inode_blk) - 1 ) *
|
||||
QNX4_INODES_PER_BLOCK +
|
||||
de->link.dl_inode_ndx;
|
||||
}
|
||||
size = strnlen(name, size);
|
||||
size = strnlen(de->de_name, size);
|
||||
QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, name));
|
||||
if (!dir_emit(ctx, name, size, ino, DT_UNKNOWN)) {
|
||||
if (!dir_emit(ctx, de->de_name, size, ino, DT_UNKNOWN)) {
|
||||
brelse(bh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/*
|
||||
* fs/cifs/smbfsctl.h: SMB, CIFS, SMB2 FSCTL definitions
|
||||
* SMB, CIFS, SMB2 FSCTL definitions
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002,2013
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
|
||||
@@ -306,11 +306,13 @@ enum afs_flock_operation {
|
||||
|
||||
enum afs_cb_break_reason {
|
||||
afs_cb_break_no_break,
|
||||
afs_cb_break_no_promise,
|
||||
afs_cb_break_for_callback,
|
||||
afs_cb_break_for_deleted,
|
||||
afs_cb_break_for_lapsed,
|
||||
afs_cb_break_for_s_reinit,
|
||||
afs_cb_break_for_unlink,
|
||||
afs_cb_break_for_vsbreak,
|
||||
afs_cb_break_for_v_break,
|
||||
afs_cb_break_for_volume_callback,
|
||||
afs_cb_break_for_zap,
|
||||
};
|
||||
@@ -602,11 +604,13 @@ enum afs_cb_break_reason {
|
||||
|
||||
#define afs_cb_break_reasons \
|
||||
EM(afs_cb_break_no_break, "no-break") \
|
||||
EM(afs_cb_break_no_promise, "no-promise") \
|
||||
EM(afs_cb_break_for_callback, "break-cb") \
|
||||
EM(afs_cb_break_for_deleted, "break-del") \
|
||||
EM(afs_cb_break_for_lapsed, "break-lapsed") \
|
||||
EM(afs_cb_break_for_s_reinit, "s-reinit") \
|
||||
EM(afs_cb_break_for_unlink, "break-unlink") \
|
||||
EM(afs_cb_break_for_vsbreak, "break-vs") \
|
||||
EM(afs_cb_break_for_v_break, "break-v") \
|
||||
EM(afs_cb_break_for_volume_callback, "break-v-cb") \
|
||||
E_(afs_cb_break_for_zap, "break-zap")
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
|
||||
/*
|
||||
* include/uapi/linux/cifs/cifs_mount.h
|
||||
*
|
||||
* Author(s): Scott Lovenberg (scott.lovenberg@gmail.com)
|
||||
*
|
||||
|
||||
@@ -3417,6 +3417,7 @@ void unmap_mapping_pages(struct address_space *mapping, pgoff_t start,
|
||||
unmap_mapping_range_tree(&mapping->i_mmap, &details);
|
||||
i_mmap_unlock_write(mapping);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unmap_mapping_pages);
|
||||
|
||||
/**
|
||||
* unmap_mapping_range - unmap the portion of all mmaps in the specified
|
||||
|
||||
Reference in New Issue
Block a user