diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-24 10:41:13 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-24 10:41:13 -0400 | 
| commit | 4fd5ec509bd486b5dd8cac1a4d4d7e2cbdf7c546 (patch) | |
| tree | a8ddfdcc4bfb702457e8eeff57fd6b5a2f4249b2 | |
| parent | 6e188240ebc2a132d70924942d7c8b9acb46e11a (diff) | |
| parent | 6d27e64d74e14c1cf2b4af438d7e8a77017bd654 (diff) | |
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:
  9p: Optimize TCREATE by eliminating a redundant fid clone.
  9p: cleanup: remove unneeded assignment
  9p: Add mksock support
  fs/9p: Make sure we properly instantiate dentry.
  9p: add 9P2000.L rename operation
  9p: add 9P2000.L statfs operation
  9p: VFS switches for 9p2000.L: VFS switches
  9p: VFS switches for 9p2000.L: protocol and client changes
| -rw-r--r-- | fs/9p/v9fs_vfs.h | 2 | ||||
| -rw-r--r-- | fs/9p/vfs_dir.c | 8 | ||||
| -rw-r--r-- | fs/9p/vfs_file.c | 11 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 107 | ||||
| -rw-r--r-- | fs/9p/vfs_super.c | 55 | ||||
| -rw-r--r-- | include/net/9p/9p.h | 33 | ||||
| -rw-r--r-- | include/net/9p/client.h | 2 | ||||
| -rw-r--r-- | net/9p/client.c | 70 | ||||
| -rw-r--r-- | net/9p/protocol.c | 6 | 
9 files changed, 261 insertions, 33 deletions
| diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index ed835836e0dc..32ef4009d030 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
| @@ -40,7 +40,9 @@ | |||
| 40 | extern struct file_system_type v9fs_fs_type; | 40 | extern struct file_system_type v9fs_fs_type; | 
| 41 | extern const struct address_space_operations v9fs_addr_operations; | 41 | extern const struct address_space_operations v9fs_addr_operations; | 
| 42 | extern const struct file_operations v9fs_file_operations; | 42 | extern const struct file_operations v9fs_file_operations; | 
| 43 | extern const struct file_operations v9fs_file_operations_dotl; | ||
| 43 | extern const struct file_operations v9fs_dir_operations; | 44 | extern const struct file_operations v9fs_dir_operations; | 
| 45 | extern const struct file_operations v9fs_dir_operations_dotl; | ||
| 44 | extern const struct dentry_operations v9fs_dentry_operations; | 46 | extern const struct dentry_operations v9fs_dentry_operations; | 
| 45 | extern const struct dentry_operations v9fs_cached_dentry_operations; | 47 | extern const struct dentry_operations v9fs_cached_dentry_operations; | 
| 46 | 48 | ||
| diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 0adfd64dfcee..d61e3b28ce37 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
| @@ -203,3 +203,11 @@ const struct file_operations v9fs_dir_operations = { | |||
| 203 | .open = v9fs_file_open, | 203 | .open = v9fs_file_open, | 
| 204 | .release = v9fs_dir_release, | 204 | .release = v9fs_dir_release, | 
| 205 | }; | 205 | }; | 
| 206 | |||
| 207 | const struct file_operations v9fs_dir_operations_dotl = { | ||
| 208 | .read = generic_read_dir, | ||
| 209 | .llseek = generic_file_llseek, | ||
| 210 | .readdir = v9fs_dir_readdir, | ||
| 211 | .open = v9fs_file_open, | ||
| 212 | .release = v9fs_dir_release, | ||
| 213 | }; | ||
| diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index df52d488d2a6..25b300e1c9d7 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -296,3 +296,14 @@ const struct file_operations v9fs_file_operations = { | |||
| 296 | .mmap = generic_file_readonly_mmap, | 296 | .mmap = generic_file_readonly_mmap, | 
| 297 | .fsync = v9fs_file_fsync, | 297 | .fsync = v9fs_file_fsync, | 
| 298 | }; | 298 | }; | 
| 299 | |||
| 300 | const struct file_operations v9fs_file_operations_dotl = { | ||
| 301 | .llseek = generic_file_llseek, | ||
| 302 | .read = v9fs_file_read, | ||
| 303 | .write = v9fs_file_write, | ||
| 304 | .open = v9fs_file_open, | ||
| 305 | .release = v9fs_dir_release, | ||
| 306 | .lock = v9fs_file_lock, | ||
| 307 | .mmap = generic_file_readonly_mmap, | ||
| 308 | .fsync = v9fs_file_fsync, | ||
| 309 | }; | ||
| diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 6d4d86187c55..4331b3b5ee1c 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -44,9 +44,12 @@ | |||
| 44 | #include "cache.h" | 44 | #include "cache.h" | 
| 45 | 45 | ||
| 46 | static const struct inode_operations v9fs_dir_inode_operations; | 46 | static const struct inode_operations v9fs_dir_inode_operations; | 
| 47 | static const struct inode_operations v9fs_dir_inode_operations_ext; | 47 | static const struct inode_operations v9fs_dir_inode_operations_dotu; | 
| 48 | static const struct inode_operations v9fs_dir_inode_operations_dotl; | ||
| 48 | static const struct inode_operations v9fs_file_inode_operations; | 49 | static const struct inode_operations v9fs_file_inode_operations; | 
| 50 | static const struct inode_operations v9fs_file_inode_operations_dotl; | ||
| 49 | static const struct inode_operations v9fs_symlink_inode_operations; | 51 | static const struct inode_operations v9fs_symlink_inode_operations; | 
| 52 | static const struct inode_operations v9fs_symlink_inode_operations_dotl; | ||
| 50 | 53 | ||
| 51 | /** | 54 | /** | 
| 52 | * unixmode2p9mode - convert unix mode bits to plan 9 | 55 | * unixmode2p9mode - convert unix mode bits to plan 9 | 
| @@ -273,25 +276,44 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
| 273 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 276 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 
| 274 | break; | 277 | break; | 
| 275 | case S_IFREG: | 278 | case S_IFREG: | 
| 276 | inode->i_op = &v9fs_file_inode_operations; | 279 | if (v9fs_proto_dotl(v9ses)) { | 
| 277 | inode->i_fop = &v9fs_file_operations; | 280 | inode->i_op = &v9fs_file_inode_operations_dotl; | 
| 281 | inode->i_fop = &v9fs_file_operations_dotl; | ||
| 282 | } else { | ||
| 283 | inode->i_op = &v9fs_file_inode_operations; | ||
| 284 | inode->i_fop = &v9fs_file_operations; | ||
| 285 | } | ||
| 286 | |||
| 278 | break; | 287 | break; | 
| 288 | |||
| 279 | case S_IFLNK: | 289 | case S_IFLNK: | 
| 280 | if (!v9fs_proto_dotu(v9ses)) { | 290 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { | 
| 281 | P9_DPRINTK(P9_DEBUG_ERROR, | 291 | P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with " | 
| 282 | "extended modes used w/o 9P2000.u\n"); | 292 | "legacy protocol.\n"); | 
| 283 | err = -EINVAL; | 293 | err = -EINVAL; | 
| 284 | goto error; | 294 | goto error; | 
| 285 | } | 295 | } | 
| 286 | inode->i_op = &v9fs_symlink_inode_operations; | 296 | |
| 297 | if (v9fs_proto_dotl(v9ses)) | ||
| 298 | inode->i_op = &v9fs_symlink_inode_operations_dotl; | ||
| 299 | else | ||
| 300 | inode->i_op = &v9fs_symlink_inode_operations; | ||
| 301 | |||
| 287 | break; | 302 | break; | 
| 288 | case S_IFDIR: | 303 | case S_IFDIR: | 
| 289 | inc_nlink(inode); | 304 | inc_nlink(inode); | 
| 290 | if (v9fs_proto_dotu(v9ses)) | 305 | if (v9fs_proto_dotl(v9ses)) | 
| 291 | inode->i_op = &v9fs_dir_inode_operations_ext; | 306 | inode->i_op = &v9fs_dir_inode_operations_dotl; | 
| 307 | else if (v9fs_proto_dotu(v9ses)) | ||
| 308 | inode->i_op = &v9fs_dir_inode_operations_dotu; | ||
| 292 | else | 309 | else | 
| 293 | inode->i_op = &v9fs_dir_inode_operations; | 310 | inode->i_op = &v9fs_dir_inode_operations; | 
| 294 | inode->i_fop = &v9fs_dir_operations; | 311 | |
| 312 | if (v9fs_proto_dotl(v9ses)) | ||
| 313 | inode->i_fop = &v9fs_dir_operations_dotl; | ||
| 314 | else | ||
| 315 | inode->i_fop = &v9fs_dir_operations; | ||
| 316 | |||
| 295 | break; | 317 | break; | 
| 296 | default: | 318 | default: | 
| 297 | P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", | 319 | P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n", | 
| @@ -432,14 +454,12 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 432 | { | 454 | { | 
| 433 | int retval; | 455 | int retval; | 
| 434 | struct inode *file_inode; | 456 | struct inode *file_inode; | 
| 435 | struct v9fs_session_info *v9ses; | ||
| 436 | struct p9_fid *v9fid; | 457 | struct p9_fid *v9fid; | 
| 437 | 458 | ||
| 438 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, | 459 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file, | 
| 439 | rmdir); | 460 | rmdir); | 
| 440 | 461 | ||
| 441 | file_inode = file->d_inode; | 462 | file_inode = file->d_inode; | 
| 442 | v9ses = v9fs_inode2v9ses(file_inode); | ||
| 443 | v9fid = v9fs_fid_clone(file); | 463 | v9fid = v9fs_fid_clone(file); | 
| 444 | if (IS_ERR(v9fid)) | 464 | if (IS_ERR(v9fid)) | 
| 445 | return PTR_ERR(v9fid); | 465 | return PTR_ERR(v9fid); | 
| @@ -482,12 +502,11 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
| 482 | ofid = NULL; | 502 | ofid = NULL; | 
| 483 | fid = NULL; | 503 | fid = NULL; | 
| 484 | name = (char *) dentry->d_name.name; | 504 | name = (char *) dentry->d_name.name; | 
| 485 | dfid = v9fs_fid_clone(dentry->d_parent); | 505 | dfid = v9fs_fid_lookup(dentry->d_parent); | 
| 486 | if (IS_ERR(dfid)) { | 506 | if (IS_ERR(dfid)) { | 
| 487 | err = PTR_ERR(dfid); | 507 | err = PTR_ERR(dfid); | 
| 488 | P9_DPRINTK(P9_DEBUG_VFS, "fid clone failed %d\n", err); | 508 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | 
| 489 | dfid = NULL; | 509 | return ERR_PTR(err); | 
| 490 | goto error; | ||
| 491 | } | 510 | } | 
| 492 | 511 | ||
| 493 | /* clone a fid to use for creation */ | 512 | /* clone a fid to use for creation */ | 
| @@ -495,8 +514,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
| 495 | if (IS_ERR(ofid)) { | 514 | if (IS_ERR(ofid)) { | 
| 496 | err = PTR_ERR(ofid); | 515 | err = PTR_ERR(ofid); | 
| 497 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | 516 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | 
| 498 | ofid = NULL; | 517 | return ERR_PTR(err); | 
| 499 | goto error; | ||
| 500 | } | 518 | } | 
| 501 | 519 | ||
| 502 | err = p9_client_fcreate(ofid, name, perm, mode, extension); | 520 | err = p9_client_fcreate(ofid, name, perm, mode, extension); | 
| @@ -506,14 +524,13 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
| 506 | } | 524 | } | 
| 507 | 525 | ||
| 508 | /* now walk from the parent so we can get unopened fid */ | 526 | /* now walk from the parent so we can get unopened fid */ | 
| 509 | fid = p9_client_walk(dfid, 1, &name, 0); | 527 | fid = p9_client_walk(dfid, 1, &name, 1); | 
| 510 | if (IS_ERR(fid)) { | 528 | if (IS_ERR(fid)) { | 
| 511 | err = PTR_ERR(fid); | 529 | err = PTR_ERR(fid); | 
| 512 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | 530 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | 
| 513 | fid = NULL; | 531 | fid = NULL; | 
| 514 | goto error; | 532 | goto error; | 
| 515 | } else | 533 | } | 
| 516 | dfid = NULL; | ||
| 517 | 534 | ||
| 518 | /* instantiate inode and assign the unopened fid to the dentry */ | 535 | /* instantiate inode and assign the unopened fid to the dentry */ | 
| 519 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | 536 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | 
| @@ -536,9 +553,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
| 536 | return ofid; | 553 | return ofid; | 
| 537 | 554 | ||
| 538 | error: | 555 | error: | 
| 539 | if (dfid) | ||
| 540 | p9_client_clunk(dfid); | ||
| 541 | |||
| 542 | if (ofid) | 556 | if (ofid) | 
| 543 | p9_client_clunk(ofid); | 557 | p9_client_clunk(ofid); | 
| 544 | 558 | ||
| @@ -673,8 +687,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 673 | if (IS_ERR(fid)) { | 687 | if (IS_ERR(fid)) { | 
| 674 | result = PTR_ERR(fid); | 688 | result = PTR_ERR(fid); | 
| 675 | if (result == -ENOENT) { | 689 | if (result == -ENOENT) { | 
| 676 | d_add(dentry, NULL); | 690 | inode = NULL; | 
| 677 | return NULL; | 691 | goto inst_out; | 
| 678 | } | 692 | } | 
| 679 | 693 | ||
| 680 | return ERR_PTR(result); | 694 | return ERR_PTR(result); | 
| @@ -691,7 +705,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 691 | if (result < 0) | 705 | if (result < 0) | 
| 692 | goto error; | 706 | goto error; | 
| 693 | 707 | ||
| 694 | if ((fid->qid.version) && (v9ses->cache)) | 708 | inst_out: | 
| 709 | if (v9ses->cache) | ||
| 695 | dentry->d_op = &v9fs_cached_dentry_operations; | 710 | dentry->d_op = &v9fs_cached_dentry_operations; | 
| 696 | else | 711 | else | 
| 697 | dentry->d_op = &v9fs_dentry_operations; | 712 | dentry->d_op = &v9fs_dentry_operations; | 
| @@ -770,6 +785,13 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 770 | goto clunk_olddir; | 785 | goto clunk_olddir; | 
| 771 | } | 786 | } | 
| 772 | 787 | ||
| 788 | if (v9fs_proto_dotl(v9ses)) { | ||
| 789 | retval = p9_client_rename(oldfid, newdirfid, | ||
| 790 | (char *) new_dentry->d_name.name); | ||
| 791 | if (retval != -ENOSYS) | ||
| 792 | goto clunk_newdir; | ||
| 793 | } | ||
| 794 | |||
| 773 | /* 9P can only handle file rename in the same directory */ | 795 | /* 9P can only handle file rename in the same directory */ | 
| 774 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { | 796 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { | 
| 775 | P9_DPRINTK(P9_DEBUG_ERROR, | 797 | P9_DPRINTK(P9_DEBUG_ERROR, | 
| @@ -1195,6 +1217,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
| 1195 | sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); | 1217 | sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); | 
| 1196 | else if (S_ISFIFO(mode)) | 1218 | else if (S_ISFIFO(mode)) | 
| 1197 | *name = 0; | 1219 | *name = 0; | 
| 1220 | else if (S_ISSOCK(mode)) | ||
| 1221 | *name = 0; | ||
| 1198 | else { | 1222 | else { | 
| 1199 | __putname(name); | 1223 | __putname(name); | 
| 1200 | return -EINVAL; | 1224 | return -EINVAL; | 
| @@ -1206,7 +1230,21 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
| 1206 | return retval; | 1230 | return retval; | 
| 1207 | } | 1231 | } | 
| 1208 | 1232 | ||
| 1209 | static const struct inode_operations v9fs_dir_inode_operations_ext = { | 1233 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 
| 1234 | .create = v9fs_vfs_create, | ||
| 1235 | .lookup = v9fs_vfs_lookup, | ||
| 1236 | .symlink = v9fs_vfs_symlink, | ||
| 1237 | .link = v9fs_vfs_link, | ||
| 1238 | .unlink = v9fs_vfs_unlink, | ||
| 1239 | .mkdir = v9fs_vfs_mkdir, | ||
| 1240 | .rmdir = v9fs_vfs_rmdir, | ||
| 1241 | .mknod = v9fs_vfs_mknod, | ||
| 1242 | .rename = v9fs_vfs_rename, | ||
| 1243 | .getattr = v9fs_vfs_getattr, | ||
| 1244 | .setattr = v9fs_vfs_setattr, | ||
| 1245 | }; | ||
| 1246 | |||
| 1247 | static const struct inode_operations v9fs_dir_inode_operations_dotl = { | ||
| 1210 | .create = v9fs_vfs_create, | 1248 | .create = v9fs_vfs_create, | 
| 1211 | .lookup = v9fs_vfs_lookup, | 1249 | .lookup = v9fs_vfs_lookup, | 
| 1212 | .symlink = v9fs_vfs_symlink, | 1250 | .symlink = v9fs_vfs_symlink, | 
| @@ -1237,6 +1275,11 @@ static const struct inode_operations v9fs_file_inode_operations = { | |||
| 1237 | .setattr = v9fs_vfs_setattr, | 1275 | .setattr = v9fs_vfs_setattr, | 
| 1238 | }; | 1276 | }; | 
| 1239 | 1277 | ||
| 1278 | static const struct inode_operations v9fs_file_inode_operations_dotl = { | ||
| 1279 | .getattr = v9fs_vfs_getattr, | ||
| 1280 | .setattr = v9fs_vfs_setattr, | ||
| 1281 | }; | ||
| 1282 | |||
| 1240 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1283 | static const struct inode_operations v9fs_symlink_inode_operations = { | 
| 1241 | .readlink = generic_readlink, | 1284 | .readlink = generic_readlink, | 
| 1242 | .follow_link = v9fs_vfs_follow_link, | 1285 | .follow_link = v9fs_vfs_follow_link, | 
| @@ -1244,3 +1287,11 @@ static const struct inode_operations v9fs_symlink_inode_operations = { | |||
| 1244 | .getattr = v9fs_vfs_getattr, | 1287 | .getattr = v9fs_vfs_getattr, | 
| 1245 | .setattr = v9fs_vfs_setattr, | 1288 | .setattr = v9fs_vfs_setattr, | 
| 1246 | }; | 1289 | }; | 
| 1290 | |||
| 1291 | static const struct inode_operations v9fs_symlink_inode_operations_dotl = { | ||
| 1292 | .readlink = generic_readlink, | ||
| 1293 | .follow_link = v9fs_vfs_follow_link, | ||
| 1294 | .put_link = v9fs_vfs_put_link, | ||
| 1295 | .getattr = v9fs_vfs_getattr, | ||
| 1296 | .setattr = v9fs_vfs_setattr, | ||
| 1297 | }; | ||
| diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 806da5d3b3a0..be74d020436e 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -38,6 +38,7 @@ | |||
| 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 <net/9p/9p.h> | 42 | #include <net/9p/9p.h> | 
| 42 | #include <net/9p/client.h> | 43 | #include <net/9p/client.h> | 
| 43 | 44 | ||
| @@ -45,7 +46,7 @@ | |||
| 45 | #include "v9fs_vfs.h" | 46 | #include "v9fs_vfs.h" | 
| 46 | #include "fid.h" | 47 | #include "fid.h" | 
| 47 | 48 | ||
| 48 | static const struct super_operations v9fs_super_ops; | 49 | static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; | 
| 49 | 50 | ||
| 50 | /** | 51 | /** | 
| 51 | * v9fs_set_super - set the superblock | 52 | * v9fs_set_super - set the superblock | 
| @@ -76,7 +77,10 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
| 76 | sb->s_blocksize_bits = fls(v9ses->maxdata - 1); | 77 | sb->s_blocksize_bits = fls(v9ses->maxdata - 1); | 
| 77 | sb->s_blocksize = 1 << sb->s_blocksize_bits; | 78 | sb->s_blocksize = 1 << sb->s_blocksize_bits; | 
| 78 | sb->s_magic = V9FS_MAGIC; | 79 | sb->s_magic = V9FS_MAGIC; | 
| 79 | sb->s_op = &v9fs_super_ops; | 80 | if (v9fs_proto_dotl(v9ses)) | 
| 81 | sb->s_op = &v9fs_super_ops_dotl; | ||
| 82 | else | ||
| 83 | sb->s_op = &v9fs_super_ops; | ||
| 80 | sb->s_bdi = &v9ses->bdi; | 84 | sb->s_bdi = &v9ses->bdi; | 
| 81 | 85 | ||
| 82 | sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | | 86 | sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC | | 
| @@ -211,6 +215,42 @@ v9fs_umount_begin(struct super_block *sb) | |||
| 211 | v9fs_session_begin_cancel(v9ses); | 215 | v9fs_session_begin_cancel(v9ses); | 
| 212 | } | 216 | } | 
| 213 | 217 | ||
| 218 | static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) | ||
| 219 | { | ||
| 220 | struct v9fs_session_info *v9ses; | ||
| 221 | struct p9_fid *fid; | ||
| 222 | struct p9_rstatfs rs; | ||
| 223 | int res; | ||
| 224 | |||
| 225 | fid = v9fs_fid_lookup(dentry); | ||
| 226 | if (IS_ERR(fid)) { | ||
| 227 | res = PTR_ERR(fid); | ||
| 228 | goto done; | ||
| 229 | } | ||
| 230 | |||
| 231 | v9ses = v9fs_inode2v9ses(dentry->d_inode); | ||
| 232 | if (v9fs_proto_dotl(v9ses)) { | ||
| 233 | res = p9_client_statfs(fid, &rs); | ||
| 234 | if (res == 0) { | ||
| 235 | buf->f_type = rs.type; | ||
| 236 | buf->f_bsize = rs.bsize; | ||
| 237 | buf->f_blocks = rs.blocks; | ||
| 238 | buf->f_bfree = rs.bfree; | ||
| 239 | buf->f_bavail = rs.bavail; | ||
| 240 | buf->f_files = rs.files; | ||
| 241 | buf->f_ffree = rs.ffree; | ||
| 242 | buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; | ||
| 243 | buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; | ||
| 244 | buf->f_namelen = rs.namelen; | ||
| 245 | } | ||
| 246 | if (res != -ENOSYS) | ||
| 247 | goto done; | ||
| 248 | } | ||
| 249 | res = simple_statfs(dentry, buf); | ||
| 250 | done: | ||
| 251 | return res; | ||
| 252 | } | ||
| 253 | |||
| 214 | static const struct super_operations v9fs_super_ops = { | 254 | static const struct super_operations v9fs_super_ops = { | 
| 215 | #ifdef CONFIG_9P_FSCACHE | 255 | #ifdef CONFIG_9P_FSCACHE | 
| 216 | .alloc_inode = v9fs_alloc_inode, | 256 | .alloc_inode = v9fs_alloc_inode, | 
| @@ -222,6 +262,17 @@ static const struct super_operations v9fs_super_ops = { | |||
| 222 | .umount_begin = v9fs_umount_begin, | 262 | .umount_begin = v9fs_umount_begin, | 
| 223 | }; | 263 | }; | 
| 224 | 264 | ||
| 265 | static const struct super_operations v9fs_super_ops_dotl = { | ||
| 266 | #ifdef CONFIG_9P_FSCACHE | ||
| 267 | .alloc_inode = v9fs_alloc_inode, | ||
| 268 | .destroy_inode = v9fs_destroy_inode, | ||
| 269 | #endif | ||
| 270 | .statfs = v9fs_statfs, | ||
| 271 | .clear_inode = v9fs_clear_inode, | ||
| 272 | .show_options = generic_show_options, | ||
| 273 | .umount_begin = v9fs_umount_begin, | ||
| 274 | }; | ||
| 275 | |||
| 225 | struct file_system_type v9fs_fs_type = { | 276 | struct file_system_type v9fs_fs_type = { | 
| 226 | .name = "9p", | 277 | .name = "9p", | 
| 227 | .get_sb = v9fs_get_sb, | 278 | .get_sb = v9fs_get_sb, | 
| diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index a7fb54808a23..156c26bb8bd7 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h | |||
| @@ -86,6 +86,10 @@ do { \ | |||
| 86 | 86 | ||
| 87 | /** | 87 | /** | 
| 88 | * enum p9_msg_t - 9P message types | 88 | * enum p9_msg_t - 9P message types | 
| 89 | * @P9_TSTATFS: file system status request | ||
| 90 | * @P9_RSTATFS: file system status response | ||
| 91 | * @P9_TRENAME: rename request | ||
| 92 | * @P9_RRENAME: rename response | ||
| 89 | * @P9_TVERSION: version handshake request | 93 | * @P9_TVERSION: version handshake request | 
| 90 | * @P9_RVERSION: version handshake response | 94 | * @P9_RVERSION: version handshake response | 
| 91 | * @P9_TAUTH: request to establish authentication channel | 95 | * @P9_TAUTH: request to establish authentication channel | 
| @@ -125,6 +129,10 @@ do { \ | |||
| 125 | */ | 129 | */ | 
| 126 | 130 | ||
| 127 | enum p9_msg_t { | 131 | enum p9_msg_t { | 
| 132 | P9_TSTATFS = 8, | ||
| 133 | P9_RSTATFS, | ||
| 134 | P9_TRENAME = 20, | ||
| 135 | P9_RRENAME, | ||
| 128 | P9_TVERSION = 100, | 136 | P9_TVERSION = 100, | 
| 129 | P9_RVERSION, | 137 | P9_RVERSION, | 
| 130 | P9_TAUTH = 102, | 138 | P9_TAUTH = 102, | 
| @@ -350,6 +358,31 @@ struct p9_wstat { | |||
| 350 | }; | 358 | }; | 
| 351 | 359 | ||
| 352 | /* Structures for Protocol Operations */ | 360 | /* Structures for Protocol Operations */ | 
| 361 | struct p9_tstatfs { | ||
| 362 | u32 fid; | ||
| 363 | }; | ||
| 364 | |||
| 365 | struct p9_rstatfs { | ||
| 366 | u32 type; | ||
| 367 | u32 bsize; | ||
| 368 | u64 blocks; | ||
| 369 | u64 bfree; | ||
| 370 | u64 bavail; | ||
| 371 | u64 files; | ||
| 372 | u64 ffree; | ||
| 373 | u64 fsid; | ||
| 374 | u32 namelen; | ||
| 375 | }; | ||
| 376 | |||
| 377 | struct p9_trename { | ||
| 378 | u32 fid; | ||
| 379 | u32 newdirfid; | ||
| 380 | struct p9_str name; | ||
| 381 | }; | ||
| 382 | |||
| 383 | struct p9_rrename { | ||
| 384 | }; | ||
| 385 | |||
| 353 | struct p9_tversion { | 386 | struct p9_tversion { | 
| 354 | u32 msize; | 387 | u32 msize; | 
| 355 | struct p9_str version; | 388 | struct p9_str version; | 
| diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 4f3760afc20f..7dd3ed85c782 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
| @@ -195,6 +195,8 @@ struct p9_fid { | |||
| 195 | struct list_head dlist; /* list of all fids attached to a dentry */ | 195 | struct list_head dlist; /* list of all fids attached to a dentry */ | 
| 196 | }; | 196 | }; | 
| 197 | 197 | ||
| 198 | int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); | ||
| 199 | int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name); | ||
| 198 | int p9_client_version(struct p9_client *); | 200 | int p9_client_version(struct p9_client *); | 
| 199 | struct p9_client *p9_client_create(const char *dev_name, char *options); | 201 | struct p9_client *p9_client_create(const char *dev_name, char *options); | 
| 200 | void p9_client_destroy(struct p9_client *clnt); | 202 | void p9_client_destroy(struct p9_client *clnt); | 
| diff --git a/net/9p/client.c b/net/9p/client.c index 0aa79faa9850..37c8da07a80b 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -1321,7 +1321,8 @@ static int p9_client_statsize(struct p9_wstat *wst, int proto_version) | |||
| 1321 | if (wst->muid) | 1321 | if (wst->muid) | 
| 1322 | ret += strlen(wst->muid); | 1322 | ret += strlen(wst->muid); | 
| 1323 | 1323 | ||
| 1324 | if (proto_version == p9_proto_2000u) { | 1324 | if ((proto_version == p9_proto_2000u) || | 
| 1325 | (proto_version == p9_proto_2000L)) { | ||
| 1325 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ | 1326 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ | 
| 1326 | if (wst->extension) | 1327 | if (wst->extension) | 
| 1327 | ret += strlen(wst->extension); | 1328 | ret += strlen(wst->extension); | 
| @@ -1364,3 +1365,70 @@ error: | |||
| 1364 | return err; | 1365 | return err; | 
| 1365 | } | 1366 | } | 
| 1366 | EXPORT_SYMBOL(p9_client_wstat); | 1367 | EXPORT_SYMBOL(p9_client_wstat); | 
| 1368 | |||
| 1369 | int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) | ||
| 1370 | { | ||
| 1371 | int err; | ||
| 1372 | struct p9_req_t *req; | ||
| 1373 | struct p9_client *clnt; | ||
| 1374 | |||
| 1375 | err = 0; | ||
| 1376 | clnt = fid->clnt; | ||
| 1377 | |||
| 1378 | P9_DPRINTK(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid); | ||
| 1379 | |||
| 1380 | req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid); | ||
| 1381 | if (IS_ERR(req)) { | ||
| 1382 | err = PTR_ERR(req); | ||
| 1383 | goto error; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type, | ||
| 1387 | &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, | ||
| 1388 | &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); | ||
| 1389 | if (err) { | ||
| 1390 | p9pdu_dump(1, req->rc); | ||
| 1391 | p9_free_req(clnt, req); | ||
| 1392 | goto error; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | P9_DPRINTK(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld " | ||
| 1396 | "blocks %llu bfree %llu bavail %llu files %llu ffree %llu " | ||
| 1397 | "fsid %llu namelen %ld\n", | ||
| 1398 | fid->fid, (long unsigned int)sb->type, (long int)sb->bsize, | ||
| 1399 | sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, | ||
| 1400 | sb->fsid, (long int)sb->namelen); | ||
| 1401 | |||
| 1402 | p9_free_req(clnt, req); | ||
| 1403 | error: | ||
| 1404 | return err; | ||
| 1405 | } | ||
| 1406 | EXPORT_SYMBOL(p9_client_statfs); | ||
| 1407 | |||
| 1408 | int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name) | ||
| 1409 | { | ||
| 1410 | int err; | ||
| 1411 | struct p9_req_t *req; | ||
| 1412 | struct p9_client *clnt; | ||
| 1413 | |||
| 1414 | err = 0; | ||
| 1415 | clnt = fid->clnt; | ||
| 1416 | |||
| 1417 | P9_DPRINTK(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n", | ||
| 1418 | fid->fid, newdirfid->fid, name); | ||
| 1419 | |||
| 1420 | req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid, | ||
| 1421 | newdirfid->fid, name); | ||
| 1422 | if (IS_ERR(req)) { | ||
| 1423 | err = PTR_ERR(req); | ||
| 1424 | goto error; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | P9_DPRINTK(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid); | ||
| 1428 | |||
| 1429 | p9_free_req(clnt, req); | ||
| 1430 | error: | ||
| 1431 | return err; | ||
| 1432 | } | ||
| 1433 | EXPORT_SYMBOL(p9_client_rename); | ||
| 1434 | |||
| diff --git a/net/9p/protocol.c b/net/9p/protocol.c index e7541d5b0118..77d3aab4036b 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
| @@ -341,7 +341,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
| 341 | } | 341 | } | 
| 342 | break; | 342 | break; | 
| 343 | case '?': | 343 | case '?': | 
| 344 | if (proto_version != p9_proto_2000u) | 344 | if ((proto_version != p9_proto_2000u) && | 
| 345 | (proto_version != p9_proto_2000L)) | ||
| 345 | return 0; | 346 | return 0; | 
| 346 | break; | 347 | break; | 
| 347 | default: | 348 | default: | 
| @@ -488,7 +489,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
| 488 | } | 489 | } | 
| 489 | break; | 490 | break; | 
| 490 | case '?': | 491 | case '?': | 
| 491 | if (proto_version != p9_proto_2000u) | 492 | if ((proto_version != p9_proto_2000u) && | 
| 493 | (proto_version != p9_proto_2000L)) | ||
| 492 | return 0; | 494 | return 0; | 
| 493 | break; | 495 | break; | 
| 494 | default: | 496 | default: | 
