diff options
author | Paul Mackerras <paulus@samba.org> | 2005-09-28 23:13:36 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-09-28 23:13:36 -0400 |
commit | ab11d1ea281e85895369ef57c5259ad8a432fabb (patch) | |
tree | 684147479c6a8bb2fbed21bdcf12de1dd519c730 /fs | |
parent | 952ecef7a0479049c8abb7c34a688ec2981ceadd (diff) | |
parent | 664cceb0093b755739e56572b836a99104ee8a75 (diff) |
Merge by hand from Linus' tree.
Signed-off-by: Paul Mackerras <paulus@samba.org>
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 | 21 | ||||
-rw-r--r-- | fs/Kconfig | 3 | ||||
-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/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 |
19 files changed, 307 insertions, 270 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..0957f4da91d4 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -129,8 +129,7 @@ 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); | 132 | return newfid; |
133 | return ERR_PTR(newfid); | ||
134 | } | 133 | } |
135 | 134 | ||
136 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 135 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); |
@@ -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 | ||
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/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); |