Commit 1421e98662f1cab802e0fa39d16b8dc6b874a4eb

Authored by Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  fs/9p: Don't use dotl version of mknod for dotu inode operations
  fs/9p: Use the correct dentry operations
  9p: Check for NULL fid in v9fs_dir_release()
  fs/9p: Fix error handling in v9fs_get_sb
  fs/9p, net/9p: memory leak fixes

Showing 4 changed files Inline Diff

1 /* 1 /*
2 * linux/fs/9p/vfs_dir.c 2 * linux/fs/9p/vfs_dir.c
3 * 3 *
4 * This file contains vfs directory ops for the 9P2000 protocol. 4 * This file contains vfs directory ops for the 9P2000 protocol.
5 * 5 *
6 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 6 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation. 11 * as published by the Free Software Foundation.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to: 19 * along with this program; if not, write to:
20 * Free Software Foundation 20 * Free Software Foundation
21 * 51 Franklin Street, Fifth Floor 21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02111-1301 USA 22 * Boston, MA 02111-1301 USA
23 * 23 *
24 */ 24 */
25 25
26 #include <linux/module.h> 26 #include <linux/module.h>
27 #include <linux/errno.h> 27 #include <linux/errno.h>
28 #include <linux/fs.h> 28 #include <linux/fs.h>
29 #include <linux/file.h> 29 #include <linux/file.h>
30 #include <linux/stat.h> 30 #include <linux/stat.h>
31 #include <linux/string.h> 31 #include <linux/string.h>
32 #include <linux/sched.h> 32 #include <linux/sched.h>
33 #include <linux/inet.h> 33 #include <linux/inet.h>
34 #include <linux/idr.h> 34 #include <linux/idr.h>
35 #include <linux/slab.h> 35 #include <linux/slab.h>
36 #include <net/9p/9p.h> 36 #include <net/9p/9p.h>
37 #include <net/9p/client.h> 37 #include <net/9p/client.h>
38 38
39 #include "v9fs.h" 39 #include "v9fs.h"
40 #include "v9fs_vfs.h" 40 #include "v9fs_vfs.h"
41 #include "fid.h" 41 #include "fid.h"
42 42
43 /** 43 /**
44 * struct p9_rdir - readdir accounting 44 * struct p9_rdir - readdir accounting
45 * @mutex: mutex protecting readdir 45 * @mutex: mutex protecting readdir
46 * @head: start offset of current dirread buffer 46 * @head: start offset of current dirread buffer
47 * @tail: end offset of current dirread buffer 47 * @tail: end offset of current dirread buffer
48 * @buf: dirread buffer 48 * @buf: dirread buffer
49 * 49 *
50 * private structure for keeping track of readdir 50 * private structure for keeping track of readdir
51 * allocated on demand 51 * allocated on demand
52 */ 52 */
53 53
54 struct p9_rdir { 54 struct p9_rdir {
55 struct mutex mutex; 55 struct mutex mutex;
56 int head; 56 int head;
57 int tail; 57 int tail;
58 uint8_t *buf; 58 uint8_t *buf;
59 }; 59 };
60 60
61 /** 61 /**
62 * dt_type - return file type 62 * dt_type - return file type
63 * @mistat: mistat structure 63 * @mistat: mistat structure
64 * 64 *
65 */ 65 */
66 66
67 static inline int dt_type(struct p9_wstat *mistat) 67 static inline int dt_type(struct p9_wstat *mistat)
68 { 68 {
69 unsigned long perm = mistat->mode; 69 unsigned long perm = mistat->mode;
70 int rettype = DT_REG; 70 int rettype = DT_REG;
71 71
72 if (perm & P9_DMDIR) 72 if (perm & P9_DMDIR)
73 rettype = DT_DIR; 73 rettype = DT_DIR;
74 if (perm & P9_DMSYMLINK) 74 if (perm & P9_DMSYMLINK)
75 rettype = DT_LNK; 75 rettype = DT_LNK;
76 76
77 return rettype; 77 return rettype;
78 } 78 }
79 79
80 static void p9stat_init(struct p9_wstat *stbuf) 80 static void p9stat_init(struct p9_wstat *stbuf)
81 { 81 {
82 stbuf->name = NULL; 82 stbuf->name = NULL;
83 stbuf->uid = NULL; 83 stbuf->uid = NULL;
84 stbuf->gid = NULL; 84 stbuf->gid = NULL;
85 stbuf->muid = NULL; 85 stbuf->muid = NULL;
86 stbuf->extension = NULL; 86 stbuf->extension = NULL;
87 } 87 }
88 88
89 /** 89 /**
90 * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir 90 * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
91 * @filp: opened file structure 91 * @filp: opened file structure
92 * @buflen: Length in bytes of buffer to allocate 92 * @buflen: Length in bytes of buffer to allocate
93 * 93 *
94 */ 94 */
95 95
96 static int v9fs_alloc_rdir_buf(struct file *filp, int buflen) 96 static int v9fs_alloc_rdir_buf(struct file *filp, int buflen)
97 { 97 {
98 struct p9_rdir *rdir; 98 struct p9_rdir *rdir;
99 struct p9_fid *fid; 99 struct p9_fid *fid;
100 int err = 0; 100 int err = 0;
101 101
102 fid = filp->private_data; 102 fid = filp->private_data;
103 if (!fid->rdir) { 103 if (!fid->rdir) {
104 rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); 104 rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);
105 105
106 if (rdir == NULL) { 106 if (rdir == NULL) {
107 err = -ENOMEM; 107 err = -ENOMEM;
108 goto exit; 108 goto exit;
109 } 109 }
110 spin_lock(&filp->f_dentry->d_lock); 110 spin_lock(&filp->f_dentry->d_lock);
111 if (!fid->rdir) { 111 if (!fid->rdir) {
112 rdir->buf = (uint8_t *)rdir + sizeof(struct p9_rdir); 112 rdir->buf = (uint8_t *)rdir + sizeof(struct p9_rdir);
113 mutex_init(&rdir->mutex); 113 mutex_init(&rdir->mutex);
114 rdir->head = rdir->tail = 0; 114 rdir->head = rdir->tail = 0;
115 fid->rdir = (void *) rdir; 115 fid->rdir = (void *) rdir;
116 rdir = NULL; 116 rdir = NULL;
117 } 117 }
118 spin_unlock(&filp->f_dentry->d_lock); 118 spin_unlock(&filp->f_dentry->d_lock);
119 kfree(rdir); 119 kfree(rdir);
120 } 120 }
121 exit: 121 exit:
122 return err; 122 return err;
123 } 123 }
124 124
125 /** 125 /**
126 * v9fs_dir_readdir - read a directory 126 * v9fs_dir_readdir - read a directory
127 * @filp: opened file structure 127 * @filp: opened file structure
128 * @dirent: directory structure ??? 128 * @dirent: directory structure ???
129 * @filldir: function to populate directory structure ??? 129 * @filldir: function to populate directory structure ???
130 * 130 *
131 */ 131 */
132 132
133 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) 133 static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
134 { 134 {
135 int over; 135 int over;
136 struct p9_wstat st; 136 struct p9_wstat st;
137 int err = 0; 137 int err = 0;
138 struct p9_fid *fid; 138 struct p9_fid *fid;
139 int buflen; 139 int buflen;
140 int reclen = 0; 140 int reclen = 0;
141 struct p9_rdir *rdir; 141 struct p9_rdir *rdir;
142 142
143 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 143 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
144 fid = filp->private_data; 144 fid = filp->private_data;
145 145
146 buflen = fid->clnt->msize - P9_IOHDRSZ; 146 buflen = fid->clnt->msize - P9_IOHDRSZ;
147 147
148 err = v9fs_alloc_rdir_buf(filp, buflen); 148 err = v9fs_alloc_rdir_buf(filp, buflen);
149 if (err) 149 if (err)
150 goto exit; 150 goto exit;
151 rdir = (struct p9_rdir *) fid->rdir; 151 rdir = (struct p9_rdir *) fid->rdir;
152 152
153 err = mutex_lock_interruptible(&rdir->mutex); 153 err = mutex_lock_interruptible(&rdir->mutex);
154 if (err) 154 if (err)
155 return err; 155 return err;
156 while (err == 0) { 156 while (err == 0) {
157 if (rdir->tail == rdir->head) { 157 if (rdir->tail == rdir->head) {
158 err = v9fs_file_readn(filp, rdir->buf, NULL, 158 err = v9fs_file_readn(filp, rdir->buf, NULL,
159 buflen, filp->f_pos); 159 buflen, filp->f_pos);
160 if (err <= 0) 160 if (err <= 0)
161 goto unlock_and_exit; 161 goto unlock_and_exit;
162 162
163 rdir->head = 0; 163 rdir->head = 0;
164 rdir->tail = err; 164 rdir->tail = err;
165 } 165 }
166 while (rdir->head < rdir->tail) { 166 while (rdir->head < rdir->tail) {
167 p9stat_init(&st); 167 p9stat_init(&st);
168 err = p9stat_read(rdir->buf + rdir->head, 168 err = p9stat_read(rdir->buf + rdir->head,
169 rdir->tail - rdir->head, &st, 169 rdir->tail - rdir->head, &st,
170 fid->clnt->proto_version); 170 fid->clnt->proto_version);
171 if (err) { 171 if (err) {
172 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); 172 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err);
173 err = -EIO; 173 err = -EIO;
174 p9stat_free(&st); 174 p9stat_free(&st);
175 goto unlock_and_exit; 175 goto unlock_and_exit;
176 } 176 }
177 reclen = st.size+2; 177 reclen = st.size+2;
178 178
179 over = filldir(dirent, st.name, strlen(st.name), 179 over = filldir(dirent, st.name, strlen(st.name),
180 filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); 180 filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st));
181 181
182 p9stat_free(&st); 182 p9stat_free(&st);
183 183
184 if (over) { 184 if (over) {
185 err = 0; 185 err = 0;
186 goto unlock_and_exit; 186 goto unlock_and_exit;
187 } 187 }
188 rdir->head += reclen; 188 rdir->head += reclen;
189 filp->f_pos += reclen; 189 filp->f_pos += reclen;
190 } 190 }
191 } 191 }
192 192
193 unlock_and_exit: 193 unlock_and_exit:
194 mutex_unlock(&rdir->mutex); 194 mutex_unlock(&rdir->mutex);
195 exit: 195 exit:
196 return err; 196 return err;
197 } 197 }
198 198
199 /** 199 /**
200 * v9fs_dir_readdir_dotl - read a directory 200 * v9fs_dir_readdir_dotl - read a directory
201 * @filp: opened file structure 201 * @filp: opened file structure
202 * @dirent: buffer to fill dirent structures 202 * @dirent: buffer to fill dirent structures
203 * @filldir: function to populate dirent structures 203 * @filldir: function to populate dirent structures
204 * 204 *
205 */ 205 */
206 static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, 206 static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent,
207 filldir_t filldir) 207 filldir_t filldir)
208 { 208 {
209 int over; 209 int over;
210 int err = 0; 210 int err = 0;
211 struct p9_fid *fid; 211 struct p9_fid *fid;
212 int buflen; 212 int buflen;
213 struct p9_rdir *rdir; 213 struct p9_rdir *rdir;
214 struct p9_dirent curdirent; 214 struct p9_dirent curdirent;
215 u64 oldoffset = 0; 215 u64 oldoffset = 0;
216 216
217 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); 217 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
218 fid = filp->private_data; 218 fid = filp->private_data;
219 219
220 buflen = fid->clnt->msize - P9_READDIRHDRSZ; 220 buflen = fid->clnt->msize - P9_READDIRHDRSZ;
221 221
222 err = v9fs_alloc_rdir_buf(filp, buflen); 222 err = v9fs_alloc_rdir_buf(filp, buflen);
223 if (err) 223 if (err)
224 goto exit; 224 goto exit;
225 rdir = (struct p9_rdir *) fid->rdir; 225 rdir = (struct p9_rdir *) fid->rdir;
226 226
227 err = mutex_lock_interruptible(&rdir->mutex); 227 err = mutex_lock_interruptible(&rdir->mutex);
228 if (err) 228 if (err)
229 return err; 229 return err;
230 230
231 while (err == 0) { 231 while (err == 0) {
232 if (rdir->tail == rdir->head) { 232 if (rdir->tail == rdir->head) {
233 err = p9_client_readdir(fid, rdir->buf, buflen, 233 err = p9_client_readdir(fid, rdir->buf, buflen,
234 filp->f_pos); 234 filp->f_pos);
235 if (err <= 0) 235 if (err <= 0)
236 goto unlock_and_exit; 236 goto unlock_and_exit;
237 237
238 rdir->head = 0; 238 rdir->head = 0;
239 rdir->tail = err; 239 rdir->tail = err;
240 } 240 }
241 241
242 while (rdir->head < rdir->tail) { 242 while (rdir->head < rdir->tail) {
243 243
244 err = p9dirent_read(rdir->buf + rdir->head, 244 err = p9dirent_read(rdir->buf + rdir->head,
245 buflen - rdir->head, &curdirent, 245 buflen - rdir->head, &curdirent,
246 fid->clnt->proto_version); 246 fid->clnt->proto_version);
247 if (err < 0) { 247 if (err < 0) {
248 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); 248 P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err);
249 err = -EIO; 249 err = -EIO;
250 goto unlock_and_exit; 250 goto unlock_and_exit;
251 } 251 }
252 252
253 /* d_off in dirent structure tracks the offset into 253 /* d_off in dirent structure tracks the offset into
254 * the next dirent in the dir. However, filldir() 254 * the next dirent in the dir. However, filldir()
255 * expects offset into the current dirent. Hence 255 * expects offset into the current dirent. Hence
256 * while calling filldir send the offset from the 256 * while calling filldir send the offset from the
257 * previous dirent structure. 257 * previous dirent structure.
258 */ 258 */
259 over = filldir(dirent, curdirent.d_name, 259 over = filldir(dirent, curdirent.d_name,
260 strlen(curdirent.d_name), 260 strlen(curdirent.d_name),
261 oldoffset, v9fs_qid2ino(&curdirent.qid), 261 oldoffset, v9fs_qid2ino(&curdirent.qid),
262 curdirent.d_type); 262 curdirent.d_type);
263 oldoffset = curdirent.d_off; 263 oldoffset = curdirent.d_off;
264 264
265 if (over) { 265 if (over) {
266 err = 0; 266 err = 0;
267 goto unlock_and_exit; 267 goto unlock_and_exit;
268 } 268 }
269 269
270 filp->f_pos = curdirent.d_off; 270 filp->f_pos = curdirent.d_off;
271 rdir->head += err; 271 rdir->head += err;
272 } 272 }
273 } 273 }
274 274
275 unlock_and_exit: 275 unlock_and_exit:
276 mutex_unlock(&rdir->mutex); 276 mutex_unlock(&rdir->mutex);
277 exit: 277 exit:
278 return err; 278 return err;
279 } 279 }
280 280
281 281
282 /** 282 /**
283 * v9fs_dir_release - close a directory 283 * v9fs_dir_release - close a directory
284 * @inode: inode of the directory 284 * @inode: inode of the directory
285 * @filp: file pointer to a directory 285 * @filp: file pointer to a directory
286 * 286 *
287 */ 287 */
288 288
289 int v9fs_dir_release(struct inode *inode, struct file *filp) 289 int v9fs_dir_release(struct inode *inode, struct file *filp)
290 { 290 {
291 struct p9_fid *fid; 291 struct p9_fid *fid;
292 292
293 fid = filp->private_data; 293 fid = filp->private_data;
294 P9_DPRINTK(P9_DEBUG_VFS, 294 P9_DPRINTK(P9_DEBUG_VFS,
295 "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid); 295 "v9fs_dir_release: inode: %p filp: %p fid: %d\n",
296 inode, filp, fid ? fid->fid : -1);
296 filemap_write_and_wait(inode->i_mapping); 297 filemap_write_and_wait(inode->i_mapping);
297 p9_client_clunk(fid); 298 if (fid)
299 p9_client_clunk(fid);
298 return 0; 300 return 0;
299 } 301 }
300 302
301 const struct file_operations v9fs_dir_operations = { 303 const struct file_operations v9fs_dir_operations = {
302 .read = generic_read_dir, 304 .read = generic_read_dir,
303 .llseek = generic_file_llseek, 305 .llseek = generic_file_llseek,
304 .readdir = v9fs_dir_readdir, 306 .readdir = v9fs_dir_readdir,
305 .open = v9fs_file_open, 307 .open = v9fs_file_open,
306 .release = v9fs_dir_release, 308 .release = v9fs_dir_release,
307 }; 309 };
308 310
309 const struct file_operations v9fs_dir_operations_dotl = { 311 const struct file_operations v9fs_dir_operations_dotl = {
310 .read = generic_read_dir, 312 .read = generic_read_dir,
311 .llseek = generic_file_llseek, 313 .llseek = generic_file_llseek,
312 .readdir = v9fs_dir_readdir_dotl, 314 .readdir = v9fs_dir_readdir_dotl,
313 .open = v9fs_file_open, 315 .open = v9fs_file_open,
314 .release = v9fs_dir_release, 316 .release = v9fs_dir_release,
315 }; 317 };
316 318
1 /* 1 /*
2 * linux/fs/9p/vfs_inode.c 2 * linux/fs/9p/vfs_inode.c
3 * 3 *
4 * This file contains vfs inode ops for the 9P2000 protocol. 4 * This file contains vfs inode ops for the 9P2000 protocol.
5 * 5 *
6 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 6 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation. 11 * as published by the Free Software Foundation.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to: 19 * along with this program; if not, write to:
20 * Free Software Foundation 20 * Free Software Foundation
21 * 51 Franklin Street, Fifth Floor 21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02111-1301 USA 22 * Boston, MA 02111-1301 USA
23 * 23 *
24 */ 24 */
25 25
26 #include <linux/module.h> 26 #include <linux/module.h>
27 #include <linux/errno.h> 27 #include <linux/errno.h>
28 #include <linux/fs.h> 28 #include <linux/fs.h>
29 #include <linux/file.h> 29 #include <linux/file.h>
30 #include <linux/pagemap.h> 30 #include <linux/pagemap.h>
31 #include <linux/stat.h> 31 #include <linux/stat.h>
32 #include <linux/string.h> 32 #include <linux/string.h>
33 #include <linux/inet.h> 33 #include <linux/inet.h>
34 #include <linux/namei.h> 34 #include <linux/namei.h>
35 #include <linux/idr.h> 35 #include <linux/idr.h>
36 #include <linux/sched.h> 36 #include <linux/sched.h>
37 #include <linux/slab.h> 37 #include <linux/slab.h>
38 #include <linux/xattr.h> 38 #include <linux/xattr.h>
39 #include <net/9p/9p.h> 39 #include <net/9p/9p.h>
40 #include <net/9p/client.h> 40 #include <net/9p/client.h>
41 41
42 #include "v9fs.h" 42 #include "v9fs.h"
43 #include "v9fs_vfs.h" 43 #include "v9fs_vfs.h"
44 #include "fid.h" 44 #include "fid.h"
45 #include "cache.h" 45 #include "cache.h"
46 #include "xattr.h" 46 #include "xattr.h"
47 47
48 static const struct inode_operations v9fs_dir_inode_operations; 48 static const struct inode_operations v9fs_dir_inode_operations;
49 static const struct inode_operations v9fs_dir_inode_operations_dotu; 49 static const struct inode_operations v9fs_dir_inode_operations_dotu;
50 static const struct inode_operations v9fs_dir_inode_operations_dotl; 50 static const struct inode_operations v9fs_dir_inode_operations_dotl;
51 static const struct inode_operations v9fs_file_inode_operations; 51 static const struct inode_operations v9fs_file_inode_operations;
52 static const struct inode_operations v9fs_file_inode_operations_dotl; 52 static const struct inode_operations v9fs_file_inode_operations_dotl;
53 static const struct inode_operations v9fs_symlink_inode_operations; 53 static const struct inode_operations v9fs_symlink_inode_operations;
54 static const struct inode_operations v9fs_symlink_inode_operations_dotl; 54 static const struct inode_operations v9fs_symlink_inode_operations_dotl;
55 55
56 /** 56 /**
57 * unixmode2p9mode - convert unix mode bits to plan 9 57 * unixmode2p9mode - convert unix mode bits to plan 9
58 * @v9ses: v9fs session information 58 * @v9ses: v9fs session information
59 * @mode: mode to convert 59 * @mode: mode to convert
60 * 60 *
61 */ 61 */
62 62
63 static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode) 63 static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
64 { 64 {
65 int res; 65 int res;
66 res = mode & 0777; 66 res = mode & 0777;
67 if (S_ISDIR(mode)) 67 if (S_ISDIR(mode))
68 res |= P9_DMDIR; 68 res |= P9_DMDIR;
69 if (v9fs_proto_dotu(v9ses)) { 69 if (v9fs_proto_dotu(v9ses)) {
70 if (S_ISLNK(mode)) 70 if (S_ISLNK(mode))
71 res |= P9_DMSYMLINK; 71 res |= P9_DMSYMLINK;
72 if (v9ses->nodev == 0) { 72 if (v9ses->nodev == 0) {
73 if (S_ISSOCK(mode)) 73 if (S_ISSOCK(mode))
74 res |= P9_DMSOCKET; 74 res |= P9_DMSOCKET;
75 if (S_ISFIFO(mode)) 75 if (S_ISFIFO(mode))
76 res |= P9_DMNAMEDPIPE; 76 res |= P9_DMNAMEDPIPE;
77 if (S_ISBLK(mode)) 77 if (S_ISBLK(mode))
78 res |= P9_DMDEVICE; 78 res |= P9_DMDEVICE;
79 if (S_ISCHR(mode)) 79 if (S_ISCHR(mode))
80 res |= P9_DMDEVICE; 80 res |= P9_DMDEVICE;
81 } 81 }
82 82
83 if ((mode & S_ISUID) == S_ISUID) 83 if ((mode & S_ISUID) == S_ISUID)
84 res |= P9_DMSETUID; 84 res |= P9_DMSETUID;
85 if ((mode & S_ISGID) == S_ISGID) 85 if ((mode & S_ISGID) == S_ISGID)
86 res |= P9_DMSETGID; 86 res |= P9_DMSETGID;
87 if ((mode & S_ISVTX) == S_ISVTX) 87 if ((mode & S_ISVTX) == S_ISVTX)
88 res |= P9_DMSETVTX; 88 res |= P9_DMSETVTX;
89 if ((mode & P9_DMLINK)) 89 if ((mode & P9_DMLINK))
90 res |= P9_DMLINK; 90 res |= P9_DMLINK;
91 } 91 }
92 92
93 return res; 93 return res;
94 } 94 }
95 95
96 /** 96 /**
97 * p9mode2unixmode- convert plan9 mode bits to unix mode bits 97 * p9mode2unixmode- convert plan9 mode bits to unix mode bits
98 * @v9ses: v9fs session information 98 * @v9ses: v9fs session information
99 * @mode: mode to convert 99 * @mode: mode to convert
100 * 100 *
101 */ 101 */
102 102
103 static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) 103 static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
104 { 104 {
105 int res; 105 int res;
106 106
107 res = mode & 0777; 107 res = mode & 0777;
108 108
109 if ((mode & P9_DMDIR) == P9_DMDIR) 109 if ((mode & P9_DMDIR) == P9_DMDIR)
110 res |= S_IFDIR; 110 res |= S_IFDIR;
111 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses))) 111 else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses)))
112 res |= S_IFLNK; 112 res |= S_IFLNK;
113 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses)) 113 else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses))
114 && (v9ses->nodev == 0)) 114 && (v9ses->nodev == 0))
115 res |= S_IFSOCK; 115 res |= S_IFSOCK;
116 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses)) 116 else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses))
117 && (v9ses->nodev == 0)) 117 && (v9ses->nodev == 0))
118 res |= S_IFIFO; 118 res |= S_IFIFO;
119 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) 119 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
120 && (v9ses->nodev == 0)) 120 && (v9ses->nodev == 0))
121 res |= S_IFBLK; 121 res |= S_IFBLK;
122 else 122 else
123 res |= S_IFREG; 123 res |= S_IFREG;
124 124
125 if (v9fs_proto_dotu(v9ses)) { 125 if (v9fs_proto_dotu(v9ses)) {
126 if ((mode & P9_DMSETUID) == P9_DMSETUID) 126 if ((mode & P9_DMSETUID) == P9_DMSETUID)
127 res |= S_ISUID; 127 res |= S_ISUID;
128 128
129 if ((mode & P9_DMSETGID) == P9_DMSETGID) 129 if ((mode & P9_DMSETGID) == P9_DMSETGID)
130 res |= S_ISGID; 130 res |= S_ISGID;
131 131
132 if ((mode & P9_DMSETVTX) == P9_DMSETVTX) 132 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
133 res |= S_ISVTX; 133 res |= S_ISVTX;
134 } 134 }
135 135
136 return res; 136 return res;
137 } 137 }
138 138
139 /** 139 /**
140 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits 140 * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
141 * @uflags: flags to convert 141 * @uflags: flags to convert
142 * @extended: if .u extensions are active 142 * @extended: if .u extensions are active
143 */ 143 */
144 144
145 int v9fs_uflags2omode(int uflags, int extended) 145 int v9fs_uflags2omode(int uflags, int extended)
146 { 146 {
147 int ret; 147 int ret;
148 148
149 ret = 0; 149 ret = 0;
150 switch (uflags&3) { 150 switch (uflags&3) {
151 default: 151 default:
152 case O_RDONLY: 152 case O_RDONLY:
153 ret = P9_OREAD; 153 ret = P9_OREAD;
154 break; 154 break;
155 155
156 case O_WRONLY: 156 case O_WRONLY:
157 ret = P9_OWRITE; 157 ret = P9_OWRITE;
158 break; 158 break;
159 159
160 case O_RDWR: 160 case O_RDWR:
161 ret = P9_ORDWR; 161 ret = P9_ORDWR;
162 break; 162 break;
163 } 163 }
164 164
165 if (uflags & O_TRUNC) 165 if (uflags & O_TRUNC)
166 ret |= P9_OTRUNC; 166 ret |= P9_OTRUNC;
167 167
168 if (extended) { 168 if (extended) {
169 if (uflags & O_EXCL) 169 if (uflags & O_EXCL)
170 ret |= P9_OEXCL; 170 ret |= P9_OEXCL;
171 171
172 if (uflags & O_APPEND) 172 if (uflags & O_APPEND)
173 ret |= P9_OAPPEND; 173 ret |= P9_OAPPEND;
174 } 174 }
175 175
176 return ret; 176 return ret;
177 } 177 }
178 178
179 /** 179 /**
180 * v9fs_blank_wstat - helper function to setup a 9P stat structure 180 * v9fs_blank_wstat - helper function to setup a 9P stat structure
181 * @wstat: structure to initialize 181 * @wstat: structure to initialize
182 * 182 *
183 */ 183 */
184 184
185 void 185 void
186 v9fs_blank_wstat(struct p9_wstat *wstat) 186 v9fs_blank_wstat(struct p9_wstat *wstat)
187 { 187 {
188 wstat->type = ~0; 188 wstat->type = ~0;
189 wstat->dev = ~0; 189 wstat->dev = ~0;
190 wstat->qid.type = ~0; 190 wstat->qid.type = ~0;
191 wstat->qid.version = ~0; 191 wstat->qid.version = ~0;
192 *((long long *)&wstat->qid.path) = ~0; 192 *((long long *)&wstat->qid.path) = ~0;
193 wstat->mode = ~0; 193 wstat->mode = ~0;
194 wstat->atime = ~0; 194 wstat->atime = ~0;
195 wstat->mtime = ~0; 195 wstat->mtime = ~0;
196 wstat->length = ~0; 196 wstat->length = ~0;
197 wstat->name = NULL; 197 wstat->name = NULL;
198 wstat->uid = NULL; 198 wstat->uid = NULL;
199 wstat->gid = NULL; 199 wstat->gid = NULL;
200 wstat->muid = NULL; 200 wstat->muid = NULL;
201 wstat->n_uid = ~0; 201 wstat->n_uid = ~0;
202 wstat->n_gid = ~0; 202 wstat->n_gid = ~0;
203 wstat->n_muid = ~0; 203 wstat->n_muid = ~0;
204 wstat->extension = NULL; 204 wstat->extension = NULL;
205 } 205 }
206 206
207 #ifdef CONFIG_9P_FSCACHE 207 #ifdef CONFIG_9P_FSCACHE
208 /** 208 /**
209 * v9fs_alloc_inode - helper function to allocate an inode 209 * v9fs_alloc_inode - helper function to allocate an inode
210 * This callback is executed before setting up the inode so that we 210 * This callback is executed before setting up the inode so that we
211 * can associate a vcookie with each inode. 211 * can associate a vcookie with each inode.
212 * 212 *
213 */ 213 */
214 214
215 struct inode *v9fs_alloc_inode(struct super_block *sb) 215 struct inode *v9fs_alloc_inode(struct super_block *sb)
216 { 216 {
217 struct v9fs_cookie *vcookie; 217 struct v9fs_cookie *vcookie;
218 vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache, 218 vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
219 GFP_KERNEL); 219 GFP_KERNEL);
220 if (!vcookie) 220 if (!vcookie)
221 return NULL; 221 return NULL;
222 222
223 vcookie->fscache = NULL; 223 vcookie->fscache = NULL;
224 vcookie->qid = NULL; 224 vcookie->qid = NULL;
225 spin_lock_init(&vcookie->lock); 225 spin_lock_init(&vcookie->lock);
226 return &vcookie->inode; 226 return &vcookie->inode;
227 } 227 }
228 228
229 /** 229 /**
230 * v9fs_destroy_inode - destroy an inode 230 * v9fs_destroy_inode - destroy an inode
231 * 231 *
232 */ 232 */
233 233
234 void v9fs_destroy_inode(struct inode *inode) 234 void v9fs_destroy_inode(struct inode *inode)
235 { 235 {
236 kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode)); 236 kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
237 } 237 }
238 #endif 238 #endif
239 239
240 /** 240 /**
241 * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a 241 * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a
242 * new file system object. This checks the S_ISGID to determine the owning 242 * new file system object. This checks the S_ISGID to determine the owning
243 * group of the new file system object. 243 * group of the new file system object.
244 */ 244 */
245 245
246 static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) 246 static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
247 { 247 {
248 BUG_ON(dir_inode == NULL); 248 BUG_ON(dir_inode == NULL);
249 249
250 if (dir_inode->i_mode & S_ISGID) { 250 if (dir_inode->i_mode & S_ISGID) {
251 /* set_gid bit is set.*/ 251 /* set_gid bit is set.*/
252 return dir_inode->i_gid; 252 return dir_inode->i_gid;
253 } 253 }
254 return current_fsgid(); 254 return current_fsgid();
255 } 255 }
256 256
257 /** 257 /**
258 * v9fs_dentry_from_dir_inode - helper function to get the dentry from 258 * v9fs_dentry_from_dir_inode - helper function to get the dentry from
259 * dir inode. 259 * dir inode.
260 * 260 *
261 */ 261 */
262 262
263 static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) 263 static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
264 { 264 {
265 struct dentry *dentry; 265 struct dentry *dentry;
266 266
267 spin_lock(&dcache_lock); 267 spin_lock(&dcache_lock);
268 /* Directory should have only one entry. */ 268 /* Directory should have only one entry. */
269 BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); 269 BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
270 dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); 270 dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
271 spin_unlock(&dcache_lock); 271 spin_unlock(&dcache_lock);
272 return dentry; 272 return dentry;
273 } 273 }
274 274
275 /** 275 /**
276 * v9fs_get_inode - helper function to setup an inode 276 * v9fs_get_inode - helper function to setup an inode
277 * @sb: superblock 277 * @sb: superblock
278 * @mode: mode to setup inode with 278 * @mode: mode to setup inode with
279 * 279 *
280 */ 280 */
281 281
282 struct inode *v9fs_get_inode(struct super_block *sb, int mode) 282 struct inode *v9fs_get_inode(struct super_block *sb, int mode)
283 { 283 {
284 int err; 284 int err;
285 struct inode *inode; 285 struct inode *inode;
286 struct v9fs_session_info *v9ses = sb->s_fs_info; 286 struct v9fs_session_info *v9ses = sb->s_fs_info;
287 287
288 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 288 P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
289 289
290 inode = new_inode(sb); 290 inode = new_inode(sb);
291 if (!inode) { 291 if (!inode) {
292 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); 292 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
293 return ERR_PTR(-ENOMEM); 293 return ERR_PTR(-ENOMEM);
294 } 294 }
295 295
296 inode_init_owner(inode, NULL, mode); 296 inode_init_owner(inode, NULL, mode);
297 inode->i_blocks = 0; 297 inode->i_blocks = 0;
298 inode->i_rdev = 0; 298 inode->i_rdev = 0;
299 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 299 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
300 inode->i_mapping->a_ops = &v9fs_addr_operations; 300 inode->i_mapping->a_ops = &v9fs_addr_operations;
301 301
302 switch (mode & S_IFMT) { 302 switch (mode & S_IFMT) {
303 case S_IFIFO: 303 case S_IFIFO:
304 case S_IFBLK: 304 case S_IFBLK:
305 case S_IFCHR: 305 case S_IFCHR:
306 case S_IFSOCK: 306 case S_IFSOCK:
307 if (v9fs_proto_dotl(v9ses)) { 307 if (v9fs_proto_dotl(v9ses)) {
308 inode->i_op = &v9fs_file_inode_operations_dotl; 308 inode->i_op = &v9fs_file_inode_operations_dotl;
309 inode->i_fop = &v9fs_file_operations_dotl; 309 inode->i_fop = &v9fs_file_operations_dotl;
310 } else if (v9fs_proto_dotu(v9ses)) { 310 } else if (v9fs_proto_dotu(v9ses)) {
311 inode->i_op = &v9fs_file_inode_operations; 311 inode->i_op = &v9fs_file_inode_operations;
312 inode->i_fop = &v9fs_file_operations; 312 inode->i_fop = &v9fs_file_operations;
313 } else { 313 } else {
314 P9_DPRINTK(P9_DEBUG_ERROR, 314 P9_DPRINTK(P9_DEBUG_ERROR,
315 "special files without extended mode\n"); 315 "special files without extended mode\n");
316 err = -EINVAL; 316 err = -EINVAL;
317 goto error; 317 goto error;
318 } 318 }
319 init_special_inode(inode, inode->i_mode, inode->i_rdev); 319 init_special_inode(inode, inode->i_mode, inode->i_rdev);
320 break; 320 break;
321 case S_IFREG: 321 case S_IFREG:
322 if (v9fs_proto_dotl(v9ses)) { 322 if (v9fs_proto_dotl(v9ses)) {
323 inode->i_op = &v9fs_file_inode_operations_dotl; 323 inode->i_op = &v9fs_file_inode_operations_dotl;
324 inode->i_fop = &v9fs_file_operations_dotl; 324 inode->i_fop = &v9fs_file_operations_dotl;
325 } else { 325 } else {
326 inode->i_op = &v9fs_file_inode_operations; 326 inode->i_op = &v9fs_file_inode_operations;
327 inode->i_fop = &v9fs_file_operations; 327 inode->i_fop = &v9fs_file_operations;
328 } 328 }
329 329
330 break; 330 break;
331 331
332 case S_IFLNK: 332 case S_IFLNK:
333 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { 333 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
334 P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with " 334 P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with "
335 "legacy protocol.\n"); 335 "legacy protocol.\n");
336 err = -EINVAL; 336 err = -EINVAL;
337 goto error; 337 goto error;
338 } 338 }
339 339
340 if (v9fs_proto_dotl(v9ses)) 340 if (v9fs_proto_dotl(v9ses))
341 inode->i_op = &v9fs_symlink_inode_operations_dotl; 341 inode->i_op = &v9fs_symlink_inode_operations_dotl;
342 else 342 else
343 inode->i_op = &v9fs_symlink_inode_operations; 343 inode->i_op = &v9fs_symlink_inode_operations;
344 344
345 break; 345 break;
346 case S_IFDIR: 346 case S_IFDIR:
347 inc_nlink(inode); 347 inc_nlink(inode);
348 if (v9fs_proto_dotl(v9ses)) 348 if (v9fs_proto_dotl(v9ses))
349 inode->i_op = &v9fs_dir_inode_operations_dotl; 349 inode->i_op = &v9fs_dir_inode_operations_dotl;
350 else if (v9fs_proto_dotu(v9ses)) 350 else if (v9fs_proto_dotu(v9ses))
351 inode->i_op = &v9fs_dir_inode_operations_dotu; 351 inode->i_op = &v9fs_dir_inode_operations_dotu;
352 else 352 else
353 inode->i_op = &v9fs_dir_inode_operations; 353 inode->i_op = &v9fs_dir_inode_operations;
354 354
355 if (v9fs_proto_dotl(v9ses)) 355 if (v9fs_proto_dotl(v9ses))
356 inode->i_fop = &v9fs_dir_operations_dotl; 356 inode->i_fop = &v9fs_dir_operations_dotl;
357 else 357 else
358 inode->i_fop = &v9fs_dir_operations; 358 inode->i_fop = &v9fs_dir_operations;
359 359
360 break; 360 break;
361 default: 361 default:
362 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", 362 P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
363 mode, mode & S_IFMT); 363 mode, mode & S_IFMT);
364 err = -EINVAL; 364 err = -EINVAL;
365 goto error; 365 goto error;
366 } 366 }
367 367
368 return inode; 368 return inode;
369 369
370 error: 370 error:
371 iput(inode); 371 iput(inode);
372 return ERR_PTR(err); 372 return ERR_PTR(err);
373 } 373 }
374 374
375 /* 375 /*
376 static struct v9fs_fid* 376 static struct v9fs_fid*
377 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) 377 v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
378 { 378 {
379 int err; 379 int err;
380 int nfid; 380 int nfid;
381 struct v9fs_fid *ret; 381 struct v9fs_fid *ret;
382 struct v9fs_fcall *fcall; 382 struct v9fs_fcall *fcall;
383 383
384 nfid = v9fs_get_idpool(&v9ses->fidpool); 384 nfid = v9fs_get_idpool(&v9ses->fidpool);
385 if (nfid < 0) { 385 if (nfid < 0) {
386 eprintk(KERN_WARNING, "no free fids available\n"); 386 eprintk(KERN_WARNING, "no free fids available\n");
387 return ERR_PTR(-ENOSPC); 387 return ERR_PTR(-ENOSPC);
388 } 388 }
389 389
390 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, 390 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
391 &fcall); 391 &fcall);
392 392
393 if (err < 0) { 393 if (err < 0) {
394 if (fcall && fcall->id == RWALK) 394 if (fcall && fcall->id == RWALK)
395 goto clunk_fid; 395 goto clunk_fid;
396 396
397 PRINT_FCALL_ERROR("walk error", fcall); 397 PRINT_FCALL_ERROR("walk error", fcall);
398 v9fs_put_idpool(nfid, &v9ses->fidpool); 398 v9fs_put_idpool(nfid, &v9ses->fidpool);
399 goto error; 399 goto error;
400 } 400 }
401 401
402 kfree(fcall); 402 kfree(fcall);
403 fcall = NULL; 403 fcall = NULL;
404 ret = v9fs_fid_create(v9ses, nfid); 404 ret = v9fs_fid_create(v9ses, nfid);
405 if (!ret) { 405 if (!ret) {
406 err = -ENOMEM; 406 err = -ENOMEM;
407 goto clunk_fid; 407 goto clunk_fid;
408 } 408 }
409 409
410 err = v9fs_fid_insert(ret, dentry); 410 err = v9fs_fid_insert(ret, dentry);
411 if (err < 0) { 411 if (err < 0) {
412 v9fs_fid_destroy(ret); 412 v9fs_fid_destroy(ret);
413 goto clunk_fid; 413 goto clunk_fid;
414 } 414 }
415 415
416 return ret; 416 return ret;
417 417
418 clunk_fid: 418 clunk_fid:
419 v9fs_t_clunk(v9ses, nfid); 419 v9fs_t_clunk(v9ses, nfid);
420 420
421 error: 421 error:
422 kfree(fcall); 422 kfree(fcall);
423 return ERR_PTR(err); 423 return ERR_PTR(err);
424 } 424 }
425 */ 425 */
426 426
427 427
428 /** 428 /**
429 * v9fs_clear_inode - release an inode 429 * v9fs_clear_inode - release an inode
430 * @inode: inode to release 430 * @inode: inode to release
431 * 431 *
432 */ 432 */
433 void v9fs_evict_inode(struct inode *inode) 433 void v9fs_evict_inode(struct inode *inode)
434 { 434 {
435 truncate_inode_pages(inode->i_mapping, 0); 435 truncate_inode_pages(inode->i_mapping, 0);
436 end_writeback(inode); 436 end_writeback(inode);
437 filemap_fdatawrite(inode->i_mapping); 437 filemap_fdatawrite(inode->i_mapping);
438 438
439 #ifdef CONFIG_9P_FSCACHE 439 #ifdef CONFIG_9P_FSCACHE
440 v9fs_cache_inode_put_cookie(inode); 440 v9fs_cache_inode_put_cookie(inode);
441 #endif 441 #endif
442 } 442 }
443 443
444 static struct inode * 444 static struct inode *
445 v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid, 445 v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid,
446 struct super_block *sb) 446 struct super_block *sb)
447 { 447 {
448 int err, umode; 448 int err, umode;
449 struct inode *ret = NULL; 449 struct inode *ret = NULL;
450 struct p9_wstat *st; 450 struct p9_wstat *st;
451 451
452 st = p9_client_stat(fid); 452 st = p9_client_stat(fid);
453 if (IS_ERR(st)) 453 if (IS_ERR(st))
454 return ERR_CAST(st); 454 return ERR_CAST(st);
455 455
456 umode = p9mode2unixmode(v9ses, st->mode); 456 umode = p9mode2unixmode(v9ses, st->mode);
457 ret = v9fs_get_inode(sb, umode); 457 ret = v9fs_get_inode(sb, umode);
458 if (IS_ERR(ret)) { 458 if (IS_ERR(ret)) {
459 err = PTR_ERR(ret); 459 err = PTR_ERR(ret);
460 goto error; 460 goto error;
461 } 461 }
462 462
463 v9fs_stat2inode(st, ret, sb); 463 v9fs_stat2inode(st, ret, sb);
464 ret->i_ino = v9fs_qid2ino(&st->qid); 464 ret->i_ino = v9fs_qid2ino(&st->qid);
465 465
466 #ifdef CONFIG_9P_FSCACHE 466 #ifdef CONFIG_9P_FSCACHE
467 v9fs_vcookie_set_qid(ret, &st->qid); 467 v9fs_vcookie_set_qid(ret, &st->qid);
468 v9fs_cache_inode_get_cookie(ret); 468 v9fs_cache_inode_get_cookie(ret);
469 #endif 469 #endif
470 p9stat_free(st); 470 p9stat_free(st);
471 kfree(st); 471 kfree(st);
472 return ret; 472 return ret;
473 error: 473 error:
474 p9stat_free(st); 474 p9stat_free(st);
475 kfree(st); 475 kfree(st);
476 return ERR_PTR(err); 476 return ERR_PTR(err);
477 } 477 }
478 478
479 static struct inode * 479 static struct inode *
480 v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, 480 v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
481 struct super_block *sb) 481 struct super_block *sb)
482 { 482 {
483 struct inode *ret = NULL; 483 struct inode *ret = NULL;
484 int err; 484 int err;
485 struct p9_stat_dotl *st; 485 struct p9_stat_dotl *st;
486 486
487 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 487 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
488 if (IS_ERR(st)) 488 if (IS_ERR(st))
489 return ERR_CAST(st); 489 return ERR_CAST(st);
490 490
491 ret = v9fs_get_inode(sb, st->st_mode); 491 ret = v9fs_get_inode(sb, st->st_mode);
492 if (IS_ERR(ret)) { 492 if (IS_ERR(ret)) {
493 err = PTR_ERR(ret); 493 err = PTR_ERR(ret);
494 goto error; 494 goto error;
495 } 495 }
496 496
497 v9fs_stat2inode_dotl(st, ret); 497 v9fs_stat2inode_dotl(st, ret);
498 ret->i_ino = v9fs_qid2ino(&st->qid); 498 ret->i_ino = v9fs_qid2ino(&st->qid);
499 #ifdef CONFIG_9P_FSCACHE 499 #ifdef CONFIG_9P_FSCACHE
500 v9fs_vcookie_set_qid(ret, &st->qid); 500 v9fs_vcookie_set_qid(ret, &st->qid);
501 v9fs_cache_inode_get_cookie(ret); 501 v9fs_cache_inode_get_cookie(ret);
502 #endif 502 #endif
503 kfree(st); 503 kfree(st);
504 return ret; 504 return ret;
505 error: 505 error:
506 kfree(st); 506 kfree(st);
507 return ERR_PTR(err); 507 return ERR_PTR(err);
508 } 508 }
509 509
510 /** 510 /**
511 * v9fs_inode_from_fid - Helper routine to populate an inode by 511 * v9fs_inode_from_fid - Helper routine to populate an inode by
512 * issuing a attribute request 512 * issuing a attribute request
513 * @v9ses: session information 513 * @v9ses: session information
514 * @fid: fid to issue attribute request for 514 * @fid: fid to issue attribute request for
515 * @sb: superblock on which to create inode 515 * @sb: superblock on which to create inode
516 * 516 *
517 */ 517 */
518 static inline struct inode * 518 static inline struct inode *
519 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 519 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
520 struct super_block *sb) 520 struct super_block *sb)
521 { 521 {
522 if (v9fs_proto_dotl(v9ses)) 522 if (v9fs_proto_dotl(v9ses))
523 return v9fs_inode_dotl(v9ses, fid, sb); 523 return v9fs_inode_dotl(v9ses, fid, sb);
524 else 524 else
525 return v9fs_inode(v9ses, fid, sb); 525 return v9fs_inode(v9ses, fid, sb);
526 } 526 }
527 527
528 /** 528 /**
529 * v9fs_remove - helper function to remove files and directories 529 * v9fs_remove - helper function to remove files and directories
530 * @dir: directory inode that is being deleted 530 * @dir: directory inode that is being deleted
531 * @file: dentry that is being deleted 531 * @file: dentry that is being deleted
532 * @rmdir: removing a directory 532 * @rmdir: removing a directory
533 * 533 *
534 */ 534 */
535 535
536 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 536 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
537 { 537 {
538 int retval; 538 int retval;
539 struct inode *file_inode; 539 struct inode *file_inode;
540 struct p9_fid *v9fid; 540 struct p9_fid *v9fid;
541 541
542 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, 542 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
543 rmdir); 543 rmdir);
544 544
545 file_inode = file->d_inode; 545 file_inode = file->d_inode;
546 v9fid = v9fs_fid_clone(file); 546 v9fid = v9fs_fid_clone(file);
547 if (IS_ERR(v9fid)) 547 if (IS_ERR(v9fid))
548 return PTR_ERR(v9fid); 548 return PTR_ERR(v9fid);
549 549
550 retval = p9_client_remove(v9fid); 550 retval = p9_client_remove(v9fid);
551 if (!retval) 551 if (!retval)
552 drop_nlink(file_inode); 552 drop_nlink(file_inode);
553 return retval; 553 return retval;
554 } 554 }
555 555
556 static int 556 static int
557 v9fs_open_created(struct inode *inode, struct file *file) 557 v9fs_open_created(struct inode *inode, struct file *file)
558 { 558 {
559 return 0; 559 return 0;
560 } 560 }
561 561
562 562
563 /** 563 /**
564 * v9fs_create - Create a file 564 * v9fs_create - Create a file
565 * @v9ses: session information 565 * @v9ses: session information
566 * @dir: directory that dentry is being created in 566 * @dir: directory that dentry is being created in
567 * @dentry: dentry that is being created 567 * @dentry: dentry that is being created
568 * @extension: 9p2000.u extension string to support devices, etc. 568 * @extension: 9p2000.u extension string to support devices, etc.
569 * @perm: create permissions 569 * @perm: create permissions
570 * @mode: open mode 570 * @mode: open mode
571 * 571 *
572 */ 572 */
573 static struct p9_fid * 573 static struct p9_fid *
574 v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, 574 v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
575 struct dentry *dentry, char *extension, u32 perm, u8 mode) 575 struct dentry *dentry, char *extension, u32 perm, u8 mode)
576 { 576 {
577 int err; 577 int err;
578 char *name; 578 char *name;
579 struct p9_fid *dfid, *ofid, *fid; 579 struct p9_fid *dfid, *ofid, *fid;
580 struct inode *inode; 580 struct inode *inode;
581 581
582 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 582 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
583 583
584 err = 0; 584 err = 0;
585 ofid = NULL; 585 ofid = NULL;
586 fid = NULL; 586 fid = NULL;
587 name = (char *) dentry->d_name.name; 587 name = (char *) dentry->d_name.name;
588 dfid = v9fs_fid_lookup(dentry->d_parent); 588 dfid = v9fs_fid_lookup(dentry->d_parent);
589 if (IS_ERR(dfid)) { 589 if (IS_ERR(dfid)) {
590 err = PTR_ERR(dfid); 590 err = PTR_ERR(dfid);
591 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 591 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
592 return ERR_PTR(err); 592 return ERR_PTR(err);
593 } 593 }
594 594
595 /* clone a fid to use for creation */ 595 /* clone a fid to use for creation */
596 ofid = p9_client_walk(dfid, 0, NULL, 1); 596 ofid = p9_client_walk(dfid, 0, NULL, 1);
597 if (IS_ERR(ofid)) { 597 if (IS_ERR(ofid)) {
598 err = PTR_ERR(ofid); 598 err = PTR_ERR(ofid);
599 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 599 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
600 return ERR_PTR(err); 600 return ERR_PTR(err);
601 } 601 }
602 602
603 err = p9_client_fcreate(ofid, name, perm, mode, extension); 603 err = p9_client_fcreate(ofid, name, perm, mode, extension);
604 if (err < 0) { 604 if (err < 0) {
605 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err); 605 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
606 goto error; 606 goto error;
607 } 607 }
608 608
609 /* now walk from the parent so we can get unopened fid */ 609 /* now walk from the parent so we can get unopened fid */
610 fid = p9_client_walk(dfid, 1, &name, 1); 610 fid = p9_client_walk(dfid, 1, &name, 1);
611 if (IS_ERR(fid)) { 611 if (IS_ERR(fid)) {
612 err = PTR_ERR(fid); 612 err = PTR_ERR(fid);
613 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 613 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
614 fid = NULL; 614 fid = NULL;
615 goto error; 615 goto error;
616 } 616 }
617 617
618 /* instantiate inode and assign the unopened fid to the dentry */ 618 /* instantiate inode and assign the unopened fid to the dentry */
619 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 619 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
620 if (IS_ERR(inode)) { 620 if (IS_ERR(inode)) {
621 err = PTR_ERR(inode); 621 err = PTR_ERR(inode);
622 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); 622 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
623 goto error; 623 goto error;
624 } 624 }
625 625
626 if (v9ses->cache) 626 if (v9ses->cache)
627 dentry->d_op = &v9fs_cached_dentry_operations; 627 dentry->d_op = &v9fs_cached_dentry_operations;
628 else 628 else
629 dentry->d_op = &v9fs_dentry_operations; 629 dentry->d_op = &v9fs_dentry_operations;
630 630
631 d_instantiate(dentry, inode); 631 d_instantiate(dentry, inode);
632 err = v9fs_fid_add(dentry, fid); 632 err = v9fs_fid_add(dentry, fid);
633 if (err < 0) 633 if (err < 0)
634 goto error; 634 goto error;
635 635
636 return ofid; 636 return ofid;
637 637
638 error: 638 error:
639 if (ofid) 639 if (ofid)
640 p9_client_clunk(ofid); 640 p9_client_clunk(ofid);
641 641
642 if (fid) 642 if (fid)
643 p9_client_clunk(fid); 643 p9_client_clunk(fid);
644 644
645 return ERR_PTR(err); 645 return ERR_PTR(err);
646 } 646 }
647 647
648 /** 648 /**
649 * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. 649 * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
650 * @dir: directory inode that is being created 650 * @dir: directory inode that is being created
651 * @dentry: dentry that is being deleted 651 * @dentry: dentry that is being deleted
652 * @mode: create permissions 652 * @mode: create permissions
653 * @nd: path information 653 * @nd: path information
654 * 654 *
655 */ 655 */
656 656
657 static int 657 static int
658 v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, 658 v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
659 struct nameidata *nd) 659 struct nameidata *nd)
660 { 660 {
661 int err = 0; 661 int err = 0;
662 char *name = NULL; 662 char *name = NULL;
663 gid_t gid; 663 gid_t gid;
664 int flags; 664 int flags;
665 struct v9fs_session_info *v9ses; 665 struct v9fs_session_info *v9ses;
666 struct p9_fid *fid = NULL; 666 struct p9_fid *fid = NULL;
667 struct p9_fid *dfid, *ofid; 667 struct p9_fid *dfid, *ofid;
668 struct file *filp; 668 struct file *filp;
669 struct p9_qid qid; 669 struct p9_qid qid;
670 struct inode *inode; 670 struct inode *inode;
671 671
672 v9ses = v9fs_inode2v9ses(dir); 672 v9ses = v9fs_inode2v9ses(dir);
673 if (nd && nd->flags & LOOKUP_OPEN) 673 if (nd && nd->flags & LOOKUP_OPEN)
674 flags = nd->intent.open.flags - 1; 674 flags = nd->intent.open.flags - 1;
675 else 675 else
676 flags = O_RDWR; 676 flags = O_RDWR;
677 677
678 name = (char *) dentry->d_name.name; 678 name = (char *) dentry->d_name.name;
679 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " 679 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x "
680 "mode:0x%x\n", name, flags, mode); 680 "mode:0x%x\n", name, flags, mode);
681 681
682 dfid = v9fs_fid_lookup(dentry->d_parent); 682 dfid = v9fs_fid_lookup(dentry->d_parent);
683 if (IS_ERR(dfid)) { 683 if (IS_ERR(dfid)) {
684 err = PTR_ERR(dfid); 684 err = PTR_ERR(dfid);
685 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 685 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
686 return err; 686 return err;
687 } 687 }
688 688
689 /* clone a fid to use for creation */ 689 /* clone a fid to use for creation */
690 ofid = p9_client_walk(dfid, 0, NULL, 1); 690 ofid = p9_client_walk(dfid, 0, NULL, 1);
691 if (IS_ERR(ofid)) { 691 if (IS_ERR(ofid)) {
692 err = PTR_ERR(ofid); 692 err = PTR_ERR(ofid);
693 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 693 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
694 return err; 694 return err;
695 } 695 }
696 696
697 gid = v9fs_get_fsgid_for_create(dir); 697 gid = v9fs_get_fsgid_for_create(dir);
698 err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); 698 err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
699 if (err < 0) { 699 if (err < 0) {
700 P9_DPRINTK(P9_DEBUG_VFS, 700 P9_DPRINTK(P9_DEBUG_VFS,
701 "p9_client_open_dotl failed in creat %d\n", 701 "p9_client_open_dotl failed in creat %d\n",
702 err); 702 err);
703 goto error; 703 goto error;
704 } 704 }
705 705
706 /* No need to populate the inode if we are not opening the file AND 706 /* No need to populate the inode if we are not opening the file AND
707 * not in cached mode. 707 * not in cached mode.
708 */ 708 */
709 if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) { 709 if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) {
710 /* Not in cached mode. No need to populate inode with stat */ 710 /* Not in cached mode. No need to populate inode with stat */
711 dentry->d_op = &v9fs_dentry_operations; 711 dentry->d_op = &v9fs_dentry_operations;
712 p9_client_clunk(ofid); 712 p9_client_clunk(ofid);
713 d_instantiate(dentry, NULL); 713 d_instantiate(dentry, NULL);
714 return 0; 714 return 0;
715 } 715 }
716 716
717 /* Now walk from the parent so we can get an unopened fid. */ 717 /* Now walk from the parent so we can get an unopened fid. */
718 fid = p9_client_walk(dfid, 1, &name, 1); 718 fid = p9_client_walk(dfid, 1, &name, 1);
719 if (IS_ERR(fid)) { 719 if (IS_ERR(fid)) {
720 err = PTR_ERR(fid); 720 err = PTR_ERR(fid);
721 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 721 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
722 fid = NULL; 722 fid = NULL;
723 goto error; 723 goto error;
724 } 724 }
725 725
726 /* instantiate inode and assign the unopened fid to dentry */ 726 /* instantiate inode and assign the unopened fid to dentry */
727 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 727 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
728 if (IS_ERR(inode)) { 728 if (IS_ERR(inode)) {
729 err = PTR_ERR(inode); 729 err = PTR_ERR(inode);
730 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); 730 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
731 goto error; 731 goto error;
732 } 732 }
733 dentry->d_op = &v9fs_cached_dentry_operations; 733 if (v9ses->cache)
734 dentry->d_op = &v9fs_cached_dentry_operations;
735 else
736 dentry->d_op = &v9fs_dentry_operations;
734 d_instantiate(dentry, inode); 737 d_instantiate(dentry, inode);
735 err = v9fs_fid_add(dentry, fid); 738 err = v9fs_fid_add(dentry, fid);
736 if (err < 0) 739 if (err < 0)
737 goto error; 740 goto error;
738 741
739 /* if we are opening a file, assign the open fid to the file */ 742 /* if we are opening a file, assign the open fid to the file */
740 if (nd && nd->flags & LOOKUP_OPEN) { 743 if (nd && nd->flags & LOOKUP_OPEN) {
741 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); 744 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
742 if (IS_ERR(filp)) { 745 if (IS_ERR(filp)) {
743 p9_client_clunk(ofid); 746 p9_client_clunk(ofid);
744 return PTR_ERR(filp); 747 return PTR_ERR(filp);
745 } 748 }
746 filp->private_data = ofid; 749 filp->private_data = ofid;
747 } else 750 } else
748 p9_client_clunk(ofid); 751 p9_client_clunk(ofid);
749 752
750 return 0; 753 return 0;
751 754
752 error: 755 error:
753 if (ofid) 756 if (ofid)
754 p9_client_clunk(ofid); 757 p9_client_clunk(ofid);
755 if (fid) 758 if (fid)
756 p9_client_clunk(fid); 759 p9_client_clunk(fid);
757 return err; 760 return err;
758 } 761 }
759 762
760 /** 763 /**
761 * v9fs_vfs_create - VFS hook to create files 764 * v9fs_vfs_create - VFS hook to create files
762 * @dir: directory inode that is being created 765 * @dir: directory inode that is being created
763 * @dentry: dentry that is being deleted 766 * @dentry: dentry that is being deleted
764 * @mode: create permissions 767 * @mode: create permissions
765 * @nd: path information 768 * @nd: path information
766 * 769 *
767 */ 770 */
768 771
769 static int 772 static int
770 v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, 773 v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
771 struct nameidata *nd) 774 struct nameidata *nd)
772 { 775 {
773 int err; 776 int err;
774 u32 perm; 777 u32 perm;
775 int flags; 778 int flags;
776 struct v9fs_session_info *v9ses; 779 struct v9fs_session_info *v9ses;
777 struct p9_fid *fid; 780 struct p9_fid *fid;
778 struct file *filp; 781 struct file *filp;
779 782
780 err = 0; 783 err = 0;
781 fid = NULL; 784 fid = NULL;
782 v9ses = v9fs_inode2v9ses(dir); 785 v9ses = v9fs_inode2v9ses(dir);
783 perm = unixmode2p9mode(v9ses, mode); 786 perm = unixmode2p9mode(v9ses, mode);
784 if (nd && nd->flags & LOOKUP_OPEN) 787 if (nd && nd->flags & LOOKUP_OPEN)
785 flags = nd->intent.open.flags - 1; 788 flags = nd->intent.open.flags - 1;
786 else 789 else
787 flags = O_RDWR; 790 flags = O_RDWR;
788 791
789 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, 792 fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
790 v9fs_uflags2omode(flags, 793 v9fs_uflags2omode(flags,
791 v9fs_proto_dotu(v9ses))); 794 v9fs_proto_dotu(v9ses)));
792 if (IS_ERR(fid)) { 795 if (IS_ERR(fid)) {
793 err = PTR_ERR(fid); 796 err = PTR_ERR(fid);
794 fid = NULL; 797 fid = NULL;
795 goto error; 798 goto error;
796 } 799 }
797 800
798 /* if we are opening a file, assign the open fid to the file */ 801 /* if we are opening a file, assign the open fid to the file */
799 if (nd && nd->flags & LOOKUP_OPEN) { 802 if (nd && nd->flags & LOOKUP_OPEN) {
800 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); 803 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
801 if (IS_ERR(filp)) { 804 if (IS_ERR(filp)) {
802 err = PTR_ERR(filp); 805 err = PTR_ERR(filp);
803 goto error; 806 goto error;
804 } 807 }
805 808
806 filp->private_data = fid; 809 filp->private_data = fid;
807 } else 810 } else
808 p9_client_clunk(fid); 811 p9_client_clunk(fid);
809 812
810 return 0; 813 return 0;
811 814
812 error: 815 error:
813 if (fid) 816 if (fid)
814 p9_client_clunk(fid); 817 p9_client_clunk(fid);
815 818
816 return err; 819 return err;
817 } 820 }
818 821
819 /** 822 /**
820 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory 823 * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
821 * @dir: inode that is being unlinked 824 * @dir: inode that is being unlinked
822 * @dentry: dentry that is being unlinked 825 * @dentry: dentry that is being unlinked
823 * @mode: mode for new directory 826 * @mode: mode for new directory
824 * 827 *
825 */ 828 */
826 829
827 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 830 static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
828 { 831 {
829 int err; 832 int err;
830 u32 perm; 833 u32 perm;
831 struct v9fs_session_info *v9ses; 834 struct v9fs_session_info *v9ses;
832 struct p9_fid *fid; 835 struct p9_fid *fid;
833 836
834 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 837 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
835 err = 0; 838 err = 0;
836 v9ses = v9fs_inode2v9ses(dir); 839 v9ses = v9fs_inode2v9ses(dir);
837 perm = unixmode2p9mode(v9ses, mode | S_IFDIR); 840 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
838 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD); 841 fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
839 if (IS_ERR(fid)) { 842 if (IS_ERR(fid)) {
840 err = PTR_ERR(fid); 843 err = PTR_ERR(fid);
841 fid = NULL; 844 fid = NULL;
842 } 845 }
843 846
844 if (fid) 847 if (fid)
845 p9_client_clunk(fid); 848 p9_client_clunk(fid);
846 849
847 return err; 850 return err;
848 } 851 }
849 852
850 853
851 /** 854 /**
852 * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory 855 * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory
853 * @dir: inode that is being unlinked 856 * @dir: inode that is being unlinked
854 * @dentry: dentry that is being unlinked 857 * @dentry: dentry that is being unlinked
855 * @mode: mode for new directory 858 * @mode: mode for new directory
856 * 859 *
857 */ 860 */
858 861
859 static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, 862 static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry,
860 int mode) 863 int mode)
861 { 864 {
862 int err; 865 int err;
863 struct v9fs_session_info *v9ses; 866 struct v9fs_session_info *v9ses;
864 struct p9_fid *fid = NULL, *dfid = NULL; 867 struct p9_fid *fid = NULL, *dfid = NULL;
865 gid_t gid; 868 gid_t gid;
866 char *name; 869 char *name;
867 struct inode *inode; 870 struct inode *inode;
868 struct p9_qid qid; 871 struct p9_qid qid;
869 struct dentry *dir_dentry; 872 struct dentry *dir_dentry;
870 873
871 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); 874 P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
872 err = 0; 875 err = 0;
873 v9ses = v9fs_inode2v9ses(dir); 876 v9ses = v9fs_inode2v9ses(dir);
874 877
875 mode |= S_IFDIR; 878 mode |= S_IFDIR;
876 dir_dentry = v9fs_dentry_from_dir_inode(dir); 879 dir_dentry = v9fs_dentry_from_dir_inode(dir);
877 dfid = v9fs_fid_lookup(dir_dentry); 880 dfid = v9fs_fid_lookup(dir_dentry);
878 if (IS_ERR(dfid)) { 881 if (IS_ERR(dfid)) {
879 err = PTR_ERR(dfid); 882 err = PTR_ERR(dfid);
880 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 883 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
881 dfid = NULL; 884 dfid = NULL;
882 goto error; 885 goto error;
883 } 886 }
884 887
885 gid = v9fs_get_fsgid_for_create(dir); 888 gid = v9fs_get_fsgid_for_create(dir);
886 if (gid < 0) { 889 if (gid < 0) {
887 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); 890 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n");
888 goto error; 891 goto error;
889 } 892 }
890 893
891 name = (char *) dentry->d_name.name; 894 name = (char *) dentry->d_name.name;
892 err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); 895 err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
893 if (err < 0) 896 if (err < 0)
894 goto error; 897 goto error;
895 898
896 /* instantiate inode and assign the unopened fid to the dentry */ 899 /* instantiate inode and assign the unopened fid to the dentry */
897 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 900 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
898 fid = p9_client_walk(dfid, 1, &name, 1); 901 fid = p9_client_walk(dfid, 1, &name, 1);
899 if (IS_ERR(fid)) { 902 if (IS_ERR(fid)) {
900 err = PTR_ERR(fid); 903 err = PTR_ERR(fid);
901 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 904 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
902 err); 905 err);
903 fid = NULL; 906 fid = NULL;
904 goto error; 907 goto error;
905 } 908 }
906 909
907 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 910 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
908 if (IS_ERR(inode)) { 911 if (IS_ERR(inode)) {
909 err = PTR_ERR(inode); 912 err = PTR_ERR(inode);
910 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 913 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
911 err); 914 err);
912 goto error; 915 goto error;
913 } 916 }
914 dentry->d_op = &v9fs_cached_dentry_operations; 917 dentry->d_op = &v9fs_cached_dentry_operations;
915 d_instantiate(dentry, inode); 918 d_instantiate(dentry, inode);
916 err = v9fs_fid_add(dentry, fid); 919 err = v9fs_fid_add(dentry, fid);
917 if (err < 0) 920 if (err < 0)
918 goto error; 921 goto error;
919 fid = NULL; 922 fid = NULL;
920 } 923 }
921 error: 924 error:
922 if (fid) 925 if (fid)
923 p9_client_clunk(fid); 926 p9_client_clunk(fid);
924 return err; 927 return err;
925 } 928 }
926 929
927 /** 930 /**
928 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode 931 * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
929 * @dir: inode that is being walked from 932 * @dir: inode that is being walked from
930 * @dentry: dentry that is being walked to? 933 * @dentry: dentry that is being walked to?
931 * @nameidata: path data 934 * @nameidata: path data
932 * 935 *
933 */ 936 */
934 937
935 static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, 938 static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
936 struct nameidata *nameidata) 939 struct nameidata *nameidata)
937 { 940 {
938 struct super_block *sb; 941 struct super_block *sb;
939 struct v9fs_session_info *v9ses; 942 struct v9fs_session_info *v9ses;
940 struct p9_fid *dfid, *fid; 943 struct p9_fid *dfid, *fid;
941 struct inode *inode; 944 struct inode *inode;
942 char *name; 945 char *name;
943 int result = 0; 946 int result = 0;
944 947
945 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 948 P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
946 dir, dentry->d_name.name, dentry, nameidata); 949 dir, dentry->d_name.name, dentry, nameidata);
947 950
948 if (dentry->d_name.len > NAME_MAX) 951 if (dentry->d_name.len > NAME_MAX)
949 return ERR_PTR(-ENAMETOOLONG); 952 return ERR_PTR(-ENAMETOOLONG);
950 953
951 sb = dir->i_sb; 954 sb = dir->i_sb;
952 v9ses = v9fs_inode2v9ses(dir); 955 v9ses = v9fs_inode2v9ses(dir);
953 /* We can walk d_parent because we hold the dir->i_mutex */ 956 /* We can walk d_parent because we hold the dir->i_mutex */
954 dfid = v9fs_fid_lookup(dentry->d_parent); 957 dfid = v9fs_fid_lookup(dentry->d_parent);
955 if (IS_ERR(dfid)) 958 if (IS_ERR(dfid))
956 return ERR_CAST(dfid); 959 return ERR_CAST(dfid);
957 960
958 name = (char *) dentry->d_name.name; 961 name = (char *) dentry->d_name.name;
959 fid = p9_client_walk(dfid, 1, &name, 1); 962 fid = p9_client_walk(dfid, 1, &name, 1);
960 if (IS_ERR(fid)) { 963 if (IS_ERR(fid)) {
961 result = PTR_ERR(fid); 964 result = PTR_ERR(fid);
962 if (result == -ENOENT) { 965 if (result == -ENOENT) {
963 inode = NULL; 966 inode = NULL;
964 goto inst_out; 967 goto inst_out;
965 } 968 }
966 969
967 return ERR_PTR(result); 970 return ERR_PTR(result);
968 } 971 }
969 972
970 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 973 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
971 if (IS_ERR(inode)) { 974 if (IS_ERR(inode)) {
972 result = PTR_ERR(inode); 975 result = PTR_ERR(inode);
973 inode = NULL; 976 inode = NULL;
974 goto error; 977 goto error;
975 } 978 }
976 979
977 result = v9fs_fid_add(dentry, fid); 980 result = v9fs_fid_add(dentry, fid);
978 if (result < 0) 981 if (result < 0)
979 goto error; 982 goto error;
980 983
981 inst_out: 984 inst_out:
982 if (v9ses->cache) 985 if (v9ses->cache)
983 dentry->d_op = &v9fs_cached_dentry_operations; 986 dentry->d_op = &v9fs_cached_dentry_operations;
984 else 987 else
985 dentry->d_op = &v9fs_dentry_operations; 988 dentry->d_op = &v9fs_dentry_operations;
986 989
987 d_add(dentry, inode); 990 d_add(dentry, inode);
988 return NULL; 991 return NULL;
989 992
990 error: 993 error:
991 p9_client_clunk(fid); 994 p9_client_clunk(fid);
992 995
993 return ERR_PTR(result); 996 return ERR_PTR(result);
994 } 997 }
995 998
996 /** 999 /**
997 * v9fs_vfs_unlink - VFS unlink hook to delete an inode 1000 * v9fs_vfs_unlink - VFS unlink hook to delete an inode
998 * @i: inode that is being unlinked 1001 * @i: inode that is being unlinked
999 * @d: dentry that is being unlinked 1002 * @d: dentry that is being unlinked
1000 * 1003 *
1001 */ 1004 */
1002 1005
1003 static int v9fs_vfs_unlink(struct inode *i, struct dentry *d) 1006 static int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
1004 { 1007 {
1005 return v9fs_remove(i, d, 0); 1008 return v9fs_remove(i, d, 0);
1006 } 1009 }
1007 1010
1008 /** 1011 /**
1009 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory 1012 * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
1010 * @i: inode that is being unlinked 1013 * @i: inode that is being unlinked
1011 * @d: dentry that is being unlinked 1014 * @d: dentry that is being unlinked
1012 * 1015 *
1013 */ 1016 */
1014 1017
1015 static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) 1018 static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
1016 { 1019 {
1017 return v9fs_remove(i, d, 1); 1020 return v9fs_remove(i, d, 1);
1018 } 1021 }
1019 1022
1020 /** 1023 /**
1021 * v9fs_vfs_rename - VFS hook to rename an inode 1024 * v9fs_vfs_rename - VFS hook to rename an inode
1022 * @old_dir: old dir inode 1025 * @old_dir: old dir inode
1023 * @old_dentry: old dentry 1026 * @old_dentry: old dentry
1024 * @new_dir: new dir inode 1027 * @new_dir: new dir inode
1025 * @new_dentry: new dentry 1028 * @new_dentry: new dentry
1026 * 1029 *
1027 */ 1030 */
1028 1031
1029 static int 1032 static int
1030 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 1033 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1031 struct inode *new_dir, struct dentry *new_dentry) 1034 struct inode *new_dir, struct dentry *new_dentry)
1032 { 1035 {
1033 struct inode *old_inode; 1036 struct inode *old_inode;
1034 struct v9fs_session_info *v9ses; 1037 struct v9fs_session_info *v9ses;
1035 struct p9_fid *oldfid; 1038 struct p9_fid *oldfid;
1036 struct p9_fid *olddirfid; 1039 struct p9_fid *olddirfid;
1037 struct p9_fid *newdirfid; 1040 struct p9_fid *newdirfid;
1038 struct p9_wstat wstat; 1041 struct p9_wstat wstat;
1039 int retval; 1042 int retval;
1040 1043
1041 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 1044 P9_DPRINTK(P9_DEBUG_VFS, "\n");
1042 retval = 0; 1045 retval = 0;
1043 old_inode = old_dentry->d_inode; 1046 old_inode = old_dentry->d_inode;
1044 v9ses = v9fs_inode2v9ses(old_inode); 1047 v9ses = v9fs_inode2v9ses(old_inode);
1045 oldfid = v9fs_fid_lookup(old_dentry); 1048 oldfid = v9fs_fid_lookup(old_dentry);
1046 if (IS_ERR(oldfid)) 1049 if (IS_ERR(oldfid))
1047 return PTR_ERR(oldfid); 1050 return PTR_ERR(oldfid);
1048 1051
1049 olddirfid = v9fs_fid_clone(old_dentry->d_parent); 1052 olddirfid = v9fs_fid_clone(old_dentry->d_parent);
1050 if (IS_ERR(olddirfid)) { 1053 if (IS_ERR(olddirfid)) {
1051 retval = PTR_ERR(olddirfid); 1054 retval = PTR_ERR(olddirfid);
1052 goto done; 1055 goto done;
1053 } 1056 }
1054 1057
1055 newdirfid = v9fs_fid_clone(new_dentry->d_parent); 1058 newdirfid = v9fs_fid_clone(new_dentry->d_parent);
1056 if (IS_ERR(newdirfid)) { 1059 if (IS_ERR(newdirfid)) {
1057 retval = PTR_ERR(newdirfid); 1060 retval = PTR_ERR(newdirfid);
1058 goto clunk_olddir; 1061 goto clunk_olddir;
1059 } 1062 }
1060 1063
1061 down_write(&v9ses->rename_sem); 1064 down_write(&v9ses->rename_sem);
1062 if (v9fs_proto_dotl(v9ses)) { 1065 if (v9fs_proto_dotl(v9ses)) {
1063 retval = p9_client_rename(oldfid, newdirfid, 1066 retval = p9_client_rename(oldfid, newdirfid,
1064 (char *) new_dentry->d_name.name); 1067 (char *) new_dentry->d_name.name);
1065 if (retval != -ENOSYS) 1068 if (retval != -ENOSYS)
1066 goto clunk_newdir; 1069 goto clunk_newdir;
1067 } 1070 }
1068 if (old_dentry->d_parent != new_dentry->d_parent) { 1071 if (old_dentry->d_parent != new_dentry->d_parent) {
1069 /* 1072 /*
1070 * 9P .u can only handle file rename in the same directory 1073 * 9P .u can only handle file rename in the same directory
1071 */ 1074 */
1072 1075
1073 P9_DPRINTK(P9_DEBUG_ERROR, 1076 P9_DPRINTK(P9_DEBUG_ERROR,
1074 "old dir and new dir are different\n"); 1077 "old dir and new dir are different\n");
1075 retval = -EXDEV; 1078 retval = -EXDEV;
1076 goto clunk_newdir; 1079 goto clunk_newdir;
1077 } 1080 }
1078 v9fs_blank_wstat(&wstat); 1081 v9fs_blank_wstat(&wstat);
1079 wstat.muid = v9ses->uname; 1082 wstat.muid = v9ses->uname;
1080 wstat.name = (char *) new_dentry->d_name.name; 1083 wstat.name = (char *) new_dentry->d_name.name;
1081 retval = p9_client_wstat(oldfid, &wstat); 1084 retval = p9_client_wstat(oldfid, &wstat);
1082 1085
1083 clunk_newdir: 1086 clunk_newdir:
1084 if (!retval) 1087 if (!retval)
1085 /* successful rename */ 1088 /* successful rename */
1086 d_move(old_dentry, new_dentry); 1089 d_move(old_dentry, new_dentry);
1087 up_write(&v9ses->rename_sem); 1090 up_write(&v9ses->rename_sem);
1088 p9_client_clunk(newdirfid); 1091 p9_client_clunk(newdirfid);
1089 1092
1090 clunk_olddir: 1093 clunk_olddir:
1091 p9_client_clunk(olddirfid); 1094 p9_client_clunk(olddirfid);
1092 1095
1093 done: 1096 done:
1094 return retval; 1097 return retval;
1095 } 1098 }
1096 1099
1097 /** 1100 /**
1098 * v9fs_vfs_getattr - retrieve file metadata 1101 * v9fs_vfs_getattr - retrieve file metadata
1099 * @mnt: mount information 1102 * @mnt: mount information
1100 * @dentry: file to get attributes on 1103 * @dentry: file to get attributes on
1101 * @stat: metadata structure to populate 1104 * @stat: metadata structure to populate
1102 * 1105 *
1103 */ 1106 */
1104 1107
1105 static int 1108 static int
1106 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 1109 v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1107 struct kstat *stat) 1110 struct kstat *stat)
1108 { 1111 {
1109 int err; 1112 int err;
1110 struct v9fs_session_info *v9ses; 1113 struct v9fs_session_info *v9ses;
1111 struct p9_fid *fid; 1114 struct p9_fid *fid;
1112 struct p9_wstat *st; 1115 struct p9_wstat *st;
1113 1116
1114 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 1117 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1115 err = -EPERM; 1118 err = -EPERM;
1116 v9ses = v9fs_inode2v9ses(dentry->d_inode); 1119 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1117 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 1120 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
1118 return simple_getattr(mnt, dentry, stat); 1121 return simple_getattr(mnt, dentry, stat);
1119 1122
1120 fid = v9fs_fid_lookup(dentry); 1123 fid = v9fs_fid_lookup(dentry);
1121 if (IS_ERR(fid)) 1124 if (IS_ERR(fid))
1122 return PTR_ERR(fid); 1125 return PTR_ERR(fid);
1123 1126
1124 st = p9_client_stat(fid); 1127 st = p9_client_stat(fid);
1125 if (IS_ERR(st)) 1128 if (IS_ERR(st))
1126 return PTR_ERR(st); 1129 return PTR_ERR(st);
1127 1130
1128 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); 1131 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
1129 generic_fillattr(dentry->d_inode, stat); 1132 generic_fillattr(dentry->d_inode, stat);
1130 1133
1134 p9stat_free(st);
1131 kfree(st); 1135 kfree(st);
1132 return 0; 1136 return 0;
1133 } 1137 }
1134 1138
1135 static int 1139 static int
1136 v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, 1140 v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
1137 struct kstat *stat) 1141 struct kstat *stat)
1138 { 1142 {
1139 int err; 1143 int err;
1140 struct v9fs_session_info *v9ses; 1144 struct v9fs_session_info *v9ses;
1141 struct p9_fid *fid; 1145 struct p9_fid *fid;
1142 struct p9_stat_dotl *st; 1146 struct p9_stat_dotl *st;
1143 1147
1144 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); 1148 P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
1145 err = -EPERM; 1149 err = -EPERM;
1146 v9ses = v9fs_inode2v9ses(dentry->d_inode); 1150 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1147 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 1151 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
1148 return simple_getattr(mnt, dentry, stat); 1152 return simple_getattr(mnt, dentry, stat);
1149 1153
1150 fid = v9fs_fid_lookup(dentry); 1154 fid = v9fs_fid_lookup(dentry);
1151 if (IS_ERR(fid)) 1155 if (IS_ERR(fid))
1152 return PTR_ERR(fid); 1156 return PTR_ERR(fid);
1153 1157
1154 /* Ask for all the fields in stat structure. Server will return 1158 /* Ask for all the fields in stat structure. Server will return
1155 * whatever it supports 1159 * whatever it supports
1156 */ 1160 */
1157 1161
1158 st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 1162 st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
1159 if (IS_ERR(st)) 1163 if (IS_ERR(st))
1160 return PTR_ERR(st); 1164 return PTR_ERR(st);
1161 1165
1162 v9fs_stat2inode_dotl(st, dentry->d_inode); 1166 v9fs_stat2inode_dotl(st, dentry->d_inode);
1163 generic_fillattr(dentry->d_inode, stat); 1167 generic_fillattr(dentry->d_inode, stat);
1164 /* Change block size to what the server returned */ 1168 /* Change block size to what the server returned */
1165 stat->blksize = st->st_blksize; 1169 stat->blksize = st->st_blksize;
1166 1170
1167 kfree(st); 1171 kfree(st);
1168 return 0; 1172 return 0;
1169 } 1173 }
1170 1174
1171 /** 1175 /**
1172 * v9fs_vfs_setattr - set file metadata 1176 * v9fs_vfs_setattr - set file metadata
1173 * @dentry: file whose metadata to set 1177 * @dentry: file whose metadata to set
1174 * @iattr: metadata assignment structure 1178 * @iattr: metadata assignment structure
1175 * 1179 *
1176 */ 1180 */
1177 1181
1178 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) 1182 static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1179 { 1183 {
1180 int retval; 1184 int retval;
1181 struct v9fs_session_info *v9ses; 1185 struct v9fs_session_info *v9ses;
1182 struct p9_fid *fid; 1186 struct p9_fid *fid;
1183 struct p9_wstat wstat; 1187 struct p9_wstat wstat;
1184 1188
1185 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 1189 P9_DPRINTK(P9_DEBUG_VFS, "\n");
1186 retval = -EPERM; 1190 retval = -EPERM;
1187 v9ses = v9fs_inode2v9ses(dentry->d_inode); 1191 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1188 fid = v9fs_fid_lookup(dentry); 1192 fid = v9fs_fid_lookup(dentry);
1189 if(IS_ERR(fid)) 1193 if(IS_ERR(fid))
1190 return PTR_ERR(fid); 1194 return PTR_ERR(fid);
1191 1195
1192 v9fs_blank_wstat(&wstat); 1196 v9fs_blank_wstat(&wstat);
1193 if (iattr->ia_valid & ATTR_MODE) 1197 if (iattr->ia_valid & ATTR_MODE)
1194 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode); 1198 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
1195 1199
1196 if (iattr->ia_valid & ATTR_MTIME) 1200 if (iattr->ia_valid & ATTR_MTIME)
1197 wstat.mtime = iattr->ia_mtime.tv_sec; 1201 wstat.mtime = iattr->ia_mtime.tv_sec;
1198 1202
1199 if (iattr->ia_valid & ATTR_ATIME) 1203 if (iattr->ia_valid & ATTR_ATIME)
1200 wstat.atime = iattr->ia_atime.tv_sec; 1204 wstat.atime = iattr->ia_atime.tv_sec;
1201 1205
1202 if (iattr->ia_valid & ATTR_SIZE) 1206 if (iattr->ia_valid & ATTR_SIZE)
1203 wstat.length = iattr->ia_size; 1207 wstat.length = iattr->ia_size;
1204 1208
1205 if (v9fs_proto_dotu(v9ses)) { 1209 if (v9fs_proto_dotu(v9ses)) {
1206 if (iattr->ia_valid & ATTR_UID) 1210 if (iattr->ia_valid & ATTR_UID)
1207 wstat.n_uid = iattr->ia_uid; 1211 wstat.n_uid = iattr->ia_uid;
1208 1212
1209 if (iattr->ia_valid & ATTR_GID) 1213 if (iattr->ia_valid & ATTR_GID)
1210 wstat.n_gid = iattr->ia_gid; 1214 wstat.n_gid = iattr->ia_gid;
1211 } 1215 }
1212 1216
1213 retval = p9_client_wstat(fid, &wstat); 1217 retval = p9_client_wstat(fid, &wstat);
1214 if (retval < 0) 1218 if (retval < 0)
1215 return retval; 1219 return retval;
1216 1220
1217 if ((iattr->ia_valid & ATTR_SIZE) && 1221 if ((iattr->ia_valid & ATTR_SIZE) &&
1218 iattr->ia_size != i_size_read(dentry->d_inode)) { 1222 iattr->ia_size != i_size_read(dentry->d_inode)) {
1219 retval = vmtruncate(dentry->d_inode, iattr->ia_size); 1223 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
1220 if (retval) 1224 if (retval)
1221 return retval; 1225 return retval;
1222 } 1226 }
1223 1227
1224 setattr_copy(dentry->d_inode, iattr); 1228 setattr_copy(dentry->d_inode, iattr);
1225 mark_inode_dirty(dentry->d_inode); 1229 mark_inode_dirty(dentry->d_inode);
1226 return 0; 1230 return 0;
1227 } 1231 }
1228 1232
1229 /** 1233 /**
1230 * v9fs_vfs_setattr_dotl - set file metadata 1234 * v9fs_vfs_setattr_dotl - set file metadata
1231 * @dentry: file whose metadata to set 1235 * @dentry: file whose metadata to set
1232 * @iattr: metadata assignment structure 1236 * @iattr: metadata assignment structure
1233 * 1237 *
1234 */ 1238 */
1235 1239
1236 static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) 1240 static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
1237 { 1241 {
1238 int retval; 1242 int retval;
1239 struct v9fs_session_info *v9ses; 1243 struct v9fs_session_info *v9ses;
1240 struct p9_fid *fid; 1244 struct p9_fid *fid;
1241 struct p9_iattr_dotl p9attr; 1245 struct p9_iattr_dotl p9attr;
1242 1246
1243 P9_DPRINTK(P9_DEBUG_VFS, "\n"); 1247 P9_DPRINTK(P9_DEBUG_VFS, "\n");
1244 1248
1245 retval = inode_change_ok(dentry->d_inode, iattr); 1249 retval = inode_change_ok(dentry->d_inode, iattr);
1246 if (retval) 1250 if (retval)
1247 return retval; 1251 return retval;
1248 1252
1249 p9attr.valid = iattr->ia_valid; 1253 p9attr.valid = iattr->ia_valid;
1250 p9attr.mode = iattr->ia_mode; 1254 p9attr.mode = iattr->ia_mode;
1251 p9attr.uid = iattr->ia_uid; 1255 p9attr.uid = iattr->ia_uid;
1252 p9attr.gid = iattr->ia_gid; 1256 p9attr.gid = iattr->ia_gid;
1253 p9attr.size = iattr->ia_size; 1257 p9attr.size = iattr->ia_size;
1254 p9attr.atime_sec = iattr->ia_atime.tv_sec; 1258 p9attr.atime_sec = iattr->ia_atime.tv_sec;
1255 p9attr.atime_nsec = iattr->ia_atime.tv_nsec; 1259 p9attr.atime_nsec = iattr->ia_atime.tv_nsec;
1256 p9attr.mtime_sec = iattr->ia_mtime.tv_sec; 1260 p9attr.mtime_sec = iattr->ia_mtime.tv_sec;
1257 p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; 1261 p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
1258 1262
1259 retval = -EPERM; 1263 retval = -EPERM;
1260 v9ses = v9fs_inode2v9ses(dentry->d_inode); 1264 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1261 fid = v9fs_fid_lookup(dentry); 1265 fid = v9fs_fid_lookup(dentry);
1262 if (IS_ERR(fid)) 1266 if (IS_ERR(fid))
1263 return PTR_ERR(fid); 1267 return PTR_ERR(fid);
1264 1268
1265 retval = p9_client_setattr(fid, &p9attr); 1269 retval = p9_client_setattr(fid, &p9attr);
1266 if (retval < 0) 1270 if (retval < 0)
1267 return retval; 1271 return retval;
1268 1272
1269 if ((iattr->ia_valid & ATTR_SIZE) && 1273 if ((iattr->ia_valid & ATTR_SIZE) &&
1270 iattr->ia_size != i_size_read(dentry->d_inode)) { 1274 iattr->ia_size != i_size_read(dentry->d_inode)) {
1271 retval = vmtruncate(dentry->d_inode, iattr->ia_size); 1275 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
1272 if (retval) 1276 if (retval)
1273 return retval; 1277 return retval;
1274 } 1278 }
1275 1279
1276 setattr_copy(dentry->d_inode, iattr); 1280 setattr_copy(dentry->d_inode, iattr);
1277 mark_inode_dirty(dentry->d_inode); 1281 mark_inode_dirty(dentry->d_inode);
1278 return 0; 1282 return 0;
1279 } 1283 }
1280 1284
1281 /** 1285 /**
1282 * v9fs_stat2inode - populate an inode structure with mistat info 1286 * v9fs_stat2inode - populate an inode structure with mistat info
1283 * @stat: Plan 9 metadata (mistat) structure 1287 * @stat: Plan 9 metadata (mistat) structure
1284 * @inode: inode to populate 1288 * @inode: inode to populate
1285 * @sb: superblock of filesystem 1289 * @sb: superblock of filesystem
1286 * 1290 *
1287 */ 1291 */
1288 1292
1289 void 1293 void
1290 v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, 1294 v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1291 struct super_block *sb) 1295 struct super_block *sb)
1292 { 1296 {
1293 char ext[32]; 1297 char ext[32];
1294 char tag_name[14]; 1298 char tag_name[14];
1295 unsigned int i_nlink; 1299 unsigned int i_nlink;
1296 struct v9fs_session_info *v9ses = sb->s_fs_info; 1300 struct v9fs_session_info *v9ses = sb->s_fs_info;
1297 1301
1298 inode->i_nlink = 1; 1302 inode->i_nlink = 1;
1299 1303
1300 inode->i_atime.tv_sec = stat->atime; 1304 inode->i_atime.tv_sec = stat->atime;
1301 inode->i_mtime.tv_sec = stat->mtime; 1305 inode->i_mtime.tv_sec = stat->mtime;
1302 inode->i_ctime.tv_sec = stat->mtime; 1306 inode->i_ctime.tv_sec = stat->mtime;
1303 1307
1304 inode->i_uid = v9ses->dfltuid; 1308 inode->i_uid = v9ses->dfltuid;
1305 inode->i_gid = v9ses->dfltgid; 1309 inode->i_gid = v9ses->dfltgid;
1306 1310
1307 if (v9fs_proto_dotu(v9ses)) { 1311 if (v9fs_proto_dotu(v9ses)) {
1308 inode->i_uid = stat->n_uid; 1312 inode->i_uid = stat->n_uid;
1309 inode->i_gid = stat->n_gid; 1313 inode->i_gid = stat->n_gid;
1310 } 1314 }
1311 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { 1315 if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) {
1312 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { 1316 if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) {
1313 /* 1317 /*
1314 * Hadlink support got added later to 1318 * Hadlink support got added later to
1315 * to the .u extension. So there can be 1319 * to the .u extension. So there can be
1316 * server out there that doesn't support 1320 * server out there that doesn't support
1317 * this even with .u extension. So check 1321 * this even with .u extension. So check
1318 * for non NULL stat->extension 1322 * for non NULL stat->extension
1319 */ 1323 */
1320 strncpy(ext, stat->extension, sizeof(ext)); 1324 strncpy(ext, stat->extension, sizeof(ext));
1321 /* HARDLINKCOUNT %u */ 1325 /* HARDLINKCOUNT %u */
1322 sscanf(ext, "%13s %u", tag_name, &i_nlink); 1326 sscanf(ext, "%13s %u", tag_name, &i_nlink);
1323 if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) 1327 if (!strncmp(tag_name, "HARDLINKCOUNT", 13))
1324 inode->i_nlink = i_nlink; 1328 inode->i_nlink = i_nlink;
1325 } 1329 }
1326 } 1330 }
1327 inode->i_mode = p9mode2unixmode(v9ses, stat->mode); 1331 inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
1328 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { 1332 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
1329 char type = 0; 1333 char type = 0;
1330 int major = -1; 1334 int major = -1;
1331 int minor = -1; 1335 int minor = -1;
1332 1336
1333 strncpy(ext, stat->extension, sizeof(ext)); 1337 strncpy(ext, stat->extension, sizeof(ext));
1334 sscanf(ext, "%c %u %u", &type, &major, &minor); 1338 sscanf(ext, "%c %u %u", &type, &major, &minor);
1335 switch (type) { 1339 switch (type) {
1336 case 'c': 1340 case 'c':
1337 inode->i_mode &= ~S_IFBLK; 1341 inode->i_mode &= ~S_IFBLK;
1338 inode->i_mode |= S_IFCHR; 1342 inode->i_mode |= S_IFCHR;
1339 break; 1343 break;
1340 case 'b': 1344 case 'b':
1341 break; 1345 break;
1342 default: 1346 default:
1343 P9_DPRINTK(P9_DEBUG_ERROR, 1347 P9_DPRINTK(P9_DEBUG_ERROR,
1344 "Unknown special type %c %s\n", type, 1348 "Unknown special type %c %s\n", type,
1345 stat->extension); 1349 stat->extension);
1346 }; 1350 };
1347 inode->i_rdev = MKDEV(major, minor); 1351 inode->i_rdev = MKDEV(major, minor);
1348 init_special_inode(inode, inode->i_mode, inode->i_rdev); 1352 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1349 } else 1353 } else
1350 inode->i_rdev = 0; 1354 inode->i_rdev = 0;
1351 1355
1352 i_size_write(inode, stat->length); 1356 i_size_write(inode, stat->length);
1353 1357
1354 /* not real number of blocks, but 512 byte ones ... */ 1358 /* not real number of blocks, but 512 byte ones ... */
1355 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; 1359 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
1356 } 1360 }
1357 1361
1358 /** 1362 /**
1359 * v9fs_stat2inode_dotl - populate an inode structure with stat info 1363 * v9fs_stat2inode_dotl - populate an inode structure with stat info
1360 * @stat: stat structure 1364 * @stat: stat structure
1361 * @inode: inode to populate 1365 * @inode: inode to populate
1362 * @sb: superblock of filesystem 1366 * @sb: superblock of filesystem
1363 * 1367 *
1364 */ 1368 */
1365 1369
1366 void 1370 void
1367 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) 1371 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
1368 { 1372 {
1369 1373
1370 if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { 1374 if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
1371 inode->i_atime.tv_sec = stat->st_atime_sec; 1375 inode->i_atime.tv_sec = stat->st_atime_sec;
1372 inode->i_atime.tv_nsec = stat->st_atime_nsec; 1376 inode->i_atime.tv_nsec = stat->st_atime_nsec;
1373 inode->i_mtime.tv_sec = stat->st_mtime_sec; 1377 inode->i_mtime.tv_sec = stat->st_mtime_sec;
1374 inode->i_mtime.tv_nsec = stat->st_mtime_nsec; 1378 inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
1375 inode->i_ctime.tv_sec = stat->st_ctime_sec; 1379 inode->i_ctime.tv_sec = stat->st_ctime_sec;
1376 inode->i_ctime.tv_nsec = stat->st_ctime_nsec; 1380 inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
1377 inode->i_uid = stat->st_uid; 1381 inode->i_uid = stat->st_uid;
1378 inode->i_gid = stat->st_gid; 1382 inode->i_gid = stat->st_gid;
1379 inode->i_nlink = stat->st_nlink; 1383 inode->i_nlink = stat->st_nlink;
1380 inode->i_mode = stat->st_mode; 1384 inode->i_mode = stat->st_mode;
1381 inode->i_rdev = new_decode_dev(stat->st_rdev); 1385 inode->i_rdev = new_decode_dev(stat->st_rdev);
1382 1386
1383 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) 1387 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode)))
1384 init_special_inode(inode, inode->i_mode, inode->i_rdev); 1388 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1385 1389
1386 i_size_write(inode, stat->st_size); 1390 i_size_write(inode, stat->st_size);
1387 inode->i_blocks = stat->st_blocks; 1391 inode->i_blocks = stat->st_blocks;
1388 } else { 1392 } else {
1389 if (stat->st_result_mask & P9_STATS_ATIME) { 1393 if (stat->st_result_mask & P9_STATS_ATIME) {
1390 inode->i_atime.tv_sec = stat->st_atime_sec; 1394 inode->i_atime.tv_sec = stat->st_atime_sec;
1391 inode->i_atime.tv_nsec = stat->st_atime_nsec; 1395 inode->i_atime.tv_nsec = stat->st_atime_nsec;
1392 } 1396 }
1393 if (stat->st_result_mask & P9_STATS_MTIME) { 1397 if (stat->st_result_mask & P9_STATS_MTIME) {
1394 inode->i_mtime.tv_sec = stat->st_mtime_sec; 1398 inode->i_mtime.tv_sec = stat->st_mtime_sec;
1395 inode->i_mtime.tv_nsec = stat->st_mtime_nsec; 1399 inode->i_mtime.tv_nsec = stat->st_mtime_nsec;
1396 } 1400 }
1397 if (stat->st_result_mask & P9_STATS_CTIME) { 1401 if (stat->st_result_mask & P9_STATS_CTIME) {
1398 inode->i_ctime.tv_sec = stat->st_ctime_sec; 1402 inode->i_ctime.tv_sec = stat->st_ctime_sec;
1399 inode->i_ctime.tv_nsec = stat->st_ctime_nsec; 1403 inode->i_ctime.tv_nsec = stat->st_ctime_nsec;
1400 } 1404 }
1401 if (stat->st_result_mask & P9_STATS_UID) 1405 if (stat->st_result_mask & P9_STATS_UID)
1402 inode->i_uid = stat->st_uid; 1406 inode->i_uid = stat->st_uid;
1403 if (stat->st_result_mask & P9_STATS_GID) 1407 if (stat->st_result_mask & P9_STATS_GID)
1404 inode->i_gid = stat->st_gid; 1408 inode->i_gid = stat->st_gid;
1405 if (stat->st_result_mask & P9_STATS_NLINK) 1409 if (stat->st_result_mask & P9_STATS_NLINK)
1406 inode->i_nlink = stat->st_nlink; 1410 inode->i_nlink = stat->st_nlink;
1407 if (stat->st_result_mask & P9_STATS_MODE) { 1411 if (stat->st_result_mask & P9_STATS_MODE) {
1408 inode->i_mode = stat->st_mode; 1412 inode->i_mode = stat->st_mode;
1409 if ((S_ISBLK(inode->i_mode)) || 1413 if ((S_ISBLK(inode->i_mode)) ||
1410 (S_ISCHR(inode->i_mode))) 1414 (S_ISCHR(inode->i_mode)))
1411 init_special_inode(inode, inode->i_mode, 1415 init_special_inode(inode, inode->i_mode,
1412 inode->i_rdev); 1416 inode->i_rdev);
1413 } 1417 }
1414 if (stat->st_result_mask & P9_STATS_RDEV) 1418 if (stat->st_result_mask & P9_STATS_RDEV)
1415 inode->i_rdev = new_decode_dev(stat->st_rdev); 1419 inode->i_rdev = new_decode_dev(stat->st_rdev);
1416 if (stat->st_result_mask & P9_STATS_SIZE) 1420 if (stat->st_result_mask & P9_STATS_SIZE)
1417 i_size_write(inode, stat->st_size); 1421 i_size_write(inode, stat->st_size);
1418 if (stat->st_result_mask & P9_STATS_BLOCKS) 1422 if (stat->st_result_mask & P9_STATS_BLOCKS)
1419 inode->i_blocks = stat->st_blocks; 1423 inode->i_blocks = stat->st_blocks;
1420 } 1424 }
1421 if (stat->st_result_mask & P9_STATS_GEN) 1425 if (stat->st_result_mask & P9_STATS_GEN)
1422 inode->i_generation = stat->st_gen; 1426 inode->i_generation = stat->st_gen;
1423 1427
1424 /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION 1428 /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
1425 * because the inode structure does not have fields for them. 1429 * because the inode structure does not have fields for them.
1426 */ 1430 */
1427 } 1431 }
1428 1432
1429 /** 1433 /**
1430 * v9fs_qid2ino - convert qid into inode number 1434 * v9fs_qid2ino - convert qid into inode number
1431 * @qid: qid to hash 1435 * @qid: qid to hash
1432 * 1436 *
1433 * BUG: potential for inode number collisions? 1437 * BUG: potential for inode number collisions?
1434 */ 1438 */
1435 1439
1436 ino_t v9fs_qid2ino(struct p9_qid *qid) 1440 ino_t v9fs_qid2ino(struct p9_qid *qid)
1437 { 1441 {
1438 u64 path = qid->path + 2; 1442 u64 path = qid->path + 2;
1439 ino_t i = 0; 1443 ino_t i = 0;
1440 1444
1441 if (sizeof(ino_t) == sizeof(path)) 1445 if (sizeof(ino_t) == sizeof(path))
1442 memcpy(&i, &path, sizeof(ino_t)); 1446 memcpy(&i, &path, sizeof(ino_t));
1443 else 1447 else
1444 i = (ino_t) (path ^ (path >> 32)); 1448 i = (ino_t) (path ^ (path >> 32));
1445 1449
1446 return i; 1450 return i;
1447 } 1451 }
1448 1452
1449 /** 1453 /**
1450 * v9fs_readlink - read a symlink's location (internal version) 1454 * v9fs_readlink - read a symlink's location (internal version)
1451 * @dentry: dentry for symlink 1455 * @dentry: dentry for symlink
1452 * @buffer: buffer to load symlink location into 1456 * @buffer: buffer to load symlink location into
1453 * @buflen: length of buffer 1457 * @buflen: length of buffer
1454 * 1458 *
1455 */ 1459 */
1456 1460
1457 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 1461 static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1458 { 1462 {
1459 int retval; 1463 int retval;
1460 1464
1461 struct v9fs_session_info *v9ses; 1465 struct v9fs_session_info *v9ses;
1462 struct p9_fid *fid; 1466 struct p9_fid *fid;
1463 struct p9_wstat *st; 1467 struct p9_wstat *st;
1464 1468
1465 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); 1469 P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
1466 retval = -EPERM; 1470 retval = -EPERM;
1467 v9ses = v9fs_inode2v9ses(dentry->d_inode); 1471 v9ses = v9fs_inode2v9ses(dentry->d_inode);
1468 fid = v9fs_fid_lookup(dentry); 1472 fid = v9fs_fid_lookup(dentry);
1469 if (IS_ERR(fid)) 1473 if (IS_ERR(fid))
1470 return PTR_ERR(fid); 1474 return PTR_ERR(fid);
1471 1475
1472 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) 1476 if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))
1473 return -EBADF; 1477 return -EBADF;
1474 1478
1475 st = p9_client_stat(fid); 1479 st = p9_client_stat(fid);
1476 if (IS_ERR(st)) 1480 if (IS_ERR(st))
1477 return PTR_ERR(st); 1481 return PTR_ERR(st);
1478 1482
1479 if (!(st->mode & P9_DMSYMLINK)) { 1483 if (!(st->mode & P9_DMSYMLINK)) {
1480 retval = -EINVAL; 1484 retval = -EINVAL;
1481 goto done; 1485 goto done;
1482 } 1486 }
1483 1487
1484 /* copy extension buffer into buffer */ 1488 /* copy extension buffer into buffer */
1485 strncpy(buffer, st->extension, buflen); 1489 strncpy(buffer, st->extension, buflen);
1486 1490
1487 P9_DPRINTK(P9_DEBUG_VFS, 1491 P9_DPRINTK(P9_DEBUG_VFS,
1488 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer); 1492 "%s -> %s (%s)\n", dentry->d_name.name, st->extension, buffer);
1489 1493
1490 retval = strnlen(buffer, buflen); 1494 retval = strnlen(buffer, buflen);
1491 done: 1495 done:
1496 p9stat_free(st);
1492 kfree(st); 1497 kfree(st);
1493 return retval; 1498 return retval;
1494 } 1499 }
1495 1500
1496 /** 1501 /**
1497 * v9fs_vfs_follow_link - follow a symlink path 1502 * v9fs_vfs_follow_link - follow a symlink path
1498 * @dentry: dentry for symlink 1503 * @dentry: dentry for symlink
1499 * @nd: nameidata 1504 * @nd: nameidata
1500 * 1505 *
1501 */ 1506 */
1502 1507
1503 static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) 1508 static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1504 { 1509 {
1505 int len = 0; 1510 int len = 0;
1506 char *link = __getname(); 1511 char *link = __getname();
1507 1512
1508 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); 1513 P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
1509 1514
1510 if (!link) 1515 if (!link)
1511 link = ERR_PTR(-ENOMEM); 1516 link = ERR_PTR(-ENOMEM);
1512 else { 1517 else {
1513 len = v9fs_readlink(dentry, link, PATH_MAX); 1518 len = v9fs_readlink(dentry, link, PATH_MAX);
1514 1519
1515 if (len < 0) { 1520 if (len < 0) {
1516 __putname(link); 1521 __putname(link);
1517 link = ERR_PTR(len); 1522 link = ERR_PTR(len);
1518 } else 1523 } else
1519 link[min(len, PATH_MAX-1)] = 0; 1524 link[min(len, PATH_MAX-1)] = 0;
1520 } 1525 }
1521 nd_set_link(nd, link); 1526 nd_set_link(nd, link);
1522 1527
1523 return NULL; 1528 return NULL;
1524 } 1529 }
1525 1530
1526 /** 1531 /**
1527 * v9fs_vfs_put_link - release a symlink path 1532 * v9fs_vfs_put_link - release a symlink path
1528 * @dentry: dentry for symlink 1533 * @dentry: dentry for symlink
1529 * @nd: nameidata 1534 * @nd: nameidata
1530 * @p: unused 1535 * @p: unused
1531 * 1536 *
1532 */ 1537 */
1533 1538
1534 static void 1539 static void
1535 v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) 1540 v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1536 { 1541 {
1537 char *s = nd_get_link(nd); 1542 char *s = nd_get_link(nd);
1538 1543
1539 P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, 1544 P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name,
1540 IS_ERR(s) ? "<error>" : s); 1545 IS_ERR(s) ? "<error>" : s);
1541 if (!IS_ERR(s)) 1546 if (!IS_ERR(s))
1542 __putname(s); 1547 __putname(s);
1543 } 1548 }
1544 1549
1545 /** 1550 /**
1546 * v9fs_vfs_mkspecial - create a special file 1551 * v9fs_vfs_mkspecial - create a special file
1547 * @dir: inode to create special file in 1552 * @dir: inode to create special file in
1548 * @dentry: dentry to create 1553 * @dentry: dentry to create
1549 * @mode: mode to create special file 1554 * @mode: mode to create special file
1550 * @extension: 9p2000.u format extension string representing special file 1555 * @extension: 9p2000.u format extension string representing special file
1551 * 1556 *
1552 */ 1557 */
1553 1558
1554 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1559 static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1555 int mode, const char *extension) 1560 int mode, const char *extension)
1556 { 1561 {
1557 u32 perm; 1562 u32 perm;
1558 struct v9fs_session_info *v9ses; 1563 struct v9fs_session_info *v9ses;
1559 struct p9_fid *fid; 1564 struct p9_fid *fid;
1560 1565
1561 v9ses = v9fs_inode2v9ses(dir); 1566 v9ses = v9fs_inode2v9ses(dir);
1562 if (!v9fs_proto_dotu(v9ses)) { 1567 if (!v9fs_proto_dotu(v9ses)) {
1563 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); 1568 P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
1564 return -EPERM; 1569 return -EPERM;
1565 } 1570 }
1566 1571
1567 perm = unixmode2p9mode(v9ses, mode); 1572 perm = unixmode2p9mode(v9ses, mode);
1568 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm, 1573 fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
1569 P9_OREAD); 1574 P9_OREAD);
1570 if (IS_ERR(fid)) 1575 if (IS_ERR(fid))
1571 return PTR_ERR(fid); 1576 return PTR_ERR(fid);
1572 1577
1573 p9_client_clunk(fid); 1578 p9_client_clunk(fid);
1574 return 0; 1579 return 0;
1575 } 1580 }
1576 1581
1577 /** 1582 /**
1578 * v9fs_vfs_symlink_dotl - helper function to create symlinks 1583 * v9fs_vfs_symlink_dotl - helper function to create symlinks
1579 * @dir: directory inode containing symlink 1584 * @dir: directory inode containing symlink
1580 * @dentry: dentry for symlink 1585 * @dentry: dentry for symlink
1581 * @symname: symlink data 1586 * @symname: symlink data
1582 * 1587 *
1583 * See Also: 9P2000.L RFC for more information 1588 * See Also: 9P2000.L RFC for more information
1584 * 1589 *
1585 */ 1590 */
1586 1591
1587 static int 1592 static int
1588 v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, 1593 v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
1589 const char *symname) 1594 const char *symname)
1590 { 1595 {
1591 struct v9fs_session_info *v9ses; 1596 struct v9fs_session_info *v9ses;
1592 struct p9_fid *dfid; 1597 struct p9_fid *dfid;
1593 struct p9_fid *fid = NULL; 1598 struct p9_fid *fid = NULL;
1594 struct inode *inode; 1599 struct inode *inode;
1595 struct p9_qid qid; 1600 struct p9_qid qid;
1596 char *name; 1601 char *name;
1597 int err; 1602 int err;
1598 gid_t gid; 1603 gid_t gid;
1599 1604
1600 name = (char *) dentry->d_name.name; 1605 name = (char *) dentry->d_name.name;
1601 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n", 1606 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n",
1602 dir->i_ino, name, symname); 1607 dir->i_ino, name, symname);
1603 v9ses = v9fs_inode2v9ses(dir); 1608 v9ses = v9fs_inode2v9ses(dir);
1604 1609
1605 dfid = v9fs_fid_lookup(dentry->d_parent); 1610 dfid = v9fs_fid_lookup(dentry->d_parent);
1606 if (IS_ERR(dfid)) { 1611 if (IS_ERR(dfid)) {
1607 err = PTR_ERR(dfid); 1612 err = PTR_ERR(dfid);
1608 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 1613 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
1609 return err; 1614 return err;
1610 } 1615 }
1611 1616
1612 gid = v9fs_get_fsgid_for_create(dir); 1617 gid = v9fs_get_fsgid_for_create(dir);
1613 1618
1614 if (gid < 0) { 1619 if (gid < 0) {
1615 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_egid failed %d\n", gid); 1620 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_egid failed %d\n", gid);
1616 goto error; 1621 goto error;
1617 } 1622 }
1618 1623
1619 /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ 1624 /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */
1620 err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); 1625 err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid);
1621 1626
1622 if (err < 0) { 1627 if (err < 0) {
1623 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); 1628 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err);
1624 goto error; 1629 goto error;
1625 } 1630 }
1626 1631
1627 if (v9ses->cache) { 1632 if (v9ses->cache) {
1628 /* Now walk from the parent so we can get an unopened fid. */ 1633 /* Now walk from the parent so we can get an unopened fid. */
1629 fid = p9_client_walk(dfid, 1, &name, 1); 1634 fid = p9_client_walk(dfid, 1, &name, 1);
1630 if (IS_ERR(fid)) { 1635 if (IS_ERR(fid)) {
1631 err = PTR_ERR(fid); 1636 err = PTR_ERR(fid);
1632 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 1637 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
1633 err); 1638 err);
1634 fid = NULL; 1639 fid = NULL;
1635 goto error; 1640 goto error;
1636 } 1641 }
1637 1642
1638 /* instantiate inode and assign the unopened fid to dentry */ 1643 /* instantiate inode and assign the unopened fid to dentry */
1639 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 1644 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1640 if (IS_ERR(inode)) { 1645 if (IS_ERR(inode)) {
1641 err = PTR_ERR(inode); 1646 err = PTR_ERR(inode);
1642 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 1647 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
1643 err); 1648 err);
1644 goto error; 1649 goto error;
1645 } 1650 }
1646 dentry->d_op = &v9fs_cached_dentry_operations; 1651 dentry->d_op = &v9fs_cached_dentry_operations;
1647 d_instantiate(dentry, inode); 1652 d_instantiate(dentry, inode);
1648 err = v9fs_fid_add(dentry, fid); 1653 err = v9fs_fid_add(dentry, fid);
1649 if (err < 0) 1654 if (err < 0)
1650 goto error; 1655 goto error;
1651 fid = NULL; 1656 fid = NULL;
1652 } else { 1657 } else {
1653 /* Not in cached mode. No need to populate inode with stat */ 1658 /* Not in cached mode. No need to populate inode with stat */
1654 inode = v9fs_get_inode(dir->i_sb, S_IFLNK); 1659 inode = v9fs_get_inode(dir->i_sb, S_IFLNK);
1655 if (IS_ERR(inode)) { 1660 if (IS_ERR(inode)) {
1656 err = PTR_ERR(inode); 1661 err = PTR_ERR(inode);
1657 goto error; 1662 goto error;
1658 } 1663 }
1659 dentry->d_op = &v9fs_dentry_operations; 1664 dentry->d_op = &v9fs_dentry_operations;
1660 d_instantiate(dentry, inode); 1665 d_instantiate(dentry, inode);
1661 } 1666 }
1662 1667
1663 error: 1668 error:
1664 if (fid) 1669 if (fid)
1665 p9_client_clunk(fid); 1670 p9_client_clunk(fid);
1666 1671
1667 return err; 1672 return err;
1668 } 1673 }
1669 1674
1670 /** 1675 /**
1671 * v9fs_vfs_symlink - helper function to create symlinks 1676 * v9fs_vfs_symlink - helper function to create symlinks
1672 * @dir: directory inode containing symlink 1677 * @dir: directory inode containing symlink
1673 * @dentry: dentry for symlink 1678 * @dentry: dentry for symlink
1674 * @symname: symlink data 1679 * @symname: symlink data
1675 * 1680 *
1676 * See Also: 9P2000.u RFC for more information 1681 * See Also: 9P2000.u RFC for more information
1677 * 1682 *
1678 */ 1683 */
1679 1684
1680 static int 1685 static int
1681 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 1686 v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1682 { 1687 {
1683 P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, 1688 P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
1684 dentry->d_name.name, symname); 1689 dentry->d_name.name, symname);
1685 1690
1686 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname); 1691 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
1687 } 1692 }
1688 1693
1689 /** 1694 /**
1690 * v9fs_vfs_link - create a hardlink 1695 * v9fs_vfs_link - create a hardlink
1691 * @old_dentry: dentry for file to link to 1696 * @old_dentry: dentry for file to link to
1692 * @dir: inode destination for new link 1697 * @dir: inode destination for new link
1693 * @dentry: dentry for link 1698 * @dentry: dentry for link
1694 * 1699 *
1695 */ 1700 */
1696 1701
1697 static int 1702 static int
1698 v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, 1703 v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1699 struct dentry *dentry) 1704 struct dentry *dentry)
1700 { 1705 {
1701 int retval; 1706 int retval;
1702 struct p9_fid *oldfid; 1707 struct p9_fid *oldfid;
1703 char *name; 1708 char *name;
1704 1709
1705 P9_DPRINTK(P9_DEBUG_VFS, 1710 P9_DPRINTK(P9_DEBUG_VFS,
1706 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1711 " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
1707 old_dentry->d_name.name); 1712 old_dentry->d_name.name);
1708 1713
1709 oldfid = v9fs_fid_clone(old_dentry); 1714 oldfid = v9fs_fid_clone(old_dentry);
1710 if (IS_ERR(oldfid)) 1715 if (IS_ERR(oldfid))
1711 return PTR_ERR(oldfid); 1716 return PTR_ERR(oldfid);
1712 1717
1713 name = __getname(); 1718 name = __getname();
1714 if (unlikely(!name)) { 1719 if (unlikely(!name)) {
1715 retval = -ENOMEM; 1720 retval = -ENOMEM;
1716 goto clunk_fid; 1721 goto clunk_fid;
1717 } 1722 }
1718 1723
1719 sprintf(name, "%d\n", oldfid->fid); 1724 sprintf(name, "%d\n", oldfid->fid);
1720 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); 1725 retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
1721 __putname(name); 1726 __putname(name);
1722 1727
1723 clunk_fid: 1728 clunk_fid:
1724 p9_client_clunk(oldfid); 1729 p9_client_clunk(oldfid);
1725 return retval; 1730 return retval;
1726 } 1731 }
1727 1732
1728 /** 1733 /**
1729 * v9fs_vfs_link_dotl - create a hardlink for dotl 1734 * v9fs_vfs_link_dotl - create a hardlink for dotl
1730 * @old_dentry: dentry for file to link to 1735 * @old_dentry: dentry for file to link to
1731 * @dir: inode destination for new link 1736 * @dir: inode destination for new link
1732 * @dentry: dentry for link 1737 * @dentry: dentry for link
1733 * 1738 *
1734 */ 1739 */
1735 1740
1736 static int 1741 static int
1737 v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, 1742 v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
1738 struct dentry *dentry) 1743 struct dentry *dentry)
1739 { 1744 {
1740 int err; 1745 int err;
1741 struct p9_fid *dfid, *oldfid; 1746 struct p9_fid *dfid, *oldfid;
1742 char *name; 1747 char *name;
1743 struct v9fs_session_info *v9ses; 1748 struct v9fs_session_info *v9ses;
1744 struct dentry *dir_dentry; 1749 struct dentry *dir_dentry;
1745 1750
1746 P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", 1751 P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n",
1747 dir->i_ino, old_dentry->d_name.name, 1752 dir->i_ino, old_dentry->d_name.name,
1748 dentry->d_name.name); 1753 dentry->d_name.name);
1749 1754
1750 v9ses = v9fs_inode2v9ses(dir); 1755 v9ses = v9fs_inode2v9ses(dir);
1751 dir_dentry = v9fs_dentry_from_dir_inode(dir); 1756 dir_dentry = v9fs_dentry_from_dir_inode(dir);
1752 dfid = v9fs_fid_lookup(dir_dentry); 1757 dfid = v9fs_fid_lookup(dir_dentry);
1753 if (IS_ERR(dfid)) 1758 if (IS_ERR(dfid))
1754 return PTR_ERR(dfid); 1759 return PTR_ERR(dfid);
1755 1760
1756 oldfid = v9fs_fid_lookup(old_dentry); 1761 oldfid = v9fs_fid_lookup(old_dentry);
1757 if (IS_ERR(oldfid)) 1762 if (IS_ERR(oldfid))
1758 return PTR_ERR(oldfid); 1763 return PTR_ERR(oldfid);
1759 1764
1760 name = (char *) dentry->d_name.name; 1765 name = (char *) dentry->d_name.name;
1761 1766
1762 err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); 1767 err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name);
1763 1768
1764 if (err < 0) { 1769 if (err < 0) {
1765 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); 1770 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
1766 return err; 1771 return err;
1767 } 1772 }
1768 1773
1769 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 1774 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1770 /* Get the latest stat info from server. */ 1775 /* Get the latest stat info from server. */
1771 struct p9_fid *fid; 1776 struct p9_fid *fid;
1772 struct p9_stat_dotl *st; 1777 struct p9_stat_dotl *st;
1773 1778
1774 fid = v9fs_fid_lookup(old_dentry); 1779 fid = v9fs_fid_lookup(old_dentry);
1775 if (IS_ERR(fid)) 1780 if (IS_ERR(fid))
1776 return PTR_ERR(fid); 1781 return PTR_ERR(fid);
1777 1782
1778 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 1783 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
1779 if (IS_ERR(st)) 1784 if (IS_ERR(st))
1780 return PTR_ERR(st); 1785 return PTR_ERR(st);
1781 1786
1782 v9fs_stat2inode_dotl(st, old_dentry->d_inode); 1787 v9fs_stat2inode_dotl(st, old_dentry->d_inode);
1783 1788
1784 kfree(st); 1789 kfree(st);
1785 } else { 1790 } else {
1786 /* Caching disabled. No need to get upto date stat info. 1791 /* Caching disabled. No need to get upto date stat info.
1787 * This dentry will be released immediately. So, just i_count++ 1792 * This dentry will be released immediately. So, just i_count++
1788 */ 1793 */
1789 atomic_inc(&old_dentry->d_inode->i_count); 1794 atomic_inc(&old_dentry->d_inode->i_count);
1790 } 1795 }
1791 1796
1792 dentry->d_op = old_dentry->d_op; 1797 dentry->d_op = old_dentry->d_op;
1793 d_instantiate(dentry, old_dentry->d_inode); 1798 d_instantiate(dentry, old_dentry->d_inode);
1794 1799
1795 return err; 1800 return err;
1796 } 1801 }
1797 1802
1798 /** 1803 /**
1799 * v9fs_vfs_mknod - create a special file 1804 * v9fs_vfs_mknod - create a special file
1800 * @dir: inode destination for new link 1805 * @dir: inode destination for new link
1801 * @dentry: dentry for file 1806 * @dentry: dentry for file
1802 * @mode: mode for creation 1807 * @mode: mode for creation
1803 * @rdev: device associated with special file 1808 * @rdev: device associated with special file
1804 * 1809 *
1805 */ 1810 */
1806 1811
1807 static int 1812 static int
1808 v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) 1813 v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1809 { 1814 {
1810 int retval; 1815 int retval;
1811 char *name; 1816 char *name;
1812 1817
1813 P9_DPRINTK(P9_DEBUG_VFS, 1818 P9_DPRINTK(P9_DEBUG_VFS,
1814 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1819 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
1815 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1820 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1816 1821
1817 if (!new_valid_dev(rdev)) 1822 if (!new_valid_dev(rdev))
1818 return -EINVAL; 1823 return -EINVAL;
1819 1824
1820 name = __getname(); 1825 name = __getname();
1821 if (!name) 1826 if (!name)
1822 return -ENOMEM; 1827 return -ENOMEM;
1823 /* build extension */ 1828 /* build extension */
1824 if (S_ISBLK(mode)) 1829 if (S_ISBLK(mode))
1825 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev)); 1830 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1826 else if (S_ISCHR(mode)) 1831 else if (S_ISCHR(mode))
1827 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); 1832 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1828 else if (S_ISFIFO(mode)) 1833 else if (S_ISFIFO(mode))
1829 *name = 0; 1834 *name = 0;
1830 else if (S_ISSOCK(mode)) 1835 else if (S_ISSOCK(mode))
1831 *name = 0; 1836 *name = 0;
1832 else { 1837 else {
1833 __putname(name); 1838 __putname(name);
1834 return -EINVAL; 1839 return -EINVAL;
1835 } 1840 }
1836 1841
1837 retval = v9fs_vfs_mkspecial(dir, dentry, mode, name); 1842 retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
1838 __putname(name); 1843 __putname(name);
1839 1844
1840 return retval; 1845 return retval;
1841 } 1846 }
1842 1847
1843 /** 1848 /**
1844 * v9fs_vfs_mknod_dotl - create a special file 1849 * v9fs_vfs_mknod_dotl - create a special file
1845 * @dir: inode destination for new link 1850 * @dir: inode destination for new link
1846 * @dentry: dentry for file 1851 * @dentry: dentry for file
1847 * @mode: mode for creation 1852 * @mode: mode for creation
1848 * @rdev: device associated with special file 1853 * @rdev: device associated with special file
1849 * 1854 *
1850 */ 1855 */
1851 static int 1856 static int
1852 v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, 1857 v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode,
1853 dev_t rdev) 1858 dev_t rdev)
1854 { 1859 {
1855 int err; 1860 int err;
1856 char *name; 1861 char *name;
1857 struct v9fs_session_info *v9ses; 1862 struct v9fs_session_info *v9ses;
1858 struct p9_fid *fid = NULL, *dfid = NULL; 1863 struct p9_fid *fid = NULL, *dfid = NULL;
1859 struct inode *inode; 1864 struct inode *inode;
1860 gid_t gid; 1865 gid_t gid;
1861 struct p9_qid qid; 1866 struct p9_qid qid;
1862 struct dentry *dir_dentry; 1867 struct dentry *dir_dentry;
1863 1868
1864 P9_DPRINTK(P9_DEBUG_VFS, 1869 P9_DPRINTK(P9_DEBUG_VFS,
1865 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1870 " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
1866 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1871 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1867 1872
1868 if (!new_valid_dev(rdev)) 1873 if (!new_valid_dev(rdev))
1869 return -EINVAL; 1874 return -EINVAL;
1870 1875
1871 v9ses = v9fs_inode2v9ses(dir); 1876 v9ses = v9fs_inode2v9ses(dir);
1872 dir_dentry = v9fs_dentry_from_dir_inode(dir); 1877 dir_dentry = v9fs_dentry_from_dir_inode(dir);
1873 dfid = v9fs_fid_lookup(dir_dentry); 1878 dfid = v9fs_fid_lookup(dir_dentry);
1874 if (IS_ERR(dfid)) { 1879 if (IS_ERR(dfid)) {
1875 err = PTR_ERR(dfid); 1880 err = PTR_ERR(dfid);
1876 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); 1881 P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
1877 dfid = NULL; 1882 dfid = NULL;
1878 goto error; 1883 goto error;
1879 } 1884 }
1880 1885
1881 gid = v9fs_get_fsgid_for_create(dir); 1886 gid = v9fs_get_fsgid_for_create(dir);
1882 if (gid < 0) { 1887 if (gid < 0) {
1883 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); 1888 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n");
1884 goto error; 1889 goto error;
1885 } 1890 }
1886 1891
1887 name = (char *) dentry->d_name.name; 1892 name = (char *) dentry->d_name.name;
1888 1893
1889 err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); 1894 err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
1890 if (err < 0) 1895 if (err < 0)
1891 goto error; 1896 goto error;
1892 1897
1893 /* instantiate inode and assign the unopened fid to the dentry */ 1898 /* instantiate inode and assign the unopened fid to the dentry */
1894 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 1899 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
1895 fid = p9_client_walk(dfid, 1, &name, 1); 1900 fid = p9_client_walk(dfid, 1, &name, 1);
1896 if (IS_ERR(fid)) { 1901 if (IS_ERR(fid)) {
1897 err = PTR_ERR(fid); 1902 err = PTR_ERR(fid);
1898 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", 1903 P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
1899 err); 1904 err);
1900 fid = NULL; 1905 fid = NULL;
1901 goto error; 1906 goto error;
1902 } 1907 }
1903 1908
1904 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); 1909 inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
1905 if (IS_ERR(inode)) { 1910 if (IS_ERR(inode)) {
1906 err = PTR_ERR(inode); 1911 err = PTR_ERR(inode);
1907 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 1912 P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
1908 err); 1913 err);
1909 goto error; 1914 goto error;
1910 } 1915 }
1911 dentry->d_op = &v9fs_cached_dentry_operations; 1916 dentry->d_op = &v9fs_cached_dentry_operations;
1912 d_instantiate(dentry, inode); 1917 d_instantiate(dentry, inode);
1913 err = v9fs_fid_add(dentry, fid); 1918 err = v9fs_fid_add(dentry, fid);
1914 if (err < 0) 1919 if (err < 0)
1915 goto error; 1920 goto error;
1916 fid = NULL; 1921 fid = NULL;
1917 } else { 1922 } else {
1918 /* 1923 /*
1919 * Not in cached mode. No need to populate inode with stat. 1924 * Not in cached mode. No need to populate inode with stat.
1920 * socket syscall returns a fd, so we need instantiate 1925 * socket syscall returns a fd, so we need instantiate
1921 */ 1926 */
1922 inode = v9fs_get_inode(dir->i_sb, mode); 1927 inode = v9fs_get_inode(dir->i_sb, mode);
1923 if (IS_ERR(inode)) { 1928 if (IS_ERR(inode)) {
1924 err = PTR_ERR(inode); 1929 err = PTR_ERR(inode);
1925 goto error; 1930 goto error;
1926 } 1931 }
1927 dentry->d_op = &v9fs_dentry_operations; 1932 dentry->d_op = &v9fs_dentry_operations;
1928 d_instantiate(dentry, inode); 1933 d_instantiate(dentry, inode);
1929 } 1934 }
1930 1935
1931 error: 1936 error:
1932 if (fid) 1937 if (fid)
1933 p9_client_clunk(fid); 1938 p9_client_clunk(fid);
1934 return err; 1939 return err;
1935 } 1940 }
1936 1941
1937 static const struct inode_operations v9fs_dir_inode_operations_dotu = { 1942 static const struct inode_operations v9fs_dir_inode_operations_dotu = {
1938 .create = v9fs_vfs_create, 1943 .create = v9fs_vfs_create,
1939 .lookup = v9fs_vfs_lookup, 1944 .lookup = v9fs_vfs_lookup,
1940 .symlink = v9fs_vfs_symlink, 1945 .symlink = v9fs_vfs_symlink,
1941 .link = v9fs_vfs_link, 1946 .link = v9fs_vfs_link,
1942 .unlink = v9fs_vfs_unlink, 1947 .unlink = v9fs_vfs_unlink,
1943 .mkdir = v9fs_vfs_mkdir, 1948 .mkdir = v9fs_vfs_mkdir,
1944 .rmdir = v9fs_vfs_rmdir, 1949 .rmdir = v9fs_vfs_rmdir,
1945 .mknod = v9fs_vfs_mknod_dotl, 1950 .mknod = v9fs_vfs_mknod,
1946 .rename = v9fs_vfs_rename, 1951 .rename = v9fs_vfs_rename,
1947 .getattr = v9fs_vfs_getattr, 1952 .getattr = v9fs_vfs_getattr,
1948 .setattr = v9fs_vfs_setattr, 1953 .setattr = v9fs_vfs_setattr,
1949 }; 1954 };
1950 1955
1951 static const struct inode_operations v9fs_dir_inode_operations_dotl = { 1956 static const struct inode_operations v9fs_dir_inode_operations_dotl = {
1952 .create = v9fs_vfs_create_dotl, 1957 .create = v9fs_vfs_create_dotl,
1953 .lookup = v9fs_vfs_lookup, 1958 .lookup = v9fs_vfs_lookup,
1954 .link = v9fs_vfs_link_dotl, 1959 .link = v9fs_vfs_link_dotl,
1955 .symlink = v9fs_vfs_symlink_dotl, 1960 .symlink = v9fs_vfs_symlink_dotl,
1956 .unlink = v9fs_vfs_unlink, 1961 .unlink = v9fs_vfs_unlink,
1957 .mkdir = v9fs_vfs_mkdir_dotl, 1962 .mkdir = v9fs_vfs_mkdir_dotl,
1958 .rmdir = v9fs_vfs_rmdir, 1963 .rmdir = v9fs_vfs_rmdir,
1959 .mknod = v9fs_vfs_mknod_dotl, 1964 .mknod = v9fs_vfs_mknod_dotl,
1960 .rename = v9fs_vfs_rename, 1965 .rename = v9fs_vfs_rename,
1961 .getattr = v9fs_vfs_getattr_dotl, 1966 .getattr = v9fs_vfs_getattr_dotl,
1962 .setattr = v9fs_vfs_setattr_dotl, 1967 .setattr = v9fs_vfs_setattr_dotl,
1963 .setxattr = generic_setxattr, 1968 .setxattr = generic_setxattr,
1964 .getxattr = generic_getxattr, 1969 .getxattr = generic_getxattr,
1965 .removexattr = generic_removexattr, 1970 .removexattr = generic_removexattr,
1966 .listxattr = v9fs_listxattr, 1971 .listxattr = v9fs_listxattr,
1967 1972
1968 }; 1973 };
1969 1974
1970 static const struct inode_operations v9fs_dir_inode_operations = { 1975 static const struct inode_operations v9fs_dir_inode_operations = {
1971 .create = v9fs_vfs_create, 1976 .create = v9fs_vfs_create,
1972 .lookup = v9fs_vfs_lookup, 1977 .lookup = v9fs_vfs_lookup,
1973 .unlink = v9fs_vfs_unlink, 1978 .unlink = v9fs_vfs_unlink,
1974 .mkdir = v9fs_vfs_mkdir, 1979 .mkdir = v9fs_vfs_mkdir,
1975 .rmdir = v9fs_vfs_rmdir, 1980 .rmdir = v9fs_vfs_rmdir,
1976 .mknod = v9fs_vfs_mknod, 1981 .mknod = v9fs_vfs_mknod,
1977 .rename = v9fs_vfs_rename, 1982 .rename = v9fs_vfs_rename,
1978 .getattr = v9fs_vfs_getattr, 1983 .getattr = v9fs_vfs_getattr,
1979 .setattr = v9fs_vfs_setattr, 1984 .setattr = v9fs_vfs_setattr,
1980 }; 1985 };
1981 1986
1982 static const struct inode_operations v9fs_file_inode_operations = { 1987 static const struct inode_operations v9fs_file_inode_operations = {
1983 .getattr = v9fs_vfs_getattr, 1988 .getattr = v9fs_vfs_getattr,
1984 .setattr = v9fs_vfs_setattr, 1989 .setattr = v9fs_vfs_setattr,
1985 }; 1990 };
1986 1991
1987 static const struct inode_operations v9fs_file_inode_operations_dotl = { 1992 static const struct inode_operations v9fs_file_inode_operations_dotl = {
1988 .getattr = v9fs_vfs_getattr_dotl, 1993 .getattr = v9fs_vfs_getattr_dotl,
1989 .setattr = v9fs_vfs_setattr_dotl, 1994 .setattr = v9fs_vfs_setattr_dotl,
1990 .setxattr = generic_setxattr, 1995 .setxattr = generic_setxattr,
1991 .getxattr = generic_getxattr, 1996 .getxattr = generic_getxattr,
1992 .removexattr = generic_removexattr, 1997 .removexattr = generic_removexattr,
1993 .listxattr = v9fs_listxattr, 1998 .listxattr = v9fs_listxattr,
1994 }; 1999 };
1995 2000
1996 static const struct inode_operations v9fs_symlink_inode_operations = { 2001 static const struct inode_operations v9fs_symlink_inode_operations = {
1997 .readlink = generic_readlink, 2002 .readlink = generic_readlink,
1998 .follow_link = v9fs_vfs_follow_link, 2003 .follow_link = v9fs_vfs_follow_link,
1999 .put_link = v9fs_vfs_put_link, 2004 .put_link = v9fs_vfs_put_link,
2000 .getattr = v9fs_vfs_getattr, 2005 .getattr = v9fs_vfs_getattr,
2001 .setattr = v9fs_vfs_setattr, 2006 .setattr = v9fs_vfs_setattr,
2002 }; 2007 };
2003 2008
2004 static const struct inode_operations v9fs_symlink_inode_operations_dotl = { 2009 static const struct inode_operations v9fs_symlink_inode_operations_dotl = {
2005 .readlink = generic_readlink, 2010 .readlink = generic_readlink,
2006 .follow_link = v9fs_vfs_follow_link, 2011 .follow_link = v9fs_vfs_follow_link,
2007 .put_link = v9fs_vfs_put_link, 2012 .put_link = v9fs_vfs_put_link,
2008 .getattr = v9fs_vfs_getattr_dotl, 2013 .getattr = v9fs_vfs_getattr_dotl,
2009 .setattr = v9fs_vfs_setattr_dotl, 2014 .setattr = v9fs_vfs_setattr_dotl,
2010 .setxattr = generic_setxattr, 2015 .setxattr = generic_setxattr,
2011 .getxattr = generic_getxattr, 2016 .getxattr = generic_getxattr,
2012 .removexattr = generic_removexattr, 2017 .removexattr = generic_removexattr,
2013 .listxattr = v9fs_listxattr, 2018 .listxattr = v9fs_listxattr,
2014 }; 2019 };
2015 2020
1 /* 1 /*
2 * linux/fs/9p/vfs_super.c 2 * linux/fs/9p/vfs_super.c
3 * 3 *
4 * This file contians superblock ops for 9P2000. It is intended that 4 * This file contians superblock ops for 9P2000. It is intended that
5 * you mount this file system on directories. 5 * you mount this file system on directories.
6 * 6 *
7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 7 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 8 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation. 12 * as published by the Free Software Foundation.
13 * 13 *
14 * This program is distributed in the hope that it will be useful, 14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details. 17 * GNU General Public License for more details.
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to: 20 * along with this program; if not, write to:
21 * Free Software Foundation 21 * Free Software Foundation
22 * 51 Franklin Street, Fifth Floor 22 * 51 Franklin Street, Fifth Floor
23 * Boston, MA 02111-1301 USA 23 * Boston, MA 02111-1301 USA
24 * 24 *
25 */ 25 */
26 26
27 #include <linux/kernel.h> 27 #include <linux/kernel.h>
28 #include <linux/module.h> 28 #include <linux/module.h>
29 #include <linux/errno.h> 29 #include <linux/errno.h>
30 #include <linux/fs.h> 30 #include <linux/fs.h>
31 #include <linux/file.h> 31 #include <linux/file.h>
32 #include <linux/stat.h> 32 #include <linux/stat.h>
33 #include <linux/string.h> 33 #include <linux/string.h>
34 #include <linux/inet.h> 34 #include <linux/inet.h>
35 #include <linux/pagemap.h> 35 #include <linux/pagemap.h>
36 #include <linux/seq_file.h> 36 #include <linux/seq_file.h>
37 #include <linux/mount.h> 37 #include <linux/mount.h>
38 #include <linux/idr.h> 38 #include <linux/idr.h>
39 #include <linux/sched.h> 39 #include <linux/sched.h>
40 #include <linux/slab.h> 40 #include <linux/slab.h>
41 #include <linux/statfs.h> 41 #include <linux/statfs.h>
42 #include <net/9p/9p.h> 42 #include <net/9p/9p.h>
43 #include <net/9p/client.h> 43 #include <net/9p/client.h>
44 44
45 #include "v9fs.h" 45 #include "v9fs.h"
46 #include "v9fs_vfs.h" 46 #include "v9fs_vfs.h"
47 #include "fid.h" 47 #include "fid.h"
48 #include "xattr.h" 48 #include "xattr.h"
49 49
50 static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; 50 static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl;
51 51
52 /** 52 /**
53 * v9fs_set_super - set the superblock 53 * v9fs_set_super - set the superblock
54 * @s: super block 54 * @s: super block
55 * @data: file system specific data 55 * @data: file system specific data
56 * 56 *
57 */ 57 */
58 58
59 static int v9fs_set_super(struct super_block *s, void *data) 59 static int v9fs_set_super(struct super_block *s, void *data)
60 { 60 {
61 s->s_fs_info = data; 61 s->s_fs_info = data;
62 return set_anon_super(s, data); 62 return set_anon_super(s, data);
63 } 63 }
64 64
65 /** 65 /**
66 * v9fs_fill_super - populate superblock with info 66 * v9fs_fill_super - populate superblock with info
67 * @sb: superblock 67 * @sb: superblock
68 * @v9ses: session information 68 * @v9ses: session information
69 * @flags: flags propagated from v9fs_get_sb() 69 * @flags: flags propagated from v9fs_get_sb()
70 * 70 *
71 */ 71 */
72 72
73 static void 73 static void
74 v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, 74 v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
75 int flags, void *data) 75 int flags, void *data)
76 { 76 {
77 sb->s_maxbytes = MAX_LFS_FILESIZE; 77 sb->s_maxbytes = MAX_LFS_FILESIZE;
78 sb->s_blocksize_bits = fls(v9ses->maxdata - 1); 78 sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
79 sb->s_blocksize = 1 << sb->s_blocksize_bits; 79 sb->s_blocksize = 1 << sb->s_blocksize_bits;
80 sb->s_magic = V9FS_MAGIC; 80 sb->s_magic = V9FS_MAGIC;
81 if (v9fs_proto_dotl(v9ses)) { 81 if (v9fs_proto_dotl(v9ses)) {
82 sb->s_op = &v9fs_super_ops_dotl; 82 sb->s_op = &v9fs_super_ops_dotl;
83 sb->s_xattr = v9fs_xattr_handlers; 83 sb->s_xattr = v9fs_xattr_handlers;
84 } else 84 } else
85 sb->s_op = &v9fs_super_ops; 85 sb->s_op = &v9fs_super_ops;
86 sb->s_bdi = &v9ses->bdi; 86 sb->s_bdi = &v9ses->bdi;
87 87
88 sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | 88 sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
89 MS_NOATIME; 89 MS_NOATIME;
90 90
91 save_mount_options(sb, data); 91 save_mount_options(sb, data);
92 } 92 }
93 93
94 /** 94 /**
95 * v9fs_get_sb - mount a superblock 95 * v9fs_get_sb - mount a superblock
96 * @fs_type: file system type 96 * @fs_type: file system type
97 * @flags: mount flags 97 * @flags: mount flags
98 * @dev_name: device name that was mounted 98 * @dev_name: device name that was mounted
99 * @data: mount options 99 * @data: mount options
100 * @mnt: mountpoint record to be instantiated 100 * @mnt: mountpoint record to be instantiated
101 * 101 *
102 */ 102 */
103 103
104 static int v9fs_get_sb(struct file_system_type *fs_type, int flags, 104 static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
105 const char *dev_name, void *data, 105 const char *dev_name, void *data,
106 struct vfsmount *mnt) 106 struct vfsmount *mnt)
107 { 107 {
108 struct super_block *sb = NULL; 108 struct super_block *sb = NULL;
109 struct inode *inode = NULL; 109 struct inode *inode = NULL;
110 struct dentry *root = NULL; 110 struct dentry *root = NULL;
111 struct v9fs_session_info *v9ses = NULL; 111 struct v9fs_session_info *v9ses = NULL;
112 int mode = S_IRWXUGO | S_ISVTX; 112 int mode = S_IRWXUGO | S_ISVTX;
113 struct p9_fid *fid; 113 struct p9_fid *fid;
114 int retval = 0; 114 int retval = 0;
115 115
116 P9_DPRINTK(P9_DEBUG_VFS, " \n"); 116 P9_DPRINTK(P9_DEBUG_VFS, " \n");
117 117
118 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); 118 v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
119 if (!v9ses) 119 if (!v9ses)
120 return -ENOMEM; 120 return -ENOMEM;
121 121
122 fid = v9fs_session_init(v9ses, dev_name, data); 122 fid = v9fs_session_init(v9ses, dev_name, data);
123 if (IS_ERR(fid)) { 123 if (IS_ERR(fid)) {
124 retval = PTR_ERR(fid); 124 retval = PTR_ERR(fid);
125 /*
126 * we need to call session_close to tear down some
127 * of the data structure setup by session_init
128 */
125 goto close_session; 129 goto close_session;
126 } 130 }
127 131
128 sb = sget(fs_type, NULL, v9fs_set_super, v9ses); 132 sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
129 if (IS_ERR(sb)) { 133 if (IS_ERR(sb)) {
130 retval = PTR_ERR(sb); 134 retval = PTR_ERR(sb);
131 goto clunk_fid; 135 goto clunk_fid;
132 } 136 }
133 v9fs_fill_super(sb, v9ses, flags, data); 137 v9fs_fill_super(sb, v9ses, flags, data);
134 138
135 inode = v9fs_get_inode(sb, S_IFDIR | mode); 139 inode = v9fs_get_inode(sb, S_IFDIR | mode);
136 if (IS_ERR(inode)) { 140 if (IS_ERR(inode)) {
137 retval = PTR_ERR(inode); 141 retval = PTR_ERR(inode);
138 goto release_sb; 142 goto release_sb;
139 } 143 }
140 144
141 root = d_alloc_root(inode); 145 root = d_alloc_root(inode);
142 if (!root) { 146 if (!root) {
143 iput(inode); 147 iput(inode);
144 retval = -ENOMEM; 148 retval = -ENOMEM;
145 goto release_sb; 149 goto release_sb;
146 } 150 }
147
148 sb->s_root = root; 151 sb->s_root = root;
149 152
150 if (v9fs_proto_dotl(v9ses)) { 153 if (v9fs_proto_dotl(v9ses)) {
151 struct p9_stat_dotl *st = NULL; 154 struct p9_stat_dotl *st = NULL;
152 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); 155 st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
153 if (IS_ERR(st)) { 156 if (IS_ERR(st)) {
154 retval = PTR_ERR(st); 157 retval = PTR_ERR(st);
155 goto clunk_fid; 158 goto release_sb;
156 } 159 }
157 160
158 v9fs_stat2inode_dotl(st, root->d_inode); 161 v9fs_stat2inode_dotl(st, root->d_inode);
159 kfree(st); 162 kfree(st);
160 } else { 163 } else {
161 struct p9_wstat *st = NULL; 164 struct p9_wstat *st = NULL;
162 st = p9_client_stat(fid); 165 st = p9_client_stat(fid);
163 if (IS_ERR(st)) { 166 if (IS_ERR(st)) {
164 retval = PTR_ERR(st); 167 retval = PTR_ERR(st);
165 goto clunk_fid; 168 goto release_sb;
166 } 169 }
167 170
168 root->d_inode->i_ino = v9fs_qid2ino(&st->qid); 171 root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
169 v9fs_stat2inode(st, root->d_inode, sb); 172 v9fs_stat2inode(st, root->d_inode, sb);
170 173
171 p9stat_free(st); 174 p9stat_free(st);
172 kfree(st); 175 kfree(st);
173 } 176 }
174 177
175 v9fs_fid_add(root, fid); 178 v9fs_fid_add(root, fid);
176 179
177 P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); 180 P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
178 simple_set_mnt(mnt, sb); 181 simple_set_mnt(mnt, sb);
179 return 0; 182 return 0;
180 183
181 clunk_fid: 184 clunk_fid:
182 p9_client_clunk(fid); 185 p9_client_clunk(fid);
183
184 close_session: 186 close_session:
185 v9fs_session_close(v9ses); 187 v9fs_session_close(v9ses);
186 kfree(v9ses); 188 kfree(v9ses);
187 return retval; 189 return retval;
188
189 release_sb: 190 release_sb:
191 /*
192 * we will do the session_close and root dentry release
193 * in the below call. But we need to clunk fid, because we haven't
194 * attached the fid to dentry so it won't get clunked
195 * automatically.
196 */
197 p9_client_clunk(fid);
190 deactivate_locked_super(sb); 198 deactivate_locked_super(sb);
191 return retval; 199 return retval;
192 } 200 }
193 201
194 /** 202 /**
195 * v9fs_kill_super - Kill Superblock 203 * v9fs_kill_super - Kill Superblock
196 * @s: superblock 204 * @s: superblock
197 * 205 *
198 */ 206 */
199 207
200 static void v9fs_kill_super(struct super_block *s) 208 static void v9fs_kill_super(struct super_block *s)
201 { 209 {
202 struct v9fs_session_info *v9ses = s->s_fs_info; 210 struct v9fs_session_info *v9ses = s->s_fs_info;
203 211
204 P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s); 212 P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
205 213
206 if (s->s_root) 214 if (s->s_root)
207 v9fs_dentry_release(s->s_root); /* clunk root */ 215 v9fs_dentry_release(s->s_root); /* clunk root */
208 216
209 kill_anon_super(s); 217 kill_anon_super(s);
210 218
211 v9fs_session_cancel(v9ses); 219 v9fs_session_cancel(v9ses);
212 v9fs_session_close(v9ses); 220 v9fs_session_close(v9ses);
213 kfree(v9ses); 221 kfree(v9ses);
214 s->s_fs_info = NULL; 222 s->s_fs_info = NULL;
215 P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n"); 223 P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
216 } 224 }
217 225
218 static void 226 static void
219 v9fs_umount_begin(struct super_block *sb) 227 v9fs_umount_begin(struct super_block *sb)
220 { 228 {
221 struct v9fs_session_info *v9ses; 229 struct v9fs_session_info *v9ses;
222 230
223 v9ses = sb->s_fs_info; 231 v9ses = sb->s_fs_info;
224 v9fs_session_begin_cancel(v9ses); 232 v9fs_session_begin_cancel(v9ses);
225 } 233 }
226 234
227 static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) 235 static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
228 { 236 {
229 struct v9fs_session_info *v9ses; 237 struct v9fs_session_info *v9ses;
230 struct p9_fid *fid; 238 struct p9_fid *fid;
231 struct p9_rstatfs rs; 239 struct p9_rstatfs rs;
232 int res; 240 int res;
233 241
234 fid = v9fs_fid_lookup(dentry); 242 fid = v9fs_fid_lookup(dentry);
235 if (IS_ERR(fid)) { 243 if (IS_ERR(fid)) {
236 res = PTR_ERR(fid); 244 res = PTR_ERR(fid);
237 goto done; 245 goto done;
238 } 246 }
239 247
240 v9ses = v9fs_inode2v9ses(dentry->d_inode); 248 v9ses = v9fs_inode2v9ses(dentry->d_inode);
241 if (v9fs_proto_dotl(v9ses)) { 249 if (v9fs_proto_dotl(v9ses)) {
242 res = p9_client_statfs(fid, &rs); 250 res = p9_client_statfs(fid, &rs);
243 if (res == 0) { 251 if (res == 0) {
244 buf->f_type = rs.type; 252 buf->f_type = rs.type;
245 buf->f_bsize = rs.bsize; 253 buf->f_bsize = rs.bsize;
246 buf->f_blocks = rs.blocks; 254 buf->f_blocks = rs.blocks;
247 buf->f_bfree = rs.bfree; 255 buf->f_bfree = rs.bfree;
248 buf->f_bavail = rs.bavail; 256 buf->f_bavail = rs.bavail;
249 buf->f_files = rs.files; 257 buf->f_files = rs.files;
250 buf->f_ffree = rs.ffree; 258 buf->f_ffree = rs.ffree;
251 buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; 259 buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL;
252 buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; 260 buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL;
253 buf->f_namelen = rs.namelen; 261 buf->f_namelen = rs.namelen;
254 } 262 }
255 if (res != -ENOSYS) 263 if (res != -ENOSYS)
256 goto done; 264 goto done;
257 } 265 }
258 res = simple_statfs(dentry, buf); 266 res = simple_statfs(dentry, buf);
259 done: 267 done:
260 return res; 268 return res;
261 } 269 }
262 270
263 static const struct super_operations v9fs_super_ops = { 271 static const struct super_operations v9fs_super_ops = {
264 #ifdef CONFIG_9P_FSCACHE 272 #ifdef CONFIG_9P_FSCACHE
265 .alloc_inode = v9fs_alloc_inode, 273 .alloc_inode = v9fs_alloc_inode,
266 .destroy_inode = v9fs_destroy_inode, 274 .destroy_inode = v9fs_destroy_inode,
267 #endif 275 #endif
268 .statfs = simple_statfs, 276 .statfs = simple_statfs,
269 .evict_inode = v9fs_evict_inode, 277 .evict_inode = v9fs_evict_inode,
270 .show_options = generic_show_options, 278 .show_options = generic_show_options,
271 .umount_begin = v9fs_umount_begin, 279 .umount_begin = v9fs_umount_begin,
272 }; 280 };
273 281
274 static const struct super_operations v9fs_super_ops_dotl = { 282 static const struct super_operations v9fs_super_ops_dotl = {
275 #ifdef CONFIG_9P_FSCACHE 283 #ifdef CONFIG_9P_FSCACHE
276 .alloc_inode = v9fs_alloc_inode, 284 .alloc_inode = v9fs_alloc_inode,
277 .destroy_inode = v9fs_destroy_inode, 285 .destroy_inode = v9fs_destroy_inode,
278 #endif 286 #endif
279 .statfs = v9fs_statfs, 287 .statfs = v9fs_statfs,
280 .evict_inode = v9fs_evict_inode, 288 .evict_inode = v9fs_evict_inode,
281 .show_options = generic_show_options, 289 .show_options = generic_show_options,
282 .umount_begin = v9fs_umount_begin, 290 .umount_begin = v9fs_umount_begin,
283 }; 291 };
284 292
285 struct file_system_type v9fs_fs_type = { 293 struct file_system_type v9fs_fs_type = {
286 .name = "9p", 294 .name = "9p",
287 .get_sb = v9fs_get_sb, 295 .get_sb = v9fs_get_sb,
288 .kill_sb = v9fs_kill_super, 296 .kill_sb = v9fs_kill_super,
289 .owner = THIS_MODULE, 297 .owner = THIS_MODULE,
1 /* 1 /*
2 * net/9p/clnt.c 2 * net/9p/clnt.c
3 * 3 *
4 * 9P Client 4 * 9P Client
5 * 5 *
6 * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com> 6 * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
7 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net> 7 * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
8 * 8 *
9 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation. 11 * as published by the Free Software Foundation.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to: 19 * along with this program; if not, write to:
20 * Free Software Foundation 20 * Free Software Foundation
21 * 51 Franklin Street, Fifth Floor 21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02111-1301 USA 22 * Boston, MA 02111-1301 USA
23 * 23 *
24 */ 24 */
25 25
26 #include <linux/module.h> 26 #include <linux/module.h>
27 #include <linux/errno.h> 27 #include <linux/errno.h>
28 #include <linux/fs.h> 28 #include <linux/fs.h>
29 #include <linux/poll.h> 29 #include <linux/poll.h>
30 #include <linux/idr.h> 30 #include <linux/idr.h>
31 #include <linux/mutex.h> 31 #include <linux/mutex.h>
32 #include <linux/slab.h> 32 #include <linux/slab.h>
33 #include <linux/sched.h> 33 #include <linux/sched.h>
34 #include <linux/uaccess.h> 34 #include <linux/uaccess.h>
35 #include <net/9p/9p.h> 35 #include <net/9p/9p.h>
36 #include <linux/parser.h> 36 #include <linux/parser.h>
37 #include <net/9p/client.h> 37 #include <net/9p/client.h>
38 #include <net/9p/transport.h> 38 #include <net/9p/transport.h>
39 #include "protocol.h" 39 #include "protocol.h"
40 40
41 /* 41 /*
42 * Client Option Parsing (code inspired by NFS code) 42 * Client Option Parsing (code inspired by NFS code)
43 * - a little lazy - parse all client options 43 * - a little lazy - parse all client options
44 */ 44 */
45 45
46 enum { 46 enum {
47 Opt_msize, 47 Opt_msize,
48 Opt_trans, 48 Opt_trans,
49 Opt_legacy, 49 Opt_legacy,
50 Opt_version, 50 Opt_version,
51 Opt_err, 51 Opt_err,
52 }; 52 };
53 53
54 static const match_table_t tokens = { 54 static const match_table_t tokens = {
55 {Opt_msize, "msize=%u"}, 55 {Opt_msize, "msize=%u"},
56 {Opt_legacy, "noextend"}, 56 {Opt_legacy, "noextend"},
57 {Opt_trans, "trans=%s"}, 57 {Opt_trans, "trans=%s"},
58 {Opt_version, "version=%s"}, 58 {Opt_version, "version=%s"},
59 {Opt_err, NULL}, 59 {Opt_err, NULL},
60 }; 60 };
61 61
62 inline int p9_is_proto_dotl(struct p9_client *clnt) 62 inline int p9_is_proto_dotl(struct p9_client *clnt)
63 { 63 {
64 return (clnt->proto_version == p9_proto_2000L); 64 return (clnt->proto_version == p9_proto_2000L);
65 } 65 }
66 EXPORT_SYMBOL(p9_is_proto_dotl); 66 EXPORT_SYMBOL(p9_is_proto_dotl);
67 67
68 inline int p9_is_proto_dotu(struct p9_client *clnt) 68 inline int p9_is_proto_dotu(struct p9_client *clnt)
69 { 69 {
70 return (clnt->proto_version == p9_proto_2000u); 70 return (clnt->proto_version == p9_proto_2000u);
71 } 71 }
72 EXPORT_SYMBOL(p9_is_proto_dotu); 72 EXPORT_SYMBOL(p9_is_proto_dotu);
73 73
74 /* Interpret mount option for protocol version */ 74 /* Interpret mount option for protocol version */
75 static int get_protocol_version(const substring_t *name) 75 static int get_protocol_version(const substring_t *name)
76 { 76 {
77 int version = -EINVAL; 77 int version = -EINVAL;
78 78
79 if (!strncmp("9p2000", name->from, name->to-name->from)) { 79 if (!strncmp("9p2000", name->from, name->to-name->from)) {
80 version = p9_proto_legacy; 80 version = p9_proto_legacy;
81 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n"); 81 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
82 } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) { 82 } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
83 version = p9_proto_2000u; 83 version = p9_proto_2000u;
84 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); 84 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
85 } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) { 85 } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) {
86 version = p9_proto_2000L; 86 version = p9_proto_2000L;
87 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); 87 P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
88 } else { 88 } else {
89 P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ", 89 P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
90 name->from); 90 name->from);
91 } 91 }
92 return version; 92 return version;
93 } 93 }
94 94
95 static struct p9_req_t * 95 static struct p9_req_t *
96 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); 96 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
97 97
98 /** 98 /**
99 * parse_options - parse mount options into client structure 99 * parse_options - parse mount options into client structure
100 * @opts: options string passed from mount 100 * @opts: options string passed from mount
101 * @clnt: existing v9fs client information 101 * @clnt: existing v9fs client information
102 * 102 *
103 * Return 0 upon success, -ERRNO upon failure 103 * Return 0 upon success, -ERRNO upon failure
104 */ 104 */
105 105
106 static int parse_opts(char *opts, struct p9_client *clnt) 106 static int parse_opts(char *opts, struct p9_client *clnt)
107 { 107 {
108 char *options, *tmp_options; 108 char *options, *tmp_options;
109 char *p; 109 char *p;
110 substring_t args[MAX_OPT_ARGS]; 110 substring_t args[MAX_OPT_ARGS];
111 int option; 111 int option;
112 int ret = 0; 112 int ret = 0;
113 113
114 clnt->proto_version = p9_proto_2000u; 114 clnt->proto_version = p9_proto_2000u;
115 clnt->msize = 8192; 115 clnt->msize = 8192;
116 116
117 if (!opts) 117 if (!opts)
118 return 0; 118 return 0;
119 119
120 tmp_options = kstrdup(opts, GFP_KERNEL); 120 tmp_options = kstrdup(opts, GFP_KERNEL);
121 if (!tmp_options) { 121 if (!tmp_options) {
122 P9_DPRINTK(P9_DEBUG_ERROR, 122 P9_DPRINTK(P9_DEBUG_ERROR,
123 "failed to allocate copy of option string\n"); 123 "failed to allocate copy of option string\n");
124 return -ENOMEM; 124 return -ENOMEM;
125 } 125 }
126 options = tmp_options; 126 options = tmp_options;
127 127
128 while ((p = strsep(&options, ",")) != NULL) { 128 while ((p = strsep(&options, ",")) != NULL) {
129 int token; 129 int token;
130 if (!*p) 130 if (!*p)
131 continue; 131 continue;
132 token = match_token(p, tokens, args); 132 token = match_token(p, tokens, args);
133 if (token < Opt_trans) { 133 if (token < Opt_trans) {
134 int r = match_int(&args[0], &option); 134 int r = match_int(&args[0], &option);
135 if (r < 0) { 135 if (r < 0) {
136 P9_DPRINTK(P9_DEBUG_ERROR, 136 P9_DPRINTK(P9_DEBUG_ERROR,
137 "integer field, but no integer?\n"); 137 "integer field, but no integer?\n");
138 ret = r; 138 ret = r;
139 continue; 139 continue;
140 } 140 }
141 } 141 }
142 switch (token) { 142 switch (token) {
143 case Opt_msize: 143 case Opt_msize:
144 clnt->msize = option; 144 clnt->msize = option;
145 break; 145 break;
146 case Opt_trans: 146 case Opt_trans:
147 clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); 147 clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
148 if(clnt->trans_mod == NULL) { 148 if(clnt->trans_mod == NULL) {
149 P9_DPRINTK(P9_DEBUG_ERROR, 149 P9_DPRINTK(P9_DEBUG_ERROR,
150 "Could not find request transport: %s\n", 150 "Could not find request transport: %s\n",
151 (char *) &args[0]); 151 (char *) &args[0]);
152 ret = -EINVAL; 152 ret = -EINVAL;
153 goto free_and_return; 153 goto free_and_return;
154 } 154 }
155 break; 155 break;
156 case Opt_legacy: 156 case Opt_legacy:
157 clnt->proto_version = p9_proto_legacy; 157 clnt->proto_version = p9_proto_legacy;
158 break; 158 break;
159 case Opt_version: 159 case Opt_version:
160 ret = get_protocol_version(&args[0]); 160 ret = get_protocol_version(&args[0]);
161 if (ret == -EINVAL) 161 if (ret == -EINVAL)
162 goto free_and_return; 162 goto free_and_return;
163 clnt->proto_version = ret; 163 clnt->proto_version = ret;
164 break; 164 break;
165 default: 165 default:
166 continue; 166 continue;
167 } 167 }
168 } 168 }
169 169
170 free_and_return: 170 free_and_return:
171 kfree(tmp_options); 171 kfree(tmp_options);
172 return ret; 172 return ret;
173 } 173 }
174 174
175 /** 175 /**
176 * p9_tag_alloc - lookup/allocate a request by tag 176 * p9_tag_alloc - lookup/allocate a request by tag
177 * @c: client session to lookup tag within 177 * @c: client session to lookup tag within
178 * @tag: numeric id for transaction 178 * @tag: numeric id for transaction
179 * 179 *
180 * this is a simple array lookup, but will grow the 180 * this is a simple array lookup, but will grow the
181 * request_slots as necessary to accomodate transaction 181 * request_slots as necessary to accomodate transaction
182 * ids which did not previously have a slot. 182 * ids which did not previously have a slot.
183 * 183 *
184 * this code relies on the client spinlock to manage locks, its 184 * this code relies on the client spinlock to manage locks, its
185 * possible we should switch to something else, but I'd rather 185 * possible we should switch to something else, but I'd rather
186 * stick with something low-overhead for the common case. 186 * stick with something low-overhead for the common case.
187 * 187 *
188 */ 188 */
189 189
190 static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) 190 static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
191 { 191 {
192 unsigned long flags; 192 unsigned long flags;
193 int row, col; 193 int row, col;
194 struct p9_req_t *req; 194 struct p9_req_t *req;
195 195
196 /* This looks up the original request by tag so we know which 196 /* This looks up the original request by tag so we know which
197 * buffer to read the data into */ 197 * buffer to read the data into */
198 tag++; 198 tag++;
199 199
200 if (tag >= c->max_tag) { 200 if (tag >= c->max_tag) {
201 spin_lock_irqsave(&c->lock, flags); 201 spin_lock_irqsave(&c->lock, flags);
202 /* check again since original check was outside of lock */ 202 /* check again since original check was outside of lock */
203 while (tag >= c->max_tag) { 203 while (tag >= c->max_tag) {
204 row = (tag / P9_ROW_MAXTAG); 204 row = (tag / P9_ROW_MAXTAG);
205 c->reqs[row] = kcalloc(P9_ROW_MAXTAG, 205 c->reqs[row] = kcalloc(P9_ROW_MAXTAG,
206 sizeof(struct p9_req_t), GFP_ATOMIC); 206 sizeof(struct p9_req_t), GFP_ATOMIC);
207 207
208 if (!c->reqs[row]) { 208 if (!c->reqs[row]) {
209 printk(KERN_ERR "Couldn't grow tag array\n"); 209 printk(KERN_ERR "Couldn't grow tag array\n");
210 spin_unlock_irqrestore(&c->lock, flags); 210 spin_unlock_irqrestore(&c->lock, flags);
211 return ERR_PTR(-ENOMEM); 211 return ERR_PTR(-ENOMEM);
212 } 212 }
213 for (col = 0; col < P9_ROW_MAXTAG; col++) { 213 for (col = 0; col < P9_ROW_MAXTAG; col++) {
214 c->reqs[row][col].status = REQ_STATUS_IDLE; 214 c->reqs[row][col].status = REQ_STATUS_IDLE;
215 c->reqs[row][col].tc = NULL; 215 c->reqs[row][col].tc = NULL;
216 } 216 }
217 c->max_tag += P9_ROW_MAXTAG; 217 c->max_tag += P9_ROW_MAXTAG;
218 } 218 }
219 spin_unlock_irqrestore(&c->lock, flags); 219 spin_unlock_irqrestore(&c->lock, flags);
220 } 220 }
221 row = tag / P9_ROW_MAXTAG; 221 row = tag / P9_ROW_MAXTAG;
222 col = tag % P9_ROW_MAXTAG; 222 col = tag % P9_ROW_MAXTAG;
223 223
224 req = &c->reqs[row][col]; 224 req = &c->reqs[row][col];
225 if (!req->tc) { 225 if (!req->tc) {
226 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); 226 req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
227 if (!req->wq) { 227 if (!req->wq) {
228 printk(KERN_ERR "Couldn't grow tag array\n"); 228 printk(KERN_ERR "Couldn't grow tag array\n");
229 return ERR_PTR(-ENOMEM); 229 return ERR_PTR(-ENOMEM);
230 } 230 }
231 init_waitqueue_head(req->wq); 231 init_waitqueue_head(req->wq);
232 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, 232 req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
233 GFP_KERNEL); 233 GFP_KERNEL);
234 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, 234 req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
235 GFP_KERNEL); 235 GFP_KERNEL);
236 if ((!req->tc) || (!req->rc)) { 236 if ((!req->tc) || (!req->rc)) {
237 printk(KERN_ERR "Couldn't grow tag array\n"); 237 printk(KERN_ERR "Couldn't grow tag array\n");
238 kfree(req->tc); 238 kfree(req->tc);
239 kfree(req->rc); 239 kfree(req->rc);
240 kfree(req->wq); 240 kfree(req->wq);
241 req->tc = req->rc = NULL; 241 req->tc = req->rc = NULL;
242 req->wq = NULL; 242 req->wq = NULL;
243 return ERR_PTR(-ENOMEM); 243 return ERR_PTR(-ENOMEM);
244 } 244 }
245 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); 245 req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
246 req->tc->capacity = c->msize; 246 req->tc->capacity = c->msize;
247 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); 247 req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
248 req->rc->capacity = c->msize; 248 req->rc->capacity = c->msize;
249 } 249 }
250 250
251 p9pdu_reset(req->tc); 251 p9pdu_reset(req->tc);
252 p9pdu_reset(req->rc); 252 p9pdu_reset(req->rc);
253 253
254 req->tc->tag = tag-1; 254 req->tc->tag = tag-1;
255 req->status = REQ_STATUS_ALLOC; 255 req->status = REQ_STATUS_ALLOC;
256 256
257 return &c->reqs[row][col]; 257 return &c->reqs[row][col];
258 } 258 }
259 259
260 /** 260 /**
261 * p9_tag_lookup - lookup a request by tag 261 * p9_tag_lookup - lookup a request by tag
262 * @c: client session to lookup tag within 262 * @c: client session to lookup tag within
263 * @tag: numeric id for transaction 263 * @tag: numeric id for transaction
264 * 264 *
265 */ 265 */
266 266
267 struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag) 267 struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
268 { 268 {
269 int row, col; 269 int row, col;
270 270
271 /* This looks up the original request by tag so we know which 271 /* This looks up the original request by tag so we know which
272 * buffer to read the data into */ 272 * buffer to read the data into */
273 tag++; 273 tag++;
274 274
275 BUG_ON(tag >= c->max_tag); 275 BUG_ON(tag >= c->max_tag);
276 276
277 row = tag / P9_ROW_MAXTAG; 277 row = tag / P9_ROW_MAXTAG;
278 col = tag % P9_ROW_MAXTAG; 278 col = tag % P9_ROW_MAXTAG;
279 279
280 return &c->reqs[row][col]; 280 return &c->reqs[row][col];
281 } 281 }
282 EXPORT_SYMBOL(p9_tag_lookup); 282 EXPORT_SYMBOL(p9_tag_lookup);
283 283
284 /** 284 /**
285 * p9_tag_init - setup tags structure and contents 285 * p9_tag_init - setup tags structure and contents
286 * @c: v9fs client struct 286 * @c: v9fs client struct
287 * 287 *
288 * This initializes the tags structure for each client instance. 288 * This initializes the tags structure for each client instance.
289 * 289 *
290 */ 290 */
291 291
292 static int p9_tag_init(struct p9_client *c) 292 static int p9_tag_init(struct p9_client *c)
293 { 293 {
294 int err = 0; 294 int err = 0;
295 295
296 c->tagpool = p9_idpool_create(); 296 c->tagpool = p9_idpool_create();
297 if (IS_ERR(c->tagpool)) { 297 if (IS_ERR(c->tagpool)) {
298 err = PTR_ERR(c->tagpool); 298 err = PTR_ERR(c->tagpool);
299 c->tagpool = NULL; 299 c->tagpool = NULL;
300 goto error; 300 goto error;
301 } 301 }
302 302
303 p9_idpool_get(c->tagpool); /* reserve tag 0 */ 303 p9_idpool_get(c->tagpool); /* reserve tag 0 */
304 304
305 c->max_tag = 0; 305 c->max_tag = 0;
306 error: 306 error:
307 return err; 307 return err;
308 } 308 }
309 309
310 /** 310 /**
311 * p9_tag_cleanup - cleans up tags structure and reclaims resources 311 * p9_tag_cleanup - cleans up tags structure and reclaims resources
312 * @c: v9fs client struct 312 * @c: v9fs client struct
313 * 313 *
314 * This frees resources associated with the tags structure 314 * This frees resources associated with the tags structure
315 * 315 *
316 */ 316 */
317 static void p9_tag_cleanup(struct p9_client *c) 317 static void p9_tag_cleanup(struct p9_client *c)
318 { 318 {
319 int row, col; 319 int row, col;
320 320
321 /* check to insure all requests are idle */ 321 /* check to insure all requests are idle */
322 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { 322 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
323 for (col = 0; col < P9_ROW_MAXTAG; col++) { 323 for (col = 0; col < P9_ROW_MAXTAG; col++) {
324 if (c->reqs[row][col].status != REQ_STATUS_IDLE) { 324 if (c->reqs[row][col].status != REQ_STATUS_IDLE) {
325 P9_DPRINTK(P9_DEBUG_MUX, 325 P9_DPRINTK(P9_DEBUG_MUX,
326 "Attempting to cleanup non-free tag %d,%d\n", 326 "Attempting to cleanup non-free tag %d,%d\n",
327 row, col); 327 row, col);
328 /* TODO: delay execution of cleanup */ 328 /* TODO: delay execution of cleanup */
329 return; 329 return;
330 } 330 }
331 } 331 }
332 } 332 }
333 333
334 if (c->tagpool) 334 if (c->tagpool) {
335 p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */
335 p9_idpool_destroy(c->tagpool); 336 p9_idpool_destroy(c->tagpool);
337 }
336 338
337 /* free requests associated with tags */ 339 /* free requests associated with tags */
338 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { 340 for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
339 for (col = 0; col < P9_ROW_MAXTAG; col++) { 341 for (col = 0; col < P9_ROW_MAXTAG; col++) {
340 kfree(c->reqs[row][col].wq); 342 kfree(c->reqs[row][col].wq);
341 kfree(c->reqs[row][col].tc); 343 kfree(c->reqs[row][col].tc);
342 kfree(c->reqs[row][col].rc); 344 kfree(c->reqs[row][col].rc);
343 } 345 }
344 kfree(c->reqs[row]); 346 kfree(c->reqs[row]);
345 } 347 }
346 c->max_tag = 0; 348 c->max_tag = 0;
347 } 349 }
348 350
349 /** 351 /**
350 * p9_free_req - free a request and clean-up as necessary 352 * p9_free_req - free a request and clean-up as necessary
351 * c: client state 353 * c: client state
352 * r: request to release 354 * r: request to release
353 * 355 *
354 */ 356 */
355 357
356 static void p9_free_req(struct p9_client *c, struct p9_req_t *r) 358 static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
357 { 359 {
358 int tag = r->tc->tag; 360 int tag = r->tc->tag;
359 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag); 361 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag);
360 362
361 r->status = REQ_STATUS_IDLE; 363 r->status = REQ_STATUS_IDLE;
362 if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool)) 364 if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
363 p9_idpool_put(tag, c->tagpool); 365 p9_idpool_put(tag, c->tagpool);
364 } 366 }
365 367
366 /** 368 /**
367 * p9_client_cb - call back from transport to client 369 * p9_client_cb - call back from transport to client
368 * c: client state 370 * c: client state
369 * req: request received 371 * req: request received
370 * 372 *
371 */ 373 */
372 void p9_client_cb(struct p9_client *c, struct p9_req_t *req) 374 void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
373 { 375 {
374 P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); 376 P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
375 wake_up(req->wq); 377 wake_up(req->wq);
376 P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); 378 P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
377 } 379 }
378 EXPORT_SYMBOL(p9_client_cb); 380 EXPORT_SYMBOL(p9_client_cb);
379 381
380 /** 382 /**
381 * p9_parse_header - parse header arguments out of a packet 383 * p9_parse_header - parse header arguments out of a packet
382 * @pdu: packet to parse 384 * @pdu: packet to parse
383 * @size: size of packet 385 * @size: size of packet
384 * @type: type of request 386 * @type: type of request
385 * @tag: tag of packet 387 * @tag: tag of packet
386 * @rewind: set if we need to rewind offset afterwards 388 * @rewind: set if we need to rewind offset afterwards
387 */ 389 */
388 390
389 int 391 int
390 p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag, 392 p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
391 int rewind) 393 int rewind)
392 { 394 {
393 int8_t r_type; 395 int8_t r_type;
394 int16_t r_tag; 396 int16_t r_tag;
395 int32_t r_size; 397 int32_t r_size;
396 int offset = pdu->offset; 398 int offset = pdu->offset;
397 int err; 399 int err;
398 400
399 pdu->offset = 0; 401 pdu->offset = 0;
400 if (pdu->size == 0) 402 if (pdu->size == 0)
401 pdu->size = 7; 403 pdu->size = 7;
402 404
403 err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag); 405 err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
404 if (err) 406 if (err)
405 goto rewind_and_exit; 407 goto rewind_and_exit;
406 408
407 pdu->size = r_size; 409 pdu->size = r_size;
408 pdu->id = r_type; 410 pdu->id = r_type;
409 pdu->tag = r_tag; 411 pdu->tag = r_tag;
410 412
411 P9_DPRINTK(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", pdu->size, 413 P9_DPRINTK(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", pdu->size,
412 pdu->id, pdu->tag); 414 pdu->id, pdu->tag);
413 415
414 if (type) 416 if (type)
415 *type = r_type; 417 *type = r_type;
416 if (tag) 418 if (tag)
417 *tag = r_tag; 419 *tag = r_tag;
418 if (size) 420 if (size)
419 *size = r_size; 421 *size = r_size;
420 422
421 423
422 rewind_and_exit: 424 rewind_and_exit:
423 if (rewind) 425 if (rewind)
424 pdu->offset = offset; 426 pdu->offset = offset;
425 return err; 427 return err;
426 } 428 }
427 EXPORT_SYMBOL(p9_parse_header); 429 EXPORT_SYMBOL(p9_parse_header);
428 430
429 /** 431 /**
430 * p9_check_errors - check 9p packet for error return and process it 432 * p9_check_errors - check 9p packet for error return and process it
431 * @c: current client instance 433 * @c: current client instance
432 * @req: request to parse and check for error conditions 434 * @req: request to parse and check for error conditions
433 * 435 *
434 * returns error code if one is discovered, otherwise returns 0 436 * returns error code if one is discovered, otherwise returns 0
435 * 437 *
436 * this will have to be more complicated if we have multiple 438 * this will have to be more complicated if we have multiple
437 * error packet types 439 * error packet types
438 */ 440 */
439 441
440 static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) 442 static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
441 { 443 {
442 int8_t type; 444 int8_t type;
443 int err; 445 int err;
444 446
445 err = p9_parse_header(req->rc, NULL, &type, NULL, 0); 447 err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
446 if (err) { 448 if (err) {
447 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); 449 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
448 return err; 450 return err;
449 } 451 }
450 452
451 if (type == P9_RERROR) { 453 if (type == P9_RERROR) {
452 int ecode; 454 int ecode;
453 char *ename; 455 char *ename;
454 456
455 err = p9pdu_readf(req->rc, c->proto_version, "s?d", 457 err = p9pdu_readf(req->rc, c->proto_version, "s?d",
456 &ename, &ecode); 458 &ename, &ecode);
457 if (err) { 459 if (err) {
458 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", 460 P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
459 err); 461 err);
460 return err; 462 return err;
461 } 463 }
462 464
463 if (p9_is_proto_dotu(c) || 465 if (p9_is_proto_dotu(c) ||
464 p9_is_proto_dotl(c)) 466 p9_is_proto_dotl(c))
465 err = -ecode; 467 err = -ecode;
466 468
467 if (!err || !IS_ERR_VALUE(err)) 469 if (!err || !IS_ERR_VALUE(err))
468 err = p9_errstr2errno(ename, strlen(ename)); 470 err = p9_errstr2errno(ename, strlen(ename));
469 471
470 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); 472 P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
471 473
472 kfree(ename); 474 kfree(ename);
473 } else 475 } else
474 err = 0; 476 err = 0;
475 477
476 return err; 478 return err;
477 } 479 }
478 480
479 /** 481 /**
480 * p9_client_flush - flush (cancel) a request 482 * p9_client_flush - flush (cancel) a request
481 * @c: client state 483 * @c: client state
482 * @oldreq: request to cancel 484 * @oldreq: request to cancel
483 * 485 *
484 * This sents a flush for a particular requests and links 486 * This sents a flush for a particular requests and links
485 * the flush request to the original request. The current 487 * the flush request to the original request. The current
486 * code only supports a single flush request although the protocol 488 * code only supports a single flush request although the protocol
487 * allows for multiple flush requests to be sent for a single request. 489 * allows for multiple flush requests to be sent for a single request.
488 * 490 *
489 */ 491 */
490 492
491 static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) 493 static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq)
492 { 494 {
493 struct p9_req_t *req; 495 struct p9_req_t *req;
494 int16_t oldtag; 496 int16_t oldtag;
495 int err; 497 int err;
496 498
497 err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1); 499 err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1);
498 if (err) 500 if (err)
499 return err; 501 return err;
500 502
501 P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag); 503 P9_DPRINTK(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag);
502 504
503 req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag); 505 req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag);
504 if (IS_ERR(req)) 506 if (IS_ERR(req))
505 return PTR_ERR(req); 507 return PTR_ERR(req);
506 508
507 509
508 /* if we haven't received a response for oldreq, 510 /* if we haven't received a response for oldreq,
509 remove it from the list. */ 511 remove it from the list. */
510 spin_lock(&c->lock); 512 spin_lock(&c->lock);
511 if (oldreq->status == REQ_STATUS_FLSH) 513 if (oldreq->status == REQ_STATUS_FLSH)
512 list_del(&oldreq->req_list); 514 list_del(&oldreq->req_list);
513 spin_unlock(&c->lock); 515 spin_unlock(&c->lock);
514 516
515 p9_free_req(c, req); 517 p9_free_req(c, req);
516 return 0; 518 return 0;
517 } 519 }
518 520
519 /** 521 /**
520 * p9_client_rpc - issue a request and wait for a response 522 * p9_client_rpc - issue a request and wait for a response
521 * @c: client session 523 * @c: client session
522 * @type: type of request 524 * @type: type of request
523 * @fmt: protocol format string (see protocol.c) 525 * @fmt: protocol format string (see protocol.c)
524 * 526 *
525 * Returns request structure (which client must free using p9_free_req) 527 * Returns request structure (which client must free using p9_free_req)
526 */ 528 */
527 529
528 static struct p9_req_t * 530 static struct p9_req_t *
529 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) 531 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
530 { 532 {
531 va_list ap; 533 va_list ap;
532 int tag, err; 534 int tag, err;
533 struct p9_req_t *req; 535 struct p9_req_t *req;
534 unsigned long flags; 536 unsigned long flags;
535 int sigpending; 537 int sigpending;
536 538
537 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); 539 P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
538 540
539 /* we allow for any status other than disconnected */ 541 /* we allow for any status other than disconnected */
540 if (c->status == Disconnected) 542 if (c->status == Disconnected)
541 return ERR_PTR(-EIO); 543 return ERR_PTR(-EIO);
542 544
543 /* if status is begin_disconnected we allow only clunk request */ 545 /* if status is begin_disconnected we allow only clunk request */
544 if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) 546 if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
545 return ERR_PTR(-EIO); 547 return ERR_PTR(-EIO);
546 548
547 if (signal_pending(current)) { 549 if (signal_pending(current)) {
548 sigpending = 1; 550 sigpending = 1;
549 clear_thread_flag(TIF_SIGPENDING); 551 clear_thread_flag(TIF_SIGPENDING);
550 } else 552 } else
551 sigpending = 0; 553 sigpending = 0;
552 554
553 tag = P9_NOTAG; 555 tag = P9_NOTAG;
554 if (type != P9_TVERSION) { 556 if (type != P9_TVERSION) {
555 tag = p9_idpool_get(c->tagpool); 557 tag = p9_idpool_get(c->tagpool);
556 if (tag < 0) 558 if (tag < 0)
557 return ERR_PTR(-ENOMEM); 559 return ERR_PTR(-ENOMEM);
558 } 560 }
559 561
560 req = p9_tag_alloc(c, tag); 562 req = p9_tag_alloc(c, tag);
561 if (IS_ERR(req)) 563 if (IS_ERR(req))
562 return req; 564 return req;
563 565
564 /* marshall the data */ 566 /* marshall the data */
565 p9pdu_prepare(req->tc, tag, type); 567 p9pdu_prepare(req->tc, tag, type);
566 va_start(ap, fmt); 568 va_start(ap, fmt);
567 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); 569 err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap);
568 va_end(ap); 570 va_end(ap);
569 p9pdu_finalize(req->tc); 571 p9pdu_finalize(req->tc);
570 572
571 err = c->trans_mod->request(c, req); 573 err = c->trans_mod->request(c, req);
572 if (err < 0) { 574 if (err < 0) {
573 c->status = Disconnected; 575 c->status = Disconnected;
574 goto reterr; 576 goto reterr;
575 } 577 }
576 578
577 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); 579 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
578 err = wait_event_interruptible(*req->wq, 580 err = wait_event_interruptible(*req->wq,
579 req->status >= REQ_STATUS_RCVD); 581 req->status >= REQ_STATUS_RCVD);
580 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", 582 P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
581 req->wq, tag, err); 583 req->wq, tag, err);
582 584
583 if (req->status == REQ_STATUS_ERROR) { 585 if (req->status == REQ_STATUS_ERROR) {
584 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); 586 P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
585 err = req->t_err; 587 err = req->t_err;
586 } 588 }
587 589
588 if ((err == -ERESTARTSYS) && (c->status == Connected)) { 590 if ((err == -ERESTARTSYS) && (c->status == Connected)) {
589 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); 591 P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
590 sigpending = 1; 592 sigpending = 1;
591 clear_thread_flag(TIF_SIGPENDING); 593 clear_thread_flag(TIF_SIGPENDING);
592 594
593 if (c->trans_mod->cancel(c, req)) 595 if (c->trans_mod->cancel(c, req))
594 p9_client_flush(c, req); 596 p9_client_flush(c, req);
595 597
596 /* if we received the response anyway, don't signal error */ 598 /* if we received the response anyway, don't signal error */
597 if (req->status == REQ_STATUS_RCVD) 599 if (req->status == REQ_STATUS_RCVD)
598 err = 0; 600 err = 0;
599 } 601 }
600 602
601 if (sigpending) { 603 if (sigpending) {
602 spin_lock_irqsave(&current->sighand->siglock, flags); 604 spin_lock_irqsave(&current->sighand->siglock, flags);
603 recalc_sigpending(); 605 recalc_sigpending();
604 spin_unlock_irqrestore(&current->sighand->siglock, flags); 606 spin_unlock_irqrestore(&current->sighand->siglock, flags);
605 } 607 }
606 608
607 if (err < 0) 609 if (err < 0)
608 goto reterr; 610 goto reterr;
609 611
610 err = p9_check_errors(c, req); 612 err = p9_check_errors(c, req);
611 if (!err) { 613 if (!err) {
612 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type); 614 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d\n", c, type);
613 return req; 615 return req;
614 } 616 }
615 617
616 reterr: 618 reterr:
617 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type, 619 P9_DPRINTK(P9_DEBUG_MUX, "exit: client %p op %d error: %d\n", c, type,
618 err); 620 err);
619 p9_free_req(c, req); 621 p9_free_req(c, req);
620 return ERR_PTR(err); 622 return ERR_PTR(err);
621 } 623 }
622 624
623 static struct p9_fid *p9_fid_create(struct p9_client *clnt) 625 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
624 { 626 {
625 int ret; 627 int ret;
626 struct p9_fid *fid; 628 struct p9_fid *fid;
627 unsigned long flags; 629 unsigned long flags;
628 630
629 P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt); 631 P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
630 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); 632 fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
631 if (!fid) 633 if (!fid)
632 return ERR_PTR(-ENOMEM); 634 return ERR_PTR(-ENOMEM);
633 635
634 ret = p9_idpool_get(clnt->fidpool); 636 ret = p9_idpool_get(clnt->fidpool);
635 if (ret < 0) { 637 if (ret < 0) {
636 ret = -ENOSPC; 638 ret = -ENOSPC;
637 goto error; 639 goto error;
638 } 640 }
639 fid->fid = ret; 641 fid->fid = ret;
640 642
641 memset(&fid->qid, 0, sizeof(struct p9_qid)); 643 memset(&fid->qid, 0, sizeof(struct p9_qid));
642 fid->mode = -1; 644 fid->mode = -1;
643 fid->uid = current_fsuid(); 645 fid->uid = current_fsuid();
644 fid->clnt = clnt; 646 fid->clnt = clnt;
645 fid->rdir = NULL; 647 fid->rdir = NULL;
646 spin_lock_irqsave(&clnt->lock, flags); 648 spin_lock_irqsave(&clnt->lock, flags);
647 list_add(&fid->flist, &clnt->fidlist); 649 list_add(&fid->flist, &clnt->fidlist);
648 spin_unlock_irqrestore(&clnt->lock, flags); 650 spin_unlock_irqrestore(&clnt->lock, flags);
649 651
650 return fid; 652 return fid;
651 653
652 error: 654 error:
653 kfree(fid); 655 kfree(fid);
654 return ERR_PTR(ret); 656 return ERR_PTR(ret);
655 } 657 }
656 658
657 static void p9_fid_destroy(struct p9_fid *fid) 659 static void p9_fid_destroy(struct p9_fid *fid)
658 { 660 {
659 struct p9_client *clnt; 661 struct p9_client *clnt;
660 unsigned long flags; 662 unsigned long flags;
661 663
662 P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid); 664 P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
663 clnt = fid->clnt; 665 clnt = fid->clnt;
664 p9_idpool_put(fid->fid, clnt->fidpool); 666 p9_idpool_put(fid->fid, clnt->fidpool);
665 spin_lock_irqsave(&clnt->lock, flags); 667 spin_lock_irqsave(&clnt->lock, flags);
666 list_del(&fid->flist); 668 list_del(&fid->flist);
667 spin_unlock_irqrestore(&clnt->lock, flags); 669 spin_unlock_irqrestore(&clnt->lock, flags);
668 kfree(fid->rdir); 670 kfree(fid->rdir);
669 kfree(fid); 671 kfree(fid);
670 } 672 }
671 673
672 int p9_client_version(struct p9_client *c) 674 int p9_client_version(struct p9_client *c)
673 { 675 {
674 int err = 0; 676 int err = 0;
675 struct p9_req_t *req; 677 struct p9_req_t *req;
676 char *version; 678 char *version;
677 int msize; 679 int msize;
678 680
679 P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", 681 P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
680 c->msize, c->proto_version); 682 c->msize, c->proto_version);
681 683
682 switch (c->proto_version) { 684 switch (c->proto_version) {
683 case p9_proto_2000L: 685 case p9_proto_2000L:
684 req = p9_client_rpc(c, P9_TVERSION, "ds", 686 req = p9_client_rpc(c, P9_TVERSION, "ds",
685 c->msize, "9P2000.L"); 687 c->msize, "9P2000.L");
686 break; 688 break;
687 case p9_proto_2000u: 689 case p9_proto_2000u:
688 req = p9_client_rpc(c, P9_TVERSION, "ds", 690 req = p9_client_rpc(c, P9_TVERSION, "ds",
689 c->msize, "9P2000.u"); 691 c->msize, "9P2000.u");
690 break; 692 break;
691 case p9_proto_legacy: 693 case p9_proto_legacy:
692 req = p9_client_rpc(c, P9_TVERSION, "ds", 694 req = p9_client_rpc(c, P9_TVERSION, "ds",
693 c->msize, "9P2000"); 695 c->msize, "9P2000");
694 break; 696 break;
695 default: 697 default:
696 return -EINVAL; 698 return -EINVAL;
697 break; 699 break;
698 } 700 }
699 701
700 if (IS_ERR(req)) 702 if (IS_ERR(req))
701 return PTR_ERR(req); 703 return PTR_ERR(req);
702 704
703 err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); 705 err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version);
704 if (err) { 706 if (err) {
705 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); 707 P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
706 p9pdu_dump(1, req->rc); 708 p9pdu_dump(1, req->rc);
707 goto error; 709 goto error;
708 } 710 }
709 711
710 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); 712 P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
711 if (!strncmp(version, "9P2000.L", 8)) 713 if (!strncmp(version, "9P2000.L", 8))
712 c->proto_version = p9_proto_2000L; 714 c->proto_version = p9_proto_2000L;
713 else if (!strncmp(version, "9P2000.u", 8)) 715 else if (!strncmp(version, "9P2000.u", 8))
714 c->proto_version = p9_proto_2000u; 716 c->proto_version = p9_proto_2000u;
715 else if (!strncmp(version, "9P2000", 6)) 717 else if (!strncmp(version, "9P2000", 6))
716 c->proto_version = p9_proto_legacy; 718 c->proto_version = p9_proto_legacy;
717 else { 719 else {
718 err = -EREMOTEIO; 720 err = -EREMOTEIO;
719 goto error; 721 goto error;
720 } 722 }
721 723
722 if (msize < c->msize) 724 if (msize < c->msize)
723 c->msize = msize; 725 c->msize = msize;
724 726
725 error: 727 error:
726 kfree(version); 728 kfree(version);
727 p9_free_req(c, req); 729 p9_free_req(c, req);
728 730
729 return err; 731 return err;
730 } 732 }
731 EXPORT_SYMBOL(p9_client_version); 733 EXPORT_SYMBOL(p9_client_version);
732 734
733 struct p9_client *p9_client_create(const char *dev_name, char *options) 735 struct p9_client *p9_client_create(const char *dev_name, char *options)
734 { 736 {
735 int err; 737 int err;
736 struct p9_client *clnt; 738 struct p9_client *clnt;
737 739
738 err = 0; 740 err = 0;
739 clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); 741 clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
740 if (!clnt) 742 if (!clnt)
741 return ERR_PTR(-ENOMEM); 743 return ERR_PTR(-ENOMEM);
742 744
743 clnt->trans_mod = NULL; 745 clnt->trans_mod = NULL;
744 clnt->trans = NULL; 746 clnt->trans = NULL;
745 spin_lock_init(&clnt->lock); 747 spin_lock_init(&clnt->lock);
746 INIT_LIST_HEAD(&clnt->fidlist); 748 INIT_LIST_HEAD(&clnt->fidlist);
747 749
748 p9_tag_init(clnt); 750 p9_tag_init(clnt);
749 751
750 err = parse_opts(options, clnt); 752 err = parse_opts(options, clnt);
751 if (err < 0) 753 if (err < 0)
752 goto free_client; 754 goto free_client;
753 755
754 if (!clnt->trans_mod) 756 if (!clnt->trans_mod)
755 clnt->trans_mod = v9fs_get_default_trans(); 757 clnt->trans_mod = v9fs_get_default_trans();
756 758
757 if (clnt->trans_mod == NULL) { 759 if (clnt->trans_mod == NULL) {
758 err = -EPROTONOSUPPORT; 760 err = -EPROTONOSUPPORT;
759 P9_DPRINTK(P9_DEBUG_ERROR, 761 P9_DPRINTK(P9_DEBUG_ERROR,
760 "No transport defined or default transport\n"); 762 "No transport defined or default transport\n");
761 goto free_client; 763 goto free_client;
762 } 764 }
763 765
764 clnt->fidpool = p9_idpool_create(); 766 clnt->fidpool = p9_idpool_create();
765 if (IS_ERR(clnt->fidpool)) { 767 if (IS_ERR(clnt->fidpool)) {
766 err = PTR_ERR(clnt->fidpool); 768 err = PTR_ERR(clnt->fidpool);
767 clnt->fidpool = NULL; 769 clnt->fidpool = NULL;
768 goto put_trans; 770 goto put_trans;
769 } 771 }
770 772
771 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", 773 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
772 clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); 774 clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
773 775
774 err = clnt->trans_mod->create(clnt, dev_name, options); 776 err = clnt->trans_mod->create(clnt, dev_name, options);
775 if (err) 777 if (err)
776 goto destroy_fidpool; 778 goto destroy_fidpool;
777 779
778 if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) 780 if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
779 clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; 781 clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
780 782
781 err = p9_client_version(clnt); 783 err = p9_client_version(clnt);
782 if (err) 784 if (err)
783 goto close_trans; 785 goto close_trans;
784 786
785 return clnt; 787 return clnt;
786 788
787 close_trans: 789 close_trans:
788 clnt->trans_mod->close(clnt); 790 clnt->trans_mod->close(clnt);
789 destroy_fidpool: 791 destroy_fidpool:
790 p9_idpool_destroy(clnt->fidpool); 792 p9_idpool_destroy(clnt->fidpool);
791 put_trans: 793 put_trans:
792 v9fs_put_trans(clnt->trans_mod); 794 v9fs_put_trans(clnt->trans_mod);
793 free_client: 795 free_client:
794 kfree(clnt); 796 kfree(clnt);
795 return ERR_PTR(err); 797 return ERR_PTR(err);
796 } 798 }
797 EXPORT_SYMBOL(p9_client_create); 799 EXPORT_SYMBOL(p9_client_create);
798 800
799 void p9_client_destroy(struct p9_client *clnt) 801 void p9_client_destroy(struct p9_client *clnt)
800 { 802 {
801 struct p9_fid *fid, *fidptr; 803 struct p9_fid *fid, *fidptr;
802 804
803 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt); 805 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p\n", clnt);
804 806
805 if (clnt->trans_mod) 807 if (clnt->trans_mod)
806 clnt->trans_mod->close(clnt); 808 clnt->trans_mod->close(clnt);
807 809
808 v9fs_put_trans(clnt->trans_mod); 810 v9fs_put_trans(clnt->trans_mod);
809 811
810 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) { 812 list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
811 printk(KERN_INFO "Found fid %d not clunked\n", fid->fid); 813 printk(KERN_INFO "Found fid %d not clunked\n", fid->fid);
812 p9_fid_destroy(fid); 814 p9_fid_destroy(fid);
813 } 815 }
814 816
815 if (clnt->fidpool) 817 if (clnt->fidpool)
816 p9_idpool_destroy(clnt->fidpool); 818 p9_idpool_destroy(clnt->fidpool);
817 819
818 p9_tag_cleanup(clnt); 820 p9_tag_cleanup(clnt);
819 821
820 kfree(clnt); 822 kfree(clnt);
821 } 823 }
822 EXPORT_SYMBOL(p9_client_destroy); 824 EXPORT_SYMBOL(p9_client_destroy);
823 825
824 void p9_client_disconnect(struct p9_client *clnt) 826 void p9_client_disconnect(struct p9_client *clnt)
825 { 827 {
826 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 828 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
827 clnt->status = Disconnected; 829 clnt->status = Disconnected;
828 } 830 }
829 EXPORT_SYMBOL(p9_client_disconnect); 831 EXPORT_SYMBOL(p9_client_disconnect);
830 832
831 void p9_client_begin_disconnect(struct p9_client *clnt) 833 void p9_client_begin_disconnect(struct p9_client *clnt)
832 { 834 {
833 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); 835 P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
834 clnt->status = BeginDisconnect; 836 clnt->status = BeginDisconnect;
835 } 837 }
836 EXPORT_SYMBOL(p9_client_begin_disconnect); 838 EXPORT_SYMBOL(p9_client_begin_disconnect);
837 839
838 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, 840 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
839 char *uname, u32 n_uname, char *aname) 841 char *uname, u32 n_uname, char *aname)
840 { 842 {
841 int err; 843 int err;
842 struct p9_req_t *req; 844 struct p9_req_t *req;
843 struct p9_fid *fid; 845 struct p9_fid *fid;
844 struct p9_qid qid; 846 struct p9_qid qid;
845 847
846 P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n", 848 P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
847 afid ? afid->fid : -1, uname, aname); 849 afid ? afid->fid : -1, uname, aname);
848 err = 0; 850 err = 0;
849 851
850 fid = p9_fid_create(clnt); 852 fid = p9_fid_create(clnt);
851 if (IS_ERR(fid)) { 853 if (IS_ERR(fid)) {
852 err = PTR_ERR(fid); 854 err = PTR_ERR(fid);
853 fid = NULL; 855 fid = NULL;
854 goto error; 856 goto error;
855 } 857 }
856 858
857 req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid, 859 req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
858 afid ? afid->fid : P9_NOFID, uname, aname, n_uname); 860 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
859 if (IS_ERR(req)) { 861 if (IS_ERR(req)) {
860 err = PTR_ERR(req); 862 err = PTR_ERR(req);
861 goto error; 863 goto error;
862 } 864 }
863 865
864 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); 866 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
865 if (err) { 867 if (err) {
866 p9pdu_dump(1, req->rc); 868 p9pdu_dump(1, req->rc);
867 p9_free_req(clnt, req); 869 p9_free_req(clnt, req);
868 goto error; 870 goto error;
869 } 871 }
870 872
871 P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n", 873 P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
872 qid.type, 874 qid.type,
873 (unsigned long long)qid.path, 875 (unsigned long long)qid.path,
874 qid.version); 876 qid.version);
875 877
876 memmove(&fid->qid, &qid, sizeof(struct p9_qid)); 878 memmove(&fid->qid, &qid, sizeof(struct p9_qid));
877 879
878 p9_free_req(clnt, req); 880 p9_free_req(clnt, req);
879 return fid; 881 return fid;
880 882
881 error: 883 error:
882 if (fid) 884 if (fid)
883 p9_fid_destroy(fid); 885 p9_fid_destroy(fid);
884 return ERR_PTR(err); 886 return ERR_PTR(err);
885 } 887 }
886 EXPORT_SYMBOL(p9_client_attach); 888 EXPORT_SYMBOL(p9_client_attach);
887 889
888 struct p9_fid * 890 struct p9_fid *
889 p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) 891 p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
890 { 892 {
891 int err; 893 int err;
892 struct p9_req_t *req; 894 struct p9_req_t *req;
893 struct p9_qid qid; 895 struct p9_qid qid;
894 struct p9_fid *afid; 896 struct p9_fid *afid;
895 897
896 P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname); 898 P9_DPRINTK(P9_DEBUG_9P, ">>> TAUTH uname %s aname %s\n", uname, aname);
897 err = 0; 899 err = 0;
898 900
899 afid = p9_fid_create(clnt); 901 afid = p9_fid_create(clnt);
900 if (IS_ERR(afid)) { 902 if (IS_ERR(afid)) {
901 err = PTR_ERR(afid); 903 err = PTR_ERR(afid);
902 afid = NULL; 904 afid = NULL;
903 goto error; 905 goto error;
904 } 906 }
905 907
906 req = p9_client_rpc(clnt, P9_TAUTH, "dss?d", 908 req = p9_client_rpc(clnt, P9_TAUTH, "dss?d",
907 afid ? afid->fid : P9_NOFID, uname, aname, n_uname); 909 afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
908 if (IS_ERR(req)) { 910 if (IS_ERR(req)) {
909 err = PTR_ERR(req); 911 err = PTR_ERR(req);
910 goto error; 912 goto error;
911 } 913 }
912 914
913 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); 915 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid);
914 if (err) { 916 if (err) {
915 p9pdu_dump(1, req->rc); 917 p9pdu_dump(1, req->rc);
916 p9_free_req(clnt, req); 918 p9_free_req(clnt, req);
917 goto error; 919 goto error;
918 } 920 }
919 921
920 P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n", 922 P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
921 qid.type, 923 qid.type,
922 (unsigned long long)qid.path, 924 (unsigned long long)qid.path,
923 qid.version); 925 qid.version);
924 926
925 memmove(&afid->qid, &qid, sizeof(struct p9_qid)); 927 memmove(&afid->qid, &qid, sizeof(struct p9_qid));
926 p9_free_req(clnt, req); 928 p9_free_req(clnt, req);
927 return afid; 929 return afid;
928 930
929 error: 931 error:
930 if (afid) 932 if (afid)
931 p9_fid_destroy(afid); 933 p9_fid_destroy(afid);
932 return ERR_PTR(err); 934 return ERR_PTR(err);
933 } 935 }
934 EXPORT_SYMBOL(p9_client_auth); 936 EXPORT_SYMBOL(p9_client_auth);
935 937
936 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, 938 struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
937 int clone) 939 int clone)
938 { 940 {
939 int err; 941 int err;
940 struct p9_client *clnt; 942 struct p9_client *clnt;
941 struct p9_fid *fid; 943 struct p9_fid *fid;
942 struct p9_qid *wqids; 944 struct p9_qid *wqids;
943 struct p9_req_t *req; 945 struct p9_req_t *req;
944 int16_t nwqids, count; 946 int16_t nwqids, count;
945 947
946 err = 0; 948 err = 0;
949 wqids = NULL;
947 clnt = oldfid->clnt; 950 clnt = oldfid->clnt;
948 if (clone) { 951 if (clone) {
949 fid = p9_fid_create(clnt); 952 fid = p9_fid_create(clnt);
950 if (IS_ERR(fid)) { 953 if (IS_ERR(fid)) {
951 err = PTR_ERR(fid); 954 err = PTR_ERR(fid);
952 fid = NULL; 955 fid = NULL;
953 goto error; 956 goto error;
954 } 957 }
955 958
956 fid->uid = oldfid->uid; 959 fid->uid = oldfid->uid;
957 } else 960 } else
958 fid = oldfid; 961 fid = oldfid;
959 962
960 963
961 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n", 964 P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
962 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); 965 oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
963 966
964 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, 967 req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
965 nwname, wnames); 968 nwname, wnames);
966 if (IS_ERR(req)) { 969 if (IS_ERR(req)) {
967 err = PTR_ERR(req); 970 err = PTR_ERR(req);
968 goto error; 971 goto error;
969 } 972 }
970 973
971 err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); 974 err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids);
972 if (err) { 975 if (err) {
973 p9pdu_dump(1, req->rc); 976 p9pdu_dump(1, req->rc);
974 p9_free_req(clnt, req); 977 p9_free_req(clnt, req);
975 goto clunk_fid; 978 goto clunk_fid;
976 } 979 }
977 p9_free_req(clnt, req); 980 p9_free_req(clnt, req);
978 981
979 P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids); 982 P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);
980 983
981 if (nwqids != nwname) { 984 if (nwqids != nwname) {
982 err = -ENOENT; 985 err = -ENOENT;
983 goto clunk_fid; 986 goto clunk_fid;
984 } 987 }
985 988
986 for (count = 0; count < nwqids; count++) 989 for (count = 0; count < nwqids; count++)
987 P9_DPRINTK(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n", 990 P9_DPRINTK(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n",
988 count, wqids[count].type, 991 count, wqids[count].type,
989 (unsigned long long)wqids[count].path, 992 (unsigned long long)wqids[count].path,
990 wqids[count].version); 993 wqids[count].version);
991 994
992 if (nwname) 995 if (nwname)
993 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); 996 memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
994 else 997 else
995 fid->qid = oldfid->qid; 998 fid->qid = oldfid->qid;
996 999
1000 kfree(wqids);
997 return fid; 1001 return fid;
998 1002
999 clunk_fid: 1003 clunk_fid:
1004 kfree(wqids);
1000 p9_client_clunk(fid); 1005 p9_client_clunk(fid);
1001 fid = NULL; 1006 fid = NULL;
1002 1007
1003 error: 1008 error:
1004 if (fid && (fid != oldfid)) 1009 if (fid && (fid != oldfid))
1005 p9_fid_destroy(fid); 1010 p9_fid_destroy(fid);
1006 1011
1007 return ERR_PTR(err); 1012 return ERR_PTR(err);
1008 } 1013 }
1009 EXPORT_SYMBOL(p9_client_walk); 1014 EXPORT_SYMBOL(p9_client_walk);
1010 1015
1011 int p9_client_open(struct p9_fid *fid, int mode) 1016 int p9_client_open(struct p9_fid *fid, int mode)
1012 { 1017 {
1013 int err; 1018 int err;
1014 struct p9_client *clnt; 1019 struct p9_client *clnt;
1015 struct p9_req_t *req; 1020 struct p9_req_t *req;
1016 struct p9_qid qid; 1021 struct p9_qid qid;
1017 int iounit; 1022 int iounit;
1018 1023
1019 clnt = fid->clnt; 1024 clnt = fid->clnt;
1020 P9_DPRINTK(P9_DEBUG_9P, ">>> %s fid %d mode %d\n", 1025 P9_DPRINTK(P9_DEBUG_9P, ">>> %s fid %d mode %d\n",
1021 p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode); 1026 p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode);
1022 err = 0; 1027 err = 0;
1023 1028
1024 if (fid->mode != -1) 1029 if (fid->mode != -1)
1025 return -EINVAL; 1030 return -EINVAL;
1026 1031
1027 if (p9_is_proto_dotl(clnt)) 1032 if (p9_is_proto_dotl(clnt))
1028 req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode); 1033 req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode);
1029 else 1034 else
1030 req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode); 1035 req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
1031 if (IS_ERR(req)) { 1036 if (IS_ERR(req)) {
1032 err = PTR_ERR(req); 1037 err = PTR_ERR(req);
1033 goto error; 1038 goto error;
1034 } 1039 }
1035 1040
1036 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); 1041 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
1037 if (err) { 1042 if (err) {
1038 p9pdu_dump(1, req->rc); 1043 p9pdu_dump(1, req->rc);
1039 goto free_and_error; 1044 goto free_and_error;
1040 } 1045 }
1041 1046
1042 P9_DPRINTK(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n", 1047 P9_DPRINTK(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n",
1043 p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, 1048 p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type,
1044 (unsigned long long)qid.path, qid.version, iounit); 1049 (unsigned long long)qid.path, qid.version, iounit);
1045 1050
1046 fid->mode = mode; 1051 fid->mode = mode;
1047 fid->iounit = iounit; 1052 fid->iounit = iounit;
1048 1053
1049 free_and_error: 1054 free_and_error:
1050 p9_free_req(clnt, req); 1055 p9_free_req(clnt, req);
1051 error: 1056 error:
1052 return err; 1057 return err;
1053 } 1058 }
1054 EXPORT_SYMBOL(p9_client_open); 1059 EXPORT_SYMBOL(p9_client_open);
1055 1060
1056 int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode, 1061 int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
1057 gid_t gid, struct p9_qid *qid) 1062 gid_t gid, struct p9_qid *qid)
1058 { 1063 {
1059 int err = 0; 1064 int err = 0;
1060 struct p9_client *clnt; 1065 struct p9_client *clnt;
1061 struct p9_req_t *req; 1066 struct p9_req_t *req;
1062 int iounit; 1067 int iounit;
1063 1068
1064 P9_DPRINTK(P9_DEBUG_9P, 1069 P9_DPRINTK(P9_DEBUG_9P,
1065 ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n", 1070 ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n",
1066 ofid->fid, name, flags, mode, gid); 1071 ofid->fid, name, flags, mode, gid);
1067 clnt = ofid->clnt; 1072 clnt = ofid->clnt;
1068 1073
1069 if (ofid->mode != -1) 1074 if (ofid->mode != -1)
1070 return -EINVAL; 1075 return -EINVAL;
1071 1076
1072 req = p9_client_rpc(clnt, P9_TLCREATE, "dsddd", ofid->fid, name, flags, 1077 req = p9_client_rpc(clnt, P9_TLCREATE, "dsddd", ofid->fid, name, flags,
1073 mode, gid); 1078 mode, gid);
1074 if (IS_ERR(req)) { 1079 if (IS_ERR(req)) {
1075 err = PTR_ERR(req); 1080 err = PTR_ERR(req);
1076 goto error; 1081 goto error;
1077 } 1082 }
1078 1083
1079 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit); 1084 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit);
1080 if (err) { 1085 if (err) {
1081 p9pdu_dump(1, req->rc); 1086 p9pdu_dump(1, req->rc);
1082 goto free_and_error; 1087 goto free_and_error;
1083 } 1088 }
1084 1089
1085 P9_DPRINTK(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n", 1090 P9_DPRINTK(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n",
1086 qid->type, 1091 qid->type,
1087 (unsigned long long)qid->path, 1092 (unsigned long long)qid->path,
1088 qid->version, iounit); 1093 qid->version, iounit);
1089 1094
1090 ofid->mode = mode; 1095 ofid->mode = mode;
1091 ofid->iounit = iounit; 1096 ofid->iounit = iounit;
1092 1097
1093 free_and_error: 1098 free_and_error:
1094 p9_free_req(clnt, req); 1099 p9_free_req(clnt, req);
1095 error: 1100 error:
1096 return err; 1101 return err;
1097 } 1102 }
1098 EXPORT_SYMBOL(p9_client_create_dotl); 1103 EXPORT_SYMBOL(p9_client_create_dotl);
1099 1104
1100 int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, 1105 int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
1101 char *extension) 1106 char *extension)
1102 { 1107 {
1103 int err; 1108 int err;
1104 struct p9_client *clnt; 1109 struct p9_client *clnt;
1105 struct p9_req_t *req; 1110 struct p9_req_t *req;
1106 struct p9_qid qid; 1111 struct p9_qid qid;
1107 int iounit; 1112 int iounit;
1108 1113
1109 P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n", 1114 P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
1110 fid->fid, name, perm, mode); 1115 fid->fid, name, perm, mode);
1111 err = 0; 1116 err = 0;
1112 clnt = fid->clnt; 1117 clnt = fid->clnt;
1113 1118
1114 if (fid->mode != -1) 1119 if (fid->mode != -1)
1115 return -EINVAL; 1120 return -EINVAL;
1116 1121
1117 req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm, 1122 req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
1118 mode, extension); 1123 mode, extension);
1119 if (IS_ERR(req)) { 1124 if (IS_ERR(req)) {
1120 err = PTR_ERR(req); 1125 err = PTR_ERR(req);
1121 goto error; 1126 goto error;
1122 } 1127 }
1123 1128
1124 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); 1129 err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit);
1125 if (err) { 1130 if (err) {
1126 p9pdu_dump(1, req->rc); 1131 p9pdu_dump(1, req->rc);
1127 goto free_and_error; 1132 goto free_and_error;
1128 } 1133 }
1129 1134
1130 P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n", 1135 P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
1131 qid.type, 1136 qid.type,
1132 (unsigned long long)qid.path, 1137 (unsigned long long)qid.path,
1133 qid.version, iounit); 1138 qid.version, iounit);
1134 1139
1135 fid->mode = mode; 1140 fid->mode = mode;
1136 fid->iounit = iounit; 1141 fid->iounit = iounit;
1137 1142
1138 free_and_error: 1143 free_and_error:
1139 p9_free_req(clnt, req); 1144 p9_free_req(clnt, req);
1140 error: 1145 error:
1141 return err; 1146 return err;
1142 } 1147 }
1143 EXPORT_SYMBOL(p9_client_fcreate); 1148 EXPORT_SYMBOL(p9_client_fcreate);
1144 1149
1145 int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid, 1150 int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, gid_t gid,
1146 struct p9_qid *qid) 1151 struct p9_qid *qid)
1147 { 1152 {
1148 int err = 0; 1153 int err = 0;
1149 struct p9_client *clnt; 1154 struct p9_client *clnt;
1150 struct p9_req_t *req; 1155 struct p9_req_t *req;
1151 1156
1152 P9_DPRINTK(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s symtgt %s\n", 1157 P9_DPRINTK(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s symtgt %s\n",
1153 dfid->fid, name, symtgt); 1158 dfid->fid, name, symtgt);
1154 clnt = dfid->clnt; 1159 clnt = dfid->clnt;
1155 1160
1156 req = p9_client_rpc(clnt, P9_TSYMLINK, "dssd", dfid->fid, name, symtgt, 1161 req = p9_client_rpc(clnt, P9_TSYMLINK, "dssd", dfid->fid, name, symtgt,
1157 gid); 1162 gid);
1158 if (IS_ERR(req)) { 1163 if (IS_ERR(req)) {
1159 err = PTR_ERR(req); 1164 err = PTR_ERR(req);
1160 goto error; 1165 goto error;
1161 } 1166 }
1162 1167
1163 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); 1168 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1164 if (err) { 1169 if (err) {
1165 p9pdu_dump(1, req->rc); 1170 p9pdu_dump(1, req->rc);
1166 goto free_and_error; 1171 goto free_and_error;
1167 } 1172 }
1168 1173
1169 P9_DPRINTK(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n", 1174 P9_DPRINTK(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n",
1170 qid->type, (unsigned long long)qid->path, qid->version); 1175 qid->type, (unsigned long long)qid->path, qid->version);
1171 1176
1172 free_and_error: 1177 free_and_error:
1173 p9_free_req(clnt, req); 1178 p9_free_req(clnt, req);
1174 error: 1179 error:
1175 return err; 1180 return err;
1176 } 1181 }
1177 EXPORT_SYMBOL(p9_client_symlink); 1182 EXPORT_SYMBOL(p9_client_symlink);
1178 1183
1179 int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) 1184 int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname)
1180 { 1185 {
1181 struct p9_client *clnt; 1186 struct p9_client *clnt;
1182 struct p9_req_t *req; 1187 struct p9_req_t *req;
1183 1188
1184 P9_DPRINTK(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n", 1189 P9_DPRINTK(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n",
1185 dfid->fid, oldfid->fid, newname); 1190 dfid->fid, oldfid->fid, newname);
1186 clnt = dfid->clnt; 1191 clnt = dfid->clnt;
1187 req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid, 1192 req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid,
1188 newname); 1193 newname);
1189 if (IS_ERR(req)) 1194 if (IS_ERR(req))
1190 return PTR_ERR(req); 1195 return PTR_ERR(req);
1191 1196
1192 P9_DPRINTK(P9_DEBUG_9P, "<<< RLINK\n"); 1197 P9_DPRINTK(P9_DEBUG_9P, "<<< RLINK\n");
1193 p9_free_req(clnt, req); 1198 p9_free_req(clnt, req);
1194 return 0; 1199 return 0;
1195 } 1200 }
1196 EXPORT_SYMBOL(p9_client_link); 1201 EXPORT_SYMBOL(p9_client_link);
1197 1202
1198 int p9_client_clunk(struct p9_fid *fid) 1203 int p9_client_clunk(struct p9_fid *fid)
1199 { 1204 {
1200 int err; 1205 int err;
1201 struct p9_client *clnt; 1206 struct p9_client *clnt;
1202 struct p9_req_t *req; 1207 struct p9_req_t *req;
1203 1208
1204 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); 1209 P9_DPRINTK(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid);
1205 err = 0; 1210 err = 0;
1206 clnt = fid->clnt; 1211 clnt = fid->clnt;
1207 1212
1208 req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid); 1213 req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
1209 if (IS_ERR(req)) { 1214 if (IS_ERR(req)) {
1210 err = PTR_ERR(req); 1215 err = PTR_ERR(req);
1211 goto error; 1216 goto error;
1212 } 1217 }
1213 1218
1214 P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid); 1219 P9_DPRINTK(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid);
1215 1220
1216 p9_free_req(clnt, req); 1221 p9_free_req(clnt, req);
1217 p9_fid_destroy(fid); 1222 p9_fid_destroy(fid);
1218 1223
1219 error: 1224 error:
1220 return err; 1225 return err;
1221 } 1226 }
1222 EXPORT_SYMBOL(p9_client_clunk); 1227 EXPORT_SYMBOL(p9_client_clunk);
1223 1228
1224 int p9_client_remove(struct p9_fid *fid) 1229 int p9_client_remove(struct p9_fid *fid)
1225 { 1230 {
1226 int err; 1231 int err;
1227 struct p9_client *clnt; 1232 struct p9_client *clnt;
1228 struct p9_req_t *req; 1233 struct p9_req_t *req;
1229 1234
1230 P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid); 1235 P9_DPRINTK(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
1231 err = 0; 1236 err = 0;
1232 clnt = fid->clnt; 1237 clnt = fid->clnt;
1233 1238
1234 req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid); 1239 req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
1235 if (IS_ERR(req)) { 1240 if (IS_ERR(req)) {
1236 err = PTR_ERR(req); 1241 err = PTR_ERR(req);
1237 goto error; 1242 goto error;
1238 } 1243 }
1239 1244
1240 P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid); 1245 P9_DPRINTK(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid);
1241 1246
1242 p9_free_req(clnt, req); 1247 p9_free_req(clnt, req);
1243 error: 1248 error:
1244 p9_fid_destroy(fid); 1249 p9_fid_destroy(fid);
1245 return err; 1250 return err;
1246 } 1251 }
1247 EXPORT_SYMBOL(p9_client_remove); 1252 EXPORT_SYMBOL(p9_client_remove);
1248 1253
1249 int 1254 int
1250 p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1255 p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1251 u32 count) 1256 u32 count)
1252 { 1257 {
1253 int err, rsize, total; 1258 int err, rsize, total;
1254 struct p9_client *clnt; 1259 struct p9_client *clnt;
1255 struct p9_req_t *req; 1260 struct p9_req_t *req;
1256 char *dataptr; 1261 char *dataptr;
1257 1262
1258 P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid, 1263 P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
1259 (long long unsigned) offset, count); 1264 (long long unsigned) offset, count);
1260 err = 0; 1265 err = 0;
1261 clnt = fid->clnt; 1266 clnt = fid->clnt;
1262 total = 0; 1267 total = 0;
1263 1268
1264 rsize = fid->iounit; 1269 rsize = fid->iounit;
1265 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1270 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1266 rsize = clnt->msize - P9_IOHDRSZ; 1271 rsize = clnt->msize - P9_IOHDRSZ;
1267 1272
1268 if (count < rsize) 1273 if (count < rsize)
1269 rsize = count; 1274 rsize = count;
1270 1275
1271 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize); 1276 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
1272 if (IS_ERR(req)) { 1277 if (IS_ERR(req)) {
1273 err = PTR_ERR(req); 1278 err = PTR_ERR(req);
1274 goto error; 1279 goto error;
1275 } 1280 }
1276 1281
1277 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1282 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
1278 if (err) { 1283 if (err) {
1279 p9pdu_dump(1, req->rc); 1284 p9pdu_dump(1, req->rc);
1280 goto free_and_error; 1285 goto free_and_error;
1281 } 1286 }
1282 1287
1283 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1288 P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1284 1289
1285 if (data) { 1290 if (data) {
1286 memmove(data, dataptr, count); 1291 memmove(data, dataptr, count);
1287 } 1292 }
1288 1293
1289 if (udata) { 1294 if (udata) {
1290 err = copy_to_user(udata, dataptr, count); 1295 err = copy_to_user(udata, dataptr, count);
1291 if (err) { 1296 if (err) {
1292 err = -EFAULT; 1297 err = -EFAULT;
1293 goto free_and_error; 1298 goto free_and_error;
1294 } 1299 }
1295 } 1300 }
1296 1301
1297 p9_free_req(clnt, req); 1302 p9_free_req(clnt, req);
1298 return count; 1303 return count;
1299 1304
1300 free_and_error: 1305 free_and_error:
1301 p9_free_req(clnt, req); 1306 p9_free_req(clnt, req);
1302 error: 1307 error:
1303 return err; 1308 return err;
1304 } 1309 }
1305 EXPORT_SYMBOL(p9_client_read); 1310 EXPORT_SYMBOL(p9_client_read);
1306 1311
1307 int 1312 int
1308 p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, 1313 p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1309 u64 offset, u32 count) 1314 u64 offset, u32 count)
1310 { 1315 {
1311 int err, rsize, total; 1316 int err, rsize, total;
1312 struct p9_client *clnt; 1317 struct p9_client *clnt;
1313 struct p9_req_t *req; 1318 struct p9_req_t *req;
1314 1319
1315 P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n", 1320 P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1316 fid->fid, (long long unsigned) offset, count); 1321 fid->fid, (long long unsigned) offset, count);
1317 err = 0; 1322 err = 0;
1318 clnt = fid->clnt; 1323 clnt = fid->clnt;
1319 total = 0; 1324 total = 0;
1320 1325
1321 rsize = fid->iounit; 1326 rsize = fid->iounit;
1322 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1327 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1323 rsize = clnt->msize - P9_IOHDRSZ; 1328 rsize = clnt->msize - P9_IOHDRSZ;
1324 1329
1325 if (count < rsize) 1330 if (count < rsize)
1326 rsize = count; 1331 rsize = count;
1327 if (data) 1332 if (data)
1328 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset, 1333 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
1329 rsize, data); 1334 rsize, data);
1330 else 1335 else
1331 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset, 1336 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
1332 rsize, udata); 1337 rsize, udata);
1333 if (IS_ERR(req)) { 1338 if (IS_ERR(req)) {
1334 err = PTR_ERR(req); 1339 err = PTR_ERR(req);
1335 goto error; 1340 goto error;
1336 } 1341 }
1337 1342
1338 err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); 1343 err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count);
1339 if (err) { 1344 if (err) {
1340 p9pdu_dump(1, req->rc); 1345 p9pdu_dump(1, req->rc);
1341 goto free_and_error; 1346 goto free_and_error;
1342 } 1347 }
1343 1348
1344 P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); 1349 P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
1345 1350
1346 p9_free_req(clnt, req); 1351 p9_free_req(clnt, req);
1347 return count; 1352 return count;
1348 1353
1349 free_and_error: 1354 free_and_error:
1350 p9_free_req(clnt, req); 1355 p9_free_req(clnt, req);
1351 error: 1356 error:
1352 return err; 1357 return err;
1353 } 1358 }
1354 EXPORT_SYMBOL(p9_client_write); 1359 EXPORT_SYMBOL(p9_client_write);
1355 1360
1356 struct p9_wstat *p9_client_stat(struct p9_fid *fid) 1361 struct p9_wstat *p9_client_stat(struct p9_fid *fid)
1357 { 1362 {
1358 int err; 1363 int err;
1359 struct p9_client *clnt; 1364 struct p9_client *clnt;
1360 struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL); 1365 struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
1361 struct p9_req_t *req; 1366 struct p9_req_t *req;
1362 u16 ignored; 1367 u16 ignored;
1363 1368
1364 P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid); 1369 P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);
1365 1370
1366 if (!ret) 1371 if (!ret)
1367 return ERR_PTR(-ENOMEM); 1372 return ERR_PTR(-ENOMEM);
1368 1373
1369 err = 0; 1374 err = 0;
1370 clnt = fid->clnt; 1375 clnt = fid->clnt;
1371 1376
1372 req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid); 1377 req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
1373 if (IS_ERR(req)) { 1378 if (IS_ERR(req)) {
1374 err = PTR_ERR(req); 1379 err = PTR_ERR(req);
1375 goto error; 1380 goto error;
1376 } 1381 }
1377 1382
1378 err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); 1383 err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret);
1379 if (err) { 1384 if (err) {
1380 p9pdu_dump(1, req->rc); 1385 p9pdu_dump(1, req->rc);
1381 p9_free_req(clnt, req); 1386 p9_free_req(clnt, req);
1382 goto error; 1387 goto error;
1383 } 1388 }
1384 1389
1385 P9_DPRINTK(P9_DEBUG_9P, 1390 P9_DPRINTK(P9_DEBUG_9P,
1386 "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n" 1391 "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1387 "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" 1392 "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1388 "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" 1393 "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1389 "<<< uid=%d gid=%d n_muid=%d\n", 1394 "<<< uid=%d gid=%d n_muid=%d\n",
1390 ret->size, ret->type, ret->dev, ret->qid.type, 1395 ret->size, ret->type, ret->dev, ret->qid.type,
1391 (unsigned long long)ret->qid.path, ret->qid.version, ret->mode, 1396 (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
1392 ret->atime, ret->mtime, (unsigned long long)ret->length, 1397 ret->atime, ret->mtime, (unsigned long long)ret->length,
1393 ret->name, ret->uid, ret->gid, ret->muid, ret->extension, 1398 ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
1394 ret->n_uid, ret->n_gid, ret->n_muid); 1399 ret->n_uid, ret->n_gid, ret->n_muid);
1395 1400
1396 p9_free_req(clnt, req); 1401 p9_free_req(clnt, req);
1397 return ret; 1402 return ret;
1398 1403
1399 error: 1404 error:
1400 kfree(ret); 1405 kfree(ret);
1401 return ERR_PTR(err); 1406 return ERR_PTR(err);
1402 } 1407 }
1403 EXPORT_SYMBOL(p9_client_stat); 1408 EXPORT_SYMBOL(p9_client_stat);
1404 1409
1405 struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, 1410 struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
1406 u64 request_mask) 1411 u64 request_mask)
1407 { 1412 {
1408 int err; 1413 int err;
1409 struct p9_client *clnt; 1414 struct p9_client *clnt;
1410 struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl), 1415 struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl),
1411 GFP_KERNEL); 1416 GFP_KERNEL);
1412 struct p9_req_t *req; 1417 struct p9_req_t *req;
1413 1418
1414 P9_DPRINTK(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n", 1419 P9_DPRINTK(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n",
1415 fid->fid, request_mask); 1420 fid->fid, request_mask);
1416 1421
1417 if (!ret) 1422 if (!ret)
1418 return ERR_PTR(-ENOMEM); 1423 return ERR_PTR(-ENOMEM);
1419 1424
1420 err = 0; 1425 err = 0;
1421 clnt = fid->clnt; 1426 clnt = fid->clnt;
1422 1427
1423 req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask); 1428 req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask);
1424 if (IS_ERR(req)) { 1429 if (IS_ERR(req)) {
1425 err = PTR_ERR(req); 1430 err = PTR_ERR(req);
1426 goto error; 1431 goto error;
1427 } 1432 }
1428 1433
1429 err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret); 1434 err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret);
1430 if (err) { 1435 if (err) {
1431 p9pdu_dump(1, req->rc); 1436 p9pdu_dump(1, req->rc);
1432 p9_free_req(clnt, req); 1437 p9_free_req(clnt, req);
1433 goto error; 1438 goto error;
1434 } 1439 }
1435 1440
1436 P9_DPRINTK(P9_DEBUG_9P, 1441 P9_DPRINTK(P9_DEBUG_9P,
1437 "<<< RGETATTR st_result_mask=%lld\n" 1442 "<<< RGETATTR st_result_mask=%lld\n"
1438 "<<< qid=%x.%llx.%x\n" 1443 "<<< qid=%x.%llx.%x\n"
1439 "<<< st_mode=%8.8x st_nlink=%llu\n" 1444 "<<< st_mode=%8.8x st_nlink=%llu\n"
1440 "<<< st_uid=%d st_gid=%d\n" 1445 "<<< st_uid=%d st_gid=%d\n"
1441 "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n" 1446 "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n"
1442 "<<< st_atime_sec=%lld st_atime_nsec=%lld\n" 1447 "<<< st_atime_sec=%lld st_atime_nsec=%lld\n"
1443 "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n" 1448 "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
1444 "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n" 1449 "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
1445 "<<< st_btime_sec=%lld st_btime_nsec=%lld\n" 1450 "<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
1446 "<<< st_gen=%lld st_data_version=%lld", 1451 "<<< st_gen=%lld st_data_version=%lld",
1447 ret->st_result_mask, ret->qid.type, ret->qid.path, 1452 ret->st_result_mask, ret->qid.type, ret->qid.path,
1448 ret->qid.version, ret->st_mode, ret->st_nlink, ret->st_uid, 1453 ret->qid.version, ret->st_mode, ret->st_nlink, ret->st_uid,
1449 ret->st_gid, ret->st_rdev, ret->st_size, ret->st_blksize, 1454 ret->st_gid, ret->st_rdev, ret->st_size, ret->st_blksize,
1450 ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec, 1455 ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec,
1451 ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec, 1456 ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec,
1452 ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, 1457 ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec,
1453 ret->st_gen, ret->st_data_version); 1458 ret->st_gen, ret->st_data_version);
1454 1459
1455 p9_free_req(clnt, req); 1460 p9_free_req(clnt, req);
1456 return ret; 1461 return ret;
1457 1462
1458 error: 1463 error:
1459 kfree(ret); 1464 kfree(ret);
1460 return ERR_PTR(err); 1465 return ERR_PTR(err);
1461 } 1466 }
1462 EXPORT_SYMBOL(p9_client_getattr_dotl); 1467 EXPORT_SYMBOL(p9_client_getattr_dotl);
1463 1468
1464 static int p9_client_statsize(struct p9_wstat *wst, int proto_version) 1469 static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
1465 { 1470 {
1466 int ret; 1471 int ret;
1467 1472
1468 /* NOTE: size shouldn't include its own length */ 1473 /* NOTE: size shouldn't include its own length */
1469 /* size[2] type[2] dev[4] qid[13] */ 1474 /* size[2] type[2] dev[4] qid[13] */
1470 /* mode[4] atime[4] mtime[4] length[8]*/ 1475 /* mode[4] atime[4] mtime[4] length[8]*/
1471 /* name[s] uid[s] gid[s] muid[s] */ 1476 /* name[s] uid[s] gid[s] muid[s] */
1472 ret = 2+4+13+4+4+4+8+2+2+2+2; 1477 ret = 2+4+13+4+4+4+8+2+2+2+2;
1473 1478
1474 if (wst->name) 1479 if (wst->name)
1475 ret += strlen(wst->name); 1480 ret += strlen(wst->name);
1476 if (wst->uid) 1481 if (wst->uid)
1477 ret += strlen(wst->uid); 1482 ret += strlen(wst->uid);
1478 if (wst->gid) 1483 if (wst->gid)
1479 ret += strlen(wst->gid); 1484 ret += strlen(wst->gid);
1480 if (wst->muid) 1485 if (wst->muid)
1481 ret += strlen(wst->muid); 1486 ret += strlen(wst->muid);
1482 1487
1483 if ((proto_version == p9_proto_2000u) || 1488 if ((proto_version == p9_proto_2000u) ||
1484 (proto_version == p9_proto_2000L)) { 1489 (proto_version == p9_proto_2000L)) {
1485 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ 1490 ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
1486 if (wst->extension) 1491 if (wst->extension)
1487 ret += strlen(wst->extension); 1492 ret += strlen(wst->extension);
1488 } 1493 }
1489 1494
1490 return ret; 1495 return ret;
1491 } 1496 }
1492 1497
1493 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) 1498 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
1494 { 1499 {
1495 int err; 1500 int err;
1496 struct p9_req_t *req; 1501 struct p9_req_t *req;
1497 struct p9_client *clnt; 1502 struct p9_client *clnt;
1498 1503
1499 err = 0; 1504 err = 0;
1500 clnt = fid->clnt; 1505 clnt = fid->clnt;
1501 wst->size = p9_client_statsize(wst, clnt->proto_version); 1506 wst->size = p9_client_statsize(wst, clnt->proto_version);
1502 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); 1507 P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
1503 P9_DPRINTK(P9_DEBUG_9P, 1508 P9_DPRINTK(P9_DEBUG_9P,
1504 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" 1509 " sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
1505 " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" 1510 " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
1506 " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" 1511 " name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
1507 " uid=%d gid=%d n_muid=%d\n", 1512 " uid=%d gid=%d n_muid=%d\n",
1508 wst->size, wst->type, wst->dev, wst->qid.type, 1513 wst->size, wst->type, wst->dev, wst->qid.type,
1509 (unsigned long long)wst->qid.path, wst->qid.version, wst->mode, 1514 (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
1510 wst->atime, wst->mtime, (unsigned long long)wst->length, 1515 wst->atime, wst->mtime, (unsigned long long)wst->length,
1511 wst->name, wst->uid, wst->gid, wst->muid, wst->extension, 1516 wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
1512 wst->n_uid, wst->n_gid, wst->n_muid); 1517 wst->n_uid, wst->n_gid, wst->n_muid);
1513 1518
1514 req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); 1519 req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
1515 if (IS_ERR(req)) { 1520 if (IS_ERR(req)) {
1516 err = PTR_ERR(req); 1521 err = PTR_ERR(req);
1517 goto error; 1522 goto error;
1518 } 1523 }
1519 1524
1520 P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid); 1525 P9_DPRINTK(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid);
1521 1526
1522 p9_free_req(clnt, req); 1527 p9_free_req(clnt, req);
1523 error: 1528 error:
1524 return err; 1529 return err;
1525 } 1530 }
1526 EXPORT_SYMBOL(p9_client_wstat); 1531 EXPORT_SYMBOL(p9_client_wstat);
1527 1532
1528 int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr) 1533 int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
1529 { 1534 {
1530 int err; 1535 int err;
1531 struct p9_req_t *req; 1536 struct p9_req_t *req;
1532 struct p9_client *clnt; 1537 struct p9_client *clnt;
1533 1538
1534 err = 0; 1539 err = 0;
1535 clnt = fid->clnt; 1540 clnt = fid->clnt;
1536 P9_DPRINTK(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid); 1541 P9_DPRINTK(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid);
1537 P9_DPRINTK(P9_DEBUG_9P, 1542 P9_DPRINTK(P9_DEBUG_9P,
1538 " valid=%x mode=%x uid=%d gid=%d size=%lld\n" 1543 " valid=%x mode=%x uid=%d gid=%d size=%lld\n"
1539 " atime_sec=%lld atime_nsec=%lld\n" 1544 " atime_sec=%lld atime_nsec=%lld\n"
1540 " mtime_sec=%lld mtime_nsec=%lld\n", 1545 " mtime_sec=%lld mtime_nsec=%lld\n",
1541 p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid, 1546 p9attr->valid, p9attr->mode, p9attr->uid, p9attr->gid,
1542 p9attr->size, p9attr->atime_sec, p9attr->atime_nsec, 1547 p9attr->size, p9attr->atime_sec, p9attr->atime_nsec,
1543 p9attr->mtime_sec, p9attr->mtime_nsec); 1548 p9attr->mtime_sec, p9attr->mtime_nsec);
1544 1549
1545 req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr); 1550 req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr);
1546 1551
1547 if (IS_ERR(req)) { 1552 if (IS_ERR(req)) {
1548 err = PTR_ERR(req); 1553 err = PTR_ERR(req);
1549 goto error; 1554 goto error;
1550 } 1555 }
1551 P9_DPRINTK(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid); 1556 P9_DPRINTK(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid);
1552 p9_free_req(clnt, req); 1557 p9_free_req(clnt, req);
1553 error: 1558 error:
1554 return err; 1559 return err;
1555 } 1560 }
1556 EXPORT_SYMBOL(p9_client_setattr); 1561 EXPORT_SYMBOL(p9_client_setattr);
1557 1562
1558 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) 1563 int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
1559 { 1564 {
1560 int err; 1565 int err;
1561 struct p9_req_t *req; 1566 struct p9_req_t *req;
1562 struct p9_client *clnt; 1567 struct p9_client *clnt;
1563 1568
1564 err = 0; 1569 err = 0;
1565 clnt = fid->clnt; 1570 clnt = fid->clnt;
1566 1571
1567 P9_DPRINTK(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid); 1572 P9_DPRINTK(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
1568 1573
1569 req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid); 1574 req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid);
1570 if (IS_ERR(req)) { 1575 if (IS_ERR(req)) {
1571 err = PTR_ERR(req); 1576 err = PTR_ERR(req);
1572 goto error; 1577 goto error;
1573 } 1578 }
1574 1579
1575 err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type, 1580 err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type,
1576 &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, 1581 &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail,
1577 &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); 1582 &sb->files, &sb->ffree, &sb->fsid, &sb->namelen);
1578 if (err) { 1583 if (err) {
1579 p9pdu_dump(1, req->rc); 1584 p9pdu_dump(1, req->rc);
1580 p9_free_req(clnt, req); 1585 p9_free_req(clnt, req);
1581 goto error; 1586 goto error;
1582 } 1587 }
1583 1588
1584 P9_DPRINTK(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld " 1589 P9_DPRINTK(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld "
1585 "blocks %llu bfree %llu bavail %llu files %llu ffree %llu " 1590 "blocks %llu bfree %llu bavail %llu files %llu ffree %llu "
1586 "fsid %llu namelen %ld\n", 1591 "fsid %llu namelen %ld\n",
1587 fid->fid, (long unsigned int)sb->type, (long int)sb->bsize, 1592 fid->fid, (long unsigned int)sb->type, (long int)sb->bsize,
1588 sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, 1593 sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree,
1589 sb->fsid, (long int)sb->namelen); 1594 sb->fsid, (long int)sb->namelen);
1590 1595
1591 p9_free_req(clnt, req); 1596 p9_free_req(clnt, req);
1592 error: 1597 error:
1593 return err; 1598 return err;
1594 } 1599 }
1595 EXPORT_SYMBOL(p9_client_statfs); 1600 EXPORT_SYMBOL(p9_client_statfs);
1596 1601
1597 int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name) 1602 int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name)
1598 { 1603 {
1599 int err; 1604 int err;
1600 struct p9_req_t *req; 1605 struct p9_req_t *req;
1601 struct p9_client *clnt; 1606 struct p9_client *clnt;
1602 1607
1603 err = 0; 1608 err = 0;
1604 clnt = fid->clnt; 1609 clnt = fid->clnt;
1605 1610
1606 P9_DPRINTK(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n", 1611 P9_DPRINTK(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n",
1607 fid->fid, newdirfid->fid, name); 1612 fid->fid, newdirfid->fid, name);
1608 1613
1609 req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid, 1614 req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid,
1610 newdirfid->fid, name); 1615 newdirfid->fid, name);
1611 if (IS_ERR(req)) { 1616 if (IS_ERR(req)) {
1612 err = PTR_ERR(req); 1617 err = PTR_ERR(req);
1613 goto error; 1618 goto error;
1614 } 1619 }
1615 1620
1616 P9_DPRINTK(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid); 1621 P9_DPRINTK(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid);
1617 1622
1618 p9_free_req(clnt, req); 1623 p9_free_req(clnt, req);
1619 error: 1624 error:
1620 return err; 1625 return err;
1621 } 1626 }
1622 EXPORT_SYMBOL(p9_client_rename); 1627 EXPORT_SYMBOL(p9_client_rename);
1623 1628
1624 /* 1629 /*
1625 * An xattrwalk without @attr_name gives the fid for the lisxattr namespace 1630 * An xattrwalk without @attr_name gives the fid for the lisxattr namespace
1626 */ 1631 */
1627 struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, 1632 struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
1628 const char *attr_name, u64 *attr_size) 1633 const char *attr_name, u64 *attr_size)
1629 { 1634 {
1630 int err; 1635 int err;
1631 struct p9_req_t *req; 1636 struct p9_req_t *req;
1632 struct p9_client *clnt; 1637 struct p9_client *clnt;
1633 struct p9_fid *attr_fid; 1638 struct p9_fid *attr_fid;
1634 1639
1635 err = 0; 1640 err = 0;
1636 clnt = file_fid->clnt; 1641 clnt = file_fid->clnt;
1637 attr_fid = p9_fid_create(clnt); 1642 attr_fid = p9_fid_create(clnt);
1638 if (IS_ERR(attr_fid)) { 1643 if (IS_ERR(attr_fid)) {
1639 err = PTR_ERR(attr_fid); 1644 err = PTR_ERR(attr_fid);
1640 attr_fid = NULL; 1645 attr_fid = NULL;
1641 goto error; 1646 goto error;
1642 } 1647 }
1643 P9_DPRINTK(P9_DEBUG_9P, 1648 P9_DPRINTK(P9_DEBUG_9P,
1644 ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n", 1649 ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n",
1645 file_fid->fid, attr_fid->fid, attr_name); 1650 file_fid->fid, attr_fid->fid, attr_name);
1646 1651
1647 req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds", 1652 req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds",
1648 file_fid->fid, attr_fid->fid, attr_name); 1653 file_fid->fid, attr_fid->fid, attr_name);
1649 if (IS_ERR(req)) { 1654 if (IS_ERR(req)) {
1650 err = PTR_ERR(req); 1655 err = PTR_ERR(req);
1651 goto error; 1656 goto error;
1652 } 1657 }
1653 err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size); 1658 err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size);
1654 if (err) { 1659 if (err) {
1655 p9pdu_dump(1, req->rc); 1660 p9pdu_dump(1, req->rc);
1656 p9_free_req(clnt, req); 1661 p9_free_req(clnt, req);
1657 goto clunk_fid; 1662 goto clunk_fid;
1658 } 1663 }
1659 p9_free_req(clnt, req); 1664 p9_free_req(clnt, req);
1660 P9_DPRINTK(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n", 1665 P9_DPRINTK(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n",
1661 attr_fid->fid, *attr_size); 1666 attr_fid->fid, *attr_size);
1662 return attr_fid; 1667 return attr_fid;
1663 clunk_fid: 1668 clunk_fid:
1664 p9_client_clunk(attr_fid); 1669 p9_client_clunk(attr_fid);
1665 attr_fid = NULL; 1670 attr_fid = NULL;
1666 error: 1671 error:
1667 if (attr_fid && (attr_fid != file_fid)) 1672 if (attr_fid && (attr_fid != file_fid))
1668 p9_fid_destroy(attr_fid); 1673 p9_fid_destroy(attr_fid);
1669 1674
1670 return ERR_PTR(err); 1675 return ERR_PTR(err);
1671 } 1676 }
1672 EXPORT_SYMBOL_GPL(p9_client_xattrwalk); 1677 EXPORT_SYMBOL_GPL(p9_client_xattrwalk);
1673 1678
1674 int p9_client_xattrcreate(struct p9_fid *fid, const char *name, 1679 int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
1675 u64 attr_size, int flags) 1680 u64 attr_size, int flags)
1676 { 1681 {
1677 int err; 1682 int err;
1678 struct p9_req_t *req; 1683 struct p9_req_t *req;
1679 struct p9_client *clnt; 1684 struct p9_client *clnt;
1680 1685
1681 P9_DPRINTK(P9_DEBUG_9P, 1686 P9_DPRINTK(P9_DEBUG_9P,
1682 ">>> TXATTRCREATE fid %d name %s size %lld flag %d\n", 1687 ">>> TXATTRCREATE fid %d name %s size %lld flag %d\n",
1683 fid->fid, name, (long long)attr_size, flags); 1688 fid->fid, name, (long long)attr_size, flags);
1684 err = 0; 1689 err = 0;
1685 clnt = fid->clnt; 1690 clnt = fid->clnt;
1686 req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd", 1691 req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd",
1687 fid->fid, name, attr_size, flags); 1692 fid->fid, name, attr_size, flags);
1688 if (IS_ERR(req)) { 1693 if (IS_ERR(req)) {
1689 err = PTR_ERR(req); 1694 err = PTR_ERR(req);
1690 goto error; 1695 goto error;
1691 } 1696 }
1692 P9_DPRINTK(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid); 1697 P9_DPRINTK(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid);
1693 p9_free_req(clnt, req); 1698 p9_free_req(clnt, req);
1694 error: 1699 error:
1695 return err; 1700 return err;
1696 } 1701 }
1697 EXPORT_SYMBOL_GPL(p9_client_xattrcreate); 1702 EXPORT_SYMBOL_GPL(p9_client_xattrcreate);
1698 1703
1699 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) 1704 int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
1700 { 1705 {
1701 int err, rsize, total; 1706 int err, rsize, total;
1702 struct p9_client *clnt; 1707 struct p9_client *clnt;
1703 struct p9_req_t *req; 1708 struct p9_req_t *req;
1704 char *dataptr; 1709 char *dataptr;
1705 1710
1706 P9_DPRINTK(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", 1711 P9_DPRINTK(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
1707 fid->fid, (long long unsigned) offset, count); 1712 fid->fid, (long long unsigned) offset, count);
1708 1713
1709 err = 0; 1714 err = 0;
1710 clnt = fid->clnt; 1715 clnt = fid->clnt;
1711 total = 0; 1716 total = 0;
1712 1717
1713 rsize = fid->iounit; 1718 rsize = fid->iounit;
1714 if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) 1719 if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ)
1715 rsize = clnt->msize - P9_READDIRHDRSZ; 1720 rsize = clnt->msize - P9_READDIRHDRSZ;
1716 1721
1717 if (count < rsize) 1722 if (count < rsize)
1718 rsize = count; 1723 rsize = count;
1719 1724
1720 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize); 1725 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize);
1721 if (IS_ERR(req)) { 1726 if (IS_ERR(req)) {
1722 err = PTR_ERR(req); 1727 err = PTR_ERR(req);
1723 goto error; 1728 goto error;
1724 } 1729 }
1725 1730
1726 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1731 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
1727 if (err) { 1732 if (err) {
1728 p9pdu_dump(1, req->rc); 1733 p9pdu_dump(1, req->rc);
1729 goto free_and_error; 1734 goto free_and_error;
1730 } 1735 }
1731 1736
1732 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); 1737 P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
1733 1738
1734 if (data) 1739 if (data)
1735 memmove(data, dataptr, count); 1740 memmove(data, dataptr, count);
1736 1741
1737 p9_free_req(clnt, req); 1742 p9_free_req(clnt, req);
1738 return count; 1743 return count;
1739 1744
1740 free_and_error: 1745 free_and_error:
1741 p9_free_req(clnt, req); 1746 p9_free_req(clnt, req);
1742 error: 1747 error:
1743 return err; 1748 return err;
1744 } 1749 }
1745 EXPORT_SYMBOL(p9_client_readdir); 1750 EXPORT_SYMBOL(p9_client_readdir);
1746 1751
1747 int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode, 1752 int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode,
1748 dev_t rdev, gid_t gid, struct p9_qid *qid) 1753 dev_t rdev, gid_t gid, struct p9_qid *qid)
1749 { 1754 {
1750 int err; 1755 int err;
1751 struct p9_client *clnt; 1756 struct p9_client *clnt;
1752 struct p9_req_t *req; 1757 struct p9_req_t *req;
1753 1758
1754 err = 0; 1759 err = 0;
1755 clnt = fid->clnt; 1760 clnt = fid->clnt;
1756 P9_DPRINTK(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d " 1761 P9_DPRINTK(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d "
1757 "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev)); 1762 "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev));
1758 req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddd", fid->fid, name, mode, 1763 req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddd", fid->fid, name, mode,
1759 MAJOR(rdev), MINOR(rdev), gid); 1764 MAJOR(rdev), MINOR(rdev), gid);
1760 if (IS_ERR(req)) 1765 if (IS_ERR(req))
1761 return PTR_ERR(req); 1766 return PTR_ERR(req);
1762 1767
1763 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); 1768 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1764 if (err) { 1769 if (err) {
1765 p9pdu_dump(1, req->rc); 1770 p9pdu_dump(1, req->rc);
1766 goto error; 1771 goto error;
1767 } 1772 }
1768 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, 1773 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type,
1769 (unsigned long long)qid->path, qid->version); 1774 (unsigned long long)qid->path, qid->version);
1770 1775
1771 error: 1776 error:
1772 p9_free_req(clnt, req); 1777 p9_free_req(clnt, req);
1773 return err; 1778 return err;
1774 1779
1775 } 1780 }
1776 EXPORT_SYMBOL(p9_client_mknod_dotl); 1781 EXPORT_SYMBOL(p9_client_mknod_dotl);
1777 1782
1778 int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, 1783 int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode,
1779 gid_t gid, struct p9_qid *qid) 1784 gid_t gid, struct p9_qid *qid)
1780 { 1785 {
1781 int err; 1786 int err;
1782 struct p9_client *clnt; 1787 struct p9_client *clnt;
1783 struct p9_req_t *req; 1788 struct p9_req_t *req;
1784 1789
1785 err = 0; 1790 err = 0;
1786 clnt = fid->clnt; 1791 clnt = fid->clnt;
1787 P9_DPRINTK(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n", 1792 P9_DPRINTK(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
1788 fid->fid, name, mode, gid); 1793 fid->fid, name, mode, gid);
1789 req = p9_client_rpc(clnt, P9_TMKDIR, "dsdd", fid->fid, name, mode, 1794 req = p9_client_rpc(clnt, P9_TMKDIR, "dsdd", fid->fid, name, mode,
1790 gid); 1795 gid);
1791 if (IS_ERR(req)) 1796 if (IS_ERR(req))
1792 return PTR_ERR(req); 1797 return PTR_ERR(req);
1793 1798
1794 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); 1799 err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid);
1795 if (err) { 1800 if (err) {
1796 p9pdu_dump(1, req->rc); 1801 p9pdu_dump(1, req->rc);
1797 goto error; 1802 goto error;
1798 } 1803 }
1799 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, 1804 P9_DPRINTK(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type,
1800 (unsigned long long)qid->path, qid->version); 1805 (unsigned long long)qid->path, qid->version);
1801 1806
1802 error: 1807 error:
1803 p9_free_req(clnt, req); 1808 p9_free_req(clnt, req);
1804 return err; 1809 return err;
1805 1810
1806 } 1811 }
1807 EXPORT_SYMBOL(p9_client_mkdir_dotl); 1812 EXPORT_SYMBOL(p9_client_mkdir_dotl);
1808 1813