diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/error.c | 1 | ||||
| -rw-r--r-- | fs/9p/fid.c | 69 | ||||
| -rw-r--r-- | fs/9p/fid.h | 5 | ||||
| -rw-r--r-- | fs/9p/mux.c | 4 | ||||
| -rw-r--r-- | fs/9p/v9fs.c | 11 | ||||
| -rw-r--r-- | fs/9p/vfs_file.c | 47 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 206 | ||||
| -rw-r--r-- | fs/binfmt_elf.c | 51 | ||||
| -rw-r--r-- | fs/binfmt_elf_fdpic.c | 8 | ||||
| -rw-r--r-- | fs/buffer.c | 15 | ||||
| -rw-r--r-- | fs/fs-writeback.c | 13 | ||||
| -rw-r--r-- | fs/nfsd/nfs3xdr.c | 9 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 5 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfsxdr.c | 5 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 28 | ||||
| -rw-r--r-- | fs/proc/base.c | 8 |
17 files changed, 320 insertions, 173 deletions
diff --git a/fs/9p/error.c b/fs/9p/error.c index ae91555c1558..0d7fa4e08812 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c | |||
| @@ -83,6 +83,7 @@ int v9fs_errstr2errno(char *errstr, int len) | |||
| 83 | 83 | ||
| 84 | if (errno == 0) { | 84 | if (errno == 0) { |
| 85 | /* TODO: if error isn't found, add it dynamically */ | 85 | /* TODO: if error isn't found, add it dynamically */ |
| 86 | errstr[len] = 0; | ||
| 86 | printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, | 87 | printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__, |
| 87 | errstr); | 88 | errstr); |
| 88 | errno = 1; | 89 | errno = 1; |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 27507201f9e7..a9b6301a04fc 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
| 26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
| 27 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
| 28 | #include <asm/semaphore.h> | ||
| 28 | 29 | ||
| 29 | #include "debug.h" | 30 | #include "debug.h" |
| 30 | #include "v9fs.h" | 31 | #include "v9fs.h" |
| @@ -84,6 +85,7 @@ struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) | |||
| 84 | new->iounit = 0; | 85 | new->iounit = 0; |
| 85 | new->rdir_pos = 0; | 86 | new->rdir_pos = 0; |
| 86 | new->rdir_fcall = NULL; | 87 | new->rdir_fcall = NULL; |
| 88 | init_MUTEX(&new->lock); | ||
| 87 | INIT_LIST_HEAD(&new->list); | 89 | INIT_LIST_HEAD(&new->list); |
| 88 | 90 | ||
| 89 | return new; | 91 | return new; |
| @@ -102,11 +104,11 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | /** | 106 | /** |
| 105 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry | 107 | * v9fs_fid_lookup - return a locked fid from a dentry |
| 106 | * @dentry: dentry to look for fid in | 108 | * @dentry: dentry to look for fid in |
| 107 | * @type: intent of lookup (operation or traversal) | ||
| 108 | * | 109 | * |
| 109 | * find a fid in the dentry | 110 | * find a fid in the dentry, obtain its semaphore and return a reference to it. |
| 111 | * code calling lookup is responsible for releasing lock | ||
| 110 | * | 112 | * |
| 111 | * TODO: only match fids that have the same uid as current user | 113 | * TODO: only match fids that have the same uid as current user |
| 112 | * | 114 | * |
| @@ -124,7 +126,68 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
| 124 | 126 | ||
| 125 | if (!return_fid) { | 127 | if (!return_fid) { |
| 126 | dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); | 128 | dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); |
| 129 | return_fid = ERR_PTR(-EBADF); | ||
| 127 | } | 130 | } |
| 128 | 131 | ||
| 132 | if(down_interruptible(&return_fid->lock)) | ||
| 133 | return ERR_PTR(-EINTR); | ||
| 134 | |||
| 129 | return return_fid; | 135 | return return_fid; |
| 130 | } | 136 | } |
| 137 | |||
| 138 | /** | ||
| 139 | * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it | ||
| 140 | * @dentry: dentry to look for fid in | ||
| 141 | * | ||
| 142 | * find a fid in the dentry and then clone to a new private fid | ||
| 143 | * | ||
| 144 | * TODO: only match fids that have the same uid as current user | ||
| 145 | * | ||
| 146 | */ | ||
| 147 | |||
| 148 | struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry) | ||
| 149 | { | ||
| 150 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | ||
| 151 | struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF); | ||
| 152 | struct v9fs_fcall *fcall = NULL; | ||
| 153 | int fid, err; | ||
| 154 | |||
| 155 | base_fid = v9fs_fid_lookup(dentry); | ||
| 156 | |||
| 157 | if(IS_ERR(base_fid)) | ||
| 158 | return base_fid; | ||
| 159 | |||
| 160 | if(base_fid) { /* clone fid */ | ||
| 161 | fid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 162 | if (fid < 0) { | ||
| 163 | eprintk(KERN_WARNING, "newfid fails!\n"); | ||
| 164 | new_fid = ERR_PTR(-ENOSPC); | ||
| 165 | goto Release_Fid; | ||
| 166 | } | ||
| 167 | |||
| 168 | err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall); | ||
| 169 | if (err < 0) { | ||
| 170 | dprintk(DEBUG_ERROR, "clone walk didn't work\n"); | ||
| 171 | v9fs_put_idpool(fid, &v9ses->fidpool); | ||
| 172 | new_fid = ERR_PTR(err); | ||
| 173 | goto Free_Fcall; | ||
| 174 | } | ||
| 175 | new_fid = v9fs_fid_create(v9ses, fid); | ||
| 176 | if (new_fid == NULL) { | ||
| 177 | dprintk(DEBUG_ERROR, "out of memory\n"); | ||
| 178 | new_fid = ERR_PTR(-ENOMEM); | ||
| 179 | } | ||
| 180 | Free_Fcall: | ||
| 181 | kfree(fcall); | ||
| 182 | } | ||
| 183 | |||
| 184 | Release_Fid: | ||
| 185 | up(&base_fid->lock); | ||
| 186 | return new_fid; | ||
| 187 | } | ||
| 188 | |||
| 189 | void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid) | ||
| 190 | { | ||
| 191 | v9fs_t_clunk(v9ses, fid->fid); | ||
| 192 | v9fs_fid_destroy(fid); | ||
| 193 | } | ||
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index aa974d6875c3..48fc170c26c8 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
| @@ -30,6 +30,8 @@ struct v9fs_fid { | |||
| 30 | struct list_head list; /* list of fids associated with a dentry */ | 30 | struct list_head list; /* list of fids associated with a dentry */ |
| 31 | struct list_head active; /* XXX - debug */ | 31 | struct list_head active; /* XXX - debug */ |
| 32 | 32 | ||
| 33 | struct semaphore lock; | ||
| 34 | |||
| 33 | u32 fid; | 35 | u32 fid; |
| 34 | unsigned char fidopen; /* set when fid is opened */ | 36 | unsigned char fidopen; /* set when fid is opened */ |
| 35 | unsigned char fidclunked; /* set when fid has already been clunked */ | 37 | unsigned char fidclunked; /* set when fid has already been clunked */ |
| @@ -55,3 +57,6 @@ struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | |||
| 55 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 57 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
| 56 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); | 58 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); |
| 57 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); | 59 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); |
| 60 | struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry); | ||
| 61 | void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid); | ||
| 62 | |||
diff --git a/fs/9p/mux.c b/fs/9p/mux.c index 944273c3dbff..147ceef8e537 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c | |||
| @@ -132,8 +132,10 @@ int v9fs_mux_global_init(void) | |||
| 132 | v9fs_mux_poll_tasks[i].task = NULL; | 132 | v9fs_mux_poll_tasks[i].task = NULL; |
| 133 | 133 | ||
| 134 | v9fs_mux_wq = create_workqueue("v9fs"); | 134 | v9fs_mux_wq = create_workqueue("v9fs"); |
| 135 | if (!v9fs_mux_wq) | 135 | if (!v9fs_mux_wq) { |
| 136 | printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); | ||
| 136 | return -ENOMEM; | 137 | return -ENOMEM; |
| 138 | } | ||
| 137 | 139 | ||
| 138 | return 0; | 140 | return 0; |
| 139 | } | 141 | } |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 0b96fae8b479..d9b561ba5e58 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
| @@ -457,14 +457,19 @@ static int __init init_v9fs(void) | |||
| 457 | 457 | ||
| 458 | v9fs_error_init(); | 458 | v9fs_error_init(); |
| 459 | 459 | ||
| 460 | printk(KERN_INFO "Installing v9fs 9P2000 file system support\n"); | 460 | printk(KERN_INFO "Installing v9fs 9p2000 file system support\n"); |
| 461 | 461 | ||
| 462 | ret = v9fs_mux_global_init(); | 462 | ret = v9fs_mux_global_init(); |
| 463 | if (!ret) | 463 | if (ret) { |
| 464 | printk(KERN_WARNING "v9fs: starting mux failed\n"); | ||
| 464 | return ret; | 465 | return ret; |
| 466 | } | ||
| 465 | ret = register_filesystem(&v9fs_fs_type); | 467 | ret = register_filesystem(&v9fs_fs_type); |
| 466 | if (!ret) | 468 | if (ret) { |
| 469 | printk(KERN_WARNING "v9fs: registering file system failed\n"); | ||
| 467 | v9fs_mux_global_exit(); | 470 | v9fs_mux_global_exit(); |
| 471 | } | ||
| 472 | |||
| 468 | return ret; | 473 | return ret; |
| 469 | } | 474 | } |
| 470 | 475 | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index e86a07151280..9f17b0cacdd0 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -55,53 +55,22 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
| 55 | struct v9fs_fid *vfid; | 55 | struct v9fs_fid *vfid; |
| 56 | struct v9fs_fcall *fcall = NULL; | 56 | struct v9fs_fcall *fcall = NULL; |
| 57 | int omode; | 57 | int omode; |
| 58 | int fid = V9FS_NOFID; | ||
| 59 | int err; | 58 | int err; |
| 60 | 59 | ||
| 61 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); | 60 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
| 62 | 61 | ||
| 63 | vfid = v9fs_fid_lookup(file->f_path.dentry); | 62 | vfid = v9fs_fid_clone(file->f_path.dentry); |
| 64 | if (!vfid) { | 63 | if (IS_ERR(vfid)) |
| 65 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 64 | return PTR_ERR(vfid); |
| 66 | return -EBADF; | ||
| 67 | } | ||
| 68 | |||
| 69 | fid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 70 | if (fid < 0) { | ||
| 71 | eprintk(KERN_WARNING, "newfid fails!\n"); | ||
| 72 | return -ENOSPC; | ||
| 73 | } | ||
| 74 | 65 | ||
| 75 | err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall); | ||
| 76 | if (err < 0) { | ||
| 77 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | ||
| 78 | if (fcall && fcall->id == RWALK) | ||
| 79 | goto clunk_fid; | ||
| 80 | else { | ||
| 81 | v9fs_put_idpool(fid, &v9ses->fidpool); | ||
| 82 | goto free_fcall; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | kfree(fcall); | ||
| 86 | |||
| 87 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | ||
| 88 | /* translate open mode appropriately */ | ||
| 89 | omode = v9fs_uflags2omode(file->f_flags); | 66 | omode = v9fs_uflags2omode(file->f_flags); |
| 90 | err = v9fs_t_open(v9ses, fid, omode, &fcall); | 67 | err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall); |
| 91 | if (err < 0) { | 68 | if (err < 0) { |
| 92 | PRINT_FCALL_ERROR("open failed", fcall); | 69 | PRINT_FCALL_ERROR("open failed", fcall); |
| 93 | goto clunk_fid; | 70 | goto Clunk_Fid; |
| 94 | } | ||
| 95 | |||
| 96 | vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | ||
| 97 | if (vfid == NULL) { | ||
| 98 | dprintk(DEBUG_ERROR, "out of memory\n"); | ||
| 99 | err = -ENOMEM; | ||
| 100 | goto clunk_fid; | ||
| 101 | } | 71 | } |
| 102 | 72 | ||
| 103 | file->private_data = vfid; | 73 | file->private_data = vfid; |
| 104 | vfid->fid = fid; | ||
| 105 | vfid->fidopen = 1; | 74 | vfid->fidopen = 1; |
| 106 | vfid->fidclunked = 0; | 75 | vfid->fidclunked = 0; |
| 107 | vfid->iounit = fcall->params.ropen.iounit; | 76 | vfid->iounit = fcall->params.ropen.iounit; |
| @@ -112,10 +81,8 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
| 112 | 81 | ||
| 113 | return 0; | 82 | return 0; |
| 114 | 83 | ||
| 115 | clunk_fid: | 84 | Clunk_Fid: |
| 116 | v9fs_t_clunk(v9ses, fid); | 85 | v9fs_fid_clunk(v9ses, vfid); |
| 117 | |||
| 118 | free_fcall: | ||
| 119 | kfree(fcall); | 86 | kfree(fcall); |
| 120 | 87 | ||
| 121 | return err; | 88 | return err; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 18f26cdfd882..9109ba1d6969 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -416,12 +416,8 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 416 | sb = file_inode->i_sb; | 416 | sb = file_inode->i_sb; |
| 417 | v9ses = v9fs_inode2v9ses(file_inode); | 417 | v9ses = v9fs_inode2v9ses(file_inode); |
| 418 | v9fid = v9fs_fid_lookup(file); | 418 | v9fid = v9fs_fid_lookup(file); |
| 419 | 419 | if(IS_ERR(v9fid)) | |
| 420 | if (!v9fid) { | 420 | return PTR_ERR(v9fid); |
| 421 | dprintk(DEBUG_ERROR, | ||
| 422 | "no v9fs_fid\n"); | ||
| 423 | return -EBADF; | ||
| 424 | } | ||
| 425 | 421 | ||
| 426 | fid = v9fid->fid; | 422 | fid = v9fid->fid; |
| 427 | if (fid < 0) { | 423 | if (fid < 0) { |
| @@ -433,11 +429,13 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 433 | result = v9fs_t_remove(v9ses, fid, &fcall); | 429 | result = v9fs_t_remove(v9ses, fid, &fcall); |
| 434 | if (result < 0) { | 430 | if (result < 0) { |
| 435 | PRINT_FCALL_ERROR("remove fails", fcall); | 431 | PRINT_FCALL_ERROR("remove fails", fcall); |
| 432 | goto Error; | ||
| 436 | } | 433 | } |
| 437 | 434 | ||
| 438 | v9fs_put_idpool(fid, &v9ses->fidpool); | 435 | v9fs_put_idpool(fid, &v9ses->fidpool); |
| 439 | v9fs_fid_destroy(v9fid); | 436 | v9fs_fid_destroy(v9fid); |
| 440 | 437 | ||
| 438 | Error: | ||
| 441 | kfree(fcall); | 439 | kfree(fcall); |
| 442 | return result; | 440 | return result; |
| 443 | } | 441 | } |
| @@ -473,9 +471,13 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 473 | inode = NULL; | 471 | inode = NULL; |
| 474 | vfid = NULL; | 472 | vfid = NULL; |
| 475 | v9ses = v9fs_inode2v9ses(dir); | 473 | v9ses = v9fs_inode2v9ses(dir); |
| 476 | dfid = v9fs_fid_lookup(dentry->d_parent); | 474 | dfid = v9fs_fid_clone(dentry->d_parent); |
| 477 | perm = unixmode2p9mode(v9ses, mode); | 475 | if(IS_ERR(dfid)) { |
| 476 | err = PTR_ERR(dfid); | ||
| 477 | goto error; | ||
| 478 | } | ||
| 478 | 479 | ||
| 480 | perm = unixmode2p9mode(v9ses, mode); | ||
| 479 | if (nd && nd->flags & LOOKUP_OPEN) | 481 | if (nd && nd->flags & LOOKUP_OPEN) |
| 480 | flags = nd->intent.open.flags - 1; | 482 | flags = nd->intent.open.flags - 1; |
| 481 | else | 483 | else |
| @@ -485,9 +487,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 485 | perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit); | 487 | perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit); |
| 486 | 488 | ||
| 487 | if (err) | 489 | if (err) |
| 488 | goto error; | 490 | goto clunk_dfid; |
| 489 | 491 | ||
| 490 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | 492 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); |
| 493 | v9fs_fid_clunk(v9ses, dfid); | ||
| 491 | if (IS_ERR(vfid)) { | 494 | if (IS_ERR(vfid)) { |
| 492 | err = PTR_ERR(vfid); | 495 | err = PTR_ERR(vfid); |
| 493 | vfid = NULL; | 496 | vfid = NULL; |
| @@ -525,6 +528,9 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
| 525 | 528 | ||
| 526 | return 0; | 529 | return 0; |
| 527 | 530 | ||
| 531 | clunk_dfid: | ||
| 532 | v9fs_fid_clunk(v9ses, dfid); | ||
| 533 | |||
| 528 | error: | 534 | error: |
| 529 | if (vfid) | 535 | if (vfid) |
| 530 | v9fs_fid_destroy(vfid); | 536 | v9fs_fid_destroy(vfid); |
| @@ -551,7 +557,12 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 551 | inode = NULL; | 557 | inode = NULL; |
| 552 | vfid = NULL; | 558 | vfid = NULL; |
| 553 | v9ses = v9fs_inode2v9ses(dir); | 559 | v9ses = v9fs_inode2v9ses(dir); |
| 554 | dfid = v9fs_fid_lookup(dentry->d_parent); | 560 | dfid = v9fs_fid_clone(dentry->d_parent); |
| 561 | if(IS_ERR(dfid)) { | ||
| 562 | err = PTR_ERR(dfid); | ||
| 563 | goto error; | ||
| 564 | } | ||
| 565 | |||
| 555 | perm = unixmode2p9mode(v9ses, mode | S_IFDIR); | 566 | perm = unixmode2p9mode(v9ses, mode | S_IFDIR); |
| 556 | 567 | ||
| 557 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | 568 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, |
| @@ -559,37 +570,36 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 559 | 570 | ||
| 560 | if (err) { | 571 | if (err) { |
| 561 | dprintk(DEBUG_ERROR, "create error %d\n", err); | 572 | dprintk(DEBUG_ERROR, "create error %d\n", err); |
| 562 | goto error; | 573 | goto clean_up_dfid; |
| 563 | } | ||
| 564 | |||
| 565 | err = v9fs_t_clunk(v9ses, fid); | ||
| 566 | if (err) { | ||
| 567 | dprintk(DEBUG_ERROR, "clunk error %d\n", err); | ||
| 568 | goto error; | ||
| 569 | } | 574 | } |
| 570 | 575 | ||
| 571 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | 576 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); |
| 572 | if (IS_ERR(vfid)) { | 577 | if (IS_ERR(vfid)) { |
| 573 | err = PTR_ERR(vfid); | 578 | err = PTR_ERR(vfid); |
| 574 | vfid = NULL; | 579 | vfid = NULL; |
| 575 | goto error; | 580 | goto clean_up_dfid; |
| 576 | } | 581 | } |
| 577 | 582 | ||
| 583 | v9fs_fid_clunk(v9ses, dfid); | ||
| 578 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | 584 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); |
| 579 | if (IS_ERR(inode)) { | 585 | if (IS_ERR(inode)) { |
| 580 | err = PTR_ERR(inode); | 586 | err = PTR_ERR(inode); |
| 581 | inode = NULL; | 587 | inode = NULL; |
| 582 | goto error; | 588 | goto clean_up_fids; |
| 583 | } | 589 | } |
| 584 | 590 | ||
| 585 | dentry->d_op = &v9fs_dentry_operations; | 591 | dentry->d_op = &v9fs_dentry_operations; |
| 586 | d_instantiate(dentry, inode); | 592 | d_instantiate(dentry, inode); |
| 587 | return 0; | 593 | return 0; |
| 588 | 594 | ||
| 589 | error: | 595 | clean_up_fids: |
| 590 | if (vfid) | 596 | if (vfid) |
| 591 | v9fs_fid_destroy(vfid); | 597 | v9fs_fid_destroy(vfid); |
| 592 | 598 | ||
| 599 | clean_up_dfid: | ||
| 600 | v9fs_fid_clunk(v9ses, dfid); | ||
| 601 | |||
| 602 | error: | ||
| 593 | return err; | 603 | return err; |
| 594 | } | 604 | } |
| 595 | 605 | ||
| @@ -622,28 +632,23 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 622 | dentry->d_op = &v9fs_dentry_operations; | 632 | dentry->d_op = &v9fs_dentry_operations; |
| 623 | dirfid = v9fs_fid_lookup(dentry->d_parent); | 633 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
| 624 | 634 | ||
| 625 | if (!dirfid) { | 635 | if(IS_ERR(dirfid)) |
| 626 | dprintk(DEBUG_ERROR, "no dirfid\n"); | 636 | return ERR_PTR(PTR_ERR(dirfid)); |
| 627 | return ERR_PTR(-EINVAL); | ||
| 628 | } | ||
| 629 | 637 | ||
| 630 | dirfidnum = dirfid->fid; | 638 | dirfidnum = dirfid->fid; |
| 631 | 639 | ||
| 632 | if (dirfidnum < 0) { | ||
| 633 | dprintk(DEBUG_ERROR, "no dirfid for inode %p, #%lu\n", | ||
| 634 | dir, dir->i_ino); | ||
| 635 | return ERR_PTR(-EBADF); | ||
| 636 | } | ||
| 637 | |||
| 638 | newfid = v9fs_get_idpool(&v9ses->fidpool); | 640 | newfid = v9fs_get_idpool(&v9ses->fidpool); |
| 639 | if (newfid < 0) { | 641 | if (newfid < 0) { |
| 640 | eprintk(KERN_WARNING, "newfid fails!\n"); | 642 | eprintk(KERN_WARNING, "newfid fails!\n"); |
| 641 | return ERR_PTR(-ENOSPC); | 643 | result = -ENOSPC; |
| 644 | goto Release_Dirfid; | ||
| 642 | } | 645 | } |
| 643 | 646 | ||
| 644 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, | 647 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, |
| 645 | (char *)dentry->d_name.name, &fcall); | 648 | (char *)dentry->d_name.name, &fcall); |
| 646 | 649 | ||
| 650 | up(&dirfid->lock); | ||
| 651 | |||
| 647 | if (result < 0) { | 652 | if (result < 0) { |
| 648 | if (fcall && fcall->id == RWALK) | 653 | if (fcall && fcall->id == RWALK) |
| 649 | v9fs_t_clunk(v9ses, newfid); | 654 | v9fs_t_clunk(v9ses, newfid); |
| @@ -701,8 +706,12 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 701 | 706 | ||
| 702 | return NULL; | 707 | return NULL; |
| 703 | 708 | ||
| 704 | FreeFcall: | 709 | Release_Dirfid: |
| 710 | up(&dirfid->lock); | ||
| 711 | |||
| 712 | FreeFcall: | ||
| 705 | kfree(fcall); | 713 | kfree(fcall); |
| 714 | |||
| 706 | return ERR_PTR(result); | 715 | return ERR_PTR(result); |
| 707 | } | 716 | } |
| 708 | 717 | ||
| @@ -746,10 +755,8 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 746 | struct inode *old_inode = old_dentry->d_inode; | 755 | struct inode *old_inode = old_dentry->d_inode; |
| 747 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); | 756 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); |
| 748 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); | 757 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
| 749 | struct v9fs_fid *olddirfid = | 758 | struct v9fs_fid *olddirfid; |
| 750 | v9fs_fid_lookup(old_dentry->d_parent); | 759 | struct v9fs_fid *newdirfid; |
| 751 | struct v9fs_fid *newdirfid = | ||
| 752 | v9fs_fid_lookup(new_dentry->d_parent); | ||
| 753 | struct v9fs_wstat wstat; | 760 | struct v9fs_wstat wstat; |
| 754 | struct v9fs_fcall *fcall = NULL; | 761 | struct v9fs_fcall *fcall = NULL; |
| 755 | int fid = -1; | 762 | int fid = -1; |
| @@ -759,16 +766,26 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 759 | 766 | ||
| 760 | dprintk(DEBUG_VFS, "\n"); | 767 | dprintk(DEBUG_VFS, "\n"); |
| 761 | 768 | ||
| 762 | if ((!oldfid) || (!olddirfid) || (!newdirfid)) { | 769 | if(IS_ERR(oldfid)) |
| 763 | dprintk(DEBUG_ERROR, "problem with arguments\n"); | 770 | return PTR_ERR(oldfid); |
| 764 | return -EBADF; | 771 | |
| 772 | olddirfid = v9fs_fid_clone(old_dentry->d_parent); | ||
| 773 | if(IS_ERR(olddirfid)) { | ||
| 774 | retval = PTR_ERR(olddirfid); | ||
| 775 | goto Release_lock; | ||
| 776 | } | ||
| 777 | |||
| 778 | newdirfid = v9fs_fid_clone(new_dentry->d_parent); | ||
| 779 | if(IS_ERR(newdirfid)) { | ||
| 780 | retval = PTR_ERR(newdirfid); | ||
| 781 | goto Clunk_olddir; | ||
| 765 | } | 782 | } |
| 766 | 783 | ||
| 767 | /* 9P can only handle file rename in the same directory */ | 784 | /* 9P can only handle file rename in the same directory */ |
| 768 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { | 785 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { |
| 769 | dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); | 786 | dprintk(DEBUG_ERROR, "old dir and new dir are different\n"); |
| 770 | retval = -EPERM; | 787 | retval = -EXDEV; |
| 771 | goto FreeFcallnBail; | 788 | goto Clunk_newdir; |
| 772 | } | 789 | } |
| 773 | 790 | ||
| 774 | fid = oldfid->fid; | 791 | fid = oldfid->fid; |
| @@ -779,7 +796,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 779 | dprintk(DEBUG_ERROR, "no fid for old file #%lu\n", | 796 | dprintk(DEBUG_ERROR, "no fid for old file #%lu\n", |
| 780 | old_inode->i_ino); | 797 | old_inode->i_ino); |
| 781 | retval = -EBADF; | 798 | retval = -EBADF; |
| 782 | goto FreeFcallnBail; | 799 | goto Clunk_newdir; |
| 783 | } | 800 | } |
| 784 | 801 | ||
| 785 | v9fs_blank_wstat(&wstat); | 802 | v9fs_blank_wstat(&wstat); |
| @@ -788,11 +805,20 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 788 | 805 | ||
| 789 | retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); | 806 | retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall); |
| 790 | 807 | ||
| 791 | FreeFcallnBail: | ||
| 792 | if (retval < 0) | 808 | if (retval < 0) |
| 793 | PRINT_FCALL_ERROR("wstat error", fcall); | 809 | PRINT_FCALL_ERROR("wstat error", fcall); |
| 794 | 810 | ||
| 795 | kfree(fcall); | 811 | kfree(fcall); |
| 812 | |||
| 813 | Clunk_newdir: | ||
| 814 | v9fs_fid_clunk(v9ses, newdirfid); | ||
| 815 | |||
| 816 | Clunk_olddir: | ||
| 817 | v9fs_fid_clunk(v9ses, olddirfid); | ||
| 818 | |||
| 819 | Release_lock: | ||
| 820 | up(&oldfid->lock); | ||
| 821 | |||
| 796 | return retval; | 822 | return retval; |
| 797 | } | 823 | } |
| 798 | 824 | ||
| @@ -810,15 +836,12 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 810 | { | 836 | { |
| 811 | struct v9fs_fcall *fcall = NULL; | 837 | struct v9fs_fcall *fcall = NULL; |
| 812 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 838 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 813 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 839 | struct v9fs_fid *fid = v9fs_fid_clone(dentry); |
| 814 | int err = -EPERM; | 840 | int err = -EPERM; |
| 815 | 841 | ||
| 816 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); | 842 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); |
| 817 | if (!fid) { | 843 | if(IS_ERR(fid)) |
| 818 | dprintk(DEBUG_ERROR, | 844 | return PTR_ERR(fid); |
| 819 | "couldn't find fid associated with dentry\n"); | ||
| 820 | return -EBADF; | ||
| 821 | } | ||
| 822 | 845 | ||
| 823 | err = v9fs_t_stat(v9ses, fid->fid, &fcall); | 846 | err = v9fs_t_stat(v9ses, fid->fid, &fcall); |
| 824 | 847 | ||
| @@ -831,6 +854,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 831 | } | 854 | } |
| 832 | 855 | ||
| 833 | kfree(fcall); | 856 | kfree(fcall); |
| 857 | v9fs_fid_clunk(v9ses, fid); | ||
| 834 | return err; | 858 | return err; |
| 835 | } | 859 | } |
| 836 | 860 | ||
| @@ -844,18 +868,14 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 844 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | 868 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) |
| 845 | { | 869 | { |
| 846 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 870 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 847 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 871 | struct v9fs_fid *fid = v9fs_fid_clone(dentry); |
| 848 | struct v9fs_fcall *fcall = NULL; | 872 | struct v9fs_fcall *fcall = NULL; |
| 849 | struct v9fs_wstat wstat; | 873 | struct v9fs_wstat wstat; |
| 850 | int res = -EPERM; | 874 | int res = -EPERM; |
| 851 | 875 | ||
| 852 | dprintk(DEBUG_VFS, "\n"); | 876 | dprintk(DEBUG_VFS, "\n"); |
| 853 | 877 | if(IS_ERR(fid)) | |
| 854 | if (!fid) { | 878 | return PTR_ERR(fid); |
| 855 | dprintk(DEBUG_ERROR, | ||
| 856 | "Couldn't find fid associated with dentry\n"); | ||
| 857 | return -EBADF; | ||
| 858 | } | ||
| 859 | 879 | ||
| 860 | v9fs_blank_wstat(&wstat); | 880 | v9fs_blank_wstat(&wstat); |
| 861 | if (iattr->ia_valid & ATTR_MODE) | 881 | if (iattr->ia_valid & ATTR_MODE) |
| @@ -887,6 +907,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
| 887 | if (res >= 0) | 907 | if (res >= 0) |
| 888 | res = inode_setattr(dentry->d_inode, iattr); | 908 | res = inode_setattr(dentry->d_inode, iattr); |
| 889 | 909 | ||
| 910 | v9fs_fid_clunk(v9ses, fid); | ||
| 890 | return res; | 911 | return res; |
| 891 | } | 912 | } |
| 892 | 913 | ||
| @@ -987,18 +1008,15 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 987 | 1008 | ||
| 988 | struct v9fs_fcall *fcall = NULL; | 1009 | struct v9fs_fcall *fcall = NULL; |
| 989 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 1010 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 990 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); | 1011 | struct v9fs_fid *fid = v9fs_fid_clone(dentry); |
| 991 | 1012 | ||
| 992 | if (!fid) { | 1013 | if(IS_ERR(fid)) |
| 993 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); | 1014 | return PTR_ERR(fid); |
| 994 | retval = -EBADF; | ||
| 995 | goto FreeFcall; | ||
| 996 | } | ||
| 997 | 1015 | ||
| 998 | if (!v9ses->extended) { | 1016 | if (!v9ses->extended) { |
| 999 | retval = -EBADF; | 1017 | retval = -EBADF; |
| 1000 | dprintk(DEBUG_ERROR, "not extended\n"); | 1018 | dprintk(DEBUG_ERROR, "not extended\n"); |
| 1001 | goto FreeFcall; | 1019 | goto ClunkFid; |
| 1002 | } | 1020 | } |
| 1003 | 1021 | ||
| 1004 | dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name); | 1022 | dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name); |
| @@ -1009,8 +1027,10 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1009 | goto FreeFcall; | 1027 | goto FreeFcall; |
| 1010 | } | 1028 | } |
| 1011 | 1029 | ||
| 1012 | if (!fcall) | 1030 | if (!fcall) { |
| 1013 | return -EIO; | 1031 | retval = -EIO; |
| 1032 | goto ClunkFid; | ||
| 1033 | } | ||
| 1014 | 1034 | ||
| 1015 | if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { | 1035 | if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) { |
| 1016 | retval = -EINVAL; | 1036 | retval = -EINVAL; |
| @@ -1028,9 +1048,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1028 | fcall->params.rstat.stat.extension.str, buffer); | 1048 | fcall->params.rstat.stat.extension.str, buffer); |
| 1029 | retval = buflen; | 1049 | retval = buflen; |
| 1030 | 1050 | ||
| 1031 | FreeFcall: | 1051 | FreeFcall: |
| 1032 | kfree(fcall); | 1052 | kfree(fcall); |
| 1033 | 1053 | ||
| 1054 | ClunkFid: | ||
| 1055 | v9fs_fid_clunk(v9ses, fid); | ||
| 1056 | |||
| 1034 | return retval; | 1057 | return retval; |
| 1035 | } | 1058 | } |
| 1036 | 1059 | ||
| @@ -1123,52 +1146,58 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
| 1123 | int err; | 1146 | int err; |
| 1124 | u32 fid, perm; | 1147 | u32 fid, perm; |
| 1125 | struct v9fs_session_info *v9ses; | 1148 | struct v9fs_session_info *v9ses; |
| 1126 | struct v9fs_fid *dfid, *vfid; | 1149 | struct v9fs_fid *dfid, *vfid = NULL; |
| 1127 | struct inode *inode; | 1150 | struct inode *inode = NULL; |
| 1128 | 1151 | ||
| 1129 | inode = NULL; | ||
| 1130 | vfid = NULL; | ||
| 1131 | v9ses = v9fs_inode2v9ses(dir); | 1152 | v9ses = v9fs_inode2v9ses(dir); |
| 1132 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
| 1133 | perm = unixmode2p9mode(v9ses, mode); | ||
| 1134 | |||
| 1135 | if (!v9ses->extended) { | 1153 | if (!v9ses->extended) { |
| 1136 | dprintk(DEBUG_ERROR, "not extended\n"); | 1154 | dprintk(DEBUG_ERROR, "not extended\n"); |
| 1137 | return -EPERM; | 1155 | return -EPERM; |
| 1138 | } | 1156 | } |
| 1139 | 1157 | ||
| 1158 | dfid = v9fs_fid_clone(dentry->d_parent); | ||
| 1159 | if(IS_ERR(dfid)) { | ||
| 1160 | err = PTR_ERR(dfid); | ||
| 1161 | goto error; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | perm = unixmode2p9mode(v9ses, mode); | ||
| 1165 | |||
| 1140 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | 1166 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, |
| 1141 | perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL); | 1167 | perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL); |
| 1142 | 1168 | ||
| 1143 | if (err) | 1169 | if (err) |
| 1144 | goto error; | 1170 | goto clunk_dfid; |
| 1145 | 1171 | ||
| 1146 | err = v9fs_t_clunk(v9ses, fid); | 1172 | err = v9fs_t_clunk(v9ses, fid); |
| 1147 | if (err) | 1173 | if (err) |
| 1148 | goto error; | 1174 | goto clunk_dfid; |
| 1149 | 1175 | ||
| 1150 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | 1176 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); |
| 1151 | if (IS_ERR(vfid)) { | 1177 | if (IS_ERR(vfid)) { |
| 1152 | err = PTR_ERR(vfid); | 1178 | err = PTR_ERR(vfid); |
| 1153 | vfid = NULL; | 1179 | vfid = NULL; |
| 1154 | goto error; | 1180 | goto clunk_dfid; |
| 1155 | } | 1181 | } |
| 1156 | 1182 | ||
| 1157 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | 1183 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); |
| 1158 | if (IS_ERR(inode)) { | 1184 | if (IS_ERR(inode)) { |
| 1159 | err = PTR_ERR(inode); | 1185 | err = PTR_ERR(inode); |
| 1160 | inode = NULL; | 1186 | inode = NULL; |
| 1161 | goto error; | 1187 | goto free_vfid; |
| 1162 | } | 1188 | } |
| 1163 | 1189 | ||
| 1164 | dentry->d_op = &v9fs_dentry_operations; | 1190 | dentry->d_op = &v9fs_dentry_operations; |
| 1165 | d_instantiate(dentry, inode); | 1191 | d_instantiate(dentry, inode); |
| 1166 | return 0; | 1192 | return 0; |
| 1167 | 1193 | ||
| 1168 | error: | 1194 | free_vfid: |
| 1169 | if (vfid) | 1195 | v9fs_fid_destroy(vfid); |
| 1170 | v9fs_fid_destroy(vfid); | 1196 | |
| 1197 | clunk_dfid: | ||
| 1198 | v9fs_fid_clunk(v9ses, dfid); | ||
| 1171 | 1199 | ||
| 1200 | error: | ||
| 1172 | return err; | 1201 | return err; |
| 1173 | 1202 | ||
| 1174 | } | 1203 | } |
| @@ -1209,26 +1238,29 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1209 | struct dentry *dentry) | 1238 | struct dentry *dentry) |
| 1210 | { | 1239 | { |
| 1211 | int retval; | 1240 | int retval; |
| 1241 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | ||
| 1212 | struct v9fs_fid *oldfid; | 1242 | struct v9fs_fid *oldfid; |
| 1213 | char *name; | 1243 | char *name; |
| 1214 | 1244 | ||
| 1215 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, | 1245 | dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name, |
| 1216 | old_dentry->d_name.name); | 1246 | old_dentry->d_name.name); |
| 1217 | 1247 | ||
| 1218 | oldfid = v9fs_fid_lookup(old_dentry); | 1248 | oldfid = v9fs_fid_clone(old_dentry); |
| 1219 | if (!oldfid) { | 1249 | if(IS_ERR(oldfid)) |
| 1220 | dprintk(DEBUG_ERROR, "can't find oldfid\n"); | 1250 | return PTR_ERR(oldfid); |
| 1221 | return -EPERM; | ||
| 1222 | } | ||
| 1223 | 1251 | ||
| 1224 | name = __getname(); | 1252 | name = __getname(); |
| 1225 | if (unlikely(!name)) | 1253 | if (unlikely(!name)) { |
| 1226 | return -ENOMEM; | 1254 | retval = -ENOMEM; |
| 1255 | goto clunk_fid; | ||
| 1256 | } | ||
| 1227 | 1257 | ||
| 1228 | sprintf(name, "%d\n", oldfid->fid); | 1258 | sprintf(name, "%d\n", oldfid->fid); |
| 1229 | retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); | 1259 | retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name); |
| 1230 | __putname(name); | 1260 | __putname(name); |
| 1231 | 1261 | ||
| 1262 | clunk_fid: | ||
| 1263 | v9fs_fid_clunk(v9ses, oldfid); | ||
| 1232 | return retval; | 1264 | return retval; |
| 1233 | } | 1265 | } |
| 1234 | 1266 | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7cb28720f90e..669dbe5b0317 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -682,6 +682,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 682 | retval = PTR_ERR(interpreter); | 682 | retval = PTR_ERR(interpreter); |
| 683 | if (IS_ERR(interpreter)) | 683 | if (IS_ERR(interpreter)) |
| 684 | goto out_free_interp; | 684 | goto out_free_interp; |
| 685 | |||
| 686 | /* | ||
| 687 | * If the binary is not readable then enforce | ||
| 688 | * mm->dumpable = 0 regardless of the interpreter's | ||
| 689 | * permissions. | ||
| 690 | */ | ||
| 691 | if (file_permission(interpreter, MAY_READ) < 0) | ||
| 692 | bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; | ||
| 693 | |||
| 685 | retval = kernel_read(interpreter, 0, bprm->buf, | 694 | retval = kernel_read(interpreter, 0, bprm->buf, |
| 686 | BINPRM_BUF_SIZE); | 695 | BINPRM_BUF_SIZE); |
| 687 | if (retval != BINPRM_BUF_SIZE) { | 696 | if (retval != BINPRM_BUF_SIZE) { |
| @@ -1178,6 +1187,10 @@ static int dump_seek(struct file *file, loff_t off) | |||
| 1178 | */ | 1187 | */ |
| 1179 | static int maydump(struct vm_area_struct *vma) | 1188 | static int maydump(struct vm_area_struct *vma) |
| 1180 | { | 1189 | { |
| 1190 | /* The vma can be set up to tell us the answer directly. */ | ||
| 1191 | if (vma->vm_flags & VM_ALWAYSDUMP) | ||
| 1192 | return 1; | ||
| 1193 | |||
| 1181 | /* Do not dump I/O mapped devices or special mappings */ | 1194 | /* Do not dump I/O mapped devices or special mappings */ |
| 1182 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) | 1195 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) |
| 1183 | return 0; | 1196 | return 0; |
| @@ -1424,6 +1437,32 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
| 1424 | return sz; | 1437 | return sz; |
| 1425 | } | 1438 | } |
| 1426 | 1439 | ||
| 1440 | static struct vm_area_struct *first_vma(struct task_struct *tsk, | ||
| 1441 | struct vm_area_struct *gate_vma) | ||
| 1442 | { | ||
| 1443 | struct vm_area_struct *ret = tsk->mm->mmap; | ||
| 1444 | |||
| 1445 | if (ret) | ||
| 1446 | return ret; | ||
| 1447 | return gate_vma; | ||
| 1448 | } | ||
| 1449 | /* | ||
| 1450 | * Helper function for iterating across a vma list. It ensures that the caller | ||
| 1451 | * will visit `gate_vma' prior to terminating the search. | ||
| 1452 | */ | ||
| 1453 | static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma, | ||
| 1454 | struct vm_area_struct *gate_vma) | ||
| 1455 | { | ||
| 1456 | struct vm_area_struct *ret; | ||
| 1457 | |||
| 1458 | ret = this_vma->vm_next; | ||
| 1459 | if (ret) | ||
| 1460 | return ret; | ||
| 1461 | if (this_vma == gate_vma) | ||
| 1462 | return NULL; | ||
| 1463 | return gate_vma; | ||
| 1464 | } | ||
| 1465 | |||
| 1427 | /* | 1466 | /* |
| 1428 | * Actual dumper | 1467 | * Actual dumper |
| 1429 | * | 1468 | * |
| @@ -1439,7 +1478,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1439 | int segs; | 1478 | int segs; |
| 1440 | size_t size = 0; | 1479 | size_t size = 0; |
| 1441 | int i; | 1480 | int i; |
| 1442 | struct vm_area_struct *vma; | 1481 | struct vm_area_struct *vma, *gate_vma; |
| 1443 | struct elfhdr *elf = NULL; | 1482 | struct elfhdr *elf = NULL; |
| 1444 | loff_t offset = 0, dataoff, foffset; | 1483 | loff_t offset = 0, dataoff, foffset; |
| 1445 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; | 1484 | unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur; |
| @@ -1525,6 +1564,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1525 | segs += ELF_CORE_EXTRA_PHDRS; | 1564 | segs += ELF_CORE_EXTRA_PHDRS; |
| 1526 | #endif | 1565 | #endif |
| 1527 | 1566 | ||
| 1567 | gate_vma = get_gate_vma(current); | ||
| 1568 | if (gate_vma != NULL) | ||
| 1569 | segs++; | ||
| 1570 | |||
| 1528 | /* Set up header */ | 1571 | /* Set up header */ |
| 1529 | fill_elf_header(elf, segs + 1); /* including notes section */ | 1572 | fill_elf_header(elf, segs + 1); /* including notes section */ |
| 1530 | 1573 | ||
| @@ -1592,7 +1635,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1592 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); | 1635 | dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); |
| 1593 | 1636 | ||
| 1594 | /* Write program headers for segments dump */ | 1637 | /* Write program headers for segments dump */ |
| 1595 | for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { | 1638 | for (vma = first_vma(current, gate_vma); vma != NULL; |
| 1639 | vma = next_vma(vma, gate_vma)) { | ||
| 1596 | struct elf_phdr phdr; | 1640 | struct elf_phdr phdr; |
| 1597 | size_t sz; | 1641 | size_t sz; |
| 1598 | 1642 | ||
| @@ -1641,7 +1685,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) | |||
| 1641 | /* Align to page */ | 1685 | /* Align to page */ |
| 1642 | DUMP_SEEK(dataoff - foffset); | 1686 | DUMP_SEEK(dataoff - foffset); |
| 1643 | 1687 | ||
| 1644 | for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { | 1688 | for (vma = first_vma(current, gate_vma); vma != NULL; |
| 1689 | vma = next_vma(vma, gate_vma)) { | ||
| 1645 | unsigned long addr; | 1690 | unsigned long addr; |
| 1646 | 1691 | ||
| 1647 | if (!maydump(vma)) | 1692 | if (!maydump(vma)) |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 6e6d4568d548..a4d933a51208 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
| @@ -234,6 +234,14 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
| 234 | goto error; | 234 | goto error; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | /* | ||
| 238 | * If the binary is not readable then enforce | ||
| 239 | * mm->dumpable = 0 regardless of the interpreter's | ||
| 240 | * permissions. | ||
| 241 | */ | ||
| 242 | if (file_permission(interpreter, MAY_READ) < 0) | ||
| 243 | bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; | ||
| 244 | |||
| 237 | retval = kernel_read(interpreter, 0, bprm->buf, | 245 | retval = kernel_read(interpreter, 0, bprm->buf, |
| 238 | BINPRM_BUF_SIZE); | 246 | BINPRM_BUF_SIZE); |
| 239 | if (retval < 0) | 247 | if (retval < 0) |
diff --git a/fs/buffer.c b/fs/buffer.c index 3b116078b4c3..460f1c43238e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -2834,7 +2834,7 @@ int try_to_free_buffers(struct page *page) | |||
| 2834 | int ret = 0; | 2834 | int ret = 0; |
| 2835 | 2835 | ||
| 2836 | BUG_ON(!PageLocked(page)); | 2836 | BUG_ON(!PageLocked(page)); |
| 2837 | if (PageDirty(page) || PageWriteback(page)) | 2837 | if (PageWriteback(page)) |
| 2838 | return 0; | 2838 | return 0; |
| 2839 | 2839 | ||
| 2840 | if (mapping == NULL) { /* can this still happen? */ | 2840 | if (mapping == NULL) { /* can this still happen? */ |
| @@ -2845,6 +2845,19 @@ int try_to_free_buffers(struct page *page) | |||
| 2845 | spin_lock(&mapping->private_lock); | 2845 | spin_lock(&mapping->private_lock); |
| 2846 | ret = drop_buffers(page, &buffers_to_free); | 2846 | ret = drop_buffers(page, &buffers_to_free); |
| 2847 | spin_unlock(&mapping->private_lock); | 2847 | spin_unlock(&mapping->private_lock); |
| 2848 | |||
| 2849 | /* | ||
| 2850 | * If the filesystem writes its buffers by hand (eg ext3) | ||
| 2851 | * then we can have clean buffers against a dirty page. We | ||
| 2852 | * clean the page here; otherwise the VM will never notice | ||
| 2853 | * that the filesystem did any IO at all. | ||
| 2854 | * | ||
| 2855 | * Also, during truncate, discard_buffer will have marked all | ||
| 2856 | * the page's buffers clean. We discover that here and clean | ||
| 2857 | * the page also. | ||
| 2858 | */ | ||
| 2859 | if (ret) | ||
| 2860 | cancel_dirty_page(page, PAGE_CACHE_SIZE); | ||
| 2848 | out: | 2861 | out: |
| 2849 | if (buffers_to_free) { | 2862 | if (buffers_to_free) { |
| 2850 | struct buffer_head *bh = buffers_to_free; | 2863 | struct buffer_head *bh = buffers_to_free; |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c403b66ec83c..a4b142a6a2c7 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
| @@ -251,8 +251,19 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
| 251 | WARN_ON(inode->i_state & I_WILL_FREE); | 251 | WARN_ON(inode->i_state & I_WILL_FREE); |
| 252 | 252 | ||
| 253 | if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { | 253 | if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_LOCK)) { |
| 254 | struct address_space *mapping = inode->i_mapping; | ||
| 255 | int ret; | ||
| 256 | |||
| 254 | list_move(&inode->i_list, &inode->i_sb->s_dirty); | 257 | list_move(&inode->i_list, &inode->i_sb->s_dirty); |
| 255 | return 0; | 258 | |
| 259 | /* | ||
| 260 | * Even if we don't actually write the inode itself here, | ||
| 261 | * we can at least start some of the data writeout.. | ||
| 262 | */ | ||
| 263 | spin_unlock(&inode_lock); | ||
| 264 | ret = do_writepages(mapping, wbc); | ||
| 265 | spin_lock(&inode_lock); | ||
| 266 | return ret; | ||
| 256 | } | 267 | } |
| 257 | 268 | ||
| 258 | /* | 269 | /* |
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 277df40f098d..e695660921ec 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
| @@ -990,15 +990,16 @@ encode_entry(struct readdir_cd *ccd, const char *name, | |||
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | int | 992 | int |
| 993 | nfs3svc_encode_entry(struct readdir_cd *cd, const char *name, | 993 | nfs3svc_encode_entry(void *cd, const char *name, |
| 994 | int namlen, loff_t offset, ino_t ino, unsigned int d_type) | 994 | int namlen, loff_t offset, u64 ino, unsigned int d_type) |
| 995 | { | 995 | { |
| 996 | return encode_entry(cd, name, namlen, offset, ino, d_type, 0); | 996 | return encode_entry(cd, name, namlen, offset, ino, d_type, 0); |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | int | 999 | int |
| 1000 | nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name, | 1000 | nfs3svc_encode_entry_plus(void *cd, const char *name, |
| 1001 | int namlen, loff_t offset, ino_t ino, unsigned int d_type) | 1001 | int namlen, loff_t offset, u64 ino, |
| 1002 | unsigned int d_type) | ||
| 1002 | { | 1003 | { |
| 1003 | return encode_entry(cd, name, namlen, offset, ino, d_type, 1); | 1004 | return encode_entry(cd, name, namlen, offset, ino, d_type, 1); |
| 1004 | } | 1005 | } |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index fea46368afb2..18aa9440df14 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -1880,9 +1880,10 @@ nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) | |||
| 1880 | } | 1880 | } |
| 1881 | 1881 | ||
| 1882 | static int | 1882 | static int |
| 1883 | nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen, | 1883 | nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, |
| 1884 | loff_t offset, ino_t ino, unsigned int d_type) | 1884 | loff_t offset, u64 ino, unsigned int d_type) |
| 1885 | { | 1885 | { |
| 1886 | struct readdir_cd *ccd = ccdv; | ||
| 1886 | struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); | 1887 | struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); |
| 1887 | int buflen; | 1888 | int buflen; |
| 1888 | __be32 *p = cd->buffer; | 1889 | __be32 *p = cd->buffer; |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 0aaccb03bf76..fbf5d51947ea 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -72,7 +72,7 @@ static struct svc_program nfsd_acl_program = { | |||
| 72 | .pg_prog = NFS_ACL_PROGRAM, | 72 | .pg_prog = NFS_ACL_PROGRAM, |
| 73 | .pg_nvers = NFSD_ACL_NRVERS, | 73 | .pg_nvers = NFSD_ACL_NRVERS, |
| 74 | .pg_vers = nfsd_acl_versions, | 74 | .pg_vers = nfsd_acl_versions, |
| 75 | .pg_name = "nfsd", | 75 | .pg_name = "nfsacl", |
| 76 | .pg_class = "nfsd", | 76 | .pg_class = "nfsd", |
| 77 | .pg_stats = &nfsd_acl_svcstats, | 77 | .pg_stats = &nfsd_acl_svcstats, |
| 78 | .pg_authenticate = &svc_set_client, | 78 | .pg_authenticate = &svc_set_client, |
| @@ -118,16 +118,16 @@ int nfsd_vers(int vers, enum vers_op change) | |||
| 118 | switch(change) { | 118 | switch(change) { |
| 119 | case NFSD_SET: | 119 | case NFSD_SET: |
| 120 | nfsd_versions[vers] = nfsd_version[vers]; | 120 | nfsd_versions[vers] = nfsd_version[vers]; |
| 121 | break; | ||
| 122 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 121 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
| 123 | if (vers < NFSD_ACL_NRVERS) | 122 | if (vers < NFSD_ACL_NRVERS) |
| 124 | nfsd_acl_version[vers] = nfsd_acl_version[vers]; | 123 | nfsd_acl_versions[vers] = nfsd_acl_version[vers]; |
| 125 | #endif | 124 | #endif |
| 125 | break; | ||
| 126 | case NFSD_CLEAR: | 126 | case NFSD_CLEAR: |
| 127 | nfsd_versions[vers] = NULL; | 127 | nfsd_versions[vers] = NULL; |
| 128 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 128 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
| 129 | if (vers < NFSD_ACL_NRVERS) | 129 | if (vers < NFSD_ACL_NRVERS) |
| 130 | nfsd_acl_version[vers] = NULL; | 130 | nfsd_acl_versions[vers] = NULL; |
| 131 | #endif | 131 | #endif |
| 132 | break; | 132 | break; |
| 133 | case NFSD_TEST: | 133 | case NFSD_TEST: |
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index f5243f943996..6555c50d9006 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c | |||
| @@ -462,9 +462,10 @@ nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p, | |||
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | int | 464 | int |
| 465 | nfssvc_encode_entry(struct readdir_cd *ccd, const char *name, | 465 | nfssvc_encode_entry(void *ccdv, const char *name, |
| 466 | int namlen, loff_t offset, ino_t ino, unsigned int d_type) | 466 | int namlen, loff_t offset, u64 ino, unsigned int d_type) |
| 467 | { | 467 | { |
| 468 | struct readdir_cd *ccd = ccdv; | ||
| 468 | struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common); | 469 | struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common); |
| 469 | __be32 *p = cd->buffer; | 470 | __be32 *p = cd->buffer; |
| 470 | int buflen, slen; | 471 | int buflen, slen; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7a79c23aa6d4..5d32e5fa697e 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -822,7 +822,8 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset | |||
| 822 | rqstp->rq_res.page_len = size; | 822 | rqstp->rq_res.page_len = size; |
| 823 | } else if (page != pp[-1]) { | 823 | } else if (page != pp[-1]) { |
| 824 | get_page(page); | 824 | get_page(page); |
| 825 | put_page(*pp); | 825 | if (*pp) |
| 826 | put_page(*pp); | ||
| 826 | *pp = page; | 827 | *pp = page; |
| 827 | rqstp->rq_resused++; | 828 | rqstp->rq_resused++; |
| 828 | rqstp->rq_res.page_len += size; | 829 | rqstp->rq_res.page_len += size; |
| @@ -1244,7 +1245,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1244 | __be32 err; | 1245 | __be32 err; |
| 1245 | int host_err; | 1246 | int host_err; |
| 1246 | __u32 v_mtime=0, v_atime=0; | 1247 | __u32 v_mtime=0, v_atime=0; |
| 1247 | int v_mode=0; | ||
| 1248 | 1248 | ||
| 1249 | err = nfserr_perm; | 1249 | err = nfserr_perm; |
| 1250 | if (!flen) | 1250 | if (!flen) |
| @@ -1281,16 +1281,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1281 | goto out; | 1281 | goto out; |
| 1282 | 1282 | ||
| 1283 | if (createmode == NFS3_CREATE_EXCLUSIVE) { | 1283 | if (createmode == NFS3_CREATE_EXCLUSIVE) { |
| 1284 | /* while the verifier would fit in mtime+atime, | 1284 | /* solaris7 gets confused (bugid 4218508) if these have |
| 1285 | * solaris7 gets confused (bugid 4218508) if these have | 1285 | * the high bit set, so just clear the high bits. |
| 1286 | * the high bit set, so we use the mode as well | ||
| 1287 | */ | 1286 | */ |
| 1288 | v_mtime = verifier[0]&0x7fffffff; | 1287 | v_mtime = verifier[0]&0x7fffffff; |
| 1289 | v_atime = verifier[1]&0x7fffffff; | 1288 | v_atime = verifier[1]&0x7fffffff; |
| 1290 | v_mode = S_IFREG | ||
| 1291 | | ((verifier[0]&0x80000000) >> (32-7)) /* u+x */ | ||
| 1292 | | ((verifier[1]&0x80000000) >> (32-9)) /* u+r */ | ||
| 1293 | ; | ||
| 1294 | } | 1289 | } |
| 1295 | 1290 | ||
| 1296 | if (dchild->d_inode) { | 1291 | if (dchild->d_inode) { |
| @@ -1318,7 +1313,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1318 | case NFS3_CREATE_EXCLUSIVE: | 1313 | case NFS3_CREATE_EXCLUSIVE: |
| 1319 | if ( dchild->d_inode->i_mtime.tv_sec == v_mtime | 1314 | if ( dchild->d_inode->i_mtime.tv_sec == v_mtime |
| 1320 | && dchild->d_inode->i_atime.tv_sec == v_atime | 1315 | && dchild->d_inode->i_atime.tv_sec == v_atime |
| 1321 | && dchild->d_inode->i_mode == v_mode | ||
| 1322 | && dchild->d_inode->i_size == 0 ) | 1316 | && dchild->d_inode->i_size == 0 ) |
| 1323 | break; | 1317 | break; |
| 1324 | /* fallthru */ | 1318 | /* fallthru */ |
| @@ -1340,26 +1334,22 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 1340 | } | 1334 | } |
| 1341 | 1335 | ||
| 1342 | if (createmode == NFS3_CREATE_EXCLUSIVE) { | 1336 | if (createmode == NFS3_CREATE_EXCLUSIVE) { |
| 1343 | /* Cram the verifier into atime/mtime/mode */ | 1337 | /* Cram the verifier into atime/mtime */ |
| 1344 | iap->ia_valid = ATTR_MTIME|ATTR_ATIME | 1338 | iap->ia_valid = ATTR_MTIME|ATTR_ATIME |
| 1345 | | ATTR_MTIME_SET|ATTR_ATIME_SET | 1339 | | ATTR_MTIME_SET|ATTR_ATIME_SET; |
| 1346 | | ATTR_MODE; | ||
| 1347 | /* XXX someone who knows this better please fix it for nsec */ | 1340 | /* XXX someone who knows this better please fix it for nsec */ |
| 1348 | iap->ia_mtime.tv_sec = v_mtime; | 1341 | iap->ia_mtime.tv_sec = v_mtime; |
| 1349 | iap->ia_atime.tv_sec = v_atime; | 1342 | iap->ia_atime.tv_sec = v_atime; |
| 1350 | iap->ia_mtime.tv_nsec = 0; | 1343 | iap->ia_mtime.tv_nsec = 0; |
| 1351 | iap->ia_atime.tv_nsec = 0; | 1344 | iap->ia_atime.tv_nsec = 0; |
| 1352 | iap->ia_mode = v_mode; | ||
| 1353 | } | 1345 | } |
| 1354 | 1346 | ||
| 1355 | /* Set file attributes. | 1347 | /* Set file attributes. |
| 1356 | * Mode has already been set but we might need to reset it | ||
| 1357 | * for CREATE_EXCLUSIVE | ||
| 1358 | * Irix appears to send along the gid when it tries to | 1348 | * Irix appears to send along the gid when it tries to |
| 1359 | * implement setgid directories via NFS. Clear out all that cruft. | 1349 | * implement setgid directories via NFS. Clear out all that cruft. |
| 1360 | */ | 1350 | */ |
| 1361 | set_attr: | 1351 | set_attr: |
| 1362 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) { | 1352 | if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) { |
| 1363 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); | 1353 | __be32 err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); |
| 1364 | if (err2) | 1354 | if (err2) |
| 1365 | err = err2; | 1355 | err = err2; |
| @@ -1726,7 +1716,7 @@ out: | |||
| 1726 | */ | 1716 | */ |
| 1727 | __be32 | 1717 | __be32 |
| 1728 | nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, | 1718 | nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, |
| 1729 | struct readdir_cd *cdp, encode_dent_fn func) | 1719 | struct readdir_cd *cdp, filldir_t func) |
| 1730 | { | 1720 | { |
| 1731 | __be32 err; | 1721 | __be32 err; |
| 1732 | int host_err; | 1722 | int host_err; |
| @@ -1751,7 +1741,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, | |||
| 1751 | 1741 | ||
| 1752 | do { | 1742 | do { |
| 1753 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | 1743 | cdp->err = nfserr_eof; /* will be cleared on successful read */ |
| 1754 | host_err = vfs_readdir(file, (filldir_t) func, cdp); | 1744 | host_err = vfs_readdir(file, func, cdp); |
| 1755 | } while (host_err >=0 && cdp->err == nfs_ok); | 1745 | } while (host_err >=0 && cdp->err == nfs_ok); |
| 1756 | if (host_err) | 1746 | if (host_err) |
| 1757 | err = nfserrno(host_err); | 1747 | err = nfserrno(host_err); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 77a57b5799c4..ff7a66850602 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -371,9 +371,11 @@ static int mounts_open(struct inode *inode, struct file *file) | |||
| 371 | 371 | ||
| 372 | if (task) { | 372 | if (task) { |
| 373 | task_lock(task); | 373 | task_lock(task); |
| 374 | ns = task->nsproxy->mnt_ns; | 374 | if (task->nsproxy) { |
| 375 | if (ns) | 375 | ns = task->nsproxy->mnt_ns; |
| 376 | get_mnt_ns(ns); | 376 | if (ns) |
| 377 | get_mnt_ns(ns); | ||
| 378 | } | ||
| 377 | task_unlock(task); | 379 | task_unlock(task); |
| 378 | put_task_struct(task); | 380 | put_task_struct(task); |
| 379 | } | 381 | } |
