ed23734c23
Current release - regressions: - sched: act_pedit: free pedit keys on bail from offset check Current release - new code bugs: - pds_core: - Kconfig fixes (DEBUGFS and AUXILIARY_BUS) - fix mutex double unlock in error path Previous releases - regressions: - sched: cls_api: remove block_cb from driver_list before freeing - nf_tables: fix ct untracked match breakage - eth: mtk_eth_soc: drop generic vlan rx offload - sched: flower: fix error handler on replace Previous releases - always broken: - tcp: fix skb_copy_ubufs() vs BIG TCP - ipv6: fix skb hash for some RST packets - af_packet: don't send zero-byte data in packet_sendmsg_spkt() - rxrpc: timeout handling fixes after moving client call connection to the I/O thread - ixgbe: fix panic during XDP_TX with > 64 CPUs - igc: RMW the SRRCTL register to prevent losing timestamp config - dsa: mt7530: fix corrupt frames using TRGMII on 40 MHz XTAL MT7621 - r8152: - fix flow control issue of RTL8156A - fix the poor throughput for 2.5G devices - move setting r8153b_rx_agg_chg_indicate() to fix coalescing - enable autosuspend - ncsi: clear Tx enable mode when handling a Config required AEN - octeontx2-pf: macsec: fixes for CN10KB ASIC rev Misc: - 9p: remove INET dependency Signed-off-by: Jakub Kicinski <kuba@kernel.org> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE6jPA+I1ugmIBA4hXMUZtbf5SIrsFAmRVeUIACgkQMUZtbf5S IrtTug/9Hhg/L0PTSwrfuGh4W1/cjheMWppNLkwyWQUiKG7FcZQ9vu9PxceE3VRu 2fTqHyvgDMZ8jACovXObeda8z1+g3s/tIPaXELephBIjVlF/h3kG2OaIzlU4jDb4 A4vklwf8eLbfyVBG22QgKl/I70zVMtnmnOo6c6CPuIOTcMPzslndFO9tB0nCg99F DCgCM1BBP1tz+OUch2rLnSzYcqkWqS49BhRk6dhYSliawUFU/5+1tDGDjwWolkfm 0jqP9DjBOSpZKO8m7SpsUNz7NFRIfYErWZ+YebWbggNxj/6TRJTP83MM0tGoK1rE /mz2xpuOki59frlwVOAD6gb/qefjHUp21P4NA7bnhizxFlQL5MHpCeGQ9yLHBSmY 9Q4ArJkM4jXQ0oDA2nII/pz+cDZGEWFGQ14WW3kYUb7WFmISH4I9OiA9i0TBW6OL r1Y/rqzkUvtKWzh9RpiAF9lsdHAm3SX9ES5RfMxzv0x886VOZR4jaMmokRDdPRzq 0r2Oyj75b62+X0r44Fe22Pl/kPS/uh3642xo9h85aAv/EvhT9JNzMvomJm9d6tkb 966I085AVbwxPAy+rl5SWyAq60EWDExNTjZvPv0mSMlmSsQ9iK5//xOF2Saw2zai /44zQ27tVGkCC44Ou5KmfJN3u4OrKkhcuyxtcDr9QeoOdKZRkMg= =9xND -----END PGP SIGNATURE----- Merge tag 'net-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net Pull networking fixes from Jakub Kicinski: "Including fixes from netfilter. Current release - regressions: - sched: act_pedit: free pedit keys on bail from offset check Current release - new code bugs: - pds_core: - Kconfig fixes (DEBUGFS and AUXILIARY_BUS) - fix mutex double unlock in error path Previous releases - regressions: - sched: cls_api: remove block_cb from driver_list before freeing - nf_tables: fix ct untracked match breakage - eth: mtk_eth_soc: drop generic vlan rx offload - sched: flower: fix error handler on replace Previous releases - always broken: - tcp: fix skb_copy_ubufs() vs BIG TCP - ipv6: fix skb hash for some RST packets - af_packet: don't send zero-byte data in packet_sendmsg_spkt() - rxrpc: timeout handling fixes after moving client call connection to the I/O thread - ixgbe: fix panic during XDP_TX with > 64 CPUs - igc: RMW the SRRCTL register to prevent losing timestamp config - dsa: mt7530: fix corrupt frames using TRGMII on 40 MHz XTAL MT7621 - r8152: - fix flow control issue of RTL8156A - fix the poor throughput for 2.5G devices - move setting r8153b_rx_agg_chg_indicate() to fix coalescing - enable autosuspend - ncsi: clear Tx enable mode when handling a Config required AEN - octeontx2-pf: macsec: fixes for CN10KB ASIC rev Misc: - 9p: remove INET dependency" * tag 'net-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (69 commits) net: bcmgenet: Remove phy_stop() from bcmgenet_netif_stop() pds_core: fix mutex double unlock in error path net/sched: flower: fix error handler on replace Revert "net/sched: flower: Fix wrong handle assignment during filter change" net/sched: flower: fix filter idr initialization net: fec: correct the counting of XDP sent frames bonding: add xdp_features support net: enetc: check the index of the SFI rather than the handle sfc: Add back mailing list virtio_net: suppress cpu stall when free_unused_bufs ice: block LAN in case of VF to VF offload net: dsa: mt7530: fix network connectivity with multiple CPU ports net: dsa: mt7530: fix corrupt frames using trgmii on 40 MHz XTAL MT7621 9p: Remove INET dependency netfilter: nf_tables: fix ct untracked match breakage af_packet: Don't send zero-byte data in packet_sendmsg_spkt(). igc: read before write to SRRCTL register pds_core: add AUXILIARY_BUS and NET_DEVLINK to Kconfig pds_core: remove CONFIG_DEBUG_FS from makefile ionic: catch failure from devlink_alloc ...
254 lines
5.4 KiB
C
254 lines
5.4 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* This file contains vfs directory ops for the 9P2000 protocol.
|
|
*
|
|
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
|
|
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/file.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/string.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/uio.h>
|
|
#include <linux/fscache.h>
|
|
#include <net/9p/9p.h>
|
|
#include <net/9p/client.h>
|
|
|
|
#include "v9fs.h"
|
|
#include "v9fs_vfs.h"
|
|
#include "fid.h"
|
|
|
|
/**
|
|
* struct p9_rdir - readdir accounting
|
|
* @head: start offset of current dirread buffer
|
|
* @tail: end offset of current dirread buffer
|
|
* @buf: dirread buffer
|
|
*
|
|
* private structure for keeping track of readdir
|
|
* allocated on demand
|
|
*/
|
|
|
|
struct p9_rdir {
|
|
int head;
|
|
int tail;
|
|
uint8_t buf[];
|
|
};
|
|
|
|
/**
|
|
* dt_type - return file type
|
|
* @mistat: mistat structure
|
|
*
|
|
*/
|
|
|
|
static inline int dt_type(struct p9_wstat *mistat)
|
|
{
|
|
unsigned long perm = mistat->mode;
|
|
int rettype = DT_REG;
|
|
|
|
if (perm & P9_DMDIR)
|
|
rettype = DT_DIR;
|
|
if (perm & P9_DMSYMLINK)
|
|
rettype = DT_LNK;
|
|
|
|
return rettype;
|
|
}
|
|
|
|
/**
|
|
* v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
|
|
* @filp: opened file structure
|
|
* @buflen: Length in bytes of buffer to allocate
|
|
*
|
|
*/
|
|
|
|
static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
|
|
{
|
|
struct p9_fid *fid = filp->private_data;
|
|
|
|
if (!fid->rdir)
|
|
fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
|
|
return fid->rdir;
|
|
}
|
|
|
|
/**
|
|
* v9fs_dir_readdir - iterate through a directory
|
|
* @file: opened file structure
|
|
* @ctx: actor we feed the entries to
|
|
*
|
|
*/
|
|
|
|
static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
|
|
{
|
|
bool over;
|
|
struct p9_wstat st;
|
|
int err = 0;
|
|
struct p9_fid *fid;
|
|
int buflen;
|
|
struct p9_rdir *rdir;
|
|
struct kvec kvec;
|
|
|
|
p9_debug(P9_DEBUG_VFS, "name %pD\n", file);
|
|
fid = file->private_data;
|
|
|
|
buflen = fid->clnt->msize - P9_IOHDRSZ;
|
|
|
|
rdir = v9fs_alloc_rdir_buf(file, buflen);
|
|
if (!rdir)
|
|
return -ENOMEM;
|
|
kvec.iov_base = rdir->buf;
|
|
kvec.iov_len = buflen;
|
|
|
|
while (1) {
|
|
if (rdir->tail == rdir->head) {
|
|
struct iov_iter to;
|
|
int n;
|
|
|
|
iov_iter_kvec(&to, ITER_DEST, &kvec, 1, buflen);
|
|
n = p9_client_read(file->private_data, ctx->pos, &to,
|
|
&err);
|
|
if (err)
|
|
return err;
|
|
if (n == 0)
|
|
return 0;
|
|
|
|
rdir->head = 0;
|
|
rdir->tail = n;
|
|
}
|
|
while (rdir->head < rdir->tail) {
|
|
err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
|
|
rdir->tail - rdir->head, &st);
|
|
if (err <= 0) {
|
|
p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
|
|
return -EIO;
|
|
}
|
|
|
|
over = !dir_emit(ctx, st.name, strlen(st.name),
|
|
v9fs_qid2ino(&st.qid), dt_type(&st));
|
|
p9stat_free(&st);
|
|
if (over)
|
|
return 0;
|
|
|
|
rdir->head += err;
|
|
ctx->pos += err;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* v9fs_dir_readdir_dotl - iterate through a directory
|
|
* @file: opened file structure
|
|
* @ctx: actor we feed the entries to
|
|
*
|
|
*/
|
|
static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
|
|
{
|
|
int err = 0;
|
|
struct p9_fid *fid;
|
|
int buflen;
|
|
struct p9_rdir *rdir;
|
|
struct p9_dirent curdirent;
|
|
|
|
p9_debug(P9_DEBUG_VFS, "name %pD\n", file);
|
|
fid = file->private_data;
|
|
|
|
buflen = fid->clnt->msize - P9_READDIRHDRSZ;
|
|
|
|
rdir = v9fs_alloc_rdir_buf(file, buflen);
|
|
if (!rdir)
|
|
return -ENOMEM;
|
|
|
|
while (1) {
|
|
if (rdir->tail == rdir->head) {
|
|
err = p9_client_readdir(fid, rdir->buf, buflen,
|
|
ctx->pos);
|
|
if (err <= 0)
|
|
return err;
|
|
|
|
rdir->head = 0;
|
|
rdir->tail = err;
|
|
}
|
|
|
|
while (rdir->head < rdir->tail) {
|
|
|
|
err = p9dirent_read(fid->clnt, rdir->buf + rdir->head,
|
|
rdir->tail - rdir->head,
|
|
&curdirent);
|
|
if (err < 0) {
|
|
p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
|
|
return -EIO;
|
|
}
|
|
|
|
if (!dir_emit(ctx, curdirent.d_name,
|
|
strlen(curdirent.d_name),
|
|
v9fs_qid2ino(&curdirent.qid),
|
|
curdirent.d_type))
|
|
return 0;
|
|
|
|
ctx->pos = curdirent.d_off;
|
|
rdir->head += err;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* v9fs_dir_release - close a directory or a file
|
|
* @inode: inode of the directory or file
|
|
* @filp: file pointer to a directory or file
|
|
*
|
|
*/
|
|
|
|
int v9fs_dir_release(struct inode *inode, struct file *filp)
|
|
{
|
|
struct v9fs_inode *v9inode = V9FS_I(inode);
|
|
struct p9_fid *fid;
|
|
__le32 version;
|
|
loff_t i_size;
|
|
int retval = 0;
|
|
|
|
fid = filp->private_data;
|
|
p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n",
|
|
inode, filp, fid ? fid->fid : -1);
|
|
|
|
if (fid) {
|
|
if ((S_ISREG(inode->i_mode)) && (filp->f_mode & FMODE_WRITE))
|
|
retval = filemap_fdatawrite(inode->i_mapping);
|
|
|
|
spin_lock(&inode->i_lock);
|
|
hlist_del(&fid->ilist);
|
|
spin_unlock(&inode->i_lock);
|
|
retval = p9_fid_put(fid);
|
|
}
|
|
|
|
if ((filp->f_mode & FMODE_WRITE)) {
|
|
version = cpu_to_le32(v9inode->qid.version);
|
|
i_size = i_size_read(inode);
|
|
fscache_unuse_cookie(v9fs_inode_cookie(v9inode),
|
|
&version, &i_size);
|
|
} else {
|
|
fscache_unuse_cookie(v9fs_inode_cookie(v9inode), NULL, NULL);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
const struct file_operations v9fs_dir_operations = {
|
|
.read = generic_read_dir,
|
|
.llseek = generic_file_llseek,
|
|
.iterate_shared = v9fs_dir_readdir,
|
|
.open = v9fs_file_open,
|
|
.release = v9fs_dir_release,
|
|
};
|
|
|
|
const struct file_operations v9fs_dir_operations_dotl = {
|
|
.read = generic_read_dir,
|
|
.llseek = generic_file_llseek,
|
|
.iterate_shared = v9fs_dir_readdir_dotl,
|
|
.open = v9fs_file_open,
|
|
.release = v9fs_dir_release,
|
|
.fsync = v9fs_file_fsync_dotl,
|
|
};
|