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.c617
1 files changed, 209 insertions, 408 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 0ea965c3bb7d..d933ef1fbd8a 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -40,7 +40,6 @@
40#include "v9fs.h" 40#include "v9fs.h"
41#include "9p.h" 41#include "9p.h"
42#include "v9fs_vfs.h" 42#include "v9fs_vfs.h"
43#include "conv.h"
44#include "fid.h" 43#include "fid.h"
45 44
46static struct inode_operations v9fs_dir_inode_operations; 45static struct inode_operations v9fs_dir_inode_operations;
@@ -127,100 +126,32 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
127} 126}
128 127
129/** 128/**
130 * v9fs_blank_mistat - helper function to setup a 9P stat structure 129 * v9fs_blank_wstat - helper function to setup a 9P stat structure
131 * @v9ses: 9P session info (for determining extended mode) 130 * @v9ses: 9P session info (for determining extended mode)
132 * @mistat: structure to initialize 131 * @wstat: structure to initialize
133 * 132 *
134 */ 133 */
135 134
136static void 135static void
137v9fs_blank_mistat(struct v9fs_session_info *v9ses, struct v9fs_stat *mistat) 136v9fs_blank_wstat(struct v9fs_wstat *wstat)
138{ 137{
139 mistat->type = ~0; 138 wstat->type = ~0;
140 mistat->dev = ~0; 139 wstat->dev = ~0;
141 mistat->qid.type = ~0; 140 wstat->qid.type = ~0;
142 mistat->qid.version = ~0; 141 wstat->qid.version = ~0;
143 *((long long *)&mistat->qid.path) = ~0; 142 *((long long *)&wstat->qid.path) = ~0;
144 mistat->mode = ~0; 143 wstat->mode = ~0;
145 mistat->atime = ~0; 144 wstat->atime = ~0;
146 mistat->mtime = ~0; 145 wstat->mtime = ~0;
147 mistat->length = ~0; 146 wstat->length = ~0;
148 mistat->name = mistat->data; 147 wstat->name = NULL;
149 mistat->uid = mistat->data; 148 wstat->uid = NULL;
150 mistat->gid = mistat->data; 149 wstat->gid = NULL;
151 mistat->muid = mistat->data; 150 wstat->muid = NULL;
152 if (v9ses->extended) { 151 wstat->n_uid = ~0;
153 mistat->n_uid = ~0; 152 wstat->n_gid = ~0;
154 mistat->n_gid = ~0; 153 wstat->n_muid = ~0;
155 mistat->n_muid = ~0; 154 wstat->extension = NULL;
156 mistat->extension = mistat->data;
157 }
158 *mistat->data = 0;
159}
160
161/**
162 * v9fs_mistat2unix - convert mistat to unix stat
163 * @mistat: Plan 9 metadata (mistat) structure
164 * @buf: unix metadata (stat) structure to populate
165 * @sb: superblock
166 *
167 */
168
169static void
170v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf,
171 struct super_block *sb)
172{
173 struct v9fs_session_info *v9ses = sb ? sb->s_fs_info : NULL;
174
175 buf->st_nlink = 1;
176
177 buf->st_atime = mistat->atime;
178 buf->st_mtime = mistat->mtime;
179 buf->st_ctime = mistat->mtime;
180
181 buf->st_uid = (unsigned short)-1;
182 buf->st_gid = (unsigned short)-1;
183
184 if (v9ses && v9ses->extended) {
185 /* TODO: string to uid mapping via user-space daemon */
186 if (mistat->n_uid != -1)
187 sscanf(mistat->uid, "%x", (unsigned int *)&buf->st_uid);
188
189 if (mistat->n_gid != -1)
190 sscanf(mistat->gid, "%x", (unsigned int *)&buf->st_gid);
191 }
192
193 if (buf->st_uid == (unsigned short)-1)
194 buf->st_uid = v9ses->uid;
195 if (buf->st_gid == (unsigned short)-1)
196 buf->st_gid = v9ses->gid;
197
198 buf->st_mode = p9mode2unixmode(v9ses, mistat->mode);
199 if ((S_ISBLK(buf->st_mode)) || (S_ISCHR(buf->st_mode))) {
200 char type = 0;
201 int major = -1;
202 int minor = -1;
203 sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
204 switch (type) {
205 case 'c':
206 buf->st_mode &= ~S_IFBLK;
207 buf->st_mode |= S_IFCHR;
208 break;
209 case 'b':
210 break;
211 default:
212 dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
213 type, mistat->extension);
214 };
215 buf->st_rdev = MKDEV(major, minor);
216 } else
217 buf->st_rdev = 0;
218
219 buf->st_size = mistat->length;
220
221 buf->st_blksize = sb->s_blocksize;
222 buf->st_blocks =
223 (buf->st_size + buf->st_blksize - 1) >> sb->s_blocksize_bits;
224} 155}
225 156
226/** 157/**
@@ -312,12 +243,12 @@ v9fs_create(struct inode *dir,
312 struct inode *file_inode = NULL; 243 struct inode *file_inode = NULL;
313 struct v9fs_fcall *fcall = NULL; 244 struct v9fs_fcall *fcall = NULL;
314 struct v9fs_qid qid; 245 struct v9fs_qid qid;
315 struct stat newstat;
316 int dirfidnum = -1; 246 int dirfidnum = -1;
317 long newfid = -1; 247 long newfid = -1;
318 int result = 0; 248 int result = 0;
319 unsigned int iounit = 0; 249 unsigned int iounit = 0;
320 int wfidno = -1; 250 int wfidno = -1;
251 int err;
321 252
322 perm = unixmode2p9mode(v9ses, perm); 253 perm = unixmode2p9mode(v9ses, perm);
323 254
@@ -349,57 +280,64 @@ v9fs_create(struct inode *dir,
349 280
350 result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); 281 result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall);
351 if (result < 0) { 282 if (result < 0) {
352 dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); 283 PRINT_FCALL_ERROR("clone error", fcall);
353 v9fs_put_idpool(newfid, &v9ses->fidpool); 284 v9fs_put_idpool(newfid, &v9ses->fidpool);
354 newfid = -1; 285 newfid = -1;
355 goto CleanUpFid; 286 goto CleanUpFid;
356 } 287 }
357 288
358 kfree(fcall); 289 kfree(fcall);
290 fcall = NULL;
359 291
360 result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, 292 result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name,
361 perm, open_mode, &fcall); 293 perm, open_mode, &fcall);
362 if (result < 0) { 294 if (result < 0) {
363 dprintk(DEBUG_ERROR, "create fails: %s(%d)\n", 295 PRINT_FCALL_ERROR("create fails", fcall);
364 FCALL_ERROR(fcall), result);
365
366 goto CleanUpFid; 296 goto CleanUpFid;
367 } 297 }
368 298
369 iounit = fcall->params.rcreate.iounit; 299 iounit = fcall->params.rcreate.iounit;
370 qid = fcall->params.rcreate.qid; 300 qid = fcall->params.rcreate.qid;
371 kfree(fcall); 301 kfree(fcall);
302 fcall = NULL;
372 303
373 fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); 304 if (!(perm&V9FS_DMDIR)) {
374 dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); 305 fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1);
375 if (!fid) { 306 dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate);
376 result = -ENOMEM; 307 if (!fid) {
377 goto CleanUpFid; 308 result = -ENOMEM;
378 } 309 goto CleanUpFid;
310 }
379 311
380 fid->qid = qid; 312 fid->qid = qid;
381 fid->iounit = iounit; 313 fid->iounit = iounit;
314 } else {
315 err = v9fs_t_clunk(v9ses, newfid);
316 newfid = -1;
317 if (err < 0)
318 dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err);
319 }
382 320
383 /* walk to the newly created file and put the fid in the dentry */ 321 /* walk to the newly created file and put the fid in the dentry */
384 wfidno = v9fs_get_idpool(&v9ses->fidpool); 322 wfidno = v9fs_get_idpool(&v9ses->fidpool);
385 if (newfid < 0) { 323 if (wfidno < 0) {
386 eprintk(KERN_WARNING, "no free fids available\n"); 324 eprintk(KERN_WARNING, "no free fids available\n");
387 return -ENOSPC; 325 return -ENOSPC;
388 } 326 }
389 327
390 result = v9fs_t_walk(v9ses, dirfidnum, wfidno, 328 result = v9fs_t_walk(v9ses, dirfidnum, wfidno,
391 (char *) file_dentry->d_name.name, NULL); 329 (char *) file_dentry->d_name.name, &fcall);
392 if (result < 0) { 330 if (result < 0) {
393 dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); 331 PRINT_FCALL_ERROR("clone error", fcall);
394 v9fs_put_idpool(wfidno, &v9ses->fidpool); 332 v9fs_put_idpool(wfidno, &v9ses->fidpool);
395 wfidno = -1; 333 wfidno = -1;
396 goto CleanUpFid; 334 goto CleanUpFid;
397 } 335 }
336 kfree(fcall);
337 fcall = NULL;
398 338
399 if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { 339 if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) {
400 if (!v9fs_t_clunk(v9ses, newfid, &fcall)) { 340 v9fs_put_idpool(wfidno, &v9ses->fidpool);
401 v9fs_put_idpool(wfidno, &v9ses->fidpool);
402 }
403 341
404 goto CleanUpFid; 342 goto CleanUpFid;
405 } 343 }
@@ -409,62 +347,43 @@ v9fs_create(struct inode *dir,
409 (perm & V9FS_DMDEVICE)) 347 (perm & V9FS_DMDEVICE))
410 return 0; 348 return 0;
411 349
412 result = v9fs_t_stat(v9ses, newfid, &fcall); 350 result = v9fs_t_stat(v9ses, wfidno, &fcall);
413 if (result < 0) { 351 if (result < 0) {
414 dprintk(DEBUG_ERROR, "stat error: %s(%d)\n", FCALL_ERROR(fcall), 352 PRINT_FCALL_ERROR("stat error", fcall);
415 result);
416 goto CleanUpFid; 353 goto CleanUpFid;
417 } 354 }
418 355
419 v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
420 356
421 file_inode = v9fs_get_inode(sb, newstat.st_mode); 357 file_inode = v9fs_get_inode(sb,
358 p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode));
359
422 if ((!file_inode) || IS_ERR(file_inode)) { 360 if ((!file_inode) || IS_ERR(file_inode)) {
423 dprintk(DEBUG_ERROR, "create inode failed\n"); 361 dprintk(DEBUG_ERROR, "create inode failed\n");
424 result = -EBADF; 362 result = -EBADF;
425 goto CleanUpFid; 363 goto CleanUpFid;
426 } 364 }
427 365
428 v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb); 366 v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb);
429 kfree(fcall); 367 kfree(fcall);
430 fcall = NULL; 368 fcall = NULL;
431 file_dentry->d_op = &v9fs_dentry_operations; 369 file_dentry->d_op = &v9fs_dentry_operations;
432 d_instantiate(file_dentry, file_inode); 370 d_instantiate(file_dentry, file_inode);
433 371
434 if (perm & V9FS_DMDIR) {
435 if (!v9fs_t_clunk(v9ses, newfid, &fcall))
436 v9fs_put_idpool(newfid, &v9ses->fidpool);
437 else
438 dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n",
439 FCALL_ERROR(fcall));
440 kfree(fcall);
441 fid->fidopen = 0;
442 fid->fidcreate = 0;
443 d_drop(file_dentry);
444 }
445
446 return 0; 372 return 0;
447 373
448 CleanUpFid: 374 CleanUpFid:
449 kfree(fcall); 375 kfree(fcall);
376 fcall = NULL;
450 377
451 if (newfid >= 0) { 378 if (newfid >= 0) {
452 if (!v9fs_t_clunk(v9ses, newfid, &fcall)) 379 err = v9fs_t_clunk(v9ses, newfid);
453 v9fs_put_idpool(newfid, &v9ses->fidpool); 380 if (err < 0)
454 else 381 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
455 dprintk(DEBUG_ERROR, "clunk failed: %s\n",
456 FCALL_ERROR(fcall));
457
458 kfree(fcall);
459 } 382 }
460 if (wfidno >= 0) { 383 if (wfidno >= 0) {
461 if (!v9fs_t_clunk(v9ses, wfidno, &fcall)) 384 err = v9fs_t_clunk(v9ses, wfidno);
462 v9fs_put_idpool(wfidno, &v9ses->fidpool); 385 if (err < 0)
463 else 386 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
464 dprintk(DEBUG_ERROR, "clunk failed: %s\n",
465 FCALL_ERROR(fcall));
466
467 kfree(fcall);
468 } 387 }
469 return result; 388 return result;
470} 389}
@@ -509,10 +428,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
509 } 428 }
510 429
511 result = v9fs_t_remove(v9ses, fid, &fcall); 430 result = v9fs_t_remove(v9ses, fid, &fcall);
512 if (result < 0) 431 if (result < 0) {
513 dprintk(DEBUG_ERROR, "remove of file fails: %s(%d)\n", 432 PRINT_FCALL_ERROR("remove fails", fcall);
514 FCALL_ERROR(fcall), result); 433 } else {
515 else {
516 v9fs_put_idpool(fid, &v9ses->fidpool); 434 v9fs_put_idpool(fid, &v9ses->fidpool);
517 v9fs_fid_destroy(v9fid); 435 v9fs_fid_destroy(v9fid);
518 } 436 }
@@ -567,7 +485,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
567 struct v9fs_fid *fid; 485 struct v9fs_fid *fid;
568 struct inode *inode; 486 struct inode *inode;
569 struct v9fs_fcall *fcall = NULL; 487 struct v9fs_fcall *fcall = NULL;
570 struct stat newstat;
571 int dirfidnum = -1; 488 int dirfidnum = -1;
572 int newfid = -1; 489 int newfid = -1;
573 int result = 0; 490 int result = 0;
@@ -620,8 +537,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
620 goto FreeFcall; 537 goto FreeFcall;
621 } 538 }
622 539
623 v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb); 540 inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses,
624 inode = v9fs_get_inode(sb, newstat.st_mode); 541 fcall->params.rstat.stat.mode));
625 542
626 if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) { 543 if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
627 eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n", 544 eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
@@ -631,7 +548,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
631 goto FreeFcall; 548 goto FreeFcall;
632 } 549 }
633 550
634 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); 551 inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
635 552
636 fid = v9fs_fid_create(dentry, v9ses, newfid, 0); 553 fid = v9fs_fid_create(dentry, v9ses, newfid, 0);
637 if (fid == NULL) { 554 if (fid == NULL) {
@@ -640,10 +557,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
640 goto FreeFcall; 557 goto FreeFcall;
641 } 558 }
642 559
643 fid->qid = fcall->params.rstat.stat->qid; 560 fid->qid = fcall->params.rstat.stat.qid;
644 561
645 dentry->d_op = &v9fs_dentry_operations; 562 dentry->d_op = &v9fs_dentry_operations;
646 v9fs_mistat2inode(fcall->params.rstat.stat, inode, inode->i_sb); 563 v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
647 564
648 d_add(dentry, inode); 565 d_add(dentry, inode);
649 kfree(fcall); 566 kfree(fcall);
@@ -699,7 +616,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
699 v9fs_fid_lookup(old_dentry->d_parent); 616 v9fs_fid_lookup(old_dentry->d_parent);
700 struct v9fs_fid *newdirfid = 617 struct v9fs_fid *newdirfid =
701 v9fs_fid_lookup(new_dentry->d_parent); 618 v9fs_fid_lookup(new_dentry->d_parent);
702 struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); 619 struct v9fs_wstat wstat;
703 struct v9fs_fcall *fcall = NULL; 620 struct v9fs_fcall *fcall = NULL;
704 int fid = -1; 621 int fid = -1;
705 int olddirfidnum = -1; 622 int olddirfidnum = -1;
@@ -708,9 +625,6 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
708 625
709 dprintk(DEBUG_VFS, "\n"); 626 dprintk(DEBUG_VFS, "\n");
710 627
711 if (!mistat)
712 return -ENOMEM;
713
714 if ((!oldfid) || (!olddirfid) || (!newdirfid)) { 628 if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
715 dprintk(DEBUG_ERROR, "problem with arguments\n"); 629 dprintk(DEBUG_ERROR, "problem with arguments\n");
716 return -EBADF; 630 return -EBADF;
@@ -734,26 +648,15 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
734 goto FreeFcallnBail; 648 goto FreeFcallnBail;
735 } 649 }
736 650
737 v9fs_blank_mistat(v9ses, mistat); 651 v9fs_blank_wstat(&wstat);
652 wstat.muid = v9ses->name;
653 wstat.name = (char *) new_dentry->d_name.name;
738 654
739 strcpy(mistat->data + 1, v9ses->name); 655 retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
740 mistat->name = mistat->data + 1 + strlen(v9ses->name);
741
742 if (new_dentry->d_name.len >
743 (v9ses->maxdata - strlen(v9ses->name) - sizeof(struct v9fs_stat))) {
744 dprintk(DEBUG_ERROR, "new name too long\n");
745 goto FreeFcallnBail;
746 }
747
748 strcpy(mistat->name, new_dentry->d_name.name);
749 retval = v9fs_t_wstat(v9ses, fid, mistat, &fcall);
750 656
751 FreeFcallnBail: 657 FreeFcallnBail:
752 kfree(mistat);
753
754 if (retval < 0) 658 if (retval < 0)
755 dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n", 659 PRINT_FCALL_ERROR("wstat error", fcall);
756 FCALL_ERROR(fcall));
757 660
758 kfree(fcall); 661 kfree(fcall);
759 return retval; 662 return retval;
@@ -788,7 +691,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
788 if (err < 0) 691 if (err < 0)
789 dprintk(DEBUG_ERROR, "stat error\n"); 692 dprintk(DEBUG_ERROR, "stat error\n");
790 else { 693 else {
791 v9fs_mistat2inode(fcall->params.rstat.stat, dentry->d_inode, 694 v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode,
792 dentry->d_inode->i_sb); 695 dentry->d_inode->i_sb);
793 generic_fillattr(dentry->d_inode, stat); 696 generic_fillattr(dentry->d_inode, stat);
794 } 697 }
@@ -809,57 +712,44 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
809 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); 712 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
810 struct v9fs_fid *fid = v9fs_fid_lookup(dentry); 713 struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
811 struct v9fs_fcall *fcall = NULL; 714 struct v9fs_fcall *fcall = NULL;
812 struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); 715 struct v9fs_wstat wstat;
813 int res = -EPERM; 716 int res = -EPERM;
814 717
815 dprintk(DEBUG_VFS, "\n"); 718 dprintk(DEBUG_VFS, "\n");
816 719
817 if (!mistat)
818 return -ENOMEM;
819
820 if (!fid) { 720 if (!fid) {
821 dprintk(DEBUG_ERROR, 721 dprintk(DEBUG_ERROR,
822 "Couldn't find fid associated with dentry\n"); 722 "Couldn't find fid associated with dentry\n");
823 return -EBADF; 723 return -EBADF;
824 } 724 }
825 725
826 v9fs_blank_mistat(v9ses, mistat); 726 v9fs_blank_wstat(&wstat);
827 if (iattr->ia_valid & ATTR_MODE) 727 if (iattr->ia_valid & ATTR_MODE)
828 mistat->mode = unixmode2p9mode(v9ses, iattr->ia_mode); 728 wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
829 729
830 if (iattr->ia_valid & ATTR_MTIME) 730 if (iattr->ia_valid & ATTR_MTIME)
831 mistat->mtime = iattr->ia_mtime.tv_sec; 731 wstat.mtime = iattr->ia_mtime.tv_sec;
832 732
833 if (iattr->ia_valid & ATTR_ATIME) 733 if (iattr->ia_valid & ATTR_ATIME)
834 mistat->atime = iattr->ia_atime.tv_sec; 734 wstat.atime = iattr->ia_atime.tv_sec;
835 735
836 if (iattr->ia_valid & ATTR_SIZE) 736 if (iattr->ia_valid & ATTR_SIZE)
837 mistat->length = iattr->ia_size; 737 wstat.length = iattr->ia_size;
838 738
839 if (v9ses->extended) { 739 if (v9ses->extended) {
840 char *ptr = mistat->data+1; 740 if (iattr->ia_valid & ATTR_UID)
841 741 wstat.n_uid = iattr->ia_uid;
842 if (iattr->ia_valid & ATTR_UID) {
843 mistat->uid = ptr;
844 ptr += 1+sprintf(ptr, "%08x", iattr->ia_uid);
845 mistat->n_uid = iattr->ia_uid;
846 }
847 742
848 if (iattr->ia_valid & ATTR_GID) { 743 if (iattr->ia_valid & ATTR_GID)
849 mistat->gid = ptr; 744 wstat.n_gid = iattr->ia_gid;
850 ptr += 1+sprintf(ptr, "%08x", iattr->ia_gid);
851 mistat->n_gid = iattr->ia_gid;
852 }
853 } 745 }
854 746
855 res = v9fs_t_wstat(v9ses, fid->fid, mistat, &fcall); 747 res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
856 748
857 if (res < 0) 749 if (res < 0)
858 dprintk(DEBUG_ERROR, "wstat error: %s\n", FCALL_ERROR(fcall)); 750 PRINT_FCALL_ERROR("wstat error", fcall);
859 751
860 kfree(mistat);
861 kfree(fcall); 752 kfree(fcall);
862
863 if (res >= 0) 753 if (res >= 0)
864 res = inode_setattr(dentry->d_inode, iattr); 754 res = inode_setattr(dentry->d_inode, iattr);
865 755
@@ -867,51 +757,47 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
867} 757}
868 758
869/** 759/**
870 * v9fs_mistat2inode - populate an inode structure with mistat info 760 * v9fs_stat2inode - populate an inode structure with mistat info
871 * @mistat: Plan 9 metadata (mistat) structure 761 * @stat: Plan 9 metadata (mistat) structure
872 * @inode: inode to populate 762 * @inode: inode to populate
873 * @sb: superblock of filesystem 763 * @sb: superblock of filesystem
874 * 764 *
875 */ 765 */
876 766
877void 767void
878v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode, 768v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
879 struct super_block *sb) 769 struct super_block *sb)
880{ 770{
771 int n;
772 char ext[32];
881 struct v9fs_session_info *v9ses = sb->s_fs_info; 773 struct v9fs_session_info *v9ses = sb->s_fs_info;
882 774
883 inode->i_nlink = 1; 775 inode->i_nlink = 1;
884 776
885 inode->i_atime.tv_sec = mistat->atime; 777 inode->i_atime.tv_sec = stat->atime;
886 inode->i_mtime.tv_sec = mistat->mtime; 778 inode->i_mtime.tv_sec = stat->mtime;
887 inode->i_ctime.tv_sec = mistat->mtime; 779 inode->i_ctime.tv_sec = stat->mtime;
888 780
889 inode->i_uid = -1; 781 inode->i_uid = v9ses->uid;
890 inode->i_gid = -1; 782 inode->i_gid = v9ses->gid;
891 783
892 if (v9ses->extended) { 784 if (v9ses->extended) {
893 /* TODO: string to uid mapping via user-space daemon */ 785 inode->i_uid = stat->n_uid;
894 inode->i_uid = mistat->n_uid; 786 inode->i_gid = stat->n_gid;
895 inode->i_gid = mistat->n_gid;
896
897 if (mistat->n_uid == -1)
898 sscanf(mistat->uid, "%x", &inode->i_uid);
899
900 if (mistat->n_gid == -1)
901 sscanf(mistat->gid, "%x", &inode->i_gid);
902 } 787 }
903 788
904 if (inode->i_uid == -1) 789 inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
905 inode->i_uid = v9ses->uid;
906 if (inode->i_gid == -1)
907 inode->i_gid = v9ses->gid;
908
909 inode->i_mode = p9mode2unixmode(v9ses, mistat->mode);
910 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { 790 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
911 char type = 0; 791 char type = 0;
912 int major = -1; 792 int major = -1;
913 int minor = -1; 793 int minor = -1;
914 sscanf(mistat->extension, "%c %u %u", &type, &major, &minor); 794
795 n = stat->extension.len;
796 if (n > sizeof(ext)-1)
797 n = sizeof(ext)-1;
798 memmove(ext, stat->extension.str, n);
799 ext[n] = 0;
800 sscanf(ext, "%c %u %u", &type, &major, &minor);
915 switch (type) { 801 switch (type) {
916 case 'c': 802 case 'c':
917 inode->i_mode &= ~S_IFBLK; 803 inode->i_mode &= ~S_IFBLK;
@@ -920,14 +806,14 @@ v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode,
920 case 'b': 806 case 'b':
921 break; 807 break;
922 default: 808 default:
923 dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n", 809 dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n",
924 type, mistat->extension); 810 type, stat->extension.len, stat->extension.str);
925 }; 811 };
926 inode->i_rdev = MKDEV(major, minor); 812 inode->i_rdev = MKDEV(major, minor);
927 } else 813 } else
928 inode->i_rdev = 0; 814 inode->i_rdev = 0;
929 815
930 inode->i_size = mistat->length; 816 inode->i_size = stat->length;
931 817
932 inode->i_blksize = sb->s_blocksize; 818 inode->i_blksize = sb->s_blocksize;
933 inode->i_blocks = 819 inode->i_blocks =
@@ -955,71 +841,6 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid)
955} 841}
956 842
957/** 843/**
958 * v9fs_vfs_symlink - helper function to create symlinks
959 * @dir: directory inode containing symlink
960 * @dentry: dentry for symlink
961 * @symname: symlink data
962 *
963 * See 9P2000.u RFC for more information
964 *
965 */
966
967static int
968v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
969{
970 int retval = -EPERM;
971 struct v9fs_fid *newfid;
972 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
973 struct v9fs_fcall *fcall = NULL;
974 struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
975
976 dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
977 symname);
978
979 if (!mistat)
980 return -ENOMEM;
981
982 if (!v9ses->extended) {
983 dprintk(DEBUG_ERROR, "not extended\n");
984 goto FreeFcall;
985 }
986
987 /* issue a create */
988 retval = v9fs_create(dir, dentry, S_IFLNK, 0);
989 if (retval != 0)
990 goto FreeFcall;
991
992 newfid = v9fs_fid_lookup(dentry);
993
994 /* issue a twstat */
995 v9fs_blank_mistat(v9ses, mistat);
996 strcpy(mistat->data + 1, symname);
997 mistat->extension = mistat->data + 1;
998 retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
999 if (retval < 0) {
1000 dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
1001 FCALL_ERROR(fcall));
1002 goto FreeFcall;
1003 }
1004
1005 kfree(fcall);
1006
1007 if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
1008 dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
1009 FCALL_ERROR(fcall));
1010 goto FreeFcall;
1011 }
1012
1013 d_drop(dentry); /* FID - will this also clunk? */
1014
1015 FreeFcall:
1016 kfree(mistat);
1017 kfree(fcall);
1018
1019 return retval;
1020}
1021
1022/**
1023 * v9fs_readlink - read a symlink's location (internal version) 844 * v9fs_readlink - read a symlink's location (internal version)
1024 * @dentry: dentry for symlink 845 * @dentry: dentry for symlink
1025 * @buffer: buffer to load symlink location into 846 * @buffer: buffer to load symlink location into
@@ -1058,16 +879,17 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
1058 if (!fcall) 879 if (!fcall)
1059 return -EIO; 880 return -EIO;
1060 881
1061 if (!(fcall->params.rstat.stat->mode & V9FS_DMSYMLINK)) { 882 if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) {
1062 retval = -EINVAL; 883 retval = -EINVAL;
1063 goto FreeFcall; 884 goto FreeFcall;
1064 } 885 }
1065 886
1066 /* copy extension buffer into buffer */ 887 /* copy extension buffer into buffer */
1067 if (strlen(fcall->params.rstat.stat->extension) < buflen) 888 if (fcall->params.rstat.stat.extension.len < buflen)
1068 buflen = strlen(fcall->params.rstat.stat->extension); 889 buflen = fcall->params.rstat.stat.extension.len;
1069 890
1070 memcpy(buffer, fcall->params.rstat.stat->extension, buflen + 1); 891 memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
892 buffer[buflen-1] = 0;
1071 893
1072 retval = buflen; 894 retval = buflen;
1073 895
@@ -1157,6 +979,77 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
1157 __putname(s); 979 __putname(s);
1158} 980}
1159 981
982static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
983 int mode, const char *extension)
984{
985 int err, retval;
986 struct v9fs_session_info *v9ses;
987 struct v9fs_fcall *fcall;
988 struct v9fs_fid *fid;
989 struct v9fs_wstat wstat;
990
991 v9ses = v9fs_inode2v9ses(dir);
992 retval = -EPERM;
993 fcall = NULL;
994
995 if (!v9ses->extended) {
996 dprintk(DEBUG_ERROR, "not extended\n");
997 goto free_mem;
998 }
999
1000 /* issue a create */
1001 retval = v9fs_create(dir, dentry, mode, 0);
1002 if (retval != 0)
1003 goto free_mem;
1004
1005 fid = v9fs_fid_get_created(dentry);
1006 if (!fid) {
1007 dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
1008 goto free_mem;
1009 }
1010
1011 /* issue a Twstat */
1012 v9fs_blank_wstat(&wstat);
1013 wstat.muid = v9ses->name;
1014 wstat.extension = (char *) extension;
1015 retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
1016 if (retval < 0) {
1017 PRINT_FCALL_ERROR("wstat error", fcall);
1018 goto free_mem;
1019 }
1020
1021 err = v9fs_t_clunk(v9ses, fid->fid);
1022 if (err < 0) {
1023 dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
1024 goto free_mem;
1025 }
1026
1027 d_drop(dentry); /* FID - will this also clunk? */
1028
1029free_mem:
1030 kfree(fcall);
1031 return retval;
1032}
1033
1034/**
1035 * v9fs_vfs_symlink - helper function to create symlinks
1036 * @dir: directory inode containing symlink
1037 * @dentry: dentry for symlink
1038 * @symname: symlink data
1039 *
1040 * See 9P2000.u RFC for more information
1041 *
1042 */
1043
1044static int
1045v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
1046{
1047 dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
1048 symname);
1049
1050 return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
1051}
1052
1160/** 1053/**
1161 * v9fs_vfs_link - create a hardlink 1054 * v9fs_vfs_link - create a hardlink
1162 * @old_dentry: dentry for file to link to 1055 * @old_dentry: dentry for file to link to
@@ -1173,64 +1066,24 @@ static int
1173v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, 1066v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1174 struct dentry *dentry) 1067 struct dentry *dentry)
1175{ 1068{
1176 int retval = -EPERM; 1069 int retval;
1177 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); 1070 struct v9fs_fid *oldfid;
1178 struct v9fs_fcall *fcall = NULL; 1071 char *name;
1179 struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
1180 struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
1181 struct v9fs_fid *newfid = NULL;
1182 char *symname = __getname();
1183 1072
1184 dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, 1073 dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
1185 old_dentry->d_name.name); 1074 old_dentry->d_name.name);
1186 1075
1187 if (!v9ses->extended) { 1076 oldfid = v9fs_fid_lookup(old_dentry);
1188 dprintk(DEBUG_ERROR, "not extended\n"); 1077 if (!oldfid) {
1189 goto FreeMem; 1078 dprintk(DEBUG_ERROR, "can't find oldfid\n");
1190 } 1079 return -EPERM;
1191
1192 /* get fid of old_dentry */
1193 sprintf(symname, "hardlink(%d)\n", oldfid->fid);
1194
1195 /* issue a create */
1196 retval = v9fs_create(dir, dentry, V9FS_DMLINK, 0);
1197 if (retval != 0)
1198 goto FreeMem;
1199
1200 newfid = v9fs_fid_lookup(dentry);
1201 if (!newfid) {
1202 dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
1203 goto FreeMem;
1204 }
1205
1206 /* issue a twstat */
1207 v9fs_blank_mistat(v9ses, mistat);
1208 strcpy(mistat->data + 1, symname);
1209 mistat->extension = mistat->data + 1;
1210 retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
1211 if (retval < 0) {
1212 dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
1213 FCALL_ERROR(fcall));
1214 goto FreeMem;
1215 }
1216
1217 kfree(fcall);
1218
1219 if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
1220 dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
1221 FCALL_ERROR(fcall));
1222 goto FreeMem;
1223 } 1080 }
1224 1081
1225 d_drop(dentry); /* FID - will this also clunk? */ 1082 name = __getname();
1226 1083 sprintf(name, "hardlink(%d)\n", oldfid->fid);
1227 kfree(fcall); 1084 retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
1228 fcall = NULL; 1085 __putname(name);
1229 1086
1230 FreeMem:
1231 kfree(mistat);
1232 kfree(fcall);
1233 __putname(symname);
1234 return retval; 1087 return retval;
1235} 1088}
1236 1089
@@ -1246,82 +1099,30 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
1246static int 1099static int
1247v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) 1100v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1248{ 1101{
1249 int retval = -EPERM; 1102 int retval;
1250 struct v9fs_fid *newfid; 1103 char *name;
1251 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
1252 struct v9fs_fcall *fcall = NULL;
1253 struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
1254 char *symname = __getname();
1255 1104
1256 dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, 1105 dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
1257 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); 1106 dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
1258 1107
1259 if (!mistat) 1108 if (!new_valid_dev(rdev))
1260 return -ENOMEM; 1109 return -EINVAL;
1261
1262 if (!new_valid_dev(rdev)) {
1263 retval = -EINVAL;
1264 goto FreeMem;
1265 }
1266
1267 if (!v9ses->extended) {
1268 dprintk(DEBUG_ERROR, "not extended\n");
1269 goto FreeMem;
1270 }
1271
1272 /* issue a create */
1273 retval = v9fs_create(dir, dentry, mode, 0);
1274
1275 if (retval != 0)
1276 goto FreeMem;
1277
1278 newfid = v9fs_fid_lookup(dentry);
1279 if (!newfid) {
1280 dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n");
1281 retval = -EINVAL;
1282 goto FreeMem;
1283 }
1284 1110
1111 name = __getname();
1285 /* build extension */ 1112 /* build extension */
1286 if (S_ISBLK(mode)) 1113 if (S_ISBLK(mode))
1287 sprintf(symname, "b %u %u", MAJOR(rdev), MINOR(rdev)); 1114 sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
1288 else if (S_ISCHR(mode)) 1115 else if (S_ISCHR(mode))
1289 sprintf(symname, "c %u %u", MAJOR(rdev), MINOR(rdev)); 1116 sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
1290 else if (S_ISFIFO(mode)) 1117 else if (S_ISFIFO(mode))
1291 ; /* DO NOTHING */ 1118 *name = 0;
1292 else { 1119 else {
1293 retval = -EINVAL; 1120 __putname(name);
1294 goto FreeMem; 1121 return -EINVAL;
1295 }
1296
1297 if (!S_ISFIFO(mode)) {
1298 /* issue a twstat */
1299 v9fs_blank_mistat(v9ses, mistat);
1300 strcpy(mistat->data + 1, symname);
1301 mistat->extension = mistat->data + 1;
1302 retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
1303 if (retval < 0) {
1304 dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
1305 FCALL_ERROR(fcall));
1306 goto FreeMem;
1307 }
1308 } 1122 }
1309 1123
1310 /* need to update dcache so we show up */ 1124 retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
1311 kfree(fcall); 1125 __putname(name);
1312
1313 if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
1314 dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
1315 FCALL_ERROR(fcall));
1316 goto FreeMem;
1317 }
1318
1319 d_drop(dentry); /* FID - will this also clunk? */
1320
1321 FreeMem:
1322 kfree(mistat);
1323 kfree(fcall);
1324 __putname(symname);
1325 1126
1326 return retval; 1127 return retval;
1327} 1128}