^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/9p/vfs_dir.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file contains vfs directory ops for the 9P2000 protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/idr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/9p/9p.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/9p/client.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "v9fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "v9fs_vfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "fid.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * struct p9_rdir - readdir accounting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @head: start offset of current dirread buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @tail: end offset of current dirread buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @buf: dirread buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * private structure for keeping track of readdir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * allocated on demand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct p9_rdir {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) uint8_t buf[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * dt_type - return file type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @mistat: mistat structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static inline int dt_type(struct p9_wstat *mistat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long perm = mistat->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int rettype = DT_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (perm & P9_DMDIR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) rettype = DT_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (perm & P9_DMSYMLINK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) rettype = DT_LNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return rettype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @filp: opened file structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @buflen: Length in bytes of buffer to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct p9_fid *fid = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!fid->rdir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return fid->rdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * v9fs_dir_readdir - iterate through a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * @file: opened file structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * @ctx: actor we feed the entries to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) bool over;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct p9_wstat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct p9_fid *fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct p9_rdir *rdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct kvec kvec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) p9_debug(P9_DEBUG_VFS, "name %pD\n", file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) fid = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) buflen = fid->clnt->msize - P9_IOHDRSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) rdir = v9fs_alloc_rdir_buf(file, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (!rdir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) kvec.iov_base = rdir->buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) kvec.iov_len = buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (rdir->tail == rdir->head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct iov_iter to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) iov_iter_kvec(&to, READ, &kvec, 1, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) n = p9_client_read(file->private_data, ctx->pos, &to,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) &err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (n == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) rdir->head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) rdir->tail = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) while (rdir->head < rdir->tail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) rdir->tail - rdir->head, &st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (err <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) over = !dir_emit(ctx, st.name, strlen(st.name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) v9fs_qid2ino(&st.qid), dt_type(&st));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) p9stat_free(&st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (over)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) rdir->head += err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ctx->pos += err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * v9fs_dir_readdir_dotl - iterate through a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @file: opened file structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @ctx: actor we feed the entries to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct p9_fid *fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct p9_rdir *rdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct p9_dirent curdirent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) p9_debug(P9_DEBUG_VFS, "name %pD\n", file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) fid = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) buflen = fid->clnt->msize - P9_READDIRHDRSZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) rdir = v9fs_alloc_rdir_buf(file, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!rdir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (rdir->tail == rdir->head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) err = p9_client_readdir(fid, rdir->buf, buflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ctx->pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (err <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) rdir->head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) rdir->tail = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) while (rdir->head < rdir->tail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) err = p9dirent_read(fid->clnt, rdir->buf + rdir->head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rdir->tail - rdir->head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) &curdirent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!dir_emit(ctx, curdirent.d_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) strlen(curdirent.d_name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) v9fs_qid2ino(&curdirent.qid),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) curdirent.d_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ctx->pos = curdirent.d_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) rdir->head += err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * v9fs_dir_release - close a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * @inode: inode of the directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @filp: file pointer to a directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int v9fs_dir_release(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct p9_fid *fid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) fid = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) inode, filp, fid ? fid->fid : -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (fid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) p9_client_clunk(fid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) const struct file_operations v9fs_dir_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .iterate_shared = v9fs_dir_readdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .open = v9fs_file_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .release = v9fs_dir_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) const struct file_operations v9fs_dir_operations_dotl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .read = generic_read_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .llseek = generic_file_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .iterate_shared = v9fs_dir_readdir_dotl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .open = v9fs_file_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .release = v9fs_dir_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .fsync = v9fs_file_fsync_dotl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };