Blame view
fs/9p/vfs_dir.c
5.68 KB
e69e7fe5b [PATCH] v9fs: VFS... |
1 2 3 4 5 6 7 8 9 |
/* * linux/fs/9p/vfs_dir.c * * 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> * * This program is free software; you can redistribute it and/or modify |
42e8c509c [PATCH] v9fs: upd... |
10 11 |
* it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. |
e69e7fe5b [PATCH] v9fs: VFS... |
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to: * Free Software Foundation * 51 Franklin Street, Fifth Floor * Boston, MA 02111-1301 USA * */ #include <linux/module.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/stat.h> #include <linux/string.h> |
914e26379 [PATCH] severing ... |
32 |
#include <linux/sched.h> |
e69e7fe5b [PATCH] v9fs: VFS... |
33 34 |
#include <linux/inet.h> #include <linux/idr.h> |
5a0e3ad6a include cleanup: ... |
35 |
#include <linux/slab.h> |
e1200fe68 9p: switch p9_cli... |
36 |
#include <linux/uio.h> |
bd238fb43 9p: Reorganizatio... |
37 38 |
#include <net/9p/9p.h> #include <net/9p/client.h> |
e69e7fe5b [PATCH] v9fs: VFS... |
39 |
|
e69e7fe5b [PATCH] v9fs: VFS... |
40 |
#include "v9fs.h" |
531b1094b [PATCH] v9fs: zer... |
41 |
#include "v9fs_vfs.h" |
e69e7fe5b [PATCH] v9fs: VFS... |
42 43 44 |
#include "fid.h" /** |
3e2796a90 9p: fix readdir c... |
45 |
* struct p9_rdir - readdir accounting |
3e2796a90 9p: fix readdir c... |
46 47 48 49 50 51 52 53 54 |
* @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 { |
3e2796a90 9p: fix readdir c... |
55 56 |
int head; int tail; |
7ffdea7ea locking in fs/9p ... |
57 |
uint8_t buf[]; |
3e2796a90 9p: fix readdir c... |
58 59 60 |
}; /** |
e69e7fe5b [PATCH] v9fs: VFS... |
61 62 63 64 |
* dt_type - return file type * @mistat: mistat structure * */ |
02da398b9 9p: eliminate dep... |
65 |
static inline int dt_type(struct p9_wstat *mistat) |
e69e7fe5b [PATCH] v9fs: VFS... |
66 67 68 |
{ unsigned long perm = mistat->mode; int rettype = DT_REG; |
bd238fb43 9p: Reorganizatio... |
69 |
if (perm & P9_DMDIR) |
e69e7fe5b [PATCH] v9fs: VFS... |
70 |
rettype = DT_DIR; |
bd238fb43 9p: Reorganizatio... |
71 |
if (perm & P9_DMSYMLINK) |
e69e7fe5b [PATCH] v9fs: VFS... |
72 73 74 75 |
rettype = DT_LNK; return rettype; } |
fae4528b2 fs/9p: re-init th... |
76 77 78 79 80 81 82 83 |
static void p9stat_init(struct p9_wstat *stbuf) { stbuf->name = NULL; stbuf->uid = NULL; stbuf->gid = NULL; stbuf->muid = NULL; stbuf->extension = NULL; } |
e69e7fe5b [PATCH] v9fs: VFS... |
84 |
/** |
7751bdb3a 9p: readdir imple... |
85 |
* v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir |
ee443996a 9p: Documentation... |
86 |
* @filp: opened file structure |
7751bdb3a 9p: readdir imple... |
87 |
* @buflen: Length in bytes of buffer to allocate |
e69e7fe5b [PATCH] v9fs: VFS... |
88 89 |
* */ |
7ffdea7ea locking in fs/9p ... |
90 |
static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen) |
e69e7fe5b [PATCH] v9fs: VFS... |
91 |
{ |
7ffdea7ea locking in fs/9p ... |
92 93 94 95 |
struct p9_fid *fid = filp->private_data; if (!fid->rdir) fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); return fid->rdir; |
7751bdb3a 9p: readdir imple... |
96 97 98 |
} /** |
8f29843a5 [readdir] convert 9p |
99 100 101 |
* v9fs_dir_readdir - iterate through a directory * @file: opened file structure * @ctx: actor we feed the entries to |
7751bdb3a 9p: readdir imple... |
102 103 |
* */ |
8f29843a5 [readdir] convert 9p |
104 |
static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) |
7751bdb3a 9p: readdir imple... |
105 |
{ |
8f29843a5 [readdir] convert 9p |
106 |
bool over; |
7751bdb3a 9p: readdir imple... |
107 108 109 110 111 112 |
struct p9_wstat st; int err = 0; struct p9_fid *fid; int buflen; int reclen = 0; struct p9_rdir *rdir; |
e1200fe68 9p: switch p9_cli... |
113 |
struct kvec kvec; |
7751bdb3a 9p: readdir imple... |
114 |
|
4b8e99239 9p: switch to %p[dD] |
115 116 |
p9_debug(P9_DEBUG_VFS, "name %pD ", file); |
8f29843a5 [readdir] convert 9p |
117 |
fid = file->private_data; |
7751bdb3a 9p: readdir imple... |
118 119 |
buflen = fid->clnt->msize - P9_IOHDRSZ; |
8f29843a5 [readdir] convert 9p |
120 |
rdir = v9fs_alloc_rdir_buf(file, buflen); |
7ffdea7ea locking in fs/9p ... |
121 122 |
if (!rdir) return -ENOMEM; |
e1200fe68 9p: switch p9_cli... |
123 124 |
kvec.iov_base = rdir->buf; kvec.iov_len = buflen; |
3e2796a90 9p: fix readdir c... |
125 |
|
7ffdea7ea locking in fs/9p ... |
126 |
while (1) { |
3e2796a90 9p: fix readdir c... |
127 |
if (rdir->tail == rdir->head) { |
e1200fe68 9p: switch p9_cli... |
128 129 130 131 132 133 |
struct iov_iter to; int n; iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); n = p9_client_read(file->private_data, ctx->pos, &to, &err); if (err) |
7ffdea7ea locking in fs/9p ... |
134 |
return err; |
8e3c50059 fs/9p: fix readdir() |
135 136 |
if (n == 0) return 0; |
3e2796a90 9p: fix readdir c... |
137 138 |
rdir->head = 0; |
e1200fe68 9p: switch p9_cli... |
139 |
rdir->tail = n; |
3e2796a90 9p: fix readdir c... |
140 |
} |
3e2796a90 9p: fix readdir c... |
141 |
while (rdir->head < rdir->tail) { |
fae4528b2 fs/9p: re-init th... |
142 |
p9stat_init(&st); |
348b59012 net/9p: Convert n... |
143 144 |
err = p9stat_read(fid->clnt, rdir->buf + rdir->head, rdir->tail - rdir->head, &st); |
02da398b9 9p: eliminate dep... |
145 |
if (err) { |
5d3851530 9p: Reduce object... |
146 147 |
p9_debug(P9_DEBUG_VFS, "returned %d ", err); |
02da398b9 9p: eliminate dep... |
148 |
p9stat_free(&st); |
7ffdea7ea locking in fs/9p ... |
149 |
return -EIO; |
06b55b464 9p: move dirread ... |
150 |
} |
3e2796a90 9p: fix readdir c... |
151 |
reclen = st.size+2; |
06b55b464 9p: move dirread ... |
152 |
|
8f29843a5 [readdir] convert 9p |
153 154 |
over = !dir_emit(ctx, st.name, strlen(st.name), v9fs_qid2ino(&st.qid), dt_type(&st)); |
02da398b9 9p: eliminate dep... |
155 |
p9stat_free(&st); |
7ffdea7ea locking in fs/9p ... |
156 157 |
if (over) return 0; |
3e2796a90 9p: fix readdir c... |
158 |
rdir->head += reclen; |
8f29843a5 [readdir] convert 9p |
159 |
ctx->pos += reclen; |
06b55b464 9p: move dirread ... |
160 |
} |
e69e7fe5b [PATCH] v9fs: VFS... |
161 |
} |
e69e7fe5b [PATCH] v9fs: VFS... |
162 |
} |
7751bdb3a 9p: readdir imple... |
163 |
/** |
8f29843a5 [readdir] convert 9p |
164 165 166 |
* v9fs_dir_readdir_dotl - iterate through a directory * @file: opened file structure * @ctx: actor we feed the entries to |
7751bdb3a 9p: readdir imple... |
167 168 |
* */ |
8f29843a5 [readdir] convert 9p |
169 |
static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx) |
7751bdb3a 9p: readdir imple... |
170 |
{ |
7751bdb3a 9p: readdir imple... |
171 172 173 174 175 |
int err = 0; struct p9_fid *fid; int buflen; struct p9_rdir *rdir; struct p9_dirent curdirent; |
7751bdb3a 9p: readdir imple... |
176 |
|
4b8e99239 9p: switch to %p[dD] |
177 178 |
p9_debug(P9_DEBUG_VFS, "name %pD ", file); |
8f29843a5 [readdir] convert 9p |
179 |
fid = file->private_data; |
7751bdb3a 9p: readdir imple... |
180 181 |
buflen = fid->clnt->msize - P9_READDIRHDRSZ; |
8f29843a5 [readdir] convert 9p |
182 |
rdir = v9fs_alloc_rdir_buf(file, buflen); |
7ffdea7ea locking in fs/9p ... |
183 184 |
if (!rdir) return -ENOMEM; |
7751bdb3a 9p: readdir imple... |
185 |
|
7ffdea7ea locking in fs/9p ... |
186 |
while (1) { |
7751bdb3a 9p: readdir imple... |
187 188 |
if (rdir->tail == rdir->head) { err = p9_client_readdir(fid, rdir->buf, buflen, |
8f29843a5 [readdir] convert 9p |
189 |
ctx->pos); |
7751bdb3a 9p: readdir imple... |
190 |
if (err <= 0) |
7ffdea7ea locking in fs/9p ... |
191 |
return err; |
7751bdb3a 9p: readdir imple... |
192 193 194 195 196 197 |
rdir->head = 0; rdir->tail = err; } while (rdir->head < rdir->tail) { |
348b59012 net/9p: Convert n... |
198 199 200 |
err = p9dirent_read(fid->clnt, rdir->buf + rdir->head, rdir->tail - rdir->head, &curdirent); |
7751bdb3a 9p: readdir imple... |
201 |
if (err < 0) { |
5d3851530 9p: Reduce object... |
202 203 |
p9_debug(P9_DEBUG_VFS, "returned %d ", err); |
7ffdea7ea locking in fs/9p ... |
204 |
return -EIO; |
7751bdb3a 9p: readdir imple... |
205 |
} |
8f29843a5 [readdir] convert 9p |
206 207 208 209 |
if (!dir_emit(ctx, curdirent.d_name, strlen(curdirent.d_name), v9fs_qid2ino(&curdirent.qid), curdirent.d_type)) |
7ffdea7ea locking in fs/9p ... |
210 |
return 0; |
7751bdb3a 9p: readdir imple... |
211 |
|
8f29843a5 [readdir] convert 9p |
212 |
ctx->pos = curdirent.d_off; |
7751bdb3a 9p: readdir imple... |
213 214 215 |
rdir->head += err; } } |
7751bdb3a 9p: readdir imple... |
216 |
} |
bd238fb43 9p: Reorganizatio... |
217 |
|
e69e7fe5b [PATCH] v9fs: VFS... |
218 219 220 221 222 223 224 225 226 |
/** * v9fs_dir_release - close a directory * @inode: inode of the directory * @filp: file pointer to a directory * */ int v9fs_dir_release(struct inode *inode, struct file *filp) { |
bd238fb43 9p: Reorganizatio... |
227 |
struct p9_fid *fid; |
e69e7fe5b [PATCH] v9fs: VFS... |
228 |
|
bd238fb43 9p: Reorganizatio... |
229 |
fid = filp->private_data; |
5d3851530 9p: Reduce object... |
230 231 232 |
p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d ", inode, filp, fid ? fid->fid : -1); |
62726a7ab 9p: Check for NUL... |
233 234 |
if (fid) p9_client_clunk(fid); |
e69e7fe5b [PATCH] v9fs: VFS... |
235 236 |
return 0; } |
4b6f5d20b [PATCH] Make most... |
237 |
const struct file_operations v9fs_dir_operations = { |
e69e7fe5b [PATCH] v9fs: VFS... |
238 |
.read = generic_read_dir, |
59af1584b [PATCH] fix ->lls... |
239 |
.llseek = generic_file_llseek, |
5963ded8f 9p: switch to ->i... |
240 |
.iterate_shared = v9fs_dir_readdir, |
e69e7fe5b [PATCH] v9fs: VFS... |
241 242 243 |
.open = v9fs_file_open, .release = v9fs_dir_release, }; |
9b6533c9b 9p: VFS switches ... |
244 245 246 247 |
const struct file_operations v9fs_dir_operations_dotl = { .read = generic_read_dir, .llseek = generic_file_llseek, |
5963ded8f 9p: switch to ->i... |
248 |
.iterate_shared = v9fs_dir_readdir_dotl, |
9b6533c9b 9p: VFS switches ... |
249 250 |
.open = v9fs_file_open, .release = v9fs_dir_release, |
b165d6014 9p: Add datasync ... |
251 |
.fsync = v9fs_file_fsync_dotl, |
9b6533c9b 9p: VFS switches ... |
252 |
}; |