Blame view

fs/9p/vfs_dir.c 5.68 KB
e69e7fe5b   Eric Van Hensbergen   [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   Eric Van Hensbergen   [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   Eric Van Hensbergen   [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   Al Viro   [PATCH] severing ...
32
  #include <linux/sched.h>
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
33
34
  #include <linux/inet.h>
  #include <linux/idr.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
35
  #include <linux/slab.h>
e1200fe68   Al Viro   9p: switch p9_cli...
36
  #include <linux/uio.h>
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
37
38
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
39

e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
40
  #include "v9fs.h"
531b1094b   Latchesar Ionkov   [PATCH] v9fs: zer...
41
  #include "v9fs_vfs.h"
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
42
43
44
  #include "fid.h"
  
  /**
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
45
   * struct p9_rdir - readdir accounting
3e2796a90   Eric Van Hensbergen   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   Eric Van Hensbergen   9p: fix readdir c...
55
56
  	int head;
  	int tail;
7ffdea7ea   Al Viro   locking in fs/9p ...
57
  	uint8_t buf[];
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
58
59
60
  };
  
  /**
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
61
62
63
64
   * dt_type - return file type
   * @mistat: mistat structure
   *
   */
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
65
  static inline int dt_type(struct p9_wstat *mistat)
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
66
67
68
  {
  	unsigned long perm = mistat->mode;
  	int rettype = DT_REG;
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
69
  	if (perm & P9_DMDIR)
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
70
  		rettype = DT_DIR;
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
71
  	if (perm & P9_DMSYMLINK)
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
72
73
74
75
  		rettype = DT_LNK;
  
  	return rettype;
  }
fae4528b2   Aneesh Kumar K.V   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   Eric Van Hensbergen   [PATCH] v9fs: VFS...
84
  /**
7751bdb3a   Sripathi Kodi   9p: readdir imple...
85
   * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
ee443996a   Eric Van Hensbergen   9p: Documentation...
86
   * @filp: opened file structure
7751bdb3a   Sripathi Kodi   9p: readdir imple...
87
   * @buflen: Length in bytes of buffer to allocate
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
88
89
   *
   */
7ffdea7ea   Al Viro   locking in fs/9p ...
90
  static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen)
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
91
  {
7ffdea7ea   Al Viro   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   Sripathi Kodi   9p: readdir imple...
96
97
98
  }
  
  /**
8f29843a5   Al Viro   [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   Sripathi Kodi   9p: readdir imple...
102
103
   *
   */
8f29843a5   Al Viro   [readdir] convert 9p
104
  static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
7751bdb3a   Sripathi Kodi   9p: readdir imple...
105
  {
8f29843a5   Al Viro   [readdir] convert 9p
106
  	bool over;
7751bdb3a   Sripathi Kodi   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   Al Viro   9p: switch p9_cli...
113
  	struct kvec kvec;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
114

4b8e99239   Al Viro   9p: switch to %p[dD]
115
116
  	p9_debug(P9_DEBUG_VFS, "name %pD
  ", file);
8f29843a5   Al Viro   [readdir] convert 9p
117
  	fid = file->private_data;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
118
119
  
  	buflen = fid->clnt->msize - P9_IOHDRSZ;
8f29843a5   Al Viro   [readdir] convert 9p
120
  	rdir = v9fs_alloc_rdir_buf(file, buflen);
7ffdea7ea   Al Viro   locking in fs/9p ...
121
122
  	if (!rdir)
  		return -ENOMEM;
e1200fe68   Al Viro   9p: switch p9_cli...
123
124
  	kvec.iov_base = rdir->buf;
  	kvec.iov_len = buflen;
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
125

7ffdea7ea   Al Viro   locking in fs/9p ...
126
  	while (1) {
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
127
  		if (rdir->tail == rdir->head) {
e1200fe68   Al Viro   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   Al Viro   locking in fs/9p ...
134
  				return err;
8e3c50059   Johannes Berg   fs/9p: fix readdir()
135
136
  			if (n == 0)
  				return 0;
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
137
138
  
  			rdir->head = 0;
e1200fe68   Al Viro   9p: switch p9_cli...
139
  			rdir->tail = n;
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
140
  		}
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
141
  		while (rdir->head < rdir->tail) {
fae4528b2   Aneesh Kumar K.V   fs/9p: re-init th...
142
  			p9stat_init(&st);
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
143
144
  			err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
  					  rdir->tail - rdir->head, &st);
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
145
  			if (err) {
5d3851530   Joe Perches   9p: Reduce object...
146
147
  				p9_debug(P9_DEBUG_VFS, "returned %d
  ", err);
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
148
  				p9stat_free(&st);
7ffdea7ea   Al Viro   locking in fs/9p ...
149
  				return -EIO;
06b55b464   Eric Van Hensbergen   9p: move dirread ...
150
  			}
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
151
  			reclen = st.size+2;
06b55b464   Eric Van Hensbergen   9p: move dirread ...
152

8f29843a5   Al Viro   [readdir] convert 9p
153
154
  			over = !dir_emit(ctx, st.name, strlen(st.name),
  					 v9fs_qid2ino(&st.qid), dt_type(&st));
02da398b9   Eric Van Hensbergen   9p: eliminate dep...
155
  			p9stat_free(&st);
7ffdea7ea   Al Viro   locking in fs/9p ...
156
157
  			if (over)
  				return 0;
3e2796a90   Eric Van Hensbergen   9p: fix readdir c...
158
  			rdir->head += reclen;
8f29843a5   Al Viro   [readdir] convert 9p
159
  			ctx->pos += reclen;
06b55b464   Eric Van Hensbergen   9p: move dirread ...
160
  		}
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
161
  	}
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
162
  }
7751bdb3a   Sripathi Kodi   9p: readdir imple...
163
  /**
8f29843a5   Al Viro   [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   Sripathi Kodi   9p: readdir imple...
167
168
   *
   */
8f29843a5   Al Viro   [readdir] convert 9p
169
  static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx)
7751bdb3a   Sripathi Kodi   9p: readdir imple...
170
  {
7751bdb3a   Sripathi Kodi   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   Sripathi Kodi   9p: readdir imple...
176

4b8e99239   Al Viro   9p: switch to %p[dD]
177
178
  	p9_debug(P9_DEBUG_VFS, "name %pD
  ", file);
8f29843a5   Al Viro   [readdir] convert 9p
179
  	fid = file->private_data;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
180
181
  
  	buflen = fid->clnt->msize - P9_READDIRHDRSZ;
8f29843a5   Al Viro   [readdir] convert 9p
182
  	rdir = v9fs_alloc_rdir_buf(file, buflen);
7ffdea7ea   Al Viro   locking in fs/9p ...
183
184
  	if (!rdir)
  		return -ENOMEM;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
185

7ffdea7ea   Al Viro   locking in fs/9p ...
186
  	while (1) {
7751bdb3a   Sripathi Kodi   9p: readdir imple...
187
188
  		if (rdir->tail == rdir->head) {
  			err = p9_client_readdir(fid, rdir->buf, buflen,
8f29843a5   Al Viro   [readdir] convert 9p
189
  						ctx->pos);
7751bdb3a   Sripathi Kodi   9p: readdir imple...
190
  			if (err <= 0)
7ffdea7ea   Al Viro   locking in fs/9p ...
191
  				return err;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
192
193
194
195
196
197
  
  			rdir->head = 0;
  			rdir->tail = err;
  		}
  
  		while (rdir->head < rdir->tail) {
348b59012   Aneesh Kumar K.V   net/9p: Convert n...
198
199
200
  			err = p9dirent_read(fid->clnt, rdir->buf + rdir->head,
  					    rdir->tail - rdir->head,
  					    &curdirent);
7751bdb3a   Sripathi Kodi   9p: readdir imple...
201
  			if (err < 0) {
5d3851530   Joe Perches   9p: Reduce object...
202
203
  				p9_debug(P9_DEBUG_VFS, "returned %d
  ", err);
7ffdea7ea   Al Viro   locking in fs/9p ...
204
  				return -EIO;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
205
  			}
8f29843a5   Al Viro   [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   Al Viro   locking in fs/9p ...
210
  				return 0;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
211

8f29843a5   Al Viro   [readdir] convert 9p
212
  			ctx->pos = curdirent.d_off;
7751bdb3a   Sripathi Kodi   9p: readdir imple...
213
214
215
  			rdir->head += err;
  		}
  	}
7751bdb3a   Sripathi Kodi   9p: readdir imple...
216
  }
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
217

e69e7fe5b   Eric Van Hensbergen   [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   Latchesar Ionkov   9p: Reorganizatio...
227
  	struct p9_fid *fid;
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
228

bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
229
  	fid = filp->private_data;
5d3851530   Joe Perches   9p: Reduce object...
230
231
232
  	p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d
  ",
  		 inode, filp, fid ? fid->fid : -1);
62726a7ab   jvrao   9p: Check for NUL...
233
234
  	if (fid)
  		p9_client_clunk(fid);
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
235
236
  	return 0;
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
237
  const struct file_operations v9fs_dir_operations = {
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
238
  	.read = generic_read_dir,
59af1584b   Al Viro   [PATCH] fix ->lls...
239
  	.llseek = generic_file_llseek,
5963ded8f   Al Viro   9p: switch to ->i...
240
  	.iterate_shared = v9fs_dir_readdir,
e69e7fe5b   Eric Van Hensbergen   [PATCH] v9fs: VFS...
241
242
243
  	.open = v9fs_file_open,
  	.release = v9fs_dir_release,
  };
9b6533c9b   Sripathi Kodi   9p: VFS switches ...
244
245
246
247
  
  const struct file_operations v9fs_dir_operations_dotl = {
  	.read = generic_read_dir,
  	.llseek = generic_file_llseek,
5963ded8f   Al Viro   9p: switch to ->i...
248
  	.iterate_shared = v9fs_dir_readdir_dotl,
9b6533c9b   Sripathi Kodi   9p: VFS switches ...
249
250
  	.open = v9fs_file_open,
  	.release = v9fs_dir_release,
b165d6014   Venkateswararao Jujjuri (JV)   9p: Add datasync ...
251
          .fsync = v9fs_file_fsync_dotl,
9b6533c9b   Sripathi Kodi   9p: VFS switches ...
252
  };