aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c479
1 files changed, 311 insertions, 168 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 63e5b0398e8b..651a9e14d9a9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -125,6 +125,38 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
125 return res; 125 return res;
126} 126}
127 127
128int v9fs_uflags2omode(int uflags)
129{
130 int ret;
131
132 ret = 0;
133 switch (uflags&3) {
134 default:
135 case O_RDONLY:
136 ret = V9FS_OREAD;
137 break;
138
139 case O_WRONLY:
140 ret = V9FS_OWRITE;
141 break;
142
143 case O_RDWR:
144 ret = V9FS_ORDWR;
145 break;
146 }
147
148 if (uflags & O_EXCL)
149 ret |= V9FS_OEXCL;
150
151 if (uflags & O_TRUNC)
152 ret |= V9FS_OTRUNC;
153
154 if (uflags & O_APPEND)
155 ret |= V9FS_OAPPEND;
156
157 return ret;
158}
159
128/** 160/**
129 * v9fs_blank_wstat - helper function to setup a 9P stat structure 161 * v9fs_blank_wstat - helper function to setup a 9P stat structure
130 * @v9ses: 9P session info (for determining extended mode) 162 * @v9ses: 9P session info (for determining extended mode)
@@ -163,7 +195,7 @@ v9fs_blank_wstat(struct v9fs_wstat *wstat)
163 195
164struct inode *v9fs_get_inode(struct super_block *sb, int mode) 196struct inode *v9fs_get_inode(struct super_block *sb, int mode)
165{ 197{
166 struct inode *inode = NULL; 198 struct inode *inode;
167 struct v9fs_session_info *v9ses = sb->s_fs_info; 199 struct v9fs_session_info *v9ses = sb->s_fs_info;
168 200
169 dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); 201 dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
@@ -222,171 +254,133 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
222 return inode; 254 return inode;
223} 255}
224 256
225/**
226 * v9fs_create - helper function to create files and directories
227 * @dir: directory inode file is being created in
228 * @file_dentry: dentry file is being created in
229 * @perm: permissions file is being created with
230 * @open_mode: resulting open mode for file
231 *
232 */
233
234static int 257static int
235v9fs_create(struct inode *dir, 258v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
236 struct dentry *file_dentry, 259 u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
237 unsigned int perm, unsigned int open_mode)
238{ 260{
239 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); 261 u32 fid;
240 struct super_block *sb = dir->i_sb;
241 struct v9fs_fid *dirfid =
242 v9fs_fid_lookup(file_dentry->d_parent);
243 struct v9fs_fid *fid = NULL;
244 struct inode *file_inode = NULL;
245 struct v9fs_fcall *fcall = NULL;
246 struct v9fs_qid qid;
247 int dirfidnum = -1;
248 long newfid = -1;
249 int result = 0;
250 unsigned int iounit = 0;
251 int wfidno = -1;
252 int err; 262 int err;
263 struct v9fs_fcall *fcall;
253 264
254 perm = unixmode2p9mode(v9ses, perm); 265 fid = v9fs_get_idpool(&v9ses->fidpool);
255 266 if (fid < 0) {
256 dprintk(DEBUG_VFS, "dir: %p dentry: %p perm: %o mode: %o\n", dir,
257 file_dentry, perm, open_mode);
258
259 if (!dirfid)
260 return -EBADF;
261
262 dirfidnum = dirfid->fid;
263 if (dirfidnum < 0) {
264 dprintk(DEBUG_ERROR, "No fid for the directory #%lu\n",
265 dir->i_ino);
266 return -EBADF;
267 }
268
269 if (file_dentry->d_inode) {
270 dprintk(DEBUG_ERROR,
271 "Odd. There is an inode for dir %lu, name :%s:\n",
272 dir->i_ino, file_dentry->d_name.name);
273 return -EEXIST;
274 }
275
276 newfid = v9fs_get_idpool(&v9ses->fidpool);
277 if (newfid < 0) {
278 eprintk(KERN_WARNING, "no free fids available\n"); 267 eprintk(KERN_WARNING, "no free fids available\n");
279 return -ENOSPC; 268 return -ENOSPC;
280 } 269 }
281 270
282 result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); 271 err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
283 if (result < 0) { 272 if (err < 0) {
284 PRINT_FCALL_ERROR("clone error", fcall); 273 PRINT_FCALL_ERROR("clone error", fcall);
285 v9fs_put_idpool(newfid, &v9ses->fidpool); 274 goto error;
286 newfid = -1;
287 goto CleanUpFid;
288 } 275 }
289
290 kfree(fcall); 276 kfree(fcall);
291 fcall = NULL;
292 277
293 result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, 278 err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall);
294 perm, open_mode, &fcall); 279 if (err < 0) {
295 if (result < 0) {
296 PRINT_FCALL_ERROR("create fails", fcall); 280 PRINT_FCALL_ERROR("create fails", fcall);
297 goto CleanUpFid; 281 goto error;
298 } 282 }
299 283
300 iounit = fcall->params.rcreate.iounit; 284 if (iounit)
301 qid = fcall->params.rcreate.qid; 285 *iounit = fcall->params.rcreate.iounit;
286
287 if (qid)
288 *qid = fcall->params.rcreate.qid;
289
290 if (fidp)
291 *fidp = fid;
292
302 kfree(fcall); 293 kfree(fcall);
303 fcall = NULL; 294 return 0;
304 295
305 if (!(perm&V9FS_DMDIR)) { 296error:
306 fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); 297 if (fid >= 0)
307 dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); 298 v9fs_put_idpool(fid, &v9ses->fidpool);
308 if (!fid) {
309 result = -ENOMEM;
310 goto CleanUpFid;
311 }
312 299
313 fid->qid = qid; 300 kfree(fcall);
314 fid->iounit = iounit; 301 return err;
315 } else { 302}
316 err = v9fs_t_clunk(v9ses, newfid); 303
317 newfid = -1; 304static struct v9fs_fid*
318 if (err < 0) 305v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
319 dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err); 306{
320 } 307 int err;
308 u32 nfid;
309 struct v9fs_fid *ret;
310 struct v9fs_fcall *fcall;
321 311
322 /* walk to the newly created file and put the fid in the dentry */ 312 nfid = v9fs_get_idpool(&v9ses->fidpool);
323 wfidno = v9fs_get_idpool(&v9ses->fidpool); 313 if (nfid < 0) {
324 if (wfidno < 0) {
325 eprintk(KERN_WARNING, "no free fids available\n"); 314 eprintk(KERN_WARNING, "no free fids available\n");
326 return -ENOSPC; 315 return ERR_PTR(-ENOSPC);
327 } 316 }
328 317
329 result = v9fs_t_walk(v9ses, dirfidnum, wfidno, 318 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
330 (char *) file_dentry->d_name.name, &fcall); 319 &fcall);
331 if (result < 0) { 320
332 PRINT_FCALL_ERROR("clone error", fcall); 321 if (err < 0) {
333 v9fs_put_idpool(wfidno, &v9ses->fidpool); 322 PRINT_FCALL_ERROR("walk error", fcall);
334 wfidno = -1; 323 v9fs_put_idpool(nfid, &v9ses->fidpool);
335 goto CleanUpFid; 324 goto error;
336 } 325 }
326
337 kfree(fcall); 327 kfree(fcall);
338 fcall = NULL; 328 fcall = NULL;
329 ret = v9fs_fid_create(v9ses, nfid);
330 if (!ret) {
331 err = -ENOMEM;
332 goto clunk_fid;
333 }
339 334
340 if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { 335 err = v9fs_fid_insert(ret, dentry);
341 v9fs_put_idpool(wfidno, &v9ses->fidpool); 336 if (err < 0) {
342 337 v9fs_fid_destroy(ret);
343 goto CleanUpFid; 338 goto clunk_fid;
344 } 339 }
345 340
346 if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || 341 return ret;
347 (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) ||
348 (perm & V9FS_DMDEVICE))
349 return 0;
350 342
351 result = v9fs_t_stat(v9ses, wfidno, &fcall); 343clunk_fid:
352 if (result < 0) { 344 v9fs_t_clunk(v9ses, nfid);
353 PRINT_FCALL_ERROR("stat error", fcall);
354 goto CleanUpFid;
355 }
356 345
346error:
347 kfree(fcall);
348 return ERR_PTR(err);
349}
350
351struct inode *
352v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
353 struct super_block *sb)
354{
355 int err, umode;
356 struct inode *ret;
357 struct v9fs_fcall *fcall;
357 358
358 file_inode = v9fs_get_inode(sb, 359 ret = NULL;
359 p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode)); 360 err = v9fs_t_stat(v9ses, fid, &fcall);
361 if (err) {
362 PRINT_FCALL_ERROR("stat error", fcall);
363 goto error;
364 }
360 365
361 if ((!file_inode) || IS_ERR(file_inode)) { 366 umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode);
362 dprintk(DEBUG_ERROR, "create inode failed\n"); 367 ret = v9fs_get_inode(sb, umode);
363 result = -EBADF; 368 if (IS_ERR(ret)) {
364 goto CleanUpFid; 369 err = PTR_ERR(ret);
370 ret = NULL;
371 goto error;
365 } 372 }
366 373
367 v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb); 374 v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb);
368 kfree(fcall); 375 kfree(fcall);
369 fcall = NULL; 376 return ret;
370 file_dentry->d_op = &v9fs_dentry_operations;
371 d_instantiate(file_dentry, file_inode);
372
373 return 0;
374 377
375 CleanUpFid: 378error:
376 kfree(fcall); 379 kfree(fcall);
377 fcall = NULL; 380 if (ret)
381 iput(ret);
378 382
379 if (newfid >= 0) { 383 return ERR_PTR(err);
380 err = v9fs_t_clunk(v9ses, newfid);
381 if (err < 0)
382 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
383 }
384 if (wfidno >= 0) {
385 err = v9fs_t_clunk(v9ses, wfidno);
386 if (err < 0)
387 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
388 }
389 return result;
390} 384}
391 385
392/** 386/**
@@ -440,20 +434,97 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
440 return result; 434 return result;
441} 435}
442 436
437static int
438v9fs_open_created(struct inode *inode, struct file *file)
439{
440 return 0;
441}
442
443/** 443/**
444 * v9fs_vfs_create - VFS hook to create files 444 * v9fs_vfs_create - VFS hook to create files
445 * @inode: directory inode that is being deleted 445 * @inode: directory inode that is being deleted
446 * @dentry: dentry that is being deleted 446 * @dentry: dentry that is being deleted
447 * @perm: create permissions 447 * @mode: create permissions
448 * @nd: path information 448 * @nd: path information
449 * 449 *
450 */ 450 */
451 451
452static int 452static int
453v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, 453v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
454 struct nameidata *nd) 454 struct nameidata *nd)
455{ 455{
456 return v9fs_create(inode, dentry, perm, O_RDWR); 456 int err;
457 u32 fid, perm, iounit;
458 int flags;
459 struct v9fs_session_info *v9ses;
460 struct v9fs_fid *dfid, *vfid, *ffid;
461 struct inode *inode;
462 struct v9fs_qid qid;
463 struct file *filp;
464
465 inode = NULL;
466 vfid = NULL;
467 v9ses = v9fs_inode2v9ses(dir);
468 dfid = v9fs_fid_lookup(dentry->d_parent);
469 perm = unixmode2p9mode(v9ses, mode);
470
471 if (nd && nd->flags & LOOKUP_OPEN)
472 flags = nd->intent.open.flags - 1;
473 else
474 flags = O_RDWR;
475
476 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
477 perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit);
478
479 if (err)
480 goto error;
481
482 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
483 if (IS_ERR(vfid)) {
484 err = PTR_ERR(vfid);
485 vfid = NULL;
486 goto error;
487 }
488
489 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
490 if (IS_ERR(inode)) {
491 err = PTR_ERR(inode);
492 inode = NULL;
493 goto error;
494 }
495
496 dentry->d_op = &v9fs_dentry_operations;
497 d_instantiate(dentry, inode);
498
499 if (nd && nd->flags & LOOKUP_OPEN) {
500 ffid = v9fs_fid_create(v9ses, fid);
501 if (!ffid)
502 return -ENOMEM;
503
504 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
505 if (IS_ERR(filp)) {
506 v9fs_fid_destroy(ffid);
507 return PTR_ERR(filp);
508 }
509
510 ffid->rdir_pos = 0;
511 ffid->rdir_fcall = NULL;
512 ffid->fidopen = 1;
513 ffid->iounit = iounit;
514 ffid->filp = filp;
515 filp->private_data = ffid;
516 }
517
518 return 0;
519
520error:
521 if (vfid)
522 v9fs_fid_destroy(vfid);
523
524 if (inode)
525 iput(inode);
526
527 return err;
457} 528}
458 529
459/** 530/**
@@ -464,9 +535,57 @@ v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm,
464 * 535 *
465 */ 536 */
466 537
467static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode) 538static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
468{ 539{
469 return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY); 540 int err;
541 u32 fid, perm;
542 struct v9fs_session_info *v9ses;
543 struct v9fs_fid *dfid, *vfid;
544 struct inode *inode;
545
546 inode = NULL;
547 vfid = NULL;
548 v9ses = v9fs_inode2v9ses(dir);
549 dfid = v9fs_fid_lookup(dentry->d_parent);
550 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
551
552 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
553 perm, V9FS_OREAD, &fid, NULL, NULL);
554
555 if (err) {
556 dprintk(DEBUG_ERROR, "create error %d\n", err);
557 goto error;
558 }
559
560 err = v9fs_t_clunk(v9ses, fid);
561 if (err) {
562 dprintk(DEBUG_ERROR, "clunk error %d\n", err);
563 goto error;
564 }
565
566 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
567 if (IS_ERR(vfid)) {
568 err = PTR_ERR(vfid);
569 vfid = NULL;
570 goto error;
571 }
572
573 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
574 if (IS_ERR(inode)) {
575 err = PTR_ERR(inode);
576 inode = NULL;
577 goto error;
578 }
579
580 dentry->d_op = &v9fs_dentry_operations;
581 d_instantiate(dentry, inode);
582 return 0;
583
584error:
585 if (vfid)
586 v9fs_fid_destroy(vfid);
587
588 return err;
470} 589}
471 590
472/** 591/**
@@ -491,10 +610,11 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
491 int result = 0; 610 int result = 0;
492 611
493 dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", 612 dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
494 dir, dentry->d_iname, dentry, nameidata); 613 dir, dentry->d_name.name, dentry, nameidata);
495 614
496 sb = dir->i_sb; 615 sb = dir->i_sb;
497 v9ses = v9fs_inode2v9ses(dir); 616 v9ses = v9fs_inode2v9ses(dir);
617 dentry->d_op = &v9fs_dentry_operations;
498 dirfid = v9fs_fid_lookup(dentry->d_parent); 618 dirfid = v9fs_fid_lookup(dentry->d_parent);
499 619
500 if (!dirfid) { 620 if (!dirfid) {
@@ -516,9 +636,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
516 return ERR_PTR(-ENOSPC); 636 return ERR_PTR(-ENOSPC);
517 } 637 }
518 638
519 result = 639 result = v9fs_t_walk(v9ses, dirfidnum, newfid,
520 v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name, 640 (char *)dentry->d_name.name, NULL);
521 NULL);
522 if (result < 0) { 641 if (result < 0) {
523 v9fs_put_idpool(newfid, &v9ses->fidpool); 642 v9fs_put_idpool(newfid, &v9ses->fidpool);
524 if (result == -ENOENT) { 643 if (result == -ENOENT) {
@@ -551,16 +670,18 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
551 670
552 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); 671 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
553 672
554 fid = v9fs_fid_create(dentry, v9ses, newfid, 0); 673 fid = v9fs_fid_create(v9ses, newfid);
555 if (fid == NULL) { 674 if (fid == NULL) {
556 dprintk(DEBUG_ERROR, "couldn't insert\n"); 675 dprintk(DEBUG_ERROR, "couldn't insert\n");
557 result = -ENOMEM; 676 result = -ENOMEM;
558 goto FreeFcall; 677 goto FreeFcall;
559 } 678 }
560 679
561 fid->qid = fcall->params.rstat.stat.qid; 680 result = v9fs_fid_insert(fid, dentry);
681 if (result < 0)
682 goto FreeFcall;
562 683
563 dentry->d_op = &v9fs_dentry_operations; 684 fid->qid = fcall->params.rstat.stat.qid;
564 v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); 685 v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
565 686
566 d_add(dentry, inode); 687 d_add(dentry, inode);
@@ -886,8 +1007,8 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
886 } 1007 }
887 1008
888 /* copy extension buffer into buffer */ 1009 /* copy extension buffer into buffer */
889 if (fcall->params.rstat.stat.extension.len+1 < buflen) 1010 if (fcall->params.rstat.stat.extension.len < buflen)
890 buflen = fcall->params.rstat.stat.extension.len + 1; 1011 buflen = fcall->params.rstat.stat.extension.len;
891 1012
892 memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); 1013 memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
893 buffer[buflen-1] = 0; 1014 buffer[buflen-1] = 0;
@@ -951,7 +1072,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
951 if (!link) 1072 if (!link)
952 link = ERR_PTR(-ENOMEM); 1073 link = ERR_PTR(-ENOMEM);
953 else { 1074 else {
954 len = v9fs_readlink(dentry, link, PATH_MAX); 1075 len = v9fs_readlink(dentry, link, strlen(link));
955 1076
956 if (len < 0) { 1077 if (len < 0) {
957 __putname(link); 1078 __putname(link);
@@ -983,53 +1104,75 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
983static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, 1104static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
984 int mode, const char *extension) 1105 int mode, const char *extension)
985{ 1106{
986 int err, retval; 1107 int err;
1108 u32 fid, perm;
987 struct v9fs_session_info *v9ses; 1109 struct v9fs_session_info *v9ses;
1110 struct v9fs_fid *dfid, *vfid;
1111 struct inode *inode;
988 struct v9fs_fcall *fcall; 1112 struct v9fs_fcall *fcall;
989 struct v9fs_fid *fid;
990 struct v9fs_wstat wstat; 1113 struct v9fs_wstat wstat;
991 1114
992 v9ses = v9fs_inode2v9ses(dir);
993 retval = -EPERM;
994 fcall = NULL; 1115 fcall = NULL;
1116 inode = NULL;
1117 vfid = NULL;
1118 v9ses = v9fs_inode2v9ses(dir);
1119 dfid = v9fs_fid_lookup(dentry->d_parent);
1120 perm = unixmode2p9mode(v9ses, mode);
995 1121
996 if (!v9ses->extended) { 1122 if (!v9ses->extended) {
997 dprintk(DEBUG_ERROR, "not extended\n"); 1123 dprintk(DEBUG_ERROR, "not extended\n");
998 goto free_mem; 1124 return -EPERM;
999 } 1125 }
1000 1126
1001 /* issue a create */ 1127 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
1002 retval = v9fs_create(dir, dentry, mode, 0); 1128 perm, V9FS_OREAD, &fid, NULL, NULL);
1003 if (retval != 0)
1004 goto free_mem;
1005 1129
1006 fid = v9fs_fid_get_created(dentry); 1130 if (err)
1007 if (!fid) { 1131 goto error;
1008 dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); 1132
1009 goto free_mem; 1133 err = v9fs_t_clunk(v9ses, fid);
1134 if (err)
1135 goto error;
1136
1137 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
1138 if (IS_ERR(vfid)) {
1139 err = PTR_ERR(vfid);
1140 vfid = NULL;
1141 goto error;
1142 }
1143
1144 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
1145 if (IS_ERR(inode)) {
1146 err = PTR_ERR(inode);
1147 inode = NULL;
1148 goto error;
1010 } 1149 }
1011 1150
1012 /* issue a Twstat */ 1151 /* issue a Twstat */
1013 v9fs_blank_wstat(&wstat); 1152 v9fs_blank_wstat(&wstat);
1014 wstat.muid = v9ses->name; 1153 wstat.muid = v9ses->name;
1015 wstat.extension = (char *) extension; 1154 wstat.extension = (char *) extension;
1016 retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); 1155 err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall);
1017 if (retval < 0) {
1018 PRINT_FCALL_ERROR("wstat error", fcall);
1019 goto free_mem;
1020 }
1021
1022 err = v9fs_t_clunk(v9ses, fid->fid);
1023 if (err < 0) { 1156 if (err < 0) {
1024 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); 1157 PRINT_FCALL_ERROR("wstat error", fcall);
1025 goto free_mem; 1158 goto error;
1026 } 1159 }
1027 1160
1028 d_drop(dentry); /* FID - will this also clunk? */ 1161 kfree(fcall);
1162 dentry->d_op = &v9fs_dentry_operations;
1163 d_instantiate(dentry, inode);
1164 return 0;
1029 1165
1030free_mem: 1166error:
1031 kfree(fcall); 1167 kfree(fcall);
1032 return retval; 1168 if (vfid)
1169 v9fs_fid_destroy(vfid);
1170
1171 if (inode)
1172 iput(inode);
1173
1174 return err;
1175
1033} 1176}
1034 1177
1035/** 1178/**