diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 111 |
1 files changed, 80 insertions, 31 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index f2434fc9d2c4..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 |
@@ -253,9 +256,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
253 | return ERR_PTR(-ENOMEM); | 256 | return ERR_PTR(-ENOMEM); |
254 | } | 257 | } |
255 | 258 | ||
256 | inode->i_mode = mode; | 259 | inode_init_owner(inode, NULL, mode); |
257 | inode->i_uid = current_fsuid(); | ||
258 | inode->i_gid = current_fsgid(); | ||
259 | inode->i_blocks = 0; | 260 | inode->i_blocks = 0; |
260 | inode->i_rdev = 0; | 261 | inode->i_rdev = 0; |
261 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 262 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
@@ -275,25 +276,44 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
275 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 276 | init_special_inode(inode, inode->i_mode, inode->i_rdev); |
276 | break; | 277 | break; |
277 | case S_IFREG: | 278 | case S_IFREG: |
278 | inode->i_op = &v9fs_file_inode_operations; | 279 | if (v9fs_proto_dotl(v9ses)) { |
279 | 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 | |||
280 | break; | 287 | break; |
288 | |||
281 | case S_IFLNK: | 289 | case S_IFLNK: |
282 | if (!v9fs_proto_dotu(v9ses)) { | 290 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { |
283 | P9_DPRINTK(P9_DEBUG_ERROR, | 291 | P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with " |
284 | "extended modes used w/o 9P2000.u\n"); | 292 | "legacy protocol.\n"); |
285 | err = -EINVAL; | 293 | err = -EINVAL; |
286 | goto error; | 294 | goto error; |
287 | } | 295 | } |
288 | 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 | |||
289 | break; | 302 | break; |
290 | case S_IFDIR: | 303 | case S_IFDIR: |
291 | inc_nlink(inode); | 304 | inc_nlink(inode); |
292 | if (v9fs_proto_dotu(v9ses)) | 305 | if (v9fs_proto_dotl(v9ses)) |
293 | 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; | ||
294 | else | 309 | else |
295 | inode->i_op = &v9fs_dir_inode_operations; | 310 | inode->i_op = &v9fs_dir_inode_operations; |
296 | 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 | |||
297 | break; | 317 | break; |
298 | default: | 318 | default: |
299 | 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", |
@@ -434,14 +454,12 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
434 | { | 454 | { |
435 | int retval; | 455 | int retval; |
436 | struct inode *file_inode; | 456 | struct inode *file_inode; |
437 | struct v9fs_session_info *v9ses; | ||
438 | struct p9_fid *v9fid; | 457 | struct p9_fid *v9fid; |
439 | 458 | ||
440 | 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, |
441 | rmdir); | 460 | rmdir); |
442 | 461 | ||
443 | file_inode = file->d_inode; | 462 | file_inode = file->d_inode; |
444 | v9ses = v9fs_inode2v9ses(file_inode); | ||
445 | v9fid = v9fs_fid_clone(file); | 463 | v9fid = v9fs_fid_clone(file); |
446 | if (IS_ERR(v9fid)) | 464 | if (IS_ERR(v9fid)) |
447 | return PTR_ERR(v9fid); | 465 | return PTR_ERR(v9fid); |
@@ -484,12 +502,11 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
484 | ofid = NULL; | 502 | ofid = NULL; |
485 | fid = NULL; | 503 | fid = NULL; |
486 | name = (char *) dentry->d_name.name; | 504 | name = (char *) dentry->d_name.name; |
487 | dfid = v9fs_fid_clone(dentry->d_parent); | 505 | dfid = v9fs_fid_lookup(dentry->d_parent); |
488 | if (IS_ERR(dfid)) { | 506 | if (IS_ERR(dfid)) { |
489 | err = PTR_ERR(dfid); | 507 | err = PTR_ERR(dfid); |
490 | P9_DPRINTK(P9_DEBUG_VFS, "fid clone failed %d\n", err); | 508 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); |
491 | dfid = NULL; | 509 | return ERR_PTR(err); |
492 | goto error; | ||
493 | } | 510 | } |
494 | 511 | ||
495 | /* clone a fid to use for creation */ | 512 | /* clone a fid to use for creation */ |
@@ -497,8 +514,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
497 | if (IS_ERR(ofid)) { | 514 | if (IS_ERR(ofid)) { |
498 | err = PTR_ERR(ofid); | 515 | err = PTR_ERR(ofid); |
499 | 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); |
500 | ofid = NULL; | 517 | return ERR_PTR(err); |
501 | goto error; | ||
502 | } | 518 | } |
503 | 519 | ||
504 | err = p9_client_fcreate(ofid, name, perm, mode, extension); | 520 | err = p9_client_fcreate(ofid, name, perm, mode, extension); |
@@ -508,14 +524,13 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
508 | } | 524 | } |
509 | 525 | ||
510 | /* now walk from the parent so we can get unopened fid */ | 526 | /* now walk from the parent so we can get unopened fid */ |
511 | fid = p9_client_walk(dfid, 1, &name, 0); | 527 | fid = p9_client_walk(dfid, 1, &name, 1); |
512 | if (IS_ERR(fid)) { | 528 | if (IS_ERR(fid)) { |
513 | err = PTR_ERR(fid); | 529 | err = PTR_ERR(fid); |
514 | 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); |
515 | fid = NULL; | 531 | fid = NULL; |
516 | goto error; | 532 | goto error; |
517 | } else | 533 | } |
518 | dfid = NULL; | ||
519 | 534 | ||
520 | /* instantiate inode and assign the unopened fid to the dentry */ | 535 | /* instantiate inode and assign the unopened fid to the dentry */ |
521 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | 536 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); |
@@ -538,9 +553,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, | |||
538 | return ofid; | 553 | return ofid; |
539 | 554 | ||
540 | error: | 555 | error: |
541 | if (dfid) | ||
542 | p9_client_clunk(dfid); | ||
543 | |||
544 | if (ofid) | 556 | if (ofid) |
545 | p9_client_clunk(ofid); | 557 | p9_client_clunk(ofid); |
546 | 558 | ||
@@ -675,8 +687,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
675 | if (IS_ERR(fid)) { | 687 | if (IS_ERR(fid)) { |
676 | result = PTR_ERR(fid); | 688 | result = PTR_ERR(fid); |
677 | if (result == -ENOENT) { | 689 | if (result == -ENOENT) { |
678 | d_add(dentry, NULL); | 690 | inode = NULL; |
679 | return NULL; | 691 | goto inst_out; |
680 | } | 692 | } |
681 | 693 | ||
682 | return ERR_PTR(result); | 694 | return ERR_PTR(result); |
@@ -693,7 +705,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
693 | if (result < 0) | 705 | if (result < 0) |
694 | goto error; | 706 | goto error; |
695 | 707 | ||
696 | if ((fid->qid.version) && (v9ses->cache)) | 708 | inst_out: |
709 | if (v9ses->cache) | ||
697 | dentry->d_op = &v9fs_cached_dentry_operations; | 710 | dentry->d_op = &v9fs_cached_dentry_operations; |
698 | else | 711 | else |
699 | dentry->d_op = &v9fs_dentry_operations; | 712 | dentry->d_op = &v9fs_dentry_operations; |
@@ -772,6 +785,13 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
772 | goto clunk_olddir; | 785 | goto clunk_olddir; |
773 | } | 786 | } |
774 | 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 | |||
775 | /* 9P can only handle file rename in the same directory */ | 795 | /* 9P can only handle file rename in the same directory */ |
776 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { | 796 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { |
777 | P9_DPRINTK(P9_DEBUG_ERROR, | 797 | P9_DPRINTK(P9_DEBUG_ERROR, |
@@ -1197,6 +1217,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1197 | sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); | 1217 | sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); |
1198 | else if (S_ISFIFO(mode)) | 1218 | else if (S_ISFIFO(mode)) |
1199 | *name = 0; | 1219 | *name = 0; |
1220 | else if (S_ISSOCK(mode)) | ||
1221 | *name = 0; | ||
1200 | else { | 1222 | else { |
1201 | __putname(name); | 1223 | __putname(name); |
1202 | return -EINVAL; | 1224 | return -EINVAL; |
@@ -1208,7 +1230,21 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1208 | return retval; | 1230 | return retval; |
1209 | } | 1231 | } |
1210 | 1232 | ||
1211 | 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 = { | ||
1212 | .create = v9fs_vfs_create, | 1248 | .create = v9fs_vfs_create, |
1213 | .lookup = v9fs_vfs_lookup, | 1249 | .lookup = v9fs_vfs_lookup, |
1214 | .symlink = v9fs_vfs_symlink, | 1250 | .symlink = v9fs_vfs_symlink, |
@@ -1239,6 +1275,11 @@ static const struct inode_operations v9fs_file_inode_operations = { | |||
1239 | .setattr = v9fs_vfs_setattr, | 1275 | .setattr = v9fs_vfs_setattr, |
1240 | }; | 1276 | }; |
1241 | 1277 | ||
1278 | static const struct inode_operations v9fs_file_inode_operations_dotl = { | ||
1279 | .getattr = v9fs_vfs_getattr, | ||
1280 | .setattr = v9fs_vfs_setattr, | ||
1281 | }; | ||
1282 | |||
1242 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1283 | static const struct inode_operations v9fs_symlink_inode_operations = { |
1243 | .readlink = generic_readlink, | 1284 | .readlink = generic_readlink, |
1244 | .follow_link = v9fs_vfs_follow_link, | 1285 | .follow_link = v9fs_vfs_follow_link, |
@@ -1246,3 +1287,11 @@ static const struct inode_operations v9fs_symlink_inode_operations = { | |||
1246 | .getattr = v9fs_vfs_getattr, | 1287 | .getattr = v9fs_vfs_getattr, |
1247 | .setattr = v9fs_vfs_setattr, | 1288 | .setattr = v9fs_vfs_setattr, |
1248 | }; | 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 | }; | ||