aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
authorLatchesar Ionkov <lucho@ionkov.net>2006-03-02 05:54:30 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-02 11:33:07 -0500
commit6a3124a3946c16159c3faf83e62ffdb5d1134b3a (patch)
tree989f1e89ed0971824db973af5347b879e12c67cd /fs/9p/vfs_inode.c
parent77a3313551afd53c90012e5a87f7f2b2195fc67e (diff)
[PATCH] v9fs: fix atomic create open
In order to assure atomic create+open v9fs stores the open fid produced by v9fs_vfs_create in the dentry, from where v9fs_file_open retrieves it and associates it with the open file. This patch modifies v9fs to use nameidata.intent.open values to do the atomic create+open. Signed-off-by: Latchesar Ionkov <lucho@ionkov.net> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c478
1 files changed, 312 insertions, 166 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 63e5b0398e8b..dce729d42869 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,135 @@ 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 err = -ENOSPC;
269 goto error;
280 } 270 }
281 271
282 result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); 272 err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
283 if (result < 0) { 273 if (err < 0) {
284 PRINT_FCALL_ERROR("clone error", fcall); 274 PRINT_FCALL_ERROR("clone error", fcall);
285 v9fs_put_idpool(newfid, &v9ses->fidpool); 275 goto error;
286 newfid = -1;
287 goto CleanUpFid;
288 } 276 }
289
290 kfree(fcall); 277 kfree(fcall);
291 fcall = NULL;
292 278
293 result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, 279 err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall);
294 perm, open_mode, &fcall); 280 if (err < 0) {
295 if (result < 0) {
296 PRINT_FCALL_ERROR("create fails", fcall); 281 PRINT_FCALL_ERROR("create fails", fcall);
297 goto CleanUpFid; 282 goto error;
298 } 283 }
299 284
300 iounit = fcall->params.rcreate.iounit; 285 if (iounit)
301 qid = fcall->params.rcreate.qid; 286 *iounit = fcall->params.rcreate.iounit;
287
288 if (qid)
289 *qid = fcall->params.rcreate.qid;
290
291 if (fidp)
292 *fidp = fid;
293
302 kfree(fcall); 294 kfree(fcall);
303 fcall = NULL; 295 return 0;
304 296
305 if (!(perm&V9FS_DMDIR)) { 297error:
306 fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); 298 if (fid >= 0)
307 dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); 299 v9fs_put_idpool(fid, &v9ses->fidpool);
308 if (!fid) {
309 result = -ENOMEM;
310 goto CleanUpFid;
311 }
312 300
313 fid->qid = qid; 301 kfree(fcall);
314 fid->iounit = iounit; 302 return err;
315 } else { 303}
316 err = v9fs_t_clunk(v9ses, newfid); 304
317 newfid = -1; 305static struct v9fs_fid*
318 if (err < 0) 306v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
319 dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err); 307{
320 } 308 int err;
309 u32 nfid;
310 struct v9fs_fid *ret;
311 struct v9fs_fcall *fcall;
321 312
322 /* walk to the newly created file and put the fid in the dentry */ 313 nfid = v9fs_get_idpool(&v9ses->fidpool);
323 wfidno = v9fs_get_idpool(&v9ses->fidpool); 314 if (nfid < 0) {
324 if (wfidno < 0) {
325 eprintk(KERN_WARNING, "no free fids available\n"); 315 eprintk(KERN_WARNING, "no free fids available\n");
326 return -ENOSPC; 316 err = -ENOSPC;
317 goto error;
327 } 318 }
328 319
329 result = v9fs_t_walk(v9ses, dirfidnum, wfidno, 320 err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name,
330 (char *) file_dentry->d_name.name, &fcall); 321 &fcall);
331 if (result < 0) { 322
332 PRINT_FCALL_ERROR("clone error", fcall); 323 if (err < 0) {
333 v9fs_put_idpool(wfidno, &v9ses->fidpool); 324 PRINT_FCALL_ERROR("walk error", fcall);
334 wfidno = -1; 325 v9fs_put_idpool(nfid, &v9ses->fidpool);
335 goto CleanUpFid; 326 goto error;
336 } 327 }
328
337 kfree(fcall); 329 kfree(fcall);
338 fcall = NULL; 330 fcall = NULL;
331 ret = v9fs_fid_create(v9ses, nfid);
332 if (!ret) {
333 err = -ENOMEM;
334 goto clunk_fid;
335 }
339 336
340 if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { 337 err = v9fs_fid_insert(ret, dentry);
341 v9fs_put_idpool(wfidno, &v9ses->fidpool); 338 if (err < 0) {
342 339 v9fs_fid_destroy(ret);
343 goto CleanUpFid; 340 goto clunk_fid;
344 } 341 }
345 342
346 if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || 343 return ret;
347 (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) ||
348 (perm & V9FS_DMDEVICE))
349 return 0;
350 344
351 result = v9fs_t_stat(v9ses, wfidno, &fcall); 345clunk_fid:
352 if (result < 0) { 346 v9fs_t_clunk(v9ses, nfid);
353 PRINT_FCALL_ERROR("stat error", fcall); 347
354 goto CleanUpFid; 348error:
355 } 349 kfree(fcall);
350 return ERR_PTR(err);
351}
356 352
353struct inode *
354v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
355 struct super_block *sb)
356{
357 int err, umode;
358 struct inode *ret;
359 struct v9fs_fcall *fcall;
357 360
358 file_inode = v9fs_get_inode(sb, 361 ret = NULL;
359 p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode)); 362 err = v9fs_t_stat(v9ses, fid, &fcall);
363 if (err) {
364 PRINT_FCALL_ERROR("stat error", fcall);
365 goto error;
366 }
360 367
361 if ((!file_inode) || IS_ERR(file_inode)) { 368 umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode);
362 dprintk(DEBUG_ERROR, "create inode failed\n"); 369 ret = v9fs_get_inode(sb, umode);
363 result = -EBADF; 370 if (IS_ERR(ret)) {
364 goto CleanUpFid; 371 err = PTR_ERR(ret);
372 ret = NULL;
373 goto error;
365 } 374 }
366 375
367 v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb); 376 v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb);
368 kfree(fcall); 377 kfree(fcall);
369 fcall = NULL; 378 return ret;
370 file_dentry->d_op = &v9fs_dentry_operations;
371 d_instantiate(file_dentry, file_inode);
372
373 return 0;
374 379
375 CleanUpFid: 380error:
376 kfree(fcall); 381 kfree(fcall);
377 fcall = NULL; 382 if (ret)
383 iput(ret);
378 384
379 if (newfid >= 0) { 385 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} 386}
391 387
392/** 388/**
@@ -440,20 +436,97 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
440 return result; 436 return result;
441} 437}
442 438
439static int
440v9fs_open_created(struct inode *inode, struct file *file)
441{
442 return 0;
443}
444
443/** 445/**
444 * v9fs_vfs_create - VFS hook to create files 446 * v9fs_vfs_create - VFS hook to create files
445 * @inode: directory inode that is being deleted 447 * @inode: directory inode that is being deleted
446 * @dentry: dentry that is being deleted 448 * @dentry: dentry that is being deleted
447 * @perm: create permissions 449 * @mode: create permissions
448 * @nd: path information 450 * @nd: path information
449 * 451 *
450 */ 452 */
451 453
452static int 454static int
453v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, 455v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
454 struct nameidata *nd) 456 struct nameidata *nd)
455{ 457{
456 return v9fs_create(inode, dentry, perm, O_RDWR); 458 int err;
459 u32 fid, perm, iounit;
460 int flags;
461 struct v9fs_session_info *v9ses;
462 struct v9fs_fid *dfid, *vfid, *ffid;
463 struct inode *inode;
464 struct v9fs_qid qid;
465 struct file *filp;
466
467 inode = NULL;
468 vfid = NULL;
469 v9ses = v9fs_inode2v9ses(dir);
470 dfid = v9fs_fid_lookup(dentry->d_parent);
471 perm = unixmode2p9mode(v9ses, mode);
472
473 if (nd && nd->flags & LOOKUP_OPEN)
474 flags = nd->intent.open.flags - 1;
475 else
476 flags = O_RDWR;
477
478 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
479 perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit);
480
481 if (err)
482 goto error;
483
484 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
485 if (IS_ERR(vfid)) {
486 err = PTR_ERR(vfid);
487 vfid = NULL;
488 goto error;
489 }
490
491 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
492 if (IS_ERR(inode)) {
493 err = PTR_ERR(inode);
494 inode = NULL;
495 goto error;
496 }
497
498 dentry->d_op = &v9fs_dentry_operations;
499 d_instantiate(dentry, inode);
500
501 if (nd && nd->flags & LOOKUP_OPEN) {
502 ffid = v9fs_fid_create(v9ses, fid);
503 if (!ffid)
504 return -ENOMEM;
505
506 filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
507 if (IS_ERR(filp)) {
508 v9fs_fid_destroy(ffid);
509 return PTR_ERR(filp);
510 }
511
512 ffid->rdir_pos = 0;
513 ffid->rdir_fcall = NULL;
514 ffid->fidopen = 1;
515 ffid->iounit = iounit;
516 ffid->filp = filp;
517 filp->private_data = ffid;
518 }
519
520 return 0;
521
522error:
523 if (vfid)
524 v9fs_fid_destroy(vfid);
525
526 if (inode)
527 iput(inode);
528
529 return err;
457} 530}
458 531
459/** 532/**
@@ -464,9 +537,57 @@ v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm,
464 * 537 *
465 */ 538 */
466 539
467static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode) 540static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
468{ 541{
469 return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY); 542 int err;
543 u32 fid, perm;
544 struct v9fs_session_info *v9ses;
545 struct v9fs_fid *dfid, *vfid;
546 struct inode *inode;
547
548 inode = NULL;
549 vfid = NULL;
550 v9ses = v9fs_inode2v9ses(dir);
551 dfid = v9fs_fid_lookup(dentry->d_parent);
552 perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
553
554 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
555 perm, V9FS_OREAD, &fid, NULL, NULL);
556
557 if (err) {
558 dprintk(DEBUG_ERROR, "create error %d\n", err);
559 goto error;
560 }
561
562 err = v9fs_t_clunk(v9ses, fid);
563 if (err) {
564 dprintk(DEBUG_ERROR, "clunk error %d\n", err);
565 goto error;
566 }
567
568 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
569 if (IS_ERR(vfid)) {
570 err = PTR_ERR(vfid);
571 vfid = NULL;
572 goto error;
573 }
574
575 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
576 if (IS_ERR(inode)) {
577 err = PTR_ERR(inode);
578 inode = NULL;
579 goto error;
580 }
581
582 dentry->d_op = &v9fs_dentry_operations;
583 d_instantiate(dentry, inode);
584 return 0;
585
586error:
587 if (vfid)
588 v9fs_fid_destroy(vfid);
589
590 return err;
470} 591}
471 592
472/** 593/**
@@ -516,9 +637,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
516 return ERR_PTR(-ENOSPC); 637 return ERR_PTR(-ENOSPC);
517 } 638 }
518 639
519 result = 640 result = v9fs_t_walk(v9ses, dirfidnum, newfid,
520 v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name, 641 (char *)dentry->d_name.name, NULL);
521 NULL);
522 if (result < 0) { 642 if (result < 0) {
523 v9fs_put_idpool(newfid, &v9ses->fidpool); 643 v9fs_put_idpool(newfid, &v9ses->fidpool);
524 if (result == -ENOENT) { 644 if (result == -ENOENT) {
@@ -551,13 +671,17 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
551 671
552 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); 672 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
553 673
554 fid = v9fs_fid_create(dentry, v9ses, newfid, 0); 674 fid = v9fs_fid_create(v9ses, newfid);
555 if (fid == NULL) { 675 if (fid == NULL) {
556 dprintk(DEBUG_ERROR, "couldn't insert\n"); 676 dprintk(DEBUG_ERROR, "couldn't insert\n");
557 result = -ENOMEM; 677 result = -ENOMEM;
558 goto FreeFcall; 678 goto FreeFcall;
559 } 679 }
560 680
681 result = v9fs_fid_insert(fid, dentry);
682 if (result < 0)
683 goto FreeFcall;
684
561 fid->qid = fcall->params.rstat.stat.qid; 685 fid->qid = fcall->params.rstat.stat.qid;
562 686
563 dentry->d_op = &v9fs_dentry_operations; 687 dentry->d_op = &v9fs_dentry_operations;
@@ -886,8 +1010,8 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
886 } 1010 }
887 1011
888 /* copy extension buffer into buffer */ 1012 /* copy extension buffer into buffer */
889 if (fcall->params.rstat.stat.extension.len+1 < buflen) 1013 if (fcall->params.rstat.stat.extension.len < buflen)
890 buflen = fcall->params.rstat.stat.extension.len + 1; 1014 buflen = fcall->params.rstat.stat.extension.len;
891 1015
892 memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); 1016 memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
893 buffer[buflen-1] = 0; 1017 buffer[buflen-1] = 0;
@@ -951,7 +1075,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
951 if (!link) 1075 if (!link)
952 link = ERR_PTR(-ENOMEM); 1076 link = ERR_PTR(-ENOMEM);
953 else { 1077 else {
954 len = v9fs_readlink(dentry, link, PATH_MAX); 1078 len = v9fs_readlink(dentry, link, strlen(link));
955 1079
956 if (len < 0) { 1080 if (len < 0) {
957 __putname(link); 1081 __putname(link);
@@ -983,53 +1107,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, 1107static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
984 int mode, const char *extension) 1108 int mode, const char *extension)
985{ 1109{
986 int err, retval; 1110 int err;
1111 u32 fid, perm;
987 struct v9fs_session_info *v9ses; 1112 struct v9fs_session_info *v9ses;
1113 struct v9fs_fid *dfid, *vfid;
1114 struct inode *inode;
988 struct v9fs_fcall *fcall; 1115 struct v9fs_fcall *fcall;
989 struct v9fs_fid *fid;
990 struct v9fs_wstat wstat; 1116 struct v9fs_wstat wstat;
991 1117
992 v9ses = v9fs_inode2v9ses(dir);
993 retval = -EPERM;
994 fcall = NULL; 1118 fcall = NULL;
1119 inode = NULL;
1120 vfid = NULL;
1121 v9ses = v9fs_inode2v9ses(dir);
1122 dfid = v9fs_fid_lookup(dentry->d_parent);
1123 perm = unixmode2p9mode(v9ses, mode);
995 1124
996 if (!v9ses->extended) { 1125 if (!v9ses->extended) {
997 dprintk(DEBUG_ERROR, "not extended\n"); 1126 dprintk(DEBUG_ERROR, "not extended\n");
998 goto free_mem; 1127 return -EPERM;
999 } 1128 }
1000 1129
1001 /* issue a create */ 1130 err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
1002 retval = v9fs_create(dir, dentry, mode, 0); 1131 perm, V9FS_OREAD, &fid, NULL, NULL);
1003 if (retval != 0)
1004 goto free_mem;
1005 1132
1006 fid = v9fs_fid_get_created(dentry); 1133 if (err)
1007 if (!fid) { 1134 goto error;
1008 dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); 1135
1009 goto free_mem; 1136 err = v9fs_t_clunk(v9ses, fid);
1137 if (err)
1138 goto error;
1139
1140 vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
1141 if (IS_ERR(vfid)) {
1142 err = PTR_ERR(vfid);
1143 vfid = NULL;
1144 goto error;
1145 }
1146
1147 inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
1148 if (IS_ERR(inode)) {
1149 err = PTR_ERR(inode);
1150 inode = NULL;
1151 goto error;
1010 } 1152 }
1011 1153
1012 /* issue a Twstat */ 1154 /* issue a Twstat */
1013 v9fs_blank_wstat(&wstat); 1155 v9fs_blank_wstat(&wstat);
1014 wstat.muid = v9ses->name; 1156 wstat.muid = v9ses->name;
1015 wstat.extension = (char *) extension; 1157 wstat.extension = (char *) extension;
1016 retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); 1158 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) { 1159 if (err < 0) {
1024 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); 1160 PRINT_FCALL_ERROR("wstat error", fcall);
1025 goto free_mem; 1161 goto error;
1026 } 1162 }
1027 1163
1028 d_drop(dentry); /* FID - will this also clunk? */ 1164 kfree(fcall);
1165 dentry->d_op = &v9fs_dentry_operations;
1166 d_instantiate(dentry, inode);
1167 return 0;
1029 1168
1030free_mem: 1169error:
1031 kfree(fcall); 1170 kfree(fcall);
1032 return retval; 1171 if (vfid)
1172 v9fs_fid_destroy(vfid);
1173
1174 if (inode)
1175 iput(inode);
1176
1177 return err;
1178
1033} 1179}
1034 1180
1035/** 1181/**