diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/fid.c | 73 | ||||
| -rw-r--r-- | fs/9p/fid.h | 5 | ||||
| -rw-r--r-- | fs/9p/v9fs_vfs.h | 1 | ||||
| -rw-r--r-- | fs/9p/vfs_file.c | 106 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 478 | ||||
| -rw-r--r-- | fs/9p/vfs_super.c | 12 |
6 files changed, 379 insertions, 296 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index eda449778fa5..c27f546dd25b 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | * | 40 | * |
| 41 | */ | 41 | */ |
| 42 | 42 | ||
| 43 | static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | 43 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) |
| 44 | { | 44 | { |
| 45 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 45 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
| 46 | dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, | 46 | dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, |
| @@ -68,14 +68,11 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | |||
| 68 | * | 68 | * |
| 69 | */ | 69 | */ |
| 70 | 70 | ||
| 71 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, | 71 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) |
| 72 | struct v9fs_session_info *v9ses, int fid, int create) | ||
| 73 | { | 72 | { |
| 74 | struct v9fs_fid *new; | 73 | struct v9fs_fid *new; |
| 75 | 74 | ||
| 76 | dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", | 75 | dprintk(DEBUG_9P, "fid create fid %d\n", fid); |
| 77 | dentry, fid, create); | ||
| 78 | |||
| 79 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 76 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
| 80 | if (new == NULL) { | 77 | if (new == NULL) { |
| 81 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | 78 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
| @@ -85,19 +82,13 @@ struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, | |||
| 85 | new->fid = fid; | 82 | new->fid = fid; |
| 86 | new->v9ses = v9ses; | 83 | new->v9ses = v9ses; |
| 87 | new->fidopen = 0; | 84 | new->fidopen = 0; |
| 88 | new->fidcreate = create; | ||
| 89 | new->fidclunked = 0; | 85 | new->fidclunked = 0; |
| 90 | new->iounit = 0; | 86 | new->iounit = 0; |
| 91 | new->rdir_pos = 0; | 87 | new->rdir_pos = 0; |
| 92 | new->rdir_fcall = NULL; | 88 | new->rdir_fcall = NULL; |
| 89 | INIT_LIST_HEAD(&new->list); | ||
| 93 | 90 | ||
| 94 | if (v9fs_fid_insert(new, dentry) == 0) | ||
| 95 | return new; | 91 | return new; |
| 96 | else { | ||
| 97 | dprintk(DEBUG_ERROR, "Problems inserting to dentry\n"); | ||
| 98 | kfree(new); | ||
| 99 | return NULL; | ||
| 100 | } | ||
| 101 | } | 92 | } |
| 102 | 93 | ||
| 103 | /** | 94 | /** |
| @@ -119,7 +110,7 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
| 119 | static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) | 110 | static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) |
| 120 | { | 111 | { |
| 121 | int fidnum, cfidnum, err; | 112 | int fidnum, cfidnum, err; |
| 122 | struct v9fs_fid *cfid; | 113 | struct v9fs_fid *cfid, *fid; |
| 123 | struct dentry *cde; | 114 | struct dentry *cde; |
| 124 | struct v9fs_session_info *v9ses; | 115 | struct v9fs_session_info *v9ses; |
| 125 | 116 | ||
| @@ -158,7 +149,16 @@ static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) | |||
| 158 | cde = cde->d_parent; | 149 | cde = cde->d_parent; |
| 159 | } | 150 | } |
| 160 | 151 | ||
| 161 | return v9fs_fid_create(dentry, v9ses, fidnum, 0); | 152 | fid = v9fs_fid_create(v9ses, fidnum); |
| 153 | if (fid) { | ||
| 154 | err = v9fs_fid_insert(fid, dentry); | ||
| 155 | if (err < 0) { | ||
| 156 | kfree(fid); | ||
| 157 | goto clunk_fid; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | return fid; | ||
| 162 | 162 | ||
| 163 | clunk_fid: | 163 | clunk_fid: |
| 164 | v9fs_t_clunk(v9ses, fidnum); | 164 | v9fs_t_clunk(v9ses, fidnum); |
| @@ -179,29 +179,12 @@ clunk_fid: | |||
| 179 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) | 179 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) |
| 180 | { | 180 | { |
| 181 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 181 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
| 182 | struct v9fs_fid *current_fid = NULL; | ||
| 183 | struct v9fs_fid *temp = NULL; | ||
| 184 | struct v9fs_fid *return_fid = NULL; | 182 | struct v9fs_fid *return_fid = NULL; |
| 185 | 183 | ||
| 186 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 184 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
| 187 | 185 | ||
| 188 | if (fid_list) { | 186 | if (fid_list) |
| 189 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { | 187 | return_fid = list_entry(fid_list->next, struct v9fs_fid, list); |
| 190 | if (!current_fid->fidcreate) { | ||
| 191 | return_fid = current_fid; | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | if (!return_fid) | ||
| 197 | return_fid = current_fid; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* we are at the root but didn't match */ | ||
| 201 | if ((!return_fid) && (dentry->d_parent == dentry)) { | ||
| 202 | /* TODO: clone attach with new uid */ | ||
| 203 | return_fid = current_fid; | ||
| 204 | } | ||
| 205 | 188 | ||
| 206 | if (!return_fid) { | 189 | if (!return_fid) { |
| 207 | struct dentry *par = current->fs->pwd->d_parent; | 190 | struct dentry *par = current->fs->pwd->d_parent; |
| @@ -228,25 +211,3 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
| 228 | 211 | ||
| 229 | return return_fid; | 212 | return return_fid; |
| 230 | } | 213 | } |
| 231 | |||
| 232 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) | ||
| 233 | { | ||
| 234 | struct list_head *fid_list; | ||
| 235 | struct v9fs_fid *fid, *ftmp, *ret; | ||
| 236 | |||
| 237 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); | ||
| 238 | fid_list = (struct list_head *)dentry->d_fsdata; | ||
| 239 | ret = NULL; | ||
| 240 | if (fid_list) { | ||
| 241 | list_for_each_entry_safe(fid, ftmp, fid_list, list) { | ||
| 242 | if (fid->fidcreate && fid->pid == current->pid) { | ||
| 243 | list_del(&fid->list); | ||
| 244 | ret = fid; | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | dprintk(DEBUG_9P, "return %p\n", ret); | ||
| 251 | return ret; | ||
| 252 | } | ||
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 84c673a44c83..7ccf0d064e25 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
| @@ -33,7 +33,6 @@ struct v9fs_fid { | |||
| 33 | 33 | ||
| 34 | u32 fid; | 34 | u32 fid; |
| 35 | unsigned char fidopen; /* set when fid is opened */ | 35 | unsigned char fidopen; /* set when fid is opened */ |
| 36 | unsigned char fidcreate; /* set when fid was just created */ | ||
| 37 | unsigned char fidclunked; /* set when fid has already been clunked */ | 36 | unsigned char fidclunked; /* set when fid has already been clunked */ |
| 38 | 37 | ||
| 39 | struct v9fs_qid qid; | 38 | struct v9fs_qid qid; |
| @@ -56,5 +55,5 @@ struct v9fs_fid { | |||
| 56 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); | 55 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); |
| 57 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | 56 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); |
| 58 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 57 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
| 59 | struct v9fs_fid *v9fs_fid_create(struct dentry *, | 58 | struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); |
| 60 | struct v9fs_session_info *v9ses, int fid, int create); | 59 | int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); |
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 69cf2905dc90..a759278acaae 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
| @@ -51,3 +51,4 @@ int v9fs_dir_release(struct inode *inode, struct file *filp); | |||
| 51 | int v9fs_file_open(struct inode *inode, struct file *file); | 51 | int v9fs_file_open(struct inode *inode, struct file *file); |
| 52 | void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); | 52 | void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); |
| 53 | void v9fs_dentry_release(struct dentry *); | 53 | void v9fs_dentry_release(struct dentry *); |
| 54 | int v9fs_uflags2omode(int uflags); | ||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index c7e14d917215..de3a129698da 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -53,94 +53,70 @@ | |||
| 53 | int v9fs_file_open(struct inode *inode, struct file *file) | 53 | int v9fs_file_open(struct inode *inode, struct file *file) |
| 54 | { | 54 | { |
| 55 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 55 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
| 56 | struct v9fs_fid *v9fid, *fid; | 56 | struct v9fs_fid *vfid; |
| 57 | struct v9fs_fcall *fcall = NULL; | 57 | struct v9fs_fcall *fcall = NULL; |
| 58 | int open_mode = 0; | 58 | int omode; |
| 59 | unsigned int iounit = 0; | 59 | int fid = V9FS_NOFID; |
| 60 | int newfid = -1; | 60 | int err; |
| 61 | long result = -1; | ||
| 62 | 61 | ||
| 63 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); | 62 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
| 64 | 63 | ||
| 65 | v9fid = v9fs_fid_get_created(file->f_dentry); | 64 | vfid = v9fs_fid_lookup(file->f_dentry); |
| 66 | if (!v9fid) | 65 | if (!vfid) { |
| 67 | v9fid = v9fs_fid_lookup(file->f_dentry); | ||
| 68 | |||
| 69 | if (!v9fid) { | ||
| 70 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 66 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); |
| 71 | return -EBADF; | 67 | return -EBADF; |
| 72 | } | 68 | } |
| 73 | 69 | ||
| 74 | if (!v9fid->fidcreate) { | 70 | fid = v9fs_get_idpool(&v9ses->fidpool); |
| 75 | fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 71 | if (fid < 0) { |
| 76 | if (fid == NULL) { | ||
| 77 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | ||
| 78 | return -ENOMEM; | ||
| 79 | } | ||
| 80 | |||
| 81 | fid->fidopen = 0; | ||
| 82 | fid->fidcreate = 0; | ||
| 83 | fid->fidclunked = 0; | ||
| 84 | fid->iounit = 0; | ||
| 85 | fid->v9ses = v9ses; | ||
| 86 | |||
| 87 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 88 | if (newfid < 0) { | ||
| 89 | eprintk(KERN_WARNING, "newfid fails!\n"); | 72 | eprintk(KERN_WARNING, "newfid fails!\n"); |
| 90 | return -ENOSPC; | 73 | return -ENOSPC; |
| 91 | } | 74 | } |
| 92 | 75 | ||
| 93 | result = | 76 | err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL); |
| 94 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); | 77 | if (err < 0) { |
| 95 | |||
| 96 | if (result < 0) { | ||
| 97 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
| 98 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | 78 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); |
| 99 | return -EBADF; | 79 | goto put_fid; |
| 80 | } | ||
| 81 | |||
| 82 | vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | ||
| 83 | if (vfid == NULL) { | ||
| 84 | dprintk(DEBUG_ERROR, "out of memory\n"); | ||
| 85 | goto clunk_fid; | ||
| 100 | } | 86 | } |
| 101 | 87 | ||
| 102 | fid->fid = newfid; | ||
| 103 | v9fid = fid; | ||
| 104 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | 88 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ |
| 105 | /* translate open mode appropriately */ | 89 | /* translate open mode appropriately */ |
| 106 | open_mode = file->f_flags & 0x3; | 90 | omode = v9fs_uflags2omode(file->f_flags); |
| 91 | err = v9fs_t_open(v9ses, fid, omode, &fcall); | ||
| 92 | if (err < 0) { | ||
| 93 | PRINT_FCALL_ERROR("open failed", fcall); | ||
| 94 | goto destroy_vfid; | ||
| 95 | } | ||
| 107 | 96 | ||
| 108 | if (file->f_flags & O_EXCL) | 97 | file->private_data = vfid; |
| 109 | open_mode |= V9FS_OEXCL; | 98 | vfid->fid = fid; |
| 99 | vfid->fidopen = 1; | ||
| 100 | vfid->fidclunked = 0; | ||
| 101 | vfid->iounit = fcall->params.ropen.iounit; | ||
| 102 | vfid->rdir_pos = 0; | ||
| 103 | vfid->rdir_fcall = NULL; | ||
| 104 | vfid->filp = file; | ||
| 105 | kfree(fcall); | ||
| 110 | 106 | ||
| 111 | if (v9ses->extended) { | 107 | return 0; |
| 112 | if (file->f_flags & O_TRUNC) | ||
| 113 | open_mode |= V9FS_OTRUNC; | ||
| 114 | 108 | ||
| 115 | if (file->f_flags & O_APPEND) | 109 | destroy_vfid: |
| 116 | open_mode |= V9FS_OAPPEND; | 110 | v9fs_fid_destroy(vfid); |
| 117 | } | ||
| 118 | 111 | ||
| 119 | result = v9fs_t_open(v9ses, newfid, open_mode, &fcall); | 112 | clunk_fid: |
| 120 | if (result < 0) { | 113 | v9fs_t_clunk(v9ses, fid); |
| 121 | PRINT_FCALL_ERROR("open failed", fcall); | ||
| 122 | kfree(fcall); | ||
| 123 | return result; | ||
| 124 | } | ||
| 125 | 114 | ||
| 126 | iounit = fcall->params.ropen.iounit; | 115 | put_fid: |
| 116 | v9fs_put_idpool(fid, &v9ses->fidpool); | ||
| 127 | kfree(fcall); | 117 | kfree(fcall); |
| 128 | } else { | ||
| 129 | /* create case */ | ||
| 130 | newfid = v9fid->fid; | ||
| 131 | iounit = v9fid->iounit; | ||
| 132 | v9fid->fidcreate = 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | file->private_data = v9fid; | ||
| 136 | |||
| 137 | v9fid->rdir_pos = 0; | ||
| 138 | v9fid->rdir_fcall = NULL; | ||
| 139 | v9fid->fidopen = 1; | ||
| 140 | v9fid->filp = file; | ||
| 141 | v9fid->iounit = iounit; | ||
| 142 | 118 | ||
| 143 | return 0; | 119 | return err; |
| 144 | } | 120 | } |
| 145 | 121 | ||
| 146 | /** | 122 | /** |
| @@ -289,9 +265,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
| 289 | total += result; | 265 | total += result; |
| 290 | } while (count); | 266 | } while (count); |
| 291 | 267 | ||
| 292 | if(inode->i_mapping->nrpages) | ||
| 293 | invalidate_inode_pages2(inode->i_mapping); | 268 | invalidate_inode_pages2(inode->i_mapping); |
| 294 | |||
| 295 | return total; | 269 | return total; |
| 296 | } | 270 | } |
| 297 | 271 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 63e5b0398e8b..dce729d42869 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -125,6 +125,38 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) | |||
| 125 | return res; | 125 | return res; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | int v9fs_uflags2omode(int uflags) | ||
| 129 | { | ||
| 130 | int ret; | ||
| 131 | |||
| 132 | ret = 0; | ||
| 133 | switch (uflags&3) { | ||
| 134 | default: | ||
| 135 | case O_RDONLY: | ||
| 136 | ret = V9FS_OREAD; | ||
| 137 | break; | ||
| 138 | |||
| 139 | case O_WRONLY: | ||
| 140 | ret = V9FS_OWRITE; | ||
| 141 | break; | ||
| 142 | |||
| 143 | case O_RDWR: | ||
| 144 | ret = V9FS_ORDWR; | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (uflags & O_EXCL) | ||
| 149 | ret |= V9FS_OEXCL; | ||
| 150 | |||
| 151 | if (uflags & O_TRUNC) | ||
| 152 | ret |= V9FS_OTRUNC; | ||
| 153 | |||
| 154 | if (uflags & O_APPEND) | ||
| 155 | ret |= V9FS_OAPPEND; | ||
| 156 | |||
| 157 | return ret; | ||
| 158 | } | ||
| 159 | |||
| 128 | /** | 160 | /** |
| 129 | * v9fs_blank_wstat - helper function to setup a 9P stat structure | 161 | * v9fs_blank_wstat - helper function to setup a 9P stat structure |
| 130 | * @v9ses: 9P session info (for determining extended mode) | 162 | * @v9ses: 9P session info (for determining extended mode) |
| @@ -163,7 +195,7 @@ v9fs_blank_wstat(struct v9fs_wstat *wstat) | |||
| 163 | 195 | ||
| 164 | struct inode *v9fs_get_inode(struct super_block *sb, int mode) | 196 | struct inode *v9fs_get_inode(struct super_block *sb, int mode) |
| 165 | { | 197 | { |
| 166 | struct inode *inode = NULL; | 198 | struct inode *inode; |
| 167 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 199 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
| 168 | 200 | ||
| 169 | dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); | 201 | dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); |
| @@ -222,171 +254,135 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
| 222 | return inode; | 254 | return inode; |
| 223 | } | 255 | } |
| 224 | 256 | ||
| 225 | /** | ||
| 226 | * v9fs_create - helper function to create files and directories | ||
| 227 | * @dir: directory inode file is being created in | ||
| 228 | * @file_dentry: dentry file is being created in | ||
| 229 | * @perm: permissions file is being created with | ||
| 230 | * @open_mode: resulting open mode for file | ||
| 231 | * | ||
| 232 | */ | ||
| 233 | |||
| 234 | static int | 257 | static int |
| 235 | v9fs_create(struct inode *dir, | 258 | v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, |
| 236 | struct dentry *file_dentry, | 259 | u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit) |
| 237 | unsigned int perm, unsigned int open_mode) | ||
| 238 | { | 260 | { |
| 239 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 261 | u32 fid; |
| 240 | struct super_block *sb = dir->i_sb; | ||
| 241 | struct v9fs_fid *dirfid = | ||
| 242 | v9fs_fid_lookup(file_dentry->d_parent); | ||
| 243 | struct v9fs_fid *fid = NULL; | ||
| 244 | struct inode *file_inode = NULL; | ||
| 245 | struct v9fs_fcall *fcall = NULL; | ||
| 246 | struct v9fs_qid qid; | ||
| 247 | int dirfidnum = -1; | ||
| 248 | long newfid = -1; | ||
| 249 | int result = 0; | ||
| 250 | unsigned int iounit = 0; | ||
| 251 | int wfidno = -1; | ||
| 252 | int err; | 262 | int err; |
| 263 | struct v9fs_fcall *fcall; | ||
| 253 | 264 | ||
| 254 | perm = unixmode2p9mode(v9ses, perm); | 265 | fid = v9fs_get_idpool(&v9ses->fidpool); |
| 255 | 266 | if (fid < 0) { | |
| 256 | dprintk(DEBUG_VFS, "dir: %p dentry: %p perm: %o mode: %o\n", dir, | ||
| 257 | file_dentry, perm, open_mode); | ||
| 258 | |||
| 259 | if (!dirfid) | ||
| 260 | return -EBADF; | ||
| 261 | |||
| 262 | dirfidnum = dirfid->fid; | ||
| 263 | if (dirfidnum < 0) { | ||
| 264 | dprintk(DEBUG_ERROR, "No fid for the directory #%lu\n", | ||
| 265 | dir->i_ino); | ||
| 266 | return -EBADF; | ||
| 267 | } | ||
| 268 | |||
| 269 | if (file_dentry->d_inode) { | ||
| 270 | dprintk(DEBUG_ERROR, | ||
| 271 | "Odd. There is an inode for dir %lu, name :%s:\n", | ||
| 272 | dir->i_ino, file_dentry->d_name.name); | ||
| 273 | return -EEXIST; | ||
| 274 | } | ||
| 275 | |||
| 276 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 277 | if (newfid < 0) { | ||
| 278 | eprintk(KERN_WARNING, "no free fids available\n"); | 267 | eprintk(KERN_WARNING, "no free fids available\n"); |
| 279 | return -ENOSPC; | 268 | err = -ENOSPC; |
| 269 | goto error; | ||
| 280 | } | 270 | } |
| 281 | 271 | ||
| 282 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); | 272 | err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall); |
| 283 | if (result < 0) { | 273 | if (err < 0) { |
| 284 | PRINT_FCALL_ERROR("clone error", fcall); | 274 | PRINT_FCALL_ERROR("clone error", fcall); |
| 285 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 275 | goto error; |
| 286 | newfid = -1; | ||
| 287 | goto CleanUpFid; | ||
| 288 | } | 276 | } |
| 289 | |||
| 290 | kfree(fcall); | 277 | kfree(fcall); |
| 291 | fcall = NULL; | ||
| 292 | 278 | ||
| 293 | result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, | 279 | err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall); |
| 294 | perm, open_mode, &fcall); | 280 | if (err < 0) { |
| 295 | if (result < 0) { | ||
| 296 | PRINT_FCALL_ERROR("create fails", fcall); | 281 | PRINT_FCALL_ERROR("create fails", fcall); |
| 297 | goto CleanUpFid; | 282 | goto error; |
| 298 | } | 283 | } |
| 299 | 284 | ||
| 300 | iounit = fcall->params.rcreate.iounit; | 285 | if (iounit) |
| 301 | qid = fcall->params.rcreate.qid; | 286 | *iounit = fcall->params.rcreate.iounit; |
| 287 | |||
| 288 | if (qid) | ||
| 289 | *qid = fcall->params.rcreate.qid; | ||
| 290 | |||
| 291 | if (fidp) | ||
| 292 | *fidp = fid; | ||
| 293 | |||
| 302 | kfree(fcall); | 294 | kfree(fcall); |
| 303 | fcall = NULL; | 295 | return 0; |
| 304 | 296 | ||
| 305 | if (!(perm&V9FS_DMDIR)) { | 297 | error: |
| 306 | fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); | 298 | if (fid >= 0) |
| 307 | dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); | 299 | v9fs_put_idpool(fid, &v9ses->fidpool); |
| 308 | if (!fid) { | ||
| 309 | result = -ENOMEM; | ||
| 310 | goto CleanUpFid; | ||
| 311 | } | ||
| 312 | 300 | ||
| 313 | fid->qid = qid; | 301 | kfree(fcall); |
| 314 | fid->iounit = iounit; | 302 | return err; |
| 315 | } else { | 303 | } |
| 316 | err = v9fs_t_clunk(v9ses, newfid); | 304 | |
| 317 | newfid = -1; | 305 | static struct v9fs_fid* |
| 318 | if (err < 0) | 306 | v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) |
| 319 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err); | 307 | { |
| 320 | } | 308 | int err; |
| 309 | u32 nfid; | ||
| 310 | struct v9fs_fid *ret; | ||
| 311 | struct v9fs_fcall *fcall; | ||
| 321 | 312 | ||
| 322 | /* walk to the newly created file and put the fid in the dentry */ | 313 | nfid = v9fs_get_idpool(&v9ses->fidpool); |
| 323 | wfidno = v9fs_get_idpool(&v9ses->fidpool); | 314 | if (nfid < 0) { |
| 324 | if (wfidno < 0) { | ||
| 325 | eprintk(KERN_WARNING, "no free fids available\n"); | 315 | eprintk(KERN_WARNING, "no free fids available\n"); |
| 326 | return -ENOSPC; | 316 | err = -ENOSPC; |
| 317 | goto error; | ||
| 327 | } | 318 | } |
| 328 | 319 | ||
| 329 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | 320 | err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, |
| 330 | (char *) file_dentry->d_name.name, &fcall); | 321 | &fcall); |
| 331 | if (result < 0) { | 322 | |
| 332 | PRINT_FCALL_ERROR("clone error", fcall); | 323 | if (err < 0) { |
| 333 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | 324 | PRINT_FCALL_ERROR("walk error", fcall); |
| 334 | wfidno = -1; | 325 | v9fs_put_idpool(nfid, &v9ses->fidpool); |
| 335 | goto CleanUpFid; | 326 | goto error; |
| 336 | } | 327 | } |
| 328 | |||
| 337 | kfree(fcall); | 329 | kfree(fcall); |
| 338 | fcall = NULL; | 330 | fcall = NULL; |
| 331 | ret = v9fs_fid_create(v9ses, nfid); | ||
| 332 | if (!ret) { | ||
| 333 | err = -ENOMEM; | ||
| 334 | goto clunk_fid; | ||
| 335 | } | ||
| 339 | 336 | ||
| 340 | if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { | 337 | err = v9fs_fid_insert(ret, dentry); |
| 341 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | 338 | if (err < 0) { |
| 342 | 339 | v9fs_fid_destroy(ret); | |
| 343 | goto CleanUpFid; | 340 | goto clunk_fid; |
| 344 | } | 341 | } |
| 345 | 342 | ||
| 346 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || | 343 | return ret; |
| 347 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || | ||
| 348 | (perm & V9FS_DMDEVICE)) | ||
| 349 | return 0; | ||
| 350 | 344 | ||
| 351 | result = v9fs_t_stat(v9ses, wfidno, &fcall); | 345 | clunk_fid: |
| 352 | if (result < 0) { | 346 | v9fs_t_clunk(v9ses, nfid); |
| 353 | PRINT_FCALL_ERROR("stat error", fcall); | 347 | |
| 354 | goto CleanUpFid; | 348 | error: |
| 355 | } | 349 | kfree(fcall); |
| 350 | return ERR_PTR(err); | ||
| 351 | } | ||
| 356 | 352 | ||
| 353 | struct inode * | ||
| 354 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, | ||
| 355 | struct super_block *sb) | ||
| 356 | { | ||
| 357 | int err, umode; | ||
| 358 | struct inode *ret; | ||
| 359 | struct v9fs_fcall *fcall; | ||
| 357 | 360 | ||
| 358 | file_inode = v9fs_get_inode(sb, | 361 | ret = NULL; |
| 359 | p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode)); | 362 | err = v9fs_t_stat(v9ses, fid, &fcall); |
| 363 | if (err) { | ||
| 364 | PRINT_FCALL_ERROR("stat error", fcall); | ||
| 365 | goto error; | ||
| 366 | } | ||
| 360 | 367 | ||
| 361 | if ((!file_inode) || IS_ERR(file_inode)) { | 368 | umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode); |
| 362 | dprintk(DEBUG_ERROR, "create inode failed\n"); | 369 | ret = v9fs_get_inode(sb, umode); |
| 363 | result = -EBADF; | 370 | if (IS_ERR(ret)) { |
| 364 | goto CleanUpFid; | 371 | err = PTR_ERR(ret); |
| 372 | ret = NULL; | ||
| 373 | goto error; | ||
| 365 | } | 374 | } |
| 366 | 375 | ||
| 367 | v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb); | 376 | v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb); |
| 368 | kfree(fcall); | 377 | kfree(fcall); |
| 369 | fcall = NULL; | 378 | return ret; |
| 370 | file_dentry->d_op = &v9fs_dentry_operations; | ||
| 371 | d_instantiate(file_dentry, file_inode); | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | 379 | ||
| 375 | CleanUpFid: | 380 | error: |
| 376 | kfree(fcall); | 381 | kfree(fcall); |
| 377 | fcall = NULL; | 382 | if (ret) |
| 383 | iput(ret); | ||
| 378 | 384 | ||
| 379 | if (newfid >= 0) { | 385 | return ERR_PTR(err); |
| 380 | err = v9fs_t_clunk(v9ses, newfid); | ||
| 381 | if (err < 0) | ||
| 382 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | ||
| 383 | } | ||
| 384 | if (wfidno >= 0) { | ||
| 385 | err = v9fs_t_clunk(v9ses, wfidno); | ||
| 386 | if (err < 0) | ||
| 387 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | ||
| 388 | } | ||
| 389 | return result; | ||
| 390 | } | 386 | } |
| 391 | 387 | ||
| 392 | /** | 388 | /** |
| @@ -440,20 +436,97 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 440 | return result; | 436 | return result; |
| 441 | } | 437 | } |
| 442 | 438 | ||
| 439 | static int | ||
| 440 | v9fs_open_created(struct inode *inode, struct file *file) | ||
| 441 | { | ||
| 442 | return 0; | ||
| 443 | } | ||
| 444 | |||
| 443 | /** | 445 | /** |
| 444 | * v9fs_vfs_create - VFS hook to create files | 446 | * v9fs_vfs_create - VFS hook to create files |
| 445 | * @inode: directory inode that is being deleted | 447 | * @inode: directory inode that is being deleted |
| 446 | * @dentry: dentry that is being deleted | 448 | * @dentry: dentry that is being deleted |
| 447 | * @perm: create permissions | 449 | * @mode: create permissions |
| 448 | * @nd: path information | 450 | * @nd: path information |
| 449 | * | 451 | * |
| 450 | */ | 452 | */ |
| 451 | 453 | ||
| 452 | static int | 454 | static int |
| 453 | v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, | 455 | v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, |
| 454 | struct nameidata *nd) | 456 | struct nameidata *nd) |
| 455 | { | 457 | { |
| 456 | return v9fs_create(inode, dentry, perm, O_RDWR); | 458 | int err; |
| 459 | u32 fid, perm, iounit; | ||
| 460 | int flags; | ||
| 461 | struct v9fs_session_info *v9ses; | ||
| 462 | struct v9fs_fid *dfid, *vfid, *ffid; | ||
| 463 | struct inode *inode; | ||
| 464 | struct v9fs_qid qid; | ||
| 465 | struct file *filp; | ||
| 466 | |||
| 467 | inode = NULL; | ||
| 468 | vfid = NULL; | ||
| 469 | v9ses = v9fs_inode2v9ses(dir); | ||
| 470 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
| 471 | perm = unixmode2p9mode(v9ses, mode); | ||
| 472 | |||
| 473 | if (nd && nd->flags & LOOKUP_OPEN) | ||
| 474 | flags = nd->intent.open.flags - 1; | ||
| 475 | else | ||
| 476 | flags = O_RDWR; | ||
| 477 | |||
| 478 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | ||
| 479 | perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit); | ||
| 480 | |||
| 481 | if (err) | ||
| 482 | goto error; | ||
| 483 | |||
| 484 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | ||
| 485 | if (IS_ERR(vfid)) { | ||
| 486 | err = PTR_ERR(vfid); | ||
| 487 | vfid = NULL; | ||
| 488 | goto error; | ||
| 489 | } | ||
| 490 | |||
| 491 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | ||
| 492 | if (IS_ERR(inode)) { | ||
| 493 | err = PTR_ERR(inode); | ||
| 494 | inode = NULL; | ||
| 495 | goto error; | ||
| 496 | } | ||
| 497 | |||
| 498 | dentry->d_op = &v9fs_dentry_operations; | ||
| 499 | d_instantiate(dentry, inode); | ||
| 500 | |||
| 501 | if (nd && nd->flags & LOOKUP_OPEN) { | ||
| 502 | ffid = v9fs_fid_create(v9ses, fid); | ||
| 503 | if (!ffid) | ||
| 504 | return -ENOMEM; | ||
| 505 | |||
| 506 | filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); | ||
| 507 | if (IS_ERR(filp)) { | ||
| 508 | v9fs_fid_destroy(ffid); | ||
| 509 | return PTR_ERR(filp); | ||
| 510 | } | ||
| 511 | |||
| 512 | ffid->rdir_pos = 0; | ||
| 513 | ffid->rdir_fcall = NULL; | ||
| 514 | ffid->fidopen = 1; | ||
| 515 | ffid->iounit = iounit; | ||
| 516 | ffid->filp = filp; | ||
| 517 | filp->private_data = ffid; | ||
| 518 | } | ||
| 519 | |||
| 520 | return 0; | ||
| 521 | |||
| 522 | error: | ||
| 523 | if (vfid) | ||
| 524 | v9fs_fid_destroy(vfid); | ||
| 525 | |||
| 526 | if (inode) | ||
| 527 | iput(inode); | ||
| 528 | |||
| 529 | return err; | ||
| 457 | } | 530 | } |
| 458 | 531 | ||
| 459 | /** | 532 | /** |
| @@ -464,9 +537,57 @@ v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, | |||
| 464 | * | 537 | * |
| 465 | */ | 538 | */ |
| 466 | 539 | ||
| 467 | static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode) | 540 | static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
| 468 | { | 541 | { |
| 469 | return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY); | 542 | int err; |
| 543 | u32 fid, perm; | ||
| 544 | struct v9fs_session_info *v9ses; | ||
| 545 | struct v9fs_fid *dfid, *vfid; | ||
| 546 | struct inode *inode; | ||
| 547 | |||
| 548 | inode = NULL; | ||
| 549 | vfid = NULL; | ||
| 550 | v9ses = v9fs_inode2v9ses(dir); | ||
| 551 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
| 552 | perm = unixmode2p9mode(v9ses, mode | S_IFDIR); | ||
| 553 | |||
| 554 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, | ||
| 555 | perm, V9FS_OREAD, &fid, NULL, NULL); | ||
| 556 | |||
| 557 | if (err) { | ||
| 558 | dprintk(DEBUG_ERROR, "create error %d\n", err); | ||
| 559 | goto error; | ||
| 560 | } | ||
| 561 | |||
| 562 | err = v9fs_t_clunk(v9ses, fid); | ||
| 563 | if (err) { | ||
| 564 | dprintk(DEBUG_ERROR, "clunk error %d\n", err); | ||
| 565 | goto error; | ||
| 566 | } | ||
| 567 | |||
| 568 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | ||
| 569 | if (IS_ERR(vfid)) { | ||
| 570 | err = PTR_ERR(vfid); | ||
| 571 | vfid = NULL; | ||
| 572 | goto error; | ||
| 573 | } | ||
| 574 | |||
| 575 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | ||
| 576 | if (IS_ERR(inode)) { | ||
| 577 | err = PTR_ERR(inode); | ||
| 578 | inode = NULL; | ||
| 579 | goto error; | ||
| 580 | } | ||
| 581 | |||
| 582 | dentry->d_op = &v9fs_dentry_operations; | ||
| 583 | d_instantiate(dentry, inode); | ||
| 584 | return 0; | ||
| 585 | |||
| 586 | error: | ||
| 587 | if (vfid) | ||
| 588 | v9fs_fid_destroy(vfid); | ||
| 589 | |||
| 590 | return err; | ||
| 470 | } | 591 | } |
| 471 | 592 | ||
| 472 | /** | 593 | /** |
| @@ -516,9 +637,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 516 | return ERR_PTR(-ENOSPC); | 637 | return ERR_PTR(-ENOSPC); |
| 517 | } | 638 | } |
| 518 | 639 | ||
| 519 | result = | 640 | result = v9fs_t_walk(v9ses, dirfidnum, newfid, |
| 520 | v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name, | 641 | (char *)dentry->d_name.name, NULL); |
| 521 | NULL); | ||
| 522 | if (result < 0) { | 642 | if (result < 0) { |
| 523 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 643 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
| 524 | if (result == -ENOENT) { | 644 | if (result == -ENOENT) { |
| @@ -551,13 +671,17 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 551 | 671 | ||
| 552 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); | 672 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); |
| 553 | 673 | ||
| 554 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); | 674 | fid = v9fs_fid_create(v9ses, newfid); |
| 555 | if (fid == NULL) { | 675 | if (fid == NULL) { |
| 556 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | 676 | dprintk(DEBUG_ERROR, "couldn't insert\n"); |
| 557 | result = -ENOMEM; | 677 | result = -ENOMEM; |
| 558 | goto FreeFcall; | 678 | goto FreeFcall; |
| 559 | } | 679 | } |
| 560 | 680 | ||
| 681 | result = v9fs_fid_insert(fid, dentry); | ||
| 682 | if (result < 0) | ||
| 683 | goto FreeFcall; | ||
| 684 | |||
| 561 | fid->qid = fcall->params.rstat.stat.qid; | 685 | fid->qid = fcall->params.rstat.stat.qid; |
| 562 | 686 | ||
| 563 | dentry->d_op = &v9fs_dentry_operations; | 687 | dentry->d_op = &v9fs_dentry_operations; |
| @@ -886,8 +1010,8 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 886 | } | 1010 | } |
| 887 | 1011 | ||
| 888 | /* copy extension buffer into buffer */ | 1012 | /* copy extension buffer into buffer */ |
| 889 | if (fcall->params.rstat.stat.extension.len+1 < buflen) | 1013 | if (fcall->params.rstat.stat.extension.len < buflen) |
| 890 | buflen = fcall->params.rstat.stat.extension.len + 1; | 1014 | buflen = fcall->params.rstat.stat.extension.len; |
| 891 | 1015 | ||
| 892 | memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); | 1016 | memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); |
| 893 | buffer[buflen-1] = 0; | 1017 | buffer[buflen-1] = 0; |
| @@ -951,7 +1075,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
| 951 | if (!link) | 1075 | if (!link) |
| 952 | link = ERR_PTR(-ENOMEM); | 1076 | link = ERR_PTR(-ENOMEM); |
| 953 | else { | 1077 | else { |
| 954 | len = v9fs_readlink(dentry, link, PATH_MAX); | 1078 | len = v9fs_readlink(dentry, link, strlen(link)); |
| 955 | 1079 | ||
| 956 | if (len < 0) { | 1080 | if (len < 0) { |
| 957 | __putname(link); | 1081 | __putname(link); |
| @@ -983,53 +1107,75 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void | |||
| 983 | static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | 1107 | static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, |
| 984 | int mode, const char *extension) | 1108 | int mode, const char *extension) |
| 985 | { | 1109 | { |
| 986 | int err, retval; | 1110 | int err; |
| 1111 | u32 fid, perm; | ||
| 987 | struct v9fs_session_info *v9ses; | 1112 | struct v9fs_session_info *v9ses; |
| 1113 | struct v9fs_fid *dfid, *vfid; | ||
| 1114 | struct inode *inode; | ||
| 988 | struct v9fs_fcall *fcall; | 1115 | struct v9fs_fcall *fcall; |
| 989 | struct v9fs_fid *fid; | ||
| 990 | struct v9fs_wstat wstat; | 1116 | struct v9fs_wstat wstat; |
| 991 | 1117 | ||
| 992 | v9ses = v9fs_inode2v9ses(dir); | ||
| 993 | retval = -EPERM; | ||
| 994 | fcall = NULL; | 1118 | fcall = NULL; |
| 1119 | inode = NULL; | ||
| 1120 | vfid = NULL; | ||
| 1121 | v9ses = v9fs_inode2v9ses(dir); | ||
| 1122 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
| 1123 | perm = unixmode2p9mode(v9ses, mode); | ||
| 995 | 1124 | ||
| 996 | if (!v9ses->extended) { | 1125 | if (!v9ses->extended) { |
| 997 | dprintk(DEBUG_ERROR, "not extended\n"); | 1126 | dprintk(DEBUG_ERROR, "not extended\n"); |
| 998 | goto free_mem; | 1127 | return -EPERM; |
| 999 | } | 1128 | } |
| 1000 | 1129 | ||
| 1001 | /* issue a create */ | 1130 | err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, |
| 1002 | retval = v9fs_create(dir, dentry, mode, 0); | 1131 | perm, V9FS_OREAD, &fid, NULL, NULL); |
| 1003 | if (retval != 0) | ||
| 1004 | goto free_mem; | ||
| 1005 | 1132 | ||
| 1006 | fid = v9fs_fid_get_created(dentry); | 1133 | if (err) |
| 1007 | if (!fid) { | 1134 | goto error; |
| 1008 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1135 | |
| 1009 | goto free_mem; | 1136 | err = v9fs_t_clunk(v9ses, fid); |
| 1137 | if (err) | ||
| 1138 | goto error; | ||
| 1139 | |||
| 1140 | vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); | ||
| 1141 | if (IS_ERR(vfid)) { | ||
| 1142 | err = PTR_ERR(vfid); | ||
| 1143 | vfid = NULL; | ||
| 1144 | goto error; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); | ||
| 1148 | if (IS_ERR(inode)) { | ||
| 1149 | err = PTR_ERR(inode); | ||
| 1150 | inode = NULL; | ||
| 1151 | goto error; | ||
| 1010 | } | 1152 | } |
| 1011 | 1153 | ||
| 1012 | /* issue a Twstat */ | 1154 | /* issue a Twstat */ |
| 1013 | v9fs_blank_wstat(&wstat); | 1155 | v9fs_blank_wstat(&wstat); |
| 1014 | wstat.muid = v9ses->name; | 1156 | wstat.muid = v9ses->name; |
| 1015 | wstat.extension = (char *) extension; | 1157 | wstat.extension = (char *) extension; |
| 1016 | retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); | 1158 | err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall); |
| 1017 | if (retval < 0) { | ||
| 1018 | PRINT_FCALL_ERROR("wstat error", fcall); | ||
| 1019 | goto free_mem; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | err = v9fs_t_clunk(v9ses, fid->fid); | ||
| 1023 | if (err < 0) { | 1159 | if (err < 0) { |
| 1024 | dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); | 1160 | PRINT_FCALL_ERROR("wstat error", fcall); |
| 1025 | goto free_mem; | 1161 | goto error; |
| 1026 | } | 1162 | } |
| 1027 | 1163 | ||
| 1028 | d_drop(dentry); /* FID - will this also clunk? */ | 1164 | kfree(fcall); |
| 1165 | dentry->d_op = &v9fs_dentry_operations; | ||
| 1166 | d_instantiate(dentry, inode); | ||
| 1167 | return 0; | ||
| 1029 | 1168 | ||
| 1030 | free_mem: | 1169 | error: |
| 1031 | kfree(fcall); | 1170 | kfree(fcall); |
| 1032 | return retval; | 1171 | if (vfid) |
| 1172 | v9fs_fid_destroy(vfid); | ||
| 1173 | |||
| 1174 | if (inode) | ||
| 1175 | iput(inode); | ||
| 1176 | |||
| 1177 | return err; | ||
| 1178 | |||
| 1033 | } | 1179 | } |
| 1034 | 1180 | ||
| 1035 | /** | 1181 | /** |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 2c4fa75be025..0c85872be51a 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -146,7 +146,6 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
| 146 | inode->i_gid = gid; | 146 | inode->i_gid = gid; |
| 147 | 147 | ||
| 148 | root = d_alloc_root(inode); | 148 | root = d_alloc_root(inode); |
| 149 | |||
| 150 | if (!root) { | 149 | if (!root) { |
| 151 | retval = -ENOMEM; | 150 | retval = -ENOMEM; |
| 152 | goto put_back_sb; | 151 | goto put_back_sb; |
| @@ -157,24 +156,27 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
| 157 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); | 156 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); |
| 158 | if (stat_result < 0) { | 157 | if (stat_result < 0) { |
| 159 | dprintk(DEBUG_ERROR, "stat error\n"); | 158 | dprintk(DEBUG_ERROR, "stat error\n"); |
| 159 | kfree(fcall); | ||
| 160 | v9fs_t_clunk(v9ses, newfid); | 160 | v9fs_t_clunk(v9ses, newfid); |
| 161 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
| 162 | } else { | 161 | } else { |
| 163 | /* Setup the Root Inode */ | 162 | /* Setup the Root Inode */ |
| 164 | root_fid = v9fs_fid_create(root, v9ses, newfid, 0); | 163 | kfree(fcall); |
| 164 | root_fid = v9fs_fid_create(v9ses, newfid); | ||
| 165 | if (root_fid == NULL) { | 165 | if (root_fid == NULL) { |
| 166 | retval = -ENOMEM; | 166 | retval = -ENOMEM; |
| 167 | goto put_back_sb; | 167 | goto put_back_sb; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | retval = v9fs_fid_insert(root_fid, root); | ||
| 171 | if (retval < 0) | ||
| 172 | goto put_back_sb; | ||
| 173 | |||
| 170 | root_fid->qid = fcall->params.rstat.stat.qid; | 174 | root_fid->qid = fcall->params.rstat.stat.qid; |
| 171 | root->d_inode->i_ino = | 175 | root->d_inode->i_ino = |
| 172 | v9fs_qid2ino(&fcall->params.rstat.stat.qid); | 176 | v9fs_qid2ino(&fcall->params.rstat.stat.qid); |
| 173 | v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); | 177 | v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); |
| 174 | } | 178 | } |
| 175 | 179 | ||
| 176 | kfree(fcall); | ||
| 177 | |||
| 178 | if (stat_result < 0) { | 180 | if (stat_result < 0) { |
| 179 | retval = stat_result; | 181 | retval = stat_result; |
| 180 | goto put_back_sb; | 182 | goto put_back_sb; |
