diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
| -rw-r--r-- | fs/9p/vfs_inode.c | 107 |
1 files changed, 79 insertions, 28 deletions
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 | }; | ||
