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