diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/9p/fid.c | 176 | ||||
| -rw-r--r-- | fs/9p/fid.h | 7 | ||||
| -rw-r--r-- | fs/9p/vfs_dentry.c | 2 | ||||
| -rw-r--r-- | fs/9p/vfs_dir.c | 11 | ||||
| -rw-r--r-- | fs/9p/vfs_file.c | 88 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 91 | ||||
| -rw-r--r-- | fs/9p/vfs_super.c | 19 | ||||
| -rw-r--r-- | fs/Kconfig | 3 | ||||
| -rw-r--r-- | fs/aio.c | 98 | ||||
| -rw-r--r-- | fs/eventpoll.c | 8 | ||||
| -rw-r--r-- | fs/ext2/ialloc.c | 25 | ||||
| -rw-r--r-- | fs/ext3/ialloc.c | 29 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 6 | ||||
| -rw-r--r-- | fs/fuse/file.c | 4 | ||||
| -rw-r--r-- | fs/hostfs/hostfs_kern.c | 7 | ||||
| -rw-r--r-- | fs/ntfs/ChangeLog | 10 | ||||
| -rw-r--r-- | fs/ntfs/layout.h | 8 | ||||
| -rw-r--r-- | fs/ntfs/lcnalloc.c | 31 | ||||
| -rw-r--r-- | fs/ntfs/lcnalloc.h | 27 | ||||
| -rw-r--r-- | fs/ntfs/logfile.c | 30 | ||||
| -rw-r--r-- | fs/ntfs/logfile.h | 2 | ||||
| -rw-r--r-- | fs/ntfs/mft.c | 2 | ||||
| -rw-r--r-- | fs/read_write.c | 3 |
23 files changed, 358 insertions, 329 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 821c9c4d76aa..d95f8626d170 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
| @@ -71,21 +71,28 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) | |||
| 71 | * | 71 | * |
| 72 | */ | 72 | */ |
| 73 | 73 | ||
| 74 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry) | 74 | struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, |
| 75 | struct v9fs_session_info *v9ses, int fid, int create) | ||
| 75 | { | 76 | { |
| 76 | struct v9fs_fid *new; | 77 | struct v9fs_fid *new; |
| 77 | 78 | ||
| 79 | dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", | ||
| 80 | dentry, fid, create); | ||
| 81 | |||
| 78 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); | 82 | new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
| 79 | if (new == NULL) { | 83 | if (new == NULL) { |
| 80 | dprintk(DEBUG_ERROR, "Out of Memory\n"); | 84 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
| 81 | return ERR_PTR(-ENOMEM); | 85 | return ERR_PTR(-ENOMEM); |
| 82 | } | 86 | } |
| 83 | 87 | ||
| 84 | new->fid = -1; | 88 | new->fid = fid; |
| 89 | new->v9ses = v9ses; | ||
| 85 | new->fidopen = 0; | 90 | new->fidopen = 0; |
| 86 | new->fidcreate = 0; | 91 | new->fidcreate = create; |
| 87 | new->fidclunked = 0; | 92 | new->fidclunked = 0; |
| 88 | new->iounit = 0; | 93 | new->iounit = 0; |
| 94 | new->rdir_pos = 0; | ||
| 95 | new->rdir_fcall = NULL; | ||
| 89 | 96 | ||
| 90 | if (v9fs_fid_insert(new, dentry) == 0) | 97 | if (v9fs_fid_insert(new, dentry) == 0) |
| 91 | return new; | 98 | return new; |
| @@ -109,6 +116,59 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
| 109 | } | 116 | } |
| 110 | 117 | ||
| 111 | /** | 118 | /** |
| 119 | * v9fs_fid_walk_up - walks from the process current directory | ||
| 120 | * up to the specified dentry. | ||
| 121 | */ | ||
| 122 | static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) | ||
| 123 | { | ||
| 124 | int fidnum, cfidnum, err; | ||
| 125 | struct v9fs_fid *cfid; | ||
| 126 | struct dentry *cde; | ||
| 127 | struct v9fs_session_info *v9ses; | ||
| 128 | |||
| 129 | v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
| 130 | cfid = v9fs_fid_lookup(current->fs->pwd); | ||
| 131 | if (cfid == NULL) { | ||
| 132 | dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n"); | ||
| 133 | return ERR_PTR(-ENOENT); | ||
| 134 | } | ||
| 135 | |||
| 136 | cfidnum = cfid->fid; | ||
| 137 | cde = current->fs->pwd; | ||
| 138 | /* TODO: take advantage of multiwalk */ | ||
| 139 | |||
| 140 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | ||
| 141 | if (fidnum < 0) { | ||
| 142 | dprintk(DEBUG_ERROR, "could not get a new fid num\n"); | ||
| 143 | err = -ENOENT; | ||
| 144 | goto clunk_fid; | ||
| 145 | } | ||
| 146 | |||
| 147 | while (cde != dentry) { | ||
| 148 | if (cde == cde->d_parent) { | ||
| 149 | dprintk(DEBUG_ERROR, "can't find dentry\n"); | ||
| 150 | err = -ENOENT; | ||
| 151 | goto clunk_fid; | ||
| 152 | } | ||
| 153 | |||
| 154 | err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL); | ||
| 155 | if (err < 0) { | ||
| 156 | dprintk(DEBUG_ERROR, "problem walking to parent\n"); | ||
| 157 | goto clunk_fid; | ||
| 158 | } | ||
| 159 | |||
| 160 | cfidnum = fidnum; | ||
| 161 | cde = cde->d_parent; | ||
| 162 | } | ||
| 163 | |||
| 164 | return v9fs_fid_create(dentry, v9ses, fidnum, 0); | ||
| 165 | |||
| 166 | clunk_fid: | ||
| 167 | v9fs_t_clunk(v9ses, fidnum, NULL); | ||
| 168 | return ERR_PTR(err); | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 112 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry | 172 | * v9fs_fid_lookup - retrieve the right fid from a particular dentry |
| 113 | * @dentry: dentry to look for fid in | 173 | * @dentry: dentry to look for fid in |
| 114 | * @type: intent of lookup (operation or traversal) | 174 | * @type: intent of lookup (operation or traversal) |
| @@ -119,49 +179,25 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) | |||
| 119 | * | 179 | * |
| 120 | */ | 180 | */ |
| 121 | 181 | ||
| 122 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) | 182 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) |
| 123 | { | 183 | { |
| 124 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; | 184 | struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; |
| 125 | struct v9fs_fid *current_fid = NULL; | 185 | struct v9fs_fid *current_fid = NULL; |
| 126 | struct v9fs_fid *temp = NULL; | 186 | struct v9fs_fid *temp = NULL; |
| 127 | struct v9fs_fid *return_fid = NULL; | 187 | struct v9fs_fid *return_fid = NULL; |
| 128 | int found_parent = 0; | ||
| 129 | int found_user = 0; | ||
| 130 | 188 | ||
| 131 | dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry, | 189 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
| 132 | type); | ||
| 133 | 190 | ||
| 134 | if (fid_list && !list_empty(fid_list)) { | 191 | if (fid_list) { |
| 135 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { | 192 | list_for_each_entry_safe(current_fid, temp, fid_list, list) { |
| 136 | if (current_fid->uid == current->uid) { | 193 | if (!current_fid->fidcreate) { |
| 137 | if (return_fid == NULL) { | 194 | return_fid = current_fid; |
| 138 | if ((type == FID_OP) | 195 | break; |
| 139 | || (!current_fid->fidopen)) { | ||
| 140 | return_fid = current_fid; | ||
| 141 | found_user = 1; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | } | ||
| 145 | if (current_fid->pid == current->real_parent->pid) { | ||
| 146 | if ((return_fid == NULL) || (found_parent) | ||
| 147 | || (found_user)) { | ||
| 148 | if ((type == FID_OP) | ||
| 149 | || (!current_fid->fidopen)) { | ||
| 150 | return_fid = current_fid; | ||
| 151 | found_parent = 1; | ||
| 152 | found_user = 0; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | } | ||
| 156 | if (current_fid->pid == current->pid) { | ||
| 157 | if ((type == FID_OP) || | ||
| 158 | (!current_fid->fidopen)) { | ||
| 159 | return_fid = current_fid; | ||
| 160 | found_parent = 0; | ||
| 161 | found_user = 0; | ||
| 162 | } | ||
| 163 | } | 196 | } |
| 164 | } | 197 | } |
| 198 | |||
| 199 | if (!return_fid) | ||
| 200 | return_fid = current_fid; | ||
| 165 | } | 201 | } |
| 166 | 202 | ||
| 167 | /* we are at the root but didn't match */ | 203 | /* we are at the root but didn't match */ |
| @@ -187,55 +223,33 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type) | |||
| 187 | 223 | ||
| 188 | /* XXX - there may be some duplication we can get rid of */ | 224 | /* XXX - there may be some duplication we can get rid of */ |
| 189 | if (par == dentry) { | 225 | if (par == dentry) { |
| 190 | /* we need to fid_lookup the starting point */ | 226 | return_fid = v9fs_fid_walk_up(dentry); |
| 191 | int fidnum = -1; | 227 | if (IS_ERR(return_fid)) |
| 192 | int oldfid = -1; | 228 | return_fid = NULL; |
| 193 | int result = -1; | 229 | } |
| 194 | struct v9fs_session_info *v9ses = | 230 | } |
| 195 | v9fs_inode2v9ses(current->fs->pwd->d_inode); | ||
| 196 | |||
| 197 | current_fid = | ||
| 198 | v9fs_fid_lookup(current->fs->pwd, FID_WALK); | ||
| 199 | if (current_fid == NULL) { | ||
| 200 | dprintk(DEBUG_ERROR, | ||
| 201 | "process cwd doesn't have a fid\n"); | ||
| 202 | return return_fid; | ||
| 203 | } | ||
| 204 | oldfid = current_fid->fid; | ||
| 205 | par = current->fs->pwd; | ||
| 206 | /* TODO: take advantage of multiwalk */ | ||
| 207 | 231 | ||
| 208 | fidnum = v9fs_get_idpool(&v9ses->fidpool); | 232 | return return_fid; |
| 209 | if (fidnum < 0) { | 233 | } |
| 210 | dprintk(DEBUG_ERROR, | ||
| 211 | "could not get a new fid num\n"); | ||
| 212 | return return_fid; | ||
| 213 | } | ||
| 214 | 234 | ||
| 215 | while (par != dentry) { | 235 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) |
| 216 | result = | 236 | { |
| 217 | v9fs_t_walk(v9ses, oldfid, fidnum, "..", | 237 | struct list_head *fid_list; |
| 218 | NULL); | 238 | struct v9fs_fid *fid, *ftmp, *ret; |
| 219 | if (result < 0) { | 239 | |
| 220 | dprintk(DEBUG_ERROR, | 240 | dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); |
| 221 | "problem walking to parent\n"); | 241 | fid_list = (struct list_head *)dentry->d_fsdata; |
| 222 | 242 | ret = NULL; | |
| 223 | break; | 243 | if (fid_list) { |
| 224 | } | 244 | list_for_each_entry_safe(fid, ftmp, fid_list, list) { |
| 225 | oldfid = fidnum; | 245 | if (fid->fidcreate && fid->pid == current->pid) { |
| 226 | if (par == par->d_parent) { | 246 | list_del(&fid->list); |
| 227 | dprintk(DEBUG_ERROR, | 247 | ret = fid; |
| 228 | "can't find dentry\n"); | 248 | break; |
| 229 | break; | ||
| 230 | } | ||
| 231 | par = par->d_parent; | ||
| 232 | } | ||
| 233 | if (par == dentry) { | ||
| 234 | return_fid = v9fs_fid_create(dentry); | ||
| 235 | return_fid->fid = fidnum; | ||
| 236 | } | 249 | } |
| 237 | } | 250 | } |
| 238 | } | 251 | } |
| 239 | 252 | ||
| 240 | return return_fid; | 253 | dprintk(DEBUG_9P, "return %p\n", ret); |
| 254 | return ret; | ||
| 241 | } | 255 | } |
diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 7db478ccca36..84c673a44c83 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | #define FID_OP 0 | 26 | #define FID_OP 0 |
| 27 | #define FID_WALK 1 | 27 | #define FID_WALK 1 |
| 28 | #define FID_CREATE 2 | ||
| 28 | 29 | ||
| 29 | struct v9fs_fid { | 30 | struct v9fs_fid { |
| 30 | struct list_head list; /* list of fids associated with a dentry */ | 31 | struct list_head list; /* list of fids associated with a dentry */ |
| @@ -52,6 +53,8 @@ struct v9fs_fid { | |||
| 52 | struct v9fs_session_info *v9ses; /* session info for this FID */ | 53 | struct v9fs_session_info *v9ses; /* session info for this FID */ |
| 53 | }; | 54 | }; |
| 54 | 55 | ||
| 55 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type); | 56 | struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); |
| 57 | struct v9fs_fid *v9fs_fid_get_created(struct dentry *); | ||
| 56 | void v9fs_fid_destroy(struct v9fs_fid *fid); | 58 | void v9fs_fid_destroy(struct v9fs_fid *fid); |
| 57 | struct v9fs_fid *v9fs_fid_create(struct dentry *); | 59 | struct v9fs_fid *v9fs_fid_create(struct dentry *, |
| 60 | struct v9fs_session_info *v9ses, int fid, int create); | ||
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 306c96741f81..a6aa947de0f9 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
| @@ -67,7 +67,7 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) | |||
| 67 | struct dentry *dc = current->fs->pwd; | 67 | struct dentry *dc = current->fs->pwd; |
| 68 | 68 | ||
| 69 | dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); | 69 | dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); |
| 70 | if (v9fs_fid_lookup(dentry, FID_OP)) { | 70 | if (v9fs_fid_lookup(dentry)) { |
| 71 | dprintk(DEBUG_VFS, "VALID\n"); | 71 | dprintk(DEBUG_VFS, "VALID\n"); |
| 72 | return 1; | 72 | return 1; |
| 73 | } | 73 | } |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index c478a7384186..57a43b8feef5 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
| @@ -197,21 +197,18 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
| 197 | filemap_fdatawait(inode->i_mapping); | 197 | filemap_fdatawait(inode->i_mapping); |
| 198 | 198 | ||
| 199 | if (fidnum >= 0) { | 199 | if (fidnum >= 0) { |
| 200 | fid->fidopen--; | ||
| 201 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, | 200 | dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen, |
| 202 | fid->fid); | 201 | fid->fid); |
| 203 | 202 | ||
| 204 | if (fid->fidopen == 0) { | 203 | if (v9fs_t_clunk(v9ses, fidnum, NULL)) |
| 205 | if (v9fs_t_clunk(v9ses, fidnum, NULL)) | 204 | dprintk(DEBUG_ERROR, "clunk failed\n"); |
| 206 | dprintk(DEBUG_ERROR, "clunk failed\n"); | ||
| 207 | 205 | ||
| 208 | v9fs_put_idpool(fid->fid, &v9ses->fidpool); | 206 | v9fs_put_idpool(fid->fid, &v9ses->fidpool); |
| 209 | } | ||
| 210 | 207 | ||
| 211 | kfree(fid->rdir_fcall); | 208 | kfree(fid->rdir_fcall); |
| 209 | kfree(fid); | ||
| 212 | 210 | ||
| 213 | filp->private_data = NULL; | 211 | filp->private_data = NULL; |
| 214 | v9fs_fid_destroy(fid); | ||
| 215 | } | 212 | } |
| 216 | 213 | ||
| 217 | d_drop(filp->f_dentry); | 214 | d_drop(filp->f_dentry); |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 1f8ae7d580ab..a4799e971d1c 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -53,30 +53,36 @@ | |||
| 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 = v9fs_fid_lookup(file->f_dentry, FID_WALK); | 56 | struct v9fs_fid *v9fid, *fid; |
| 57 | struct v9fs_fid *v9newfid = NULL; | ||
| 58 | struct v9fs_fcall *fcall = NULL; | 57 | struct v9fs_fcall *fcall = NULL; |
| 59 | int open_mode = 0; | 58 | int open_mode = 0; |
| 60 | unsigned int iounit = 0; | 59 | unsigned int iounit = 0; |
| 61 | int newfid = -1; | 60 | int newfid = -1; |
| 62 | long result = -1; | 61 | long result = -1; |
| 63 | 62 | ||
| 64 | dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file, | 63 | dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); |
| 65 | v9fid); | 64 | |
| 65 | v9fid = v9fs_fid_get_created(file->f_dentry); | ||
| 66 | if (!v9fid) | ||
| 67 | v9fid = v9fs_fid_lookup(file->f_dentry); | ||
| 66 | 68 | ||
| 67 | if (!v9fid) { | 69 | if (!v9fid) { |
| 68 | struct dentry *dentry = file->f_dentry; | ||
| 69 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); | 70 | dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); |
| 71 | return -EBADF; | ||
| 72 | } | ||
| 70 | 73 | ||
| 71 | /* XXX - some duplication from lookup, generalize later */ | 74 | if (!v9fid->fidcreate) { |
| 72 | /* basically vfs_lookup is too heavy weight */ | 75 | fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); |
| 73 | v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP); | 76 | if (fid == NULL) { |
| 74 | if (!v9fid) | 77 | dprintk(DEBUG_ERROR, "Out of Memory\n"); |
| 75 | return -EBADF; | 78 | return -ENOMEM; |
| 79 | } | ||
| 76 | 80 | ||
| 77 | v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 81 | fid->fidopen = 0; |
| 78 | if (!v9fid) | 82 | fid->fidcreate = 0; |
| 79 | return -EBADF; | 83 | fid->fidclunked = 0; |
| 84 | fid->iounit = 0; | ||
| 85 | fid->v9ses = v9ses; | ||
| 80 | 86 | ||
| 81 | newfid = v9fs_get_idpool(&v9ses->fidpool); | 87 | newfid = v9fs_get_idpool(&v9ses->fidpool); |
| 82 | if (newfid < 0) { | 88 | if (newfid < 0) { |
| @@ -85,58 +91,16 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
| 85 | } | 91 | } |
| 86 | 92 | ||
| 87 | result = | 93 | result = |
| 88 | v9fs_t_walk(v9ses, v9fid->fid, newfid, | 94 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); |
| 89 | (char *)file->f_dentry->d_name.name, NULL); | 95 | |
| 90 | if (result < 0) { | 96 | if (result < 0) { |
| 91 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 97 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
| 92 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); | 98 | dprintk(DEBUG_ERROR, "rewalk didn't work\n"); |
| 93 | return -EBADF; | 99 | return -EBADF; |
| 94 | } | 100 | } |
| 95 | 101 | ||
| 96 | v9fid = v9fs_fid_create(dentry); | 102 | fid->fid = newfid; |
| 97 | if (v9fid == NULL) { | 103 | v9fid = fid; |
| 98 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | ||
| 99 | return -ENOMEM; | ||
| 100 | } | ||
| 101 | v9fid->fid = newfid; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (v9fid->fidcreate) { | ||
| 105 | /* create case */ | ||
| 106 | newfid = v9fid->fid; | ||
| 107 | iounit = v9fid->iounit; | ||
| 108 | v9fid->fidcreate = 0; | ||
| 109 | } else { | ||
| 110 | if (!S_ISDIR(inode->i_mode)) | ||
| 111 | newfid = v9fid->fid; | ||
| 112 | else { | ||
| 113 | newfid = v9fs_get_idpool(&v9ses->fidpool); | ||
| 114 | if (newfid < 0) { | ||
| 115 | eprintk(KERN_WARNING, "allocation failed\n"); | ||
| 116 | return -ENOSPC; | ||
| 117 | } | ||
| 118 | /* This would be a somewhat critical clone */ | ||
| 119 | result = | ||
| 120 | v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, | ||
| 121 | &fcall); | ||
| 122 | if (result < 0) { | ||
| 123 | dprintk(DEBUG_ERROR, "clone error: %s\n", | ||
| 124 | FCALL_ERROR(fcall)); | ||
| 125 | kfree(fcall); | ||
| 126 | return result; | ||
| 127 | } | ||
| 128 | |||
| 129 | v9newfid = v9fs_fid_create(file->f_dentry); | ||
| 130 | v9newfid->fid = newfid; | ||
| 131 | v9newfid->qid = v9fid->qid; | ||
| 132 | v9newfid->iounit = v9fid->iounit; | ||
| 133 | v9newfid->fidopen = 0; | ||
| 134 | v9newfid->fidclunked = 0; | ||
| 135 | v9newfid->v9ses = v9ses; | ||
| 136 | v9fid = v9newfid; | ||
| 137 | kfree(fcall); | ||
| 138 | } | ||
| 139 | |||
| 140 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ | 104 | /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ |
| 141 | /* translate open mode appropriately */ | 105 | /* translate open mode appropriately */ |
| 142 | open_mode = file->f_flags & 0x3; | 106 | open_mode = file->f_flags & 0x3; |
| @@ -163,9 +127,13 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
| 163 | 127 | ||
| 164 | iounit = fcall->params.ropen.iounit; | 128 | iounit = fcall->params.ropen.iounit; |
| 165 | kfree(fcall); | 129 | kfree(fcall); |
| 130 | } else { | ||
| 131 | /* create case */ | ||
| 132 | newfid = v9fid->fid; | ||
| 133 | iounit = v9fid->iounit; | ||
| 134 | v9fid->fidcreate = 0; | ||
| 166 | } | 135 | } |
| 167 | 136 | ||
| 168 | |||
| 169 | file->private_data = v9fid; | 137 | file->private_data = v9fid; |
| 170 | 138 | ||
| 171 | v9fid->rdir_pos = 0; | 139 | v9fid->rdir_pos = 0; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b16322db5ce6..2b696ae6655a 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -307,7 +307,7 @@ v9fs_create(struct inode *dir, | |||
| 307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 307 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
| 308 | struct super_block *sb = dir->i_sb; | 308 | struct super_block *sb = dir->i_sb; |
| 309 | struct v9fs_fid *dirfid = | 309 | struct v9fs_fid *dirfid = |
| 310 | v9fs_fid_lookup(file_dentry->d_parent, FID_WALK); | 310 | v9fs_fid_lookup(file_dentry->d_parent); |
| 311 | struct v9fs_fid *fid = NULL; | 311 | struct v9fs_fid *fid = NULL; |
| 312 | struct inode *file_inode = NULL; | 312 | struct inode *file_inode = NULL; |
| 313 | struct v9fs_fcall *fcall = NULL; | 313 | struct v9fs_fcall *fcall = NULL; |
| @@ -317,6 +317,7 @@ v9fs_create(struct inode *dir, | |||
| 317 | long newfid = -1; | 317 | long newfid = -1; |
| 318 | int result = 0; | 318 | int result = 0; |
| 319 | unsigned int iounit = 0; | 319 | unsigned int iounit = 0; |
| 320 | int wfidno = -1; | ||
| 320 | 321 | ||
| 321 | perm = unixmode2p9mode(v9ses, perm); | 322 | perm = unixmode2p9mode(v9ses, perm); |
| 322 | 323 | ||
| @@ -350,7 +351,7 @@ v9fs_create(struct inode *dir, | |||
| 350 | if (result < 0) { | 351 | if (result < 0) { |
| 351 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | 352 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); |
| 352 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 353 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
| 353 | newfid = 0; | 354 | newfid = -1; |
| 354 | goto CleanUpFid; | 355 | goto CleanUpFid; |
| 355 | } | 356 | } |
| 356 | 357 | ||
| @@ -369,20 +370,39 @@ v9fs_create(struct inode *dir, | |||
| 369 | qid = fcall->params.rcreate.qid; | 370 | qid = fcall->params.rcreate.qid; |
| 370 | kfree(fcall); | 371 | kfree(fcall); |
| 371 | 372 | ||
| 372 | fid = v9fs_fid_create(file_dentry); | 373 | fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); |
| 374 | dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); | ||
| 373 | if (!fid) { | 375 | if (!fid) { |
| 374 | result = -ENOMEM; | 376 | result = -ENOMEM; |
| 375 | goto CleanUpFid; | 377 | goto CleanUpFid; |
| 376 | } | 378 | } |
| 377 | 379 | ||
| 378 | fid->fid = newfid; | ||
| 379 | fid->fidopen = 0; | ||
| 380 | fid->fidcreate = 1; | ||
| 381 | fid->qid = qid; | 380 | fid->qid = qid; |
| 382 | fid->iounit = iounit; | 381 | fid->iounit = iounit; |
| 383 | fid->rdir_pos = 0; | 382 | |
| 384 | fid->rdir_fcall = NULL; | 383 | /* walk to the newly created file and put the fid in the dentry */ |
| 385 | fid->v9ses = v9ses; | 384 | wfidno = v9fs_get_idpool(&v9ses->fidpool); |
| 385 | if (newfid < 0) { | ||
| 386 | eprintk(KERN_WARNING, "no free fids available\n"); | ||
| 387 | return -ENOSPC; | ||
| 388 | } | ||
| 389 | |||
| 390 | result = v9fs_t_walk(v9ses, dirfidnum, wfidno, | ||
| 391 | (char *) file_dentry->d_name.name, NULL); | ||
| 392 | if (result < 0) { | ||
| 393 | dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall)); | ||
| 394 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
| 395 | wfidno = -1; | ||
| 396 | goto CleanUpFid; | ||
| 397 | } | ||
| 398 | |||
| 399 | if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { | ||
| 400 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) { | ||
| 401 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
| 402 | } | ||
| 403 | |||
| 404 | goto CleanUpFid; | ||
| 405 | } | ||
| 386 | 406 | ||
| 387 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || | 407 | if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || |
| 388 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || | 408 | (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || |
| @@ -410,11 +430,11 @@ v9fs_create(struct inode *dir, | |||
| 410 | d_instantiate(file_dentry, file_inode); | 430 | d_instantiate(file_dentry, file_inode); |
| 411 | 431 | ||
| 412 | if (perm & V9FS_DMDIR) { | 432 | if (perm & V9FS_DMDIR) { |
| 413 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 433 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
| 434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
| 435 | else | ||
| 414 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", | 436 | dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n", |
| 415 | FCALL_ERROR(fcall)); | 437 | FCALL_ERROR(fcall)); |
| 416 | |||
| 417 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
| 418 | kfree(fcall); | 438 | kfree(fcall); |
| 419 | fid->fidopen = 0; | 439 | fid->fidopen = 0; |
| 420 | fid->fidcreate = 0; | 440 | fid->fidcreate = 0; |
| @@ -426,12 +446,22 @@ v9fs_create(struct inode *dir, | |||
| 426 | CleanUpFid: | 446 | CleanUpFid: |
| 427 | kfree(fcall); | 447 | kfree(fcall); |
| 428 | 448 | ||
| 429 | if (newfid) { | 449 | if (newfid >= 0) { |
| 430 | if (v9fs_t_clunk(v9ses, newfid, &fcall)) | 450 | if (!v9fs_t_clunk(v9ses, newfid, &fcall)) |
| 451 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
| 452 | else | ||
| 453 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | ||
| 454 | FCALL_ERROR(fcall)); | ||
| 455 | |||
| 456 | kfree(fcall); | ||
| 457 | } | ||
| 458 | if (wfidno >= 0) { | ||
| 459 | if (!v9fs_t_clunk(v9ses, wfidno, &fcall)) | ||
| 460 | v9fs_put_idpool(wfidno, &v9ses->fidpool); | ||
| 461 | else | ||
| 431 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", | 462 | dprintk(DEBUG_ERROR, "clunk failed: %s\n", |
| 432 | FCALL_ERROR(fcall)); | 463 | FCALL_ERROR(fcall)); |
| 433 | 464 | ||
| 434 | v9fs_put_idpool(newfid, &v9ses->fidpool); | ||
| 435 | kfree(fcall); | 465 | kfree(fcall); |
| 436 | } | 466 | } |
| 437 | return result; | 467 | return result; |
| @@ -461,7 +491,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
| 461 | file_inode = file->d_inode; | 491 | file_inode = file->d_inode; |
| 462 | sb = file_inode->i_sb; | 492 | sb = file_inode->i_sb; |
| 463 | v9ses = v9fs_inode2v9ses(file_inode); | 493 | v9ses = v9fs_inode2v9ses(file_inode); |
| 464 | v9fid = v9fs_fid_lookup(file, FID_OP); | 494 | v9fid = v9fs_fid_lookup(file); |
| 465 | 495 | ||
| 466 | if (!v9fid) { | 496 | if (!v9fid) { |
| 467 | dprintk(DEBUG_ERROR, | 497 | dprintk(DEBUG_ERROR, |
| @@ -545,7 +575,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 545 | 575 | ||
| 546 | sb = dir->i_sb; | 576 | sb = dir->i_sb; |
| 547 | v9ses = v9fs_inode2v9ses(dir); | 577 | v9ses = v9fs_inode2v9ses(dir); |
| 548 | dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK); | 578 | dirfid = v9fs_fid_lookup(dentry->d_parent); |
| 549 | 579 | ||
| 550 | if (!dirfid) { | 580 | if (!dirfid) { |
| 551 | dprintk(DEBUG_ERROR, "no dirfid\n"); | 581 | dprintk(DEBUG_ERROR, "no dirfid\n"); |
| @@ -573,7 +603,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 573 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 603 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
| 574 | if (result == -ENOENT) { | 604 | if (result == -ENOENT) { |
| 575 | d_add(dentry, NULL); | 605 | d_add(dentry, NULL); |
| 576 | dprintk(DEBUG_ERROR, | 606 | dprintk(DEBUG_VFS, |
| 577 | "Return negative dentry %p count %d\n", | 607 | "Return negative dentry %p count %d\n", |
| 578 | dentry, atomic_read(&dentry->d_count)); | 608 | dentry, atomic_read(&dentry->d_count)); |
| 579 | return NULL; | 609 | return NULL; |
| @@ -601,16 +631,13 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 601 | 631 | ||
| 602 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 632 | inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid); |
| 603 | 633 | ||
| 604 | fid = v9fs_fid_create(dentry); | 634 | fid = v9fs_fid_create(dentry, v9ses, newfid, 0); |
| 605 | if (fid == NULL) { | 635 | if (fid == NULL) { |
| 606 | dprintk(DEBUG_ERROR, "couldn't insert\n"); | 636 | dprintk(DEBUG_ERROR, "couldn't insert\n"); |
| 607 | result = -ENOMEM; | 637 | result = -ENOMEM; |
| 608 | goto FreeFcall; | 638 | goto FreeFcall; |
| 609 | } | 639 | } |
| 610 | 640 | ||
| 611 | fid->fid = newfid; | ||
| 612 | fid->fidopen = 0; | ||
| 613 | fid->v9ses = v9ses; | ||
| 614 | fid->qid = fcall->params.rstat.stat->qid; | 641 | fid->qid = fcall->params.rstat.stat->qid; |
| 615 | 642 | ||
| 616 | dentry->d_op = &v9fs_dentry_operations; | 643 | dentry->d_op = &v9fs_dentry_operations; |
| @@ -665,11 +692,11 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 665 | { | 692 | { |
| 666 | struct inode *old_inode = old_dentry->d_inode; | 693 | struct inode *old_inode = old_dentry->d_inode; |
| 667 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); | 694 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode); |
| 668 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK); | 695 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
| 669 | struct v9fs_fid *olddirfid = | 696 | struct v9fs_fid *olddirfid = |
| 670 | v9fs_fid_lookup(old_dentry->d_parent, FID_WALK); | 697 | v9fs_fid_lookup(old_dentry->d_parent); |
| 671 | struct v9fs_fid *newdirfid = | 698 | struct v9fs_fid *newdirfid = |
| 672 | v9fs_fid_lookup(new_dentry->d_parent, FID_WALK); | 699 | v9fs_fid_lookup(new_dentry->d_parent); |
| 673 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 700 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
| 674 | struct v9fs_fcall *fcall = NULL; | 701 | struct v9fs_fcall *fcall = NULL; |
| 675 | int fid = -1; | 702 | int fid = -1; |
| @@ -744,7 +771,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 744 | { | 771 | { |
| 745 | struct v9fs_fcall *fcall = NULL; | 772 | struct v9fs_fcall *fcall = NULL; |
| 746 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 773 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 747 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 774 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
| 748 | int err = -EPERM; | 775 | int err = -EPERM; |
| 749 | 776 | ||
| 750 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); | 777 | dprintk(DEBUG_VFS, "dentry: %p\n", dentry); |
| @@ -778,7 +805,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 778 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | 805 | static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) |
| 779 | { | 806 | { |
| 780 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 807 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 781 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 808 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
| 782 | struct v9fs_fcall *fcall = NULL; | 809 | struct v9fs_fcall *fcall = NULL; |
| 783 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 810 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
| 784 | int res = -EPERM; | 811 | int res = -EPERM; |
| @@ -960,7 +987,7 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
| 960 | if (retval != 0) | 987 | if (retval != 0) |
| 961 | goto FreeFcall; | 988 | goto FreeFcall; |
| 962 | 989 | ||
| 963 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 990 | newfid = v9fs_fid_lookup(dentry); |
| 964 | 991 | ||
| 965 | /* issue a twstat */ | 992 | /* issue a twstat */ |
| 966 | v9fs_blank_mistat(v9ses, mistat); | 993 | v9fs_blank_mistat(v9ses, mistat); |
| @@ -1004,7 +1031,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
| 1004 | 1031 | ||
| 1005 | struct v9fs_fcall *fcall = NULL; | 1032 | struct v9fs_fcall *fcall = NULL; |
| 1006 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); | 1033 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode); |
| 1007 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP); | 1034 | struct v9fs_fid *fid = v9fs_fid_lookup(dentry); |
| 1008 | 1035 | ||
| 1009 | if (!fid) { | 1036 | if (!fid) { |
| 1010 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); | 1037 | dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n"); |
| @@ -1148,7 +1175,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1148 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); | 1175 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
| 1149 | struct v9fs_fcall *fcall = NULL; | 1176 | struct v9fs_fcall *fcall = NULL; |
| 1150 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); | 1177 | struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL); |
| 1151 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP); | 1178 | struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry); |
| 1152 | struct v9fs_fid *newfid = NULL; | 1179 | struct v9fs_fid *newfid = NULL; |
| 1153 | char *symname = __getname(); | 1180 | char *symname = __getname(); |
| 1154 | 1181 | ||
| @@ -1168,7 +1195,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 1168 | if (retval != 0) | 1195 | if (retval != 0) |
| 1169 | goto FreeMem; | 1196 | goto FreeMem; |
| 1170 | 1197 | ||
| 1171 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1198 | newfid = v9fs_fid_lookup(dentry); |
| 1172 | if (!newfid) { | 1199 | if (!newfid) { |
| 1173 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); | 1200 | dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); |
| 1174 | goto FreeMem; | 1201 | goto FreeMem; |
| @@ -1246,7 +1273,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
| 1246 | if (retval != 0) | 1273 | if (retval != 0) |
| 1247 | goto FreeMem; | 1274 | goto FreeMem; |
| 1248 | 1275 | ||
| 1249 | newfid = v9fs_fid_lookup(dentry, FID_OP); | 1276 | newfid = v9fs_fid_lookup(dentry); |
| 1250 | if (!newfid) { | 1277 | if (!newfid) { |
| 1251 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); | 1278 | dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n"); |
| 1252 | retval = -EINVAL; | 1279 | retval = -EINVAL; |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 1e2b2b54d300..82c5b0084079 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -129,7 +129,6 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
| 129 | 129 | ||
| 130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { | 130 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { |
| 131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); | 131 | dprintk(DEBUG_ERROR, "problem initiating session\n"); |
| 132 | kfree(v9ses); | ||
| 133 | return ERR_PTR(newfid); | 132 | return ERR_PTR(newfid); |
| 134 | } | 133 | } |
| 135 | 134 | ||
| @@ -155,23 +154,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
| 155 | 154 | ||
| 156 | sb->s_root = root; | 155 | sb->s_root = root; |
| 157 | 156 | ||
| 158 | /* Setup the Root Inode */ | ||
| 159 | root_fid = v9fs_fid_create(root); | ||
| 160 | if (root_fid == NULL) { | ||
| 161 | retval = -ENOMEM; | ||
| 162 | goto put_back_sb; | ||
| 163 | } | ||
| 164 | |||
| 165 | root_fid->fidopen = 0; | ||
| 166 | root_fid->v9ses = v9ses; | ||
| 167 | |||
| 168 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); | 157 | stat_result = v9fs_t_stat(v9ses, newfid, &fcall); |
| 169 | if (stat_result < 0) { | 158 | if (stat_result < 0) { |
| 170 | dprintk(DEBUG_ERROR, "stat error\n"); | 159 | dprintk(DEBUG_ERROR, "stat error\n"); |
| 171 | v9fs_t_clunk(v9ses, newfid, NULL); | 160 | v9fs_t_clunk(v9ses, newfid, NULL); |
| 172 | v9fs_put_idpool(newfid, &v9ses->fidpool); | 161 | v9fs_put_idpool(newfid, &v9ses->fidpool); |
| 173 | } else { | 162 | } else { |
| 174 | root_fid->fid = newfid; | 163 | /* Setup the Root Inode */ |
| 164 | root_fid = v9fs_fid_create(root, v9ses, newfid, 0); | ||
| 165 | if (root_fid == NULL) { | ||
| 166 | retval = -ENOMEM; | ||
| 167 | goto put_back_sb; | ||
| 168 | } | ||
| 169 | |||
| 175 | root_fid->qid = fcall->params.rstat.stat->qid; | 170 | root_fid->qid = fcall->params.rstat.stat->qid; |
| 176 | root->d_inode->i_ino = | 171 | root->d_inode->i_ino = |
| 177 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); | 172 | v9fs_qid2ino(&fcall->params.rstat.stat->qid); |
diff --git a/fs/Kconfig b/fs/Kconfig index 068ccea2f184..48f5422cb19a 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -472,6 +472,9 @@ config FUSE_FS | |||
| 472 | utilities is available from the FUSE homepage: | 472 | utilities is available from the FUSE homepage: |
| 473 | <http://fuse.sourceforge.net/> | 473 | <http://fuse.sourceforge.net/> |
| 474 | 474 | ||
| 475 | See <file:Documentation/filesystems/fuse.txt> for more information. | ||
| 476 | See <file:Documentation/Changes> for needed library/utility version. | ||
| 477 | |||
| 475 | If you want to develop a userspace FS, or if you want to use | 478 | If you want to develop a userspace FS, or if you want to use |
| 476 | a filesystem based on FUSE, answer Y or M. | 479 | a filesystem based on FUSE, answer Y or M. |
| 477 | 480 | ||
| @@ -741,19 +741,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) | |||
| 741 | ret = retry(iocb); | 741 | ret = retry(iocb); |
| 742 | current->io_wait = NULL; | 742 | current->io_wait = NULL; |
| 743 | 743 | ||
| 744 | if (-EIOCBRETRY != ret) { | 744 | if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) { |
| 745 | if (-EIOCBQUEUED != ret) { | 745 | BUG_ON(!list_empty(&iocb->ki_wait.task_list)); |
| 746 | BUG_ON(!list_empty(&iocb->ki_wait.task_list)); | 746 | aio_complete(iocb, ret, 0); |
| 747 | aio_complete(iocb, ret, 0); | ||
| 748 | /* must not access the iocb after this */ | ||
| 749 | } | ||
| 750 | } else { | ||
| 751 | /* | ||
| 752 | * Issue an additional retry to avoid waiting forever if | ||
| 753 | * no waits were queued (e.g. in case of a short read). | ||
| 754 | */ | ||
| 755 | if (list_empty(&iocb->ki_wait.task_list)) | ||
| 756 | kiocbSetKicked(iocb); | ||
| 757 | } | 747 | } |
| 758 | out: | 748 | out: |
| 759 | spin_lock_irq(&ctx->ctx_lock); | 749 | spin_lock_irq(&ctx->ctx_lock); |
| @@ -899,16 +889,24 @@ static void aio_kick_handler(void *data) | |||
| 899 | * and if required activate the aio work queue to process | 889 | * and if required activate the aio work queue to process |
| 900 | * it | 890 | * it |
| 901 | */ | 891 | */ |
| 902 | static void queue_kicked_iocb(struct kiocb *iocb) | 892 | static void try_queue_kicked_iocb(struct kiocb *iocb) |
| 903 | { | 893 | { |
| 904 | struct kioctx *ctx = iocb->ki_ctx; | 894 | struct kioctx *ctx = iocb->ki_ctx; |
| 905 | unsigned long flags; | 895 | unsigned long flags; |
| 906 | int run = 0; | 896 | int run = 0; |
| 907 | 897 | ||
| 908 | WARN_ON((!list_empty(&iocb->ki_wait.task_list))); | 898 | /* We're supposed to be the only path putting the iocb back on the run |
| 899 | * list. If we find that the iocb is *back* on a wait queue already | ||
| 900 | * than retry has happened before we could queue the iocb. This also | ||
| 901 | * means that the retry could have completed and freed our iocb, no | ||
| 902 | * good. */ | ||
| 903 | BUG_ON((!list_empty(&iocb->ki_wait.task_list))); | ||
| 909 | 904 | ||
| 910 | spin_lock_irqsave(&ctx->ctx_lock, flags); | 905 | spin_lock_irqsave(&ctx->ctx_lock, flags); |
| 911 | run = __queue_kicked_iocb(iocb); | 906 | /* set this inside the lock so that we can't race with aio_run_iocb() |
| 907 | * testing it and putting the iocb on the run list under the lock */ | ||
| 908 | if (!kiocbTryKick(iocb)) | ||
| 909 | run = __queue_kicked_iocb(iocb); | ||
| 912 | spin_unlock_irqrestore(&ctx->ctx_lock, flags); | 910 | spin_unlock_irqrestore(&ctx->ctx_lock, flags); |
| 913 | if (run) | 911 | if (run) |
| 914 | aio_queue_work(ctx); | 912 | aio_queue_work(ctx); |
| @@ -931,10 +929,7 @@ void fastcall kick_iocb(struct kiocb *iocb) | |||
| 931 | return; | 929 | return; |
| 932 | } | 930 | } |
| 933 | 931 | ||
| 934 | /* If its already kicked we shouldn't queue it again */ | 932 | try_queue_kicked_iocb(iocb); |
| 935 | if (!kiocbTryKick(iocb)) { | ||
| 936 | queue_kicked_iocb(iocb); | ||
| 937 | } | ||
| 938 | } | 933 | } |
| 939 | EXPORT_SYMBOL(kick_iocb); | 934 | EXPORT_SYMBOL(kick_iocb); |
| 940 | 935 | ||
| @@ -1322,8 +1317,11 @@ asmlinkage long sys_io_destroy(aio_context_t ctx) | |||
| 1322 | } | 1317 | } |
| 1323 | 1318 | ||
| 1324 | /* | 1319 | /* |
| 1325 | * Default retry method for aio_read (also used for first time submit) | 1320 | * aio_p{read,write} are the default ki_retry methods for |
| 1326 | * Responsible for updating iocb state as retries progress | 1321 | * IO_CMD_P{READ,WRITE}. They maintains kiocb retry state around potentially |
| 1322 | * multiple calls to f_op->aio_read(). They loop around partial progress | ||
| 1323 | * instead of returning -EIOCBRETRY because they don't have the means to call | ||
| 1324 | * kick_iocb(). | ||
| 1327 | */ | 1325 | */ |
| 1328 | static ssize_t aio_pread(struct kiocb *iocb) | 1326 | static ssize_t aio_pread(struct kiocb *iocb) |
| 1329 | { | 1327 | { |
| @@ -1332,25 +1330,25 @@ static ssize_t aio_pread(struct kiocb *iocb) | |||
| 1332 | struct inode *inode = mapping->host; | 1330 | struct inode *inode = mapping->host; |
| 1333 | ssize_t ret = 0; | 1331 | ssize_t ret = 0; |
| 1334 | 1332 | ||
| 1335 | ret = file->f_op->aio_read(iocb, iocb->ki_buf, | 1333 | do { |
| 1336 | iocb->ki_left, iocb->ki_pos); | 1334 | ret = file->f_op->aio_read(iocb, iocb->ki_buf, |
| 1335 | iocb->ki_left, iocb->ki_pos); | ||
| 1336 | /* | ||
| 1337 | * Can't just depend on iocb->ki_left to determine | ||
| 1338 | * whether we are done. This may have been a short read. | ||
| 1339 | */ | ||
| 1340 | if (ret > 0) { | ||
| 1341 | iocb->ki_buf += ret; | ||
| 1342 | iocb->ki_left -= ret; | ||
| 1343 | } | ||
| 1337 | 1344 | ||
| 1338 | /* | ||
| 1339 | * Can't just depend on iocb->ki_left to determine | ||
| 1340 | * whether we are done. This may have been a short read. | ||
| 1341 | */ | ||
| 1342 | if (ret > 0) { | ||
| 1343 | iocb->ki_buf += ret; | ||
| 1344 | iocb->ki_left -= ret; | ||
| 1345 | /* | 1345 | /* |
| 1346 | * For pipes and sockets we return once we have | 1346 | * For pipes and sockets we return once we have some data; for |
| 1347 | * some data; for regular files we retry till we | 1347 | * regular files we retry till we complete the entire read or |
| 1348 | * complete the entire read or find that we can't | 1348 | * find that we can't read any more data (e.g short reads). |
| 1349 | * read any more data (e.g short reads). | ||
| 1350 | */ | 1349 | */ |
| 1351 | if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)) | 1350 | } while (ret > 0 && iocb->ki_left > 0 && |
| 1352 | ret = -EIOCBRETRY; | 1351 | !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)); |
| 1353 | } | ||
| 1354 | 1352 | ||
| 1355 | /* This means we must have transferred all that we could */ | 1353 | /* This means we must have transferred all that we could */ |
| 1356 | /* No need to retry anymore */ | 1354 | /* No need to retry anymore */ |
| @@ -1360,27 +1358,21 @@ static ssize_t aio_pread(struct kiocb *iocb) | |||
| 1360 | return ret; | 1358 | return ret; |
| 1361 | } | 1359 | } |
| 1362 | 1360 | ||
| 1363 | /* | 1361 | /* see aio_pread() */ |
| 1364 | * Default retry method for aio_write (also used for first time submit) | ||
| 1365 | * Responsible for updating iocb state as retries progress | ||
| 1366 | */ | ||
| 1367 | static ssize_t aio_pwrite(struct kiocb *iocb) | 1362 | static ssize_t aio_pwrite(struct kiocb *iocb) |
| 1368 | { | 1363 | { |
| 1369 | struct file *file = iocb->ki_filp; | 1364 | struct file *file = iocb->ki_filp; |
| 1370 | ssize_t ret = 0; | 1365 | ssize_t ret = 0; |
| 1371 | 1366 | ||
| 1372 | ret = file->f_op->aio_write(iocb, iocb->ki_buf, | 1367 | do { |
| 1373 | iocb->ki_left, iocb->ki_pos); | 1368 | ret = file->f_op->aio_write(iocb, iocb->ki_buf, |
| 1374 | 1369 | iocb->ki_left, iocb->ki_pos); | |
| 1375 | if (ret > 0) { | 1370 | if (ret > 0) { |
| 1376 | iocb->ki_buf += ret; | 1371 | iocb->ki_buf += ret; |
| 1377 | iocb->ki_left -= ret; | 1372 | iocb->ki_left -= ret; |
| 1378 | 1373 | } | |
| 1379 | ret = -EIOCBRETRY; | 1374 | } while (ret > 0 && iocb->ki_left > 0); |
| 1380 | } | ||
| 1381 | 1375 | ||
| 1382 | /* This means we must have transferred all that we could */ | ||
| 1383 | /* No need to retry anymore */ | ||
| 1384 | if ((ret == 0) || (iocb->ki_left == 0)) | 1376 | if ((ret == 0) || (iocb->ki_left == 0)) |
| 1385 | ret = iocb->ki_nbytes - iocb->ki_left; | 1377 | ret = iocb->ki_nbytes - iocb->ki_left; |
| 1386 | 1378 | ||
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 403b90a1213d..4284cd31eba6 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
| @@ -101,6 +101,10 @@ | |||
| 101 | /* Maximum number of poll wake up nests we are allowing */ | 101 | /* Maximum number of poll wake up nests we are allowing */ |
| 102 | #define EP_MAX_POLLWAKE_NESTS 4 | 102 | #define EP_MAX_POLLWAKE_NESTS 4 |
| 103 | 103 | ||
| 104 | /* Maximum msec timeout value storeable in a long int */ | ||
| 105 | #define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ) | ||
| 106 | |||
| 107 | |||
| 104 | struct epoll_filefd { | 108 | struct epoll_filefd { |
| 105 | struct file *file; | 109 | struct file *file; |
| 106 | int fd; | 110 | int fd; |
| @@ -1506,8 +1510,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, | |||
| 1506 | * and the overflow condition. The passed timeout is in milliseconds, | 1510 | * and the overflow condition. The passed timeout is in milliseconds, |
| 1507 | * that why (t * HZ) / 1000. | 1511 | * that why (t * HZ) / 1000. |
| 1508 | */ | 1512 | */ |
| 1509 | jtimeout = timeout == -1 || timeout > (MAX_SCHEDULE_TIMEOUT - 1000) / HZ ? | 1513 | jtimeout = (timeout < 0 || timeout >= EP_MAX_MSTIMEO) ? |
| 1510 | MAX_SCHEDULE_TIMEOUT: (timeout * HZ + 999) / 1000; | 1514 | MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000; |
| 1511 | 1515 | ||
| 1512 | retry: | 1516 | retry: |
| 1513 | write_lock_irqsave(&ep->lock, flags); | 1517 | write_lock_irqsave(&ep->lock, flags); |
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index c8d07030c897..e2d6208633a7 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c | |||
| @@ -605,27 +605,28 @@ got: | |||
| 605 | insert_inode_hash(inode); | 605 | insert_inode_hash(inode); |
| 606 | 606 | ||
| 607 | if (DQUOT_ALLOC_INODE(inode)) { | 607 | if (DQUOT_ALLOC_INODE(inode)) { |
| 608 | DQUOT_DROP(inode); | ||
| 609 | err = -ENOSPC; | 608 | err = -ENOSPC; |
| 610 | goto fail2; | 609 | goto fail_drop; |
| 611 | } | 610 | } |
| 611 | |||
| 612 | err = ext2_init_acl(inode, dir); | 612 | err = ext2_init_acl(inode, dir); |
| 613 | if (err) { | 613 | if (err) |
| 614 | DQUOT_FREE_INODE(inode); | 614 | goto fail_free_drop; |
| 615 | DQUOT_DROP(inode); | 615 | |
| 616 | goto fail2; | ||
| 617 | } | ||
| 618 | err = ext2_init_security(inode,dir); | 616 | err = ext2_init_security(inode,dir); |
| 619 | if (err) { | 617 | if (err) |
| 620 | DQUOT_FREE_INODE(inode); | 618 | goto fail_free_drop; |
| 621 | goto fail2; | 619 | |
| 622 | } | ||
| 623 | mark_inode_dirty(inode); | 620 | mark_inode_dirty(inode); |
| 624 | ext2_debug("allocating inode %lu\n", inode->i_ino); | 621 | ext2_debug("allocating inode %lu\n", inode->i_ino); |
| 625 | ext2_preread_inode(inode); | 622 | ext2_preread_inode(inode); |
| 626 | return inode; | 623 | return inode; |
| 627 | 624 | ||
| 628 | fail2: | 625 | fail_free_drop: |
| 626 | DQUOT_FREE_INODE(inode); | ||
| 627 | |||
| 628 | fail_drop: | ||
| 629 | DQUOT_DROP(inode); | ||
| 629 | inode->i_flags |= S_NOQUOTA; | 630 | inode->i_flags |= S_NOQUOTA; |
| 630 | inode->i_nlink = 0; | 631 | inode->i_nlink = 0; |
| 631 | iput(inode); | 632 | iput(inode); |
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 96552769d039..6549945f9ac1 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c | |||
| @@ -597,27 +597,22 @@ got: | |||
| 597 | 597 | ||
| 598 | ret = inode; | 598 | ret = inode; |
| 599 | if(DQUOT_ALLOC_INODE(inode)) { | 599 | if(DQUOT_ALLOC_INODE(inode)) { |
| 600 | DQUOT_DROP(inode); | ||
| 601 | err = -EDQUOT; | 600 | err = -EDQUOT; |
| 602 | goto fail2; | 601 | goto fail_drop; |
| 603 | } | 602 | } |
| 603 | |||
| 604 | err = ext3_init_acl(handle, inode, dir); | 604 | err = ext3_init_acl(handle, inode, dir); |
| 605 | if (err) { | 605 | if (err) |
| 606 | DQUOT_FREE_INODE(inode); | 606 | goto fail_free_drop; |
| 607 | DQUOT_DROP(inode); | 607 | |
| 608 | goto fail2; | ||
| 609 | } | ||
| 610 | err = ext3_init_security(handle,inode, dir); | 608 | err = ext3_init_security(handle,inode, dir); |
| 611 | if (err) { | 609 | if (err) |
| 612 | DQUOT_FREE_INODE(inode); | 610 | goto fail_free_drop; |
| 613 | goto fail2; | 611 | |
| 614 | } | ||
| 615 | err = ext3_mark_inode_dirty(handle, inode); | 612 | err = ext3_mark_inode_dirty(handle, inode); |
| 616 | if (err) { | 613 | if (err) { |
| 617 | ext3_std_error(sb, err); | 614 | ext3_std_error(sb, err); |
| 618 | DQUOT_FREE_INODE(inode); | 615 | goto fail_free_drop; |
| 619 | DQUOT_DROP(inode); | ||
| 620 | goto fail2; | ||
| 621 | } | 616 | } |
| 622 | 617 | ||
| 623 | ext3_debug("allocating inode %lu\n", inode->i_ino); | 618 | ext3_debug("allocating inode %lu\n", inode->i_ino); |
| @@ -631,7 +626,11 @@ really_out: | |||
| 631 | brelse(bitmap_bh); | 626 | brelse(bitmap_bh); |
| 632 | return ret; | 627 | return ret; |
| 633 | 628 | ||
| 634 | fail2: | 629 | fail_free_drop: |
| 630 | DQUOT_FREE_INODE(inode); | ||
| 631 | |||
| 632 | fail_drop: | ||
| 633 | DQUOT_DROP(inode); | ||
| 635 | inode->i_flags |= S_NOQUOTA; | 634 | inode->i_flags |= S_NOQUOTA; |
| 636 | inode->i_nlink = 0; | 635 | inode->i_nlink = 0; |
| 637 | iput(inode); | 636 | iput(inode); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e79e49b3eec7..29f1e9f6e85c 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -96,6 +96,8 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, | |||
| 96 | fuse_lookup_init(req, dir, entry, &outarg); | 96 | fuse_lookup_init(req, dir, entry, &outarg); |
| 97 | request_send(fc, req); | 97 | request_send(fc, req); |
| 98 | err = req->out.h.error; | 98 | err = req->out.h.error; |
| 99 | if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID)) | ||
| 100 | err = -EIO; | ||
| 99 | if (!err) { | 101 | if (!err) { |
| 100 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 102 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
| 101 | &outarg.attr); | 103 | &outarg.attr); |
| @@ -152,6 +154,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
| 152 | fuse_put_request(fc, req); | 154 | fuse_put_request(fc, req); |
| 153 | return err; | 155 | return err; |
| 154 | } | 156 | } |
| 157 | if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) { | ||
| 158 | fuse_put_request(fc, req); | ||
| 159 | return -EIO; | ||
| 160 | } | ||
| 155 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 161 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
| 156 | &outarg.attr); | 162 | &outarg.attr); |
| 157 | if (!inode) { | 163 | if (!inode) { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6454022b0536..657ab11c173b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -23,6 +23,10 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
| 23 | struct fuse_file *ff; | 23 | struct fuse_file *ff; |
| 24 | int err; | 24 | int err; |
| 25 | 25 | ||
| 26 | /* VFS checks this, but only _after_ ->open() */ | ||
| 27 | if (file->f_flags & O_DIRECT) | ||
| 28 | return -EINVAL; | ||
| 29 | |||
| 26 | err = generic_file_open(inode, file); | 30 | err = generic_file_open(inode, file); |
| 27 | if (err) | 31 | if (err) |
| 28 | return err; | 32 | return err; |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 59c5062cd63f..dd7113106269 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
| @@ -793,11 +793,6 @@ int hostfs_rename(struct inode *from_ino, struct dentry *from, | |||
| 793 | return(err); | 793 | return(err); |
| 794 | } | 794 | } |
| 795 | 795 | ||
| 796 | void hostfs_truncate(struct inode *ino) | ||
| 797 | { | ||
| 798 | not_implemented(); | ||
| 799 | } | ||
| 800 | |||
| 801 | int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) | 796 | int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) |
| 802 | { | 797 | { |
| 803 | char *name; | 798 | char *name; |
| @@ -894,7 +889,6 @@ static struct inode_operations hostfs_iops = { | |||
| 894 | .rmdir = hostfs_rmdir, | 889 | .rmdir = hostfs_rmdir, |
| 895 | .mknod = hostfs_mknod, | 890 | .mknod = hostfs_mknod, |
| 896 | .rename = hostfs_rename, | 891 | .rename = hostfs_rename, |
| 897 | .truncate = hostfs_truncate, | ||
| 898 | .permission = hostfs_permission, | 892 | .permission = hostfs_permission, |
| 899 | .setattr = hostfs_setattr, | 893 | .setattr = hostfs_setattr, |
| 900 | .getattr = hostfs_getattr, | 894 | .getattr = hostfs_getattr, |
| @@ -910,7 +904,6 @@ static struct inode_operations hostfs_dir_iops = { | |||
| 910 | .rmdir = hostfs_rmdir, | 904 | .rmdir = hostfs_rmdir, |
| 911 | .mknod = hostfs_mknod, | 905 | .mknod = hostfs_mknod, |
| 912 | .rename = hostfs_rename, | 906 | .rename = hostfs_rename, |
| 913 | .truncate = hostfs_truncate, | ||
| 914 | .permission = hostfs_permission, | 907 | .permission = hostfs_permission, |
| 915 | .setattr = hostfs_setattr, | 908 | .setattr = hostfs_setattr, |
| 916 | .getattr = hostfs_getattr, | 909 | .getattr = hostfs_getattr, |
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index c7e9237379c2..83f3322765cd 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
| @@ -29,7 +29,8 @@ ToDo/Notes: | |||
| 29 | The Windows boot will run chkdsk and then reboot. The user can then | 29 | The Windows boot will run chkdsk and then reboot. The user can then |
| 30 | immediately boot into Linux rather than having to do a full Windows | 30 | immediately boot into Linux rather than having to do a full Windows |
| 31 | boot first before rebooting into Linux and we will recognize such a | 31 | boot first before rebooting into Linux and we will recognize such a |
| 32 | journal and empty it as it is clean by definition. | 32 | journal and empty it as it is clean by definition. Note, this only |
| 33 | works if chkdsk left the journal in an obviously clean state. | ||
| 33 | - Support journals ($LogFile) with only one restart page as well as | 34 | - Support journals ($LogFile) with only one restart page as well as |
| 34 | journals with two different restart pages. We sanity check both and | 35 | journals with two different restart pages. We sanity check both and |
| 35 | either use the only sane one or the more recent one of the two in the | 36 | either use the only sane one or the more recent one of the two in the |
| @@ -94,6 +95,13 @@ ToDo/Notes: | |||
| 94 | my ways. | 95 | my ways. |
| 95 | - Fix various bugs in the runlist merging code. (Based on libntfs | 96 | - Fix various bugs in the runlist merging code. (Based on libntfs |
| 96 | changes by Richard Russon.) | 97 | changes by Richard Russon.) |
| 98 | - Fix sparse warnings that have crept in over time. | ||
| 99 | - Change ntfs_cluster_free() to require a write locked runlist on entry | ||
| 100 | since we otherwise get into a lock reversal deadlock if a read locked | ||
| 101 | runlist is passed in. In the process also change it to take an ntfs | ||
| 102 | inode instead of a vfs inode as parameter. | ||
| 103 | - Fix the definition of the CHKD ntfs record magic. It had an off by | ||
| 104 | two error causing it to be CHKB instead of CHKD. | ||
| 97 | 105 | ||
| 98 | 2.1.23 - Implement extension of resident files and make writing safe as well as | 106 | 2.1.23 - Implement extension of resident files and make writing safe as well as |
| 99 | many bug fixes, cleanups, and enhancements... | 107 | many bug fixes, cleanups, and enhancements... |
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 609ad1728ce4..01f2dfa39cec 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h | |||
| @@ -123,7 +123,7 @@ enum { | |||
| 123 | magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ | 123 | magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ |
| 124 | 124 | ||
| 125 | /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ | 125 | /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ |
| 126 | magic_CHKD = const_cpu_to_le32(0x424b4843), /* Modified by chkdsk. */ | 126 | magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */ |
| 127 | 127 | ||
| 128 | /* Found in all ntfs record containing records. */ | 128 | /* Found in all ntfs record containing records. */ |
| 129 | magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector | 129 | magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector |
| @@ -308,10 +308,8 @@ typedef le16 MFT_RECORD_FLAGS; | |||
| 308 | * The _LE versions are to be applied on little endian MFT_REFs. | 308 | * The _LE versions are to be applied on little endian MFT_REFs. |
| 309 | * Note: The _LE versions will return a CPU endian formatted value! | 309 | * Note: The _LE versions will return a CPU endian formatted value! |
| 310 | */ | 310 | */ |
| 311 | typedef enum { | 311 | #define MFT_REF_MASK_CPU 0x0000ffffffffffffULL |
| 312 | MFT_REF_MASK_CPU = 0x0000ffffffffffffULL, | 312 | #define MFT_REF_MASK_LE const_cpu_to_le64(0x0000ffffffffffffULL) |
| 313 | MFT_REF_MASK_LE = const_cpu_to_le64(0x0000ffffffffffffULL), | ||
| 314 | } MFT_REF_CONSTS; | ||
| 315 | 313 | ||
| 316 | typedef u64 MFT_REF; | 314 | typedef u64 MFT_REF; |
| 317 | typedef le64 leMFT_REF; | 315 | typedef le64 leMFT_REF; |
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 7b5934290685..5af3bf0b7eee 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c | |||
| @@ -779,14 +779,13 @@ out: | |||
| 779 | 779 | ||
| 780 | /** | 780 | /** |
| 781 | * __ntfs_cluster_free - free clusters on an ntfs volume | 781 | * __ntfs_cluster_free - free clusters on an ntfs volume |
| 782 | * @vi: vfs inode whose runlist describes the clusters to free | 782 | * @ni: ntfs inode whose runlist describes the clusters to free |
| 783 | * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters | 783 | * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters |
| 784 | * @count: number of clusters to free or -1 for all clusters | 784 | * @count: number of clusters to free or -1 for all clusters |
| 785 | * @write_locked: true if the runlist is locked for writing | ||
| 786 | * @is_rollback: true if this is a rollback operation | 785 | * @is_rollback: true if this is a rollback operation |
| 787 | * | 786 | * |
| 788 | * Free @count clusters starting at the cluster @start_vcn in the runlist | 787 | * Free @count clusters starting at the cluster @start_vcn in the runlist |
| 789 | * described by the vfs inode @vi. | 788 | * described by the vfs inode @ni. |
| 790 | * | 789 | * |
| 791 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are | 790 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are |
| 792 | * deallocated. Thus, to completely free all clusters in a runlist, use | 791 | * deallocated. Thus, to completely free all clusters in a runlist, use |
| @@ -801,31 +800,28 @@ out: | |||
| 801 | * Return the number of deallocated clusters (not counting sparse ones) on | 800 | * Return the number of deallocated clusters (not counting sparse ones) on |
| 802 | * success and -errno on error. | 801 | * success and -errno on error. |
| 803 | * | 802 | * |
| 804 | * Locking: - The runlist described by @vi must be locked on entry and is | 803 | * Locking: - The runlist described by @ni must be locked for writing on entry |
| 805 | * locked on return. Note if the runlist is locked for reading the | 804 | * and is locked on return. Note the runlist may be modified when |
| 806 | * lock may be dropped and reacquired. Note the runlist may be | 805 | * needed runlist fragments need to be mapped. |
| 807 | * modified when needed runlist fragments need to be mapped. | ||
| 808 | * - The volume lcn bitmap must be unlocked on entry and is unlocked | 806 | * - The volume lcn bitmap must be unlocked on entry and is unlocked |
| 809 | * on return. | 807 | * on return. |
| 810 | * - This function takes the volume lcn bitmap lock for writing and | 808 | * - This function takes the volume lcn bitmap lock for writing and |
| 811 | * modifies the bitmap contents. | 809 | * modifies the bitmap contents. |
| 812 | */ | 810 | */ |
| 813 | s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | 811 | s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count, |
| 814 | const BOOL write_locked, const BOOL is_rollback) | 812 | const BOOL is_rollback) |
| 815 | { | 813 | { |
| 816 | s64 delta, to_free, total_freed, real_freed; | 814 | s64 delta, to_free, total_freed, real_freed; |
| 817 | ntfs_inode *ni; | ||
| 818 | ntfs_volume *vol; | 815 | ntfs_volume *vol; |
| 819 | struct inode *lcnbmp_vi; | 816 | struct inode *lcnbmp_vi; |
| 820 | runlist_element *rl; | 817 | runlist_element *rl; |
| 821 | int err; | 818 | int err; |
| 822 | 819 | ||
| 823 | BUG_ON(!vi); | 820 | BUG_ON(!ni); |
| 824 | ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count " | 821 | ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count " |
| 825 | "0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn, | 822 | "0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn, |
| 826 | (unsigned long long)count, | 823 | (unsigned long long)count, |
| 827 | is_rollback ? " (rollback)" : ""); | 824 | is_rollback ? " (rollback)" : ""); |
| 828 | ni = NTFS_I(vi); | ||
| 829 | vol = ni->vol; | 825 | vol = ni->vol; |
| 830 | lcnbmp_vi = vol->lcnbmp_ino; | 826 | lcnbmp_vi = vol->lcnbmp_ino; |
| 831 | BUG_ON(!lcnbmp_vi); | 827 | BUG_ON(!lcnbmp_vi); |
| @@ -843,7 +839,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
| 843 | 839 | ||
| 844 | total_freed = real_freed = 0; | 840 | total_freed = real_freed = 0; |
| 845 | 841 | ||
| 846 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked); | 842 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, TRUE); |
| 847 | if (IS_ERR(rl)) { | 843 | if (IS_ERR(rl)) { |
| 848 | if (!is_rollback) | 844 | if (!is_rollback) |
| 849 | ntfs_error(vol->sb, "Failed to find first runlist " | 845 | ntfs_error(vol->sb, "Failed to find first runlist " |
| @@ -897,7 +893,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
| 897 | 893 | ||
| 898 | /* Attempt to map runlist. */ | 894 | /* Attempt to map runlist. */ |
| 899 | vcn = rl->vcn; | 895 | vcn = rl->vcn; |
| 900 | rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked); | 896 | rl = ntfs_attr_find_vcn_nolock(ni, vcn, TRUE); |
| 901 | if (IS_ERR(rl)) { | 897 | if (IS_ERR(rl)) { |
| 902 | err = PTR_ERR(rl); | 898 | err = PTR_ERR(rl); |
| 903 | if (!is_rollback) | 899 | if (!is_rollback) |
| @@ -965,8 +961,7 @@ err_out: | |||
| 965 | * If rollback fails, set the volume errors flag, emit an error | 961 | * If rollback fails, set the volume errors flag, emit an error |
| 966 | * message, and return the error code. | 962 | * message, and return the error code. |
| 967 | */ | 963 | */ |
| 968 | delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked, | 964 | delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE); |
| 969 | TRUE); | ||
| 970 | if (delta < 0) { | 965 | if (delta < 0) { |
| 971 | ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " | 966 | ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " |
| 972 | "inconsistent metadata! Unmount and run " | 967 | "inconsistent metadata! Unmount and run " |
diff --git a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h index e4d7fb98d685..a6a8827882e7 100644 --- a/fs/ntfs/lcnalloc.h +++ b/fs/ntfs/lcnalloc.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the | 2 | * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the |
| 3 | * Linux-NTFS project. | 3 | * Linux-NTFS project. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2004 Anton Altaparmakov | 5 | * Copyright (c) 2004-2005 Anton Altaparmakov |
| 6 | * | 6 | * |
| 7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU General Public License as published | 8 | * modify it under the terms of the GNU General Public License as published |
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
| 29 | 29 | ||
| 30 | #include "types.h" | 30 | #include "types.h" |
| 31 | #include "inode.h" | ||
| 31 | #include "runlist.h" | 32 | #include "runlist.h" |
| 32 | #include "volume.h" | 33 | #include "volume.h" |
| 33 | 34 | ||
| @@ -42,18 +43,17 @@ extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, | |||
| 42 | const VCN start_vcn, const s64 count, const LCN start_lcn, | 43 | const VCN start_vcn, const s64 count, const LCN start_lcn, |
| 43 | const NTFS_CLUSTER_ALLOCATION_ZONES zone); | 44 | const NTFS_CLUSTER_ALLOCATION_ZONES zone); |
| 44 | 45 | ||
| 45 | extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, | 46 | extern s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, |
| 46 | s64 count, const BOOL write_locked, const BOOL is_rollback); | 47 | s64 count, const BOOL is_rollback); |
| 47 | 48 | ||
| 48 | /** | 49 | /** |
| 49 | * ntfs_cluster_free - free clusters on an ntfs volume | 50 | * ntfs_cluster_free - free clusters on an ntfs volume |
| 50 | * @vi: vfs inode whose runlist describes the clusters to free | 51 | * @ni: ntfs inode whose runlist describes the clusters to free |
| 51 | * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters | 52 | * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters |
| 52 | * @count: number of clusters to free or -1 for all clusters | 53 | * @count: number of clusters to free or -1 for all clusters |
| 53 | * @write_locked: true if the runlist is locked for writing | ||
| 54 | * | 54 | * |
| 55 | * Free @count clusters starting at the cluster @start_vcn in the runlist | 55 | * Free @count clusters starting at the cluster @start_vcn in the runlist |
| 56 | * described by the vfs inode @vi. | 56 | * described by the ntfs inode @ni. |
| 57 | * | 57 | * |
| 58 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are | 58 | * If @count is -1, all clusters from @start_vcn to the end of the runlist are |
| 59 | * deallocated. Thus, to completely free all clusters in a runlist, use | 59 | * deallocated. Thus, to completely free all clusters in a runlist, use |
| @@ -65,19 +65,18 @@ extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, | |||
| 65 | * Return the number of deallocated clusters (not counting sparse ones) on | 65 | * Return the number of deallocated clusters (not counting sparse ones) on |
| 66 | * success and -errno on error. | 66 | * success and -errno on error. |
| 67 | * | 67 | * |
| 68 | * Locking: - The runlist described by @vi must be locked on entry and is | 68 | * Locking: - The runlist described by @ni must be locked for writing on entry |
| 69 | * locked on return. Note if the runlist is locked for reading the | 69 | * and is locked on return. Note the runlist may be modified when |
| 70 | * lock may be dropped and reacquired. Note the runlist may be | 70 | * needed runlist fragments need to be mapped. |
| 71 | * modified when needed runlist fragments need to be mapped. | ||
| 72 | * - The volume lcn bitmap must be unlocked on entry and is unlocked | 71 | * - The volume lcn bitmap must be unlocked on entry and is unlocked |
| 73 | * on return. | 72 | * on return. |
| 74 | * - This function takes the volume lcn bitmap lock for writing and | 73 | * - This function takes the volume lcn bitmap lock for writing and |
| 75 | * modifies the bitmap contents. | 74 | * modifies the bitmap contents. |
| 76 | */ | 75 | */ |
| 77 | static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn, | 76 | static inline s64 ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, |
| 78 | s64 count, const BOOL write_locked) | 77 | s64 count) |
| 79 | { | 78 | { |
| 80 | return __ntfs_cluster_free(vi, start_vcn, count, write_locked, FALSE); | 79 | return __ntfs_cluster_free(ni, start_vcn, count, FALSE); |
| 81 | } | 80 | } |
| 82 | 81 | ||
| 83 | extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, | 82 | extern int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, |
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 0173e95500d9..0fd70295cca6 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c | |||
| @@ -51,7 +51,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
| 51 | RESTART_PAGE_HEADER *rp, s64 pos) | 51 | RESTART_PAGE_HEADER *rp, s64 pos) |
| 52 | { | 52 | { |
| 53 | u32 logfile_system_page_size, logfile_log_page_size; | 53 | u32 logfile_system_page_size, logfile_log_page_size; |
| 54 | u16 usa_count, usa_ofs, usa_end, ra_ofs; | 54 | u16 ra_ofs, usa_count, usa_ofs, usa_end = 0; |
| 55 | BOOL have_usa = TRUE; | ||
| 55 | 56 | ||
| 56 | ntfs_debug("Entering."); | 57 | ntfs_debug("Entering."); |
| 57 | /* | 58 | /* |
| @@ -86,6 +87,14 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
| 86 | (int)sle16_to_cpu(rp->minor_ver)); | 87 | (int)sle16_to_cpu(rp->minor_ver)); |
| 87 | return FALSE; | 88 | return FALSE; |
| 88 | } | 89 | } |
| 90 | /* | ||
| 91 | * If chkdsk has been run the restart page may not be protected by an | ||
| 92 | * update sequence array. | ||
| 93 | */ | ||
| 94 | if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { | ||
| 95 | have_usa = FALSE; | ||
| 96 | goto skip_usa_checks; | ||
| 97 | } | ||
| 89 | /* Verify the size of the update sequence array. */ | 98 | /* Verify the size of the update sequence array. */ |
| 90 | usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); | 99 | usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); |
| 91 | if (usa_count != le16_to_cpu(rp->usa_count)) { | 100 | if (usa_count != le16_to_cpu(rp->usa_count)) { |
| @@ -102,6 +111,7 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
| 102 | "inconsistent update sequence array offset."); | 111 | "inconsistent update sequence array offset."); |
| 103 | return FALSE; | 112 | return FALSE; |
| 104 | } | 113 | } |
| 114 | skip_usa_checks: | ||
| 105 | /* | 115 | /* |
| 106 | * Verify the position of the restart area. It must be: | 116 | * Verify the position of the restart area. It must be: |
| 107 | * - aligned to 8-byte boundary, | 117 | * - aligned to 8-byte boundary, |
| @@ -109,7 +119,8 @@ static BOOL ntfs_check_restart_page_header(struct inode *vi, | |||
| 109 | * - within the system page size. | 119 | * - within the system page size. |
| 110 | */ | 120 | */ |
| 111 | ra_ofs = le16_to_cpu(rp->restart_area_offset); | 121 | ra_ofs = le16_to_cpu(rp->restart_area_offset); |
| 112 | if (ra_ofs & 7 || ra_ofs < usa_end || | 122 | if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : |
| 123 | ra_ofs < sizeof(RESTART_PAGE_HEADER)) || | ||
| 113 | ra_ofs > logfile_system_page_size) { | 124 | ra_ofs > logfile_system_page_size) { |
| 114 | ntfs_error(vi->i_sb, "$LogFile restart page specifies " | 125 | ntfs_error(vi->i_sb, "$LogFile restart page specifies " |
| 115 | "inconsistent restart area offset."); | 126 | "inconsistent restart area offset."); |
| @@ -402,8 +413,12 @@ static int ntfs_check_and_load_restart_page(struct inode *vi, | |||
| 402 | idx++; | 413 | idx++; |
| 403 | } while (to_read > 0); | 414 | } while (to_read > 0); |
| 404 | } | 415 | } |
| 405 | /* Perform the multi sector transfer deprotection on the buffer. */ | 416 | /* |
| 406 | if (post_read_mst_fixup((NTFS_RECORD*)trp, | 417 | * Perform the multi sector transfer deprotection on the buffer if the |
| 418 | * restart page is protected. | ||
| 419 | */ | ||
| 420 | if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) | ||
| 421 | && post_read_mst_fixup((NTFS_RECORD*)trp, | ||
| 407 | le32_to_cpu(rp->system_page_size))) { | 422 | le32_to_cpu(rp->system_page_size))) { |
| 408 | /* | 423 | /* |
| 409 | * A multi sector tranfer error was detected. We only need to | 424 | * A multi sector tranfer error was detected. We only need to |
| @@ -615,11 +630,16 @@ is_empty: | |||
| 615 | * Otherwise just throw it away. | 630 | * Otherwise just throw it away. |
| 616 | */ | 631 | */ |
| 617 | if (rstr2_lsn > rstr1_lsn) { | 632 | if (rstr2_lsn > rstr1_lsn) { |
| 633 | ntfs_debug("Using second restart page as it is more " | ||
| 634 | "recent."); | ||
| 618 | ntfs_free(rstr1_ph); | 635 | ntfs_free(rstr1_ph); |
| 619 | rstr1_ph = rstr2_ph; | 636 | rstr1_ph = rstr2_ph; |
| 620 | /* rstr1_lsn = rstr2_lsn; */ | 637 | /* rstr1_lsn = rstr2_lsn; */ |
| 621 | } else | 638 | } else { |
| 639 | ntfs_debug("Using first restart page as it is more " | ||
| 640 | "recent."); | ||
| 622 | ntfs_free(rstr2_ph); | 641 | ntfs_free(rstr2_ph); |
| 642 | } | ||
| 623 | rstr2_ph = NULL; | 643 | rstr2_ph = NULL; |
| 624 | } | 644 | } |
| 625 | /* All consistency checks passed. */ | 645 | /* All consistency checks passed. */ |
diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h index 42388f95ea6d..a51f3dd0e9eb 100644 --- a/fs/ntfs/logfile.h +++ b/fs/ntfs/logfile.h | |||
| @@ -113,7 +113,7 @@ typedef struct { | |||
| 113 | */ | 113 | */ |
| 114 | enum { | 114 | enum { |
| 115 | RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), | 115 | RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), |
| 116 | RESTART_SPACE_FILLER = 0xffff, /* gcc: Force enum bit width to 16. */ | 116 | RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ |
| 117 | } __attribute__ ((__packed__)); | 117 | } __attribute__ ((__packed__)); |
| 118 | 118 | ||
| 119 | typedef le16 RESTART_AREA_FLAGS; | 119 | typedef le16 RESTART_AREA_FLAGS; |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 2c32b84385a8..247586d1d5dc 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
| @@ -1953,7 +1953,7 @@ restore_undo_alloc: | |||
| 1953 | a = ctx->attr; | 1953 | a = ctx->attr; |
| 1954 | a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1); | 1954 | a->data.non_resident.highest_vcn = cpu_to_sle64(old_last_vcn - 1); |
| 1955 | undo_alloc: | 1955 | undo_alloc: |
| 1956 | if (ntfs_cluster_free(vol->mft_ino, old_last_vcn, -1, TRUE) < 0) { | 1956 | if (ntfs_cluster_free(mft_ni, old_last_vcn, -1) < 0) { |
| 1957 | ntfs_error(vol->sb, "Failed to free clusters from mft data " | 1957 | ntfs_error(vol->sb, "Failed to free clusters from mft data " |
| 1958 | "attribute.%s", es); | 1958 | "attribute.%s", es); |
| 1959 | NVolSetErrors(vol); | 1959 | NVolSetErrors(vol); |
diff --git a/fs/read_write.c b/fs/read_write.c index b60324aaa2b6..a091ee4f430d 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -499,6 +499,9 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
| 499 | ret = rw_verify_area(type, file, pos, tot_len); | 499 | ret = rw_verify_area(type, file, pos, tot_len); |
| 500 | if (ret) | 500 | if (ret) |
| 501 | goto out; | 501 | goto out; |
| 502 | ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE); | ||
| 503 | if (ret) | ||
| 504 | goto out; | ||
| 502 | 505 | ||
| 503 | fnv = NULL; | 506 | fnv = NULL; |
| 504 | if (type == READ) { | 507 | if (type == READ) { |
